Обнаружение и защита от DDoS-атак

Опасность большинства DDoS-атак – в их абсолютной прозрачности и «нормальности». Ведь если ошибка в программном обеспечении всегда может быть исправлена, то полное сжирание ресурсов - явление почти обыденное. С ним сталкиваются многие администраторы, когда ресурсов машины (ширины канала) становится недостаточно, или web-сайт подвергается слэшдот-эффекту (twitter стал недоступен уже через несколько минут после первого известия о смерти Майкла Джексона). И если резать трафик и ресурсы для всех подряд, то спасешься от DDoS, но потеряешь добрую половину клиентов.

Выхода из этой ситуации фактически нет, однако последствия DDoS-атак и их эффективность можно существенно снизить за счет правильной настройки маршрутизатора, брандмауэра и постоянного анализа аномалий в сетевом трафике.

Существует два типа DoS/DDoS-атак, и наиболее распространенная из них основана на идее флуда, то есть заваливания жертвы огромным количеством пакетов. Флуд бывает разным: ICMP-флуд, SYN-флуд, UDP-флуд и HTTP-флуд. Современные DoS-боты могут использовать все эти виды атак одновременно, поэтому следует заранее позаботиться об адекватной защите от каждой из них.

Универсальные советы для защиты. Чтобы не попасть в безвыходное положение во время обрушения DDoS на системы, необходимо тщательным образом подготовить их к такой ситуации:

  1. Все сервера, имеющие прямой доступ во внешнюю сеть, должны быть подготовлены к простому и быстрому удаленному ребуту (sshd спасет отца русской демократии). Большим плюсом будет наличие второго, административного, сетевого интерфейса, через который можно получить доступ к серверу в случае забитости основного канала.
  2. ПО, используемое на сервере, всегда должно находиться в актуальном состоянии. Все дырки - пропатчены, обновления установлены (простой, как сапог, совет, которому многие не следуют). Это оградит тебя от DoS-атак, эксплуатирующих баги в сервисах.
  3. Все слушающие сетевые сервисы, предназначенные для административного использования, должны быть спрятаны брандмауэром ото всех, кто не должен иметь к ним доступ. Тогда атакующий не сможет использовать их для проведения DoS-атаки или брутфорса.

Обнаружение DoS-атак

Первым делом смотрим показатель Загрузка системы (Load average, LA) (в статье указаны допустимые значения LA для двухъядерного процессора.)

  • Вариант №1. Подсчитать количество соединений для каждого IP по протоколам tcp и udp: netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
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
  • Количество конектов на 80, 443 порту
netstat -na | grep ":80\ " | wc -l
netstat -na | grep ":443\ " | wc -l
  • Просмотреть список IP- адресов, с которых идут запросы на подключение на порт 443:
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):

  • Выяснить какой именной сайт, а чаще всего какую именно страницу засыпают запросами, например при помощи httpry или просмотр логов вебсервера.
  • Предположим DDOS идет на страницу сайта с url sitemap. Можем создать команду, которая создаст файл с ip для подключения к 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
  • Вариант жесткой блокировки DDOS. На выходе получаем подобный файл, где в начале блокируем: ботов, устаревший протокол HTTP1.0, некоторые юзер агенты (вы можете добавить на свое усмотрение) и ниже добавлены ip из предыдущего пункта. Если расположить этот файл в директории /etc/nginx/vhosts-includes/block_ddos.conf, то он автоматически, после перезагрузки nginx, подключиться ко всем доменам.
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

Блокирование атак при помощи null route или blackhole

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

DDoS-атака с использованием SSDP

Атака с использованием простого протокола обнаружения сервисов (SSDP) – это тип DDoS-атак с отражением, эксплуатирующий набор сетевых протоколов Universal Plug and Play (UPnP) для отправки амплифицированного потока трафика серверу-жертве. Этот трафик переполняет инфраструктуру атакуемого сервера и приводит к его отказу. В обычном режиме протокол SSDP используется для объявления доступности устройств, использующих стандарт Universal Plug and Play. К примеру, когда UPnP-принтер соединяется с обычной сетью, он сообщает о своих сервисах, которые предоставляет, компьютерам в этой сети, отправив сообщение на специальный IP-адрес, называемый групповым. Групповой адрес после этого сообщает всем компьютерам в сети о новом принтере. Как только каждый отдельный компьютер получает сообщение о принтере, он запрашивает у него полное описание его функций, после чего принтер формирует прямой ответ с полным списком всего, что он может предложить. SSDP-атака использует уязвимость этого конечного запроса о предоставляемых сервисах, вынуждая устройство отправлять ответ в адрес выбранной цели атаки.

Как защититься от SSDP-атаки? Ключевым моментом для системных администраторов является блокирование входящего UDP-трафика с портом 1900 при помощи межсетевого экрана. Если объема атакующего трафика не хватает для переполнения сетевой инфраструктуры, таких мер достаточно.

PQ VPS сервера в 28+ странах.