Короткий ответ
Rate limiting — потолок новых сессий и HTTP-запросов, не замена allow-листа. На периметре: nft limit/meter, RouterOS limit/connection-limit, synproxy/cookie где умеете штатно. На reverse proxy в DMZ 10.0.30.10: limit_req/limit_conn nginx. Не ставьте 1 SYN/min на весь офис. Не nft flush, не stop nginx «чтобы пропустило». Brute паролей — ещё и отдельная статья.
WAN 203.0.113.10, LAN 10.0.10.0/24.
Симптомы и как отличить
Conntrack table full в dmesg. Сайт лежит, ping шлюза жив. netstat/ss тысячи SYN_RECV с WAN. nginx access.log: один /24, сотни rps на /wp-login.php или API. IDS орёт на flood.
| Слой | Инструмент | Кого режет |
|---|---|---|
| L3/L4 new | nft/RouterOS | SYN/UDP flood |
| HTTP | nginx limit_req | тяжёлые URL |
| IPS | SID flood | может ложно резать |
Отличие от «канал 100 Мбит забит видео»: saturation vs мелкий пакетный flood. Смотрите pps, не только bps.
Возможные причины
- Политика forward/input без limit.
- Публикация 443 без proxy limits.
- UDP DNS recursion открыт в мир — отдельный инцидент.
- Микротик FastTrack, CPU в interrupt.
- Боты легитимного вида, нужен limit на URI.
- Свой мониторинг без whitelist.
Диагностика
sudo conntrack -S
sudo nft list ruleset | grep -iE 'limit|meter'
ss -ltn | grep ':443'/ip firewall filter print where limit!=""
/ip firewall connection print count-only
/interface print statsНа web:
sudo grep limit_req /etc/nginx/nginx.conf /etc/nginx/sites-enabled/* 2>/dev/null
sudo tail -n 20 /var/log/nginx/access.logНе генерируйте свой flood на прод «для проверки» сверх лёгкого теста. Не флудите чужие адреса.
dmesg: nf_conntrack: table full — да, нужен limit + размер таблицы осмысленный, не «просто увеличить в 100 раз без потолка new».
Концепция pf: max-src-conn-rate, synproxy. Смотрите states. Не выдумывайте опции GUI.
Решение
Сценарий A. nftables new с WAN
sudo cp /etc/nftables.conf /root/nftables.conf.bak.rateПример идеи (сверьте синтаксис meter в man nft 22.04/24.04):
# iifname "ens18" tcp flags syn / syn,ack ct state new \
# meter wan_syn { ip saddr limit rate 20/second } counter accept
# превышение — drop с log prefix WAN-SYN-LIMIT limit rate 5/secondДля UDP VPN: лимит выше, иначе отрежете handshake. Белый список mgmt.
sudo nft -c -f /etc/nftables.conf
sudo systemctl reload nftablesСценарий B. RouterOS 7
/ip firewall filter add chain=input in-interface-list=WAN connection-state=new protocol=tcp \
tcp-flags=syn action=accept limit=50,10:packet comment="WAN SYN budget"
/ip firewall filter add chain=input in-interface-list=WAN connection-state=new protocol=tcp \
tcp-flags=syn action=drop log=yes log-prefix="SYN-LIM"Порядок: allow VPN UDP выше. connection-limit на dstnat 443 по src.
Сверьте limit= в справке вашей сборки. Не reset-configuration.
Сценарий C. nginx в DMZ
# http {
# limit_req_zone $binary_remote_addr zone=one:10m rate=8r/s;
# }
# location /login { limit_req zone=one burst=12 nodelay; }limit_req_status 429. Trust real_ip только свой proxy, иначе все за одним NAT офиса словят лимит — см. NAT src.
Проверка nginx -t, reload. Не stop firewall на web.
Сценарий D. DNS
Рекурсор не на WAN. Если есть — уберите, иначе UDP flood + amplification с вашего IP. Это не «чуть limit», это закрыть 53 с мира кроме своих резолверов.
Сценарий E. Свой сканер/мониторинг
Whitelist 10.0.99.20 в meter. Иначе канарейка ломает алерт.
IPS SYN-flood SID: если режет легитим — detect + perimeter limit, не наоборот.
Откат: bak nft, disable одного limit-правила, не всей цепи.
Два бюджета: публикация 443 и UDP VPN, не один SYN на всех
Снимите baseline легитима: conntrack new/sec на ens18 в рабочий час, rps nginx / и /login отдельно. WAN SYN limit ставьте выше пика легитима с запасом, иначе утро понедельника = ложный «DDoS». UDP 51820/4500 — отдельное правило с более высоким бюджетом: иначе rate «спасёт сайт» и убьёт VPN админов.
nginx limit_req на /login и API, не на статику. Если origin за прокси, лимит по $binary_remote_addr без real_ip банит весь офис как один IP — чините XFF trust, не отключайте limit. Свой мониторинг 10.0.99.20 в whitelist meter. Тест: умеренные SYN на закрытый порт своего WAN, prefix SYN-LIM в syslog, 443 жив. Не устраивайте генератор нагрузки на прод ради скриншота.
Как проверить, что проблема устранена
- Лёгкий тест своего WAN: несколько SYN на закрытый порт — drop log SYN-LIM, сервис 443 жив.
- Не устраивайте ботнет.
- Легитимный логин сайта проходит.
- conntrack -S не растёт в потолок при умеренном шуме.
- Мониторинг не в бане.
- nft/RouterOS/nginx конфиги в SCM.
С офиса откройте сайт, с LTE тоже. 429 на /login при агрессивном F5 — ожидаемо.
Если не помогло
- Flood объёма канала — нужен провайдер/scrubbing, не только nft.
- Application slow без высокого pps — не flood.
- limit_req по
$binary_remote_addr= IP прокси. - IPv6 отдельный meter.
- FastTrack обходит limit — исключите публикацию из FastTrack.
Профилактика
- Базовый WAN SYN budget в шаблоне шлюза.
- limit_req на login/API с первого дня сайта.
- Алерт conntrack > порога.
- Закрытый DNS/NTP recursion.
- Нагрузочный тест своего стенда, не продакшена клиентов.
FAQ
SYN cookies вместо limit?
Дополнительно, если ОС включены штатно (sysctl net.ipv4.tcp_syncookies — проверьте текущее, не выдумывайте значения). Не отменяет nft.
Cloudflare перед сайтом
Тогда limit на origin только с IP Cloudflare/своего proxy. Иначе origin всё ещё торчит — проверьте nmap своего origin IP.
UDP VPN и limit
Слишком жёсткий limit = «VPN не поднимается». Отдельный бюджет на dst-port VPN.
Можно ли 1000/s на всех?
Бессмысленно как защита. Цифра из измерения легитима + запас, не с потолка блога.
RouterOS queue tree вместо filter limit
QoS не drop flood на input CPU. Для SYN flood нужен filter/raw. Queue — про полосу.