Опасность большинства DDoS-атак – в их абсолютной прозрачности и «нормальности». Ведь если ошибка в программном обеспечении всегда может быть исправлена, то полное сжирание ресурсов - явление почти обыденное. С ним сталкиваются многие администраторы, когда ресурсов машины (ширины канала) становится недостаточно, или web-сайт подвергается слэшдот-эффекту (twitter стал недоступен уже через несколько минут после первого известия о смерти Майкла Джексона). И если резать трафик и ресурсы для всех подряд, то спасешься от DDoS, но потеряешь добрую половину клиентов.
Выхода из этой ситуации фактически нет, однако последствия DDoS-атак и их эффективность можно существенно снизить за счет правильной настройки маршрутизатора, брандмауэра и постоянного анализа аномалий в сетевом трафике.
Существует два типа DoS/DDoS-атак, и наиболее распространенная из них основана на идее флуда, то есть заваливания жертвы огромным количеством пакетов. Флуд бывает разным: ICMP-флуд, SYN-флуд, UDP-флуд и HTTP-флуд. Современные DoS-боты могут использовать все эти виды атак одновременно, поэтому следует заранее позаботиться об адекватной защите от каждой из них.
Универсальные советы для защиты. Чтобы не попасть в безвыходное положение во время обрушения DDoS на системы, необходимо тщательным образом подготовить их к такой ситуации:
Первым делом смотрим показатель Загрузка системы (Load average, LA) (в статье указаны допустимые значения LA для двухъядерного процессора.)
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
cat /proc/net/nf_conntrack | grep udp | wc -l cat /proc/net/ip_conntrack | grep udp | wc -l
Наличие SYN- флуда устанавливается легко - через подсчет числа «полуоткрытых» TCP- соединений. В обычной ситуации их не должно быть совсем (или очень небольшое количество: максимум 1-3).
netstat -na | grep ":1720\ " | grep SYN_RCVD netstat -na | grep ":443\ " | grep SYN_RCVD netstat -na | grep ":80\ " | wc -l
Один из распространенных способов не только забить канал связи, но и ввести сетевой стек операционной системы в такое состояние, когда он уже не сможет принимать новые запросы на подключение. Основан на попытке инициализации большого числа одновременных TCP-соединений через посылку SYN-пакета с несуществующим обратным адресом. После нескольких попыток отослать ответный ACK-пакет на недоступный адрес большинство операционок ставят неустановленное соединение в очередь. И только после n-ой попытки закрывают соединение. Так как поток ACK-пакетов очень велик, вскоре очередь оказывается заполненной, и ядро дает отказ на попытки открыть новое соединение. Наиболее умные DoS-боты еще и анализируют систему перед началом атаки, чтобы слать запросы только на открытые жизненно важные порты. Идентифицировать такую атаку просто: достаточно попробовать подключиться к одному из сервисов. Оборонительные мероприятия обычно включают в себя:
Увеличение очереди «полуоткрытых» TCP-соединений:
# sysctl -w net.ipv4.tcp_max_syn_backlog=1024
Уменьшение времени удержания «полуоткрытых» соединений:
# sysctl -w net.ipv4.tcp_synack_retries=1
Включение механизма TCP syncookies:
# sysctl -w net.ipv4.tcp_syncookies=1
iptables -A INPUT -m conntrack --ctstate NEW,INVALID -p tcp --tcp-flags SYN,ACK SYN,ACK -j LOG --log-level info --log-prefix "DROP SYN,ACK: " iptables -A INPUT -m conntrack --ctstate NEW,INVALID -p tcp --tcp-flags SYN,ACK SYN,ACK -j REJECT --reject-with tcp-reset
Ведь если мы получаем пакет с установленными флагами SYN и ACK (такой комбинацией флагов обладает только ответ на SYN-пакет) по еще не открытому соединению, это означает, что кто-то послал другому хосту SYN-пакет от нашего имени, и ответ пришел к нам. Конечно, злоумышленнику предстоит еще угадать номер последовательности, но лучше не предоставлять ему такого шанса. Согласно приведенному правилу, наш хост ответит RST- пакетом, после получения которого атакуемый хост закроет соединение. Добавление такого правила в конфигурацию фаервола настоятельно рекомендуется, потому что если злоумышленнику удастся осуществить спуфинг-атаку от вашего имени, при расследовании этого эпизода следы приведут к вам.
Возможно для защита от спуфинга вам придется изменить некоторые параметры в ядре Linux. В этой статье они не приводятся, так как кажутся сомнительными для современных версии ядер Linux, ну а для старых хватает информации в интернете.
Метод захламления полосы пропускания. Основан на бесконечной посылке UDP-пакетов на порты различных UDP-сервисов. Легко устраняется за счет отрезания таких сервисов от внешнего мира и установки в фаерволе лимита на количество соединений в единицу времени.
# udp 5060 iptables -A INPUT -p udp --dport 5060 -m connlimit --connlimit-above 60 -j LOG --log-level info --log-prefix "REJECT 5060: " iptables -A INPUT -p udp --dport 5060 -m connlimit --connlimit-above 60 -j REJECT # tcp 1720 iptables -A INPUT -p tcp --syn --dport 1720 -m connlimit --connlimit-above 60 -j LOG --log-level info --log-prefix "REJECT 1720: " iptables -A INPUT -p tcp --syn --dport 1720 -m connlimit --connlimit-above 60 -j REJECT
Очень примитивный метод забивания полосы пропускания и создания нагрузок на сетевой стек через монотонную посылку запросов ECHO (пинг) Не умеешь правильно фильтровать ICMP - не фильтруй вообще!!!. Легко обнаруживается с помощью анализа потоков трафика в обе стороны: во время атаки типа ICMP-флуд они практически идентичны. Почти безболезненный способ абсолютной защиты основан на отключении ответов на запросы ICMP ECHO:
sysctl net.ipv4.icmp_echo_ignore_all=1
Или с помощью брандмауэра:
iptables -A INPUT -p icmp -j DROP --icmp-type 8
Полностью заблокировать протокол icmp (не рекомендуется):
iptables -A INPUT -p icmp -f -j DROP
Нужно подсчитать количество процессов Web - сервера (например Apache) и количество конектов на 80-ый порт. Значения, в несколько раз превышающие среднестатистические, дают основания задуматься.
ps aux | grep apache | wc -l ps aux | grep nginx | wc -l
netstat -na | grep ":80\ " | wc -l netstat -na | grep ":443\ " | wc -l
netstat -na | grep ":443\ " | sort | uniq -c | sort -nr 1 tcp6 0 0 :::443 :::* LISTEN 1 tcp 0 0 193.233.203.51:443 54.36.149.33:60447 TIME_WAIT 1 tcp 0 0 193.233.203.51:443 178.64.46.67:60800 ESTABLISHED 1 tcp 0 0 193.233.203.51:443 178.64.46.67:60796 ESTABLISHED 1 tcp 0 0 193.233.203.51:443 178.64.46.67:60795 ESTABLISHED 1 tcp 0 0 193.233.203.51:443 144.76.58.13:51728 ESTABLISHED 1 tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
Алгоритм защиты от HTTP флуда (подразумевается в мир смотрит Nginx):
cat /var/log/nginx/site-access.log | grep sitemap | awk '{ print $1 }' | sort |uniq -c | sort -nr | awk '{ if ($1>100 ) print "deny " $2 ";"}' >> /etc/nginx/vhosts-includes/block_ddos.conf && nginx -t && nginx -s reload && echo > /var/log/nginx/site-access.log
Еще один вариант создания списка IP для блокировки, после его запуска не забываем обнулять файл лога site.error.log, например командой echo:
cat /var/www/httpd-logs/site.error.log| grep perip | cut -d : -f5 | cut -d , -f1 | sort | uniq -c | sort -nr | awk '{ if ($1>100) print "deny " $2";"}' echo -n > /var/www/httpd-logs/site.error.log
if ($http_referer ~* (arm-eais.rkn.gov.ru|eais.rkn.gov.ru|cases.corp.google.com|iframe-toloka.com|classdom.ru|savemyass.org|yahoo.com|facebook|ba idu.com|qq.com|reddit.com|bing.com|youtube.com|gmail.com) ) { return 444; } if ($server_protocol ~* "HTTP/1.0") { return 444; } if ($http_user_agent ~ "python-requests") { return 444; } if ($http_user_agent ~ "Wget") { return 444; } if ($http_user_agent ~ "curl/7.36.0") { return 444; } if ($http_user_agent ~ Siege.*) { return 444; } if ($http_user_agent ~ ApacheBench.*) { return 444; } deny 196.xxx.xxx.xxx; deny 104.xxx.xxx.xxx; ...
Bash cкрипт выводит топ-список ip адресов для конкретного домена, в запускаемый скрипт нужно передать параметр - имя домена:
#!/bin/bash # Скрипт выводит топ-список ip адресов для конкретного домена # в запускаемый скрипт нужно передать параметр - имя домена, например # ./top_ips.sh YourDomen.ua # Доменное имя DM=$1 #DM='YourDomen.ua' # Директория для отчетов RPDir='/var/log/apache2' # Файл журнала LOGFILE="/var/log/apache2/$DM.access.log" if [ ! -f "$RPDir/$DM.txt" ] then touch "$RPDir/$DM.txt" fi if [ -f $LOGFILE ] then echo "Start log $DM..." awk '{ print $1}' $LOGFILE | sort | uniq -c | sort -nr >> $RPDir/$DM.txt| echo "End log $RPDir/$DM.txt" fi
Blackhole — это запись в таблице маршрутизации, которая направляет трафик «в никуда», пакеты с таким маршрутом будут удалены с причиной «No route to host».
ip route add blackhole 192.0.2.0/24
Отображение таблицы маршрутизации с помощью iproute
ip route default via 203.0.113.1 dev eth0 metric 2 blackhole 192.0.2.0/24 127.0.0.0/8 dev lo scope host 203.0.113.0/24 dev eth0 proto kernel scope link src 203.0.113.10
и отображать с помощью netstat
netstat -rn Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 0.0.0.0 203.0.113.1 0.0.0.0 UG 0 0 0 eth0 192.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 * 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo 203.0.113.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
Таким образом, можно исключить определенные IP из доступа к целевому IP.
Чтобы удалить добавленный маршрут:
ip route del blackhole 192.0.2.0/24
Атака с использованием простого протокола обнаружения сервисов (SSDP) – это тип DDoS-атак с отражением, эксплуатирующий набор сетевых протоколов Universal Plug and Play (UPnP) для отправки амплифицированного потока трафика серверу-жертве. Этот трафик переполняет инфраструктуру атакуемого сервера и приводит к его отказу. В обычном режиме протокол SSDP используется для объявления доступности устройств, использующих стандарт Universal Plug and Play. К примеру, когда UPnP-принтер соединяется с обычной сетью, он сообщает о своих сервисах, которые предоставляет, компьютерам в этой сети, отправив сообщение на специальный IP-адрес, называемый групповым. Групповой адрес после этого сообщает всем компьютерам в сети о новом принтере. Как только каждый отдельный компьютер получает сообщение о принтере, он запрашивает у него полное описание его функций, после чего принтер формирует прямой ответ с полным списком всего, что он может предложить. SSDP-атака использует уязвимость этого конечного запроса о предоставляемых сервисах, вынуждая устройство отправлять ответ в адрес выбранной цели атаки.
Как защититься от SSDP-атаки? Ключевым моментом для системных администраторов является блокирование входящего UDP-трафика с портом 1900 при помощи межсетевого экрана. Если объема атакующего трафика не хватает для переполнения сетевой инфраструктуры, таких мер достаточно.