
Анатомия DDoS-атаки: почему мощное железо тут почти ни при чём
Разговор про DDoS обычно сводится к размеру. Сколько гигабит, сколько ботов, сколько терабит было в последнем рекорде. Из этого рождается вывод, который кажется очевидным: чтобы выдержать атаку, нужно железо побольше.
Вывод неверный, и ломается он на простом вопросе. У вас на сервере кончится не «мощность». У вас кончится что-то конкретное: полоса канала, место в таблице соединений, количество рабочих процессов или процессорное время. Это четыре разных ресурса, и они кончаются от четырёх разных вещей.
Поэтому возможна ситуация, которая выглядит абсурдно, пока не разберёшься: сайт лежит, а процессор свободен. Или наоборот, процессор в сотке, а трафика почти нет. Шестнадцать ядер не помогают против того, что кончилось в одном месте, и купленная гигабитная полоса не спасёт, если упёрлись вы вообще не в полосу.
💥 Рекорд атаки
31,4 Тбит/с
⏱ Сколько он длился
35 секунд
📉 А хватит и этого
100 Мбит/с
Дальше по порядку: какие ресурсы кончаются, почему их так дёшево исчерпать, что из этого реально встречается сегодня и что настраивается за вечер. Ломать мы ничего не будем, разбираем с той стороны, где ваш сервер.
Кому пригодится: если держите сайт или сервис и хотите понимать, что именно у вас сломается; если уже ловили странный простой при спокойных графиках; или если вам предлагали «защиту от DDoS» и вы не знаете, от какой части.
Содержание
- Четыре разных ресурса
- Усиление: как один байт превращается в пятьдесят килобайт
- Самое дешёвое: ваш собственный процессор
- Соединения, которых всего двести пятьдесят шесть
- Почему железо не спасает
- Что происходит в реальности
- Что настраивается за вечер
- Чего настройки не сделают
- Частые ошибки
- Короткий итог
Четыре разных ресурса
Если запомнить из статьи одну вещь, пусть это будет таблица. Слева то, что кончается, справа то, чем это измеряется и почему добавление ядер не помогает.
| Что кончается | Измеряется | Помогает ли железо |
|---|---|---|
| Полоса канала | гигабиты в секунду | нет. Канал кончается до вашего сервера, у провайдера |
| Обработка пакетов | пакеты в секунду | нет. Упирается в прерывания и сетевую карту, а не в количество ядер |
| Состояние соединений | количество записей | нет. Таблица конечна, её размер задан числом, а не объёмом памяти |
| Процессорное время | такты на один запрос | частично. Ядра помогают, только их шестнадцать, а запросов тысячи |
Смотрите в правую колонку. Три ресурса из четырёх вообще не масштабируются покупкой более мощной машины, потому что ограничение живёт либо выше вас по сети, либо в конфигурации, где написано конкретное число.
И дальше всё самое интересное. Чем выше по этой таблице, тем больше трафика нужно атакующему. Чем ниже, тем дешевле ему обходится ваш простой. Поэтому серьёзные ресурсы валят сверху, а маленькие и средние снизу, где достаточно одной машины и домашнего интернета.
Отдельно стоит запомнить, какого размера бывает «мало». Cloudflare в своём отчёте формулирует это так: «A 100 Mbps attack is enough to overwhelm a server or website». Сто мегабит. Это не рекорд и не сенсация, такое раздаётся в любом тарифе, и этого хватает, чтобы ваш сайт перестал открываться.
Усиление: как один байт превращается в пятьдесят килобайт
Самый известный механизм, и он же самый контринтуитивный. Атакующему не нужен широкий канал. Ему нужен посредник, который отвечает больше, чем его спросили.
Работает так. Берётся протокол на UDP, где ответ заметно больше запроса. Запрос отправляется не вам, а на чужой публичный сервер, который этот протокол обслуживает. В поле «обратный адрес» подставляется ваш адрес, потому что UDP не проверяет, кто на самом деле отправитель. Сервер добросовестно отвечает, и ответ прилетает к вам.
Насколько больше становится трафик, посчитано и опубликовано. Вот часть таблицы из бюллетеня CISA, где коэффициент это во сколько раз ответ больше запроса:
Длина полосы тут условная, по порядку величины: иначе первая строка была бы в пятьсот раз длиннее последней и остальные превратились бы в точки.
Задержитесь на первой строке. Десять тысяч это в лучшем случае, а в худшем пятьдесят одна тысяча. Килобайт исходящего трафика у атакующего превращается в десятки мегабайт входящего у вас.
GitHub, 28 февраля 2018 года. В отчёте компании всё описано подробно: атака шла с более чем тысячи автономных систем и достигла 1,35 Тбит/с при 126,9 миллиона пакетов в секунду. GitHub был недоступен с 17:21 до 17:26 UTC и с перебоями до 17:30, после чего прилетела вторая волна на 400 Гбит/с. Механизм был именно memcached: тысячи серверов кэша, выставленных в интернет с включённым UDP, отвечали на подделанные запросы.
Что тут важно для вас. Каждый такой посредник это чья-то забытая настройка. Memcached, который слушает 0.0.0.0 вместо локалхоста, потому что так было в примере конфига. Открытый наружу DNS-резолвер. Включённый SNMP с настройками по умолчанию. Ваш сервер в этой схеме может оказаться не жертвой, а оружием, и узнаете вы об этом из письма хостера про жалобу.
Проверка, как обычно, одной командой:
ss -ulpn
Все строчки с UDP и адресом 0.0.0.0 или * стоит пересмотреть. Нужно ли это слушать наружу вообще, а если нужно, то всему ли интернету. Про то, как правильно поднимать резолвер, чтобы он не стал усилителем, я подробно писал в статье про свой DoH/DoT.
Кстати, старые векторы не умирают, а переизобретаются. В отчёте Cloudflare за первую половину 2026 года центр тяжести атак сместился с ботнетов обратно на отражение и усиление, а вектор CLDAP, который абузит выставленные наружу службы каталогов, вырос за квартал на 580%.
Самое дешёвое: ваш собственный процессор
Переходим вниз таблицы, туда, где атака стоит копейки. Здесь трафика нужно совсем мало, зато каждый запрос заставляет ваш сервер выполнить непропорционально много работы.
Лучшее доказательство того, насколько это дёшево, в том, что два самых известных случая были случайными. Никто не атаковал, люди просто написали код.
🧮 Stack Overflow, 2016
Лежал 34 минуты из-за одного сообщения с двадцатью тысячами пробелов.
🌍 Cloudflare, 2019
27 минут недоступности по всей планете из одной строки в конфиге.
Stack Overflow, 20 июля 2016 года. Причина: пользователь опубликовал сообщение, в котором на одной строке оказалось около двадцати тысяч пробелов подряд. На сайте работало регулярное выражение, которое обрезает пробелы по краям строки, что-то вида [\s]+$. Движок регулярных выражений с возвратом начинает с первого пробела, проходит двадцать тысяч символов, не находит конца строки, возвращается ко второму пробелу, проходит 19 999 символов, снова не находит, и так далее. В разборе инцидента посчитали итог: 199 990 000 проверок на одном сообщении.
Дальше начинается самое красивое. Сообщение попало в список на главной странице, то есть регулярка выполнялась при каждом её открытии. А балансировщик нагрузки проверял работоспособность серверов именно по главной странице, и серверы, которые не отвечали вовремя, он выводил из обслуживания. Так сайт выключил себя сам, по собственному протоколу проверки здоровья.
Cloudflare, 2 июля 2019 года. История ещё внушительнее по последствиям. В правила межсетевого экрана приложений добавили регулярное выражение для обнаружения атак, и у него оказался тот самый катастрофический возврат. Правило раскатали в 13:42 UTC через систему, которая разносит изменения по всей сети за секунды. Процессорное время кончилось на всех ядрах, обслуживающих HTTP и HTTPS, по всей планете.
Теперь понятно, почему это самый дешёвый класс атак. Если неудачная строка в конфиге способна положить сеть, обслуживающую четверть интернета, то отправить запрос, который сам упирается в такую строку, стоит одного запроса.
Исторический пример для полноты картины: атака на хеш-таблицы, 2011
На конференции 28C3 в 2011 году Александр Клинк и Юлиан Вальде показали атаку на хеш-таблицы. Почти все платформы раскладывают параметры запроса в хеш-таблицу, и если подобрать ключи с одинаковым хешем, вставка перестаёт быть быстрой и становится квадратичной по времени. В формулировке исследователей сервер приложений заставляли «use 99% of CPU for several minutes to hours for a single HTTP request». Один запрос, часы процессорного времени.
Задеты были PHP, Java, Python, Ruby, Tomcat, Jetty, Glassfish, движок V8 и ещё десяток имён. Это починили почти везде рандомизацией хеш-функции, но жанр остался: ищется любая операция, где стоимость запроса для вас растёт быстрее, чем стоимость его отправки для атакующего.
Куда смотреть у себя:
- Любое регулярное выражение, которое применяется к пользовательскому вводу без ограничения длины.
- Любой эндпоинт, который генерирует отчёт, распаковывает архив, рендерит картинку или выполняет сложный запрос к базе без кэша.
- Любой поиск, который умеет принимать запрос в сто мегабайт, потому что ограничения никто не поставил.
Соединения, которых всего двести пятьдесят шесть
Третий ресурс из таблицы, и мой личный фаворит по соотношению эффекта к затратам.
Классика жанра называется Slowloris, её показал исследователь под псевдонимом RSnake в 2009 году. Идея в том, чтобы открыть соединения и не закрывать их, отправляя запрос по чуть-чуть. Сервер обязан ждать: по протоколу HTTP заголовки заканчиваются пустой строкой, и пока её не прислали, запрос не считается полученным. Соединение занято и ждёт.
You need few 1000 packets to get started and then a few hundred on a regular integrated basis to continue, 200 to 300 packets per minute. You can easily do it with a single machine.
RSnake, автор Slowloris, в интервью The Register
Двести-триста пакетов в минуту на поддержание. Это меньше, чем генерирует открытая вкладка с мессенджером.
Почему это работает, видно в конфигурации, которую почти никто не смотрит. У Apache в режиме prefork значение MaxRequestWorkers по умолчанию 256. В поточных режимах по умолчанию получается 400, это 16 процессов на 25 потоков каждый. Больше одновременных запросов сервер не обслуживает, остальные встают в очередь.
А теперь загляните в PHP-FPM. В конфиге, который приезжает с пакетом, написано:
pm = dynamic
pm.max_children = 5
Пять. Это значение из поставляемого примера конфигурации, и на боевых серверах его регулярно забывают поднять. Пять одновременных запросов к PHP, и шестой ждёт. Никакой атаки не нужно, достаточно, чтобы ваш сайт кто-то запостил в популярный канал.
Интересно, что от Slowloris изначально страдали не все. По словам автора, он подтвердил проблему на Apache 1.x и 2.x, на dhttpd, GoAhead и Squid, но IIS и lighttpd не задело. Причина архитектурная: там используется пул рабочих потоков, которые не привязаны к соединению жёстко, и висящее соединение не занимает собой работника. Nginx устроен похоже и поэтому держит медленные соединения куда спокойнее, хотя и у него есть свои лимиты, которые стоит настроить.
Современная версия той же идеи оказалась ещё дешевле. В 2023 году нашли способ атаки на HTTP/2 через быстрый сброс потоков: клиент открывает поток и немедленно его отменяет, сервер уже начал обрабатывать запрос, а место в лимите одновременных потоков освободилось. Cloudflare зафиксировала пик 201 миллион запросов в секунду, и вот деталь, ради которой я это упоминаю: ботнет состоял всего из двадцати тысяч машин. Двадцать тысяч против двухсот миллионов запросов в секунду, то есть по десять тысяч запросов с машины. Эффективность достигается не количеством, а тем, что протокол позволяет начать работу и отказаться от неё бесплатно.
Почему железо не спасает
Соберём объяснение целиком, потому что теперь на него есть из чего ответить.
Шестнадцать ядер не помогают против исчерпания таблицы соединений, потому что размер таблицы это число в настройке ядра, а не производная от количества ядер. Запись о соединении занимает несколько сотен байт, и память тут не ограничение.
Гигабитный канал не помогает против атаки с усилением, потому что затор возникает выше вас. Когда к вам идёт больше трафика, чем вмещает канал провайдера до вашего сервера, пакеты отбрасываются на стыке. Вы это даже не увидите: на сервере тишина, в графиках ничего, потому что то, что отбросили, до вас не доехало.
Мощный процессор не помогает против дорогих запросов, он лишь сдвигает порог. Если один запрос стоит секунду процессорного времени, то вдвое более быстрый процессор потребует вдвое больше запросов. Для атакующего это означает удвоить и так копеечный расход.
И отдельно про память. Больше памяти иногда делает хуже, и это неинтуитивно. Большие буферы означают, что система не отбрасывает лишнее сразу, а складывает в очередь, и секундный всплеск превращается в многоминутную деградацию, где всё отвечает, но отвечает ужасно. Это ровно тот же механизм, который я разбирал в статье про пинг и bufferbloat: здоровая система должна выбрасывать лишнее быстро, а не героически пытаться обслужить всё.
Правильный вопрос звучит не «сколько у меня ресурсов», а «что у меня кончится первым». Ответ находится не покупкой железа, а чтением конфигов и одной командой ss -s, которая покажет текущее количество соединений.
Что происходит в реальности
Чтобы разговор не остался теоретическим, вот состояние дел на сегодня, по отчётам тех, кто это всё видит в масштабе.
Рекорды. Cloudflare в отчёте за четвёртый квартал 2025 года сообщает о пике 31,4 Тбит/с, который длился 35 секунд. Чуть раньше была атака на 29,7 Тбит/с продолжительностью 69 секунд, устроенная ботнетом под названием Aisuru: в ней трафик раскидывался в среднем по пятнадцати тысячам портов получателя в секунду, чтобы сложнее было фильтровать. Microsoft 24 октября 2025 года отбила на Azure атаку в 15,72 Тбит/с и 3,64 миллиарда пакетов в секунду, назвав её крупнейшей в истории их облака. Сам ботнет Aisuru собран, по разным оценкам, из одного-четырёх миллионов заражённых устройств, в основном домашних.
Количество. За первую половину 2026 года Cloudflare отбила 935 атак мощнее терабита в секунду. Во втором квартале таких было 805 против примерно 130 в первом, то есть рост в шесть раз за квартал.
А вот главная цифра не про размер. В том же отчёте есть наблюдение, которое стоит всей статистики: атаки короткие, рекордные укладываются в десятки секунд, и вывод там сформулирован прямо: «by the time an alert reaches a security analyst, the attack has already completed». К моменту, когда уведомление дойдёт до человека, атака закончилась.
Из этого следует неприятное. Схема «мне придёт уведомление, я зайду по SSH и что-нибудь сделаю» не работает вообще. Не потому, что вы медленный, а потому, что событие короче вашего времени реакции. Работает только то, что настроено заранее и срабатывает без вас.
И про то, кто это делает. В апреле 2026-го прошла очередная итерация международной операции против сервисов заказных атак: 21 страна, изъято 53 домена, предупреждения отправлены более чем 75 тысячам пользователей, четыре задержания. Семьдесят пять тысяч пользователей. Это не хакеры, а подписчики с тарифом и кнопкой. Экономику этого рынка, включая цены, я разбирал в «Кому я нужен», и она объясняет, почему атака на маленький сайт перестала требовать причины.
Что настраивается за вечер
По порядку, от самого дешёвого к самому хлопотному. Заранее скажу: ни один из пунктов не защитит от терабита, и ниже отдельный раздел про то, чего эти настройки не сделают.
Включить cookies для SYN, точнее проверить, что включены. В ядре Linux это давно значение по умолчанию:
sysctl net.ipv4.tcp_syncookies
Должна вернуться единица. Механизм позволяет не хранить состояние для полуоткрытых соединений: сервер кодирует нужное в номер последовательности и проверяет при ответе клиента. Только без иллюзий: в документации ядра прямо сказано, что это аварийный механизм и «It MUST NOT be used to help highly loaded servers». То есть он спасает от затопления таблицы, а не делает вас неуязвимым.
Поставить лимиты в nginx. Два правила, которые закрывают большую часть прикладной мелочи:
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_req_zone $binary_remote_addr zone=reqs:10m rate=10r/s;
server {
limit_conn perip 20;
limit_req zone=reqs burst=20 nodelay;
}
Двадцать одновременных соединений и десять запросов в секунду с адреса. Живой человек с открытым сайтом в это укладывается с запасом, а автоматика упирается сразу.
Прижать таймауты. Это прямое лекарство от медленных соединений:
client_header_timeout 10s;
client_body_timeout 10s;
send_timeout 10s;
client_max_body_size 10m;
Последняя строка заодно про предыдущий раздел: она не даёт отправить вам сто мегабайт в поле поиска.
Посмотреть на свои рабочие процессы. Откройте /etc/php-fpm.d/www.conf или его аналог и найдите pm.max_children. Если там пятёрка из примера, поднимите до разумного, посчитав от памяти: сколько съедает один процесс, умножить на количество, должно влезать в машину с запасом. Та же мысль про MaxRequestWorkers у Apache, если он у вас фронтом.
Поставить кэш перед тяжёлым. Самый недооценённый пункт. Если дорогой запрос отдаётся из кэша, он перестаёт быть дорогим, и весь класс атак на процессор обесценивается. Даже минута кэширования главной страницы меняет картину полностью.
Настроить мониторинг снаружи и заранее. Не для того, чтобы успеть вмешаться, выше объяснено, почему не успеете. А для того, чтобы знать, что происходило, и иметь данные для разговора с провайдером. Как это собрать на отдельной машине, у меня есть отдельная статья.
Знать заранее, куда звонить. Самый важный пункт и единственный нетехнический. Выясните до инцидента: есть ли у вашего хостера защита, включается ли она автоматически, что они делают при атаке на вас и в какой момент выключают сервер, чтобы не страдала остальная сеть. Это надо прочитать в договоре в спокойный день, а не выяснять в три ночи.
Чего настройки не сделают
Раздел для честности, потому что без него предыдущий выглядит как обещание.
Против исчерпания канала локальные настройки бесполезны. Если к вам идёт десять гигабит, а канал гигабитный, то всё решается выше вас. Никакие правила на сервере не помогут, потому что пакеты отбрасываются до него. Тут работает только фильтрация на стороне провайдера или вынос сервиса за посредника, и у второго варианта есть своя цена, про которую я написал отдельную статью про Cloudflare.
fail2ban от распределённой атаки не защищает, и это стоит сказать прямо, потому что его ставят именно с такой надеждой. Он блокирует адрес, с которого пришло слишком много попыток. Когда адресов тысяча и с каждого по одной попытке, порог не срабатывает ни у одного. Подробнее этот и ещё семь популярных советов я разбирал в «Советах по безопасности, которые не работают».
Блокировка по странам отваливается о реальность. Современные атаки идут с домашних адресов обычных пользователей по всему миру, потому что домашние адреса ценнее серверных и их специально собирают. Блокировка по географии отрежет вам часть живых посетителей и почти не заденет атаку.
И самое неприятное. При серьёзной атаке хостер может выключить ваш сервер. Не из злого умысла: трафик к вам идёт через общие стыки, и пока вас заливают, страдают соседи. Отключить одного клиента дешевле, чем потерять сегмент. Строчка про это есть в правилах почти у всех, просто её читают уже после.
Частые ошибки
- Считать, что DDoS это про объём трафика. Это про то, какой из четырёх ресурсов кончится первым. Три из них вообще не расширяются покупкой железа.
- Докупать ядра и память. Таблица соединений задана числом, канал кончается у провайдера, а память в больших буферах иногда делает хуже.
- Думать, что успеете отреагировать. Рекордные атаки длятся десятки секунд. К моменту, когда уведомление дойдёт до человека, всё закончилось.
- Надеяться на fail2ban. Он считает попытки с одного адреса, а в распределённой атаке адресов тысячи по одной попытке.
- Не знать свои лимиты.
pm.max_children = 5в поставляемом конфиге PHP-FPM и 256 у Apache это числа, из которых состоит ваш реальный потолок. - Оставлять UDP наружу, не подумав. Memcached с коэффициентом усиления до 51 000 делает из вашего сервера оружие, и жалоба придёт вам.
- Применять регулярки к вводу без ограничения длины. Cloudflare положила этим четверть интернета на 27 минут, причём случайно.
- Отдавать тяжёлые страницы без кэша. Кэш обесценивает весь класс атак на процессор, и это самая дешёвая мера из существующих.
- Читать правила хостера после инцидента. Выключить вас, чтобы не страдала остальная сеть, разрешено почти везде.
Где это держать
Практическая мысль про площадку, раз уж полтекста про то, что решается выше вашего сервера.
Из всего списка защиты сами вы контролируете только прикладную часть: лимиты, таймауты, кэш, разумные числа в конфигах. Канал и фильтрация на входе целиком на стороне площадки, и в этом смысле выбор хостера тут значит больше, чем выбор конфигурации сервера.
Смотреть стоит на три вещи:
- Есть ли фильтрация на входе и включается ли она без вашего участия, потому что ручное включение бесполезно по причинам из раздела про тридцать пять секунд.
- Что написано в договоре про отключение при атаке.
- Какая у площадки полоса на стыках, потому что именно она определяет, что до вас вообще доедет.
Короткий итог
- Кончается не «мощность», а один из четырёх ресурсов: канал, обработка пакетов, таблица соединений, процессорное время. Три из четырёх не расширяются железом.
- Ста мегабит достаточно, чтобы положить сайт. Это формулировка Cloudflare, а не преувеличение.
- Усиление делает канал атакующего неважным: у memcached коэффициент до 51 000, у NTP около 557. GitHub так получил 1,35 Тбит/с и 126,9 миллиона пакетов в секунду.
- Ваш сервер может оказаться усилителем, если слушает UDP наружу. Жалоба придёт вам.
- Самый дешёвый класс атак бьёт по процессору. Stack Overflow положило одно сообщение с двадцатью тысячами пробелов, Cloudflare положила одна строчка в конфиге на 27 минут. Оба раза случайно.
- Потолок соединений это число в конфиге: 256 у Apache, пятёрка в поставляемом примере PHP-FPM. Slowloris держится на 200-300 пакетах в минуту с одной машины.
- Двадцать тысяч машин дали 201 миллион запросов в секунду через сброс потоков в HTTP/2. Решает не количество, а бесплатность отказа от начатой работы.
- Рекорд сегодня 31,4 Тбит/с, и он длился 35 секунд. Реагировать вручную невозможно, работает только настроенное заранее.
- Семьдесят пять тысяч пользователей сервисов заказных атак получили предупреждения в одной операции. Порога входа нет.
- Настраивается за вечер: лимиты и таймауты в nginx, кэш перед тяжёлым, разумные числа рабочих процессов, мониторинг снаружи и прочитанный договор с хостером.
Главная мысль под всем этим. Асимметрия в DDoS не в деньгах и не в мощности, а в том, что одна сторона платит за отправку запроса, а другая за его обработку. Пока эти две цены различаются в сотни раз, никакое железо разницу не покроет. Зато её неплохо покрывают кэш, лимиты и знание того, какое именно число у вас в конфиге стоит потолком.
Вообще я микроразработчик, со мной можно связаться как угодно, я открыт ко всему
Сторонний мой проект: Zapret2UI.
Источники
Должно было быть больше, но я уперся в лимит 30к символов в статье, увы да, но всё что тут есть источники и полезная инфа. Всех благ
- Cloudflare: отчёт по DDoS за первую половину 2026 года, про 935 атак свыше терабита и невозможность ручной реакции
- Cloudflare: отчёт за четвёртый квартал 2025 года, рекорд 31,4 Тбит/с длиной 35 секунд
- Cloudflare: отчёт за третий квартал 2025 года, атака Aisuru на 29,7 Тбит/с
- Microsoft Azure: разбор атаки 15,72 Тбит/с и 3,64 млрд пакетов в секунду
- CISA: бюллетень по атакам с усилением на UDP, таблица коэффициентов
- GitHub: отчёт об инциденте 28 февраля 2018 года
- Stack Exchange: разбор падения 20 июля 2016 года из-за регулярного выражения
- Cloudflare: подробный разбор собственного падения 2 июля 2019 года
- oCERT: advisory по атаке на хеш-таблицы, список затронутых платформ
- Ars Technica: разбор атаки на хеш-таблицы с 28C3
Zajrzyj do pozostałych artykułów bazy wiedzy — sąsiednie tematy też są tam omówione.
