MAATRIX / Блог / DDoS на 20 минут: что видно в графиках и что делать в моменте

DDoS на 20 минут: что видно в графиках и что делать в моменте

MAATRIX

Сайт вдруг перестаёт отвечать или отвечает через раз, мониторинг сыплет алертами, а через какое-то время всё само проходит — трафик падает, сервер оживает, будто ничего не было. Знакомая ситуация для тех, кто держит публичный сервис: короткая волна DDoS прошла и закончилась быстрее, чем вы успели что-то предпринять. Разберём, что в такой момент видно на графиках, как на глаз отличить реальную атаку от резкого наплыва обычных посетителей и что из этого можно сделать самому, а что — нет. Дальше — обобщённый сценарий, без привязки к конкретным цифрам и конкретному инциденту: у вас атака может длиться и пять минут, и два часа, объём и pps будут своими в каждом случае. Мы условно берём короткую волну на 15-20 минут как удобный пример для разбора, не как измеренный где-то реальный кейс.

Как это выглядит на графиках в первые минуты

Если у вас настроен мониторинг (Zabbix, Netdata, Grafana с Prometheus или хотя бы vnstat/iftop под рукой), картина обычно разворачивается так:

  • Входящий трафик и pps резко идут вверх почти вертикально — не плавный рост за 10-15 минут, как бывает при органическом наплыве, а скачок за секунды-минуты.
  • Число соединений в conntrack растёт следом или одновременно. Проверить текущее состояние:
# сколько записей в таблице трекинга соединений сейчас
cat /proc/sys/net/netfilter/nf_conntrack_count
# лимит, после которого ядро начнёт резать новые соединения
cat /proc/sys/net/netfilter/nf_conntrack_max

Если первое число резко приближается ко второму — это уже само по себе причина деградации: новые соединения не создаются, клиенты получают обрывы и таймауты. Подробнее о том, почему именно эта таблица часто кладёт сервер раньше, чем кончится CPU или полоса, — в статье про conntrack.

  • Нагрузка на обработку пакетов — растут si (softirq) в top/vmstat, растёт %soft в mpstat -P ALL 1. Это отличается от обычной нагрузки на CPU от приложения: софтирки означают, что ядро тратит время именно на разбор и маршрутизацию пакетов, а не на выполнение вашего кода.
  • nginx (если атака идёт на L7, то есть на 80/443) показывает рост активных соединений и воркеров, упирающихся в worker_connections. Смотрите статус:
# если включён stub_status
curl -s http://127.0.0.1/nginx_status
# или через ss — сколько соединений в разных состояниях
ss -s
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn

Резкий рост строк в состоянии SYN-RECV в выводе ss -ant — характерный признак SYN-флуда, а не проблемы с приложением.

  • Дисковый ввод-вывод и память почти всегда остаются спокойными — если "легло всё сразу", включая диск и память, это скорее повод посмотреть в сторону внутренней проблемы приложения, а не DDoS (см. как читать логи и находить причину сбоя).

Ключевой сигнал короткой волны — скачок так же резко обрывается, как начался: pps и conntrack падают почти вертикально, а не затухают постепенно. Если атака закончилась сама, у вас, скорее всего, было мало времени среагировать руками — и это нормально.

Отличаем DDoS от органического всплеска трафика

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

Признаки, что это атака, а не наплыв реальных посетителей:

  • Концентрация с малого числа подсетей. Проверьте топ источников по логам nginx:
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -30

Если 70-80% запросов за последние минуты пришли из 5-10 адресов или пары смежных подсетей (/24) — это явно не органика. Для быстрой группировки по подсетям:

awk '{print $1}' /var/log/nginx/access.log | awk -F. '{print $1"."$2"."$3".0/24"}' | sort | uniq -c | sort -rn | head -20
  • Или наоборот — огромное число разных IP с одинаковым паттерном запроса. Это характерно для ботнетов: тысячи разных адресов, но запрос к одному и тому же URL, с одинаковыми параметрами или вообще без них, часто с одинаковым (или явно поддельным) User-Agent:
tail -n 50000 /var/log/nginx/access.log | awk -F'"' '{print $6}' | sort | uniq -c | sort -rn | head -20

Если один User-Agent (особенно нетипичный, вроде голого curl/7.x или устаревшего Mozilla/4.0) резко занимает большую долю от общего числа запросов за короткий период — подозрение усиливается.

  • Нетипичный паттерн запросов и статика. Реальные посетители ходят по сайту (главная → карточка → корзина), у них разные referrer, и на одну HTML-страницу браузер тянет ещё десяток файлов статики. При атаке чаще видно однообразное долбление в один и тот же (часто тяжёлый — поиск, генерация PDF, авторизация) URL, с одинаковыми или пустыми referrer и почти без обращений к .css/.js/.png.
  • Volumetric L3/L4-атака может вообще не оставить следов в логах nginx. Если бьют по каналу или SYN-флудом ниже уровня приложения, до nginx многие пакеты не доходят в виде осмысленных HTTP-запросов — сервер "тонет" в сетевом стеке, а access.log выглядит почти пустым. Тогда ориентируйтесь на графики трафика/pps и conntrack, а не на логи веб-сервера.

Честно: стопроцентно надёжного автоматического критерия нет, и в моменте вы почти всегда принимаете решение по совокупности признаков, а не по одному числу.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Что реально можно сделать самому прямо сейчас

Пока атака идёт, у вас есть небольшой набор быстрых действий на уровне сервера — они не остановят по-настоящему объёмную атаку, но снижают нагрузку и часто позволяют сайту дожить до конца волны в рабочем состоянии.

1. Rate limiting на уровне nginx. Если ещё не настроен — добавьте зоны ограничения запросов и соединений:

# в http {}
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

server {
    limit_req zone=req_limit burst=20 nodelay;
    limit_conn conn_limit 20;
    ...
}

Если зона уже была настроена заранее — в момент атаки просто временно ужесточите rate и burst и перезагрузите конфиг (nginx -t && nginx -s reload), не перезапуская сам процесс.

2. Временная блокировка явно вредоносных диапазонов. Если по логам видно концентрацию с конкретных подсетей — блокируйте их точечно через nftables или iptables:

# nftables, временное правило
nft add rule inet filter input ip saddr 203.0.113.0/24 drop

# iptables, тот же смысл
iptables -I INPUT -s 203.0.113.0/24 -j DROP

Для десятков диапазонов удобнее собрать список в ipset — так фильтрация одним правилом на входе, без раздувания цепочки:

ipset create ddos_block hash:net
ipset add ddos_block 203.0.113.0/24
ipset add ddos_block 198.51.100.0/24
iptables -I INPUT -m set --match-set ddos_block src -j DROP

3. fail2ban с агрессивным правилом на время атаки. Если атака идёт через повторяющиеся HTTP-запросы к одному эндпоинту, временное правило с низким порогом срабатывания и коротким findtime может отсечь часть автоматических клиентов. Как собрать такие правила под nginx — в статье про fail2ban для nginx.

4. Снизить нагрузку на приложение. Если атака целится в тяжёлый эндпоинт (поиск, генерация отчётов, авторизация) — временно отдавайте по нему заглушку или 429 без обращения к бэкенду, чтобы не убивать базу и воркеры лишними запросами, даже если nginx их пропускает.

5. Проверить и при необходимости поднять nf_conntrack_max, если именно упор в таблицу трекинга — узкое место, а не сам канал:

sysctl -w net.netfilter.nf_conntrack_max=262144

Это не решает проблему по существу (если канал реально забит, поднятый лимит просто отодвинет момент падения на пару минут), но иногда даёт запас, которого хватает пережить короткую волну. В целом на этом уровне вы отсекаете и облегчаете только то, что физически доходит до вашего сервера — если атака объёмная и бьёт по каналу до него, эти меры помогают частично или не помогают вовсе, и это нормально.

Где заканчиваются возможности локальных настроек

Здесь важно быть честными с собой: rate limiting, firewall-правила и fail2ban работают на уровне вашего сервера — а он подключён к сети через канал определённой пропускной способности, которым управляет не он сам, а провайдер/дата-центр.

Если атака объёмная и работает на уровне L3/L4 (UDP-флуд, ICMP-флуд, SYN-флуд большого объёма, амплификационные атаки через DNS/NTP/memcached) — она может забивать входящий канал ещё до того, как трафик доходит до сетевой карты сервера. Правила iptables/nftables тут уже не помогают: пакеты доедут до интерфейса, но канал перед ним уже насыщен, и легитимный трафик тонет вместе с вредоносным ещё на подходе. Единственное, что реально работает в такой ситуации, — фильтрация выше по сети: на стороне провайдера, upstream-транзита или через специализированный anti-DDoS сервис (прокси вроде Cloudflare закрывает только HTTP/HTTPS-трафик к сайту, а не всю сетевую поверхность сервера, если на нём открыты и другие порты). При этом по-настоящему объёмные L3-атаки в терабитном масштабе не остановит и большинство anti-DDoS сервисов среднего уровня — там счёт идёт на инфраструктуру Tier-1 операторов и специализированных scrubbing-центров.

Это не значит, что настройки на сервере бесполезны — они хорошо отсекают L7-атаки (флуд HTTP-запросами, брутфорс, паразитных ботов) и часть L4 в разумных пределах пропускной способности канала. Но если график показывает насыщение всего входящего канала независимо от того, что вы блокируете правилами, — проблему нужно решать выше уровня сервера, а не искать более хитрый iptables-конфиг. Разграничение зон ответственности разобрано в статье DDoS-атака: первые действия, а более широкий обзор вариантов защиты — в материале про защиту от DDoS на выделенном сервере.

Атака закончилась сама — что это значит

Короткие волны DDoS (минуты, а не часы) часто заканчиваются одинаково резко, как начинаются. Несколько типичных причин, без претензии на то, что в вашем случае было именно так: скрипт атаки был запущен с ограничением по времени или объёму трафика (дешевле и проще для атакующего, чем держать атаку долго); цель была не "положить сайт надолго", а проверить реакцию защиты или отвлечь внимание — короткие тестовые волны не редкость; автоматика провайдера/upstream частично отфильтровала трафик без вашего участия, и вы увидели уже смягчённую версию; атакующий переключился на другую цель из пула адресов, по которым идёт перебор.

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

Разбор логов постфактум и что укрепить

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

Что посмотреть в логах:

# топ IP за время инцидента с точностью до временного окна
awk -v start="05/Sep/2026:14:00:00" -v end="05/Sep/2026:14:25:00" \
  '$4 >= "["start && $4 <= "["end {print $1}' /var/log/nginx/access.log \
  | sort | uniq -c | sort -rn | head -30

# какие URL были самыми частыми целями
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

Для более наглядного разбора удобны goaccess или связка логов с Grafana Loki, если она уже настроена, — можно быстро построить график распределения запросов по IP и URL за интересующий интервал.

Дальше стоит зафиксировать для себя: список source-подсетей, засветившихся в атаке (не для вечной блокировки — адреса часто динамические или принадлежат облачным провайдерам с легитимными клиентами тоже, а как справочный материал); точный паттерн запроса — какой URL и с какими параметрами долбили, чтобы настроить limit_req именно для уязвимого эндпоинта, а не резать лимиты всем подряд; момент, когда деградация стала заметна пользователям, сопоставленный с графиками conntrack/pps — так виднее реальное узкое место (канал, conntrack, воркеры nginx или бэкенд).

Что стоит рассмотреть с точки зрения защиты на будущее:

  • Прокси перед сервером — Cloudflare (в бесплатном тарифе уже даёт базовую фильтрацию L7 и скрывает реальный IP сервера) или другой CDN/WAF, если сайт публичный и трафик преимущественно HTTP/HTTPS.
  • Anti-DDoS сервис на стороне хостера — там, где именно объёмная фильтрация происходит выше вашего канала, а не на самом сервере. Уточняйте у провайдера, что именно входит: L3/L4-фильтрация обычно либо в базовом пакете, либо отдельной опцией.
  • Постоянный мониторинг с алертами по трафику и conntrack, чтобы в следующий раз узнать об атаке за секунды, а не по жалобам пользователей — базовая настройка описана в статье про мониторинг и алерты при падении сайта.
  • Базовый набор постоянных (не разовых) правил rate limiting и fail2ban — держать их включёнными всегда с разумными порогами, а не настраивать только в момент, когда уже плохо.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

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

Как быстро понять, что это именно DDoS, а не проблема на самом сервере или в приложении?

Смотрите на связку признаков: резкий скачок pps/трафика и conntrack одновременно с ростом softirq на CPU — это про сеть. Если вместо этого растёт нагрузка на диск, память или конкретный процесс без роста сетевых метрик — вероятнее внутренняя проблема (утечка памяти, тяжёлый запрос к БД, зависший процесс), а не атака.

Стоит ли сразу перезагружать сервер, если он не отвечает во время атаки?

Обычно нет смысла — если проблема в насыщении канала или conntrack, перезагрузка ничего не изменит, атака продолжится с той же интенсивностью, а вы дополнительно потеряете время на простой при загрузке. Перезапуск полезен только если конкретный процесс (nginx, приложение) реально завис или упёрся в лимит файловых дескрипторов и не восстанавливается сам после снятия нагрузки.

Поможет ли просто увеличить worker_connections и лимиты в nginx?

Частично и ненадолго — это отодвигает момент исчерпания ресурсов, но не убирает первопричину. Если канал или conntrack уже насыщены, увеличенные лимиты просто позволят серверу дольше пытаться обработать больше мусорных соединений, тратя на это те же ограниченные ресурсы CPU и памяти.

Что делать, если атака идёт не на 80/443, а на произвольные UDP-порты или ICMP?

Здесь rate limiting nginx не при чём — это уровень firewall и, для по-настоящему объёмных случаев, уровень провайдера. На сервере можно временно ограничить или полностью закрыть ненужные порты через nftables/iptables, но от объёмного флуда это защищает слабо — см. предыдущий раздел про пределы локальных настроек.

Нужен ли Cloudflare или похожий прокси, если сервер и так арендован у хостера с фильтрацией на аплинке?

Базовая фильтрация на аплинке обычно закрывает грубые объёмные атаки на уровне сети, но не защищает от точечного L7-флуда HTTP-запросами — для этого прокси с собственным WAF даёт дополнительный уровень. Их разумно использовать вместе, а не как взаимозаменяемые варианты.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →