Fail2ban ставят на сервер, когда тот получает белый IP, но зачастую дальше установки дело не идёт. Получается, что сервис запущен и джейл sshd включен, но конфиг был дефолтный, бан длится по десять минут, логи читаются не из того места, а половина открытых сервисов вообще находится вне поля зрения. Под катом разберу ошибки и покажу настройки. 

Для тех, кто с fail2ban дела не имел, — это демон, который читает логи сервисов, находит в них строки про неудачные попытки входа и после нескольких повторов с одного адреса добавляет этот адрес в файрвол на определённое время. На Debian и Ubuntu ставится стандартно:

sudo apt update

sudo apt install fail2ban

sudo systemctl enable --now fail2ban

После установки первым делом нужно проверить, что сервис вообще стартовал:

sudo systemctl status fail2ban

sudo fail2ban-client status

Если вторая команда показывает только Number of jail: 0, Fail2ban запущен, но пока ничего не защищает. Дьявол, как обычно, в настройках...

Ошибка 1. Дефолтный конфиг считается рабочим

Откройте свежий jail.conf и посмотрите на цифры по умолчанию — maxretry 5, findtime 10 минут, bantime 10 минут. Переведу, если в течение десяти минут ботнет совершил пять попыток подбора, то его отстраняют от входа на десять минут, а потом можно возвращаться (обратите на это внимание, ведь и тут бывают ошибки с maxretry). 

Сейчас ботнеты и не думают долбиться в одну дверь, они перебирают данные по одной-две попытки с адреса в час, и дефолтный findtime раз в десять минут такую атаку может не заметить, ведь каждая попытка выглядит как первая. А если бан всё же случился, через десять минут бот начинает, всё начинается заново, и такая история может длиться вечно.

На основе этого, первое, что нужно сделать на новой машине — это унести параметры в разумные пределы и включить прогрессивный бан, который растит срок с каждым новым нарушением одного и того же адреса:

# /etc/fail2ban/jail.local

[DEFAULT]

maxretry = 3

findtime = 1d

bantime  = 1h

bantime.increment = true

bantime.factor    = 24

bantime.maxtime   = 5w

Три ошибки за сутки дают первый бан на час. Если тот же адрес снова добирается до порога после разблокировки, следующий бан вырастет до суток, затем до двух, четырёх и дальше по экспоненте, пока не упрётся в пять недель.

Ошибка 2. Правки в jail.conf

Классика жанра — настроили все прямо в /etc/fail2ban/jail.conf, а потом получили конфликт с новой версией файла при обновлении пакета. Тут правило простое, jail.conf — файл поставщика, ваши настройки должны жить в jail.local или в отдельных файлах, ведь они перекрывают дефолт: 

sudo nano /etc/fail2ban/jail.d/sshd.local

Туда же можно добавить: 

[sshd]

enabled = true

С помощью второй команды проще понять, что вы поменяли сами, а что приехало из пакета. Проверить, что реально применилось, можно командой:

sudo fail2ban-client -t

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

sudo fail2ban-client --dump-pretty

После этого перезапускаем: 

sudo systemctl restart fail2ban

Ошибка 3. Демон смотрит не в те логи

Самая коварная ошибка — Fail2ban умеет читать события из текстовых файлов и из журнала systemd, и выбор определяется параметром backend. 

На Debian и Ubuntu логи SSH пишутся в /var/log/auth.log, на RHEL-подобных в /var/log/secure, а на системах, где rsyslog не стоит вовсе, обоих файлов просто не существует, sshd пишет только в journald. 

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

sudo fail2ban-client status sshd

Она покажет состояние джейла и статистику срабатываний. А источник событий лучше проверить отдельно: 

sudo fail2ban-client get sshd logpath

sudo fail2ban-client get sshd journalmatch

Если в выводе пустой список файлов или строчки про journal, которых нет, починить это можно явным указанием источника:

[sshd]

enabled = true

backend = systemd

Сами события SSH тоже проверьте отдельно:

journalctl -u ssh -u sshd --since "1 hour ago"

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

Ошибка 4. Docker сводит баны на нет

Если сервисы крутятся в контейнерах, стандартный fail2ban может промахиваться. Тут есть две ситуации.   

Первая проблема в логах — контейнер пишет в stdout/stderr, а дальше место хранения зависит от logging driver Docker. При journald сообщения можно читать через backend = systemd и фильтровать по полям вроде CONTAINER_NAME. При стандартном json-file в systemd journal этих сообщений не будет. Проверяется через:

docker info --format '{{.LoggingDriver}}'

docker inspect --format '{{.HostConfig.LogConfig.Type}}' ИМЯ_КОНТЕЙНЕРА

Вторая в пути пакета — при бэкенде через iptables опубликованные контейнерные порты идут через forwarding и Docker-цепочки, а fail2ban по умолчанию банит в INPUT. В этом случае можно использовать DOCKER-USER вместе с iptables-action, который умеет работать с указанной цепочкой. 

Ошибка 5. Под защитой один SSH или его поменяли

Зачастую в свежем сервере из коробки включен только джейл sshd. Но у fail2ban есть готовые фильтры для Nginx, Postfix, Dovecot и других сервисов, которые включаются с помощью:

[nginx-limit-req]

enabled = true

[postfix]

enabled = true

mode = aggressive

Режим aggressive у postfix-фильтра ловит не только ошибки аутентификации, но и мусорные сессии. Если на сервере живёт WordPress, стоит поднять джейл под него. Про базовую гигиену вокруг я, кстати, уже писал, fail2ban там один из многих.

Если SSH переехал с 22-го порта на 2222, Fail2ban может видеть неудачные логины, но будет блокировать стандартный 22. В этом случае в джейл укажите реальный порт:

[sshd]

enabled = true

backend = systemd

port = 2222

И после перезапуска проверьте:

sudo fail2ban-client status sshd

Если используете nftables, посмотрите и правила:

sudo nft list ruleset

У штатного nftables action Fail2ban используется отдельная таблица f2b-table — цепочка f2b-chain и sets с заблокированными адресами. Точные имена можно переопределять, поэтому лучше смотреть фактический ruleset. 

Ошибка 6. Рецидивисты гуляют свободно

Иногда забаненные ранее боты возвращаются и заново пытаются попасть в систему. Fail2ban умеет с такими работать через джейл recidive, который читает собственный лог fail2ban: 

[recidive]

enabled   = true

logpath   = /var/log/fail2ban.log

banaction = %(banaction_allports)s

bantime   = 1w

findtime  = 1d

maxretry  = 3

Но есть правила — во-первых, увеличивая bantime свыше суток, увеличьте и dbpurgeage в fail2ban.local, иначе база забудет старые нарушения. Во-вторых, держите loglevel ниже DEBUG, иначе recidive будет учитывать собственный шум. 

Ошибка 7. Fail2ban вместо ключей

Если на SSH открыт вход по паролю, против целевой атаки с подбором fail2ban бессилен. От брутфорса лучше использовать комплексную защиту:

  • вход только по ключам,

  • PermitRootLogin no,

  • PasswordAuthentication no.

Также держите у себя прописанный ignoreip со своим статическим адресом, иначе однажды вы сами забанитесь:

[DEFAULT]

ignoreip = 127.0.0.1/8 ::1 203.0.113.15

Текущий список исключений проверяйте через сам Fail2ban:

sudo fail2ban-client get sshd ignoreip

Ошибка 8. Бан не в тот файрвол

Fail2ban сам пакеты не фильтрует, он вызывает выбранный banaction, поэтому выясните, соответствует ли он файрволу. В актуальной конфигурации для Debian он по умолчанию использует nftables, но лучше проверить:

iptables -V

sudo nft list ruleset

Поддержку IPv6 тоже смотрите отдельно. Штатные actions Fail2ban для iptables и nftables умеют работать и с IPv6, но иногда сервер закрыт по IPv4 и при этом остаётся доступным по IPv6 из-за конфига файрвола.

Ошибка 9. Regex проверяется на проде

С кастомными сервисами всё ещё веселее. Если вы нашли в интернете failregex = .*Failed.*<HOST>.* и хотите перезапустить Fail2ban, то так делать не стоит. Первое — regex может не совпасть с вашим форматом лога. Второе — если пользователь способен подставить произвольный текст туда, откуда regex затем вытащит <HOST>, атакующий может заставить Fail2ban заблокировать чужой IP. В связи с этим сначала проверьте:

sudo fail2ban-regex /var/log/myapp/auth.log /etc/fail2ban/filter.d/myapp.conf

Если работаете через systemd journal:

sudo fail2ban-regex systemd-journal sshd

Смотрите не только на количество Matched, но и Missed. Иногда фильтр идеально ловит один вид ошибки и полностью пропускает другой.

Ошибка 10. Fail2ban банит proxy

В случае, если nginx или приложение стоит за HAProxy, Cloudflare, ingress-контроллером или другим reverse proxy, в журнале может оказаться именно IP-адрес прокси. Fail2ban увидит пять неудачных попыток и заблокирует его. После этого доступ к сайту потеряют ваши пользователи. 

Здесь сначала нужно понять, какой адрес реально попадает в лог:

tail -f /var/log/nginx/access.log

или:

journalctl -f -u nginx

И если сервис всё-таки работает за прокси, настройте корректное получение реального IP-адреса устройства и убедитесь, что доверяете XFF или PROXY protocol-у. 

Как проверить, что защита живая

Сначала настройте:

# /etc/fail2ban/jail.d/sshd.local

[DEFAULT]

bantime = 30m

findtime = 10m

maxretry = 5

bantime.increment = true

bantime.factor = 2

bantime.maxtime = 1d

ignoreip = 127.0.0.1/8 ::1

[sshd]

enabled = true

backend = systemd

port = 22

Если SSH работает на другом порту, меняем его. После этого:

sudo fail2ban-client -t

sudo systemctl restart fail2ban

sudo fail2ban-client status

sudo fail2ban-client status sshd

Затем фильтр проверяйте на реальном логе, без запуска демона:

sudo fail2ban-regex systemd-journal sshd

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

sudo fail2ban-client status

sudo fail2ban-client status sshd

Финальный тест проводите с другой машины или через мобильную сеть — сделайте столько неудачных попыток входа, сколько задано в maxretry, в пределах findtime, и проверьте появление адреса в списке банов и в правилах файрвола. Разбанить себя после эксперимента можно без перезапуска:

sudo fail2ban-client set sshd unbanip ВАШ_IP

И последнее, смотрим:

sudo nft list ruleset

Если что-то из этой цепочки не сработало, возвращайтесь к разделам про бэкенд и action. Когда защита работает, раз в месяц всё равно прогоняйте сервер на предмет того, что она могла пропустить. Об этом рассказал тут. 

Пишите в комментариях, на какие ошибки в Fail2ban натыкались вы, и случался ли у вас самобан. Что делали в этих случаях?

© 2026 ООО «МТ ФИНАНС»

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