nginx 通过 access_by_lua_block 在权限校验阶段调用外部轻量推理服务实现毫秒级爬虫识别,核心是特征组装、快速转发与决策拦截;需严格超时控制、失败降级及缓存优化。

Nginx 本身不执行机器学习推理,但可以在 access 阶段用 Lua 调用外部轻量推理服务,实现毫秒级爬虫识别。关键不是把模型塞进 Nginx,而是让 Lua 做好「特征组装 + 快速转发 + 决策拦截」这三件事。
access_by_lua_block 是核心入口
必须用 access_by_lua_block(不能用 content 阶段),因为它运行在权限校验环节,早于文件分发或代理转发,不影响静态资源 sendfile 性能。示例配置:
location / {
access_by_lua_block {
local ip = ngx.var.remote_addr
local ua = ngx.var.http_user_agent or ""
local referer = ngx.var.http_referer or ""
local method = ngx.var.request_method
local uri = ngx.var.uri
local req_time = tonumber(ngx.var.request_time) or 0
-- 构造请求体(JSON 格式,字段与模型训练时一致)
local data = {
remote_addr = ip,
http_user_agent = ua,
http_referer = referer,
request_method = method,
uri = uri,
request_time = req_time
}
-- 同步调用推理服务(超时严格控制在 300ms 内)
local res = ngx.location.capture("/_ml_bot_check", {
method = ngx.HTTP_POST,
body = cjson.encode(data),
timeout = 300
})
if res.status == 200 then
local json = cjson.decode(res.body)
if json.is_anomaly == true or (json.score and json.score > 0.82) then
ngx.exit(403)
end
elseif res.status >= 400 then
-- 服务异常时保守策略:放行(避免雪崩)
ngx.log(ngx.WARN, "ML service failed: ", res.status)
end
}
proxy_pass http://backend;
}
推理服务要极简、无状态、低延迟
后端 FastAPI/Flask 服务只做一件事:接收结构化请求 → 提取特征 → 跑 ONNX 模型 → 返回 {"is_anomaly": true, "score": 0.91}。
- 特征工程必须和训练时完全一致:比如 UA 做 xxHash 后取模 10000,URI 计算路径深度+参数个数+特殊字符密度
- 模型选型推荐 Isolation Forest(无监督,适合未知爬虫)或轻量 XGBoost(有标注数据时)
- 不用加载完整 sklearn,用 ONNX Runtime 加载导出模型,单次预测
防御伪装爬虫的关键特征组合
光靠 UA 容易被绕过,Lua 中应主动组合多维信号:
-
ua == "" or referer == ""→ 高风险(正常浏览器几乎总有 referer) -
method == "GET" and string.match(uri, "/api/.*%.php")→ 异常路径模式 req_time → 极快响应 + 简短 UA(常见于 headless 爬虫)-
string.find(ua, "HeadlessChrome") or string.find(ua, "PhantomJS")→ 明确指纹
这些可提前在 Lua 中计算为 risk_score,再作为附加字段传给推理服务,或直接用于兜底拦截。
必须加的保护机制
-
超时硬限制:
timeout = 300,防止 ML 服务卡住拖慢全部流量 - 失败降级:ML 服务不可用时默认放行,不 return 500 或阻塞
- 共享字典缓存:对高频 IP 或 UA 哈希做 1 分钟结果缓存,减少重复调用
-
日志标记:
ngx.log(ngx.INFO, "BOT_CHECK ip=", ip, " score=", json.score),便于后续分析误判
本质上,Nginx + Lua 在这里是个“智能网关代理”,不是模型容器。真正的 AI 能力由独立服务承载,Nginx 只负责快、稳、准地把请求送过去,并根据返回结果执行 403 或放行。











