Защита от DoS и DDoS атак

Материал из darklurker wiki
Перейти к: навигация, поиск

L7 атаки ориентированы на логику веб-приложения и нацелены на исчерпание ресурсов веб-сервера при обработке "тяжелых" запросов, интенсивных функций обработки или памяти.

Кратко

  • Анализируем логи и ошибки /var/logs/httpd/access_log или /etc/httpd/logs/access_log
  • Отслеживаем количество запросов в секунду.
  • Баним адреса ботов.
  • Лимитируем ресурсы (размеры буферов) в nginx
  • Настраиваем тайм-ауты в nginx
  • Лимитируем соединия в nginx (limit_conn и limit_req)
  • Тюним ядро.
  • Посмотреть установленные соединения, забанить IP-адреса.
netstat -n -p | awk '{print $ class=sc_digt>5}'|awk -F: '{print $ class=sc_digt>1}' | sort -n | uniq -c | sort -nr | head -n10
  • Использовать fail2ban.
  • Можно использовать Haproxy


Бан адресов через утилиту ipset скриптом

ipset -N ban iphash
tail -f access.log | while read LINE; do echo "$LINE" | \
    cut -d'"' -f3 | cut -d' ' -f2 | grep -q 444 && ipset -A 
    ban "${L%% *}"; done


Вариант поиска и бана ботов

  • Приступим к созданию blacklist-а. В бан мы помеcтим только самых агрессивных ботов, дабы не перегружать iptables.
# ищем ботов
cat /var/log/nginx/error.log | grep "limiting connections by zone" | grep "request: \"GET / HTTP/1.1"| awk '{print $12}'| awk -F"," '{print $1}'| sort | uniq -c | sort -nr > /tmp/botnet.blacklist

# очищаем скрипт бана
cat /dev/null > /tmp/iptables_ban.sh

# создаем DROP правила для 50 самых агрессивных ботов
awk '{print "iptables -A INPUT -p tcp --dport 80 -s " $2 " -j DROP" }' botnet.blacklist | head -n 50 >> /tmp/iptables_ban.sh
 
# загружаем blacklist
bash /tmp/iptables_ban.sh

# делаем ротацию лога
cat /dev/null > /home/www/nginx_log/error.log [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`
  • Добавляем скрипт в крон с частотой несколько минут. Частоту подбираем опытным путем, например, раз в 5 минут.
*/5 * * * * /root/script/ban.sh

В результате iptables будет пополнятся новыми ботами.


Тюнинг ядра

sysctl.conf
#Включим защиту от «наводнения» syn пакетами
net.ipv4.tcp_syncookies = 1
#Размеры буферов для приема и отправки данных через сокеты:
net.core.rmem_default = 16777216
net.core.rmem_max = 16777216
net.core.wmem_default = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 16777216 16777216
net.ipv4.tcp_wmem = 4096 16777216 16777216
#Запретим принимать ICMP редиректы:
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
#Игнорируем широковещательные ICMP запросы:
net.ipv4.icmp_echo_ignore_broadcasts=1
#Уменьшим время которое используется для сообщений о поддержке keep alive соединений:
net.ipv4.tcp_keepalive_time = 1800
#Уменьшим время до закрытия TCP-соединения.
#net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 200000
#Увеличиваем количество conntrack соединений. Необходимо менять значение по умолчанию только на высоко нагруженных серверах
#net.ipv4.ip_conntrack_max = 64000000
#Указываем время в секундах, в течении которого следует ожидать приема FIN до закрытия сокета:
net.ipv4.tcp_fin_timeout = 30
#Указываем количество пакетов проверки keepalive посылать, прежде чем TCP соединение будет закрыто:
net.ipv4.tcp_keepalive_probes = 2
#Указываем максимальное количество начальных SYN и SYN+ACK повторов для установки TCP соединения.
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
#Увеличим длину очереди для входящих пакетов.
net.core.netdev_max_backlog = 10000a
#Далее увеличиваем количество возможных подключений к сокету аналогичным образом.
#По умолчанию значение равно 128, что при высоко нагруженном сервере будет являться узким местом.
net.core.somaxconn=2048
#Увеличиваем буфер под хранение SYN запросов на соединение.
net.ipv4.tcp_max_syn_backlog = 2048
# Увеличим возможное количество сокетов в состоянии TIME_WAIT
net.ipv4.tcp_max_tw_buckets = 720000
#Разрешаем быструю утилизацию сокетов находящихся в состоянии TIME_WAIT
net.ipv4.tcp_tw_recycle = 1
#Включаем tcp_timestamps иначе не будет работать опция tcp_tw_reuse описанная ниже
net.ipv4.tcp_timestamps = 1