⭐ 推荐:社区规则条款 V1.0

Nginx 防爬虫配置如何测试拦截效果?

周末
周末 萌新站长
发布于 2026-10-20 11:40 ·18 浏览 ·0 回复
内容摘要

验证 Nginx 防爬虫配置需依次用 curl 检查返回 403/444、用 access.log 统计拦截量,并用 dry_run 或灰度日志观察 1-3 天防误杀;只改配置不验证等于没做。

结论:验证 Nginx 防爬虫效果,只需要走完三步:先用 curl 模拟爬虫请求并查看返回码是否为 403 或 444,再用 access.log 统计真实拦截量,最后用 limit_req_dry_run 或灰度日志观察 1-3 天确认没有误杀。只改配置不验证,等于没做。

怎么用 curl 最快验证拦截规则已经生效?

结论:一条 curl 命令就能判断规则是否命中,关键看返回码是 200 还是 403/444。

按你实际配置的拦截维度逐条构造请求。如果按 UA 拦截,就清空 UA,或伪装成脚本 UA:


curl -s -o /dev/null -w "%{http_code}\n" -A "" https://example.com/
# 常见脚本 UA
curl -s -o /dev/null -w "%{http_code}\n" -A "python-requests/2.31.0" https://example.com/
curl -s -o /dev/null -w "%{http_code}\n" -A "Scrapy/2.11" https://example.com/

期望输出 403。如果按 Referer 拦截,就加 -e "" 传空 Referer;如果按请求头拦截,就用 -H "X-Requested-With:" 删掉该请求头。配置改完后必须先执行 nginx -t 检查语法,再执行 nginx -s reload,否则规则没有加载,测试结果全错。

Nginx 返回 403 和 444 有什么区别?

结论:403 会正常返回一个响应报文并写入日志,444 是 Nginx 专有的“直接关闭连接”状态码,客户端收不到任何响应,对爬虫的惩罚更重,也更省带宽。

用 444 时,curl 不会打印状态码,只会报 curl: (52) Empty reply from server,-w "%{http_code}" 输出 000。这是正常现象,不是配置失败。判断 444 是否生效,看日志里是否出现 " 444 ,不要依赖 curl 的返回码。

怎么确认拦截规则没有误伤正常用户?

结论:用真实浏览器的完整请求头复测一遍,返回码必须是 200,这一步不做,上线就可能封掉正常用户。

最省事的办法是从 Chrome 打开开发者工具的 Network 面板,右键任意请求,选择 Copy as cURL,把整条命令粘贴到终端执行。这条命令带上了真实的 UA、Accept、Accept-Language、sec-ch-ua 等头,能最大程度还原真实流量。再补测两类高风险场景:一是带 Cookie 的登录态请求,二是搜索引擎爬虫,后者应通过官方公布的 IP 段做白名单,而不是只匹配 UA 字符串,因为 UA 可以伪造。

怎么用日志统计真实的拦截数量?

结论:在 log_format 里显式记录 $status 和 $limit_req_status,再用 awk 聚合,就能量化拦截效果。

# 统计各状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# 单独统计 444 的次数
grep -c '" 444 ' /var/log/nginx/access.log

$limit_req_status 是 Nginx 1.17.6 引入的变量,取值为 PASSED、DELAYED、REJECTED,把它写进 log_format 后,就能区分“被限频拒绝”和“被其他规则拦截”。另外建议加 add_header X-Blocked-Reason "ua" always;,方便排查具体是哪条规则命中的;但要注意在 444 场景下响应头不会返回给客户端,此时只能靠日志确认。

限频规则怎么压测才准确?

结论:用 30 次连续请求打同一个 URL,观察状态码序列是否从 200 切换为 503,就能验证 limit_req 是否按预期触发。

for i in $(seq 1 30); do curl -s -o /dev/null -w "%{http_code} " https://example.com/; done; echo

假设配置为 limit_req zone=req_zone burst=5 nodelay;,且 rate=1r/s,那么前 6 个请求应返回 200,第 7 个起变为 503。Nginx 限频默认返回 503,如果想返回语义更准确的 429,需要显式设置 limit_req_status 429;。测试时注意:只发单线程串行请求可能因网络延迟掩盖限频效果,并发压测可以用 ab -n 50 -c 10 https://example.com/ 更贴近真实攻击流量。

上线前怎么灰度验证,避免一次性误杀?

结论:先开启 dry-run 模式,只记录不拦截,观察 1-3 天后再切换为真正的拦截。

Nginx 1.17.6 起支持 limit_req_dry_run on;,此时超限请求正常放行,但 $limit_req_status 会记为 REJECTED_DRY_RUN,从日志里就能统计“如果真拦会拦掉多少”。UA 类规则没有 dry-run 开关,可以用 map 先定义变量,只写入日志、不执行 return,观察期结束后再把 if ($bad_ua) { return 403; } 打开。灰度期重点看两个数:被标记的请求占总量比例是否异常偏高,以及来源 IP 是否集中在少数几个正常业务方。


总的做法是:先用 curl 逐条确认规则命中,再用日志量化拦截量,然后压测限频阈值,最后用 dry-run 灰度上线。三步都跑通再全量,比改完配置直接看“好像生效了”可靠得多。

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2316.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~