Как защитить SSH, WordPress и почту с помощью fail2ban
fail2ban следит за журналами и временно блокирует IP-адреса, которые раз за разом проваливают аутентификацию. В этом руководстве разобрана практическая настройка на Linux-сервере: разумные значения по умолчанию для SSH, отдельный jail для флуда на форму входа WordPress, jail для Postfix и Dovecot, белый список собственных адресов и проверка банов. Руководство рассчитано на тех, кто сам администрирует VPS или выделенный сервер и заглядывает в логи время от времени, а не круглосуточно.
Как устроен jail: фильтр, действие, журнал
Всё в fail2ban строится вокруг jail, а jail состоит всего из трёх связанных частей:
- Журнал: файл или журнал systemd, за которым наблюдает jail, например /var/log/auth.log.
- Фильтр: набор регулярных выражений (failregex), которые определяют, какие строки журнала считать неудачной попыткой и какой IP её сделал.
- Действие: что происходит, когда один IP набирает maxretry неудач за findtime, обычно это правило файрвола, отбрасывающее его трафик на время bantime.
Установка из стандартных репозиториев:
apt install fail2ban # Debian, Ubuntu dnf install fail2ban # AlmaLinux, Rocky
Никогда не правьте /etc/fail2ban/jail.conf напрямую: обновления пакета его перезаписывают. Свои изменения кладите в /etc/fail2ban/jail.local или в отдельные файлы в /etc/fail2ban/jail.d/. Фильтры живут в /etc/fail2ban/filter.d/, по одному файлу на фильтр.
Разумные значения по умолчанию и jail для sshd
Вариант /etc/fail2ban/jail.local, который покрывает большинство одиночных серверов:
[DEFAULT] bantime = 1h findtime = 10m maxretry = 5 bantime.increment = true bantime.maxtime = 1w ignoreip = 127.0.0.1/8 ::1 203.0.113.10 [sshd] enabled = true maxretry = 3 bantime = 2h
Параметр bantime.increment удваивает бан при каждом возвращении того же IP, вплоть до недели, и тихо убирает настойчивых ботов. В Debian 12 и других дистрибутивах без rsyslog файла auth.log нет, поэтому jail для sshd должен читать журнал systemd: добавьте backend = systemd в секцию [sshd]. Перезагрузите конфигурацию и убедитесь, что jail работает:
systemctl reload fail2ban fail2ban-client status sshd
Jail для WordPress против флуда на wp-login.php
Боты долбят wp-login.php и xmlrpc.php POST-запросами. Журнал доступа веб-сервера не сообщает, был ли пароль верным, но это и не нужно: человек ошибается дважды, бот шлёт сотни POST. Создайте /etc/fail2ban/filter.d/wordpress-login.conf:
[Definition]
failregex = ^<HOST> .* "POST /wp-login\.php
^<HOST> .* "POST /xmlrpc\.php
ignoreregex =
Затем сам jail, в файле /etc/fail2ban/jail.d/wordpress.local:
[wordpress-login] enabled = true port = http,https filter = wordpress-login logpath = /var/log/nginx/access.log maxretry = 5 findtime = 5m bantime = 4h
Два предостережения. Во-первых, перед включением проверьте фильтр на реальном журнале и убедитесь, что совпадают только строки с POST:
fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wordpress-login.conf
Во-вторых, если сайт стоит за обратным прокси или CDN, первым полем в журнале будет адрес прокси, и этот jail забанит ваш собственный прокси. Сначала настройте веб-сервер так, чтобы в журнал писался реальный IP клиента из X-Forwarded-For, и только потом включайте jail.
Почта: jail для postfix и dovecot
Для обоих fail2ban поставляется с готовыми фильтрами, свои регулярные выражения не нужны:
[postfix] enabled = true mode = aggressive logpath = /var/log/mail.log [dovecot] enabled = true logpath = /var/log/mail.log
Jail postfix в режиме aggressive ловит ошибки SASL-аутентификации на порту 25 и портах submission, а также клиентов, ломающих протокол SMTP. Jail dovecot покрывает входы по IMAP и POP3. Почтовый перебор обычно медленный и распределённый, одна попытка в час с одного IP - обычное дело, поэтому для этих двух jail имеет смысл поднять findtime до 1h; бюджет попыток остаётся тем же, но под бан попадают и медленные сканеры.
Белый список и проверка банов
Классическая авария с fail2ban: заблокировать самого себя. Внесите каждый адрес, с которого администрируете сервер, в ignoreip в секции [DEFAULT], через пробел, нотация CIDR допустима. Добавьте IP офиса и дома, а также системы мониторинга, которые регулярно опрашивают сервисы.
Повседневная проверка:
fail2ban-client status # список jail fail2ban-client status sshd # счётчики и забаненные IP fail2ban-client set sshd unbanip 198.51.100.7 fail2ban-client set sshd banip 203.0.113.99 grep Ban /var/log/fail2ban.log # история банов
После любого изменения конфигурации выполните fail2ban-client reload и снова посмотрите статус jail: опечатка в фильтре молча даёт jail, который не совпадает ни с одной строкой.
Почему fail2ban не заменяет SSH только по ключам
fail2ban реактивен. Каждый атакующий IP всё равно получает maxretry минус одну бесплатную попытку за каждое окно findtime, а реальные атаки распределённые: ботнет из десяти тысяч адресов получает десятки тысяч попыток подбора пароля в день, не нарушая ни одного лимита. Если парольная аутентификация включена, а пароль слабый, fail2ban лишь замедляет атакующего.
Поэтому относитесь к этим уровням защиты как к взаимодополняющим. SSH только по ключам убирает сам угадываемый секрет; fail2ban после этого убирает шум, лишние затраты CPU на рукопожатия TLS и SSH и закрывает сервисы, где ключи невозможны, например почту и вход в WordPress. В /etc/ssh/sshd_config:
PasswordAuthentication no KbdInteractiveAuthentication no
Вся описанная настройка занимает около получаса на свежем сервере и дальше не требует обслуживания. Если хотите сначала потренироваться на чистой машине, достаточно небольшого VPS: всё описанное спокойно работает в 1 GB RAM, а конфигурацию можно ломать и собирать заново, не трогая продакшен.
Читайте дальше
Готовы начать?
Запустите за минуты или обсудите с инженером, что подходит вашему проекту.