可直接使用 limit_req 和 limit_conn 指令实现请求速率限制和并发连接数限制,二者均基于 nginx 的漏桶算法,需配合 limit_req_zone 或 limit_conn_zone 定义共享内存区域。

直接用 limit_req 和 limit_conn 做刚性拦截,核心是「精准识别 + 严格限速 + 拒绝响应」,不给爬虫任何试探或绕过机会。关键不在参数多高,而在策略是否贴合真实攻击特征。
基于IP的请求频率硬限制(limit_req)
这是对抗高频盗刷最常用也最有效的手段。重点不是压低阈值,而是让规则匹配真实恶意行为模式:
-
定义合理速率桶:比如
limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/s;表示每个IP每秒最多5个请求。对API接口可进一步压到1r/s或启用突发缓冲(burst=3 nodelay)只放行首3个,后续全部503 -
绑定到具体location:不要全局启用,只在敏感路径如
/api/、/search、/download下触发限流,避免误伤正常用户静态资源访问 -
拒绝必须显式声明:在 location 块中加
limit_req zone=perip reject=503;(Nginx 1.23+ 支持),旧版本用limit_req_status 503;配合limit_req,确保返回明确错误码而非等待或静默丢弃
连接数级硬隔离(limit_conn)防并发扫荡
当爬虫使用多线程/协程发起大量并发连接时,limit_conn 可从TCP连接层直接掐断:
-
按IP限制并发连接数:如
limit_conn_zone $binary_remote_addr zone=addr:10m;+limit_conn addr 2;表示单IP最多维持2个长连接。对HTTP/1.1场景非常有效 -
区分server与location粒度:若只保护某类后端(如PHP-FPM),可在
location ~ \.php$中配置;若需全站防护,放在server块更稳妥 -
配合超时快速释放:设置
keepalive_timeout 15;并缩短client_header_timeout和client_body_timeout至5秒内,防止恶意空连接长期占位
组合策略增强刚性(非简单叠加)
单独用任一模块都可能被绕过,组合使用才能形成“请求→连接→响应”全链路压制:
-
先限连再限频:在
server块用limit_conn控制最大并发,在location块用limit_req控制单位时间请求数,两者独立计数、双重触发 -
用变量动态调整强度:例如根据 User-Agent 匹配已知恶意特征(如
python-requests、curl、无Referer+高频)设置不同zone,或结合$request_uri对 /login、/verify 等高危路径启用更严策略 -
拒绝响应不带重试提示:禁用
limit_req的默认延迟行为(去掉nodelay),并确保返回纯503页面(甚至空响应体),避免暴露服务状态或诱导重试
验证与规避要点
上线前务必实测,避免规则被轻易绕过:
- 测试代理/IP轮换效果:用多个出口IP或透明代理反复请求,确认每个IP独立受控,且无法通过改头(如X-Forwarded-For)欺骗
-
检查日志是否记录真实客户端IP:若前端有CDN或负载均衡,需提前用
set_real_ip_from和real_ip_header正确提取源IP,否则$binary_remote_addr会变成中间节点地址 -
监控limit状态码分布:在 access_log 中加入
$limit_req_status和$limit_conn_status,观察rejected是否显著上升,及时发现漏网或误杀











