fail2ban на большинстве production-серверов настроен по-минимуму — sshd jail, и всё. А между тем инструмент способен на большее: банить ботов, сканеры, WordPress-брут, почтовых спамеров. Разберёмся, как настроить полноценный фильтр за пару часов.
Плюс важный совет: как не заблокировать себя, свою CI, свой Cloudflare — самая частая проблема с fail2ban.
Как fail2ban устроен
Демон fail2ban мониторит логи (nginx, sshd, mail и т.д.) по регулярным выражениям. При превышении порога попыток за время-окно — вызывает action (обычно iptables/nftables drop на IP на N секунд).
Ключевые понятия:
- Jail — правило: что мониторить + фильтр + action.
- Filter — regex, определяющий «плохую» строку в логе.
- Action — что делать (обычно ban через iptables).
- Findtime — окно, за которое считаются попытки.
- Maxretry — сколько попыток можно за findtime.
- Bantime — насколько заблокировать.
Базовый конфиг: sshd
Файл — не редактируйте /etc/fail2ban/jail.conf. Создавайте /etc/fail2ban/jail.local:
# /etc/fail2ban/jail.local
[DEFAULT]
# Сколько банить (10 мин обычно; для сильно настырных увеличьте)
bantime = 1h
findtime = 10m
maxretry = 5
# Игнорируем свои IP и Cloudflare
ignoreip = 127.0.0.1/8 ::1 \
203.0.113.42 \
173.245.48.0/20 103.21.244.0/22 \
103.22.200.0/22 103.31.4.0/22 \
141.101.64.0/18 108.162.192.0/18 \
190.93.240.0/20 188.114.96.0/20 \
197.234.240.0/22 198.41.128.0/17 \
162.158.0.0/15 104.16.0.0/13 \
104.24.0.0/14 172.64.0.0/13 131.0.72.0/22
# Уведомления — куда шлём (при желании)
destemail = [email protected]
sender = [email protected]
action = %(action_)s
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = systemdСписок Cloudflare-подсетей обновляется — держите cloudflare.com/ips-v4 актуальным через cron. Иначе новый CF-диапазон приведёт к бану легитимного трафика.
Jail для nginx-401/403 (сканеры)
Стандартный nginx-http-auth — банит только Basic Auth брут. Дополним: любые массовые 401/403/404 (сканеры путей).
# /etc/fail2ban/jail.local — добавить:
[nginx-badbots]
enabled = true
port = http,https
filter = nginx-badbots
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 5m
bantime = 24h
[nginx-404-scanner]
enabled = true
port = http,https
filter = nginx-404-scanner
logpath = /var/log/nginx/access.log
maxretry = 20
findtime = 5m
bantime = 6h
# Файл /etc/fail2ban/filter.d/nginx-404-scanner.conf:
# [Definition]
# failregex = ^<HOST> .* "[A-Z]+ .*" 404 .*$
# ignoreregex = ^<HOST> .* "[A-Z]+ /(favicon\.ico|robots\.txt)" 404Jail для WordPress брута
WordPress-логин (/wp-login.php, /xmlrpc.php) — типовая цель. Специальный jail:
# /etc/fail2ban/jail.local:
[wordpress-login]
enabled = true
port = http,https
filter = wordpress-login
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 5m
bantime = 6h
# /etc/fail2ban/filter.d/wordpress-login.conf:
# [Definition]
# failregex = ^<HOST> .* "POST /wp-login\.php HTTP.*" 200
# ^<HOST> .* "POST /xmlrpc\.php HTTP.*" 200Postfix / Dovecot
Если крутите свою почту — обязательные jail:
[postfix-sasl]
enabled = true
port = smtp,465,submission
filter = postfix-sasl
logpath = /var/log/mail.log
maxretry = 3
findtime = 10m
bantime = 24h
[dovecot]
enabled = true
port = imap,imaps,pop3,pop3s
filter = dovecot
logpath = /var/log/mail.log
maxretry = 5
findtime = 10m
bantime = 24hОбход Cloudflare — реальный IP
Если фронт стоит за Cloudflare, все IP в логе — CF-адреса. Fail2ban будет банить CF (плохо!), и злоумышленники всё равно пройдут.
Решение: nginx должен писать реальный IP из X-Forwarded-For. Проверьте, что в конфиге nginx:
# /etc/nginx/nginx.conf в http {}
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
# ... остальные диапазоны Cloudflare
real_ip_header CF-Connecting-IP;
log_format combined_real '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
access_log /var/log/nginx/access.log combined_real;Мониторинг и не-забанить-себя
Проверить активные баны:
fail2ban-client status
fail2ban-client status sshd
fail2ban-client status nginx-404-scanner
# Разбанить IP
fail2ban-client set sshd unbanip 1.2.3.4
# Логи fail2ban
tail -f /var/log/fail2ban.logОбязательно добавьте ignoreip для CI-сервисов (GitHub Actions), Uptimerobot IP, своего офиса. Иначе первая же нагрузочная проверка выкосит их.