使用 Fail2Ban 保护服务器安全

| 分类 security linux  | 标签 Fail2Ban  Nginx  防爬虫  入侵防护 

✅ 什么是 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 纳入多层防御体系中。