Many administrators face this dilemma when configuring Fail2Ban: choosing between catching rapid brute force attempts (with short findtime) or catching slow, distributed attacks (with long findtime). Neither approach provides complete protection when used alone.
The solution lies in implementing multiple jail configurations with different time windows. Here's how to set this up in your jail.local
file:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
[sshd-fast]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
findtime = 600
maxretry = 3
bantime = 86400
[sshd-slow]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
findtime = 3600
maxretry = 5
bantime = 86400
The sshd-fast
jail catches rapid attacks with a 10-minute window, while sshd-slow
covers longer intervals. The different maxretry values prevent false positives - slower attacks require more attempts to trigger a ban.
To verify your setup, use these commands:
# Check active jails
sudo fail2ban-client status
# Monitor specific jail
sudo fail2ban-client status sshd-slow
# Test regex matching
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
For more precise detection, create custom filters in /etc/fail2ban/filter.d/
:
[Definition]
failregex = ^%(__prefix_line)s(?:error: PAM: )?Authentication failure for .* from <HOST>
^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>
ignoreregex =
Remember to reload after changes:
sudo systemctl restart fail2ban
When hardening SSH security with Fail2Ban, we often face a dilemma between detection sensitivity and coverage duration. The default configuration requires choosing between:
# Option 1: Sensitive but short window
findtime = 600 # 10 minutes
maxretry = 2
# Option 2: Broad but potentially misses rapid attacks
findtime = 3600 # 1 hour
maxretry = 2
Instead of trying to make one jail do everything, implement multiple jails with different time windows:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
bantime = 86400
[sshd-fast]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
findtime = 600
maxretry = 5
bantime = 86400
[sshd-slow]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
findtime = 3600
maxretry = 2
bantime = 86400
While Fail2Ban doesn't natively support separate scan intervals from findtime, we can achieve similar results through these methods:
Method 1: Aggressive Datepattern Matching
[sshd-aggressive]
findtime = 3600
maxretry = 3
datepattern = %%Y-%%m-%%d %%H:%%M:%%S
# Scan logs more frequently via systemd timer
Method 2: Combine with Logrotate Tweaks
# In /etc/logrotate.d/fail2ban
/var/log/fail2ban.log {
rotate 4
hourly
missingok
notifempty
compress
delaycompress
postrotate
fail2ban-client set logtarget /var/log/fail2ban.log
endscript
}
For maximum control, implement a custom action that checks more frequently:
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = iptables -I fail2ban- 1 -s -j DROP
actionunban = iptables -D fail2ban- -s -j DROP
[Init]
# Custom scanning interval in seconds
scan_interval = 300
After implementation, verify with:
fail2ban-client status sshd
fail2ban-client get sshd findtime
tail -f /var/log/fail2ban.log
Monitor effectiveness by tracking patterns in your auth logs:
grep "Failed password" /var/log/auth.log | awk '{print $1,$2}' | uniq -c