nginx轮询策略本身不支持请求过滤,所有安全控制必须在upstream之外的location/server块中实现:在proxy_pass前用if+return拦截恶意请求、用map/geo动态分流、透传清洗标记,并避免在upstream内写过滤逻辑。

在 Nginx 负载均衡的轮询(round-robin)策略中,**不能直接在 upstream 块内“过滤请求包”**——因为 upstream 只定义后端节点列表,不参与请求处理逻辑。真正的过滤必须发生在请求进入 upstream 之前,也就是在 location 或 server 块中完成。换句话说:轮询本身不负责清洗,Nginx 的反向代理入口才是第一道过滤网。
在 proxy_pass 前拦截非法请求
所有过滤动作必须放在 proxy_pass 指令之前,确保恶意请求根本不会发往后端:
- 用
if + return阻断含 SQL 注入、路径穿越等特征的请求:if ($args ~ "(union\s+select|\.%2e|etc/passwd)") { return 403; } - 拒绝非常规 HTTP 方法:
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS)$) { return 405; } - 校验 Host 头合法性,防 IP 直连或扫描器试探:
if ($host !~ ^(example\.com|api\.example\.com)$) { return 444; }
按请求特征动态分流,避开轮询陷阱
轮询是默认行为,但你可以绕过它,把高风险流量导向隔离区,而不是平均分发:
- 用
map提取风险信号(如可疑 UA、异常参数),再结合if跳转:map $http_user_agent $is_scanner { "~*sqlmap|nikto" 1; default 0; }<br>if ($is_scanner) { return 444; } - 对已识别的恶意 IP,直接
deny或转发到蜜罐:geo $bad_ip { default 0; 192.168.1.100 1; }<br>if ($bad_ip) { proxy_pass http://honey_pot; break; }
标准化并透传原始信息给后端清洗服务
若后端有专用清洗模块(如自研风控中间件),Nginx 不做深度处理,只做轻量打标与透传:
- 清理伪造头,重设真实来源:
proxy_set_header X-Real-IP $remote_addr;<br>proxy_set_header X-Forwarded-For "";
- 添加清洗标记,便于后端识别处理阶段:
proxy_set_header X-Proxy-Stage "lb";<br>proxy_set_header X-Filter-Action "pass";
并在拦截时改写为"block_sql"或"drop_no_host" - 记录原始请求长度、TLS 版本等元数据,支撑后续分析:
log_format clean '$request_length $ssl_protocol $status $upstream_http_x_filter_result';
避免常见误区
轮询策略本身不可控,别试图在 upstream 里加 if 或 return——语法错误且无效。重点始终是:
- 过滤不在 upstream,而在 location;
- 分流不靠轮询,而靠
proxy_pass前的条件判断; - 静默丢弃用
return 444,比 403/400 更彻底; - CDN 场景下,
$binary_remote_addr要换成可信的$http_x_forwarded_for并校验头有效性。











