核心是控制转发给后端的请求头,防止客户端伪造关键信息、泄露敏感上下文或绕过前端校验逻辑;需显式覆盖host、清空易伪造头(如x-forwarded-for)、注入可信上下文(如x-forwarded-proto),并禁用下划线头与未校验的$http_*变量。

在 Nginx 中使用 proxy_set_header 实现安全隔离后端,核心是**控制转发给后端的请求头,防止客户端伪造关键信息、泄露敏感上下文,或绕过前端校验逻辑**。这不是简单地“加几个头”,而是有意识地清理、重写、补全请求头,构建可信的代理边界。
只传递必要且可信的请求头
默认情况下,Nginx 会将大部分客户端请求头原样转发给后端(如 User-Agent、Referer),这可能带来风险:攻击者可伪造 X-Forwarded-For、X-Real-IP 或自定义头绕过权限判断。应显式覆盖或清除非必需头:
- 用
proxy_set_header Host $host;替换原始Host,避免后端被诱导访问错误域名(尤其当后端依赖 Host 判断租户时) - 用
proxy_set_header X-Real-IP $remote_addr;提供真实客户端 IP,而非依赖不可信的X-Forwarded-For - 用
proxy_set_header X-Forwarded-For ""; proxy_set_header X-Forwarded-Proto ""; proxy_set_header X-Forwarded-Host "";清空这些易伪造的头,除非你明确需要并做了校验(如只信任内部负载均衡器添加的X-Forwarded-For)
主动注入可信上下文头
让后端无需解析原始请求,就能获得经过 Nginx 校验后的可信信息:
-
proxy_set_header X-Forwarded-Proto $scheme;—— 明确告知后端当前是 http 还是 https,避免后端因无法判断协议而生成错误跳转链接 -
proxy_set_header X-Forwarded-Port $server_port;—— 补充端口信息,尤其当 Nginx 前置 SSL 终结时有用 - 若已做身份认证(如 JWT 验证),可注入
proxy_set_header X-Auth-User $jwt_claim_sub;(需配合 auth_request 模块或 Lua),把解析后的用户 ID 安全透传,后端直接信任该字段
禁止客户端随意注入自定义头
Nginx 默认不阻止客户端发送任意头(如 X-Admin: true),若后端未过滤就直接使用,会造成越权。可通过以下方式防御:
- 在
location块中,用underscores_in_headers off;(默认值)防止下划线命名的头被忽略(某些语言框架会把X-My-Header转为x_my_header,注意兼容性) - 对高敏感接口,用
map指令或 Lua 脚本检查请求头白名单,非法头直接返回 400;或统一用proxy_pass_request_headers off;+ 手动proxy_set_header,彻底关闭自动转发 - 避免在配置中使用
$http_*变量拼接头(如proxy_set_header X-Custom $http_x_custom;),除非你确认该头已被严格校验
验证后端是否真正依赖这些头
设置完 proxy_set_header 后,务必检查后端代码逻辑:
- 后端是否只从
X-Real-IP读取客户端 IP?是否仍解析X-Forwarded-For?若后者未清理,隔离就失效 - 后端是否把
Host头当作可信来源?是否允许通过 Host 绕过路由或租户隔离? - 日志和审计系统是否记录的是 Nginx 注入的
X-Auth-User,而不是原始Authorization头?
不复杂但容易忽略。











