Nginx 中 proxy_pass 仅转发请求,恶意爬虫过滤需在转发前通过 if、map、return 等指令实现;常用方式包括基于 User-Agent 黑名单(如 sqlmap、Nikto)、IP 限流(limit_req_zone)、URI/参数正则匹配(如 wp-admin、SQL 注入特征)及空/短 UA 拦截。

在 Nginx 中,proxy_pass 本身不负责过滤请求,它只做反向代理转发。真正实现“过滤并清理恶意爬虫请求”的工作,需在 proxy_pass 执行前,通过 if、map、return、deny 等指令,在 server 或 location 块中完成识别与拦截。
基于 User-Agent 过滤常见恶意爬虫
很多扫描器、垃圾爬虫会使用特征明显的 User-Agent(如 sqlmap、Nikto、ZmEu、libwww-perl)。可用 map 预定义黑名单,再配合 if 拦截:
<!-- 在 http 块中定义 -->
map $http_user_agent $bad_ua {
default 0;
"~*sqlmap" 1;
"~*nikto" 1;
"~*ZmEu" 1;
"~*libwww-perl" 1;
"~*python-requests" 1; # 可选:限制无头 SDK 请求
}<!-- 在 server 或 location 中使用 -->
if ($bad_ua) {
return 403 "Forbidden";
}⚠️注意:if 在 location 中慎用,但用于简单字符串匹配(如 UA)是安全且高效的。避免在 if 中调用复杂变量或嵌套逻辑。
结合 IP 频率限制 + 爬虫特征双重防控
单靠 UA 容易被伪造,建议叠加限流和 IP 黑名单:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 用
limit_req_zone对疑似爬虫的 UA 或所有非浏览器请求限速 - 用
geo+map标记高风险 IP 段(如已知的扫描 IP 段) - 对命中黑名单的请求,直接
return 444(关闭连接,比 403 更静默)
示例:
limit_req_zone $binary_remote_addr zone=spider:10m rate=5r/s;
<h1>在 location 中</h1><p>if ($bad_ua) {
limit_req zone=spider burst=3 nodelay;
return 444;
}利用 $request_uri 和请求头识别异常行为
恶意爬虫常带可疑路径(如 /wp-admin/、/phpmyadmin/、/cgi-bin/)或异常参数(如 ?id=1' OR '1'='1):
- 用
if ($request_uri ~* "(wp-admin|phpmyadmin|cgi-bin|\.git|\.env)") { return 403; } - 用
if ($args ~* "(%27)|(\')|(\-\-)|(%23)|(#)") { return 403; }粗筛 SQL 注入特征 - 拒绝空
User-Agent或极短 UA(如长度
⚠️注意:正则匹配开销略高,建议只在关键 location(如 / 或 API 入口)中启用,避免全局滥用。
进阶:用 Lua(OpenResty)做动态爬虫识别
若需更精细控制(如 JS 挑战、指纹验证、行为分析),纯 Nginx 配置力有不逮。可切换为 OpenResty,用 access_by_lua_block 在请求进入 proxy_pass 前执行 Lua 脚本:
- 解析 UA + IP + 请求频率 + TLS 指纹(通过
ngx.req.get_headers()等) - 对接 Redis 实时黑名单或机器学习模型输出
- 对可疑请求返回验证码页面或延迟响应,而非直接拦截
示例片段(需安装 lua-resty-waf 或自定义逻辑):
access_by_lua_block {
if is_malicious_bot(ngx.var.http_user_agent, ngx.var.remote_addr) then
ngx.exit(429)
end
}核心原则:过滤必须发生在 proxy_pass 之前;越早拦截,资源消耗越小;组合策略(UA + URI + IP + 限流)比单点防御更可靠;生产环境建议先 log 再 deny,避免误杀。

















