nginx 通过协议层特征轻量校验请求头,强制 content-type、白名单 host、可信 referer,防范下划线头丢弃,结合 request_length 与 content-type 交叉验证,并验证自定义头透传有效性。

在 Nginx 中校验请求头的完整性与合法性,核心不是解析内容,而是通过协议层特征做快速、轻量、可落地的过滤。它不替代后端鉴权或 WAF 深度检测,但能高效拦截大量自动化攻击、畸形请求和低级绕过行为。
检查关键头字段是否存在且格式合规
很多恶意工具会省略或乱填必需头字段。Nginx 可用内置变量和正则快速筛查:
- 强制要求 Content-Type:上传接口必须是
multipart/form-data,且含boundary;可用if ($content_type !~ "^multipart/form-data;.*boundary=") { return 403; } - 验证 Host 是否在白名单内:避免虚拟主机探测或 CDN 回源污染,推荐用
map预定义合法值,再配合if ($is_valid_host = 0) { return 444; } - 限制 Referer 基础可信性:用
valid_referers none blocked example.com *.example.com;+if ($invalid_referer) { return 403; }拦截明显异常来源(注意:仅作初级过滤)
防范头字段被篡改或忽略
Nginx 默认会丢弃含下划线(_)的请求头(如 X-Auth-Token),导致后端收不到 token:
- 方案一:前端改用短横线命名,如
X-Auth-Token→X-Auth-Token(推荐,符合 HTTP 头命名惯例) - 方案二:在
http块中启用underscores_in_headers on;,允许下划线(需确认后端也接受该头) - 若需透传客户端头(如
X-Api-Sign),应使用proxy_set_header X-Api-Sign $http_x_api_sign;,而非硬编码覆盖
结合请求体长度与头字段做交叉验证
单看某个头可能被伪造,但结合其他维度可提升判断置信度:
- 非上传接口(如
/api/v1/user)本不该带大 body,可设严限:if ($request_length > 262144) { return 413; } - 上传接口虽允许大 body,但若
Content-Type是text/plain却$request_length > 5m,大概率是伪装文件上传的 Webshell - 用
$request_completion在日志中识别“头已收、体未收完”的异常请求,辅助定位是否被中间设备截断或客户端主动中断
验证自定义校验头是否真正透传
设置 proxy_set_header X-Check-Sign $sign_value; 后,务必验证它是否到达后端:
- 在后端服务加日志打印所有收到的请求头,确认
X-Check-Sign存在且值正确 - 或在 Nginx 中临时加
add_header X-Debug-Header $http_x_check_sign;,用浏览器或 curl 查看响应头反推 - 避免在
http或server级别全局设置校验头,防止非目标路径也被强加,引发后端拒绝











