Защита от dns флуда

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

На сервере был установлен Centos 5, панель Kloxo и несколько сайтов. 

Проверил tcpdump -ом и обнаружил что на сервер поступает большое количество dns запросов вида  ANY? . , в количестве 500 в секунду, IP в запросе скорее всего поддельные. Сервер отвечает на каждый такой запрос и посылаетв ответ много информации. При этом top в графе %CPU для named показывал непрерывно примерно 30%.

 Оказалось что bind настроен таким образом что он отвечает на все эти запросы. 

 Решил поступить следующим образом.  Сначала добавил в конфиг bind 

allow-recursion {

127.0.0.1;

xxx.yyy.zzz.aaa; # ip of the server

}

чтобы разрешить рекурсивные запросы серверу только самому себе, а остальным только информацию о зоне.

И добавил логирование для использования fail2ban

logging {
channel default_log {
file "/var/log/named.log";
print-time yes;
};
category default {
default_log;
};
};

После этого bind стал отвергать все эти запросы, отвечая на все "refused". Это снизило %CPU до 7-10%. После этого установил fail2ban и настроил в jail.local named-refused-udp с параметрами 

findtime = 2

maxretry = 10

bantime = 2700 # эти параметры можно изменять для оптимизации.

После этого %CPU для named пришел в норму, т.к. fail2ban блокировал почти весь dns флуд. 

Чтобы лог не занимал много места и не разрастался настроил его ротацию в /etc/logrotate.d/fail2ban

/var/log/fail2ban.log {
missingok
notifempty
compress
delaycompress
rotate 10
size 30k
create 0600 root root
postrotate
/usr/bin/fail2ban-client reload 2> /dev/null || true
endscript
}

и главное в /etc/logrotate.d/named_chroot для ротации лога с запросами к named

/var/named/chroot/var/log/named.log {
missingok
size 50M
compress
rotate 7
create 0644 named named
postrotate
/sbin/service named reload 2> /dev/null > /dev/null || true
endscript
}

Смортю как работает, последние пару дней количество забаненных IP от 30 до 100 штук примерно.

Есть особенность, если отключить fail2ban и включить его снова, то он минут 5-10 может не банить ни одного ip , видимо из-за большого объема вычислений при такой загрузке, т.к, при этом в top %CPU для fail2ban поднимается до 100%. Но после того как начинает банить и в iptables добавляются ip в  цепочки fail2ban, то все становится на свои места. Поэтому предпочтительней для изменения настроек fail2ban на лету производить их, используя fail2ban-client.

Сам принцип блокировки файрволом запросов на основе ip адресов если они поддельные довольно неэффективен. Поэтому поискал альтернативные способы блокировки на основе анализа содержимого пакета.

Нашел интересные описания по этому поводу:

http://isc.sans.edu/diary/DNS+ANY+Request+Cannon+-+Need+More+Packets/132...

http://sf-alpha.bjgang.org/wordpress/2013/01/iptables-for-common-dns-amp...

http://www.topology.org/linux/iptables_dns_flood.html

http://www.stableit.ru/2013/02/iptables-dns.html

Но оказалось что на сервере iptables собран без поддержки u32 , а попытки использовать правила вида 

-p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --name dnsanyquery --rcheck --seconds 60 --hitcount 5 -j DROP

приводят к ошибке iptables: Unknown error 4294967295

Пока остановился на этом, продолжаю разбираться.

Использование iptables recent для ограничения dns any request

По мотивам http://www.topology.org/linux/iptables_dns_flood.html
Обнаружил подобную атаку на один из моих серверов, решил делать с помощью recent в iptables. Для этого добавляем вверху правил iptables :

-A INPUT -d aaa.bbb.ccc.ddd -i eth0 -p udp -m udp --dport 53 -j DNSANYFLOOD

и создаем цепочку DNSANYFLOOD

-A DNSANYFLOOD -d aaa.bbb.ccc.ddd -i eth0 -p udp -m udp --dport 53 -m recent --set --name dnsanyflood --rsource
-A DNSANYFLOOD -d aaa.bbb.ccc.ddd -i eth0 -p udp -m udp --dport 53 -m recent --update --seconds 2 --hitcount 9 --name dnsanyflood --rsource -j DROP
-A DNSANYFLOOD -d aaa.bbb.ccc.ddd -i eth0 -p udp -m udp --dport 53 -m recent --update --seconds 2 --hitcount 10 --name dnsanyflood --rsource -j DROP
-A DNSANYFLOOD -d aaa.bbb.ccc.ddd -i eth0 -p udp -m udp --dport 53 -j RETURN

Т.е. если за 2 секунды будет более 9 запросов к dns, то ip запоминается и отбрасывается. Для моего случая неплохие значения. Подбирать надо эксперементально на основе данных по количеству запросов.
При небольшом dns флуде помогает.

Но еще лучше если использовать этот метод совместно с fail2ban.
Естественно что это лишь разгружает сервер от обработки входящего трафика, т.е. разгружает процессор, но сам входящий трафик никуда не исчезает.
Очистка списка dnsanyflood : echo / > /proc/net/xt_recent/dnsanyflood

Отправить комментарий

CAPTCHA
Чтобы убедиться в том что Вы не робот, ответьте, пожалуйста, на вопрос
Fill in the blank