Если ваш VDS доступен по TCP (SSH, HTTP(S), почта, API), то одна из самых приземлённых и неприятных атак — классический SYN flood. Даже относительно небольшая волна входящих SYN-пакетов может забить очередь полусоединений, заставить ядро тратить CPU на создание состояний в conntrack и в итоге замедлить реальные подключения. Приятная новость: в Linux есть встроенная защита на уровне брандмауэра — synproxy в nftables. Она принимает на себя рукопожатие, отбрасывает мусор и пропускает дальше только валидные подключения.
Как работает SYNPROXY и чем он отличается от TCP syncookies
Механизм synproxy перехватывает исходные SYN, отвечает от имени сервера SYN+ACK, и только получив корректный финальный ACK с ожидаемыми параметрами (включая опции TCP), создаёт полноценное соединение в стеке. Это важно: до получения корректного ACK мы не расходуем память под сокеты, не увеличиваем очередь SYN-RECV и не плодим записи в conntrack. С точки зрения атакующего, сервер «жив», но ресурсов не потребляет.
Часто путают synproxy с tcp_syncookies. syncookies — механизм ядра TCP, который включается, когда переполняется очередь полусоединений. Он помогает, но срабатывает поздно и не защищает conntrack. synproxy работает раньше — на уровне пакетного фильтра — и не даёт мусору дойти до стека. Лучший результат даёт их совместное использование: synproxy обрезает львиную долю атак, а syncookies — страховка в пограничных случаях.
Где применять на VDS и какие ограничения
- Идеальный сценарий — хост с «входящими» сервисами: SSH, HTTP(S), SMTP/IMAP, прокси, API.
synproxyтолько для TCP. Против UDP- или ICMP-атак он не поможет (нужны другие приёмы).- Лучше включать на конкретных портах, а не «ко всеобщему счастью» на весь TCP: это экономит CPU и упрощает отладку.
- При асимметричной маршрутизации (вход идёт через один интерфейс, а ответ уходит через другой)
synproxyможет не сработать — контроль сеанса нарушится. На обычном VDS такая асимметрия редкость.
Ключевая польза для VDS: резкое снижение давления на
conntrackи TCP-очереди, а значит — приоритет реальных клиентов даже во время пиков.

Предварительные требования и проверка модулей
Нужно современное ядро Linux (практически любой 5.x подойдёт) и модули: nf_tables, nf_conntrack, nf_defrag_ipv4/nf_defrag_ipv6, nf_synproxy_core. Загрузим их и убедимся, что всё доступно:
uname -r
lsmod | egrep 'nf_tables|nf_conntrack|nf_defrag|synproxy'
sudo modprobe nf_tables
sudo modprobe nf_conntrack
sudo modprobe nf_defrag_ipv4
sudo modprobe nf_defrag_ipv6
sudo modprobe nf_synproxy_core
Пара полезных sysctl, которые стоит держать включёнными:
sudo sysctl -w net.ipv4.tcp_syncookies=1
sudo sysctl -w net.ipv4.tcp_timestamps=1
sudo sysctl -w net.netfilter.nf_conntrack_max=262144
tcp_timestamps нужно для корректной работы опций synproxy, а увеличение nf_conntrack_max — страховка, но с самим synproxy поток мусора туда обычно не доходит. Для проектов на HTTPS заранее продумайте SSL-сертификаты.
Базовая схема nftables с SYNPROXY
Типовой подход: в таблице inet raw мы помечаем стартовые SYN как notrack, чтобы не расходовать conntrack, а в таблице inet filter включаем сам synproxy для новых соединений на нужные порты.
1) Таблица raw: не отслеживать стартовые SYN
sudo nft add table inet raw
sudo nft add chain inet raw prerouting { type filter hook prerouting priority -300; policy accept; }
# Замените порты на свои сервисы (например, 22, 80, 443)
sudo nft add set inet raw synproxy_ports { type inet_service; flags interval; elements = { 22, 80, 443 } }
# Новые SYN на выбранных портах не попадут в conntrack
sudo nft add rule inet raw prerouting tcp dport @synproxy_ports ct state new tcp flags & syn == syn notrack
Почему приоритет -300? Это «сырое» место конвейера, где решение о трекинге соединения принимается максимально рано.
2) Таблица filter: сам SYNPROXY и базовая политика
sudo nft add table inet firewall
sudo nft add set inet firewall allowed_tcp_ports { type inet_service; flags interval; elements = { 22, 80, 443 } }
sudo nft add chain inet firewall input { type filter hook input priority 0; policy drop; }
# Базовая гигиена
sudo nft add rule inet firewall input ct state established,related accept
sudo nft add rule inet firewall input iif lo accept
sudo nft add rule inet firewall input ip protocol icmp accept
sudo nft add rule inet firewall input ip6 nexthdr ipv6-icmp accept
sudo nft add rule inet firewall input ct state invalid drop
# SYNPROXY на нужных портах (настраиваемые опции)
sudo nft add rule inet firewall input tcp dport @allowed_tcp_ports ct state new tcp flags & syn == syn counter synproxy mss clamp-to-pmtu wscale 7 timestamp sack-perm
# Отсекать «новые не-SYN» (ломаное рукопожатие)
sudo nft add rule inet firewall input tcp dport @allowed_tcp_ports ct state new tcp flags & syn != syn drop
# Пропускать установленные соединения на эти порты
sudo nft add rule inet firewall input tcp dport @allowed_tcp_ports ct state established accept
Пояснения к опциям synproxy:
mss clamp-to-pmtu— подстроит MSS под реальный MTU пути, снижая риск чёрных дыр из-за фрагментации.wscale 7— разумное значение окна для большинства интернет-сетей.timestampиsack-perm— современный TCP работает с таймстемпами и SACK, включаем.
Проверим, что правила на месте:
sudo nft list ruleset
Расширенный вариант: проходящий трафик и проксирующие узлы
Если ваш VDS — не конечный хост, а L4-прокси или роутер, включайте synproxy на цепочках prerouting и forward для транзитного трафика. Пример минимального варианта:
sudo nft add chain inet firewall forward { type filter hook forward priority 0; policy drop; }
# Разрешаем ESTABLISHED/RELATED и локальные правила
sudo nft add rule inet firewall forward ct state established,related accept
# SYNPROXY на проходящих соединениях к бекендам
sudo nft add rule inet firewall forward tcp dport @allowed_tcp_ports ct state new tcp flags & syn == syn synproxy mss clamp-to-pmtu wscale 7 timestamp sack-perm
# Остальное — по вашей политике (ACL, NAT и т.д.)
Убедитесь, что маршрутизация симметрична: «туда» и «обратно» проходит через один и тот же VDS. В противном случае synproxy не сможет корректно завершить рукопожатие.
Мониторинг и отладка под нагрузкой
Быстрые метрики
# Состояния TCP
ss -s
ss -ant state syn-recv sport = :443
# Статистика conntrack
conntrack -S
# Счётчики правил nftables (ищите counter у synproxy-правила)
sudo nft list chain inet firewall input

Тестовый трафик
Для воспроизводимого теста используйте отдельный узел в том же дата-центре или ближайший по RTT и тестируйте только на собственных ресурсах в разрешённой среде. Пара примеров:
# Имитация SYN flood (только в изолированной тестовой сети и на своих хостах)
hping3 -S -p 443 --flood 203.0.113.10
# Нагрузка валидными запросами параллельно «шуму»
wrk -t4 -c256 -d60s https://203.0.113.10/
Что должно произойти:
- Число
SYN-RECVна целевом порту не растёт лавинообразно. conntrackпрактически не увеличивается во время «мусора».- Реальные клиенты продолжают подключаться с предсказуемой задержкой.
Пакетный след
# Наблюдаем рукопожатия
sudo tcpdump -nni eth0 'tcp port 443 and (tcp[tcpflags] & (tcp-syn|tcp-ack) != 0)'
Вы увидите, что машина отвечает на входящие SYN своим SYN+ACK. Поддельные источники обычно не отвечают корректным ACK, и такие сессии не попадают в стек.
Практические советы по производительности
- Несмотря на эффективность,
synproxy— это вычисления в ядре. Включайте его прицельно по портам, где есть реальный риск или публичный доступ. - Отдельные цепочки и
set-ы для портов удешевляют lookup и упрощают поддержку. - Проверяйте MTU по пути:
mss clamp-to-pmtuсильно помогает против «чёрных дыр» у клиентов за PPPoE/туннелями. - Не забывайте про общее здоровье сети: профиль TCP (
bbr/cubic), корректныеrmem/wmem, доступный CPU на прерывания. - Сделайте конфигурацию устойчивой к перезагрузке: сохраните правила в
/etc/nftables.confи включите сервисnftables.
Частые ошибки и как их избегать
- Конфликт с другими слоями firewall. Если у вас уже работает high-level менеджер, убедитесь, что правила не перетираются. Можно держать
synproxyв отдельной таблице, а менеджер — в своей. - Забыли включить notrack в raw. Без этого вы выиграете меньше: начальные
SYNпродолжат засорятьconntrack. - Слишком общие правила. Не включайте
synproxyдля всего TCP: вы лишь повысите нагрузку на ядро без выгоды. Выбирайте только публичные порты. - Асимметричная маршрутизация. На проксирующих узлах проверьте пути туда/обратно, иначе рукопожатие развалится.
- Не открыли ICMP. Полезные ICMP-сообщения нужны для нормальной работы PMTU. Не рубите ICMP «в ноль».
Сравнение с альтернативами
- Rate limit на L7 (веб-серверы, WAF). Хорош как дополнительная ступень, но поздно в конвейере и дороже по CPU.
- TCP syncookies. Дёшево и сердито, но включается при переполнении очереди и не защищает
conntrack. - ACL на уровне провайдера или аппаратные фильтры. Максимально эффективно и желательно, но не всегда доступно.
synproxy— локальная защита, которой вы управляете сами.
Мини-чеклист внедрения
- Загрузить модули
nf_tables,nf_conntrack,nf_synproxy_core. - Включить
tcp_syncookiesиtcp_timestamps. - Создать таблицу
inet raw, добавитьnotrackдля стартовыхSYNна нужных портах. - Создать таблицу
inet firewallс базовой политикой, включитьsynproxyна целевых TCP-портах. - Проверить счётчики, протестировать нагрузкой, зафиксировать базовые метрики.
- Документировать и автоматизировать: Ansible, cloud-init, unit-тесты конфигурации.
FAQ
Нужно ли включать synproxy за CDN?
Если IP известен (например, для SSH) или CDN не «передавливает» весь ваш TCP, то synproxy полезен. Он защищает хостовую плоскость и conntrack, даже если часть трафика приходит мимо CDN.
Какие порты включать в первую очередь?
SSH, 80/443 для публичных сайтов и API. Дальше — SMTP/IMAP, если хост принимает почту извне. Остальное — по профилю угроз.
Как понять, что synproxy реально работает?
Смотрите счётчик у правила synproxy, число SYN-RECV в ss, размер conntrack под атакой. Реальные клиенты должны подключаться стабильно, даже если на вход идёт поток SYN.
Вредит ли это производительности обычных клиентов?
Незначительно. Дополнительная работа на рукопожатии окупается предотвращением очередей и конкуренции за ресурсы. На современных ядрах накладные расходы минимальны.
Если вы двигаете инфраструктуру на nftables вместе с контейнерами, пригодятся разборы: Firewall для Docker: iptables vs nftables и безопасная миграция и Динамические наборы и блок-листы в nftables.
Итоги
synproxy в связке с nftables — простой и эффективный способ защитить ваш VDS от TCP SYN flood. Он «подхватывает» рукопожатие у границы, экономит conntrack и CPU, не мешая реальным пользователям. Включайте его адресно на публичных TCP-портах, проверяйте симметрию маршрутов и наблюдайте счётчики. В большинстве сценариев это даст вам серьёзный запас прочности даже при очень шумной сети.


