Всем привет!

Краткое предисловие: я счастливый обладатель замечательного саундбара YAS-109 от Yamaha, на момент написания пользуюсь им уже целый год, и всё в целом хорошо. Но однажды я решил узнать: не подслушивает ли меня мой музыкальный друг? Ведь у него есть встроенная поддержка Alexa, а ещё Bluetooth, WiFi, Ethernet и другие прелести… Так и начинается история моего ресёрча.

Пробуем простой подход

Обычно самый простой способ изучить поведение железки — это посмотреть на файлы обновлений. Уже по ним можно сделать некоторые выводы о безопасности устройства, о подходе производителя к этой самой безопасности. Так я и сделал: полез в поиск, вбил название устройства, добавил слово firmware и первой же ссылкой получил страницу с файлами обновления:

Качаем прошивку
Качаем прошивку

В архиве меня ждёт следующий набор файлов:

Содержимое файла обновления
Содержимое файла обновления

На скрине видим четыре файла: mcu.enc, update.enc, yamaha_usb_upgrade.enc и yamaha_ver.txt. Конечно, это были никакие не файлы Wireshark, как рисует мне «Проводник», просто расширение файла совпадает. Это же расширение говорило мне и о том, что сами обновления, скорее всего, чем-то пошифрованы. Проверим? Суём файлы в hex-редактор и видим следующую картину:

Что-то на за
Что-то на зашифрованном

В самом начале можно заметить не очень приятное слово Salted__, что означает: смотри, мол, я зашифрован OpenSSL с использованием «соли». Чтобы забрутить это дело, могут уйти десятилетия, поэтому подход пришлось признать неудачным.

Пробуем сложный, но самый эффективный метод

Я с детства любил ковыряться в различных железках: тамагочи, гоночных машинках, старых магнитофонах. Разобрать такое, потом не собрать, получить за это по шапке от бати — вот моё счастливое детство. Прошли годы, и теперь «ковыряться в железках» — моя профессия. Конечно, сейчас на работе желательно собирать их обратно, но поскольку дают обычно два экземпляра, один идет под разбор.

Так вот, я решил разобрать и свой саундбар. Штука это тяжёлая, с обилием ацетатного скотча и клея внутри, чтобы ничего не вибрировало от басов.

Переворачиваем «колонку», выкручиваем все винты, запоминая, где какой длины они были. Заранее скажу, что винты, которые нам потребуется выкрутить, будут трёх форматов: длинные (корпус плюс пластиковая крышка внутри), короткие (корпус и все остальные крепления внутри) и один мелкий, удерживающий плату HDMI-аддона.

При разъединении двух половинок корпуса действуем аккуратно: сенсорная панель саундбара соединяется с основной платой управления гибким шлейфом плюс двумя проводами: заземлением и питанием.

Переходим к основной плате управления. Часть её уходит под пластиковый корпус с перфорацией, поэтому снимаем его и любуемся платкой целиком. А встречает нас тут непонятный ABOV A33G526RLN. Поиск выдаёт информацию о каком-то 32-bit-Cortex-M3-based-микроконтроллере. Смотрим распиновку:

Pinout
Pinout

Сразу отмечаем для себя наличие ног JTAG: nTRST (49), TDI (50), TMS (51), TCK (52), TDO (57), nRESET (58). Так как корпус контроллера у нас не BGA-шный, каждый из указанных выводов можно прозвонить и найти, куда именно они выведены (если выведены). Достаточно быстро удалось выяснить, что ноги JTAG приходят на такой вот разъём:

Подозрительно нераспаянный разъём
Подозрительно нераспаянный разъём

Этот разъём практически идентичен соседнему с ним — чёрному шлейфовому разъёму. Такого коннектора у меня, конечно же, не было, как и шлейфов нужной ширины, поэтому я просто подпаялся к необходимым ногам:

Подозрительно подпаянный разъём
Подозрительно подпаянный разъём

Затем я припаял к МГТФ-проводам проводки с разъёмом «мама» и подключил их к JLink, согласно распиновке. Без особой надежды на успех (мало ли, отключен JTAG) я запустил железку. И, о чудо, JLink Commander встретил меня сообщением об успешно найденном Cortex-M3 контроллере:

Cortex-M3 identified
Cortex-M3 identified

Смотрим Memory Map в даташите:

Memory Map
Memory Map

Видим, что основной код лежит в «нуле», а загрузчик — в 0x1FFF_0000. Окей, пробуем сдампить. К сожалению, если читать память во время работы, в «нуле» нас будут ждать нули же. Поэтому делаем reset и читаем снова:

Дамп прошивки ARM получен
Дамп прошивки ARM получен

Как и ожидалось, первой прочиталась обычная таблица векторов ARM-контроллера. Обрадовавшись, я полез изучать полученный код, но, к сожалению, не нашёл ничего о расшифровке обновлений. Значит, с этими обновлениями работает кто-то другой…

Попробуем снова посмотреть на плату управления, вдруг можно сдампить что-то ещё.

Оказывается, можно. Нашлась флешка в корпусе SOIC8 с маркировкой BoyaMicro 25Q32BSSIG:

Маленькая флешка
Маленькая флешка

Засовываем флешку в программатор и видим что-то, чего увидеть совсем не ожидаем, а именно:

Дамп с маленькой флешки
Дамп с маленькой флешки

Первое, что бросается в глаза: хедер MAPX и никакого внятного содержимого внутри — возможно, здесь хранятся какие-то конфиги. Ладно, идём дальше, здесь ловить нечего.

А дальше — больше. Под припаянным экраном с поролонкой я нахожу интересный контроллер с маркировкой CSR A67175:

Что под шилдом
Что под шилдом?

Поиск по данному названию приводит меня на сайт Qualcomm с чем бы вы думали… с упоминанием технологии MAPX! Конечно же, публично доступных даташитов на данную приблуду не нашлось, скачать что-либо можно только при наличии полноценного подтверждённого аккаунта на сайте вендора, притом на обычного человека оформить его нельзя. Ну что ж… Понадеявшись, что всю основную работу с обновлениями делает не этот монстр без документации, я пошёл изучать плату дальше.

Помните тот модуль, который втыкается в штырьевой разъём на основной плате, с наклейками с указанием сетевых MAC-адресов, экраном и коннектором для антенны WiFi?

Такая вот странная плата
Такая вот странная плата

Раньше я его отметал как просто модуль WiFi, а, значит, не содержащий в себе ничего интересного. Да и выпаивать такой большой экран не очень хотелось. Но раз больше на плате смотреть нечего, я решил изучить этот модуль детальнее.

На обратной стороне я обнаружил крайне интересный объект:

Ура, NAND-флеша!
Ура, NAND-флеша!

Это была NAND флеш-память Kioxia TC58NVG1S3HTA00. К сожалению, на тот момент для моего программатора ChipProg-48 не было необходимого адаптера, а с обычной универсальной для TSOP48 колодкой флешку читать он отказывался. Пришлось обращаться к «дяде» по объявлению.

Заполучив дамп на USB-флешку, дома я первым делом полез смотреть, что же там. А ждал меня полнейший сюрприз:

Что-то на зашифрованном, опять
Что-то на зашифрованном, опять

Как видите, полнейший мусор. Расстроившись, я даже успел позвонить «дяде» и высказать всё, что о нём думаю, а именно: что за ерунду он мне сдампил? Наверняка программатор кривой, или контакт плохой или колодка не та. На что мужик мне ответил, мол, приходи завтра, попробуем сдампить снова и хотя бы сравнить дампы. Если читается мусор, тогда они не совпадут. Согласившись с этим утверждением, я немного успокоился. Но дожидаться завтрашнего дня не стал, а решил пристальнее рассмотреть содержимое дампа.

Увидев чуть дальше по файлу большие блоки из FF, я понял, что дамп скорее корректный, чем нет, и предположил, что имею дело с каким-то шифрованием. Как и что именно было пошифровано я, конечно же, не знал, поэтому решил пойти новым для себя методом.

Я открыл даташит на флешу, отметил для себя организацию ячеек памяти — блоков и страниц: (2048 + 128) bytes × 64 pages × 2048 blocks. Далее я сделал предположение, что шифрование может применяться постранично или по блокам. Разбив дамп на блоки, я решил поксорить их между собой и выделить те, где оказалось бы наибольшее количество нулей, попутно сохраняя такие результаты. И, что интересно, этот подход дал свои плоды.

В некоторых результатах ксора появились более-менее читаемые строки:

Почти расшифровали
Почти расшифровали

Продолжив играться дальше, я выяснил, что первые 0x440 байт, поксоренные на третьи 0x440 байт, дают наиболее правдоподобный результат. Возможно, если поксорить второй такой блок с четвёртым, я тоже получу что-то вменяемое? Оказалось, что так оно и есть. Чуть позднее я выяснил, что первый блок можно также успешно поксорить и на 256-й блок. Написав скриптец для автоматизации сего действия, я принялся изучать полученные результаты. Но они меня не обрадовали.

Чуть далее по файлу закономерность работать перестала. Да и странно это, что для шифрования данных на флеше используется фактически её половина. Наверняка алгоритм был каким-то другим. Тем не менее тех данных, которые удалось наксорить, мне хватило для того, чтобы обнаружить ARM-овский код, который шёл следом за вот таким блоком с упоминанием слова BOOTLOADER:

Расшифровалось чуть лучше
Расшифровалось чуть лучше

Я загрузил этот код в IDA Pro (архитектура ARM64) и принялся его изучать. Кое-как подобрав ImageBase (он оказался равен 0x400), я бегло осмотрел распознанные функции и данные, которые в них используются. Конечно же, я наткнулся на список с маркировками NAND флеш-памяти, в том числе и имеющейся у меня:

Хмм, похоже на список флешек
Хмм, похоже на список флешек

Но ссылок на этот список IDA не нашла. Тем не менее прямо над ним нашлась крайне подозрительная табличка:

Какие-то сиды
Какие-то сиды

Что первым делом делает реверс-инженер, когда встречает незнакомые константы? Правильно, идёт с ними в поисковик. И, что забавно, константы нашлись на GitHub! Как раз в контексте NAND, а рядом упоминались такие слова, как randomizer и scrambling. Изучив тот код, я пришёл к выводу, что эти константы являются начальными значениями для генератора псевдослучайных данных (ключа) для шифрования данных на флеше. К сожалению, сама логика генератора с ходу не нашлась, но надежда на то, что я смогу побороть шифрование данных в дампе, появилась, и достаточно высокая.

Продолжив искать данные константы, я наткнулся на другой интересный репозиторий от ValveSoftware с названием steamlink-sdk. В этом репозитории данные константы использовались уже не как значения, которые отправляются в контроллер NAND, а тот их непонятно как использует. Здесь обнаружился… сам код генератора. Файл с именем prbs15.c содержал и саму таблицу сидов с названием seed_table, и такую функцию, как prbs15_gen, в которой эта таблица использовалась. Я незамедлительно переписал себе код функции на Python, запустил скриптец с крайне большой надеждой на положительный результат.

И… генерируемый скриптом ключ таки совпал с тем, что мне удалось получить, ксоря блоки между собой! Я ликовал!

Как оказалось, каждый сид использовался для генерации ключа размером 0x440 байт, который применялся на два блока такого же размера подряд, после чего брался следующий сид. Так расшифровывалась целая страница размером 0x22000 байт, после чего сиды снова брались с нулевого элемента. Итого получается, что реально использовалась лишь первая половина сидов из таблицы (64 элемента).

Наверняка к этому моменту у вас мог возникнуть вопрос: а почему вообще приём с ксором блоков мне помог? Дело в том, что в расшифрованном дампе оказалось очень большое количество блоков размером 0x440 байт, заполненных одними лишь нулями, либо FF. Если бы в дампе не нашлось таких блоков, данный подход бы не сработал. Пришлось бы что-то придумывать, например сравнивать дампы с флеши после каждого включения саундбара.

Особенности NAND-памяти

Вы наверняка уже и забыли о «дяде» и его предложении перечитать флешку. А я не забыл. К сожалению, вспомнить о нём мне пришлось, когда в некоторых местах расшифрованного дампа стали обнаруживаться не очень хорошие артефакты:

Особенности NAND
Особенности NAND

Как можно заметить, в двух разных блоках, данные в которых должны быть одинаковыми, некоторые строки оказались битыми. Так как в правильности ключа я был уверен, оставалось одно — местами битый дамп. Когда я спросил об этом товарища, он сказал, что это нормально и, возможно, стоит поиграться с изменением подаваемого при чтении флешки напряжения. Именно такие действия применяют умные ребята из Rusolut в своём видео об особенностях дампинга NAND.

На тот момент у меня по-прежнему не было нужной колодки для программатора, поэтому я снова созвонился с «дядей» и попросил его наделать для меня дампов при других подаваемых напряжениях. Получив в распоряжение 10 новых дампов, я принялся их сравнивать. Вы будете смеяться, но все были разными, при том биты в каждом менялись на абсолютно разных позициях! Полнейший треш…

С полученным осознанием безысходности и расшифрованным битым дампом, я принялся его изучать, первым делом натравив на него binwalk. Среди результатов поиска обнаружились сигнатуры UBIFS, скомпилированные device-tree блобы и много чего ещё. Я решил начать с device-tree.

Не буду сейчас вдаваться в структуру данного формата данных. Скажу лишь, что для каждого раздела, хранимого в структуре, хранится и SHA256-хеш, по которому можно определить целостность содержимого. После извлечения всех device-tree блобов и разделов из них, я стал их сравнивать. Так мне удалось обнаружить несколько разделов в разных блобах, отличающихся всего на некоторое количество бит. Найдя те разделы, у которых реальные хеши совпали с указанными в блобах, я взял их за основу при сравнении с теми, чьи хеши отличались. Таким образом мне удалось исправить биты в кривых разделах и немного починить оригинальный дамп.

Пришла пора переходить к UBIFS. На просторах интернета я нашёл скрипт ubidump.py и натравил его на расшифрованный дамп, чтобы тот попытался извлечь всё, что можно было. Но не тут-то было. В структуре блоков UBI имеется поле с контрольной суммой CRC32, и если она не совпадает, то дампер такой блок пропускает. К сожалению, таких блоков было очень много и нужно было что-то придумать.

А придумал я очень простую, но действенную вундервафлю:

Просто, но действенно
Просто, но действенно

Тут всё просто: если контрольная сумма не совпала, то «переключаем» один бит и снова считаем CRC32. Конечно, это не будет работать, если в данных, для которых идёт подсчёт, таких неправильных битов больше одного, но такого при сравнении дампов NAND я не обнаружил. Так, потихоньку, бит за битом, мне удалось исправить большое количество кривых байт!

Тем не менее, проблемы с UBIFS не закончились. Если вкратце, то в некоторых местах, где должны были быть блоки UBI, хранился какой-то мусор, который раньше я принимал за упакованные данные (файловая система позволяет хранить данные либо в виде потока ZLIB, либо сжатые LZO). Что это не сжатые данные, я понял, когда заметил цикличность в появлении мусора: начинались они со смещения 0xBB00 и повторялись каждые 0x22000 байт.

Неужто генератор ключа работает неправильно? Перепроверил — вроде всё нормально. Тогда в чём может быть проблема? Ответ оказался полнейшим выносом мозга! Дело в том, что контроллер NAND от MediaTek, прошивки от которого у меня не было, решил, что ему мало просто постранично что-то там скремблить. Надо ещё немного извернуться…

Вредина MT8516
Вредина MT8516

Так вот, умные ребята-разработчики прошивки этого контроллера решили, что нужно брать 22-й блок в каждой странице и шифровать его по-особому. А именно: брать 63-й сид из таблицы сидов, генерировать по нему ключ, но использовать байты получившегося ключа со смещения 0x118 (SIC!!!). Не спрашивайте, как я к этому пришёл. Но в итоге дамп стал получаться нормальным!

А вот что именно там обнаружилось, я расскажу в другой раз. Но для затравки: код там такой, что за голову хватаешься… Вот вам для подогрева интереса:

Login successful
Login successful

P.S. А ещё саундбар работает с сетью даже тогда, когда выключен (но воткнут в розетку).

Комментарии (34)


  1. mobilz
    27.09.2023 14:26
    +7

    норм затравочка )


  1. exTvr
    27.09.2023 14:26
    +16

    Ну вот, как всегда, обрыв на самом интересном месте.
    Это не вы, часом, "Лиловый шар" разбивали на части для публикации в "Пионерской правде"? :))


    1. DrMefistO Автор
      27.09.2023 14:26
      +8

      Я помоложе, так что, возможно, кто-то из родни)


  1. tuxi
    27.09.2023 14:26
    +4

    Жду, жду продолжения [поглаживая такую же ямаху] )))


  1. Leshiy26
    27.09.2023 14:26
    +4

    Читается как остросюжетный детектив. С нетерпением жду второй серии!


  1. pnetmon
    27.09.2023 14:26
    +4

    P.S. А ещё саундбар работает с сетью даже тогда, когда выключен (но воткнут в розетку).

    а еще он включается со смартфона и в требованиях к приложению беспроводная локальная сеть


  1. ImagineTables
    27.09.2023 14:26
    +8

    Автор, не томи!!! Сифонит?


    1. DrMefistO Автор
      27.09.2023 14:26
      +14

      Сифонит:)


      1. ImagineTables
        27.09.2023 14:26
        +1

        Подписался, жду продолжения.


  1. FirstEgo
    27.09.2023 14:26
    +3

    Ах ты ж хитрая ж...железка!!!


  1. sbw
    27.09.2023 14:26

    Ну вот, как же так, я его купить хотел как раз))


    1. DrMefistO Автор
      27.09.2023 14:26

      Ну, он неплохой сам по себе так то. Просто не подключать его к сети.


      1. FirstEgo
        27.09.2023 14:26

        ЭЛЕКТРОсети?.. (((


        1. DrMefistO Автор
          27.09.2023 14:26

          Нет, хотя бы вайфай с ethernet


  1. VelocidadAbsurda
    27.09.2023 14:26
    +12

    Красота! Трюк с исправлением битов, ориентируясь на CRC, отдельно порадовал. Жду продолжения!

    "Шифрование" NAND - не ради сокрытия, а просто чтобы устранить длинные последовательности одинаковых битов (в NAND высокой плотности такие сгустки зарядов могут портить соседние биты), стандартная функция многих NAND-контроллеров. И та странность с другими сидами в каждом n-ном блоке, возможно, учитывает физическую организацию некой конкретной модели NAND. Алгоритмы эти, бывает, всплывают на форумах Acelab и подобных софтов по восстановлению данных.


    1. DrMefistO Автор
      27.09.2023 14:26
      +1

      Не знал, спасибо:)


    1. HenryPootle
      27.09.2023 14:26
      +2

      На каком чудовищно сложном фундаменте стоит вся современная цивилизация! С виду - просто колонка, усиливающая звук телевизора, а автор начал разбираться - и какие бездны вершин открылись.
      Костыли, примотанные изолентой к велосипеду с квадратными колёсами, едущему по специально спроектированной под квадратные колёса мостовой. И ведь это всё работает, мы это всё ежедневно носим в кармане, это нас возит в автомобилях и отправляет в полёт на самолётах!


  1. SSLHTML
    27.09.2023 14:26
    +2

    Много очень интересных моментов в статье, особенно для меня. Понравился метод "догадки" поксоренных друг на друга ячеек, да и вообще работа с дампом памяти, снятого с NAND в TSOP48. Сам, практически ежедневно работаю с этим типом памяти. Проберы в использовании дизассемблеров разного толка ограничивают мои возможности, но когда для специалиста @DrMefistO это не проблема, то расследование становится и вправду очень интересным.

    Большое спасибо за подобные статьи с исследованиями, разработками и изысканиями. Они помогают тем, кто интересуется и стремиться вырасти в реверсинге. Спасибо также за этот вклад, как лично в мою копилку знаний, так и в ресурс Хабр.


  1. ciuafm
    27.09.2023 14:26
    +3

    Торт!


  1. acsent1
    27.09.2023 14:26

    Разве не достаточно было прокси/сниффер какой поставить?


    1. DrMefistO Автор
      27.09.2023 14:26
      +1

      А куда поставить? Простой захват трафика упёрся бы в SSL, а что внутри было бы не ясно.


  1. kay_kay
    27.09.2023 14:26
    +1

    Убийца - дворецкий.

    Расходимся!


  1. Deito
    27.09.2023 14:26

    То, что данные улетяют без спроса очевидно, интересно что будет с этим сделано. Будет ли патч на это безобразие.


    1. DrMefistO Автор
      27.09.2023 14:26

      Написал вендору, а как там будет дальше неизвестно.


      1. User79
        27.09.2023 14:26
        +2

        Ещё на зарубежные технические ресурсы статью разместить для получения огласки => ускорения реакции Yamaha


        1. DrMefistO Автор
          27.09.2023 14:26

          Да, этим можно заняться.


        1. IvanPetrof
          27.09.2023 14:26

          А по тамошним законам это законно? Не засудят?


          1. DrMefistO Автор
            27.09.2023 14:26
            +1

            Ну, текущая статья не содержит ничего такого. Публиковать эксплоиты я не планирую. Разработчик уведомлен, жду реакции. В следующей статье без его ответа я могу лишь опубликовать то, что не может привести к удалённому взлому устройства, а в личных целях никто не запрещает это делать.


  1. event1
    27.09.2023 14:26
    +1

    Наверняка к этому моменту у вас мог возникнуть вопрос: а почему вообще приём с ксором блоков мне помог? Дело в том, что в расшифрованном дампе оказалось очень большое количество блоков размером 0x440 байт, заполненных одними лишь нулями, либо FF.

    А я вот не понял, честно говоря. Вы же код взяли не из тех блоков которые были заполнены нулями или FF. Как же вам помогли пустые блоки? Или они вам помогли обнаружить периодичность?

    И ещё, в порядке товарищеской критики: по тексту немного непоследовательно используется термин "блок". Сам NAND делится на блоки стирания (erase block), которые в свою очередь делятся на страницы (pages). Блоки по 0x440 байта было бы удобнее назвать как-нибудь иначе, чтобы не путать с блоками стирания по 0x22000. Например, "сегменты".


    1. DrMefistO Автор
      27.09.2023 14:26
      +1

      Спасибо за дельную критику! Я, пожалуй, не стану менять уже имеющееся именование. В даташитах нет упоминания деления на блоки "сегменты" по 0x440, как и того, что в каждом из них представлена Spare Area. Думаю, у читателя это не должно вызвать особой путаницы.

      Касательно заполнения нулями и FF: да, там практически в самом начале расшифрованного дампа идёт огромный кусок, заполненный 00, а если точнее, то до 0x407F4 (это уже не включая вырезанные 0x40 в каждом "сегменте"). Так что мне, по сути, просто повезло встретить такое большое количество нулей.


      1. event1
        27.09.2023 14:26
        +1

        В даташитах нет упоминания деления на блоки "сегменты" по 0x440, как и того, что в каждом из них представлена Spare Area

        Я думаю, что его и нет. Во всяком случае те чипы, что мне попадались меньше страницы не делились. Скорее всего это фишка NAND-контроллера. Возможно, это самый маленький размер страницы встречающийся среди поддерживаемых NAND-чипов, вот они и работают сегментами такого размера.


        1. DrMefistO Автор
          27.09.2023 14:26

          Скорее всего так. До прошивки NAND-контроллера я тоже доберусь. Уже нашёл его JTAG.


        1. VelocidadAbsurda
          27.09.2023 14:26
          +2

          Да, это самодеятельность NAND-контроллера. К примеру, из него наружу хотят классическими секторами по 0x200, сам NAND имеет страницы по 16К, контроллер использует схему ECC по 11 байт на сектор - ну и чхать ему на некрасивые смещения, забивает физические 16K кусками данные+ECC по 0x20B байт подряд без стыков, не разбираясь, где там по задумке производителя NAND данные, где spare, у него в сторону NAND потоковый интерфейс со счётчиками байтов, разделяющий данные/ЕСС на лету, достаточно только задать ему размеры того и другого. Плюс, внимание, где-то не в начале и не в конце физ. страницы может находиться bad block marker (!=FF - блок дефектный, смещение определяет производитель, он сразу на фабрике помечает дефектные блоки. Смещения встречались ну очень некруглые), приличный NAND-контроллер и его на лету отделяет, как ни в чём ни бывало. В итоге на самом нижнем уровне формат может быть ну очень причудливым.

          И вишенкой на торте: в NAND, с которого какой-нибудь SoC напрямую грузится в embedded Linux, запросто может быть несколько зон с разными форматами страниц: BootROM понимает какой-нибудь свой причудливый формат, первичный загрузчик записан в нём, вторичным взяли какой-нибудь готовый U-Boot, организующий софтово свой формат, ядро Linux лежит в нём, а в самом ядре в драйвере ФС ещё какой-нибудь третий, и ФС - в нём :)


  1. NickWinter
    27.09.2023 14:26
    +1

    Спасибо за статью! Я все такие устройства в отдельную сеть с изоляцией друг от друга добавляю. Пускай сам себя сканирует. Ну и DNS-фильтрация