启用Imperva CDN情况下,使用Fail2Ban屏蔽恶意访问

针对 Debian 系统,以及 Imperva CDN 环境,使用“Fail2Ban + Nginx Deny” 的方案。

获取真实IP

使用Imperva时,nginx日志中只有CDN的IP地址,所以首先要获取真实IP。 配置文件在/etc/nginx/conf.d中加入配置文件:

# Imperva (Incapsula) IP Ranges
set_real_ip_from 199.83.128.0/21;
set_real_ip_from 198.143.32.0/19;
set_real_ip_from 149.126.72.0/21;
set_real_ip_from 103.28.248.0/22;
set_real_ip_from 45.64.64.0/22;
set_real_ip_from 185.11.124.0/22;
set_real_ip_from 192.230.64.0/18;
set_real_ip_from 107.154.0.0/16;
set_real_ip_from 45.60.0.0/16;
set_real_ip_from 45.223.0.0/16;
set_real_ip_from 2a02:26f0::/32;

# 告诉 Nginx 真实 IP 藏在哪个 Header 里
# Imperva 官方推荐 Incap-Client-IP,但也支持标准 X-Forwarded-For
# 我们先尝试标准方式,并开启递归搜索

#real_ip_header X-Forwarded-For;
real_ip_header Incap-Client-IP;
real_ip_recursive on;

官方建议使用real_ip_header Incap-Client-IP; 而不是X-Forwared-For。因为后者可能被伪造。

第一步:安装 Fail2Ban

sudo apt update
sudo apt install fail2ban -y
sudo systemctl status fail2ban

第二步:配置 Nginx 黑名单文件

创建一个文件专门存放被封禁的 IP,并让 Nginx 读取它。

  1. 创建黑名单文件

    
    sudo touch /etc/nginx/conf.d/ip_blacklist.conf
    # 设置权限,确保 Nginx 可读
    sudo chmod 644 /etc/nginx/conf.d/ip_blacklist.conf
    
  2. 修改 Nginx 主配置引入该文件: 编辑 /etc/nginx/nginx.conf

    sudo nano /etc/nginx/nginx.conf
    

    http { ... } 代码块内部,添加一行 include 指令:

    http {
        # ... 其他原有配置 ...
    
        # 引入 Fail2Ban 自动生成的黑名单
        include /etc/nginx/conf.d/ip_blacklist.conf;
    
        # ...
    }
    
  3. 测试并重载 Nginx

    sudo nginx -t
    # 如果显示 successful,则重载
    sudo systemctl reload nginx
    

第三步:配置 Fail2Ban 的“动作” (Action)

告诉 Fail2Ban:“封禁 IP 时,不要去动防火墙,而是把 deny IP; 写入刚才那个文件里。”

  1. 创建自定义动作文件:

    sudo nano /etc/fail2ban/action.d/nginx-deny.conf
    
  2. 粘贴以下内容:

   [Definition]
   # 封禁时:追加 deny 规则到文件,并重载 Nginx
   actionban = printf "deny <ip>;\n" >> /etc/nginx/conf.d/ip_blacklist.conf && systemctl reload nginx

   # 解封时:使用 sed 删除对应行,并重载 Nginx
   actionunban = sed -i "/deny <ip>;/d" /etc/nginx/conf.d/ip_blacklist.conf && systemctl reload nginx

Ctrl+O 保存,Ctrl+X 退出。


第四步:配置 Fail2Ban 的“过滤规则” (Filter)

需要告诉 Fail2Ban 如何从日志里识别那些扫描 WordPress 后门的攻击。

  1. 创建过滤规则文件:

    sudo nano /etc/fail2ban/filter.d/nginx-php-scan.conf
    
  2. 粘贴以下内容(可能需要修改,匹配你的日志格式):

   [Definition]
   # 匹配 "Primary script unknown" 错误,Nginx 会自动把 <HOST> 替换为真实 IP
   failregex = ^\s*\[error\] \d+#\d+: \*\d+ FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: <HOST>

   ignoreregex =

第五步:启用监控 (Jail)

最后,将规则和动作组合起来,启用监控。

  1. 创建/编辑本地配置文件(永远不要直接修改 jail.conf):

    sudo nano /etc/fail2ban/jail.local
    
  2. 在文件中添加以下内容:

   [DEFAULT]
   # 忽略你自己的 IP(如果有固定 IP,建议填入,防止误封自己)
   ignoreip = 127.0.0.1/8 ::1

   [nginx-php-scan]
   enabled = true
   # 使用我们刚才定义的 filter
   filter = nginx-php-scan
   # 指定 Nginx 错误日志路径(请确认你的路径是否正确)
   logpath = /var/log/nginx/error.log
   # 使用我们刚才定义的 action (nginx-deny)
   banaction = nginx-deny
   # 600秒(10分钟)内失败 3 次即封禁
   maxretry = 3
   findtime = 600
   # 封禁时间:86400秒 (1天)
   bantime = 86400

第六步:重启并验证

  1. 重启 Fail2Ban

    sudo systemctl restart fail2ban
    
  2. 验证状态: 查看 jail 是否启动成功:

    sudo fail2ban-client status nginx-php-scan
    

    下面应该看到 Currently failedCurrently banned 的统计数据。

  3. 如何手动测试? 可以手动往日志里写入一条模拟攻击记录(小心不要填自己的 IP,填一个假 IP,比如 1.2.3.4):

    # 模拟写入日志
    sudo sh -c 'echo "2026/01/12 16:13:04 [error] 123#123: *1 FastCGI sent in stderr: \"Primary script unknown\" while reading response header from upstream, client: 1.2.3.4, server: test" >> /var/log/nginx/error.log'
    

    重复执行该命令 3 次。

  4. 检查是否生效

    • 检查 Fail2Ban 状态:
      sudo fail2ban-client status nginx-php-scan
      
      应该看到 Banned IP list: 1.2.3.4
    • 检查 Nginx 黑名单文件:
      cat /etc/nginx/conf.d/ip_blacklist.conf
      
      应该能看到 deny 1.2.3.4;
  5. 手动解封(测试用)

    sudo fail2ban-client set nginx-php-scan unbanip 1.2.3.4
    

关键提示

由于你使用了 Imperva,请务必确认 Nginx 的 set_real_ip_fromreal_ip_header 配置已经生效。如果 Nginx 日志里记录的还是 CDN 的 IP,Fail2Ban 就会误封 CDN 节点,导致所有用户无法访问!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注