Защита игровых серверов от DDoS: ранбук для эпохи десятиминутных атак
Коротко о главном
Узнайте, как защитить игровые серверы от DDoS: детекция по pps, ранбук на 10 минут, настройка nftables и конфигурация устойчивой архитектуры.
В 21:14 очередь матчмейкинга замирает. В 21:19 она снова работает. Вы смотрите на график и видите всплеск на 620 Мбит/с шириной в шесть минут — он уже исчез, прежде чем оповещение дошло до вашего телефона. Никто в вашей команде из двух человек не видел атаку вживую, а игроки списали всё на «лаги».
Согласно отчёту Cloudflare о DDoS-угрозах за Q3 2026 года, было отражено 18,2 миллиона атак на сетевом уровне за квартал — примерно 8 226 в час, то есть одна каждые 0,44 секунды. Из них 96% заканчивались менее чем за 10 минут, а 98% оставались ниже 1 Гбит/с. Число гиперобъёмных атак выше 1 Тбит/с упало с 805 в Q2 до 251 в Q3 — падение примерно на 69%, которое отчёт связывает с ликвидацией правоохранителями IoT-ботнетов Aisuru, KimWolf, JackSkid и Mossad.
Гигантов меньше. Роев больше. И рой — это та модель угрозы, к которой небольшой игровой бэкенд подготовлен хуже всего: он одновременно слишком мал, чтобы активировать уровень защиты провайдера, и достаточно велик, чтобы насытить один игровой инстанс.
Этот ранбук — про именно этот диапазон пропускной способности.
Что на самом деле изменилось в Q3 2026
Если вы управляете игровыми серверами, важны три сдвига. Первый — длительность. Всплеск коротких низкополосных атак на 208% год к году — это операционная сигнатура арендуемых DDoS-сервисов «booter»: дёшево, повторяемо и залпами. Ждите 40 атак за вечер, а не одну.
Второй — смена векторов. CLDAP-рефлексия — атаки через скомпрометированные публичные контроллеры доменов на UDP 389 — обрушилась на 99,5% квартал к кварталу, до 0,05% атак, после высокой активности в H1. Атакующие не остановились; они сменили векторы. DNS-амплификация выросла на 215%, до 3,43% атак на сетевом уровне, а обычные UDP-флуды поднялись с 14,06% до 31,31%.
Третий — расширение целей. Медиа остались самой атакуемой отраслью, но потеряли около трёх четвертей своей доли Q2. Интернет-инфраструктура поднялась с места за пределами топ-10 до #6, а Consumer Services и Adult Entertainment вошли на #8 и #9. Игры находятся прямо в этом кластере клиентоориентированных и чувствительных к задержкам целей.
Урок для защитников: не стройте свой плейбук вокруг вектора прошлого квартала. Стройте его вокруг четырёх категорий — UDP-флуд, DNS-амплификация, рефлексия и SYN-истощение — и исходите из того, что пропорции будут дальше меняться.
Что ломается в игровом бэкенде первым
Всё ломается не одновременно, и знание порядка поможет вам не тушить не тот пожар.
- Игровой порт. UDP-флуд на основной порт сервера утилизирует очереди NIC раньше, чем CPU. Сервер кажется «живым» для health-чека оркестратора, потому что процесс работает, в то время как ядро уже отбрасывает пакеты.
- Эндпоинты сессий и входа. HTTP-флуды бьют по авторизации. Игроки, отключившиеся во время всплеска, не могут вернуться, а те, кто уже в игре, уходят, потому что цикл переподключения не работает.
- Чтение лидербордов. Это самый «усиливающий» путь чтения в большинстве игровых бэкендов: один клиентский запрос разворачивается в range-сканирование базы данных. Отправить 5000 запросов в секунду тривиально, а обслужить их дорого.
- Приём телеметрии. Часто не требует аутентификации или слабо ограничен по частоте — и это обычно самый дешёвый эндпоинт для долбёжки.
- Таблица conntrack. Её заполнение кладёт все сервисы на хосте, включая доступ по SSH. Так четырёхминутная атака превращается в четырёхчасовой простой.
Рефлексивные атаки заслуживают отдельного замечания: трафик приходит с легитимных DNS-резолверов и других сторонних серверов, поэтому блокировка по репутации IP не работает по построению. По вам бьёт невинная инфраструктура.
Детекция: сигналы, которые срабатывают раньше графиков
Дашборды отстают. Счётчики ядра — нет. Самый важный предварительный индикатор — отношение пакетов в секунду к битам в секунду. Легитимные 300 Мбит/с игрового трафика — это примерно 25 000–40 000 пакетов в секунду при типичных размерах полезной нагрузки. UDP-флуд на 300 Мбит/с пакетами по 64 байта — это ближе к 500 000 pps. Та же полоса, но в 15 раз больше пакетов — и это убьёт хост, пока ваш график пропускной способности выглядит умеренно.
Выполните это на подозрительном хосте:
# socket and memory pressure summary
ss -s
# per-protocol counters and the ones that predict a lockup
nstat -az | grep -E 'UdpInDatagrams|UdpNoPorts|UdpInErrors|TcpExtListenDrops|TcpExtTCPReqQFullDrop'
# current conntrack table occupancy vs max
conntrack -C && sysctl net.netfilter.nf_conntrack_max
# what is actually arriving on the wire
tcpdump -nn -i eth0 'udp and not port 7777' -c 200
Читайте их так:
UdpInDatagramsрастёт, а игровой цикл сообщает о снижении числа игроков = флуд.UdpNoPortsрезко растёт = сканер проходит по вашему диапазону портов, часто это предвестник.TcpExtTCPReqQFullDropне равен нулю = переполнение очереди SYN, вы уже теряете легитимные handshake.conntrack -Cвыше 70% отnf_conntrack_max= до полного отказа хоста остались минуты, а не только до отказа игрового сервера.
Если нужен взгляд по эндпоинтам, а не со стороны ядра, протокол диагностики падений UEFN-серверов разбирает, как отличить остановку на сетевом уровне от остановки на уровне движка, — это первое решение в любой триажной сессии.
Для защиты внутри процесса от мусора, который всё же проходит, per-source token bucket на уровне сокетов — дёшево и эффективно. Этот пример на C# ограничивает входящие пакеты до того, как они достигнут вашего тика симуляции:
using System.Diagnostics;
using System.Net;
public sealed class PacketGate
{
private readonly Dictionary<IPAddress, Bucket> _buckets = new();
private readonly int _ratePerSecond;
private readonly int _burst;
// A legit client at 30 Hz sends ~30 packets/s. 120/s allows
// headroom for retransmits without letting a flood through.
public PacketGate(int ratePerSecond = 120, int burst = 240)
{
_ratePerSecond = ratePerSecond;
_burst = burst;
}
public bool Allow(IPAddress source)
{
long now = Stopwatch.GetTimestamp();
if (!_buckets.TryGetValue(source, out var bucket))
{
bucket = new Bucket { Tokens = _burst, LastRefill = now };
_buckets[source] = bucket;
}
double elapsed = (now - bucket.LastRefill) / (double)Stopwatch.Frequency;
bucket.Tokens = Math.Min(_burst, bucket.Tokens + elapsed * _ratePerSecond);
bucket.LastRefill = now;
if (bucket.Tokens < 1.0) return false;
bucket.Tokens -= 1.0;
return true;
}
private sealed class Bucket
{
public double Tokens;
public long LastRefill;
}
}
Понимайте, что это делает, а что нет. Он фильтрует мусор по источникам, который помещается в вашу доступную полосу. Он бесполезен, когда канал забит: в этот момент пакеты отбрасываются выше по потоку, независимо от того, что решает ваш код.
Ранбук по реагированию: первые десять минут
Поскольку 96% атак заканчиваются раньше, чем человек успевает отреагировать, задача ранбука — не в том, чтобы вы «починили» атаку, а в том, чтобы вы собрали доказательства и уменьшили радиус поражения, пока атака выгорает сама.
T+0 — T+2 минуты: подтверждайте, не масштабируйтесь. Подавите рефлекс добавлять инстансы. Масштабирование в флуд умножает ваш счёт и поверхность атаки. Подтвердите вектор счётчиками выше, зафиксируйте pps и полосу, проверьте, не заполняется ли таблица conntrack. Если заполняется — немедленно переходите к аварийной защите хоста T+0.
T+2 — T+5 минут: сбросьте необязательную нагрузку. Отключите всё, что не является геймплеем: пакетирование телеметрии, обновление лидербордов, опрос магазина, социальные ленты. Если ваш бэкенд поддерживает удалённую конфигурацию, это один флаг, а не деплой.
T+5 — T+10 минут: примените rate-лимиты на уровне хоста. Фильтрация в ядре на порядки дешевле фильтрации в приложении:
table inet gameguard {
set udp_flood {
type ipv4_addr
flags dynamic, timeout
timeout 60s
}
chain input {
type filter hook input priority filter; policy drop;
iif lo accept
ct state established,related accept
tcp dport { 22, 443 } accept
tcp dport 7777-7800 accept
udp dport 7777-7800 accept
# drop fragmented UDP - your game protocol should never need it
ip frag-off & 0x1fff != 0 udp drop
# per-source UDP cap well above a real client's send rate
udp dport 7777-7800 update @udp_flood \
{ ip saddr limit rate over 200/second burst 400 packets } drop
}
}
Загрузите через nft -f gameguard.nft. Проверьте через nft list ruleset и nft list set inet gameguard udp_flood. Если вы ошибётесь и заблокируете сами себя, вы превратите сетевой инцидент в инцидент физического доступа — сначала тестируйте на стейджинге и храните правила в системе контроля версий.
T+10 минут и далее: эскалируйте выше по потоку. Вам нужна возможность scrubbing'а или blackhole на сетевой периферии, а не на хосте. Большинство managed-провайдеров игрового хостинга это предлагают; если ваш не предлагает — это закупочная проблема, которую надо решить до следующей атаки. Спросите конкретно про их порог митигирования UDP ниже 1 Гбит/с, потому что большинство опубликованных SLA написаны для терабитных атак, которых вы никогда не увидите.
На протяжении всего: ведите журнал с метками времени. Начало атаки, вектор, пиковый pps, пиковый Gbps, что вы меняли и когда. Постмортем стоит дороже самой митигации.
Плейбук по векторам: подбираем реакцию под форму атаки
UDP-флуд (31,31% атак). Случайные или целевые порты, вынуждающие хост проверять, есть ли слушатель, и генерировать ICMP unreachable. Статья про архитектуру фолбэков на сетевом уровне рассказывает, как сохранить деградированный, но играбельный режим, когда основной транспорт долбят. Реакция: per-source rate limit через nftables, закройте все UDP-порты, кроме игрового, и отключите генерацию ICMP unreachable на хосте.
DNS-амплификация (3,43%, рост 215%). Запросы с подделанным источником к открытым резолверам, большие ответы направляются на вас. Реакция: нельзя блокировать по источнику, потому что источники — легитимные резолверы. Остаётся только поглощать или фильтровать по размеру ответа и частоте. Проверьте, не запущен ли у вас открытый резолвер, с помощью dig +short txt chaos version.bind @your.ip — если он отвечает, закройте его сегодня же.
CLDAP (обрушился до 0,05%). Сейчас тихо, исторически огромно. Напоминание: CLDAP-амплификация работает на UDP 389, поэтому, если вам не нужен LDAP, держите его закрытым и на хосте, и в облачном файрволе. Атакующие возвращаются к незащищённым портам, когда снова меняют векторы.
SYN-флуд. Редко объём, всегда истощение. Включите SYN-куки (sysctl -w net.ipv4.tcp_syncookies=1), поднимите net.core.somaxconn и убедитесь, что таблица conntrack рассчитана на худший реалистичный случай, а не на значение по умолчанию.
Профилактика: архитектура, которая переживёт четырёхминутный всплеск
Сначала математика ёмкости, потому что она убивает много благих надежд. Сервер на 64 игроков при 100 тиках в секунду передаёт примерно 15–20 КБ/с на игрока — это около 1,2 МБ/с, то есть примерно 10 Мбит/с на инстанс. Атака на 400 Мбит/с — это в 40 раз больше легитимного трафика инстанса. Поскольку 98% атак находятся ниже 1 Гбит/с, почти любая атака в текущем распределении достаточно велика, чтобы положить один игровой инстанс, и при этом слишком мала, чтобы заинтересовать автоматическую митигацию tier-1 провайдера.
Это накладывает на архитектуру три ограничения.
Разделите контур аккаунтов и игровой контур. Если эндпоинт входа, чтение лидербордов и сохранения игроков работают на том же хосте, что и игровые серверы, флуд на игровой порт кладёт и аккаунты — игроки не увидят даже экран «мы скоро вернёмся». Запуск этих привязанных к аккаунту сервисов на horizOn — аутентификация, Cloud Save и лидерборды там полностью управляемые — означает, что всплеск на игровой порт деградирует геймплей, но не запирает каждого игрока вне его профиля.
Сделайте отключение фич изменением конфигурации, а не деплоем. Когда начинается флуд, у вас есть секунды. Удалённая конфигурация позволяет мгновенно выключить дорогие пути чтения. Если ваш единственный вариант — выкатывать билд, вы этим не воспользуетесь.
Сделайте health-чек способным видеть сетевой отказ. Проверка процесса сообщает «healthy», пока ядро отбрасывает 90% пакетов. Проверяйте реальную доступность геймплея — синтетический клиент выполняет настоящий handshake и ожидает ответ в течение 250 мс — и пусть это управляет вашим failover.
Лучшие практики: пять изменений, которые стоит выкатить на этой неделе
- Алертите по частоте пакетов, а не только по полосе. Установите порог на 2,5x вашего 95-го перцентиля pps. Алерты только по полосе полностью пропускают короткие всплески; обнаружение аномалий по pps ловит флуд на 300 Мбит/с на хосте с каналом 1 Гбит/с, который не отметил бы ни один график полосы.
- Сознательно задайте размер таблицы conntrack. Установите
net.netfilter.nf_conntrack_maxисходя из пикового числа одновременных сессий, а не из значения по умолчанию в дистрибутиве, и алертите при заполнении на 70%. Одно это изменение предотвращает самую частую эскалацию «атака превратилась в простой». - Заранее напишите набор правил nftables и тестируйте его раз в квартал. Храните его в репозитории рядом с конфигом деплоя. Непротестированное правило файрвола, применённое во время инцидента, — это второй инцидент.
- Опубликуйте для игроков контракт деградированного режима. Если лидерборды и чат отключаются на десять минут во время митигации, напишите об этом в патчноутах и на статусной странице. Тишина воспринимается как мёртвая игра. Если нужна модель — паттерны устойчивости в разборе архитектуры бэкенда после компрометации напрямую переносятся на инциденты доступности.
- Логируйте каждую атаку как структурированное событие. Метка времени, вектор, пиковый pps, пиковый Gbps, длительность, применённая митигация. После пяти вы увидите собственную закономерность — большинство инди-бэкендов атакуют в один и тот же день недели, в один и тот же час, одним и тем же booter'ом.
Вывод
Профиль угроз 2026 года враждебен командам, которые планируют защиту от терабитных атак и игнорируют шестиминутный всплеск на 400 Мбит/с. Гиганты упали на 69%; рои выросли на 208%. Митигация должна быть автоматизированной, дешёвой и жить в ядре, потому что ни один человек не успеет среагировать на атаку, которая заканчивается раньше, чем прочитано оповещение.
Начните со счётчиков, а не с дашбордов. Добавьте per-source rate limit, задайте размер таблицы conntrack, разделите контур аккаунтов и игровой контур и репетируйте десятиминутный ранбук, пока он не станет скучным.
Если часть этого разделения — неприглядная работа, которую вы предпочли бы не брать на себя, — аутентификация игроков, Cloud Save с поддержкой ревизий, лидерборды, удалённая конфигурация, которую можно переключить прямо во время инцидента, — то именно эту часть берёт на себя horizOn, чтобы ваше дежурное время уходило на игровые серверы. Попробуйте бесплатно или почитайте документацию до следующего релизного окна.
Источник: Cloudflare DDoS Threat Report 2026 Q3: больше роёв, меньше гигантов