Защита от DDoS с iptables и ipset

Это о наболевшем...

Защита на уровне iptables. Это один из самых эффективных способов защиты сервера.

 
Использование ipset для хранения IP зомби машин, и занос этих IP с использованием коммандлайнера раз в 60 секунд.
 
Динамически с использованием модуля апача - recent ограничивать запросы.
Для начала необходимо немного подстроить сетевую систему сервера sysctl.conf :
 
# Controls IP packet forwarding
net.ipv4.ip_forward = 0
 
# Controls source route verification
net.ipv4.conf.default.rp_filter = 1
 
# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0
 
# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0
 
# Controls whether core dumps will append the PID to the core filename
# Useful for debugging multi-threaded applications
kernel.core_uses_pid = 1
 
# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1
 
# Controls the maximum size of a message, in bytes
kernel.msgmnb = 65536
 
# Controls the default maxmimum size of a mesage queue
kernel.msgmax = 65536
 
# Controls the maximum shared segment size, in bytes
kernel.shmmax = 4294967295
 
# Controls the maximum number of shared memory segments, in pages
kernel.shmall = 268435456
 
# через 60 секунд с момента наступления тишины в канале сервером выполняется проба. Если клиент жив, то серверу высылается ответный пакет
net.ipv4.tcp_keepalive_time = 60
 
# если ответа на проверку нет, то с интервалом в 10 секунд повторить
net.ipv4.tcp_keepalive_intvl = 10
 
# Сколько раз повторить проверку после чего закрыть соединение
net.ipv4.tcp_keepalive_probes = 5
 
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.ipv4.tcp_timestamps = 0
 
net.ipv4.netfilter.ip_conntrack_max = 65536
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close = 30
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 30
net.ipv4.netfilter.ip_conntrack_tcp_timeout_last_ack = 120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 30
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 60
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 190
net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_recv = 30
net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_sent = 30

Есть еще такой конфиг:

# Если Ваш сегмент сети содержит множество хостов и Вы получаете в логах сообщение
# "Neighbour table overflow.", необходимо увеличить следующие параметры
net.ipv4.neigh.default.gc_thresh1 = 2048
net.ipv4.neigh.default.gc_thresh2 = 4096
net.ipv4.neigh.default.gc_thresh3 = 8192

net.ipv4.tcp_mtu_probing = 1

# Максимельное число одновременных подключений к сокету
net.core.somaxconn = 4096

# Таймауты для протокола TCP. Первый в arno-iptables-firewall устанавливается в 1800, подправьте скрипт.
net.ipv4.tcp_keepalive_time = 180
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 30

# Таймаут для сброса соединения в таблице ip_conntrack, в секундах. По умолчанию равен 5 дням, это как-то слишком.
net.netfilter.nf_conntrack_tcp_timeout_established = 28800

# Устанавливаем в 256 Кб размер буферов по умолчанию для приема и отправки данных через сокеты
net.core.rmem_default = 262144
net.core.wmem_default = 262144

# Устанавливаем в 8Мб максимальный размер буфера сокетов
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608

# Максимальный размер очереди пакетов
net.core.netdev_max_backlog = 8192

# Тюнинг буферов для TCP и UDP соединений
net.ipv4.tcp_rmem = 8192 87380 8388608
net.ipv4.tcp_wmem = 8192 65536 8388608

net.ipv4.udp_rmem_min = 16384
net.ipv4.udp_wmem_min = 16384

net.ipv4.tcp_mem = 8388608 12582912 16777216
net.ipv4.udp_mem = 8388608 12582912 16777216

# Приоритет начала своппинга. Значение от 0 до 100: 0 -  не свопим вообще, 100 - свопим всё что возможно.
vm.swappiness = 70

модуль Apache mod-evasive 

 

файл /etc/apache2/mods-available/mod-evasive.conf с вот такими настройками:

<IfModule mod_evasive20.c>
DOSHashTableSize 4096
DOSPageCount 5
DOSSiteCount 50
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 10
</IfModule>

Включаем модуль и перезапускаем Apache:

a2enmod mod-evasive
/etc/init.d/apache2 restart

В /usr/share/doc/libapache2-mod-evasive/examples есть скрипт на Perl для проверки модуля – test.pl

------------------------------------------------

 

можно добавить ограничение числа SYN пакетов в единицу времени в iptables:

iptables -N syn_flood
iptables -A INPUT -p tcp --syn -j syn_flood
iptables -A syn_flood -m limit --limit 500/s --limit-burst 1500 -j RETURN
iptables -A syn_flood -j DROP

Число новых SYN пакетов – максимум 500 в секунду, при превышении порога в 1500 – новые пакеты блокируются:

Более наглядно этот критерий можно представить себе как некоторую емкость с выпускным отверстием, через которое проходит определенное число пакетов за единицу времени (т.е. скорость «вытекания»). Скорость «вытекания» как раз и определяет величина –limit. Величина –limit-burst задает общий «объем емкости». А теперь представим себе правило –limit 3/minute –limit-burst 5, тогда после поступления 5 пакетов (за очень короткий промежуток времени), емкость «наполнится» и каждый последующий пакет будет вызывать «переполнение» емкости, т.е. «срабатывание» критерия. Через 20 секунд «уровень» в емкости будет понижен (в соответствии с величиной –limit), таким образом она готова будет принять еще один пакет, не вызывая «переполнения» емкости, т.е. срабатывания критерия.

 

Далее можно поставить ограничение по количеству одновременных соединений 

# Лимит на 20 запросов в секунду для интерфейса eth0
/sbin/iptables --new-chain lim1
/sbin/iptables --insert OUTPUT 1 -p tcp --destination-port 80 -o eth0 --jump lim1
/sbin/iptables --append lim1-m limit --limit 20/sec --jump RETURN
/sbin/iptables --append lim1--jump DROP

# Максимум 10 одновременных соединений с одного IP
/sbin/iptables -A INPUT-p tcp --dport 80 -m iplimit --iplimit-above 10 -j REJECT

# Блокировка более 10 SYN
/sbin/iptables -I INPUT -p tcp --syn --dport 80 -j DROP -m iplimit --iplimit-above 10

# 20 соединений на сеть класса С
/sbin/iptables -p tcp --dport 80 -m iplimit --iplimit-above 20 --iplimit-mask 24 -j REJECT 
 

мой:

@ iptables -I INPUT 1 -p tcp -m tcp --dport 80 --tcp-flags
  FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above 15
  --connlimit-mask 32 -j DROP

@ ipset -N blacklist iphash

@ iptables -A INPUT -p tcp -m tcp --dport 80 -m set --set blacklist src -j DROP

@ iptables -A INPUT -s x.x.x.x -j DROP