使用 Fail2Ban + Nginx 阻止网页爬虫(生产指南)

发布: (2025年12月17日 GMT+8 11:36)
7 min read
原文: Dev.to

Source: Dev.to

Ajit Kumar

Web scraping 和激进的爬虫会悄悄消耗你的基础设施预算,增加服务器负载,并在你的产品尚未准备好扩展时就暴露 API。

如果你正在运行自托管堆栈(EC2 / VPS),使用 NginxDjango(Gunicorn)Next.js 前端,Fail2Ban 是你可以部署的 最高 ROI、零成本 防御之一。

本文解释了 Fail2Ban 是什么、为何要使用它、如何配置、它在你的架构中的位置以及如何在生产环境中验证其工作

1. 问题:为何爬取成本高

即使:

  • 您的产品仍在开发中
  • 注册用户很少
  • 流量看起来“低”

爬虫和机器人也能:

  • 每分钟访问成千上万的 URL
  • 产生大量 404403 响应
  • 反复下载静态资源
  • 消耗出站带宽(AWS 数据传输 不是免费 的)

传统的速率限制有帮助,但 机器人会适应

我们需要一种机制:

  • 从行为中学习
  • 自动阻止违规者
  • 在操作系统/防火墙层面工作
  • 零成本

这正是 Fail2Ban 大显身手的地方。

2. 什么是 Fail2Ban?

Fail2Ban 是一个日志监控入侵防御工具。

从高层次来看,它:

  • 监视日志文件(例如 Nginx 访问日志)
  • 使用正则表达式匹配模式
  • 跟踪 IP 触发这些模式的频率
  • 使用防火墙规则临时封禁滥用的 IP

一旦被封禁:

  • 流量永远不会到达 Nginx
  • CPU 和带宽使用量会立即下降

Fail2Ban 的特点是:

  • 轻量级
  • 经受过实战考验
  • 在生产环境中被广泛使用

3. Fail2Ban 在技术栈中的位置

典型架构

Client (User / Bot)
        |
        v
    Nginx (Reverse Proxy)
        |
        +--> Frontend (Next.js)
        |
        +--> Backend (Gunicorn + Django)

Fail2Ban 在请求路径之外运行

Nginx access.log
        |
        v
     Fail2Ban
        |
        v
   Firewall (iptables / nftables)

一旦 IP 被封禁,请求将在到达 Nginx 之前 被丢弃。

4. 安装

在 Ubuntu 上:

sudo apt update
sudo apt install fail2ban -y

验证安装:

fail2ban-client --version

示例输出

Fail2Ban v1.0.x

5. 理解 Nginx 日志(非常重要)

Fail2Ban 依赖 日志格式

典型的 Nginx 访问日志行如下所示:

203.0.113.45 - - [17/Dec/2025:01:57:51 +0000] "GET /unknown HTTP/1.1" 404 548 "-" "SomeBot/1.0"

关键部分

  • IP 地址
  • HTTP 方法
  • 路径
  • 状态码(404403 等)

我们将检测 重复的 403 / 404 响应,这是一种强烈的爬取和探测指示。

6. 创建自定义 Fail2Ban 过滤器

创建一个新的过滤器文件:

sudo nano /etc/fail2ban/filter.d/nginx-scraping.conf

示例过滤器配置

[Definition]

# Match repeated forbidden or not‑found responses
failregex = ^ - .* "(GET|POST|HEAD).*" (403|404)

ignoreregex =

这段配置的作用

  • 捕获客户端 IP
  • 匹配任何 GETPOSTHEAD 请求
  • 仅在 403404 响应时触发
  • 忽略成功的请求(如 200301 等)

这可以最大程度地减少误报。

7. 创建 Jail 配置

编辑或创建 jail.local

sudo nano /etc/fail2ban/jail.local

示例 jail 配置

[nginx-scraping]
enabled  = true
filter   = nginx-scraping
logpath  = /var/log/nginx/access.log
maxretry = 30
findtime = 60
bantime  = 3600

各设置含义

设置目的
enabled激活该 jail
filter应用的正则规则
logpathNginx 访问日志所在路径
maxretry允许的失败次数
findtime统计失败的时间窗口(秒)
bantime封禁时长(秒)

效果: 如果一个 IP 在 60 秒内 触发 30 次 403/404 响应,则会被封禁 1 小时

8. 测试过滤器(关键步骤)

在重新启动 Fail2Ban 之前,先使用真实日志测试你的正则表达式:

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-scraping.conf

预期输出

  • 数百甚至数千条匹配
  • 没有语法错误

这确认了:

  • 正则表达式的正确性
  • 日志格式的兼容性

9. 重启并验证 Fail2Ban

重启 Fail2Ban:

sudo systemctl restart fail2ban

检查活动的监狱:

sudo fail2ban-client status

示例输出

Jail list: nginx-scraping, sshd

检查监狱详情:

sudo fail2ban-client status nginx-scraping

示例输出

Currently failed: 58
Currently banned: 2
Banned IP list: 203.0.113.10 198.51.100.42

这表明已检测到失败并且违规的 IP 已被封禁。

10. 手动解封(如有需要)

如果合法的 IP 被封禁:

sudo fail2ban-client unban <IP>

示例

sudo fail2ban-client unban 203.0.113.10

11. 为什么它在生产环境中表现良好

优势

  • 零基础设施成本
  • 内核级阻塞
  • 无需更改应用代码
  • 兼容任何后端(Django、Node、Go 等)
  • 降低 AWS 数据传输费用

限制

  • 不是实时行为分析
  • 需要良好的日志卫生
  • 应作为速率限制的补充(而非替代)

12. 推荐的后续增强

一旦运行:

  • 添加 recidive jail(对重复违规者实施更长时间的封禁)
  • 将前端和 API jail 分离
  • 与 Nginx 限流相结合
  • 在 Nginx 层面添加 User‑Agent 过滤

Fail2Ban 在分层防御中最为有效。

最后思考

如果您正在运行自托管的堆栈并为出站带宽付费,Fail2Ban 是您可以部署的最快速收益之一

它具有:

  • 简单
  • 可靠
  • 生产验证

最重要的是——它在后台静默运行,同时保护您的资源。

Back to Blog

相关文章

阅读更多 »