Для реализации этого интерфейса модули предотвращения должны реализовывать три функции:
· Функция инициализации модуля. Предназначена для выделения памяти под внутренние структуры данных и их инициализацию
· Функция деинициализации модуля. Предназначена для освобождения памяти, выделенной под внутренние структуры данных
· Функция обработки пакета. В конкретной реализации эта функция при условии отсутствия TCPSYN атаки занимается ведением положительной статистики. В условиях присутствия атаки обновление статистики приостанавливается, а данная функция принимает решение о том пропускать ли этот пакет дальше или нет.
В текущей реализации статистика "положительных клиентов" ведется по учету количества успешно установленных TCP соединений с конкретного IP адреса, от которого пакеты приходят с определенным значением TTL. Учет значения TTL затрудняет возможному злоумышленнику имитацию "положительного" клиента. Например, злоумышленник знает, что у администратора системы определенный IP. В этом случае для введения системы предотвращения атаки в заблуждения он может генерировать множество TCPSYN пакетов, указывая в качестве адреса отправителя известный ему IP адрес. Если же система так же учитывает значение TTL, то злоумышленнику для успешной имитации так же необходимо знать количество маршрутизаторов находящихся между защищаемым сервером и машиной администратора.
Реализация этого модуля так же основана на использовании бинарных деревьев Snort. Внутренняя структура данных модуля имеет вид:
интернет атака программный snort
typedefstruct _TcpSynFloodPreventionModule
{
// корень дерева со статистикой
ubi_btRootPtr rootStat;
long totalPacketsCount;
} TcpSynFloodPreventionModule;
Как видно из объявления структуры вся статистика хранится в одном дереве. Кроме того хранится общее количество обработанных модулем ACK пакетов. Оно используется при определении того, пропускать ли пакет или нет.
Следующая структура представляет собой данные, которые хранятся в узлах дерева:
typedef struct _TcpSynFloodPreventionStatTreeNodeData
{
// узелдерева
ubi_trNode Node;
// Поля идентифицирующие клиента
u_int8_tttl;
structin_addripSrc;
// Количество пакетов удовлетворяющих условию. 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:
typedefstruct _TcpSynFloodData
{
// текущий режим работы
intworkingMode;
// 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
#defineTCP_SYN_FLOOD_PREVENTION2
Очевидно, что работа каждого из модулей начинается с инициализации, которая происходит при инициализации tcp_syn_flood. Как было показано выше, за инициализацию модуля отвечает функция TcpSynFloodInit. Внутри нее происходит вызов функции TcpSynFloodRuleParseFunction, которая производит анализ параметров, указанных в правиле. Считается, что во время запуска SnortTCPSYN атака отсутствует и переменной 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
#definePACKET_TYPE_SYN 5
Как видно из приведенного выше фрагмента на внутреннее состояние модуля влияют пришедшие от клиента пакеты с установленными комбинациями флагов SYN, ACK и RST, а от защищаемого сервера – SYN+ACK и RST. Различия между RST пакетами введены для того, чтобы корректно уменьшать количество полуоткрытых соединений. Следующий фрагмент кода демонстрирует это:
switch(packetType){
casePACKET_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.Подставив такие значения в соотношение (3.14) получим:
Т.е. значение параметра max_overdue_count в правиле Snort следует принять равным 24.
Описанная выше программная реализация модуля расширения функциональности для системы предотвращения вторжений Snort_inline может быть использована для защиты критичных ресурсов корпоративной сети. Для этого необходимо создать программно-аппаратный комплекс, представляющий из себя маршрутизатор на базе Linux системы с установленным IPSSnort_inline. Во время разработки модуля акцент делался на независимость от операционной системы, но на данный момент тестирование проводилось только на ОС Linux.
К достоинствам такой реализации можно отнести возможность использовать один комплекс для защиты нескольких серверов, т.к. параметры защиты для конкретного сервера задаются в отдельном правиле Snort, допустимое количество которых ограничено лишь вычислительными возможностями оборудования.
ВЫВОДЫ
На современном этапе развития информационных технологий всё больше проявляется зависимость эффективного функционирования государственных и коммерческих предприятий и организаций от безопасности и надёжности применяемых корпоративных информационно-телекоммуникационных систем. Среди основных требований, предъявляемых к таким системам, можно выделить необходимость обеспечения услуги доступности. В виду того, что одним из самых распространенных видов атак в современных сетях являются атаки типа отказа в обслуживании, которые при успешной реализации способны парализовать работу как отдельных серверов, так и целых сетей, проблема обеспечения доступности ресурсов является чрезвычайно актуальной для общедоступных информационных систем, в частности, сети Internet.