В наше время возникла необходимость создать программируемый и настраиваемый роутер, который обеспечивал бы доступ в Интернет домашней сети без геополитических ограничений. Поискав среди старых вещей, обнаружил материнскую плату двадцатилетней давности с твердотельными конденсаторами на борту, которая, издав тихий писк, успешно стартовала. Подробности технических характеристик ПК здесь не важны, поскольку передача пакетов процесс не требовательный к мощности "железа". Докупив дополнительную сетевую карту Wi-Fi стандарта 5G и установив Ubuntu 20.04, настроил устройство согласно руководству на данном сайте, дополнительно подключив и настроил поддержку протоколов IKEv2 и SSTP. Всё работало прекрасно вплоть до неожиданного происшествия — произвольного перезагрузки устройства. Изучив лог-файлы системы после инцидента, обнаружил сообщение ядра Linux о подозрительной активности типа TCP flood.

Кратко разберемся с теорией. В протоколе TCP соединение устанавливается следующим образом: клиент отправляет серверу пакет SYN, ожидая подтверждения от сервера. Однако злоумышленники часто злоупотребляют этим механизмом, отправляя огромное количество таких запросов, заставляя систему расходовать вычислительные ресурсы на обработку несуществующих попыток подключения. Стандартно операционная система не ведет учет соединений.

Изучив проблему подробнее, нашёл подходящий инструмент — модуль hashlimit в фаерволе iptables, поставляемый вместе с операционной системой. Этот модуль позволяет отслеживать частоту новых соединений и сообщать о превышениях лимитов в системный лог. До этого момента я уже использовал утилиту Fail2Ban, которая эффективно блокировала атаки на порт SSH (22). Решил расширить её возможности и применить к защите от SYN-flooding атак. Давайте перейдем от теории к практике.

  • Создаем новое правило, которое размещается первым в очереди обработки входящих пакетов:

iptables -I INPUT 1 -i интерфейс -p tcp --syn -m hashlimit --hashlimit 200/sec --hashlimit-burst 100 --hashlimit-mode srcip --hashlimit-name synflood -j LOG --log-prefix "[SYNFLOOD] "

Здесь мы задаем фильтрацию по определенному интерфейсу для протокола TCP, отслеживая запросы на установление связи (--syn). Если частота превышает порог 200 запросов/секунду, запись фиксируется в журнале системы с отметкой [SYNFLOOD]. Фильтрация ведется по источнику (ключ srcip), что позволяет ограничить объем атакующего трафика от конкретного узла.

  • Fail2Ban получает события из журнала и применяет заданные правила блокировки, автоматически создавая цепочку в таблице фильтрации iptables. Далее настраиваем фильтр для Fail2Ban, создадим файл /etc/fail2ban/filter.d/synflood.conf следующего содержания:

[Definition]
failregex = $$SYNFLOOD$$.*SRC=.*PROTO=TCP.*SYN
ignoreregex =

Затем добавляем секцию в конфигурационный файл /etc/fail2ban/jail.local:

[synflood]
enabled = true
filter = synflood
action = iptables-allports[name=synflood, protocol=tcp]
backend = systemd
maxretry = N # Количество превышений порога за указанный период findtime (целое число)
findtime = 5m
bantime = 1d

Таким образом, Fail2Ban автоматически блокирует узлы, превысившие установленный предел запросов на подключение и разблокирует через время bantime. Перезапускаем службу systemctl restart Fail2Ban.service и проверяем статус systemctl status Fail2Ban.service. Для мониторинга и точной настройки смотрим вывод команды iptables -L -n. После внесения изменений в правила, для удобства управления, создал простой bash-скрипт, позволяющий снять блокировки со всех узлов одновременно, :

#!/bin/bash

jails=$(sudo fail2ban-client status | grep 'Jail list' | cut -d':' -f2 | tr -d ' ' | tr ',' ' ')

for jail in $jails; do
  echo "Обрабатываю jail: $jail"
  banned_ips=$(sudo fail2ban-client status $jail | grep 'Banned IP list' | cut -d':' -f2)
  for ip in $banned_ips; do
    if [[ $ip != "" ]]; then
      echo "Разбаниваю IP $ip из $jail"
      sudo fail2ban-client set $jail unbanip $ip
    fi
  done
done

echo "Все заблокированные IP были освобождены."

Система работает стабильно уже около трех месяцев, периодически проверяю список забаненных адресов — случайных пользователей среди них не наблюдалось. Надеюсь, мой опыт окажется полезным!

Всем успехов!

Комментарии (8)


  1. pae174
    02.09.2025 10:41

    Для этго существует механизм SYN cookies. Блокировать источник флуда по IP на уровне фаерволла это так себе идея по двум причинам:

    • IP адреса источника можно подделать на стороне отправителя. Если вы баните по IP источника SYN сегмента то у скрипткидди появляется отличная возможность, ну например, сделать ваш сервер недоступным для поисковиков или даже для вас самих.

    • При бокировке по IP на уровне фаерволла все же тратится память на хранение таблицы забаненных IP и тратится время на проверку по этой таблице. Еще fail2ban этот живет отдельным процессом, логи писать/читать - затратно это все. SYN cookies не тратит память, но тратит время на генерацию кукиса, но это не много.


    1. xaht88 Автор
      02.09.2025 10:41

      В /etc/sysctl.conf были включены SYN cookies. Это просто одно из решений, мне такой путь показался интересней, с логам и гибче. Правило айпитэбла можно вырубить, а можно перезаписать с DROP.


      1. AVikont
        02.09.2025 10:41

        Каждый студент должен наступить на эти грабли. Учиться на своих ошибках больно, но эффективно.


    1. A1EF
      02.09.2025 10:41

      IP адреса источника можно подделать на стороне отправителя. Если вы баните по IP источника SYN сегмента то у скрипткидди появляется отличная возможность, ну например, сделать ваш сервер недоступным для поисковиков или даже для вас самих.

      Справедливости ради, это не такая уж тривиальная задача, ибо на старте такие пакеты будут порезаны оператором. Конечно, у кого-то uRPF может и не настроен, но в целом, кажется, это очень ограниченная в реализации атака.


      1. pae174
        02.09.2025 10:41

        Пару месяцев назад CloudFlare написали в своем бложике об успешно отраженной супер-пупер атаке на 7.3 терабита в секунду, в которой по часть трафика была со спуфнутых IP. Так что это до сих пор работает.

        В 2016 у них же в блоге был анализ спуфнутых адресов. Там помимо всего прочего утверждалось, что до CloudFlare доходят сегменты, якобы посланные с адресов приватных блоков, мультикаст, и даже 127/8, который вот никогда вообще не ожидаешь снаружи, но он там есть.


        1. A1EF
          02.09.2025 10:41

          Спору нет, что работает. Вопрос масштабов. Условные десять лет назад такое было куда проще провернуть. В международных сценариях (случай CF) и через десять лет всегда найдётся вариант влить поддельные src IP. Но я вижу что риск атак, например, с ломаных IoT устройств куда более весом и реален, а в перспективе станет ещё больше. Просто не будет иметь смысла искать оператора, через которого можно лить подозрительный трафик, когда можно устроить настоящий DDoS со "стопитсот" легитимных адресов, которые ещё фиг зафильтруешь.


  1. ki11j0y
    02.09.2025 10:41

    А ещё можно прикрыться с помощью GEOIP от половины интернета.


  1. eyeDM
    02.09.2025 10:41

    В наше время на смену iptables пришёл nftables.

    Плюс, раз уж статья преподносится как метод защиты от DDOS, можно ожидать, что блокируемых IP будет много. ОЧЕНЬ много. А большие списки IP лучше блокировать средствами ipset.

    Плюс, если принимается решение, что некий IP является источником сетевого флуда, есть смысл резать ему все протоколы, а не только TCP.