Modbus/TCP до сих пор держится в промышленных сетях очень уверенно. Причина простая: протокол старый, понятный, поддерживается кучей контроллеров, шлюзов и SCADA-систем, а значит продолжает жить даже там, где остальная инфраструктура давно ушла вперёд. Проблема в том, что вместе с этой простотой в нём живут и старые ограничения. Базовый Modbus/TCP не даёт аутентификацию, не защищает содержимое команд и никак не помогает понять, кто именно пришёл к контроллеру и с какими правами.
Для защитника это неприятная история. Кто ходит к контроллеру, что читает, что пишет, в каком ритме, какие функции для этого участка нормальны, а какие там вообще не должны появляться, все это - загадка. В Modbus/TCP слишком много решает не сам протокол, а окружение вокруг него: сегментация, маршруты, инженерный доступ и нормальный разбор трафика.
Поэтому Modbus/TCP полезно разбирать глазами того, кто потом будет смотреть пакеты, журналировать обмен и ловить отклонения. Где в запросе лежит смысл, какие коды функций важны в первую очередь, как выглядит штатный цикл опроса и с какого места он начинает ломаться. Если эту логику не держать в голове, Modbus-трафик быстро превращается в привычный фон, который все видят, но почти никто по-настоящему не читает.
Что важно понимать про Modbus/TCP
Modbus/TCP кажется простым ровно до того момента, пока не начинаешь разбирать его в трафике всерьёз. На уровне сети всё выглядит почти скучно: TCP, порт 502, короткие запросы, короткие ответы, повторяющийся цикл опроса. Но внутри этой простоты сидит главное: протокол почти не пытается защищать себя сам. Он честно передаёт команды устройству и так же честно возвращает ответ. Для промышленной автоматизации это было удобно много лет. Для защиты - лишняя головная боль.От последовательной линии к TCP/IP
Изначально Modbus жил в мире последовательной связи. Линия, адрес устройства, чёткий цикл обмена, минимум лишней логики. Когда его перенесли в TCP/IP, базовую модель почти не тронули. Логика запросов и ответов осталась той же, набор функций тоже, а поверх всего этого просто добавили сетевую упаковку для работы в Ethernet-среде.Отсюда и текущая картина. Внутри промышленного сегмента Modbus/TCP выглядит как старый протокол, который поселили в обычную IP-сеть. Он получил маршрутизацию, коммутаторы, зеркалирование, захват трафика, межсетевые экраны, но не получил встроенной аутентификации, шифрования и контроля целостности на прикладном уровне. С точки зрения защиты это ключевой момент. Удобство интеграции выросло, а базовая модель доверия осталась почти той же, что и раньше.
Как устроен запрос
У Modbus/TCP короткий формат. Сначала идёт MBAP Header, потом уже полезная часть самого запроса. В MBAP Header четыре поля: Transaction ID, Protocol ID, Length и Unit ID. Дальше идёт PDU - код функции и данные, которые этой функции нужны.Если смотреть на пакет глазами защитника, смысл начинается не с красивого слова "заголовок", а с очень приземлённых вопросов. Кто с кем говорит. Какую именно функцию вызывает клиент. К какому диапазону объектов идёт обращение. И что вернул сервер в ответ.
Transaction ID нужен, чтобы связать запрос и ответ. Поле простое, но на живом захвате полезное: по нему удобно собирать пары пакетов и не путаться в рваном трафике, когда запросов много.
Protocol ID почти всегда равен нулю и редко даёт что-то интересное сам по себе.
Length показывает длину следующей части сообщения.
Unit ID становится особенно важным рядом со шлюзами, где за одним TCP-адресом может стоять не одно конечное устройство, а несколько.
Дальше начинается то, ради чего Modbus вообще читают в захвате: код функции и данные. Код функции отвечает на вопрос "что хотят сделать". Данные отвечают на вопрос "с чем именно хотят это сделать".
Где в пакете лежит смысл
Если нужно быстро понять, что происходит в канале, первым делом смотрят на код функции. Для Modbus/TCP это самый полезный ориентир. Уже на нём видно, клиент просто снимает состояние процесса или лезет в запись.Базовый набор, который встречается чаще всего:
0x01 - чтение coils0x02 - чтение discrete inputs0x03 - чтение holding registers0x04 - чтение input registersЭто зона чтения. Такие функции обычно и составляют фон в технологическом сегменте: HMI, SCADA или сервер опроса идут по своим адресам, снимают состояние, получают ответы, повторяют цикл.
Запись начинается дальше:
0x05 - запись одного coil0x06 - запись одного регистра0x0F - запись нескольких coils0x10 - запись нескольких регистровВот здесь трафик уже интереснее. Не потому что любая запись сразу означает инцидент. В промышленной сети запись вполне может быть штатной: оператор меняет уставку, инженерная станция загружает параметры, система отправляет управляющую команду. Но вес у такого пакета другой. Чтение помогает понять, как живёт сегмент. Запись меняет объект. Для мониторинга это уже совсем другой класс событий.
Coils, inputs и registers
Без модели данных Modbus/TCP разбирается хуже. Читатель видит код функции, но не всегда понимает, к чему он вообще относится. А различие там принципиальное.Coils - дискретные выходы, то есть значения 0 или 1, которыми можно управлять.
Discrete Inputs - дискретные входы, их обычно только читают.
Input Registers - входные регистры, тоже зона чтения.
Holding Registers - самый чувствительный кусок, потому что эти регистры не только читают, но и меняют.
На практике это означает простую вещь: если в трафике постоянно мелькает 0x03, надо понимать, какие именно holding registers опрашиваются и почему. В одном участке это обычные рабочие параметры, в другом - технологические уставки, а в третьем - служебные значения, к которым вообще редко ходят. Сам по себе код функции ещё не даёт всей картины. Адрес объекта и диапазон адресов часто значат не меньше.
Как выглядит нормальный обмен
Клиент отправляет запрос. Сервер отвечает. Если всё прошло нормально, в ответе возвращается тот же код функции и данные, которые относятся к операции. Если сервер не может обработать команду, он отвечает исключением. Тогда старший бит кода функции поднимается, а в данных появляется код ошибки.Для разбора трафика это очень удобно. Пока в ответе идёт тот же код функции, канал выглядит штатно. Как только вместо 0x03 приходит 0x83, а вместо 0x06 - 0x86, уже понятно, что устройство вернуло отказ. Дальше смотрят на код исключения: неверная функция, неверный адрес, неправильное значение, занятое устройство, недоступный путь через шлюз. Один такой ответ ещё ни о чём не говорит. Серия одинаковых исключений уже даёт нормальный повод разбираться.
Почему Modbus/TCP опасен по своей конструкции
Главная проблема Modbus/TCP не в одной отдельной уязвимости. Проблема в том, как устроено доверие. Базовый протокол не проверяет, кто именно прислал команду. Не шифрует содержимое. Не защищает прикладной уровень от подмены. Не помогает отличить штатный клиент от любого другого узла, который получил маршрут до TCP/502.Это меняет всю логику защиты. В случае с обычными корпоративными протоколами часть доверия часто уже встроена в сам обмен: учётная запись, сеанс, аутентификация, шифрование, согласование параметров. В Modbus/TCP ничего такого по умолчанию нет. Если кто-то оказался в нужной зоне сети, дальше протокол будет с ним разговаривать так же спокойно, как с легитимной системой.
Отсюда и практический вывод для OT-среды. Без сегментации, контроля маршрутов, жёсткого инженерного доступа и нормальной видимости трафика сам Modbus/TCP остаётся слишком открытым. Он хорошо читается в сети, но так же хорошо позволяет читать и отправлять команды любому узлу, который уже оказался рядом.
В статье «Уязвимости промышленных протоколов связи: фундаментальное исследование Modbus TCP и BACnet/IP» мы разобрали саму логика старых промышленных протоколов: почему они до сих пор живут в OT-среде, чем за это приходится платить и откуда у Modbus берётся его хроническая проблема с доверием внутри сети.
Что важно запомнить
Для защитника у Modbus/TCP есть четыре опорные точки.Первая - MBAP Header. Он нужен, чтобы не теряться в потоке и правильно связывать запросы с ответами.
Вторая - код функции. Он сразу показывает, чтение это или запись.
Третья - адресуемые объекты. Без них нельзя понять, насколько операция чувствительна для процесса.
Четвёртая - сама модель доверия. У протокола почти нет собственной защиты, так что вся реальная безопасность живёт вокруг него, а не внутри него.
Дальше Modbus/TCP уже удобнее читать не как абстрактный промышленный стандарт, а как очень конкретный сетевой обмен: кто ходит к устройству, что именно запрашивает, как часто это делает и с какого момента этот трафик перестаёт быть штатным.
Как читать Modbus/TCP в трафике
Modbus/TCP хорошо читается в захвате. В этом его плюс и его же проблема. Пакеты короткие, структура повторяется, ответы обычно идут сразу, а ритм опроса в промышленном сегменте часто очень ровный. Если у тебя есть зеркало порта или запись с сетевого сенсора, через несколько минут уже видно, кто в сети работает как клиент, какие устройства отвечают и где в канале живут только чтения, а где встречается запись. Спецификация Modbus описывает обмен просто: запрос клиента, обычный ответ сервера или ответ с исключением.С чего начинать в Wireshark
Начинать лучше грубо: tcp.port == 502. Этого хватает, чтобы отрезать основной мусор и увидеть весь Modbus/TCP. Дальше уже можно переходить к полям самого протокола. У Wireshark есть разбор Modbus/TCP и нормальный набор полей для фильтрации: mbtcp.trans_id, mbtcp.prot_id, mbtcp.unit_id, mbtcp.modbus.func_code, mbtcp.modbus.exception_code. Этого достаточно, чтобы быстро собрать рабочую картину по функциям, Unit ID и ошибкам.Полезный приём - сразу вынести в колонки адрес источника, адрес назначения, идентификатор транзакции, Unit ID, код функции и код исключения. После этого трафик перестаёт выглядеть как простыня из пакетов. Начинает читаться нормальный цикл обмена: кто кого опрашивает, как часто, какие функции крутятся постоянно, где вылезают ошибки и в каком канале внезапно появилась запись. Поля для этого у Wireshark есть штатно.
Как выглядит обычный цикл обмена
В штатном обмене клиент отправляет запрос, а сервер отвечает с тем же кодом функции. Если запрос был на чтение holding registers с 0x03, в обычном ответе останется 0x03. Если запрос был на запись одного регистра с 0x06, в нормальном ответе сервер тоже вернёт 0x06. Это базовая вещь, но на ней держится почти весь пассивный разбор: пока код функции в ответе совпадает с запросом, канал выглядит штатно.Если сервер не может обработать команду, он возвращает исключение. Тогда старший бит кода функции становится единицей. На практике это выглядит так: вместо 0x03 приходит 0x83, вместо 0x06 - 0x86. В данных при этом появляется отдельный код исключения. Для защитника это очень удобный ориентир: по одному полю уже видно, что устройство не просто ответило, а вернуло отказ.
Какие функции смотреть в первую очередь
Для пассивного мониторинга Modbus/TCP важнее всего разделять чтение и запись. Чтение обычно даёт фон сегмента. Сюда относятся 0x01, 0x02, 0x03 и 0x04: чтение coils, discrete inputs, holding registers и input registers. Именно на этих функциях обычно строится штатный цикл опроса HMI, SCADA или сервера телеметрии. По ним удобно собирать базовую линию: кто читает, как часто, к каким диапазонам адресов обращается.Запись - это уже другой разговор. 0x05, 0x06, 0x0F и 0x10 меняют coils или registers. В одних сегментах это штатная часть управления, в других почти не встречается. Поэтому функции записи полезно выделять отдельно сразу, без философии. Если в канале месяцами шли только чтения, а потом появился 0x10 по новому диапазону регистров, это уже хороший повод смотреть глубже.
Что видно даже без активных действий
Пассивный захват даёт больше, чем многие ожидают. Без единого активного запроса можно восстановить список клиентов и серверов, понять, какие Unit ID используются, выделить нормальную частоту опроса, увидеть операции записи и понять, какие диапазоны адресов в этом сегменте трогают постоянно. Для OT это уже рабочая база. Если одна система раз в две секунды читает один и тот же блок holding registers, а потом в этот же канал влезает новый узел с редкими запросами на запись, картина меняется сразу, даже без сложной аналитики.Здесь лучше не пытаться с первого пакета угадывать инцидент. Сначала собирают нормальный рисунок обмена, потом ищут то, что из него торчит. В Modbus/TCP такими вещами чаще всего становятся новый источник, переход от чтения к записи, другой диапазон адресов, всплеск исключений и поломанный ритм опроса. Протокол сам по себе довольно прямолинейный, так что отклонения на его фоне обычно заметны, если есть с чем сравнивать.
На что смотреть в ответах с ошибкой
Исключения полезны не только как факт отказа, но и как подсказка, где именно что-то пошло криво. Самые ходовые коды - 01 Illegal Function, 02 Illegal Data Address, 03 Illegal Data Value, 04 Server Device Failure. В смешанных сетях со шлюзами ещё важны 0A Gateway Path Unavailable и 0B Gateway Target Device Failed to Respond`. Один такой ответ может быть обычной эксплуатационной историей. Серия одинаковых ошибок в одном канале - уже нет. Особенно если раньше этот же клиент работал ровно.Что полезно держать под рукой
Для быстрой работы в Wireshark вам хватит этого набора:- tcp.port == 502 - весь Modbus/TCP;
- mbtcp - только разобранный трафик Modbus/TCP;
- mbtcp.modbus.func_code == 3 - чтение holding registers;
- mbtcp.modbus.func_code == 16 - запись нескольких регистров;
- mbtcp.modbus.exception_code - ответы с исключением;
- mbtcp.unit_id == N - трафик к конкретному Unit ID.
Что считать подозрительным в Modbus-сети
В нормальном сегменте Modbus/TCP обмен обычно повторяется почти без сюрпризов. Те же клиенты, те же устройства, те же коды функций, те же диапазоны адресов и примерно тот же ритм опроса. Поэтому подозрительное поведение в такой сети чаще всего видно не по одной “магической” команде, а по тому, что ломается привычный рисунок трафика.Новый источник запросов
Первое, на что обычно смотрят, - кто вообще начал ходить к устройству. В Modbus/TCP это важно сразу по двум причинам. Протокол сам по себе не проверяет, кто именно прислал запрос, и не умеет отделять штатного клиента от постороннего узла, у которого просто появился маршрут до TCP/502. Если к контроллеру внезапно пошёл новый адрес, этот факт уже требует проверки, даже если запросы выглядят “мирно” и состоят только из чтения. Обычный список клиентов в промышленном сегменте, как правило, короткий: HMI, SCADA, шлюз, инженерная станция, иногда сервер архивации. Всё остальное проверяют отдельно.Сразу смотреть стоит на четыре вещи: откуда идёт запрос, к какому Unit ID он обращается, какие функции использует и был ли такой узел в этом канале раньше. Новый источник с постоянным чтением ещё может оказаться штатной системой после изменения конфигурации. Новый источник с записью в регистры или с обходом по разным Unit ID уже выглядит заметно хуже.
Переход от чтения к записи
В Modbus/TCP чтение и запись для защитника имеют разный вес.0x01, 0x02, 0x03, 0x04 обычно означают сбор состояния: coils, discrete inputs, holding registers, input registers. 0x05, 0x06, 0x0F, 0x10 уже меняют выходы или регистры. В спецификации это обычные публичные функции, никакой “специальной” метки опасности у них нет. Но для мониторинга это водораздел: чтение показывает, что клиент наблюдает за процессом, запись показывает, что он на процесс влияет.Здесь нельзя опираться только на номер функции. В одних участках запись штатна и идёт постоянно, в других почти не встречается. Поэтому проверяют связку: кто пишет, когда пишет, куда пишет и как часто это делал раньше. Если узел месяцами только читал holding registers, а потом начал отправлять
0x10 в новый диапазон адресов, этого уже достаточно, чтобы поднимать разбор.Новый диапазон адресов
Адресация в Modbus/TCP важна не меньше, чем код функции. Сам протокол не делит регистры на “безобидные” и “чувствительные”, он просто передаёт адрес и количество объектов. Внутри процесса разница может быть огромной. Один диапазон отвечает за обычную телеметрию, другой - за уставки, третий - за служебные параметры, к которым в штатном режиме почти не обращаются.Поэтому хороший профиль сегмента всегда включает карту нормальных диапазонов. Какие coils читают постоянно. Какие holding registers меняют только из HMI. Какие зоны памяти вообще не должны всплывать в этом канале. Новый диапазон сам по себе ещё не доказывает проблему, но в сочетании с новым источником или записью вес такого события быстро растёт.
Резкая смена ритма
Modbus/TCP хорошо держится на повторяемости. Для многих сегментов характерен ровный цикл опроса: раз в секунду, раз в две секунды, с другой фиксированной частотой. Когда ритм резко меняется, это видно даже без глубокого разбора полезной нагрузки. Слишком частые чтения, короткая серия однотипных запросов, пауза там, где раньше всё шло стабильно, всплеск обращений к одному устройству - всё это стоит разбирать отдельно.Такой признак хорош тем, что он ловит не только “неправильные” команды, но и поведение в целом. Даже легитимная функция в нетипичном ритме уже выглядит иначе. Если обычный клиент работал ровно и спокойно, а потом в том же канале пошёл плотный перебор адресов или серия записей подряд, меняется не один пакет - меняется весь рисунок обмена.
Исключения и ответы с ошибкой
Исключения в Modbus/TCP видны хорошо. В нормальном ответе сервер просто повторяет код функции из запроса. В ответе с ошибкой старший бит кода функции становится единицей, а в данных появляется код исключения. Для0x03 это будет 0x83, для 0x06 - 0x86 и так далее. Сами коды исключений перечислены в спецификации: 01 Illegal Function, 02 Illegal Data Address, 03 Illegal Data Value, 04 Server Device Failure, 05 Acknowledge, 06 Server Device Busy, 08 Memory Parity Error, 0A Gateway Path Unavailable, 0B Gateway Target Device Failed to Respond.Один такой ответ ещё ни о чём не говорит. Ошибка адреса, временная занятость устройства или сбой за шлюзом бывают и в штатной эксплуатации. Серия одинаковых исключений в стабильном канале уже выглядит иначе. Особенно если раньше этот же клиент работал без ошибок, а теперь внезапно получает
01 по новым функциям или 02 по адресам, которых в канале раньше не было.Редкие и нетипичные функции
Отдельно полезно смотреть на функции, которые на конкретной площадке почти не встречаются. В спецификации Modbus часть из них помечена какSerial Line only: например, 0x07 Read Exception Status, 0x08 Diagnostics, 0x0B Get Comm Event Counter, 0x0C Get Comm Event Log, 0x11 Report Server ID. Если такие функции появляются в обычном канале Modbus/TCP, их лучше не оставлять без внимания.Здесь не нужно впадать в крайности. Редкая функция сама по себе ещё не равна инциденту. Но для расследования она почти всегда важнее тысячного чтения holding registers. Особенно если пришла от нового источника, ушла к нетипичному Unit ID или совпала по времени с ростом ошибок и сменой ритма.
| Признак | Когда это может быть штатно | Когда уже нужен разбор |
|---|---|---|
| Новый источник запросов | Ввод новой HMI, SCADA, шлюза или инженерной станции | Узел раньше не работал в канале и сразу идёт к записи или новым адресам |
| Появление записи | Штатные действия HMI или инженерного ПО | Запись идёт из нетипичного узла, в нетипичное время или к новому диапазону |
| Новый диапазон адресов | Плановое изменение логики, наладка, ввод объекта | Адреса раньше не использовались, особенно вместе с записью |
| Смена ритма | Сервисное окно, наладка, кратковременная диагностика | Частота обмена резко меняется без понятной причины |
| Серия исключений | Временный сбой, ошибка настройки, проблемы за шлюзом | Ошибки идут подряд и совпадают с новыми функциями, адресами или источником |
| Редкая функция | Редкое обслуживание или специфическая реализация | Функция почти не встречалась в сегменте и пришла в нетипичном контексте |
В Modbus-сети обычно выигрывает самый приземлённый подход: сначала собирают нормальный профиль сегмента, потом ищут, где он ломается. Без этой опоры даже хорошо читаемый протокол быстро превращается в спорный поток событий.
Detection и мониторинг
Для Modbus/TCP хороший detection начинается не с длинного набора сигнатур, а с видимости. Если в сегменте нет нормального захвата трафика, зеркала порта или сенсора на нужном участке, дальше всё превращается в догадки. Modbus удобен тем, что его трафик читается без труда: коды функций, Unit ID, ответы с исключениями, пары запрос-ответ. Этого уже хватает, чтобы выделять запись, нетипичные обращения и сломанный ритм обмена. Проблема в другом: без контекста даже понятный трафик быстро шумит. Поэтому detection здесь обычно строят в три слоя: правила на понятные события, глубокий разбор промышленного трафика и базовая линия по конкретному сегменту. Suricata и Snort умеют работать с полями Modbus, а промышленные платформы вроде Claroty делают ставку на пассивный мониторинг именно из-за его безопасной для OT-среды природы.Suricata и Snort: что имеет смысл ловить сразу
В Suricata есть отдельныйmodbus keyword. Он позволяет писать правила по функциям, типу доступа и Unit ID. В Snort для этого же есть modbus_func, modbus_unit и modbus_data. Для Modbus-сети это важнее, чем попытки матчить голое содержимое пакета, потому что правила по разобранным полям живут дольше и читаются проще.Первый набор событий обычно очень короткий. Запись в coils и registers, если в этом сегменте запись редка. Новый источник на TCP/502. Нетипичный Unit ID. Серии ответов с исключениями. Редкие функции, которые почти не встречаются на площадке. Этого уже достаточно, чтобы быстро отсеять основную массу фона и получить внятную очередь на разбор. Пытаться запихнуть в сигнатуры всю технологическую логику обычно бессмысленно: правила получаются хрупкими, а шум только растёт.
Отдельно стоит выделять функции записи. Для Modbus это почти всегда самый тяжёлый класс событий в мониторинге. Чтение может быть фоном, инвентаризацией, обычным циклом опроса, сбоем в HMI или сервисной диагностикой. Запись почти всегда требует контекста: кто именно её сделал, к какому диапазону объектов она ушла и была ли такая операция в этом канале раньше.
Где DPI даёт больше, чем набор правил
Сигнатурный слой даёт быстрое сито, но сам по себе он слабый. В промышленной сети одно и то же событие может означать совсем разное в зависимости от роли узла. Запись в holding register от HMI в рабочее окно - одна история. Та же запись от новой станции сопровождения ночью - другая. Поэтому рядом с правилами нужен разбор промышленного трафика на уровне контекста: кто с кем говорит, какие Unit ID используются, какой набор функций считается нормальным, как выглядит обычный ритм и куда именно идут обращения. Это и есть та зона, где DPI действительно полезен. Claroty описывает пассивный мониторинг как способ получать постоянную видимость по активам и трафику в OT-среде, а Nozomi делает упор на глубокий разбор трафика и поведенческий анализ как основу видимости и выявления отклонений.Для Modbus/TCP это особенно заметно. Протокол короткий, поэтому смысл пакета быстро читается, но без контекста защитник всё равно не понимает, штатное это действие или нет. DPI нужен не ради красивого слова, а ради очень приземлённых вещей: карта клиентов и серверов, профиль обмена, перечень допустимых функций, история по Unit ID и диапазонам регистров. Когда всё это собрано, пакет перестаёт быть просто “запросом на 502-й порт” и становится частью уже понятного рисунка обмена.
Базовая линия: без неё Modbus detection быстро шумит
Базовая линия для Modbus-сегмента почти всегда важнее сложной сигнатуры. Протокол сам по себе не слишком разнообразный. Именно поэтому на его фоне хорошо видны отклонения, если уже ясно, как выглядит норма. Список постоянных клиентов, ожидаемые Unit ID, обычные функции, диапазоны адресов, интервалы опроса, допустимые записи - этого хватает, чтобы резко снизить шум.Слишком сложную модель тут строить не нужно. Обычно достаточно ответить на несколько вопросов. Какие узлы стабильно ходят к PLC. Какие функции в сегменте обычны. Где запись допустима, а где её почти не бывает. Какие адреса читают постоянно. Какие исключения встречаются редко, а какие вообще не должны появляться в штатном канале. После этого detection перестаёт жить на одном номере функции и начинает опираться на нарушение уже известного рисунка.
Что собирать в первую очередь
Минимальный набор для Modbus detection довольно понятен. Нужен пассивный доступ к трафику на участке, где проходят запросы к контроллерам. Нужен разбор самого протокола: функция, Unit ID, код исключения, направление обмена, идентификатор транзакции. Нужен список активов: HMI, SCADA, шлюзы, инженерные станции, PLC. Нужна история по времени, чтобы видеть не только содержимое пакета, но и ритм.Если этого нет, даже хороший IDS-движок упрётся в потолок. Он покажет запись, исключение или редкую функцию, но не скажет, нормальное это событие для площадки или нет. Если это есть, даже простые правила начинают работать заметно лучше, потому что они попадают не в абстрактный “опасный Modbus-трафик”, а в реальное отклонение от профиля сегмента.
Как выглядит первый рабочий набор правил
Для Modbus/TCP первый набор лучше держать коротким. В него обычно входят:- функции записи, если запись редка или разрешена только ограниченному набору узлов;
- новый клиент на TCP/502;
- обращения к нетипичному Unit ID;
- редкие функции, которые почти не встречаются на площадке;
- рост исключений в стабильном канале;
- резкий всплеск частоты запросов в коротком окне.
| Слой detection | Что даёт | Где без него сыпется качество |
|---|---|---|
| Правила Suricata / Snort | Быстрый отбор записи, исключений, редких функций, нетипичных клиентов | Без них трудно быстро вытащить важные эпизоды из полного потока |
| DPI и контекст | Роль узла, карта связей, допустимые функции, история по Unit ID и адресам | Без этого одно и то же событие выглядит спорно |
| Базовая линия | Норма по источникам, ритму, функциям и диапазонам адресов | Без неё Modbus detection быстро начинает шуметь |
| Пассивная видимость | Реальный трафик без активного вмешательства в процесс | Без неё всё остальное остаётся неполным |
В статье «Threat hunting в промышленной сети: как искать аномалии без полной видимости» тема продолжена уже со стороны охоты за отклонениями: как строить базовую линию в OT, на какие источники данных опираться и почему в промышленной сети пассивная наблюдаемость часто важнее любой красивой сигнатуры.
Защита и сдерживание
У Modbus/TCP защита начинается не в пакете, а в сети вокруг него. Сам протокол не умеет подтверждать, кто именно отправил команду, не защищает содержимое и не проверяет целостность на прикладном уровне. Поэтому главный вопрос здесь очень простой: кто вообще может дотянуться до TCP/502 и при каких условиях. Защищённый профиль Modbus Security существует отдельно: он добавляет TLS, сертификаты X.509 и использует порт 802. Это полезный слой, но он не отменяет базовые меры в самой сети.Сегментация и контроль маршрутов
Самая полезная мера для Modbus/TCP - убрать лишний путь к контроллеру ещё до всякого разбора трафика. Если обычная рабочая станция, сервер из соседнего сегмента или временный ноутбук подрядчика могут спокойно достучаться до PLC, дальше протокол уже ничем не поможет. Поэтому в промышленной сети сначала режут лишние маршруты, а уже потом обсуждают сигнатуры и аномалии.В хорошем сегменте список узлов, которым вообще разрешено ходить на TCP/502, короткий и понятный. HMI работает со своим набором устройств. SCADA - со своим. Шлюзы и инженерные станции живут отдельно. Всё, что не относится к этому контуру, не должно видеть контроллеры напрямую. Для Modbus/TCP это даёт больше пользы, чем любая сложная аналитика: когда лишнего маршрута нет, протоколом уже нельзя злоупотребить с любого попавшего в сегмент узла.
Инженерный доступ
В промышленной среде много риска приходит через сопровождение. Не потому что инженерный доступ сам по себе плохой, а потому что он часто шире, чем нужно. Если инженерная станция, сервисный ноутбук или jump host имеют постоянный и слабо ограниченный доступ к контроллерам, в этом канале быстро теряется грань между штатной работой и опасным отклонением.Здесь лучше работает короткий и учтённый доступ. Отдельные станции, понятные окна обслуживания, журналирование и жёсткий список допустимых направлений дают сети внятную форму. Тогда запись в регистры хотя бы связана с конкретным узлом, временем и задачей. Без этого любая операция записи в Modbus выглядит одинаково: команда пришла, устройство её приняло, а дальше уже приходится задним числом разбираться, кто это сделал и зачем.
Пассивный мониторинг и глубокий разбор трафика
Для OT-среды пассивный контроль почти всегда безопаснее активных проверок. Claroty прямо описывает passive monitoring как способ получать видимость по активам и трафику без внесения дополнительного сетевого шума, а Nozomi делает упор на пассивное наблюдение и глубокий разбор трафика как основу для видимости и выявления угроз. Для Modbus/TCP это особенно уместно: протокол и так хорошо читается, поэтому лишний активный шум в технологическом сегменте чаще мешает, чем помогает.На практике это значит простую вещь: у защитника должен быть доступ к реальному обмену между клиентами и контроллерами. Через зеркало порта, TAP или сенсор на нужном участке. Тогда видно, кто в сегменте постоянно читает состояние, где появляется запись, как часто идут исключения и когда ломается привычный ритм. Без этой видимости даже хорошие правила остаются половинчатыми. Они могут показать интересный пакет, но не дадут нормальной картины всего канала.
Разрешать по роли, а не по умолчанию
Modbus/TCP плохо переносит широкое сетевое доверие. Если политика доступа устроена по принципу «пусть ходят, а мониторинг потом разберётся», сегмент быстро становится рыхлым. Лучше работает обратный подход: сначала определяется роль узла, потом - куда он вообще может ходить, и только после этого открывается нужный маршрут.Это касается и чтения, и записи. Если запись в регистры нужна только HMI и одной инженерной станции, именно эти узлы и должны иметь такое право. Если определённый PLC никогда не должен принимать команды от серверов верхнего уровня, такого пути не должно существовать вовсе. Для Modbus/TCP это скучная, но очень рабочая логика. Она резко уменьшает число сценариев, в которых протоколом можно злоупотребить просто потому, что доступ оказался шире, чем нужно.
Что даёт Modbus Security и где его место
Modbus Security закрывает именно те свойства, которых не хватает классическому Modbus/TCP: аутентификацию сторон, защиту целостности и защиту содержимого канала. Modbus Organization описывает этот профиль как TLS-обёртку над традиционным Modbus с сертификатами X.509 и использованием порта 802. Технически это сильный шаг вперёд по сравнению с классическим TCP/502.Но ждать от него чудес не стоит. Даже защищённый профиль не заменяет сегментацию, контроль инженерного доступа и пассивную видимость по сети. Он закрывает транспортный слой - кто с кем говорит и можно ли доверять самому каналу. Всё остальное остаётся задачей архитектуры: какие узлы вообще должны видеть друг друга, какие команды для них нормальны и кто отвечает за контроль изменений в технологическом процессе.
| Мера | Что она даёт | Что без неё остаётся слабым |
|---|---|---|
| Сегментация и фильтрация маршрутов | Убирает лишний доступ к TCP/502 | Любой лишний узел с маршрутом до PLC остаётся риском |
| Выделённый инженерный доступ | Сужает круг узлов, которые могут менять параметры | Запись без понятного источника трудно отделить от штатной работы |
| Пассивный мониторинг | Даёт картину реального обмена без вмешательства в процесс | Без видимости трудно строить профиль сегмента и разбирать отклонения |
| Политика по ролям | Ограничивает, кто и куда вообще может ходить | Широкое сетевое доверие делает Modbus слишком открытым |
| Modbus Security | Добавляет TLS, сертификаты и защиту целостности | Классический Modbus/TCP на TCP/502 остаётся без этих свойств |
Где Modbus перестаёт быть просто фоном
Надеюсь, теперь всем стало понятно, что Modbus/TCP опасен лишь потому, что он слишком прямолинейный. Если в промышленной сети уже появился лишний маршрут до контроллера, дальше протокол сам по себе почти не мешает ни чтению, ни записи, ни ошибочным командам, ни чужому клиенту. Поэтому защита здесь держится на очень приземлённых вещах: кто вообще может выйти на TCP/502, какие узлы имеют право писать, где виден реальный обмен и насколько хорошо площадка знает свой обычный рисунок трафика. Именно в это я и заложил смысл нашего разбора.А хорошая OT-защита здесь начинается с простой дисциплины: жёсткая сегментация, короткий и понятный инженерный доступ, пассивный мониторинг и нормальный профиль обмена. Всё остальное уже надстраивается сверху. И вопрос в итоге остаётся очень интересный: ваш Modbus-трафик в сети действительно читают, или он до сих пор считается привычным производственным фоном, который никто не проверяет всерьёз?
Последнее редактирование: