When executing fail2ban-client status sshd
, you'll notice it only shows currently banned IPs, not the historical total. This is because Fail2ban maintains different lists:
# Current bans (active in iptables)
fail2ban-client status sshd | grep "Banned IP list"
# Historical bans (all recorded actions)
sudo zgrep 'Ban' /var/log/fail2ban.log*
Here are three reliable ways to view all banned IPs:
# 1. Check fail2ban log history
sudo grep -h "Ban " /var/log/fail2ban.log* | awk '{print $NF}' | sort | uniq
# 2. Query fail2ban database directly
sudo sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 \
"SELECT ip FROM bans WHERE jail='sshd';"
# 3. Inspect iptables/nftables directly
sudo iptables -L f2b-sshd -n --line-numbers | grep REJECT
Fail2ban's behavior depends on your jail configuration. In /etc/fail2ban/jail.local
:
[sshd]
enabled = true
bantime = 1d
maxretry = 5
findtime = 10m
The bantime
parameter controls duration. Use -1
for permanent bans.
To see IPs currently blocked at firewall level:
# For iptables:
sudo iptables -n -L f2b-sshd
# For nftables:
sudo nft list chain ip f2b-sshd
If IPs appear unbanned but keep trying:
- Check service restart times with
systemctl status fail2ban
- Verify log file permissions:
ls -l /var/log/auth.log
- Test regex patterns with
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
For real-time monitoring, create this script (fail2ban-monitor.sh
):
#!/bin/bash
watch -n 5 'echo "=== Currently Banned ===";
fail2ban-client status sshd | grep -A 10 "Banned IP list";
echo "=== Historical Bans ===";
sudo sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 \
"SELECT ip,timeofban FROM bans WHERE jail=\"sshd\"" 2>/dev/null'
Make executable with chmod +x fail2ban-monitor.sh
For regular email reports of banned IPs:
# Add to /etc/crontab
0 * * * * root /usr/bin/fail2ban-client status sshd | mail -s "Fail2ban Report" admin@example.com
When running fail2ban-client status sshd
, you might notice a discrepancy between "Total banned" count and the actual displayed IPs. This occurs because fail2ban only shows currently active bans, not historical ones. The command output shows:
Status for the jail: sshd
|- Filter
| |- Currently failed: 1
| |- Total failed: 81
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 2
|- Total banned: 8
`- Banned IP list: 218.65.30.61 116.31.116.7
To see all banned IPs (including expired bans), you need to check fail2ban's log files:
sudo grep 'Ban' /var/log/fail2ban.log
# For more detailed information:
sudo zgrep 'Ban' /var/log/fail2ban.log*
The proper way to check iptables for fail2ban bans is:
sudo iptables -L f2b-sshd -n --line-numbers
# Or for newer systems using nftables:
sudo nft list chain ip f2b-sshd
For better tracking, add these lines to your jail.local:
[sshd]
enabled = true
logpath = %(sshd_log)s
maxretry = 3
# Add these for persistent ban tracking
persistent = true
# Keep bans for 1 year (in seconds)
bantime = 31536000
Here's a bash script to generate a comprehensive ban report:
#!/bin/bash
echo "=== Currently Banned IPs ==="
fail2ban-client status sshd | grep "Banned IP list"
echo -e "\n=== Full Ban History ==="
sudo zgrep 'Ban' /var/log/fail2ban.log* | awk '{print $7}' | sort | uniq -c | sort -n
echo -e "\n=== Recent Unban Events ==="
sudo zgrep 'Unban' /var/log/fail2ban.log* | tail -5
For IPs that keep attacking despite being banned, check if:
- Your bantime is too short (default is 10 minutes)
- The IP is changing (range ban might be needed)
- fail2ban service is properly running
To increase ban time and add range banning:
[DEFAULT]
# Ban for 1 week
bantime = 604800
# Ban entire /24 network after 3 bans
maxretry = 3
ignoreip = 127.0.0.1/8 ::1
# Enable this for range banning
blocktype = DROP
chain = INPUT
action = iptables-allports[name=banall,protocol=all]