OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

Fail2ban + nftables sets: быстрые баны, persistency и производительность

Разбираем практичную связку fail2ban и наборов nftables для SSH и веб‑сервисов: проектирование сетов, persistency после перезагрузки, кастомный banaction, проверка и отладка. Даём готовые конфиги, советы по производительности и разбор типичных ошибок.
Fail2ban + nftables sets: быстрые баны, persistency и производительность

Fail2ban давно стал стандартной реакцией на переборы паролей и агрессивные запросы. С переходом экосистемы Linux на nftables логичнее всего направлять баны не в цепочки с десятками отдельных правил, а в наборы (sets). Это экономнее, быстрее и удобнее для отладки. Ниже — пошагово, как связать fail2ban с nftables sets, обеспечить сохранность банов при перезагрузке (persistent), разделить IPv4/IPv6, избежать конфликтов с другими firewall-инструментами и повысить устойчивость к шумным атакам.

Зачем именно nftables sets для fail2ban

Главная идея — хранить забаненные IP в наборах и проверять попадание трафика в эти наборы одной-двумя строчками правил. Это даёт:

  • Производительность: одна проверка набора дешевле десятков правил на каждый IP.
  • Простоту: баны добавляются и снимаются командами add/delete element без перестройки цепочек.
  • Чистоту ruleset: меньше динамики в самих правилах, вся динамика укладывается в содержимое набора.
  • Гибкость: отдельные наборы для SSH, HTTP(S), API. Можно использовать разные bantime и политику для каждого jail.
  • Удобство отладки: быстро посмотреть, кто именно в бане, и на сколько.

Важно: fail2ban не предназначен для отражения объёмных DDoS-атак на канальном уровне. Его сила — быстро «гасить» нежелательные IP на уровне хоста: переборы SSH, агрессивные боты к вебу, словари к /wp-login.php и прочее.

Архитектура: таблица, цепочка, наборы

Базовая схема, которой будем придерживаться:

  • Таблица inet filter — единая для IPv4 и IPv6.
  • Цепочка input с policy drop: в начале — проверки наборов на блокировку, затем allow для нужных портов и состояний.
  • Наборы: по два на каждый сервис — ...-v4 (тип ipv4_addr) и ...-v6 (тип ipv6_addr).

Почему два набора? Тип элементов должен соответствовать семейству адресов. Универсальный тип addr поддерживается не на всех комбинациях ядра/инструментов, поэтому в проде безопаснее явно разделить v4/v6.

Если вы поднимаете защиту на новом сервере, удобнее начинать на облачном VDS: там проще управлять ядром, системными службами и firewall без ограничений общего хостинга.

Схема наборов nftables с отдельными сетами для IPv4 и IPv6

Базовый ruleset nftables (с наборами для fail2ban)

Создадим или обновим /etc/nftables.conf. Пример минималистичного, но безопасного ruleset:

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
  set f2b-ssh-v4 {
    type ipv4_addr
    timeout 12h
    comment "Fail2ban SSH v4"
  }
  set f2b-ssh-v6 {
    type ipv6_addr
    timeout 12h
    comment "Fail2ban SSH v6"
  }
  set f2b-http-v4 {
    type ipv4_addr
    timeout 1h
    comment "Fail2ban HTTP v4"
  }
  set f2b-http-v6 {
    type ipv6_addr
    timeout 1h
    comment "Fail2ban HTTP v6"
  }

  chain input {
    type filter hook input priority 0; policy drop

    # Падение по наборам — строго в начале
    ip saddr @f2b-ssh-v4 drop
    ip6 saddr @f2b-ssh-v6 drop
    ip saddr @f2b-http-v4 drop
    ip6 saddr @f2b-http-v6 drop

    # Базовая гигиена
    ct state established,related accept
    iif lo accept
    ip protocol icmp accept
    ip6 nexthdr ipv6-icmp accept

    # Разрешаем нужные сервисы
    tcp dport 22 accept
    tcp dport { 80, 443 } accept

    # Остальное по умолчанию drop полисой
  }
}

Пояснения:

  • Сроки timeout задают дефолт для элементов набора. Fail2ban при добавлении IP может переопределять таймаут под конкретный бан.
  • Строки drop по наборам должны стоять раньше любых accept портов, иначе бан не сработает.
  • Запуск и автозагрузка: systemctl enable --now nftables. Проверка: nft list ruleset.

Кастомный action для fail2ban: добавляем IP в nftables sets

Стандартный action для nftables умеет сам создавать цепочки и наборы. В этой статье пойдём от обратного: наборы и правила создаём в /etc/nftables.conf, а fail2ban только добавляет/удаляет элементы. Так проще контролировать firewall и добиться persistency.

Создадим файл /etc/fail2ban/action.d/nftset.conf с минимальным набором команд:

[Definition]
# Проверяем, что наборы существуют (v4 и v6)
actioncheck = nft list set <nft_family> <nft_table> f2b-<name>-v4 >/dev/null 2>&1
              nft list set <nft_family> <nft_table> f2b-<name>-v6 >/dev/null 2>&1

# При старте/остановке jail ничего не делаем — наборы живут в /etc/nftables.conf
actionstart =
actionstop  =

# Бан/разбан: пытаемся и в v4, и в v6. Одна из команд может вернуться с ошибкой — игнорируем.
actionban = nft add element <nft_family> <nft_table> f2b-<name>-v4 { <ip> timeout <bantime>s } 2>/dev/null || true
            nft add element <nft_family> <nft_table> f2b-<name>-v6 { <ip> timeout <bantime>s } 2>/dev/null || true

actionunban = nft delete element <nft_family> <nft_table> f2b-<name>-v4 { <ip> } 2>/dev/null || true
              nft delete element <nft_family> <nft_table> f2b-<name>-v6 { <ip> } 2>/dev/null || true

[Init]
nft_family = inet
nft_table = filter

Что здесь важно:

  • Используем подстановки fail2ban: <name> — имя jail, <bantime> — время бана в секундах, <ip> — адрес.
  • Мы не создаём наборы из action — они уже определены в /etc/nftables.conf.
  • Команды для v4/v6 дублируются; «лишняя» команда завершится ошибкой и будет проигнорирована благодаря || true.

Jail-файлы: SSH и Nginx

Включим jail под SSH с использованием нашего действия. Создадим /etc/fail2ban/jail.d/sshd-nftset.local:

[sshd]
enabled = true
backend = systemd
port = 22
banaction = nftset[name=ssh]
maxretry = 5
findtime = 10m
bantime = 12h
ignoreip = 127.0.0.1/8 ::1

Для Nginx можно включить, к примеру, nginx-http-auth или nginx-botsearch. Создадим /etc/fail2ban/jail.d/nginx-nftset.local:

[nginx-botsearch]
enabled = true
banaction = nftset[name=http]
port = http,https
findtime = 10m
bantime = 1h
maxretry = 10

Под ваш стек фильтры и набор правил могут отличаться. Главное — обеспечить, чтобы в nftables были наборы f2b-http-v4/f2b-http-v6 и строки drop для них стояли первыми в chain input. Для комплексной настройки смотрите также руководство по базовой защите SSH и firewall для VDS и как защитить /wp-login.php c fail2ban и 2FA.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Persistency: что переживёт перезагрузку

Есть два аспекта persistency:

  1. Правила и наборы — живут в /etc/nftables.conf. Сервис nftables загрузит их при старте.
  2. Содержимое наборов (элементы). По умолчанию, содержимое наборов не сохраняется автоматически между перезагрузками. Однако fail2ban хранит баны в своей базе и при рестарте банит адреса заново, выполняя actionban для активных записей.

Чтобы восстановление работало гарантированно:

  • Проверьте, что fail2ban стартует после nftables (обычно так и есть из коробки).
  • Убедитесь, что banaction указывает на наш nftset.
  • Установите dbpurgeage больше, чем ваш типовой bantime (например, 1d или 7d), чтобы записи не удалялись из базы слишком рано.

Если требуется именно «заморозить» текущее содержимое наборов (без участия fail2ban), используйте регулярный дамп nft list ruleset с последующим восстановлением. Но практически в проде проще и безопаснее полагаться на штатный механизм fail2ban.

Проверка и отладка

  • Статус fail2ban и список jail: fail2ban-client status.
  • Статистика по конкретному jail: fail2ban-client status sshd.
  • Что в наборах nftables: nft list set inet filter f2b-ssh-v4, nft list set inet filter f2b-ssh-v6.
  • Принудительный бан для проверки: fail2ban-client set sshd banip 198.51.100.10.
  • Снятие бана: fail2ban-client set sshd unbanip 198.51.100.10.

Если при старте jail видите ошибки actioncheck, это почти всегда означает, что соответствующие наборы не созданы или названы по‑другому. Сверьте имена наборов в /etc/nftables.conf и аргумент name=... в banaction.

Экран со статусом jail fail2ban и выводом содержимого набора nftables

Производительность и масштабирование

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

  • Размер наборов. Тысячи записей — нормально. Десятки тысяч — тоже, но следите за памятью и временем сборки мусора в ядре (GC для timeout-наборов).
  • Порядок правил. Проверки наборов — первее, чем любые разрешающие правила сервисов.
  • Сроки бана. Не завышайте bantime до недель без необходимости — наборы будут расти, а поведение частично-блуждающих ботов меняется.
  • IPv6. Не забывайте про v6-наборы. Сегодня много сканеров уже в IPv6.

Противодействие шумным атакам

Fail2ban — это реакция на события в логах. При «шуме» (например, лавина 404/401/invalid-login) он эффективен. Но от объёмных DDoS (L3/L4) он не спасёт. Что можно добавить на уровне nftables:

  • Rate-limit на новые TCP SYN к отдельным портам (ограничивает бурст коннектов).
  • Сдерживание UDP-флуда простыми лимитами.
  • SYN cookies/SYN proxy там, где уместно (с пониманием нагрузки и совместимости).

Всё это работает совместно с наборами fail2ban: сначала быстро фильтруем злонамеренных клиентов по наборам, затем применяем лимиты для оставшихся. Для HTTPS позаботьтесь о корректном сертификате — при необходимости можно оформить SSL-сертификаты.

Миграция с iptables на nftables

Типичные шаги:

  1. Переведите системный firewall на nftables. Убедитесь, что инструменты iptables не перехватывают управление (режим iptables-nft совместим, но лучше чистый nft).
  2. Опишите таблицу inet filter и наборы в /etc/nftables.conf.
  3. Создайте action.d/nftset.conf и переведите jail на banaction = nftset.
  4. Понаблюдайте за логами и списком элементов в наборах; после убедитесь, что старые iptables-правила отключены.

Важно не мешать в одном хосте несколько управляющих систем firewall (например, firewalld, ufw и собственный nftables). Выберите одну и придерживайтесь её.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Типичные ошибки и как их избежать

  • Баны не работают. Строки drop по наборам стоят после accept портов. Решение: поднимите проверки наборов в самый верх.
  • IPv6 не банится. Нет v6-наборов или нет соответствующих строк ip6 saddr @set drop.
  • После перезагрузки баны исчезли. Fail2ban стартовал до nftables или dbpurgeage слишком мал, и записи удалены из базы. Исправьте порядок и настройки.
  • Конфликт с firewalld/ufw. Две системы одновременно управляют таблицей/цепочками. Оставьте одну.
  • Случайный flush ruleset. При экспериментировании не перезатирайте наборы с продовыми данными. Держите рабочий конфиг в VCS и применяйте обновления командой nft -f /etc/nftables.conf.

Расширения: общие блок-листы и «рецидивисты»

Подход с наборами отлично масштабируется:

  • Сделайте отдельные наборы под «рецидивистов» (например, f2b-recidive-v4/v6) с большим timeout и включите jail recidive в fail2ban.
  • Импортируйте собственные статичные блок-листы в наборы и проверяйте их в том же chain input.
  • Для почтовых сервисов смотрите также jail для Postfix и Dovecot — принципы с наборами те же.

Порядок запуска сервисов и резервная копия правил

Проверьте зависимости systemd: nftables.service должен стартовать раньше fail2ban.service. Для надёжности держите актуальную копию правил: периодически сохраняйте nft list ruleset в артефакты CI или в репозиторий с конфигурацией. Для отката достаточно применить сохранённый файл.

Итоги

Связка fail2ban + nftables sets даёт быстрые и управляемые баны без раздувания ruleset. Наборы легко отлаживаются, хорошо переживают перезагрузки при корректном порядке запуска и настройках базы fail2ban, а также масштабируются под разные сервисы и политики. В результате вы получаете компактный, быстрый и предсказуемый firewall-слой, который заметно снижает шум от переборов и агрессивных ботов, не усложняя эксплуатацию.

Поделиться статьей

Вам будет интересно

DMARC: rua, p=quarantine и p=reject — как включить без потери доставляемости OpenAI Статья написана AI (GPT 5)

DMARC: rua, p=quarantine и p=reject — как включить без потери доставляемости

Пошаговое руководство для админов: что такое DMARC и агрегированные отчёты rua, как правильно оформить rua=mailto, собрать XML-отч ...
Floating IP для Nginx: keepalived VRRP, healthcheck и быстрый failover OpenAI Статья написана AI (GPT 5)

Floating IP для Nginx: keepalived VRRP, healthcheck и быстрый failover

Пошагово строим отказоустойчивый фронтенд на двух серверах Nginx с общим floating IP. Настраиваем keepalived (VRRP), HTTP health c ...
SYNPROXY в nftables: защита VDS от TCP SYN flood пошагово OpenAI Статья написана AI (GPT 5)

SYNPROXY в nftables: защита VDS от TCP SYN flood пошагово

SYN flood забивает TCP-очереди и conntrack на VDS, съедая CPU. SYNPROXY в nftables отсекает мусор до TCP-стека. Разбираем принцип, ...