Skip to content
EN
← Все статьи

fail2ban: установка, настройка джейлов и защита от брутфорса SSH и веб-форм

Коротко. fail2ban читает логи сервисов, считает неудачные попытки входа с одного IP и на время добавляет этот адрес в правила firewall. Ставится через apt, настраивается в файле jail.local, а не в jail.conf. Ключевые параметры — maxretry, findtime, bantime и ignoreip. На современных Ubuntu логи sshd лежат в journald, поэтому джейлу нужен backend systemd, иначе он молча не сработает.

Что fail2ban делает и чего не делает

fail2ban — это демон, который следит за текстовыми логами (или журналом systemd), ищет в них строки, подходящие под регулярное выражение фильтра, и, если с одного IP-адреса за окно findtime набралось maxretry совпадений, вызывает действие: обычно добавление правила DROP или REJECT в firewall на время bantime. По истечении bantime правило снимается. Всё. Больше fail2ban ничего не делает.

Из этого следуют неприятные, но важные ограничения, которые стоит понимать до внедрения.

  • Это не firewall. fail2ban не закрывает порты и не задаёт политику доступа. Он лишь добавляет временные правила в уже существующий firewall (iptables, nftables, ufw, firewalld). Если у вас порт СУБД торчит наружу, fail2ban не поможет — нужен базовый фильтр пакетов и разбор открытых портов.
  • Это не защита от распределённого брутфорса. Современный ботнет делает 2–3 попытки с каждого из десятков тысяч адресов. Порог maxretry никогда не срабатывает, а если и срабатывает, вы забаните один адрес из пула. Против такого сценария работает не fail2ban, а отключение парольной аутентификации и лимиты на уровне приложения.
  • Это не WAF. fail2ban не разбирает тело запроса, не понимает SQL-инъекции и не проверяет payload. Он видит только то, что сервис сам записал в лог.
  • Это реактивная мера. Первые maxretry попыток всегда проходят. Если пароль подобрался с третьей попытки при maxretry = 5, бан бесполезен.
  • Он бессилен без логов. Если сервис не пишет неудачные входы или пишет их в формате, который не ловит фильтр, джейл будет висеть с нулевым счётчиком и создавать ложное ощущение защиты.

fail2ban — это способ убрать фоновый шум и снизить нагрузку на sshd, а не заменить нормальную аутентификацию. Ключи вместо паролей, PasswordAuthentication no и закрытые наружу служебные порты дают на порядок больше, чем любая настройка джейлов.

Схема работы fail2ban: лог сервиса, фильтр с регулярным выражением, счётчик попыток и правило блокировки в firewall
Цепочка fail2ban: строка в логе → фильтр → счётчик в окне findtime → действие в firewall на время bantime

Установка fail2ban на Ubuntu и Debian

Пакет есть в основных репозиториях обоих дистрибутивов, отдельные репозитории подключать не нужно.

sudo apt update
sudo apt install fail2ban

# версия и статус демона
fail2ban-client version
systemctl status fail2ban

# что уже включено «из коробки»
sudo fail2ban-client status

В Debian и Ubuntu пакет кладёт файл /etc/fail2ban/jail.d/defaults-debian.conf, в котором джейл sshd уже включён. То есть после установки минимальная защита SSH обычно работает сразу — но проверить это надо руками, а не поверить на слово (см. раздел про backend ниже).

Если вы работаете с systemd-журналом, полезно доустановить биндинги Python к journald — без них backend systemd может не подняться:

sudo apt install python3-systemd
sudo systemctl restart fail2ban
sudo journalctl -u fail2ban -n 50 --no-pager

Раскладка файлов после установки:

  • /etc/fail2ban/fail2ban.conf — настройки самого демона: уровень логирования, сокет, база банов, dbpurgeage.
  • /etc/fail2ban/jail.conf — эталонное описание всех джейлов. Не трогать.
  • /etc/fail2ban/jail.d/*.conf — фрагменты конфигурации, подключаются после jail.conf.
  • /etc/fail2ban/filter.d/*.conf — фильтры, то есть регулярные выражения.
  • /etc/fail2ban/action.d/*.conf — действия: как именно банить (iptables, nftables, отправка письма, вызов API).
  • /var/lib/fail2ban/fail2ban.sqlite3 — база активных банов, благодаря ей баны переживают перезапуск демона.
  • /var/log/fail2ban.log — собственный лог; на него опирается джейл recidive.

jail.local, jail.d и ключевые параметры

Почему нельзя править jail.conf

jail.conf принадлежит пакету. При любом обновлении fail2ban через apt менеджер пакетов увидит изменённый conf-файл и либо перезапишет его, либо вывалит диалог о конфликте конфигурации, либо оставит .dpkg-dist рядом. В любом сценарии вы теряете либо свои правки, либо новые дефолты пакета.

fail2ban читает конфигурацию слоями: сначала jail.conf, затем jail.local, затем всё из jail.d/ в алфавитном порядке. Более поздний слой переопределяет более ранний, причём по отдельным параметрам, а не по секции целиком. Поэтому в jail.local достаточно перечислить только то, что вы меняете.

sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
[DEFAULT]
# ваши доверенные адреса: локалка, офис, VPN, чекеры мониторинга
ignoreip = 127.0.0.1/8 ::1 203.0.113.0/24
bantime  = 1h
findtime = 10m
maxretry = 5
# растущий бан: повторные нарушители сидят дольше
bantime.increment = true
bantime.factor    = 2
bantime.maxtime   = 7d
banaction = nftables-multiport

[sshd]
enabled  = true
mode     = aggressive
maxretry = 4
bantime  = 1d
EOF

sudo fail2ban-client -t          # проверка синтаксиса без применения
sudo systemctl reload fail2ban

Секция [DEFAULT] задаёт значения для всех джейлов; в секции конкретного джейла они переопределяются. Отдельные файлы в jail.d/ удобны, когда конфигурацию раскатывает Ansible или Puppet: один сервис — один файл, без конфликтов при слиянии.

Как подбирать bantime, findtime, maxretry и ignoreip

Смысл параметров простой: если с одного IP за findtime набралось maxretry совпадений фильтра, адрес блокируется на bantime.

  • maxretry. Для SSH с ключами — 3–4: легитимный пользователь с правильным ключом вообще не даёт неудачных попыток. Для веб-формы входа, где люди реально забывают пароль, — 5–10, иначе завалите поддержку заявками. Учитывайте, что один заход браузера может дать несколько строк в логе.
  • findtime. Окно наблюдения. Слишком маленькое (1–2 минуты) пропускает медленный перебор «по одной попытке в минуту». Разумный диапазон — 10–60 минут. Помните: чем шире окно, тем больше памяти и тем выше шанс поймать человека, который весь день путается в паролях.
  • bantime. Час — нормальный старт. Вечный бан (bantime = -1) выглядит соблазнительно, но раздувает таблицу правил firewall до десятков тысяч записей и рано или поздно ловит легитимный адрес, который вы забудете разбанить. Правильный ответ — не вечный бан, а bantime.increment: каждый следующий бан того же адреса длиннее предыдущего.
  • ignoreip. Список адресов и подсетей, которые не банятся никогда. Сюда обязательно попадают ваша рабочая сеть, VPN, адреса внутренних чекеров и балансировщиков. Формат — через пробел, поддерживаются CIDR и (в свежих версиях) DNS-имена. Параметр ignoreself = true, включённый по умолчанию, дополнительно защищает собственные адреса сервера.

Правило подбора: сначала ставьте мягкие пороги и смотрите статистику неделю. Агрессивный maxretry = 2 на публичном сайте — это не безопасность, а генератор инцидентов «клиент не может войти».

Backend: systemd, auto и подводный камень с journald

Параметр backend определяет, откуда джейл берёт события: из текстового файла или из журнала systemd.

  • auto — fail2ban сам выбирает механизм слежения за файлом: pyinotify, если доступен, иначе периодический опрос. Ключевое слово — файл. Значение auto не означает «сам найдёт логи где угодно».
  • polling — принудительный опрос файла по таймеру. Медленнее и прожорливее, но работает там, где inotify недоступен (некоторые контейнеры, сетевые ФС).
  • systemd — чтение journald напрямую через API. В этом режиме logpath игнорируется, а фильтрация записей задаётся директивой journalmatch.

Теперь самая частая причина «поставил fail2ban, а он не банит». Исторически sshd писал в /var/log/auth.log через rsyslog, и дефолтный джейл рассчитан именно на это. В свежих установках Ubuntu rsyslog может отсутствовать: журналирование целиком отдано systemd-journald, файл /var/log/auth.log не создаётся вовсе. Джейл при этом либо падает с ошибкой о недоступном логе, либо, если файл существует, но пуст (например, остался после апгрейда), тихо работает с нулевым счётчиком.

# есть ли вообще текстовый лог аутентификации
ls -l /var/log/auth.log 2>/dev/null || echo "нет auth.log — логи в journald"

# видит ли journald попытки входа
journalctl -u ssh.service --since "-1h" | grep -i "failed password" | tail

# что говорит сам fail2ban при старте
sudo journalctl -u fail2ban --since "-10m" --no-pager | grep -iE "error|warn|found"

Если логи в журнале — переводим джейл на backend systemd:

sudo tee /etc/fail2ban/jail.d/sshd-systemd.local > /dev/null <<'EOF'
[sshd]
enabled      = true
backend      = systemd
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd
maxretry     = 4
bantime      = 1d
EOF

sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Обратите внимание на имя юнита: в Debian и Ubuntu это ssh.service, во многих RPM-дистрибутивах — sshd.service. Ошибка в journalmatch не вызывает падения — джейл просто не увидит ни одной строки. Проверять надо через fail2ban-regex (см. ниже), а не по отсутствию ошибок в логе.

Признак молчащего джейла: в выводе fail2ban-client status sshd строка «Total failed» равна нулю, хотя journalctl показывает десятки «Failed password» за последний час. Это не «атаки прекратились», это неверный источник логов.

Сравнение двух источников событий для fail2ban: текстовый файл auth.log и журнал systemd-journald
Backend auto следит за файлом, backend systemd читает журнал; при отсутствии rsyslog первый вариант не увидит ничего

Джейл sshd и другие типовые джейлы

Джейл sshd — базовый и почти всегда достаточный минимум. У фильтра sshd есть режимы (mode), которые меняют набор регулярных выражений: normal ловит неудачные пароли и ошибки аутентификации, ddos — обрывы соединений и «пустые» коннекты без попытки логина, aggressive — оба набора сразу, включая обращения с невалидными пользователями и неподдерживаемыми методами. На публичном сервере aggressive обычно оправдан, на сервере с самописными скриптами, которые часто рвут SSH-сессии, — рискован.

ДжейлЧто ловитГде логmaxretrybantime
sshdподбор паролей, вход несуществующими пользователями, аномальные обрывы соединений/var/log/auth.log или journald (ssh.service)3–51 час — 1 сутки
nginx-http-authподбор логина и пароля в HTTP Basic Auth/var/log/nginx/error.log3–51–6 часов
nginx-botsearchперебор путей: админки, .env, бэкапы, чужие CMSerror.log, при желании access.log5–101 сутки
nginx-limit-reqсрабатывания limit_req, то есть превышение частоты запросов/var/log/nginx/error.log1010 минут — 1 час
postfix, postfix-saslподбор SMTP-пароля, попытки релея/var/log/mail.log или journald3–51 час — 1 сутки
recidiveадреса, которые уже банились несколькими джейлами/var/log/fail2ban.log3–51 неделя и больше

Джейл recidive заслуживает отдельного внимания: он читает не лог сервиса, а собственный лог fail2ban и банит тех, кто уже получал бан несколько раз за сутки. Это дешёвый способ отправить упорных ботов в долгую блокировку, не поднимая порог для обычных пользователей.

[recidive]
enabled  = true
logpath  = /var/log/fail2ban.log
banaction = %(banaction_allports)s
findtime = 1d
maxretry = 4
bantime  = 4w

Действие banaction_allports блокирует адрес не на конкретном порту, а целиком — для рецидивистов это разумно.

fail2ban и nginx: готовые джейлы и свой фильтр

С веб-сервером есть нюанс: большинство штатных nginx-фильтров читают error.log, потому что именно туда nginx пишет отказы Basic Auth и срабатывания limit_req. Коды ответа 401, 403 и 429 в чистом виде живут в access.log, и для них нужен свой фильтр.

[nginx-http-auth]
enabled  = true
port     = http,https
logpath  = /var/log/nginx/error.log
maxretry = 4
bantime  = 6h

[nginx-botsearch]
enabled  = true
port     = http,https
logpath  = /var/log/nginx/error.log
maxretry = 6
bantime  = 1d

[nginx-limit-req]
enabled  = true
port     = http,https
logpath  = /var/log/nginx/error.log
findtime = 5m
maxretry = 20
bantime  = 1h

Джейл nginx-limit-req имеет смысл только вместе с директивами limit_req_zone и limit_req в конфигурации nginx: без них в error.log нечего ловить. Связка «nginx ограничивает частоту, fail2ban банит самых упорных» — рабочая двухступенчатая схема, подробнее о её проектировании — в материале про стратегии ограничения частоты запросов и о методах защиты от DDoS.

Свой фильтр в filter.d и проверка через fail2ban-regex

Допустим, нужно банить адреса, которые массово получают 401 и 429 на API. Пишем фильтр под стандартный combined-формат access.log.

sudo tee /etc/fail2ban/filter.d/nginx-4xx-api.conf > /dev/null <<'EOF'
[Definition]
failregex = ^<HOST> \S+ \S+ \[[^]]+\] "(GET|POST|PUT|PATCH|DELETE) /api/[^"]*" (401|403|429)
ignoreregex =
datepattern = ^[^\[]*\[({DATE})
EOF

Ключевые правила написания фильтра:

  • <HOST> — обязательный маркер: именно из этой группы fail2ban достаёт IP-адрес. Ровно один на выражение.
  • Регулярка должна быть якорной (^) и максимально узкой. Широкое выражение вида .*401.* поймает строку, где 401 — это часть размера ответа или User-Agent, и забанит вам живого клиента.
  • ignoreregex — исключения, которые проверяются после failregex. Удобно, чтобы вывести из-под бана служебные пути вроде /api/health.
  • Все фильтры лежат в filter.d/, а джейл ссылается на них по имени файла без расширения.

Теперь главное — проверка. fail2ban-regex прогоняет фильтр по реальному логу и показывает, сколько строк совпало и как разобралась дата.

# фильтр против файла
fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx-api.conf

# штатный sshd-фильтр против системного журнала
fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.conf

# проверка одной строки (быстрая отладка регулярки)
fail2ban-regex '198.51.100.7 - - [12/Mar/2026:10:00:01 +0300] "POST /api/login HTTP/1.1" 401 12' \
  /etc/fail2ban/filter.d/nginx-4xx-api.conf

# подробный разбор: какие строки не подошли
fail2ban-regex --print-all-missed /var/log/nginx/access.log \
  /etc/fail2ban/filter.d/nginx-4xx-api.conf

В выводе смотрите на две цифры: Lines: ... matched и Missed lines. Ноль совпадений при заведомо наличии атак означает ошибку в регулярке или в формате даты. Отдельная частая проблема — datepattern: если fail2ban не распознал время строки, он либо считает событие устаревшим, либо игнорирует его. В выводе fail2ban-regex это видно по счётчику «ignored by ... date».

Подключаем фильтр джейлом:

[nginx-4xx-api]
enabled  = true
filter   = nginx-4xx-api
port     = http,https
logpath  = /var/log/nginx/access.log
findtime = 5m
maxretry = 25
bantime  = 2h
Схема проверки собственного фильтра fail2ban: строка лога, регулярное выражение с маркером HOST, разбор даты и результат совпадения
fail2ban-regex показывает и совпадения по failregex, и корректность разбора даты — оба пункта обязательны

fail2ban-client: статус, разбан и как не забанить себя

Весь оперативный контроль — через fail2ban-client, который общается с демоном по unix-сокету.

# список активных джейлов
sudo fail2ban-client status

# детали одного джейла: счётчики и список забаненных
sudo fail2ban-client status sshd

# разбан конкретного адреса
sudo fail2ban-client set sshd unbanip 198.51.100.7

# разбан во всех джейлах сразу
sudo fail2ban-client unban 198.51.100.7
sudo fail2ban-client unban --all

# ручной бан (например, по данным из внешнего источника)
sudo fail2ban-client set sshd banip 198.51.100.7

# добавить адрес в исключения на лету, без перезапуска
sudo fail2ban-client set sshd addignoreip 203.0.113.10

# перечитать конфигурацию без потери активных банов
sudo fail2ban-client reload
sudo fail2ban-client reload sshd

Теперь про самую популярную аварию — самобан администратора. Сценарий типовой: вы правите джейл, ошибаетесь в фильтре, он начинает ловить обычные успешные подключения, и через минуту ваш IP оказывается в DROP. SSH-сессия при этом чаще всего сохраняется (established-соединение уже разрешено), но новая не установится.

  • Всегда добавляйте свой адрес в ignoreip до включения новых джейлов. Если адрес динамический — добавьте подсеть провайдера или адрес VPN.
  • Держите вторую открытую SSH-сессию на время экспериментов. Это бесплатная страховка: даже если новая аутентификация заблокирована, из старой сессии можно выполнить unban.
  • Имейте запасной канал доступа: консоль в панели хостинга, KVM или serial console. Если сервер живёт в облаке — например, в Selectel — веб-консоль работает в обход сети и firewall.
  • Проверяйте новый фильтр через fail2ban-regex до включения джейла, а не после.

Если доступ всё-таки потерян и есть только консоль, снимите бан вручную:

# посмотреть, где именно висит правило
sudo nft list ruleset | grep -A5 f2b
sudo iptables -S | grep f2b

# аварийно снять все баны
sudo fail2ban-client unban --all

# крайняя мера — остановить демон и почистить цепочки
sudo systemctl stop fail2ban

Подводные камни: firewall, reverse-proxy, logrotate и IPv6

iptables, nftables и ufw

fail2ban не заменяет firewall, а пишет в него. За способ записи отвечает banaction. Основные варианты: iptables-multiport (классика), nftables-multiport (для систем, где нативный firewall — nftables), ufw, firewallcmd-ipset. Смешивать наборы правил вслепую — плохая идея: если система работает на nftables, а fail2ban пишет через прослойку совместимости iptables-nft, правила попадут в отдельные таблицы, и порядок обработки может оказаться не тем, который вы ожидали.

С ufw есть отдельная тонкость: ufw создаёт собственные цепочки, и правила fail2ban должны вставляться перед разрешающими правилами ufw, иначе бан не сработает. Штатное действие ufw учитывает это, а вот самодельные комбинации — часто нет. После настройки всегда проверяйте фактическое состояние правил:

sudo nft list table inet f2b-table 2>/dev/null
sudo iptables -L -n --line-numbers | grep -i f2b
sudo ufw status numbered

Общие принципы укрепления фильтра пакетов и сервисов разобраны в материале про хардненинг веб-сервера.

Reverse-proxy и Cloudflare: банится не тот адрес

Если перед сервером стоит CDN, балансировщик или ещё один nginx, то в логах бэкенда виден IP прокси, а не клиента. fail2ban честно забанит его — и вы отрежете себе весь входящий трафик разом.

Лечится это не в fail2ban, а на веб-сервере: нужно, чтобы $remote_addr восстанавливался из заголовка, который проставляет прокси. Модуль realip подменяет адрес клиента и в access.log, и в записях error.log.

http {
    # подсети, которым доверяем проставление заголовка
    set_real_ip_from 192.0.2.0/24;      # ваш балансировщик
    # для CDN перечислите официальные диапазоны провайдера
    real_ip_header   X-Forwarded-For;
    real_ip_recursive on;
}

Доверять X-Forwarded-For можно только от явно перечисленных в set_real_ip_from подсетей. Если разрешить всем, любой клиент подставит чужой адрес в заголовок и заставит fail2ban забанить произвольный IP — от вашего собственного до адресов поисковых роботов. Механика заголовка и модель доверия разобраны отдельно: заголовок X-Forwarded-For.

Второй нюанс: даже с правильным realip бан на уровне firewall самого сервера бесполезен, если трафик всегда приходит от CDN. Блокировать нужно на стороне CDN — через её API. У fail2ban есть действия для внешних API, но их надёжность зависит от лимитов и доступности этого API.

Ротация логов и сброс счётчиков

logrotate переименовывает access.log в access.log.1 и создаёт пустой файл. fail2ban переоткрывает файл по смене inode и продолжает работу, но исторические строки уезжают в архив. Практические следствия:

  • Если fail2ban перезапускается (обновление пакета, reload сервиса, перезагрузка), он начинает читать актуальный файл. Сразу после ротации файл пустой, и контекст последних попыток теряется — атакующий получает свежие maxretry попыток.
  • Активные баны при этом не теряются: они лежат в sqlite-базе, а срок хранения записей задаёт dbpurgeage в fail2ban.conf.
  • Не ставьте findtime больше периода ротации: окно в сутки при ежедневной ротации будет наполовину «слепым».
  • Для journald проблема не стоит: журнал ротацию по файлам не использует, читается по курсору.

Ограничения при IPv6

Современные версии fail2ban умеют банить IPv6, но с оговорками. Во-первых, нужен banaction, поддерживающий обе версии протокола: nftables работает с inet-таблицей и покрывает оба стека, а классический iptables требует параллельных правил ip6tables. Во-вторых, у провайдера клиент обычно получает целую подсеть /64 и более — бан одного адреса ничего не даёт, атакующий возьмёт следующий из своего же префикса. Часть действий позволяет задать длину префикса для бана, но включать агрессивную блокировку по /64 на публичном сервисе стоит осознанно: под одним префиксом может сидеть много разных пользователей.

Проверить, что джейл вообще видит IPv6, проще всего по фактическому списку банов в fail2ban-client status и по правилам в nftables.

Схема прохождения запроса через CDN и reverse-proxy, где fail2ban на бэкенде видит адрес прокси вместо адреса клиента
За прокси fail2ban банит адрес прокси; реальный IP нужно восстанавливать модулем realip до записи в лог

Как проверить настройку и защищённость сервера

Настройка fail2ban проверяется на двух уровнях: внутри сервера — командами выше, снаружи — тем, что реально видит атакующий.

  • Какие порты вообще торчат наружу. fail2ban защищает только те сервисы, которые вы включили в джейлы, а закрывать лишнее надо firewall'ом. Внешний скан покажет фактическую картину: проверка открытых портов. Если наружу смотрят СУБД, панель управления или отладочный порт — это важнее любых настроек джейлов.
  • Общий скоринг безопасности. Заголовки, TLS, утечки версий и типовые ошибки конфигурации собираются в один отчёт: проверка безопасности сайта. Полезно прогонять после каждого изменения конфигурации веб-сервера.
  • Всплеск отказов и падения. Слишком агрессивные джейлы проявляются как рост 4xx, обрывы и недоступность для части пользователей. Внешний мониторинг доступности с уведомлениями ловит и это, и обратную ситуацию — когда сервер лёг под перебором.
  • Реакция на срабатывания. Настройте действие с уведомлением (штатные action.d с отправкой письма) или заберите события из /var/log/fail2ban.log в вашу систему логов. Молчащий fail2ban — это fail2ban, о состоянии которого вы ничего не знаете.

Если по итогам проверки нашлись признаки уже состоявшейся компрометации, порядок действий описан отдельно: что делать, если сайт взломали.

Частые вопросы

Нужен ли fail2ban, если вход по SSH только по ключам?

Строгой необходимости нет: с PasswordAuthentication no подобрать пароль невозможно. Но джейл всё равно полезен — он убирает фоновый шум ботов, снижает число процессов sshd и объём логов. Ставьте мягкие пороги: задача не защита, а гигиена.

Почему fail2ban показывает Currently banned: 0, хотя атаки идут?

Три основные причины по частоте: джейл читает не тот источник (файл вместо journald), фильтр не совпадает с форматом строк, атакующие адреса попали в ignoreip. Диагностика — fail2ban-client status <jail> и fail2ban-regex по реальному логу.

Можно ли банить навсегда?

Технически да, bantime = -1. На практике лучше bantime.increment = true с ограничением bantime.maxtime: правила firewall не разрастаются бесконечно, а рецидивисты всё равно уходят в блокировку на недели. Вечные баны имеет смысл держать отдельным списком, который вы сознательно ревизуете.

Спасёт ли fail2ban от DDoS?

Нет. При объёмной атаке пакеты доходят до сервера и съедают канал и CPU ещё до того, как что-то попадёт в лог. fail2ban работает после записи в лог, то есть уже после обработки запроса. Против DDoS нужны фильтрация на уровне провайдера или CDN и лимиты на уровне nginx.

Как перенести настройки fail2ban на другой сервер?

Копируйте только свои файлы: jail.local, содержимое jail.d/, собственные фильтры из filter.d/ и действия из action.d/. Копировать jail.conf и базу банов не нужно: первый принадлежит пакету и придёт с ним, вторая специфична для конкретной машины.

Сильно ли fail2ban нагружает сервер?

На типовом VPS расход незаметен, пока джейлов немного и логи не гигантские. Проблемы появляются при широком findtime на очень активных access.log и при десятках тысяч правил в firewall. Лечится сужением окна, переходом на ipset/nftables-множества и джейлом recidive вместо вечных банов.

Чеклист внедрения

  • Пакет установлен, демон включён в автозапуск, fail2ban-client status отвечает.
  • Все правки — только в jail.local и jail.d/; jail.conf не тронут.
  • Свой адрес, VPN и адреса мониторинга внесены в ignoreip.
  • Проверено, откуда реально пишутся логи sshd; при journald выставлены backend = systemd и корректный journalmatch.
  • fail2ban-client status sshd показывает ненулевой счётчик Total failed на публичном сервере.
  • Каждый собственный фильтр прогнан через fail2ban-regex с проверкой совпадений и разбора даты.
  • banaction соответствует реально используемому firewall (iptables / nftables / ufw), правила видны в выводе firewall.
  • За reverse-proxy или CDN настроен realip с явным списком доверенных подсетей.
  • Включён bantime.increment или джейл recidive вместо вечных банов.
  • Есть запасной канал доступа к серверу на случай самобана.
  • Проведён внешний скан портов и проверка безопасности, настроен внешний мониторинг доступности.
  • Отключена парольная аутентификация SSH — главная мера, ради которой fail2ban становится второстепенным.

Проверьте ваш сайт прямо сейчас

Проверить безопасность сайта →
Другие статьи: Безопасность
Безопасность
Правила WAF: написание эффективных политик веб-файрвола
16.03.2026 · 701 просм.
Безопасность
Как проверить сайт на вирусы: 4 уровня проверки и план лечения
01.04.2026 · 502 просм.
Безопасность
Заголовки безопасности: CSP, HSTS, X-Frame-Options и другие
10.03.2025 · 411 просм.
Безопасность
Реестр блокировок РКН в цифрах: анализ 131 000 заблокированных доменов (2026)
26.06.2026 · 395 просм.