1. Типы DDoS-атак: что реально угрожает VPS
Прежде чем настраивать защиту, нужно понять от чего защищаемся. DDoS-атаки делятся на два принципиально разных класса с разными методами защиты.
L3/L4 — объёмные атаки
- SYN Flood — миллионы TCP-запросов на открытие соединения без завершения рукопожатия. Переполняет таблицу соединений.
- UDP Flood — поток UDP-пакетов на случайные порты. Цель — забить канал.
- ICMP Flood — ping-шторм. Реже встречается, легко фильтруется.
Защита: sysctl + iptables + провайдер
L7 — атаки уровня приложения
- HTTP Flood — тысячи GET/POST-запросов, каждый выглядит легитимным. Нагружает CPU и БД.
- Slowloris — открывает много соединений и держит их медленными запросами. Исчерпывает worker'ы Nginx.
- Brute Force — перебор паролей на SSH, wp-login.php, API.
Защита: Nginx rate limiting + Fail2Ban + WAF
Реальность для маленького VPS
Большинство атак на небольшие проекты — это L7 HTTP-флуд и brute force. Серьёзный L3/L4 флуд объёмом >1 Гбит/с встречается реже и требует провайдерской защиты — iptables здесь бессилен, канал забит физически. Начните с Nginx + Fail2Ban, это закроет 80% угроз.
2. Шаг 1: sysctl — защита ядра от SYN-флуда
Параметры ядра Linux — первая линия обороны против SYN-флуда. Главная мера — TCP SYN Cookies: вместо хранения состояния полуоткрытых соединений в таблице ядро кодирует информацию в ISN (initial sequence number) пакета. При SYN-флуде таблица не переполняется.
sudo nano /etc/sysctl.d/99-ddos-protection.conf# ===== SYN-flood protection =====
# Главная защита: SYN cookies (не хранить состояние полуоткрытых соединений)
net.ipv4.tcp_syncookies = 1
# Уменьшить число повторов SYN-ACK при неответе клиента
net.ipv4.tcp_synack_retries = 2
# Увеличить очередь полуоткрытых TCP-соединений
net.ipv4.tcp_max_syn_backlog = 4096
# Увеличить общую очередь соединений для приложений
net.core.somaxconn = 65535
# ===== Anti-spoofing =====
# Проверять, что входящие пакеты приходят с правильного интерфейса (rp_filter)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# ===== ICMP =====
# Не отвечать на широковещательный ping (smurf-защита)
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Игнорировать некорректные ICMP-ошибки
net.ipv4.icmp_ignore_bogus_error_responses = 1
# ===== Оптимизация сети =====
# Увеличить очередь входящих пакетов до обработки
net.core.netdev_max_backlog = 10000
# Защита от TIME_WAIT assassination
net.ipv4.tcp_rfc1337 = 1sudo sysctl -p /etc/sysctl.d/99-ddos-protection.conf
# Проверить, что применились
sysctl net.ipv4.tcp_syncookies
# Ожидаемый вывод: net.ipv4.tcp_syncookies = 1Настройки сохраняются после перезагрузки
Файл в /etc/sysctl.d/ автоматически загружается при старте системы. Не нужно добавлять в rc.local или cron.
3. Шаг 2: iptables — rate limiting и фильтрация мусора
iptables позволяет ограничить число новых соединений с одного IP, дропать аномальные пакеты и защититься от сканеров портов. Правила работают на уровне ядра — быстро и эффективно для малых атак.
Если используете UFW
UFW и iptables работают вместе — UFW является оберткой над iptables. Правила ниже можно добавлять через iptables напрямую параллельно с UFW. Они не конфликтуют, если добавлять их в цепочку INPUT.
Создать скрипт защиты
sudo mkdir -p /etc/iptables
sudo nano /etc/iptables/ddos-rules.sh#!/bin/bash
# DDoS protection rules — применяется при старте сервера
# ===== Дропаем мусорные пакеты =====
# Некорректные пакеты (например, с флагами FIN+SYN одновременно)
iptables -A INPUT -m state --state INVALID -j DROP
# Xmas-пакеты (все флаги установлены — признак сканирования)
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
# Null-пакеты (без флагов — тоже признак сканирования)
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# ===== SYN-флуд =====
# Ограничить новые TCP-соединения: не более 60 в секунду (burst до 100)
iptables -A INPUT -p tcp --syn -m limit --limit 60/s --limit-burst 100 -j RETURN
# Превышение лимита — дропаем
iptables -A INPUT -p tcp --syn -j DROP
# ===== Лимит соединений с одного IP =====
# Не более 50 одновременных TCP-соединений с одного адреса
iptables -A INPUT -p tcp -m connlimit --connlimit-above 50 -j REJECT --reject-with tcp-reset
# ===== ICMP-флуд =====
# Разрешить ping, но не более 5 в секунду
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/s --limit-burst 10 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# ===== UDP-флуд =====
# UDP (кроме DNS) — не более 100 пакетов в секунду с одного IP
iptables -A INPUT -p udp ! --dport 53 -m recent --set --name UDP-FLOOD --rsource
iptables -A INPUT -p udp ! --dport 53 -m recent --update --seconds 1 --hitcount 100 --name UDP-FLOOD --rsource -j DROP
echo "DDoS rules applied"
sudo chmod +x /etc/iptables/ddos-rules.sh
sudo bash /etc/iptables/ddos-rules.shСохранить правила — автозапуск
sudo apt install -y iptables-persistent
# Сохранить текущие правила (iptables-persistent спросит при установке,
# или сохраняем вручную):
sudo netfilter-persistent save
# Проверить, что сохранились:
cat /etc/iptables/rules.v4Полезные команды для отладки
# Просмотр текущих правил с счётчиками пакетов
sudo iptables -L INPUT -v -n --line-numbers
# Удалить конкретное правило (по номеру)
sudo iptables -D INPUT 5
# Полный сброс всех правил (осторожно!)
sudo iptables -F4. Шаг 3: Nginx — защита от HTTP-флуда
Nginx имеет встроенные модули ngx_http_limit_req_module и ngx_http_limit_conn_module. Они ограничивают скорость запросов и число одновременных соединений с одного IP — это основная защита от HTTP-флуда и slowloris.
Настройка rate limiting
Зоны лимитов объявляются в блоке http {} (в nginx.conf или отдельном conf.d-файле):
# Зона для rate limiting запросов (10 МБ = ~160 000 IP-адресов)
# rate=10r/s — не более 10 запросов в секунду с одного IP
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
# Зона для лимита одновременных соединений
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# HTTP-код при превышении лимита (по умолчанию 503, лучше 429)
limit_req_status 429;
limit_conn_status 429;В блоке server {} вашего vhost-файла подключаем зоны:
server {
listen 443 ssl;
server_name example.com;
# Ограничить число одновременных соединений с одного IP
limit_conn conn_limit 20;
location / {
# Основной rate limit: burst=30 — разрешить «пачку» из 30 запросов,
# nodelay — не ставить в очередь, сразу возвращать 429
limit_req zone=req_limit burst=30 nodelay;
proxy_pass http://localhost:3000;
}
# Для API — более жёсткий лимит
location /api/ {
limit_req zone=req_limit burst=5 nodelay;
limit_conn conn_limit 5;
proxy_pass http://localhost:3000;
}
# Для статических файлов — можно не ограничивать
location /static/ {
alias /var/www/static/;
}
}Защита от Slowloris
Slowloris открывает много соединений и очень медленно отправляет заголовки, удерживая worker'ы. Защита — таймауты:
# Максимальное время ожидания заголовков запроса (по умолчанию 60s)
client_header_timeout 10s;
# Максимальное время ожидания тела запроса
client_body_timeout 10s;
# Закрывать соединения с клиентом после отправки ответа
keepalive_timeout 30s;
# Ограничить размер тела запроса (защита от загрузки огромных файлов)
client_max_body_size 10m;sudo nginx -t
sudo systemctl reload nginx5. Шаг 4: Fail2Ban для HTTP-атак
Fail2Ban читает логи Nginx и банит IP-адреса, которые превысили rate limit. В связке с предыдущими настройками: Nginx возвращает 429 → Fail2Ban видит это в логах → блокирует IP через iptables на несколько часов.
Фильтр для Nginx rate limit
sudo nano /etc/fail2ban/filter.d/nginx-req-limit.conf[Definition]
# Ловим строки вида: "limiting requests, excess: ... by zone "req_limit", client: 1.2.3.4"
failregex = limiting requests, excess:.*by zone.*client: <HOST>
ignoreregex =Добавить jail в jail.local
[nginx-req-limit]
enabled = true
filter = nginx-req-limit
action = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]
logpath = /var/log/nginx/error.log
findtime = 600
maxretry = 20
bantime = 7200
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
findtime = 300
maxretry = 5
bantime = 3600sudo systemctl restart fail2ban
# Проверить, что jail активен
sudo fail2ban-client status nginx-req-limit
# Посмотреть забаненных
sudo fail2ban-client status nginx-req-limit | grep "Banned IP"Nginx должен логировать ошибки rate limit
Убедитесь, что в конфиге Nginx установлен error_log /var/log/nginx/error.log warn;. Уровень warn или выше нужен, чтобы записывались сообщения о превышении rate limit.
6. Провайдерская DDoS-защита: когда она нужна
Все инструменты выше — защита на уровне сервера. Они не спасут от атаки объёмом >500 Мбит/с: трафик физически забьёт канал до того, как iptables успеет что-то дропнуть. Для серьёзных атак нужна фильтрация на уровне сети провайдера.
Как работает провайдерская защита
BGP Blackhole (Null-routing)
Провайдер анонсирует в BGP, что трафик до атакуемого IP нужно дропнуть на всех пиринговых роутерах. Атака прекращается, но и легитимный трафик тоже. Временная мера — IP "выключают" на время атаки.
Scrubbing-центры (Traffic Cleaning)
Весь трафик перенаправляется через специализированный узел очистки. Там аппаратные DPI-системы отделяют легитимный трафик от атаки и пропускают только чистый. Пользователи не замечают разницы.
Российские провайдеры с DDoS-защитой
Включена в стоимость
Защита до 1 Тбит/с через собственную инфраструктуру, scrubbing-центры в нескольких точках. Работает автоматически.
Базовая бесплатно
Базовая защита включена на все серверы. Расширенная защита (выше 1 Гбит/с) — как дополнительная услуга.
Включена
Базовая DDoS-защита на уровне датацентра входит во все тарифы.
Включена
Защита на уровне датацентра, ориентированы на надёжность. Самая длинная тестовая неделя среди провайдеров (7 дней для юрлиц).
Cloudflare для веб-сайтов — бесплатная альтернатива
Если ваш сервис — веб-сайт или API, Cloudflare бесплатного тарифа скрывает реальный IP сервера и фильтрует большинство L3/L4/L7 атак на своей инфраструктуре. Подключение занимает 10 минут: измените NS-записи домена на Cloudflare. При атаке включите Under Attack Mode — все посетители увидят 5-секундную проверку до загрузки сайта.
7. Мониторинг атак в реальном времени
Команды для диагностики — пригодятся и в спокойное время (понять базовую нагрузку), и во время атаки (быстро найти источник).
# Топ IP-адресов по активным TCP-соединениям
sudo ss -tn | awk '{print $5}' | grep -oE '([0-9]{1,3}.){3}[0-9]{1,3}' | sort | uniq -c | sort -rn | head -20
# SYN_RECV — признак SYN-флуда (в норме должно быть 0-10)
sudo ss -tn state syn-recv | wc -l# Установить если нет
sudo apt install -y nload
# Запустить (q для выхода)
nload eth0
# Альтернатива — ifstat (проще)
sudo apt install -y ifstat
ifstat 1# Топ IP по числу запросов за последние минуты
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# Топ запрашиваемых URL
sudo awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# Число 429-ответов (rate limit сработал)
sudo grep ' 429 ' /var/log/nginx/access.log | wc -l
# Следить за ошибками Nginx в реальном времени
sudo tail -f /var/log/nginx/error.log# Заблокировать один IP
sudo iptables -A INPUT -s 1.2.3.4 -j DROP
# Заблокировать подсеть
sudo iptables -A INPUT -s 1.2.3.0/24 -j DROP
# Посмотреть список блокировок
sudo iptables -L INPUT -v -n | grep DROP
# Снять блокировку
sudo iptables -D INPUT -s 1.2.3.4 -j DROPЧто настроили — итоговый чеклист