Алгоритм выявления сетевых атак двух типов: DDoS и сканирование портов
В результате проведенных исследований нам удалось выявить закономерности, позволяющие на основании NetFlow-данных определить IP-адреса компьютеров, с которых проводятся DDoS-атаки и сканирование портов. На основании этих закономерностей, был разработан алгоритм обнаружения атак. Прежде чем сформулировать данный алгоритм уточним формат записи данных для потока:
· Дата и время начала потока
· Длительность потока (в секундах, с точностью до тысячных)
· Название протокола передачи
· IP-адрес и порт источника
· IP-адрес и порт назначения
· Количество переданных пакетов
· Количество переданных байтов
Разработанный алгоритм обнаружения атак типа DDoS и сканирования портов заключается в следующем:
1. Найти IP-адреса источников, которые генерируют большое количество потоков.
а) Если размер данных потоков очень короткий (44 байт), то происходит сканирование портов;
б) Если размер потоков больше 44 байт, то c данного IP-адреса возможно осуществляется атака типа DoS.
2. Найти IP-адреса источников, которые генерируют очень длинные потоки (длительностью свыше 5 минут). В этом случае на IP-адрес назначение может проводиться DoS-атака.
В случае если одновременно обнаружено множество IP-адресов, с которых производится DoS-атака, то возможно проводится атака типа DDoS.
Для любой сетевой атаки важно своевременное обнаружение для того, чтобы как можно быстрее принять меры по её нейтрализации. NetFlow-данные поступают с маршрутизатора периодически, в зависимости от выставленных нами настроек. В то же время необходим баланс между частотой сбора статистики по потокам и временем, необходимым для ее обработки. Поэтому решено было установить периодичность запроса NetFlow данных один раз в одну минуту.
Следует отметить, что NetFlow-статистика содержит информацию о уже завершившихся потоках. Поскольку поток считается активным в течение определенного времени по его завершению, то подобные завершившиеся потоки также необходимо считать активными.
Листинг скрипта
Скрипт выполняет обработку файлов NetFlow-коллектора nfdump, поступающего с граничного маршрутизатора СГАУ Cisco 6509, после чего формирует список подозрительных IP-адресов, занося их в базу данных MySQL и блокируя на защищаемых серверах при помощи брандмауэра iptables.
Сначала объявляются все необходимые для обработки переменные: массивы записей параметров потоков, учетные данные входа в базу MySQL, папки с файлами nfdump, временные данные. Далее выполняется поиск последнего файла nfdump (папка /var/cache/nfdump/), поступившего с маршрутизатора. Файл nfdump представляет собой данные по всем потокам, завершившимся за последнюю минуту минуту. Этот файл преобразуется из бинарного формата в текстовый и сохраняется в указанную папку на сервере. После этого открывается текстовый файл и построчно записывается в массив (lines). В каждой строке выделяются все параметры потока и записываются в отдельные массивы. Таким образом, под каждый параметр потока отводится отдельный массив, номер элемента которого соответсвует порядковому номеру потока в исходном файле nfdump. Также формируются два массива, содержащих в себе информацию о потоках, завершенных на защищаемых серверах 91.222.128.200 и 91.222.129.201. Эти два массива сортируются по IP-адресам источников для того, чтобы подсчитать число потоков, приходящихся на каждый IP-адрес. Выполняется подсчет числа потоков, и если на один IP-адрес приходится более 300 потоков, то данный адрес заносится в список подозрительных адресов, блокируюется брандмауэром iptables и заносится в базу данных MySQL. В конце блокировка снимается на те адреса, которые были заблокированы больше 5 минут назад. Адреса, которые были заблокированы, сохраняются в файле-отчете, где указывается IP-адрес и число потоков, приходящихся на него.
********************************************************
#!/usr/bin/perl
use 5.8.8; use strict; use warnings; use DBI;
my $hostname = "localhost";
my $database = "admin";
my $user = "admin";
my $password = "Rdhw89pF%lk9D&2";
my $dbh = 0;
my $sth = 0;
my $rc = 0;
my $path = "/var/cache/nfdump/"; #путь к файлам nfcapd.xxxxxxxxxxxx
my $path1 = "/root/DATA/";
#Исходные данные
my @lines = (); #массив строк с исходными данными
my $date = 0; #дата файла
my @time = (); #массив записей времени начала потоков
my @duration = (); #массив записей длительностей потоков
my @protocol = (); #массив записей названий протоколов потоков
my @srcIP = (); #массив записей адресов источников потоков
my @srcPort = (); #массив записей портов источников потоков
my @dstIP = (); #массив записей адресов назначения потоков
my @dstPort = (); #массив записей портов назначения потоков
my @packets = (); #массив записей числа переданных в потоке пакетов
my @bytes = (); #массив записей количества переданных байт в
my $fl = 0; #Число потоков
my $fl2 = 0; # #Число потоков для второго сервера
my @masIP = (); #Массив отсортированных IP-адресов
my @masIP2 = (); # #Массив отсортированных IP-адресов для второго сервера
my @masIPstream = (); #Массив отсортированных IP-адресов stream
my $count = 0; #Счетчик числа потоков
#Вторичные данные
my @mIP = ();
my @mIP2 = (); #
#Временные данные
my $i = 0;
###############
#поиск последнего файла
chdir $path;
my (@file_list) = glob "nfcapd.20*";
my $flowfile = 0;
$flowfile = $file_list[$#file_list];
##############################
#преобразование из формата nfdump в txt и копирование в директорию $path1
my $comand = 0;
$comand = "nfdump -r ".$path.$flowfile." >> ".$path1.$flowfile.".txt";
system $comand;
#$comand = "nfdump -r ".$path.$flowfile." >> /var/www/galcev/data/".$flowfile.".txt";
#system $comand;
$comand = "rm -f ".$path.$flowfile;
system $comand;
open(FileData,$path1.$flowfile.".txt"); #открытие файла с исходными данными
@lines = <FileData>; #запись в массив строк с исходными данными
close(FileData); #закрытие файла с исходными данными
for ($i = 1; $i < @lines-4; $i++) { #заполнение массивов исходных данных
if( $lines[$i] =~ m/\d+\:\d+\:\d+\.\d+/g ){ #поиск в строке времени
$time[$fl]=substr($lines[$i],pos($lines[$i])-length($&),length($&));
}
if( $lines[$i] =~ m/\d+\.\d+/g ){ #поиск в строке длительности потока
$duration[$fl]=substr($lines[$i],pos($lines[$i])-length($&),length($&));
}
if( $lines[$i] =~ m/\w+/g ){ #поиск в строке названия протокола
$protocol[$fl]=substr($lines[$i],pos($lines[$i])-length($&),length($&));
}
if( $lines[$i] =~ m/\d+\.\d+\.\d+\.\d+/g ){ #поиск в строке IP-адреса источника пакета
$srcIP[$fl]=substr($lines[$i],pos($lines[$i])-length($&),length($&));
}
if( $lines[$i] =~ m/\:\d+/g ){ #поиск в строке порта источника пакета
$srcPort[$fl]=substr($lines[$i],pos($lines[$i])-length($&)+1,length($&));
}
if( $lines[$i] =~ m/\d+\.\d+\.\d+\.\d+/g ){ #поиск в строке IP-адреса назначения
$dstIP[$fl]=substr($lines[$i],pos($lines[$i])-length($&),length($&));
}
if( $lines[$i] =~ m/\:\d+/g ){ #поиск в строке порта назначения
$dstPort[$fl]=substr($lines[$i],pos($lines[$i])-length($&)+1,length($&));
}
if( $lines[$i] =~ m/\d+/g ){ #поиск в строке числа пакетов в потоке
$packets[$fl]=substr($lines[$i],pos($lines[$i])-length($&),length($&));
}
if( $lines[$i] =~ m/\d+\.\d+\s\w+|\d+/g ){ #поиск в строке числа байтов в потоке
$bytes[$fl]=substr($lines[$i],pos($lines[$i])-length($&),length($&));
#ФИЛЬТР ПО АДРЕСУ IP4TV.RU(91.222.128.200) и сервер трансляций (91.222.129.201)
if ($dstIP[$fl] eq "91.222.128.200") {
push(@masIP2 , [$srcIP[$fl],$time[$fl]]);
++($fl2);
}
if ($dstIP[$fl] eq "91.222.129.201") {
push(@masIP , [$srcIP[$fl],$time[$fl]]);
++($fl);
}
}
}
--($fl);
--($fl2);
#СТАТИСТИКА
#массив mIP - сортировка данных по IP-адресу источника
@mIP = sort {
( $a->[0] cmp $b->[0] )
} @masIP;
@mIP2 = sort {
( $a->[0] cmp $b->[0] )
} @masIP2;
#Формирование файла (IP-адрес источника;Число потоков > 300)
$count = 1;
open(IPToBan,">> /var/www/galcev/banIP.txt");
$dbh = DBI->connect("DBI:mysql:$database:$hostname", $user, $password)|| print IPToBan "Got error". $dbh->errstr ."\n";
my $statement = 0;
for ($i = 1; $i < $fl; $i++) {
if ($mIP[$i-1][0] eq $mIP[$i][0]) {++($count);}
else {
if ($count > 300){
my $ipT = $mIP[$i-1][0];
$statement = "select ban('".$ipT."');";
print IPToBan substr($flowfile,13,2),"\.",substr($flowfile,11,2),"\.",substr($flowfile,7,4)," ",$mIP[$i-1][1]," ",$ipT," ",$count,"\n";
$sth = $dbh->prepare($statement);
$sth->execute;
if ($sth == 1){
$comand = "iptables -I fail2ban-galcev -s ".$ipT." -j DROP";
system $comand;
}
}
$count = 1;
}
}
my $ref = 0;
$statement = "SELECT id,INET_NTOA(ip) FROM banlist WHERE time<CURRENT_TIMESTAMP-300;";
$sth = $dbh->prepare($statement);
$sth->execute;
while ($ref = $sth->fetchrow_arrayref) {
$comand = "iptables -D fail2ban-galcev -s ".$$ref[1]." -j DROP";
system $comand;
my $stm = "DELETE FROM banlist WHERE id='".$$ref[0]."';";
$sth = $dbh->prepare($stm);
$sth->execute;
}
$rc = $sth->finish;
$rc = $dbh->disconnect;
close(IPToBan);
###########################################
open(IPToBan2,">> /var/www/galcev/banIP2.txt");
$count = 1;
for ($i = 1; $i < $fl2; $i++) {
if ($mIP2[$i-1][0] eq $mIP2[$i][0]) {++($count);}
else {
if ($count > 0){
print IPToBan2 substr($flowfile,13,2),"\.",substr($flowfile,11,2),"\.",substr($flowfile,7,4)," ",$mIP2[$i-1][1]," ",$mIP2[$i-1][0]," ",$count,"\n";
}
$count = 1;
}
}
close(IPToBan2);
####################################
exit( 0 );
Дата добавления: 2017-03-29; просмотров: 944;