Статья Feature engineering для сетевого трафика: почему качество фичей решает больше, чем выбор алгоритма в ML-моделях IDS

Монитор с зелёным свечением фосфорного текста на чёрном фоне отображает парсер сетевых логов и ASCII-график важности признаков. Сканирующие полосы и зернистость создают атмосферу ретро-терминала.


Полгода назад мы убили две недели на подбор гиперпараметров LightGBM для детекта C2-бэконов в корпоративном трафике. F1 болтался между 0.71 и 0.74 - хоть learning rate крути, хоть max_depth, хоть число деревьев. Потом за один вечер добавили три фичи: стандартное отклонение межпакетных интервалов, энтропию размеров payload и соотношение исходящих к входящим байтам на уровне flow. F1 прыгнул до 0.93 на том же тестовом сете. Алгоритм тот же, данные те же - изменилось то, что модель «видит» в трафике. В feature engineering сетевого трафика для машинного обучения качество признаков определяет потолок модели, а алгоритм лишь приближает к этому потолку.
Feature Engineering - процесс преобразования исходных данных в формат, который лучше подходит для обучения моделей машинного обучения.

Алгоритм вторичен: что говорят цифры​

Типичная ошибка при построении ML-моделей обнаружения вторжений - вкладывать 80% времени в архитектуру модели и 20% в подготовку данных. Пропорция должна быть обратной.

Три алгоритма: Random Forest, LightGBM, простая полносвязная нейросеть. Подаём сырые flow-фичи из Zeek conn.log - duration, orig_bytes, resp_bytes, orig_pkts, resp_pkts, proto. Разброс F1 по классу «malicious» укладывается в 2–4 процентных пункта. Добавляем производные признаки - статистику по временным окнам, энтропию, ratio-фичи - и каждый из алгоритмов показывает прирост 15–25% F1. Разница между самими алгоритмами на обогащённых фичах остаётся в тех же 2–3%.
Random Forest - это алгоритм машинного обучения, который объединяет множество независимых «деревьев решений» в один ансамбль.
LightGBM - это популярная библиотека алгоритмов градиентного бустинга над деревьями решений, разработанная Microsoft.

Причина простая: алгоритм находит разделяющие гиперплоскости в том признаковом пространстве, которое ему дали. Но он не умеет придумывать новые оси этого пространства. Если в данных нет фичи «стандартное отклонение IAT за 60 секунд», ни одна модель не обнаружит jittered beacon по его сигнатуре в межпакетных интервалах - ей просто негде увидеть этот паттерн.

По данным IBM X-Force Threat Intelligence Index 2025, 70% инцидентов, расследованных X-Force в 2024 году, затронули критическую инфраструктуру. Сигнатурный IDS на базе Suricata или Snort ловит известные паттерны, но не адаптируется к новым TTPs. ML-based NIDS теоретически решает эту проблему - при условии, что фичи отражают реальное поведение трафика, а не шум в красивой обёртке.

Три уровня признаков сетевого трафика​

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

Пакетный уровень: атомарные характеристики​

Самый низкий уровень - отдельный пакет. Из него вытягиваются: размер пакета (total_length из IP-заголовка), TTL, TCP-флаги (SYN, ACK, FIN, RST, PSH, URG), протокол транспортного уровня, порты источника и назначения, размер payload.

В изоляции пакетный уровень почти бесполезен для классификации. Один SYN-пакет на порт 443 неотличим от начала легитимного TLS-хэндшейка и от первого пакета SYN-скана. Контекст появляется только при агрегации.

Но пакетные фичи - фундамент. Если на этом уровне вы неправильно парсите флаги через Scapy или теряете retransmissions, все производные признаки будут загрязнены. Wireshark тут - ваш лучший друг для визуальной верификации того, что парсер выдаёт на конкретной сессии.

Flow-уровень: агрегация потоков​

Flow - группа пакетов с общим 5-tuple (src_ip, dst_ip, src_port, dst_port, proto). Здесь начинается реальная работа с признаками для IDS.

ИнструментПлюсыОграниченияКогда использовать
CICFlowMeter80+ готовых фичей, GUIJava-зависимость, OOM на pcap >1 ГБ, слабая расширяемостьБыстрый прототип, работа с CIC-IDS2017
Zeek conn.logСтабильный, масштабируется, интеграция с SIEMБазовый набор flow-фичей, нужна дообработка в pandasПродакшен-пайплайн
Scapy + PythonПолный контроль над каждым битомМедленно на больших pcap (>500 МБ), весь код - ручнойИсследование кастомных фичей

Zeek conn.log выдаёт по каждому flow: ts, uid, id.orig_h/p, id.resp_h/p, proto, service, duration, orig_bytes, resp_bytes, conn_state, orig_pkts, resp_pkts. CICFlowMeter генерирует более 80 статистических фичей: средний, минимальный, максимальный размер пакета в прямом и обратном направлении, стандартное отклонение, полный набор IAT-статистик.

Критический параметр на этом уровне - таймаут flow. Zeek определяет границы TCP-сессий по FIN/RST, для UDP использует таймаут неактивности. CICFlowMeter по умолчанию ставит 120 секунд. Эта настройка напрямую бьёт по фичам: слишком длинный таймаут склеит два разных сеанса, слишком короткий - разорвёт один. Для обнаружения C2-бэконов с интервалом 300 секунд дефолтный таймаут CICFlowMeter уже не подходит - и это ловушка, на которую наступают многие.

Поведенческий уровень: окна и энтропия​

Самый ценный и самый сложный уровень. Здесь агрегируется не один flow, а поведение группы flow за временное окно - обычно 30–120 секунд.

Ключевые поведенческие фичи для обнаружения аномалий в сетевом трафике:
  • Количество уникальных dst_port от одного src_ip за 60 секунд. Значение >20 - горизонтальный скан. Нормальный пользователь за минуту обращается к 2–5 портам.
  • Энтропия dst_port по Шеннону. Если src_ip ходит на 200 разных портов за окно, энтропия будет выше 7 бит. У легитимного клиента - ниже 1.5 бит.
  • Ratio SYN-only к total TCP-соединениям за окно. SYN-flood или SYN-scan дают ratio > 0.8; нормальный трафик - 0.05–0.15.
  • Стандартное отклонение IAT (inter-arrival time). C2-бэкон с jitter показывает характерный паттерн: малое std на фоне случайного шума нормального трафика. Стабильный IAT (std < 0.5 с) при длинной сессии - красный флаг.
  • Энтропия payload на уровне байтов. Выше 7.5 бит на байт при малом размере пакета - вероятный признак шифрованного или обфусцированного канала.
  • Byte ratio (sent/received) на уровне flow. C2 с командами «poll» показывает резко асимметричный паттерн: много маленьких исходящих, редкие крупные входящие.

Какие фичи ловят какие TTPs: маппинг на MITRE ATT&CK​

1780459919653.webp

Проблема ML-based IDS - объяснимость. Модель говорит «аномалия», но а что именно аномально? Feature engineering с привязкой к конкретным TTPs снимает этот вопрос: каждая фича отражает конкретное поведение атакующего.
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Практический пайплайн: от pcap до обученной модели​

Требования к окружению​

  • ОС: Ubuntu 22.04+ или Kali Linux 2024+
  • RAM: минимум 8 ГБ для pcap до 500 МБ; рекомендуется 16 ГБ для крупных датасетов (CIC-IDS2017 в pcap-формате занимает ~50 ГБ)
  • Zeek: 6.0+ (sudo apt install zeek или сборка из исходников)
  • Python: 3.10+, зависимости: pandas, numpy, scikit-learn, lightgbm, shap
  • Режим: полностью offline после установки зависимостей; интернет не требуется

Шаги пайплайна​

1. Генерация conn.log. Команда zeek -r capture.pcap создаст структурированные логи в текущей директории. Каждая строка conn.log - один flow с полями ts, uid, id.orig_h, id.orig_p, id.resp_h, id.resp_p, proto, service, duration, orig_bytes, resp_bytes и десятком дополнительных.

2. Парсинг и базовые производные фичи.
Python:
import pandas as pd

df = pd.read_csv('conn.log', sep='\t', comment='#',
    names=['ts','uid','src_ip','src_port','dst_ip','dst_port',
           'proto','service','duration','orig_bytes','resp_bytes',
           'conn_state','missed_bytes','history','orig_pkts',
           'resp_pkts','orig_ip_bytes','resp_ip_bytes'])
df['byte_ratio'] = df['orig_bytes'] / (df['resp_bytes'] + 1)
df['pkt_ratio'] = df['orig_pkts'] / (df['resp_pkts'] + 1)
df['bytes_per_pkt_fwd'] = df['orig_bytes'] / (df['orig_pkts'] + 1)
+ 1 в знаменателях - не лень, а необходимость. Без этого деление на ноль при однонаправленных flow (типичная ситуация для SYN-scan, где resp_bytes = 0 и resp_pkts = 0) заполнит датасет NaN-ами и убьёт обучение.

3. Поведенческие фичи через временные окна. Сортируем по timestamp и для каждого flow считаем: сколько уникальных dst_port от этого src_ip за последние 60 секунд. На больших датасетах наивный groupby + rolling работает часами. Эффективнее: pd.merge_asof или предварительная агрегация в бакеты по 60 секунд с подсчётом nunique. Энтропия dst_port вычисляется функцией Шеннона: H = -sum(p * log2(p)) по распределению портов в окне.

4. Обучение и проверка через SHAP.
Python:
import shap
import lightgbm as lgb

model = lgb.LGBMClassifier(n_estimators=200, max_depth=6)
model.fit(X_train, y_train)
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)
shap.summary_plot(shap_values[1], X_test, max_display=15)
На моих экспериментах стабильная тройка лидеров feature importance: byte_ratio, dst_port_entropy_60s и std_iat. Фичи вроде TTL или src_port оказываются в хвосте - они не несут поведенческой информации и работают как шум.

Ловушки feature engineering в сетевом трафике​

1780460361482.webp

Утечка через IP-адреса​

Если оставить src_ip и dst_ip как категориальные фичи (или закодировать через one-hot), модель запомнит: «трафик с 192.168.1.105 = атака». На обучающем датасете - F1 под 0.99. На новом трафике - 0.50. Модель выучила адреса лабораторных машин атакующего, а не поведение.

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

Временная утечка​

При вычислении оконных фичей ошибка в сортировке по timestamp или использование двунаправленного окна (захват будущих событий) создаёт ситуацию: модель видит «в ближайшие 60 секунд после этого flow произойдёт ещё 50 SYN». Она предсказывает атаку с подозрительной точностью, но в продакшене будущего нет - и модель разваливается.

Проверка: обучите модель на данных до определённого timestamp, протестируйте на данных после. Если F1 падает на 15+ процентных пунктов по сравнению с random split - утечка есть.

Ловушка CICFlowMeter​

CICFlowMeter генерирует 80+ фичей, и соблазн «кинуть всё в модель» понятен. Проблема: многие из них - линейные комбинации друг друга. total_fwd_packets умноженный на avg_fwd_packet_length приблизительно равен total_length_fwd_packets. Мультиколлинеарность не убивает деревья напрямую, но маскирует реальный вклад каждой фичи. SHAP показывает 15 «важных» признаков, из которых 10 - одно и то же, вид сбоку. До обучения считайте корреляционную матрицу и отбрасывайте фичи с попарной корреляцией > 0.95. Это скучно, но без этого интерпретация модели - фикция.

Слепые зоны ML-фичей: что атакующий обходит в feature-based IDS

Feature engineering - инструмент с чёткими границами. Атакующий, который понимает устройство детекции, целенаправленно обходит конкретные фичи. Для пентестера знание этих механизмов - операционный контекст, определяющий OPSEC на внутреннем пентесте.

Mimicry-атаки. Если IDS опирается на byte_ratio, атакующий добавляет padding в C2-ответы, выравнивая соотношение до нормального (~1:1). SHAP-профиль такого трафика становится неотличим от легитимного HTTPS. На внутреннем пентесте это делается настройкой junk-данных в профиле C2-фреймворка - Cobalt Strike malleable profiles или Sliver HTTP C2 config.

Медленное сканирование. Фича «количество уникальных dst_port за 60с» не сработает, если атакующий проверяет один порт в минуту. Расширение окна до 1 часа поможет - но создаст вычислительную нагрузку и задержку детекции, неприемлемую для real-time IDS. Классический trade-off, и идеального решения нет.

Туннелирование через легитимные протоколы. DNS-туннель с энтропией subdomain < 3 бит (короткие словарные имена вместо base64) не будет пойман фичей «энтропия subdomain > 4.5». Protocol Tunneling (T1572, C2) в таком исполнении требует не статистических, а семантических фичей - анализа содержимого DNS-запросов, что выходит за рамки классического feature engineering.

Jittered beaconing. Beacon с jitter > 30% размывает стандартное отклонение IAT до уровня нормального трафика. Детект требует фичей второго порядка: автокорреляция IAT-ряда ловит скрытую периодичность даже при значительном шуме. На практике вычисление автокорреляции для каждого src_ip в реальном времени - инженерно тяжёлая задача, и мало кто её тянет.

Traffic Signaling (T1205, C2). Атакующий использует специфические комбинации TCP-флагов или значения TTL как сигналы для активации backdoor. Статистические фичи не детектят единичные пакеты-триггеры - они «растворяются» в окне агрегации. Тут нужен другой подход - rule-based детект на уровне отдельных пакетов, а не ML.

Понимание этих ограничений критично с обеих сторон: blue team видит, где нужно усилить детекцию; пентестер понимает, какие фичи IDS отслеживает и как выстроить коммуникацию с C2, не триггерящую пороговые значения. На внутреннем пентесте в modern-инфраструктуре с ML-based IDS (Darktrace, Vectra AI) знание конкретных фичей - разница между пойманным beacon и незамеченным каналом.

Заключение​

Три года я строю пайплайны обнаружения аномалий в сетевом трафике, и главный вывод неутешителен: индустрия переинвестирует в алгоритмы и недоинвестирует в фичи. На конференциях обсуждают Transformer-based IDS и graph neural networks для обнаружения lateral movement. При этом базовый набор фичей у большинства команд - сырой conn.log из Zeek без единого производного признака. Менять Random Forest на Transformer при плохих фичах - это ставить спортивный выхлоп на машину с пробитым колесом.

Прирост от правильно сконструированных признаков на порядок больше прироста от смены алгоритма, и этот эффект воспроизводится на каждом датасете, с которым я работал. Второй неудобный факт: feature engineering для ML-моделей обнаружения вторжений нельзя полностью автоматизировать. AutoML подбирает pipeline, но не понимает, почему высокая энтропия dst_port за 60 секунд - это сканирование, а не CDN-балансировка. Доменная экспертиза - понимание, что стоит за числом в реальном трафике - остаётся ручной работой, и именно она разделяет IDS с precision 0.70 и IDS с precision 0.95.

Если хочется на практике разобрать pcap и понять, какой трафик аномальный, без готовых правил и подсказок - на HackerLab.pro в сетевых задачах построены как раз такие сценарии.
 
Последнее редактирование модератором:
  • Нравится
Реакции: turexxoogmailcom
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab