Nginx需显式设置proxy_set_header Host $host;确保后端收到的Host头与其虚拟主机配置(如ServerName)严格匹配,避免因默认传递upstream地址导致404或错配,默认用$host(小写、去端口)最稳妥。

要让后端 Web 服务器在多站点(Virtual Host)模式下正确识别请求归属的域名,关键不是“传递任意 Host”,而是确保它收到的 Host 头与你配置的虚拟主机规则严格匹配。Nginx 默认会把 Host 改成 upstream 地址(如 backend:8080),这会导致后端无法路由到对应站点,直接 404 或返回默认站。
核心做法:在 proxy_pass 前显式设置 proxy_set_header Host $host; 或 $http_host;,且必须和后端 vhost 的 ServerName / ServerAlias 完全一致。
必须匹配后端虚拟主机定义
后端(如 Apache、Nginx、Spring Boot 内嵌 Tomcat)靠 Host 头做站点分发。例如:
- Apache 中某虚拟主机设了
ServerName api.example.com - Spring Boot 配了
server.tomcat.additional-tld-names=api.example.com
那么 Nginx 就必须把 Host 设为 api.example.com,不能是 localhost、127.0.0.1 或其他别名。
-
✅ 正确(客户端访问
https://api.example.com):proxy_set_header Host $host;
$host自动小写、去端口,结果就是api.example.com,完美匹配。 -
❌ 错误:
proxy_set_header Host $proxy_host; # 变成 backend:8080 → 后端找不到该站点 proxy_set_header Host ""; # Host 为空 → 多数后端 fallback 到 default server,错配
多租户或泛域名场景需动态对齐
如果后端支持泛域名(如 *.example.com)或按 Host 动态加载租户,仍需保证 Host 值真实有效:
- 客户端请求
tenant-a.example.com→ 后端需收到tenant-a.example.com - 若用了 CDN 或前置网关,确认它没重写 Host;若已重写,改用
$http_x_forwarded_host(前提是上层明确透传)
# 当上游(如 Cloudflare)设置了 X-Forwarded-Host: tenant-a.example.com proxy_set_header Host $http_x_forwarded_host;
⚠️ 注意:$http_x_forwarded_host 不是默认存在,需上游主动添加,否则为空。
避免 Host 被意外覆盖或截断
常见导致识别失败的操作:
- 在同一 location 中多次写
proxy_set_header Host,后一条会覆盖前一条 - 混用
$host和$http_host:$host会丢:8080,但若后端 vhost 显式写了ServerName app.example.com:8080,就必须用$http_host - 启用了
underscores_in_headers on;导致某些中间件解析异常,间接影响 Host 传递
建议统一使用 $host,除非后端明确依赖端口做 vhost 匹配。
验证是否生效的最快方式
- 在后端加一行日志,打印收到的 Host(如 Node.js 的
req.headers.host,Java 的request.getHeader("Host")) - 用 curl 直接测试:
curl -H "Host: api.example.com" http://your-nginx-ip/health
查看后端日志是否输出
api.example.com - 检查 Nginx access log 是否记录了正确
$host:log_format debug '$host $http_host $remote_addr - "$request"';
不复杂但容易忽略











