首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >用 Nginx 给网站加一道反爬墙:限流、封禁与实战配置

用 Nginx 给网站加一道反爬墙:限流、封禁与实战配置

原创
作者头像
用户12818508
发布于 2026-10-20 17:27:08
发布于 2026-10-20 17:27:08
2620
举报

爬虫对网站的影响,往往不是"一次被爬走多少数据"这么简单。高频请求会挤占服务器资源,让正常用户访问变慢甚至超时;内容被批量抓取后,可能被搬运到其他平台,稀释你的原创价值;更糟的是,一些扫描器会顺手探测漏洞,给安全埋下隐患。在应用层写反爬逻辑当然可以,但请求已经打到后端才被拦截,成本和风险都已经产生。Nginx 作为流量的第一道入口,是设置反爬最经济、最直接的位置。

本文从实战角度出发,介绍几种在 Nginx 层面就能落地的反爬手段:请求频率限制、User-Agent 黑名单、连接数限制和请求方法过滤,并讨论它们的适用边界与组合策略。

为什么把反爬放在 Nginx

Nginx 处理请求的效率远高于后端应用。把明显的恶意流量在 Nginx 层挡掉,有几个直接好处:

  • 省资源:被拦截的请求不会进入 PHP/Java/Node 进程,不消耗数据库连接和 CPU。
  • 响应快:拒绝一个请求只需微秒级,不会拖慢正常用户的响应。
  • 配置集中:规则写在配置文件里,统一管理,不散落在业务代码中。
  • 可快速调整:发现新的恶意特征,改配置重载即可生效,无需发版。

需要说明的是,Nginx 反爬属于"粗粒度过滤",它擅长挡住低成本的通用爬虫和扫描器,但挡不住精心伪装的定向爬取。所以它的定位是第一道防线,而不是全部。

第一道防线:限制请求频率

限流是 Nginx 反爬中最可靠的手段。原因很简单:不管爬虫怎么伪装 IP 和 User-Agent,它高频抓取的行为本身就会暴露。 而正常用户的浏览节奏,天然远低于爬虫。

Nginx 的 limit_req 模块基于漏桶算法实现限流。先在 http 块中定义限流区域:

代码语言:javascript
复制
# 分配 10MB 内存,m.huoyisz.com约可跟踪 16 万个 IP;每个 IP 允许每秒 2 个请求
limit_req_zone $binary_remote_addr zone=one:10m rate=2r/s;

这里用 $binary_remote_addr 而不是 $remote_addr,是因为二进制格式的 IP 占用内存更少,同样的内存能跟踪更多客户端。

然后在 server 或 location 中应用:

代码语言:javascript
复制
location / {
    limit_req zone=one burst=5 nodelay;
    # 其他配置...
}

几个参数的含义:

  • rate=2r/s:平均速率上限。普通浏览通常每秒不到 1 次请求,2r/s 留有一定余量;如果站点资源较重,可以调低到 1r/s。
  • burst=5:允许的突发请求数。用户打开一个页面可能同时加载多个资源,设置 burst 可以避免误伤。
  • nodelay:突发请求立即处理而不是排队延迟。不加这个参数,超出的请求会被延迟处理,可能让正常用户感觉卡顿。

对于 API 接口或下载类路径,可以设置更严格的规则,例如:

代码语言:javascript
复制
location /api/ {
    limit_req zone=one burst=3 nodelay;
}

被限流拒绝的请求默认返回 503。如果希望返回更明确的错误码,可以配置:

代码语言:javascript
复制
limit_req_status 429;

429 Too Many Requests 语义上更准确,也方便前端做提示。

第二道防线:封禁恶意 User-Agent

很多通用爬虫、采集工具和扫描器会在 User-Agent 里直接暴露身份,比如 python-requests、Scrapy、Go-http-client、SemrushBot 等。拦截它们成本极低。

推荐用 map 指令集中管理黑名单,而不是在 location 里堆 if。map 在请求处理早期求值,性能更好,也便于维护:

代码语言:javascript
复制
map $http_user_agent $bad_bot {
    default           0;
    ~*SemrushBot      1;
    ~*AhrefsBot       1;
    ~*python-requests 1;
    ~*Scrapy          1;
    ~*Go-http-client  1;
    ~*curl            1;
}

~* 表示不区分大小写的正则匹配。然后在 server 或 location 中拦截:

代码语言:javascript
复制
if ($bad_bot) {
    return 403;
}

这里有两个细节值得注意。

第一,返回码的选择。 403 会明确告诉对方"你被拒绝了";如果不想给对方任何反馈,可以用 Nginx 特有的 return 444,它会直接关闭连接、不返回任何内容,更省资源,也让对方难以判断拦截原因。

第二,避免误伤。 Googlebot、Bingbot 等搜索引擎爬虫带来的收录和流量通常是需要的,不要把它们加入黑名单。如果站点依赖搜索引擎收录,黑名单要谨慎维护,宁可漏掉一些可疑 UA,也不要误封正规爬虫。

另外,部分爬虫会伪造 User-Agent 冒充浏览器。这时 UA 黑名单就失效了,需要靠限流和行为分析来补位。

补充手段:连接数限制与请求方法过滤

限制单 IP 并发连接数

如果发现爬虫会同时开大量连接,可以加一层连接数限制。先在 http 块中定义:

代码语言:javascript
复制
limit_conn_zone $binary_remote_addr zone=addr:10m;

然后在 server 或 location 中限制:

代码语言:javascript
复制
limit_conn addr 10;  # 每个 IP 最多 10 个并发连接

这个规则对正常用户几乎无感——浏览器对同一域名的并发连接数本身就有上限,10 个已经足够宽松;但对开几百个连接狂抓的爬虫,效果立竿见影。

只放行合理的请求方法

如果网站只用于浏览,可以只放行 GET 和 HEAD,拦截其他方法:

代码语言:javascript
复制
if ($request_method !~ ^(GET|HEAD)$) {
    return 444;
}

这能挡掉一些用非标准方法试探的自动化工具。但要注意,如果你的站点有表单提交、登录等需要 POST 的功能,就不能一刀切,应该按路径分别配置。

组合策略与配置建议

实际部署时,建议把上述手段组合起来,形成分层防御:

代码语言:javascript
复制
http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=2r/s;
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    map $http_user_agent $bad_bot {
        default           0;
        ~*SemrushBot      1;
        ~*python-requests 1;
        ~*Scrapy          1;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            limit_req zone=one burst=5 nodelay;
            limit_conn addr 10;

            if ($bad_bot) {
                return 444;
            }
        }
    }
}

几点实践建议:

  1. 先观察再收紧。 上线限流规则前,先看访问日志统计正常用户的请求频率,把阈值设在合理区间,避免误伤。
  2. 改配置先测试。 修改后先执行 nginx -t 检查语法,再 nginx -s reload 平滑重载,避免配置错误导致服务中断。
  3. 关注日志。 定期分析 access.log 中被拦截的请求来源和 UA,据此调整黑名单和阈值。Nginx 的 limit_req 和 limit_conn 都有对应的日志变量,可以记录触发限流的请求,便于排查。
  4. 对静态资源单独放宽。 图片、CSS、JS 等静态资源的请求频率天然较高,可以为 location ~* \.(jpg|png|css|js)$ 单独设置更宽松的限流,避免误伤正常页面加载。

Nginx 反爬的边界

必须清醒地认识到:Nginx 层面的反爬有明确的天花板。 有经验的爬虫会轮换 IP 池、随机生成 User-Agent、模拟正常浏览间隔,仅靠 IP 和 UA 很难完全防住。限流也只能提高爬取成本,无法彻底阻止分布式低速爬取。

如果内容价值高、被爬严重,应该在 Nginx 这道防线之后,叠加应用层手段:

  • 行为验证:对可疑请求弹出验证码,或使用无感验证(如浏览器指纹、JS 挑战)。
  • 动态令牌:核心数据接口要求携带有时效性的签名,增加批量调用的难度。
  • 登录与权限控制:把高价值内容放在登录后,配合账号级别的频率限制。
  • 内容水印与追踪:对文本、图片加入可追溯的标识,便于发现搬运后维权。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 为什么把反爬放在 Nginx
  • 第一道防线:限制请求频率
  • 第二道防线:封禁恶意 User-Agent
  • 补充手段:连接数限制与请求方法过滤
    • 限制单 IP 并发连接数
    • 只放行合理的请求方法
  • 组合策略与配置建议
  • Nginx 反爬的边界
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档