Защита от небольшого DDoS’a

Что имеем: есть сервер (8Гб памяти, Intel(R) Xeon(R) CPU E31220 @ 3.10GHz) FreeBSD 8.4 Release amd64, сайт на php5.2, nginx+apache+mysql.

Перейти полностью на php-fpm не получилось, поэтому пришлось защищаться как есть. Это поможет отразить небольшую syn flood атаку.

Ниже будет приведены выполненные действия для отражения атак.

1) Тюнинг sysctl.

/boot/loader.conf:

kern.ipc.nmbclusters=65535
net.inet.tcp.syncache.hashsize=1024
net.inet.tcp.syncache.bucketlimit=100
net.inet.tcp.tcbhashsize=4096

/etc/sysctl.conf:

vfs.usermount=0
security.bsd.see_other_uids=0
security.bsd.see_other_gids=0
security.bsd.hardlink_check_uid=1
security.bsd.hardlink_check_gid=1
security.bsd.conservative_signals=1
security.bsd.unprivileged_proc_debug=0
security.bsd.unprivileged_read_msgbuf=0
security.bsd.unprivileged_get_quota=0
kern.ipc.somaxconn=32768
kern.ipc.maxsockets=204800
kern.ipc.maxsockbuf=2097152
kern.maxfiles=204800
kern.maxfilesperproc=200000
kern.random.sys.harvest.ethernet=0
kern.random.sys.harvest.interrupt=0
kern.random.sys.harvest.point_to_point=0
net.link.ether.inet.max_age=1200
net.link.ether.inet.log_arp_movements=0
net.local.stream.sendspace=65536
net.local.stream.recvspace=65536
net.inet6.ip6.redirect=0
net.inet.ip.portrange.first=1024
net.inet.ip.portrange.last=65535
net.inet.ip.fw.dyn_max=8192
net.inet.ip.redirect=0
net.inet.ip.sourceroute=0
net.inet.ip.accept_sourceroute=0
net.inet.ip.ttl=128
net.inet.ip.random_id=1
net.inet.ip.intr_queue_maxlen=4096
net.inet.icmp.drop_redirect=1
net.inet.icmp.bmcastecho=0
net.inet.icmp.maskrepl=0
net.inet.icmp.icmplim=50
net.inet.icmp.log_redirect=0
net.inet.udp.recvspace=65536
net.inet.udp.maxdgram=57344
net.inet.tcp.blackhole=2
net.inet.udp.blackhole=1
net.inet.tcp.log_in_vain=0
net.inet.udp.log_in_vain=0
net.inet.tcp.sendspace=64395
net.inet.tcp.recvspace=64395
net.inet.tcp.drop_synfin=1
net.inet.tcp.syncookies=1
net.inet.tcp.rfc1323=1
net.inet.tcp.msl=15000
net.inet.tcp.icmp_may_rst=0
net.inet.tcp.sack.enable=0
net.inet.tcp.finwait2_timeout=20000
net.inet.tcp.fast_finwait2_recycle=1
net.inet.tcp.sendbuf_max=16777216
net.inet.tcp.recvbuf_max=16777216
net.inet.tcp.maxtcptw=40960
net.inet.tcp.sack.enable=0
net.inet.tcp.delayed_ack=0
net.inet.tcp.nolocaltimewait=1

2) Файервол.

Пришлось ограничить количество соединений с одного IP до 20 шт.

ipfw add check-state
...
ipfw add allow tcp from any to me 80, 443 limit src-addr 20 via ${LanOut}
ipfw add allow tcp from 10.0.0.0/8 to me 80, 443 via ${LanIn} # для локальных юзеров
ipfw deny tcp from any to me dst-port 80,443
...

3) Nginx

— GeoIP

Поскольку сайт был украиноязычным, то решено было внедрить GeoIP (nginx пришлось пересобрать с поддержкой этого модуля) и ограничить для UA, RU, US (для гуглоботов и прочих ботов bingo, yahoo,…).

Скачиваем свежие базы GeoIP и распаковываем:

#mkdir /usr/local/etc/nginx/geoip && cd /usr/local/etc/nginx/geoip
#fetch http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz && gunzip GeoIP.dat.gz
#fetch http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz && gunzip GeoLiteCity.dat.gz

Далее в /usr/local/etc/nginx/nginx.conf добавляем такой код в раздел http:

map $geoip_country_code $good_country {
default no;
UA yes;
RU yes;
US yes;
}

— nginx map

Что бы разрешить доступ юзерам из локалки нужно создать map для нужных IP’ок. Для этого добавляем такой код в /usr/local/etc/nginx/nginx.conf в раздел http:

geo $net_geo {
default 0;
10.0.0.0/8 yes;
127.0.0.0/8 yes;
}

— применение для сайта

Что бы применить настройки GeoIP + map для нашего сайта, добавляем такой код в раздел server:

set $GOOD 0;
if ($good_country = yes) {
set $GOOD 1;
}
if ($net_geo = yes) {
set $GOOD 1;
}
if ($GOOD = 0) {
return 444;
}

Знаю, что if — это зло, но по другому никак.

— прочие настройки для nginx

В секции server добавляем

worker_rlimit_nofile  200000;
events {
worker_connections 10240;
use kqueue;
}

В секции http добавляем

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
reset_timedout_connection on;
client_body_timeout 10;
client_header_timeout 10;
send_timeout 10;

4) Прочие.

Можно написать скрипт, который будет парсить netstat на предмет syn соединений с window size 0 и банить IP.

Так же полезно отключить access-логи в apache/nginx, если они не используются для какой-то статистики. Дополнительно можно установить кешер (APC, eAccelerator, …) и смонтировать папку с кешем как tmpfs. Для mysql tmp-папку тоже смонтировать в tmpfs.

Нашёл недавно ПО ( http://synflood-defender.net/docs ) типа для защиты от атак, но не сильно верю, что оно поможет ))

Можно попробовать поставить Varnish для кеширования страниц, особенно, если боты запрашивают одну и ту же.

Защита от небольшого DDoS’a: 2 комментария

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *