Разработка и анализ эффективности средств отражения распределенных атак

Модели нарушителей глобальной информационной системы Интернет. Классификация угроз в соответствии с IT-Baseline Protection Manual. Реализация DoS/DDos атак. Программная реализация Snort: установка, препроцессоры и структура модулей обнаружения и вывода.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 05.06.2011
Размер файла 509,5 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Покажем, что поток требований является ординарным. Рассмотрим сервер с одним сетевым интерфейсом. По такому подключению одновременно не могут прийти сразу несколько IP пакетов, т.к. в блоке данных протоколов канального уровня (Ethernet, DSL-соединение, модемное подключение и др.) может быть максимум один IP пакет [18]. Соответственно, существует некоторый малый промежуток времени, в течение которого может поступить не более одной заявки. Следовательно, для сервера с одним сетевым интерфейсом входной поток TCP SYN пакетов является ординарным.

Таким образом, поток заявок, содержащих TCP SYN пакеты, поступающие на сервер с одним сетевым интерфейсом, обладает свойствами стационарности, ординарности и отсутствия последствия, и в соответствии с определением, такой поток является пуассоновским.

3.3 Сервер TCP соединения как СМО

Как было показано в п.3.2, поток поступающих на сервер TCP SYN пакетов в заданных условиях является пуассоновским. Это значит, что его можно рассматривать как поток требований, поступающих в СМО. Однако для построения модели удобнее в качестве множества заявок рассматривать эквивалентный ему поток. В нормальном режиме работы в ответ на каждый полученный TCP SYN пакет сервер должен отправить TCP SYN+ACK пакет[10]. Из того, что существует взаимнооднозначное соответствие между входящими и исходящими пакетами следует эквивалентность потоков. Далее в качестве требований СМО будем рассматривать отправляемые сервером SYN+ACK пакеты. Множеством обслуживающих приборов будем считать ресурсы сервера, предназначенные для хранения параметров TCP соединений. В такой интерпретации обслуживание требования - это резервирование соответствующих ресурсов либо до успешного установления TCP соединения (получения ACK пакета, который должен быть получен в соответствии с [10]), либо до истечения отведенного на сервере таймаута.

Для такой модели признаком TCP SYN атаки является резкое увеличение количества заявок в СМО. Находясь под воздействием атаки, сервер выделяет соответствующие ресурсы, которые остаются занятыми в течение отведенного таймаута. Для современных операционных систем и сетевых технологий времени таймаута (от десятков секунд до нескольких минут [12]) достаточно чтобы занять все доступные ресурсы сервера, предназначенные для хранения параметров TCP соединений. Для рассматриваемой нами модели это означает резкое увеличение занятых обслуживающих приборов.

Рассмотрим более детально ресурсы сервера, выступающие в качестве обслуживающих приборов. Параметры TCP соединений хранятся в соответствующем буфере [18], который можно представить в виде массива размерности L, элементы которого хранят параметры TCP соединений. Их можно разделить на три типа: содержащие параметры установленных соединений, полуоткрытых соединений и свободные. Пусть B - количество открытых в данный момент TCP соединений. Тогда n = L - B - количество элементов второго и третьего типов, совокупность которых мы будем рассматривать в качестве множества обслуживающих приборов СМО. При этом занятые обслуживанием требований приборы - это элементы второго типа. На рис. 3.1 изображен описанный массив, а на рис. 3.2 показано представление ресурсов сервера в качестве множества обслуживающих приборов.

Рис. 3.2 Сервер TCP соединения как СМО

В зависимости от соотношения интенсивности входящего потока требований и размерности массива L можно рассматривать два типа СМО. Если интенсивность входящего потока заявок значительно меньше возможностей сервера, что справедливо для большинства современных систем, то целесообразно рассматривать СМО с бесконечным числом обслуживающих приборов. В противном случае можно рассматривать СМО с отказами. Ввиду того, что на практике в нормальном режиме работы возможности сервера со значительным запасом покрывают входящие требования, то рассмотрение системы с отказами является неактуальным. В дальнейшем будем рассматривать систему первого типа.

3.4 СМО с бесконечным количеством обслуживающих приборов

Как уже было показано, для описания модели взаимодействия клиентов и сервера TCP соединения в нормальном режиме работы целесообразно рассматривать СМО с бесконечным числом обслуживающих приборов. Обозначим отношение интенсивности входящего потока требований к среднему времени обслуживания заявки коэффициентом . Т.к. поток требований является пуассоновским, то вероятность того, что в системе находится ровно k требований, определяется как

(3.3)

Подставив это значение в соотношение (3.2), описывающее среднее число приборов, занятых обслуживанием (общее число полуоткрытых соединений) получим:

(3.4)

Соответственно,

(3.5)

Из соотношений (3.4) и (3.5) для СМО с бесконечным числом обслуживающих приборов имеем [16]:

(3.6)

Предложенная модель описывает работу сервера в нормальном режиме и позволяет учитывать такие параметры, как интенсивность обращений к серверу и среднее время обслуживания заявки. Однако такая СМО недостаточно полно описывает работу сервера, т.к. не учитывает возможность потери пакетов при передаче в современных сетях.

Для усовершенствования предложенной модели целесообразно разделить рассматриваемую СМО на две системы, обслуживающие заявки на нормальное установление соединения (когда все пакеты доставлены) и полуоткрытые соединения, удаляемые по таймауту. Для разделения исходного потока требований на множества заявок для каждой из систем необходимо ввести критерий, позволяющий определить принадлежность заявок к вышеописанным типам. Для этого в дальнейшем будет использован тот факт, что в большинстве случаев время прохождения IP пакета между произвольными хостами в Internet не превосходит некоторого порогового значения [19]. Определение этого порога рассмотрено в п.4.1.

3.5 Модель, учитывающая потерю пакетов в сети

Как было отмечено выше, предложенная ранее модель требует усреднения среднего времени обслуживания по всем требованиям, что не в полной мере учитывает особенности процесса установления TCP соединений. Для устранения этого недостатка разделим описанную в п.3.3 СМО на две системы: СМО1 и СМО2. Будем считать, что первая система описывает обслуживание заявок, для которых полуоткрытые соединения будут успешно установлены после получения сервером ACK пакетов, а вторая - требования, для которых соединения не будут установлены и после истечения отведенного таймаута будут удалены.

Как будет показано в п.4.1, в большинстве случаев время обмена парой пакетов между произвольными хостами не превосходит порог . При условии того, что на клиенте корректно реализован протокол TCP, появление полуоткрытых соединений, которые не установленных в течение промежутка времени длительностью объясняется потерей либо SYN+ACK, либо ACK пакета. Поэтому к требованиям второго типа будем относить заявки, для которых TCP соединение находится в полуоткрытом состоянии дольше чем . Обозначим через s и l - количества соединений первого и второго типов соответственно. Такое представление сервера изображено на рис.3.4

Рис 3.4. Сервер TCP соединения, как СМО

Определим соотношения, описывающие состояние такой системы. Аналогично (3.6) определим среднее количество полуоткрытых соединений:

. (3.7)

Как следует из соотношения (3.7), среднее число полуоткрытых соединений является случайной величиной, равной сумме двух случайных величин, имеющих пуассоновский закон распределения. Первая из них описывает среднее количество полуоткрытых соединений, которые не представляют собой угрозу с точки зрения TCP SYN атаки. Вторая составляющая представляет собой полуоткрытые соединения, которые не будут установлены и через заданный промежуток времени (определяемый таймаутом) будут удалены, до этого занимая ресурсы сервера. Как отмечалось выше, увеличение количества таких соединений является признаком TCP SYN атаки. Поэтому в основу методики целесообразно положить СМО, учитывающую только требования второго типа.

Далее будем рассматривать в качестве заявки не все SYN+ACK пакеты, для которых сервер ожидает ответный ACK пакет, а только те, для которых время ожидания превышает пороговое значение , описанное в п.3.5. Очевидно, что при нормальной работе (отсутствии TCP SYN атаки) для каждой такой заявки был потерян либо SYN+ACK, либо ACK пакет. Интенсивность поступления таких заявок определяется следующим соотношением:

(3.8)

где:

- интенсивность поступающих на вход сетевой карты сервера TCP SYN пакетов

- вероятность появления полуоткрытого соединения, которое не будет установлено

Параметр зависит от качества работы сети, которое характеризуется вероятностью потери пакета в сети (). Методика определения фактического значения этой вероятности описана в [20]. Найдем зависимость от . Пусть событие A заключается в том, что был потерян SYN+ACK пакет, а событие B представляет собой потерю ACK пакета. Вероятность события A равна вероятности потери пакета в сети:

(3.9)

Т.к. событие B может наступить только тогда, когда не наступило событие A (ACK пакет может быть отправлен только после получения SYN+ACK пакета[10]), то его вероятность равна:

(3.10)

Рассмотрим событие C, заключающееся в появление полуоткрытого соединения второго типа. Оно равно сумме событий A и B. Отсюда с учетом (3.9) и (3.10) получим:

(3.11)

Из соотношений (3.8) и (3.11) найдем интенсивность потока требований второго типа:

(3.12)

В современных ОС таких как Windows и Linux, ядро отсылает несколько копий SYN+ACK пакетов до тех пор, пока не будет получен ACK

пакет. Обозначим количество таких копий параметром . Тогда интересующее нас событие заключается в том, что ни для одной из копий SYN + ACK пакета не дойдет ответный ACK пакет, и соотношение (3.12) принимает следующий вид:

(3.13)

Т.к. интенсивность потока требований второго типа пропорциональна интенсивности первоначального потока, то он так же является пуассоновским.

Среднее число таких заявок, находящихся на обслуживании в СМО, определяется вторым слагаемым формулы(3.7):

(3.14)

где: - таймаут отведенный на сервере на установление TCP соединения

- вероятность потери пакета в сети

- количество копий SYN + ACK пакетов отправляемых ОС

Как было показано в п.3.4, СВ характеризующая среднее количество занятых приборов в СМО рассматриваемого нами типа пуассоновский закон распределения. В нашем случае параметр этого распределения равен l. Известно, что для пуассоновского распределения математическое ожидание и дисперсия равны параметру распределения [21] и в нашем случае так же равны l.

На рисунках 3.4 и 3.5 приведены графики плотности распределения и закона распределения случайной величины, распределенной по пуассоновскому закону, с параметром .

Для определения наличия или отсутствия TCP SYN атаки нам понадобится значение функции распределения, которое, как известно, определяется следующим образом:

(3.15)

При использовании данной модели, признаком TCP SYN атаки является превышение значения функции распределения от текущего количества полуоткрытых соединений некоторого порогового значения Fпор (рис. 3.5), которое будет соответствовать вероятности верного обнаружения TCP SYN атаки (вероятности ошибки первого рода).

Достоинствами предлагаемой методики являются возможность своевременного (раннего) обнаружения атаки, ее способность адаптироваться к реальным параметрам сети. При значительном увеличении интенсивности обращений к серверу со стороны легальных пользователей количество потерянных пакетов увеличится пропорционально вероятности потери пакета в сети. Т.к. для современных сетей эта величина имеет небольшое значение, то эффективность обнаружения снизится незначительно. Недостатком является то, что неисправности сетевого оборудования, в результате которых увеличивается вероятность потери пакета в сети, будут интерпретированы как TCP SYN атака.

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

4. МЕТОДИКИ СБОРА ДАННЫХ

Для эффективного использования предложенной выше методики на практике необходимо иметь возможность определить фактические значения исходных параметров модели для системы находящейся в нормальном состоянии (при условии отсутствия атаки). Как было показано выше, такими параметрами являются: интенсивность потока заявок (TCP пакетов с установленным SYN флагом), вероятность потери пакетов в сети, к которой подключен сервер и среднее время обслуживания заявки (успешного установления TCP соединения). В этом разделе приведены возможные подходы к решению этой задачи. Более подробно этот материал изложен в [22].

4.1 Определение времени прохождения IP пакета по сети Internet

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

В обоих случаях нам необходима большая статистика времени прохождения пакетов, наиболее полно представляющая генеральную совокупность. Для ее получения была использована утилита ping.

Известно, что эта утилита предназначена для проверки качества соединения с удаленным компьютером. Утилита ping работает поверх протокола ICMP (Internet Control Message Protocol). Для проверки соединения с удаленным хостом утилита ping посылает ему ICMP-request, в ответ на который, удаленный хост должен ответить сообщением ICMP-reply.

Утилита ping позволяет получить статистику для заданного хоста. Среди прочих данных этой статистики можно определить время прохождения каждой пары пакетов с сообщениями ICMP-request и ICMP-reply между двумя хостами. Именно этот параметр нас и интересует - время за которое два удаленных хоста обмениваются парой пакетов (в нашем случае это TCP SYN+ACK и TCP ACK пакеты).

Для накопления ping статистики были использованы различные удаленные хосты, физически расположенные в разных странах и на разных континентах. Исходя из этого, можно утверждать, что полученные результаты достаточно обобщены.

Полученные результаты приведены на рисунках 4.1 - 4.3.

Рис. 4.1. Время возврата пакетов ICMP-reply

На рис. 4.1 и 4.2 приведена упорядоченная по возрастанию статистика времени возврата ICMP-reply. На рис. 4.2 статистика приведена без учета трех пакетов, время возврата которых в 40 раз превышает время возврата большинства пакетов. Рис. 4.2 приведен здесь для представления результатов в более крупном масштабе.

Рис. 4.2. Время возврата пакетов ICMP-reply

Рис. 4.3 Эмпирическое распределение времени возврата ICMP ответа.

На рис. 4.3 изображено эмпирическое распределение времени возврата ICMP ответов. По оси абсцисс отложены временные интервалы, полученные разбиением всего диапазона значений с шагом 10 мс. По оси ординат отложено количество значений, попавших в интервал.

Глядя на рис. 4.3, можно выдвинуть гипотезу о том, что распределение интересующей нас СВ представляет композицию нескольких распределений с различными параметрами. Определение этих законов и их параметров является перспективой развития полученной методики.

На данном этапе для определения порогового значения воспользуемся более простым методом. Проанализировав полученные эмпирические данные можно убедиться в том, что более чем в 98% случаев время прохождения пары пакетов от одного хоста к другому и обратно через сеть Internet не превышает 200 мс.

4.2 Определение вероятности потери пакетов

Для определения вероятности потери пакетов в сети, так же можно воспользоваться утилитой ping, описанной в предыдущем разделе. Ее значение равно отношению количества пакетов с истекшим таймаутом ожидания к общему количеству отправленных ICMP запросов.

При анализе экспериментальных данных, полученных в предыдущем разделе было получено следующее значение:

Список пингуемых хостов был получен путем обработки html страницы, сгенерированной proxy сервером. Эта страница представляет собой месячный отчет о доступе автора в internet. В связи с этим ответы на ICMP запросы отправленные на некоторые хосты получены не были. Это объясняется тем, что эти хосты могут находится за межсетевым экраном, фильтрующим пакеты протокола ICMP. Поэтому при определении количества потерянных пакетов учитывались только те хосты, от которых приходил хоть один ICMP ответ.

4.3 Определение интенсивности входящего потока требований

В качестве предложений для определения этого параметра можно выделить:

· Анализ логов какого либо сниффера. Например Ethereal, tcpdump, IDS Snort, работающей в режиме сниффера.

· Написание собственного ПО

Соответствующее ПО разработано моим коллегой [22].

В этом разделе приведены возможные подходы к определению фактических значений исходных параметров рассмотренной выше модели для защищаемой системы находящейся в нормальном состоянии (при условии отсутствия атаки). Как отмечалось выше, такими параметрами являются интенсивность потока заявок (TCP пакетов с установленным SYN флагом), вероятность потери пакетов в сети, к которой подключен сервер и среднее время обслуживания заявки (успешного установления TCP соединения). Имея фактические значения этих параметров с помощью соотношений приведенных в разделе 3 можно определить допустимое пороговое значение для количества "просроченных" полуоткрытых соединений, которое будет использовано ниже.

Одним из важных этапов исследований является программная реализация предлагаемой методики противодействия TCP SYN атаке, особенности которой рассмотрены ниже.

5. ПРОГРАММНАЯ РЕАЛИЗАЦИЯ

Было принято решение реализовать предложенную методику обнаружения TCP SYN атаки в качестве модуля расширения функциональности (plug-in) для системы обнаружения вторжений IDS Snort. В качестве достоинств Snort, которые определили этот выбор можно отметить легко расширяемую архитектуру, открытость исходного кода. Так же стоит упомянуть, что эта система способна работать на большом количестве аппаратных платформ и ОС.

Т.к. в реальности простого обнаружения атаки недостаточно для бесперебойной работы системы, то помимо обнаружения система должна обеспечивать отражение атаки. Поэтому модуль расширения функциональности разрабатывался для модификации системы Snort - IPS Snort_inline. Это система предотвращения вторжений, которая способна модифицировать пакеты в реальном режиме времени, по мере того как они поступают в сеть и/или покидают ее. Такие системы так же называются системами "с активным ответом". Для того, чтобы IPS могла контролировать весь трафик, поступающий и исходящий из сети, она должна располагаться на inline устройстве. Поэтому в предложенной реализации Snort_inline работает на Linux-системе, функционирующей в режиме маршрутизатора.

5.1 Особенности установки Snort

Как было сказано выше, целевая система для разрабатываемого модуля - это Snort_inline. Однако ее установка и настройка занятие, отнимающее много сил и времени. Поэтому на начальных этапах разработка велась на системе Snort, в то время как мой коллега занимался исследованием возможностей snort_inline [22].

Для того чтобы поставить Snort на Linux машину необходимо, предварительно установить некоторые библиотеки:

· libpcap - библиотека работающая на канальном уровне. Используется системой Snort. С помощью нее snort получает доступ ко всем пакетам поступающим на сетевой интерфейс.

· libpcre - библиотека для работы с регулярными выражениями (regular expressions)

· libipq - используется системой Snort_inline вместо библиотеки libpcap. Это библиотека организации очередей пакетов, которую предоставляет IPtables

Для непосредственной установки системы необходимо ввести стандартные команды:

/configure

make

make install

Стоит отметить, что на этапе разработки следует вызвать скрипт ./configure с опцией -enable-debug.

Настройка системы Snort (как и большинства других) дело тонкое, занимающее много времени. Поэтому на начальных этапах разработки было принято решение отлаживать модуль расширения функциональности на системе работающей со значениями практически всех параметров установленными по умолчанию. Единственным переопределяемым параметром был путь к файлу с правилами. Для того чтобы, запустить snort в таком режиме, надо выполнить следующую команду:

/snort -c rules.txt

Это значит, что snort будет проверять все пакеты на соответствие правилам, указанным в файле rules.txt.

5.2 Внутренняя структура Snort

Система Snort имеет гибкую архитектуру, представленную в виде множества подключаемых модулей. Подключаемые модули бывают трех типов:

- препроцессоры

- модули обнаружения

- модули вывода

5.2.1 Препроцессоры

Препроцессоры Snort бывают двух типов. Первый тип предназначен для обнаружения подозрительной активности, а второй тип предназначен для модификации пакетов протоколов высоких уровней (чем канальный) для последующей их обработки процессором обнаружения. Этот процесс называется нормализацией трафика. Он позволяет обнаруживать атаки, которые манипулируют внешним видом трафика для большей скрытности. Существует много препроцессоров snort, которые можно подключить или отключить, внеся соответствующие изменения в файл конфигурации. Исходные коды препроцессоров находятся в директории ./src/preprocessors. Здесь приведены только некоторые из них:

· portscan (2) - предназначен для обнаружения сканирования портов

· http_inspect - предназначен для контроля http трафика

· stream4 - предназначен для контроля за TCP сессиями

· arpspoof - предназначен для обнаружения атак arp-spoofing

· bo - предназначен для обнаружения активности BackOrifice

· frag2 - предназначен для сборки фрагментированных пакетов

· RPC-decode - декодирование RPC-трафика;

· Telnet_decode - декодирование трафика telnet-сессий;

· ASN1_decode - выявление аномалий в строках формата ASN1;

· и т.д.

Открытость архитектуры snort дает возможность разработчикам написать свои препроцессоры, ориентированные на решения специфических задач.

5.2.2 Модули обнаружения

Модули обнаружения используются непосредственно для анализа обработанного препроцессорами трафика. Если этот модуль определяет, что пакет удовлетворяет указанному правилу, то он генерирует событие, которое дальше передается модулям вывода Snort. Именно в виде модуля обнаружения реализована методика обнаружения TCP SYN атаки, поэтому его структура будет подробно описана ниже.

5.2.3 Модули вывода

Модули вывода используются Snort для записи событий безопасности, ведения логов и т.д. в различные устройства и хранилища данных. Возможно настроить систему на ведение логов в отдельную базу данных, двоичные и текстовые файлы различных форматов. Возможны даже такие экзотические варианты, как уведомления администратора по e-mail или SMS. Исходные коды этих модулей находятся в директории ./src/output-plugins Вот некоторые модули вывода:

· alert_syslog - вывод в формате syslog

· log_tcpdump - вывод в формате tcpdump

· output_database - вывод в БД. Возможны mysql, postgresql, oracle, odbc, mssql(только для Snort под Windows)

· csv - вывод в формате CSV ( coma separated values)

· и т.д.

У разработчиков так же есть возможность написания своих модулей вывода, которые благодаря открытости архитектуры легко интегрировать.

5.3 Разработка модуля обнаружения

В корневой директории Snort есть директория templates, в которой находятся шаблоны модулей вывода и обнаружения. Рассмотрим шаблон модуля обнаружения, представленный двумя файлами:

· sp_template.h - заголовочный файл модуля

· sp_template.c - файл реализации модуля

В заголовочном файле должно присутствовать объявление setup функции, которая отвечает за инициализацию модуля. Для того чтобы Snort знал, что необходимо проинициализировать данный модуль необходимо добавить вызов этой функции в функцию InitPlugIns(), реализация которой находится в файле ./src/plugbase.c. При этом, конечно, надо не забыть указать компилятору с помощью директивы #include в каком именно файле она определена.

Применительно к нашему модулю, который называется tcp_syn_flood необходимо сделать следующее:

1. создать в директории ./src/detection-plugins/ два файла:

· sp_tcp_syn_flood.h

· sp_tcp_syn_flood.с

2. в файл sp_tcp_syn_flood.h добавить объявление функции SetupTcpSynFlood(), а в файл sp_tcp_syn_flood.с ее реализацию:

void SetupTcpSynFlood()

{

/* регистрируем модуль */

RegisterPlugin("tcp_syn_flood", TcpSynFloodInit);

DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: TcpSynFlood Setup\n"););

}

Здесь вызывается функция RegisterPlugin, предоставляемая snort, которая говорит snort о том, что если в правиле встречаются опции, относящиеся к модулю tcp_syn_flood, то необходимо вызвать функцию TcpSynFloodInit, находящуюся в файле sp_tcp_syn_floodы.с. Реализация функции инициализации будет описана ниже.

3. добавить вызов функции SetupTcpSynFlood() в plugbase.c:

· В секции /* custom detection plugin */ добавить

#include "detection-plugins/sp_tcp_syn_flood.h"

· В теле функции InitPlugIns() добавить вызов функции SetupTcpSynFlood();

4. добавить элемент PLUGIN_TCP_SYN_FLOOD к перечислению (enum) доступных модулей Snort

Для того чтобы наш модуль был успешно интегрирован в snort осталось реализовать функцию TcpSynFloodInit(). Это статическая функция, в которой необходимо выделить память для используемых модулем структур данных, проинициализировать эти структуры данными, указанными в правиле. Здесь стоит отметить, что для каждого правила, в котором заданы параметры для модуля tcp_syn_flood будет вызвана эта функция.

Здесь так же стоит отметить, что модуль tcp_syn_flood должен генерировать события Snort связанные с началом и окончанием атаки. Для этого его надо зарегистрировать в качестве генератора событий Snort. Сделать это проще простого. Надо добавить соответствующие объявления в файл ./src/generatos.h:

#define GENERATOR_TCP_SYN_FLOOD 224

#define SYNFLOOD_STARTED "(tcp syn flood: PREVED)"

#define SYNFLOOD_FINISHED "(tcp syn flood: PAKA)"

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

Перед тем как продолжить описание реализации модуля на языке C, следует описать внутреннее устройство модуля и используемых в нем структур данных. Модуль tcp_syn_flood предназначен для обнаружения и возможного отражения TCP SYN атаки. Обе эти функциональности представлены отдельными подмодулями: TcpConnEstTimeChecker и TcpSynFloodPreventionModule. Первый из них предназначен именно для обнаружения атаки с помощью описанной разделе 3 методики. Он является решающей системой, которая генерирует события snort говорящие о том, что TCP атака началась или закончилась. Второй подмодуль предназначен для накопления "положительной" статистики работы защищаемого сервера при условии атаки. Под положительно статистикой здесь понимается учет количества успешно установленных TCP соединений сервера с клиентами. Дифференциация клиентов производится по признаку их IP адресов и значения поля TTL в приходящих от них пакетах. Если атака начинается, то накопление статистики приостанавливается, а на основании уже накопленных данных модуль принимает решения от каких клиентов пропускать SYN пакеты к серверу, а от каких нет.

5.3.1 Структура модуля TcpConnEstTimeChecker

Полное название этого модуля Tcp Connection Estimate Time Checker. Он предназначен для определения количества "просроченных" tcp соединений и сравнения их количества с допустимым порогом.

Стоит напомнить, что в соответствии с изложенной в разделе 3 методикой необходимо вести учет количества полуоткрытых TCP соединений, которые находятся в этом состоянии дольше определенного промежутка времени. Значения указанных параметров этот модуль берет из правила Snort:

· server_timeout_sec - таймаут отведенный на сервере для установки TCP соединений. Значение этого параметра задается в секундах

· max_overdue_count - максимально допустимое количество полуоткрытых на сервере соединений

· max_overdue_count_diviation - разброс максимально допустимого количества полуоткрытых на сервере соединений. Это значит, что модуль будет генерировать событие "TCP SYN атака началась" после того, как на сервере будет (max_overdue_count + max_overdue_count_diviation) полуоткрытых соединений и, соответственно "TCP SYN атака закончилась", когда количество таких соединений станет меньше чем (max_overdue_count -max_overdue_count_diviation)

· overdue_time_sec - время после которого полуоткрытое соединение считается "просроченным". Значение этого параметра задается в секундах

· check_period_sec - период с которым модуль должен проверять текущее количество полуоткрытых соединений. Как будет показано дальше, операция проверки количества просроченных соединений требует больше вычислительных ресурсов, чем просто обработка пакетов. Если этому параметру установить довольно большое значение, то атака будет обнаружена позже, а если маленькое значение, то больше ресурсов системы будет расходоваться на более частые проверки.

Для того чтобы минимизировать затраты памяти и увеличить быстродействие было принято решение не хранить время прихода пакетов в явном виде. Для определения "возраста" полуоткрытых соединений используется довольно хитрая структура данных: массив бинарных деревьев. Такой массив показан на рис.5.1.

Рисунок 5.1 Массив бинарных деревьев, используемый TcpConnEstTimeChecker.

В узлах каждого из деревьев хранится информация об отдельном полуоткрытом TCP соединении. Эта информация представлена следующей структурой:

typedef struct _TimeCheckerTreeNodeData

{

ubi_trNode Node;

// Номер acknowledgement последовательности (для Syn+Ack и Ack пакетов)

u_int32_t SeqAckNumber;

}

TChTreeNodeData;

Для более тесной интеграции со Snort была использована готовая реализация бинарных деревьев, поставляемая с системой. Эта реализация так же используется другими модулями. Это позволило значительно сократить время разработки модуля, повысить эффективность его реализации и уменьшить количество возможных багов. Более того, в случае если в этой реализации деревьев имеются баги, то использующий их модуль автоматически подхватит исправления, если будет установлен на более поздние версии Snort. В Snort есть несколько реализаций бинарных деревьев: ubi_BeenTree и ubi_SplayTree. Они приведены к единому интерфейсу, который позволяет работать с ними независимо от текущей реализации. То какие деревья используются указывается лишь включением соответствующего заголовочного файла. В данный момент использованы Splay деревья. В дальнейшем возможно сравнение производительности системы, основанной на другой реализации.

Как видно из приведенного фрагмента кода в структуре объявлены два поля:

· Node - узел бинарного дерева. Это поле должно идти первым в объявлении структуры. Это обусловлено оптимизацией во внутренней реализацией бинарных деревьев Snort

· SeqAckNumber - значение последовательности Acknowledgement в SYN+ACK пакетах исходящих от защищаемого сервера.

При получении данным модулем SYN+ACK пакета исходящего от защищаемого сервера в дерево, имеющее нулевое смещение в массиве помещается соответствующий элемент. Этот элемент соответствует полуоткрытому на сервере соединению.

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

Размерность массива деревьев определяется при инициализации модуля в функции InitTcpConnEstTimeChecker как:

int rootNodesCount = ceil(serverTimeout / _checkPeriod);

При такой организации внутренних структур данных "возраст" полуоткрытых соединений, которым соответствуют узлы в i-м дереве массива определяется как (_checkPeriod * i) . Узлы самого правого в массиве дерева, которые при сдвиге удаляются соответствуют полуоткрытым на защищаемом сервере соединениям для которых истек таймаут отведенный на установку соединений и они закрываются автоматически.

При получении модулем ACK пакета, предназначенного серверу, производится поиск узла дерева, соответствующего полуоткрытому соединению. Поиск производится по ключу (Acknowledge number ACK пакета - 1). После того как узел найден, он удаляется из дерева, что соответствует закрытию полуоткрытого соединения на сервере.

Как было показано в разделе 3, основным критерием по которому принимается решение о начале или окончании атаки, это количество "просроченных" полуоткрытых соединений. В терминах вышеизложенных структур данных это количество элементов в деревьях, индексы которых больше определенного граничного значения, определяемого так же в функции инициализации модуля InitTcpConnEstTimeChecker:

// the index of the first node with overdued connections

checker->firstOverduedNodeIndex = checker->overdueTime / checker->checkPeriod;

Так же стоит отметить, что модуле реализована обработка RST пакетов приходящих как от защищаемого сервера, так и от клиента.

Описанный выше модуль в программной реализации представлен в виде следующей структуры и функций работы с ним:

typedef struct _TcpConnEstTimeChecker

{

/*** Опции правила ***/

// time in seconds after which the half-open connection is overdue

int overdueTime;

// period in seconds to check the number of overdue half-open connections

int checkPeriod;

// the max allowed number of half-open connections

int overdueUpperBound;

// the diviation of overdueUpperBound

int overdueUpperBoundDiviation;

/*** Внутренние данные ***/

// the number of root nodes in the array

int rootNodesCount;

// the array of root nodes

ubi_btRoot* rootNodes;

// the index of the first node, which contains overdued connections

int firstOverduedNodeIndex;

// time when the last shift was made

time_t lastShiftTime;

// Indicates if Syn Flood atack presents

int atackState;

}

TcpConnEstTimeChecker;

/***Интерфейс***/

void InitTcpConnEstTimeChecker(TcpConnEstTimeChecker* checker, int _overdueTime,

int _checkPeriod, int _overdueUpperBound, int _overdueUpperBoundDiviation,

int _serverTimeout);

void DeInitTcpConnEstTimeChecker(TcpConnEstTimeChecker* checker);

int TcpConnEstTimeChecker_ProcessPacket(TcpConnEstTimeChecker* checker, Packet* p, int packetType);

int ShiftRootNodes(TcpConnEstTimeChecker* checker, int GenerationCount);

5.3.2 Структура модуля TcpSynFloodPreventionModule

Как упоминалось в разделе 2, на данный момент общедоступные методы противодействия TCP SYN атаке не отличаются эффективностью и обоснованностью выбора значений конкретных параметров при настройке системы. Т.к. на данный момент авторами не разработана модель, позволяющая построить математически обоснованную методику противодействия атаке, то было принято решение реализовать эту функциональность без соответствующей базы. При этом одним из требований к разработке является возможность работы с модулем посредством определенного интерфейса, не зависящего от конкретной реализации. Такое требование в дальнейшем позволит легко подключать различные (более эффективные) реализации. В объектно-ориентированных языках такой подход обычно реализуется соответствующими механизмами (наследование, интерфейсы и т.д.), однако язык С, на котором написан сам Snort таких возможностей не предоставляет. Поэтому приведение к единому интерфейсу реализовано по аналогии с бинарными деревьями Snort, в виде макроопределений, которые используются для работы с модулем. Такой подход затрудняет разработку и отладку приложения, но приводит к большему быстродействию конечного продукта.

Для реализации этого интерфейса модули предотвращения должны реализовывать три функции:

· Функция инициализации модуля. Предназначена для выделения памяти под внутренние структуры данных и их инициализацию

· Функция деинициализации модуля. Предназначена для освобождения памяти, выделенной под внутренние структуры данных

· Функция обработки пакета. В конкретной реализации эта функция при условии отсутствия TCP SYN атаки занимается ведением положительной статистики. В условиях присутствия атаки обновление статистики приостанавливается, а данная функция принимает решение о том пропускать ли этот пакет дальше или нет.

В текущей реализации статистика "положительных клиентов" ведется по учету количества успешно установленных TCP соединений с конкретного IP адреса, от которого пакеты приходят с определенным значением TTL. Учет значения TTL затрудняет возможному злоумышленнику имитацию "положительного" клиента. Например, злоумышленник знает, что у администратора системы определенный IP. В этом случае для введения системы предотвращения атаки в заблуждения он может генерировать множество TCP SYN пакетов, указывая в качестве адреса отправителя известный ему IP адрес. Если же система так же учитывает значение TTL, то злоумышленнику для успешной имитации так же необходимо знать количество маршрутизаторов находящихся между защищаемым сервером и машиной администратора.

Реализация этого модуля так же основана на использовании бинарных деревьев Snort. Внутренняя структура данных модуля имеет вид:

интернет атака программный snort

typedef struct _TcpSynFloodPreventionModule

{

// корень дерева со статистикой

ubi_btRootPtr rootStat;

long totalPacketsCount;

} TcpSynFloodPreventionModule;

Как видно из объявления структуры вся статистика хранится в одном дереве. Кроме того хранится общее количество обработанных модулем ACK пакетов. Оно используется при определении того, пропускать ли пакет или нет.

Следующая структура представляет собой данные, которые хранятся в узлах дерева:

typedef struct _TcpSynFloodPreventionStatTreeNodeData

{

// узел дерева

ubi_trNode Node;

// Поля идентифицирующие клиента

u_int8_t ttl;

struct in_addr ipSrc;

// Количество пакетов удовлетворяющих условию. TTL=ttl and IPSrc=ipSrc

long counter;

} TcpSynFloodPreventionStatTreeNodeData;

Эта структура содержит следующие поля:

· Node - структура представляющая узел бинарного дерева Snort. Это поле должно быть первым в объявлении, т.к. это обусловлено оптимизацией во внутренней реализации деревьев.

· ttl - значение TTL для узла

· ipSrc - значение IP адреса клиента

· counter - количество обработанных ACK пакетов, пришедших о клиента с IP адресом ipSrc и значением TTL=ttl.

При такой организации внутренних структур данных решение о том, стоит ли пропускать пакет в случае присутствия атаки, принимается исходя из следующего соотношения:

currNodeData->counter > (module->totalPacketsCount / ubi_trCount(module->rootStat));

5.3.3 Взаимодействие TcpConnEstTimeChecker и TcpSynFloodPreventionModule в реализации tcp_syn_flood

Для дальнейшего описания реализации следует привести структуру, в которой хранится внутреннее состояние tcp_syn_flood:

typedef struct _TcpSynFloodData

{

// текущий режим работы

int workingMode;

// IP адрес защищаемого сервера

struct in_addr serverIP;

// указатель на модуль TcpConnEstTimeChecker

TcpConnEstTimeChecker* timeChecker;

// указатель на модуль TcpSynFloodPreventionModulePtr

TcpSynFloodPreventionModulePtr preventionModule;

} TcpSynFloodData;

Как видно из объявления кроме знакомых нам TcpConnEstTimeChecker и TcpSynFloodPreventionModulePtr здесь присутствует переменная workingMode, которая хранит текущее состояние. Она может принимать следующие значения, определенные в файле sp_tcp_syn_flood.h:

/*** Режимы работы модуля ***/

#define TCP_SYN_FLOOD_DETECTION1

#define TCP_SYN_FLOOD_PREVENTION2

Очевидно, что работа каждого из модулей начинается с инициализации, которая происходит при инициализации tcp_syn_flood. Как было показано выше, за инициализацию модуля отвечает функция TcpSynFloodInit. Внутри нее происходит вызов функции TcpSynFloodRuleParseFunction, которая производит анализ параметров, указанных в правиле. Считается, что во время запуска Snort TCP SYN атака отсутствует и переменной workingMode присваивается значение TCP_SYN_FLOOD_DETECTION.

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

/*** Поддерживаемые типы пакетов ***/

#define PACKET_TYPE_UNSUPPORTED 0

#define PACKET_TYPE_SYN_ACK 1

#define PACKET_TYPE_ACK 2

#define PACKET_TYPE_RST_FROM_SERVER 3

#define PACKET_TYPE_RST_FROM_CLIENT 4

#define PACKET_TYPE_SYN 5

Как видно из приведенного выше фрагмента на внутреннее состояние модуля влияют пришедшие от клиента пакеты с установленными комбинациями флагов SYN, ACK и RST, а от защищаемого сервера - SYN+ACK и RST. Различия между RST пакетами введены для того, чтобы корректно уменьшать количество полуоткрытых соединений. Следующий фрагмент кода демонстрирует это:

switch(packetType){

case PACKET_TYPE_ACK:

findNodeData->SeqAckNumber = p->tcph->th_ack-1;

break;

case PACKET_TYPE_RST_FROM_SERVER:

findNodeData->SeqAckNumber = p->tcph->th_ack-1;

break;

case PACKET_TYPE_SYN_ACK:

findNodeData->SeqAckNumber = p->tcph->th_seq-1;

break;

}

После того, как определен тип пришедшего пакета, он передается в рассмотренный выше модуль TcpConnEstTimeChecker, функция TcpConnEstTimeChecker_ProcessPacket которого сообщает основному модулю о том, есть ли в данный момент атака или нет. Она может вернуть одно из двух следующих значений:

/*** Состояния атаки ***/

#define SYN_ATACK_IS_NOT_PRESENT 1

#define SYN_ATACK_IS_PRESENT 2

Далее идет проверка того, нужно ли сгенерировать какое-нибудь сообщение и изменить текущий режим работы. Это иллюстрируется следующим фрагментом кода:

if(checkerResult == SYN_ATACK_IS_PRESENT){

// Если атака только началась

if(tcpSynFloodData->workingMode == TCP_SYN_FLOOD_DETECTION){

// Генерируем сообщение 'Atack Started'

GenerateSnortEvent(NULL, GENERATOR_TCP_SYN_FLOOD, 0,0,0,3,SYNFLOOD_STARTED);

//изменяем режим

tcpSynFloodData->workingMode = TCP_SYN_FLOOD_PREVENTION;

}

}

else{

// Если атака только закончилась

if(tcpSynFloodData->workingMode == TCP_SYN_FLOOD_PREVENTION){

// генерируем сообщение "ATACK FINISHED"

GenerateSnortEvent(NULL, GENERATOR_TCP_SYN_FLOOD, 0,0,0,3,SYNFLOOD_FINISHED);

//изменяем режим

tcpSynFloodData->workingMode = TCP_SYN_FLOOD_DETECTION;

}

}

После этого идет проверка того, должен ли этот пакет быть обработан модулем предотвращения. Если это ACK пакет, пришедший от клиента, то он должен увеличить значение счетчика в статистике для данного клиента, а если это SYN пакет, то в зависимости от текущего режима работы модуля этот пакет либо будет пропущен, либо удален.

if(preventionResult == PREVENTION_PACKET_IS_BAD){

if(InlineMode()){

InlineDrop();

}

}

Как видно из приведенного фрагмента в случае "плохого" пакета осуществляется проверка того, в каком режиме работает Snort. Если в режиме inline, то доступен метод InlineDrop, который говорит Snort о том, что этот пакет пропускать нельзя. В качестве дальнейшего развития этого модуля возможна реализация активного ответа для Snort работающего в режиме простого обнаружения. В качестве такого активного ответа может быть рассылка серверу и клиенту RST пакетов для закрытия этого соединения.

Как отмечалось выше, исходные значения параметров для модуля задаются администратором в виде правила, которое имеет следующий вид:

#tcp_syn_flood:

# [0] - ip_server

# [1] - server_timeout_sec

# [2] - max_overdue_count

# [3] - max_overdue_count_diviation

# [4] - overdue_time_sec

# [5] - check_period_sec

pass tcp any any <> any any (tcp_syn_flood:172.20.24.20, 60, 10, 2, 5, 1;)

Конкретное значение параметра max_overdue_count можно определить с помощью соотношения (3.14) . Для этого сначала с помощью специальных утилит [22] необходимо найти значения интенсивности входящего потока и вероятности потери пакетов в сети.

Рассмотрим пример, когда интенсивность обращений к серверу л равна 1000 заявок в секунду, вероятность потери пакетов в сети Pпп 0.01, значение 1/м (отведенный на сервере таймаут ) примем равным 60 секундам, и количество попыток повторной передачи SYN+ACK пакетов равным 2.


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.