DDoS — типы атак и защита
В октябре 2016 года крупнейшая DNS-инфраструктура Dyn получила DDoS атаку мощностью 1.2 Tbps от ботнета Mirai (заражённые IoT-камеры). Twitter, GitHub, Reddit, Spotify, Netflix были недоступны несколько часов. В феврале 2023 Google заблокировал атаку 398 миллионов запросов в секунду (HTTP/2 Rapid Reset). DDoS-атаки — это не теория, это инструмент, которым регулярно ложат сервисы в production.
DDoS (Distributed Denial of Service) — это атака, в которой множество источников одновременно нагружают цель, превышая её ресурсы и делая сервис недоступным для легитимных пользователей. «Distributed» означает: не один-два злоумышленника, а тысячи или миллионы устройств — ботнет. В этом уроке разберём, чем DDoS отличается от обычной нагрузки, как делятся атаки на три категории, и какая защита реально работает.
Анатомия DDoS-атаки
Любая DDoS-атака состоит из трёх элементов:
- Источники. Скомпрометированные устройства (ботнет), open resolvers, серверы для amplification, или платная сеть бот-нодов.
- Цель. Конкретный IP-адрес или домен жертвы.
- Vector. Тип запросов или пакетов, через которые осуществляется атака.
Цель атакующего — исчерпать какой-то ресурс жертвы:
- Bandwidth — забить канал, чтобы легитимные пакеты не пролезли.
- CPU/Memory — перегрузить серверный процесс.
- State table — например, переполнить таблицу TCP-соединений.
- Database connections — забить connection pool бэкенда.
Главное отличие DDoS от обычного DoS (с одного источника) — сложно фильтровать. Если атака с одного IP — блокируем IP и всё. Если с миллиона уникальных IP, причём легитимных (домашних камер, роутеров) — нужны сложные эвристики для отделения от настоящих пользователей.
Три уровня DDoS по OSI
Атаки делятся по тому, на каком уровне OSI они работают: volumetric (L3-L4 на bandwidth), protocol (L4 на state) и application (L7 на ресурсы приложения).
Volumetric attacks — забить канал
Цель volumetric-атаки — исчерпать пропускную способность канала жертвы. Если ваш сервер имеет 10 Gbps канал, а атака генерит 50 Gbps мусорного трафика, ваши легитимные запросы просто не пролезут — их вытеснит шум.
Классический пример — amplification attack (атаки с усилением). Атакующий отправляет небольшие запросы на промежуточные серверы, подделав source IP жертвы. Сервер отвечает большим ответом — который улетает к жертве.
Популярные amplification векторы (по коэффициенту):
- NTP amplification — до x556. Команда
monlistк ntpd возвращает огромный ответ. - DNS amplification — x50-100. Запрос на DNSSEC-zone возвращает много байт подписей.
- Memcached amplification — x10000-50000. Memcached, открытый в интернет, отдаёт большие ответы. В 2018 был зафиксирован 1.35 Tbps на GitHub.
- CharGEN, SNMP, SSDP, CLDAP — классические vectors.
Защита от volumetric:
- Anycast. Распределить точку входа по сотням data-центров мира (Cloudflare, AWS CloudFront). Атакующий не сможет насытить bandwidth глобальной сети.
- Scrubbing centers. Большие сети (Cloudflare, Akamai, AWS Shield) пропускают трафик через свои очистные центры, которые фильтруют мусор и пересылают только легитимный.
- BGP blackhole. В крайнем случае ISP может «зачернить» IP-блок — весь трафик к этому IP отбрасывается на uplink-маршрутизаторе. Сервис недоступен, но не падает сеть провайдера.
- RPF (Reverse Path Forwarding). ISP проверяет, что source IP пакетов соответствует таблице маршрутизации (BCP 38). Это блокирует spoofing source — основу amplification. Внедрено плохо: только ~50% автономных систем реализуют BCP 38.
Protocol attacks — ломаем state
Атаки на L4-state эксплуатируют тот факт, что для каждого открываемого TCP-соединения сервер хранит state в памяти ядра. Если открыть миллион полу-открытых соединений — table переполнится, новые соединения не примутся.
SYN flood — классика.
SYN cookies — стандартная защита Linux: при заполнении SYN-очереди сервер не хранит state, а кодирует sequence number с криптографическим cookie. При завершении handshake клиент должен прислать правильный ACK — сервер декодирует cookie и восстанавливает state. Boris Beard и Daniel J. Bernstein, 1996.
# Включить SYN cookies в Linux:
sysctl net.ipv4.tcp_syncookies=1
# Состояние сейчас:
sysctl net.ipv4.tcp_syncookies
# net.ipv4.tcp_syncookies = 1
# Сколько SYN cookies задействовалось (метрика атаки):
cat /proc/net/netstat | grep -i syncook
Другие protocol-атаки:
- UDP flood. Шлём мусорные UDP-пакеты на random-порты. Сервер на каждый отвечает ICMP «port unreachable». Полоса забивается.
- ICMP/Ping flood. Куча ICMP-запросов. Менее эффективен в современных сетях (rate-limit на роутерах).
- ACK flood. Шлём ACK-пакеты, заставляя сервер искать соответствующее соединение в таблице.
Защита: rate limiting на edge (ISP, scrubbing center), SYN cookies, connection tracking firewall с ограничениями, тонкие настройки kernel networking stack.
Application attacks — ломаем приложение
L7 атаки — самые хитрые. Атакующий шлёт легитимно выглядящие HTTP-запросы, но в большом количестве, чтобы перегрузить именно ваше приложение (БД, рендеринг, API-кол к внешним сервисам).
Особенность: малый объём трафика, большой эффект. Один запрос на тяжёлый endpoint (например, /search?q=* с full table scan) может занимать секунду CPU. 1000 RPS таких запросов положат БД.
Виды application DDoS:
- HTTP flood. Просто много легитимных HTTP-запросов на тяжёлые endpoints.
- Slow loris. Атакующий открывает HTTP-соединения и медленно (по байту) шлёт заголовки. Сервер держит соединение открытым, ожидая остальные заголовки. Пара тысяч таких соединений — и пул worker-ов исчерпан.
- Slow read. Похоже, но при ответе: атакующий читает ответ очень медленно, заставляя сервер держать соединение и буфер.
- HTTP/2 Rapid Reset (CVE-2023-44487). Атака на HTTP/2: открыть stream и сразу его reset. Сервер тратит ресурсы, не успевая обработать.
- Cache busting. Запросы с уникальными query-параметрами, чтобы обойти CDN-кэш и хитнуть origin.
# Пример slow loris (для понимания, не для атак):
import socket
import time
HOST = 'example.com'
PORT = 80
def slow_connection():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send(b'GET / HTTP/1.1\r\n')
s.send(b'Host: example.com\r\n')
# Шлём заголовки очень медленно -- сервер думает, что мы ещё не закончили
while True:
s.send(b'X-Custom-Header: keep-alive\r\n')
time.sleep(15) # подкармливаем чтобы не таймаутнуло
# Пара тысяч таких соединений и сервер исчерпает worker pool
Защита от application DDoS:
- WAF (Web Application Firewall). Парсит запросы, ищет аномальные паттерны: высокая частота с одного IP, странные UA, странные пути.
- Rate limiting. Per-IP, per-session, per-user. NGINX, AWS WAF, Cloudflare.
- CAPTCHA / Challenge. Если IP подозрительный — покажите CAPTCHA, реальный человек пройдёт, бот — нет.
- JS challenge. Cloudflare даёт JS-задачу, которую boot не выполнит — браузер выполнит. Прозрачно для пользователя.
- Behavioral analysis. ML-модели для отделения людей от ботов по поведению (mouse movements, request patterns).
- Connection limits. Ограничение на число одновременных соединений с одного IP.
Современная DDoS-защита: Cloudflare model
Большинство сервисов сегодня не строят DDoS-защиту с нуля — они проксируют трафик через специализированные сети: Cloudflare, AWS Shield, Akamai, Imperva. Принцип одинаковый.
[Internet] -> [DDoS protection network] -> [Origin server]
Что делает Cloudflare/Akamai:
- Anycast IP. Атака распределяется по сотням data-центров.
- L3/L4 mitigation. Volumetric и protocol attacks отфильтровываются в edge-роутерах. Атака на 50 Tbps распределяется на сотни data-центров по 100 Gbps — ни один не страдает.
- L7 mitigation. WAF с millions of rules: blocking known bad IPs, rate limiting, behavioral analysis, JS challenges.
- Origin shielding. IP вашего сервера скрыт — атакующий не знает, куда стрелять. Все идут на Cloudflare, и только Cloudflare знает реальный origin.
Защита Cloudflare работает только если origin IP скрыт. Если атакующий нашёл реальный IP (через historical DNS records, SSL labs, неосторожно настроенный email-сервер с тем же IP), он может атаковать его напрямую в обход Cloudflare. Защита origin firewall-ом по списку IP Cloudflare — стандартная мера.
Реальные эпизоды DDoS
Чтобы дать представление о масштабе:
- 2016 Dyn DDoS (Mirai botnet) — 1.2 Tbps, использовал заражённые IoT-камеры. Twitter, GitHub, Spotify лежали.
- 2018 GitHub Memcached attack — 1.35 Tbps, через amplification. Cloudflare/Prolexic мониторили, но GitHub переехал на Akamai Prolexic за 10 минут.
- 2020 AWS attack — 2.3 Tbps на одного клиента AWS Shield. CLDAP reflection.
- 2023 Google HTTP/2 Rapid Reset — 398 миллионов rps. Атака на CVE-2023-44487 — слабость спецификации HTTP/2.
- 2023 Cloudflare attack — 71 миллион rps от ботнета на cloud-серверах.
Тенденция: атаки растут по объёму, но защитные сети растут быстрее. В 2026 году серьёзный DDoS-атак на крупный сайт — редкость, потому что большие сети (Cloudflare, AWS) научились их фильтровать. Атаки сместились в application layer — его сложнее автоматически отделить от легитимного трафика.
Что может junior backend developer
DDoS-защита — это не магия, и многое можно сделать на стороне приложения:
- Поставить cache CDN. Cloudflare на free плане защищает от большинства атак на статику.
- Rate limiting в API. NGINX
limit_req_zoneили middleware в FastAPI/Express. Лимит per-IP не должен бить настоящих пользователей, но останавливает простых ботов. - Captcha на чувствительные endpoint. Login, register, password reset — любые тяжёлые операции.
- Здоровые таймауты. Slow loris работает потому, что сервер ждёт заголовки минутами. Настройте
client_header_timeout 30sв NGINX. - Connection limits на edge.
limit_conn_zoneв NGINX, чтобы один IP не открыл 10000 соединений. - Скрыть origin IP. Не использовать тот же сервер для DNS, email, web — все могут проболтаться.
- Monitoring. Алерт при резком росте RPS, latency, error rate. Реакция быстрая — мититейт раньше.
http {
# Rate limit: 30 req/s на IP, burst до 100
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
# Connection limit: max 50 одновременных на IP
limit_conn_zone $binary_remote_addr zone=conn:10m;
server {
limit_req zone=api burst=100 nodelay;
limit_conn conn 50;
# Тонкие таймауты против slow loris:
client_header_timeout 10s;
client_body_timeout 10s;
keepalive_timeout 30s;
send_timeout 30s;
# Не отвечать на запросы без User-Agent (грубо, но эффективно против ботов)
if ($http_user_agent = "") {
return 444;
}
}
}
Попробуй сам
Симулируем простой stress test и посмотрим, как NGINX-rate limit его блокирует.
# Установите hey -- простой HTTP load generator:
# brew install hey
# или: go install github.com/rakyll/hey@latest
# Запустите простой сервер:
python3 -m http.server 8000 &
# Поставьте NGINX перед ним с rate-limit (см. конфиг выше) на порту 18080
# Без rate limit -- 1000 запросов в одну секунду:
hey -n 1000 -c 10 http://localhost:8000/
# Все 1000 успешны
# С rate limit (через NGINX):
hey -n 1000 -c 10 http://localhost:18080/
# Часть успешны (200), часть отбиты (503 Service Temporarily Unavailable)
Посмотрите, как меняется error rate при разных значениях rate и burst в NGINX-конфиге. Это и есть базовый DDoS-protection: не дать одному IP положить ваш backend.
Поищите по своему серверу публично открытые resolvers и memcached — они могут быть использованы для amplification:
# Проверить, не отвечает ли локальный memcached на чужие запросы:
echo -e "stats\r\n" | nc -u -w1 your-ip 11211
# Должно быть -- закрыто или connection refused
# Если отвечает -- срочно ограничить через firewall
Если у вас есть аккаунт на Cloudflare — зайдите в раздел Security и посмотрите real-time graph отклонённых запросов. На любом мало-мальски популярном сайте это сотни-тысячи в секунду — атак на bot-уровне.
Rate limiting как защита API от application-layer DDoS