要让后端正确识别原始Host,需在每层Nginx反向代理中用proxy_set_header Host $host显式传递客户端请求的Host头,避免被覆盖为上游地址;同时可选proxy_set_header X-Real-IP $remote_addr传递真实IP,或用X-Original-Host透传原始域名以应对必须改写Host的场景。

要让后端应用正确识别客户端请求的原始 Host,关键是在每层反向代理(如 Nginx)中用 proxy_set_header Host 显式传递真实 Host 值,避免被中间代理覆盖为上游地址或默认值。
明确 Host 头的来源与风险
客户端发起请求时携带 Host 头(如 Host: example.com)。若请求经过多层 Nginx 代理(如 CDN → 边缘 Nginx → 应用网关 → 后端服务),每层默认会重写 Host 为 proxy_pass 指定的上游地址(如 backend:8080),导致后端收不到原始域名,影响路由、生成绝对 URL、CORS 判断等。
常见错误配置:
proxy_set_header Host $proxy_host; —— 这会把 Host 改成上游地址,不是原始值
未设置 Host 头 —— Nginx 默认用 $proxy_host,同样丢失原始 Host
逐层配置:保留原始 Host 的推荐写法
在每一级 Nginx 的 location 或 server 块中,统一使用以下配置:
-
传递原始 Host:
proxy_set_header Host $host;
($host是客户端请求中的 Host,不含端口;若需端口,用$http_host) -
补充真实客户端 IP:
proxy_set_header X-Real-IP $remote_addr;
(配合real_ip_header和set_real_ip_from使用更可靠) -
透传原始 Host(含端口):
proxy_set_header Host $http_host;
(当客户端显式带端口如example.com:8443且后端依赖该信息时选用) -
禁用自动重写:确保没有其他
proxy_set_header Host ...覆盖此行
验证与调试方法
在后端应用(如 Node.js/Python/Java)中打印收到的 Host 头,确认是否为预期域名;也可用 curl 模拟链路测试:
- 直接访问后端:
curl -H "Host: test.example.com" http://backend-ip:8080/health - 经代理访问:
curl -v http://your-proxy-domain/health,观察响应头和后端日志中的 Host 值 - 检查 Nginx access_log:
log_format main '$host $http_host $remote_addr - $request';,快速比对各层记录
特殊场景处理
若某层代理必须改写 Host(如统一接入层需将所有流量转给内部域名),应改用 X-Original-Host 等自定义头透传原始值,并在后端读取该头替代 Host:
- 代理侧:
proxy_set_header X-Original-Host $host; - 后端侧:优先读
X-Original-Host,Fallback 到Host - 注意:需同步修改后端逻辑,且确保该自定义头不会被外网伪造(可通过只信任内网代理 IP 实现)


















