最有效的防御是禁用$http_host和$host透传,改用$proxy_host、固定域名或清空Host头,并配合X-Real-IP加固及Host白名单拦截;同时前置default_server拒绝非法Host,统一覆盖X-Forwarded-For等关键头,限制头部大小防绕过。

防止 Nginx 转发请求头时出现头部注入漏洞,核心是**不信任客户端输入、主动控制转发内容、分层拦截非法值**。Host 头是最典型、危害最大的注入入口,但 User-Agent、Referer、X-Forwarded-* 等也常被滥用。下面从最关键的三个层面给出可直接落地的配置建议。
一、严格管控 Host 头:禁透传,只用可信来源
绝不能让客户端传来的 Host 值原样转发给后端。以下写法必须禁用:
- proxy_set_header Host $http_host; —— 完全暴露,含端口、大小写、任意域名,攻击者 curl -H "Host: evil.com" 即可生效
- proxy_set_header Host $host; —— 表面标准化,实则仍来自用户输入,不可信
推荐三种安全替代方案(任选其一):
- 用 $proxy_host:取自 proxy_pass 地址,如 proxy_pass http://api:8000; → Host 头自动设为 api:8000,与业务域名解耦,最推荐
- 设固定后端域名:如 proxy_set_header Host api.internal;,适用于单租户、后端只认一个名字的场景
- 清空 Host 头(谨慎):proxy_set_header Host "";,仅在确认后端完全不依赖 Host 时使用,否则可能返回 400
二、统一加固其他关键代理头
只修 Host 不够。攻击者会转向 X-Forwarded-For、X-Real-IP、X-Forwarded-Proto 等字段做伪造或链式污染:
- proxy_set_header X-Real-IP $remote_addr; —— 强制覆盖,确保后端拿到真实源 IP
- proxy_set_header X-Forwarded-For $remote_addr; —— 不拼接原始值,避免伪造链(如 $http_x_forwarded_for)
- proxy_set_header X-Forwarded-Proto $scheme; —— 明确告知后端协议,防混合内容或跳转错误
- proxy_hide_header Server; 和 proxy_hide_header X-Powered-By; —— 隐藏技术栈,减少攻击面
三、前置拦截非法 Host 及恶意头字段
在请求进入 proxy_pass 逻辑前,就筛掉明显异常的请求:
- 每个 server 块必须显式声明合法域名:server_name example.com www.example.com;
- 额外定义一个 default_server,监听相同端口但不设 server_name,里面写:return 444;(静默断连)或 return 403;
- 过滤可疑 User-Agent 或 Referer:
if ($http_user_agent ~* "(script|alert|onerror|curl|sqlmap|nmap)") { return 403; }
if ($http_referer ~* "(%3C|%3E|javascript:|data:text/html)") { return 403; }
四、限制头部大小,防资源耗尽型攻击
超长请求头本身不是注入,但常用于绕过规则或触发 OOM:
- client_header_buffer_size 2k; —— 基础缓冲区,覆盖绝大多数正常请求
- large_client_header_buffers 4 8k; —— 允许最多 4 个大头缓冲,单个上限 8KB,总上限 32KB
- 超出即返回 400,不进 worker 内存池,避免内存被恶意头部撑爆


















