✅ What is Fail2Ban?
Fail2Ban is a log-based intrusion prevention tool. It automatically scans log files (such as Nginx, SSH, etc.), detects suspicious behaviors like failed logins or 404 attacks, and blocks offending IPs via iptables
or other firewall actions.
🔧 Install Fail2Ban
Ubuntu / Debian
sudo apt install fail2ban
CentOS / RHEL
sudo yum install epel-release
sudo yum install fail2ban
🧱 Core Components
Type | Description |
---|---|
jail | The service to monitor (e.g. sshd, nginx) |
filter | Regex rules to match malicious patterns |
action | How to respond to a match (ban IP, write file) |
🧪 Example 1: Blocking Web Scanners (Multiple 404s)
Filter: /etc/fail2ban/filter.d/nginx-404.conf
[Definition]
failregex = ^<HOST> -.*"(GET|POST).*(HTTP|HTTPS)/1.[01]" 404
ignoreregex =
Jail: /etc/fail2ban/jail.d/nginx-404.conf
[nginx-404]
enabled = true
filter = nginx-404
logpath = /var/log/nginx/access.log
maxretry = 10
findtime = 600
bantime = 3600
action = iptables[name=nginx-404, port=http, protocol=tcp]
🧪 Example 2: Prevent Brute-Force on Basic Auth (401)
Nginx configuration:
location /admin/ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
}
Filter: /etc/fail2ban/filter.d/nginx-http-auth.conf
[Definition]
failregex = ^<HOST> -.*"(GET|POST).*(HTTP|HTTPS)/1.[01]" 401
ignoreregex =
Jail: /etc/fail2ban/jail.d/nginx-http-auth.conf
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 3600
action = iptables[name=nginx-auth, port=http, protocol=tcp]
💡 Alternative: Use deny
in Nginx (no iptables)
For containers or Kubernetes environments, you can write bans directly into an Nginx file:
[Definition]
actionban = /bin/bash -c 'echo "deny <ip>;" >> /etc/nginx/denylist.conf && nginx -s reload'
actionunban = /bin/bash -c 'sed -i "/deny <ip>;/d" /etc/nginx/denylist.conf && nginx -s reload'
Nginx config:
include /etc/nginx/denylist.conf;
error_page 403 /403.html;
location = /403.html {
root /usr/share/nginx/html;
internal;
}
⏱ Remaining Ban Time Viewer
Fail2Ban doesn’t provide a direct command to view remaining ban time. The following script estimates it using the log and ban duration:
📄 Script: fail2ban-ban-remaining.sh
#!/bin/bash
# fail2ban-ban-remaining.sh
# Show remaining ban time for an IP
if [ $# -ne 2 ]; then
echo "Usage: $0 <jail-name> <ip-address>"
exit 1
fi
JAIL="$1"
IP="$2"
LOG="/var/log/fail2ban.log"
BANTIME=3600 # Update this to match your jail config
ban_time=$(grep "Ban $IP" "$LOG" | grep "\[$JAIL\]" | tail -1 | awk '{print $1" "$2}')
if [ -z "$ban_time" ]; then
echo "No ban record found for $IP in jail $JAIL"
exit 2
fi
ban_epoch=$(date -d "$ban_time" +%s 2>/dev/null)
now_epoch=$(date +%s)
elapsed=$(( now_epoch - ban_epoch ))
remaining=$(( BANTIME - elapsed ))
if [ $remaining -le 0 ]; then
echo "Ban expired for $IP"
else
echo "IP $IP was banned at $ban_time"
echo "Remaining ban time: $remaining seconds ($((remaining/60)) min)"
fi
Usage:
chmod +x fail2ban-ban-remaining.sh
./fail2ban-ban-remaining.sh nginx-http-auth 1.2.3.4
🧼 Permanent Ban and Manual Unban
- Permanent ban:
bantime = -1
- Unban manually:
fail2ban-client set nginx-http-auth unbanip 1.2.3.4
📁 References
You can integrate Fail2Ban with firewalls like iptables
, nftables
, or Kubernetes ingress controllers to form a layered defense strategy.