Мощная DDoS-атака: что делать прямо сейчас

Опубликовано 14 мин. чтения

Снять измерения, закрыть порты, ограничить порт запросов и интенсивность пакетов: что действительно помогает при затяжной DDoS-атаке. И с какого объёма работает только фильтрация в сети перед сервером.

Атака, которая заканчивается через десять минут, просто неприятность. Атака, которая уже несколько дней подряд приходит каждый вечер в одно и то же время, означает другое: ваш сервер перестал быть случайной мишенью. Эта статья показывает, что делать прямо сейчас, что вы можете закрыть своими силами и без доплат и где эти меры заканчиваются.

Все команды рассчитаны на Debian 12, Debian 13, Ubuntu 22.04 LTS и Ubuntu 24.04 LTS и записаны для пользователя root. Если вы работаете под обычным пользователем, добавляйте перед каждой командой sudo. Что такое DDoS-атака с технической стороны, объясняет статья Что такое DDoS-атака?.

Пока атака идёт: не перезагружайте сервер и не перекраивайте половину конфигурации. Перезагрузка стирает ровно те счётчики, которые нужны вам для обращения к провайдеру, а сама атака после неё возвращается в прежнем виде.

Почему так упорно атакуют именно ваш сервер

У серверов, которые обстреливают неделями, почти всегда совпадают три признака. Во-первых, они сами публикуют свой адрес: в списке серверов, в Discord, через DNS-запись. Во-вторых, их используют в строго определённые часы, поэтому простой в восемь вечера заметен максимально. В-третьих, есть кто-то, для кого этот простой чего-то стоит: конкурирующий проект, забаненный игрок, недовольный клиент.

С технической стороны добавляется то, что многие затронутые службы работают поверх UDP. В UDP нет установления соединения, которого можно было бы потребовать, а адрес отправителя легко подделать. Значит, атакующему не нужно ни заходить в вашу службу, ни правильно с ней разговаривать, чтобы создать нагрузку. У служб на TCP ресурсы вместо этого занимают полуоткрытые соединения, которые так и не доводятся до конца.

Порты, о которых на самом деле идёт речь

Атака бьёт не по «серверу», а по конкретному порту. В таблице ниже перечислены стандартные порты самых обстреливаемых служб, и она же служит вам списком для проверки: всё, чего в ней нет, но что при этом открыто, следует закрыть.

Служба Стандартный порт
Minecraft Java Edition25565 TCP
Minecraft Bedrock Edition19132 UDP
FiveM и RedM30120 TCP и UDP
ARK: Survival Evolved7777 и 7778 UDP, у Ascended только 7777 UDP
Rust28015 UDP, RCON 28016 TCP
Порт запросов Steam27015 UDP
TeamSpeak 39987 UDP, ServerQuery 10011 TCP
Веб-сервер80 и 443 TCP
Pterodactyl Wings8080 TCP, SFTP 2022 TCP
Удалённый доступSSH 22 TCP, RDP 3389 TCP
База данныхMariaDB 3306 TCP, PostgreSQL 5432 TCP
VPNOpenVPN 1194 UDP, WireGuard 51820 UDP

Вторая группа портов появляется не как цель, а как источник: 53 (DNS), 123 (NTP), 389 (CLDAP), 1900 (SSDP), 11211 (memcached) и те же 27015. Если преобладают именно такие порты источника, перед вами атака с отражением и усилением. Отправителями тогда оказываются посторонние, плохо настроенные серверы, поэтому блокировка отдельных адресов уходит в пустоту.

Что вы можете сделать сами, прежде чем тратить деньги

Этот раздел самый длинный, и так задумано: аккуратно настроенный сервер выдерживает небольшие и средние атаки собственными силами, а в серьёзном случае даёт измерения для следующего уровня защиты.

1. Первые минуты: измерять, а не крутить настройки

Прежде чем что-то менять, зафиксируйте, что происходит сейчас. Достаточно четырёх значений: входящая интенсивность пакетов, распределение соединений по состояниям, сообщения ядра и ответ на вопрос, отвечает ли служба локально.

IF=$(ip -o route get 1.1.1.1 | awk '{print $5}')
A=$(cat /sys/class/net/$IF/statistics/rx_packets) || exit 1; sleep 1; B=$(cat /sys/class/net/$IF/statistics/rx_packets); echo "$((B-A)) входящих пакетов/с на $IF"
ss -Htan | awk '{print $1}' | sort | uniq -c | sort -rn
dmesg -T | tail -50
curl -o /dev/null -s -w '%{time_total}\n' http://127.0.0.1/

Имя интерфейса берётся из маршрута по умолчанию, потому что eth0 на многих KVM-серверах вообще не существует (там он называется ens3 или enp1s0), а неверно вписанное имя совершенно спокойно покажет ноль пакетов. Крупный блок в состоянии SYN-RECV — это картина SYN-флуда. Если через 127.0.0.1 служба отвечает быстро, а снаружи недоступна, проблема находится в сети. И ещё: внутри сервера вы измеряете только то, что до него дошло, за фильтрацией вам видна лишь часть общего объёма. Как подойти к этому системно, описывает статья Как определить DDoS-атаку на сервере.

Если вы перестали пробиваться по SSH, это не повод для перезагрузки, а следствие забитого канала. Доступ в таком случае идёт через VNC-консоль в личном кабинете, которая работает независимо от сетевого подключения.

2. Инвентаризация: что слушает наружу?

ss -lntup
nmap -Pn -p- --min-rate 1000 ВАШ.IP.АДРЕС.СЕРВЕРА

Первая команда показывает вашу собственную картину, вторая, запущенная с другой машины, картину атакующего. Решает локальный адрес: 0.0.0.0:3306 означает «доступен из всего интернета», 127.0.0.1:3306 означает «только локально» и правила файрвола не требует. Попутно регулярно всплывают забытые службы: тестовый экземпляр, административная панель, база данных без локальной привязки.

3. Оставляйте открытым только то, что службе действительно нужно

Порядок важен, иначе вы закроете доступ самому себе: сначала разрешающие правила, затем политика по умолчанию, и только потом включение.

ufw allow 22/tcp comment 'SSH'
ufw allow 80,443/tcp comment 'Web'
ufw allow 25565/tcp comment 'Игровой порт'
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose

После этого проверьте вторым, заново открытым сеансом, попадаете ли вы ещё на сервер: уже установленные соединения переживают включение даже тогда, когда подходящего правила нет. Инструкция вместе с запасным путём есть в статье Настройка файрвола UFW без потери доступа.

Базе данных в открытой сети не место: в файле /etc/mysql/mariadb.conf.d/50-server.cnf должно стоять bind-address = 127.0.0.1. Административным интерфейсам там тоже не место: если постоянного IP-адреса для точечного разрешающего правила нет, оставьте порт закрытым и ходите на него через SSH-туннель.

ssh -N -L 8443:127.0.0.1:8443 root@ВАШ.IP.АДРЕС.СЕРВЕРА

Опубликованные порты контейнеров проходят мимо цепочек UFW. Привязывайте их локально, то есть -p 127.0.0.1:8080:80 вместо -p 8080:80, а доступ ведите через reverse proxy.

4. Защитить порт запросов, не закрывая его

У многих служб рядом с основным портом есть второй, который отдаёт сведения о состоянии: у игр на технологиях Steam это 27015 UDP, у Minecraft query-порт, у TeamSpeak интерфейс ServerQuery на 10011 TCP. Они отвечают без входа, а ответ больше запроса, то есть годятся для усиления атаки на третьих лиц. Закрыть их обычно нельзя: тогда ваш сервер пропадёт из списка серверов. Вместо этого ограничьте их по каждому адресу источника:

iptables -I INPUT -p udp --dport 27015 -m hashlimit --hashlimit-name query --hashlimit-mode srcip --hashlimit-above 10/sec --hashlimit-burst 20 -j DROP

Десяти запросов в секунду на адрес хватает и настоящим игрокам, и вашему мониторингу, а источник с тысячами запросов в секунду при этом отбрасывается. В Minecraft параметр enable-query=false в файле server.properties отключает query-порт целиком, и сервер из списка при этом не пропадает. Параметр enable-status=false дополнительно подавляет ответ на пинг из списка, но тогда ваш сервер будет показан как офлайн. Интерфейс ServerQuery у TeamSpeak привяжите к 127.0.0.1.

5. Ограничить число соединений и интенсивность пакетов

iptables -I INPUT -p tcp --dport 443 --syn -m connlimit --connlimit-above 40 --connlimit-mask 32 -j DROP
iptables -I INPUT -p udp --dport 7777 -m hashlimit --hashlimit-name game_udp --hashlimit-mode srcip --hashlimit-above 600/sec --hashlimit-burst 900 -j DROP

Первое правило отбрасывает новые TCP-соединения, как только с одного адреса их одновременно открыто больше сорока. Второе отбрасывает UDP-пакеты, когда из того же источника устойчиво идёт больше 600 пакетов в секунду. Обе цифры — стартовые значения, а не истина в последней инстанции: слишком жёсткая настройка выбрасывает ваших же пользователей. Проверьте командой iptables -L INPUT -n -v, растут ли счётчики совпадений. Если они остаются на нуле, до правила дело вообще не доходит.

Просто добавленные правила iptables после перезагрузки исчезают, сохраняют их командами apt-get install -y iptables-persistent и netfilter-persistent save. При работе с UFW такие правила помещают в /etc/ufw/before.rules, иначе они пропадут при следующем ufw reload. И принципиальное ограничение: лимиты по адресу источника работают ровно до тех пор, пока заметные источники вообще есть. Если каждый из 200 000 участвующих адресов отправит ровно один пакет, не выделится ни один из них.

6. Подготовить ядро к множеству мелких пакетов

sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
sysctl -w net.core.somaxconn=4096
sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max

SYN-cookies отвечают на попытку установить соединение, не занимая при этом память, и включены по умолчанию. Обе очереди переполняются первыми, когда попыток соединения приходит много одновременно. Для постоянной настройки такие значения кладут в файл в каталоге /etc/sysctl.d/ и применяют командой sysctl --system. Последняя строка показывает отслеживание соединений, которое существует только при активном файрволе: когда его таблица заполняется, сервер отбрасывает и легитимные пакеты, а в лог попадает nf_conntrack: table full, dropping packet.

7. Уровень приложения: ограничение частоты, белый список, плагины и анти-чит

Атаки, которые перегружают не канал, а приложение, выглядят иначе: пакетов мало, но каждый дорогой. HTTP-флуду на поиск интернет-магазина гигабит не нужен. Поэтому на веб-сервере самая действенная мера это ограничение по каждому адресу, в nginx оно задаётся в блоке http, а затем применяется в блоке server или location:

limit_req_zone $binary_remote_addr zone=web:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=webconn:10m;

limit_req zone=web burst=20 nodelay;
limit_conn webconn 20;

Против повторяющихся попыток входа это хорошо дополняет Fail2ban, о настройке рассказывает статья Настройка Fail2ban. На игровых серверах против всего, что заходит обычным путём, работают три вещи: белый список (в Minecraft whitelist=true вместе с enforce-whitelist=true), реалистичный верхний предел одновременных игроков и проверка сетевых событий на стороне сервера.

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

8. Список серверов, DNS и собственный IP-адрес

Здесь полезнее честность, чем выдача желаемого за действительное: ваш IP-адрес сохранить в тайне невозможно. Его знает каждый, кто хоть раз подключался, а запись в списке серверов публикует его и без вас. Две привычки всё же помогают: нигде не публиковать сам адрес собственными руками, в том числе в канале Discord и через статус-бота, и подключать пользователей по имени узла, чтобы смена адреса не ломала сразу все ссылки.

При самой смене адреса классика жанра это старые DNS-записи: забытая A-запись, поддомен со страницы статуса, MX-запись на тот же сервер. Да и в этом случае смена адреса даёт выигрыш во времени, а не решение.

9. Фиксировать данные, пока инцидент идёт

Без базы для сравнения вы потом не скажете, много ли 40 000 пакетов в секунду или это обычный вечер вторника. Команда apt-get install -y vnstat sysstat ставит постоянное измерение в фоне. Во время инцидента соберите:

mkdir -p /root/incident && cd /root/incident
date -u > 01-time.txt
ss -s > 02-sockets.txt
ip -s link > 03-interfaces.txt
sar -n DEV 1 10 > 04-packet-rate.txt
dmesg -T | tail -100 > 05-kernel.txt
tcpdump -ni "$IF" -s 96 -c 500 -q > 06-sample.txt

Команду tcpdump всегда ограничивайте ключом -c: неограниченный захват на забитом канале нагружает сервер дополнительно. В тикет затем входят время с указанием часового пояса, затронутый IP-адрес вместе с портом, измеренная интенсивность пакетов с указанием направления, распределение по протоколам и заметные порты источника. С такими данными обращение обрабатывают сразу, а после формулировки «сервер тормозил» следуют встречные вопросы.

Где эти меры заканчиваются

Теперь та часть, которую не решает ни один файл конфигурации. Все меры выше работают в конце канала. Правило файрвола решает судьбу пакета, который уже прошёл по кабелю: отбросить его вы можете, а сделать неотправленным нет.

Давайте посчитаем. Канал на 1 Гбит/с несёт 125 мегабайт в секунду и заполняется, как только кто-то отправит больше. При минимально возможном размере пакетов это примерно 1,49 миллиона пакетов в секунду, а при 10 Гбит/с около 14,9 миллиона. Серверное ядро в зависимости от CPU и сетевой карты обрабатывает несколько сотен тысяч из них, а дальше начинает отбрасывать. Значит, атака, которая не заполняет ваш канал даже на треть, всё равно кладёт сервер, потому что процессорное время уходит на само отбрасывание.

Чтобы понимать реальные порядки величин: на серверах KernelHost в реальном времени были отфильтрованы, среди прочего, атака мощностью более 473,4 Гбит/с при более чем 41,5 миллиона пакетов в секунду на голосовой сервер (9987 UDP) и UDP-флуд мощностью более 112,2 Гбит/с на игровой сервер (7777 UDP). Первый случай примерно в 473 раза превышает то, что канал на 1 Гбит/с способен пропустить в принципе. Объёмные атаки должны заканчиваться в сети перед сервером, иначе они заканчиваются в вашем канале.

Что KernelHost этому противопоставляет

Постоянная защита, которая включена в каждый сервер

Защита от DDoS в KernelHost построена в два уровня и активна постоянно, вам не нужно ничего заказывать, включать или настраивать:

  • Уровень 1: 17 Тбит/с ёмкости mitigation в глобальной scrubbing-сети. Объёмные атаки вычищаются близко к источнику, ещё до того как они дойдут до дата-центра.
  • Уровень 2: фильтрация Arbor в реальном времени на 3,2 Тбит/с на месте, во Франкфурте-на-Майне. Непосредственно перед сервером распознаются и отбрасываются схемы, характерные для конкретных протоколов, пакет за пакетом.

В серьёзной ситуации решают два свойства. Защита работает постоянно и не должна сначала отреагировать на атаку, поэтому нет тех первых минут, когда сервер недоступен. И null-routing не применяется: ваш IP-адрес остаётся в сети, отбрасываются только вредоносные пакеты. Если же провайдер убирает атакуемый адрес из сети, результат для вас ничем не отличается от успешной атаки. Дата-центр — maincubes во Франкфурте-на-Майне (Германия), оператором выступает KernelHost GmbH со штаб-квартирой в Вене (Австрия). Защита входит в каждый серверный тариф без доплаты, от KVM root-сервера до выделенного сервера.

Advanced DDoS Protection для проектов под постоянным обстрелом

Некоторые проекты атакуют не время от времени, а прицельно и неделями. Для них есть Advanced DDoS Protection от 50,00 € в месяц, по модели PrePaid и без минимального срока. Разница не в большей ёмкости, а в контроле:

  • Выделенный защищённый IP-адрес из франкфуртского ядра сети, на который ваш сервер переводится внутри нашей сети. С вашей стороны ничего перестраивать не нужно.
  • Самостоятельно управляемые правила защиты по портам и протоколам в личном кабинете, без тикета: игровой порт получает не те же правила, что порт запросов.
  • Изменения вступают в силу в реальном времени, поэтому подстраивать их можно прямо посреди идущей атаки.
  • Профиль защиты под конкретную игру, а также профили для собственных и модифицированных приложений на любых портах TCP или UDP.

Сравнение двух уровней

Характеристика Включённая постоянная защита от DDoS Advanced DDoS Protection
Цена входит в каждый серверный тариф без доплаты от 50,00 € в месяц, PrePaid
Ёмкость фильтрации 17 Тбит/с глобального scrubbing плюс фильтрация Arbor в реальном времени на 3,2 Тбит/с во Франкфурте-на-Майне та же двухуровневая фильтрация
IP-адрес IP-адрес вашего сервера дополнительный выделенный защищённый IP
Набор правил автоматические профили, настраивать ничего не нужно собственные правила по портам и протоколам в личном кабинете
Изменения применяются автоматически вступают в силу в реальном времени, в том числе во время атаки
Срок привязан к серверному тарифу PrePaid, без минимального срока, без срока расторжения, без платы за подключение

Большинству проектов хватает включённой постоянной защиты вместе с аккуратной настройкой сервера. Advanced DDoS Protection — это ответ на ситуацию, когда кто-то воспринимает происходящее лично.

Частые ошибки и что с ними делать

«Я перезагрузил сервер, и после этого какое-то время всё работало»: так вела себя атака волнами, а не перезагрузка. Перезагрузки стирают те счётчики, которые пригодились бы вам для обращения к провайдеру.

«Я сменил IP-адрес и через два часа снова был офлайн»: новый адрес атакующий взял из того же источника, что и старый, обычно из записи в списке серверов, от статус-бота или из старой DNS-записи.

«Я блокирую заметные адреса, а на их месте появляются новые»: при распределённой атаке их десятки тысяч, а при атаках с отражением вы всё равно блокируете лишь непричастных посторонних.

«Мои правила файрвола не срабатывают»: частых причин три. Правила стоят позади цепочек UFW, они пропали после последней перезагрузки, либо атака объёмная и правило работает корректно, только канал уже забит.

«Загрузка была низкой, а служба всё равно пропала»: типичная атака через интенсивность пакетов. Полоса выглядит безобидно, а число пакетов нет. Измеряйте пакеты в секунду, а не мегабиты.

«В tcpdump я не вижу ничего необычного»: если трафик фильтруется в сети перед сервером, до самого сервера ожидаемо ничего не доходит. Если же канал забит, до вас может не дойти даже SSH-сессия. Тогда используйте VNC-консоль в личном кабинете.

Коротко о главном

Сначала измеряйте, перестраивайте только после этого. Закройте всё, что службе не нужно, ограничьте порт запросов, число соединений и интенсивность пакетов по каждому адресу источника и собирайте измерения, пока инцидент идёт. Так вы подготовлены ко всему, что обходится без заметной полосы. Всё, что сверх этого, решает исключительно сеть перед сервером.

Если ваш проект уже работает в KernelHost, фильтрация активна, и делать для этого ничего не нужно. Если вы всё же замечаете странности, откройте тикет в поддержку, чтобы правила фильтрации подстроили под ваш IP-адрес. Во время идущей атаки с нами дополнительно можно связаться через экстренный чат WhatsApp по номеру +43 650 8209883.

Частые вопросы

Мой сервер недоступен уже несколько часов. Что проверить в первую очередь?
Входящую интенсивность пакетов на сетевой карте, распределение соединений по состояниям командой ss и то, отвечает ли служба быстро через 127.0.0.1. Если локально она отвечает за миллисекунды, а снаружи недоступна, проблема находится в сети, а не в приложении. Крупный блок в состоянии SYN-RECV это картина SYN-флуда.
Перезагрузить сервер или сменить IP-адрес?
И то и другое помогает редко. Перезагрузка стирает ровно те счётчики, которые нужны вам для обращения к провайдеру, а атака после неё возвращается в прежнем виде. Смена адреса даёт выигрыш во времени, а не решение: новый адрес обычно уже через несколько часов снова оказывается в том же списке серверов, у того же статус-бота или в старой DNS-записи.
Я больше не попадаю на сервер по SSH. Как до него добраться?
При забитом канале даже SSH не пробивается, это нормально и не признак поломки. Используйте VNC-консоль в личном кабинете, которая работает независимо от сетевого подключения системы. Перезагружать сервер из-за этого не нужно.
Почему при крупной атаке мой файрвол уже не помогает?
Потому что он способен отбросить только то, что уже дошло. Канал на 1 Гбит/с при минимально возможном размере пакетов исчерпан примерно на 1,49 миллиона пакетов в секунду. Реально отфильтрованная атака доходила до 473,4 Гбит/с при более чем 41,5 миллиона пакетов в секунду. Правило работает корректно, но канал всё равно забит. Объёмные атаки нужно фильтровать в сети перед сервером.
Может ли плагин или анти-чит остановить атаку?
Нет. И то и другое работает в том же процессе, что и приложение, и проверяет пакет только тогда, когда он уже обрабатывается. Встанет процесс, вместе с ним встанет и защитная логика. Против читеров и нарушителей они полезны, против атак на доступность бесполезны. То же самое верно и для белого списка, потому что тот, кто заливает сервер трафиком, заходить на него не собирается.
Уводят ли мой IP-адрес в офлайн во время атаки?
В KernelHost нет. Null-routing не применяется. Атакуемый IP-адрес остаётся в сети, отбрасываются только вредоносные пакеты, а соединения настоящих пользователей продолжают работать. Если же провайдер убирает адрес из сети, результат для вас ничем не отличается от успешной атаки.
Защита от DDoS в KernelHost стоит отдельных денег?
Нет. На каждом сервере работает двухуровневая постоянная защита без доплаты: глобальная scrubbing-сеть с ёмкостью митигации 17 Тбит/с и фильтрация Arbor в реальном времени на 3,2 Тбит/с на месте, в дата-центре maincubes во Франкфурте-на-Майне. Она активна постоянно, включать или настраивать вам ничего не нужно.
Когда дополнительно нужна Advanced DDoS Protection?
Когда ваш проект атакуют прицельно и неделями, например каждый вечер в одно и то же время и с меняющимися схемами. Вы получаете выделенный защищённый IP-адрес и сами управляете правилами защиты в личном кабинете, раздельно по портам и протоколам, с профилем под конкретную игру. Изменения вступают в силу в реальном времени. Цена начинается от 50,00 евро в месяц, PrePaid и без минимального срока.

DDoS-атака Экстренная ситуация Интенсивность пакетов iptables UFW Администрирование серверов Advanced DDoS Protection null-routing