От чего будем защищатся?
От подобных запросов:
78.24.217.120 - - [02/Jun/2010:08:06:00 +0400] "GET / HTTP/1.1" 200 1036 "-" "-"
78.24.217.120 - - [02/Jun/2010:08:06:00 +0400] "GET /index.php HTTP/1.1" 200 1036 "-" "-"
Перво наперво попытаемся выделить адреса наиболее активных ботов.
tail -100 /var/log/nginx-access.log | grep "GET / HTTP/1.1" | cut -f1 -d" "| sort -u
Теперь нужно написать скрипт который бы блокировал выбранные ip на файрволе.
Скрипт написан на перле, авторство не моё, спасибо
orenlab'у.
#!/usr/bin/perl
$num=`cat /media/rules.netstat`;
chomp $num;
$cmd = 'tail -100 /var/log/nginx-access.log | grep "GET / HTTP 1.1" |cut -f1 -d" "|sort -u';
@cmd=`$cmd`;
chomp @cmd;
foreach $each ( @cmd ) {
chomp $each;
$rule=0;
chomp $rule;
open( DB, "/media/niggerz" );
while(<DB>) {
if (/$each/) { $rule=1; break; }
}
close(DB);
unless ( $rule ) {
system("/sbin/ipfw add $num deny ip from $each to me 80" );
open( LOG,">>/media/ddos.pl.log" );
print LOG "banned ip $each as rules $num\n";
close ( LOG );
open( DB,">>/media/niggerz" );
print DB "$each\n";
close(DB);
$num++;
}}
`echo $num > /media/rules.netstat`;
Всё! основной скрипт у нас есть! Теперь сразу после запуска он будет анализировать логи и банить наиболее активные IP, но тут есть небольшая проблемка - если повесить скрипт на крон, то минимальный интервал запуска всего 1 минута! При интенсивной атаке за 1 минуту успеют положить сервер, поэтому нам нужен какой нибудь демон который будет запускать скрипт каждые 5-10 секунд, для этих целей я выбрал php:
Создаём demon.php
<?php
// Created by nick-on
set_time_limit(0);
while ( true )
{
ob_start ();
// Команда на запуск скрипта
system ( "cd /media; perl ddos-http.pl; perl ddos-http-2.pl" );
$content = ob_get_contents ();
$date = date ( "Y.m.d H:i:s", time () );
$output = <<<EOF
--------------------------------------------
Date: {$date}
Output: {$output}
EOF;
$handle = fopen ( "./demon.log", "a+" );
fwrite ( $handle, $output . "\n" );
fclose ( $handle );
// Делаем задержку цикла на 10 секунд
sleep (10);
}
?>
Запускаем demon.php из под крона и ставим его на запуск при перезагрузке системы
/usr/local/bin/php -f /media/demon.php
Но практический опыт показывает что очень часто может случится так что скрипт забанит нормальных пользователей, что в нашем случае это недопустимо, поэтому я решил очищать все правила (а их может набраться очень много) с интервалом в 5-6 часов. А так как у нас постоянно будет запущен demon.php, то через 10 секунд файрвол снова начнёт пополнятся паразитными ip-адресами.
Поэтому пишем clean.sh
# Created by nick-on
/sbin/ipfw -q flush
/sbin/ipfw -q zero
/sbin/ipfw -q resetlog
/sbin/ipfw add 9 allow ip from x.x.0.0\16 to me # разрешаем мою подсеть, вместо x.x.0.0 ставим вашу подсеть.
/sbin/ipfw add 10 allow ip from 78.24.217.120 to me # разрешаем соединения от nginx'a
/sbin/ipfw add 20 allow ip from me to me
/sbin/ipfw add 30 deny ip from any to me dst-port 8080 # блокируем порт на котором работает апач
# очищаем логи
rm /media/niggerz
rm /media/ddos.pl.log
rm /media/demon.log
rm /media/rules.netstat
Ставим задачу в крон на запуск этого скрипта каждые 5-6 часов:
sh /media/clean.sh