✅ 什么是 Fail2Ban?
Fail2Ban 是一个基于日志分析的入侵防御工具,支持自动封禁恶意 IP,防止暴力破解、扫描器、爬虫攻击等。
🔧 安装 Fail2Ban
Ubuntu / Debian
sudo apt install fail2ban
CentOS / RHEL
sudo yum install epel-release
sudo yum install fail2ban
🧱 Fail2Ban 的结构
类型 | 说明 |
---|---|
jail | 监控目标服务(如 nginx、sshd) |
filter | 匹配攻击行为的正则表达式 |
action | 检测到后如何响应(iptables、deny等) |
🧪 示例 1:拦截 Nginx 的爬虫扫描(大量 404)
创建 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]
🧪 示例 2:防止 Basic Auth 暴力破解(401)
Nginx 配置示例:
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]
💡 替代 iptables:使用 nginx deny 文件封禁
适合 Kubernetes、云主机等场景:
[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 配置:
include /etc/nginx/denylist.conf;
error_page 403 /403.html;
location = /403.html {
root /usr/share/nginx/html;
internal;
}
⏱ 剩余封禁时间查看脚本
Fail2Ban 默认无法查看某个 IP 的剩余封禁时间,但可以通过日志结合封禁时间估算。
📄 脚本:fail2ban-ban-remaining.sh
#!/bin/bash
# fail2ban-ban-remaining.sh
# 查询某个 jail 中 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 # 替换为你的配置
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
运行方式:
chmod +x fail2ban-ban-remaining.sh
./fail2ban-ban-remaining.sh nginx-http-auth 1.2.3.4
🧼 永久封禁 & 手动解封
- 永久封禁:
bantime = -1
- 手动解封:
fail2ban-client set nginx-404 unbanip 1.2.3.4
📁 参考
你可以配合 Cloudflare / iptables / kube-router 等防火墙策略,将 Fail2Ban 纳入多层防御体系中。