Введение
В рамках одного из исследований при разработке программного обеспечения для анализа сетевого трафика возникла идея проводить классификацию различных сессий пользователя по различным видам его сетевой активности. При этом, следовало ориентироваться только на параметры передаваемых пакетов, без каких-либо апелляций к адресам отправителя и получателя. Из типичных вариантов поведения пользователя были выбраны просмотр видео, прослушивание аудио, серфинг в интернет, загрузка и выгрузка файлов.
Сформулированная гипотеза выглядела так:
"Объемно-временные характеристики пакетов, принадлежащих к различным видам трафика, могут служить для его классификации".
В принципе, достаточно очевидно, что загрузка и выгрузка файлов существенно отличаются объемом трафика в направлении приема и передачи, что прослушивание аудио характерно регулярностью входящих пакетов небольшой длины, а серфинг - хаотичностью порций передаваемых данных. Однако при этом, не очень понятно, как будет реально отличаться трафик просмотра видео от закачки файла, так как и в первом и во втором случае регистрируется большой объем входящего потока данных.
Для того, чтобы проверить применимость статистического подхода для классификации типов трафика по параметрам проходящих пакетов, а также для разработки алгоритма этой классификации было принято решение проверить сформулированную гипотезу в Knime.
Процесс состоял из следующих шагов:
Выбор механизма импорта данных в Knime для его дальнейшего анализа;
Сбор тестовых данных и их ручная маркировка для обеспечения возможности использования алгоритмов машинного обучения;
Выбор параметров пакетов, используемых в качестве отличительных признаков трафика;
Выбор алгоритма и его оптимальных критериев для сортировки трафика;
Проверка и визуализация результатов.
Выбор механизма импорта
Одной из наиболее распространенных программ для анализа сетевого трафика является программа Wireshark. Стандартом формата данных при этом можно считать PCAP. Исходя из этого, а также с ориентацией на встроенную в Knime поддержку языка Python, для ввода данных был установлен пакет ScaPy. В качестве загружаемых данных удобнее всего было использовать PCAP файлы, записанные в программе Wireshark. Входных файлов предполагалось использовать множество, полученных из разных источников. Это привело к реализации следующей цепочки обработки, оформленной в виде отдельного компонента Knime, что удобно для последующего тиражирования (повторного использования) в рамках схемы обработки:
Текст скрипта для компонента Python Source
from scapy.all import rdpcap
from pandas import DataFrame
output_table = DataFrame()
file = flow_variables['pcap']
packets = rdpcap(file)
wire_len = []
payload_len=[]
time = []
fields = []
src = []
dst =[]
sport =[]
dport =[]
proto = []
tcp_flags = []
tcp_seq = []
tcp_ack = []
for L1 in packets:
L2 = L1.payload
if L2.name != "IP": continue
L3 = L2.payload
try:
if not ((L3.name == "TCP") or (L3.name == "UDP")) : continue
except:
continue
wire_len.append(L1.wirelen)
time.append(int(L1.time*1000000))
src.append(L2.src)
dst.append(L2.dst)
sport.append(L3.sport)
dport.append(L3.dport)
proto.append(L3.name)
try:
payload_len.append(len(L3.load))
except:
payload_len.append(0)
if L3.name == "TCP":
tcp_flags.append(str(L3.flags))
tcp_seq.append(str(L3.seq))
tcp_ack.append(str(L3.ack))
else:
tcp_flags.append("")
tcp_seq.append("")
tcp_ack.append("")
output_table["wire_len"] = wire_len
output_table["payload_len"] = payload_len
output_table["time"] = time
output_table["src"] = src
output_table["dst"] = dst
output_table["sport"] = sport
output_table["dport"] = dport
output_table["proto"] = proto
output_table["tcp_flags"] = tcp_flags
output_table["tcp_seq"] = tcp_seq
output_table["tcp_ack"] = tcp_ack
Идея этой схемы обработки заключалась в следующем: мы берем набор PCAP-файлов и последовательно загружаем при помощи ScaPy информацию о всех пакетах, которые там присутствуют, проставляем для каждого пакета маркер принадлежности к файлу-источнику и маркируем тип активности, который производился пользователем при записи этого файла. Далее осуществляем вспомогательные расчеты и преобразования, в том числе определяем "локальный хост", направление потока данных, "известные" порты, преобразуем формат времени UNIX к формату времени Knime. После этого отправляем весь поток дальше, для статистического анализа.
Как ни странно, но автоматическая маркировка локального хоста оказалась нетривиальной задачей. Простого преобладания в записанном трафике конкретного IP адреса, его принадлежности к зарезервированным диапазонам адресов типа 192.168.*.* оказалось недостаточно.
Для протокола TCP, в итоге, выбор локального хоста производился с учетом инициирующих пакетов SYN. Для протокола UDP - по преобладанию использования на стороне локального хоста рандомных портов со значением больше 10000.
Сбор тестовых данных
Для сбора корректного набора исходных данных (репрезентативной выборки) был применен следующий подход:
На различных машинах, подключенных к сети интернет по различным каналам, в разное время производилась при помощи Wireshark запись сеансов работы пользователя в сети интернет. При этом, при помощи обычного браузера производилось обращение к характерным ресурсам:
видео - YouTube, RuTube, Kinopoisk, ivi...
аудио - Yandex Music, TopRadio, RadioPotok, ...
скачивание/выгрузка файлов - Yandex Disk, Google Drive, Mega.nz, ...
серфинг - yandex.ru, google.ru, ...
Для удобства пользования, был реализован интерактивный диалоговый компонент, который позволял выбирать каталог, содержащий собранные PCAP-файлы, выбирать из них требуемые для анализа в рамках соответствующего заранее известного вида сетевой активности пользователя.
Выбор параметров пакетов для анализа
Ранее, мы при помощи ScaPy уже извлекли отдельные параметры каждого пакета, они представлены на рисунке ниже
Для выбранного нами подхода статистического анализа сейчас нам интересны такие параметры, как длина полезной нагрузки протокола TCP и UDP и время прихода пакета, а также направление потока относительно локального хоста. Все остальные поля мы будем игнорировать.
Предположим, что наш статистический анализатор будет выбирать фрагмент потока данных некоторой длины, рассчитывать признаки этого потока и на основании полученных данных производить предсказание вида действий пользователя в текущий момент
На рисунке далее представлена соответствующая схема обработки. С точки зрения узлов Knime эта схема делает буквально следующее:
Сортирует по времени имеющийся набор пакетов;
Разбивает этот набор на фрагменты (периоды) равной длины;
Рассчитывает признаки этих фрагментов на основании пакетов, которые в них входят;
Выбирает равное количество образцов для каждого классифицируемого типа пользовательской активности;
Обрабатывает пропущенные значения.
Для последующего выбора наиболее характерных признаков фрагментов трафика для разных видов пользовательской активности были вычислены:
медианная длина пакета;
интервал между последовательными пакетами;
размер пакетов;
количество пакетов;
количество уникальных внешних хостов;
количество уникальных внутренних портов;
стандартное отклонение размера пакетов;
стандартное отклонение интервала между пакетами.
Значения высчитывались отдельно для каждого типа протокола TCP и UDP в пределах фрагмента, а также с разделением на входящий и исходящий поток.
Формирование фрагментов осуществлялось по принципу "скользящего окна" при помощи узла Knime Window loop Start. Размер фрагмента был подобран экспериментально и его длительность составила 5 секунд. Размер смещения составил 1 секунду.
В итоге, для тестовой проверки было подготовлено 570 фрагментов, содержащих по 114 образцов трафика пяти различных видов пользовательской активности.
Выбор алгоритма и его оптимальных параметров
В качестве тестового алгоритма для проверки значимости отдельных признаков фрагмента трафика для его классификации можно выбрать простое дерево решений. Этот алгоритм элементарно реализуется в любом языке программирования при помощи операторов условного ветвления.
В ходе экспериментов были проверены различные варианты признаков, которые могли бы использоваться для классификации. Так как целью статьи являлось больше описание принципа использования Knime для оперативной проверки гипотезы, приведу здесь лишь один из простейших рабочих вариантов. Он не является оптимальным, его можно далее дорабатывать, но он уже подтверждает базовую гипотезу, что действительно, можно сравнительно точно определять вид активности пользователя путем статистического анализа пакетов во фрагменте записанного трафика.
В составе признаков трафика здесь использованы только размеры входящих и исходящих пакетов протоколов UDP и TCP анализируемого фрагмента.
Knime предоставляет удобные средства работы с деревом решений, а именно - предоставление этого дерева в виде графа с точками выбора и в виде набора правил, которые можно реализовать в программном коде.
Графическое представление дерева решений
Состав правил дерева решений
Примечание - наиболее значимые правила выделены цветом.
Проверка и визуализация результатов
В итоге применения такого дерева решений, обученного на выборке из исходного набора 50/50 (обучающий набор/тестовый набор) был получен следующий результат:
Из матрицы видно, что для выбранного набора исходных данных, при выбранных пропорциях разделения и при выбранных признаках фрагментов мы получаем достаточно точный результат, выше 90%.
Можно по разному трактовать причины ошибок, которые возникают при классификации трафика по статистике пакетов в выбранных фрагментах. В частности, очень редко бывают случаи исключительно однотипного вида активности пользователя. А именно, в ходе простого серфинга в интернет, различная контекстная реклама является причиной вторичных потоков видео, аудио. Просмотр видео в ряде случаев предполагает скачивание на ПЭВМ фрагментов видеоряда в виде файлов (кэширование) и последующий просмотр из локального кэша и т.п. Некоторые из этих ошибок устранимы путем усложнения подхода к статистическому анализу, некоторые нет.
Исследования подобного рода вполне реализуемы средствами Knime и при обладании навыка пользования его инструментарием могут производиться вполне оперативно.