关键是要准确安全透传原始host头,推荐用proxy_set_header x-forwarded-host $host;配合x-forwarded-proto和x-forwarded-port,并确保后端仅信任来自nginx的该头。

要让后端服务拿到用户真实访问的域名,关键不是“重写域名”,而是把原始 Host 头准确、安全地透传过去。Nginx 默认会转发客户端发来的 Host,但一旦你用了 proxy_set_header Host 覆盖,就可能丢掉原始值——所以得用对变量、配好上下文。
用 $host 或 $http_host 保留原始域名
这两个变量最常用,区别在于是否带端口:
-
proxy_set_header Host $host;:取请求行中的 Host 域名部分,自动去掉端口(如example.com:443→example.com),适合大多数后端 -
proxy_set_header Host $http_host;:直接取 HTTP 请求头里的 Host 字段,保留端口信息,更完整但后端若不处理端口可能出错
用 X-Forwarded-Host 透传原始域名(推荐)
这个头专为“代理告知后端原始访问域名”而设计,语义清晰、不易混淆:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 写法:
proxy_set_header X-Forwarded-Host $host; - 不用
$http_host,避免端口污染;也不硬编码,保证多子域复用 - 后端需明确启用该头(如 Django 设
USE_X_FORWARDED_HOST = True),且只信任来自 Nginx 的请求
配合 Host 头与协议头一起配置
单独传域名不够,后端生成跳转链接或绝对 URL 时还需知道协议和端口:
-
proxy_set_header Host $host;—— 让后端路由/校验用 -
proxy_set_header X-Forwarded-Host $host;—— 明确告诉后端“用户访问的是哪个域名” -
proxy_set_header X-Forwarded-Proto $scheme;—— 区分 http/https -
proxy_set_header X-Forwarded-Port $server_port;—— 配合协议判断非标准端口(如 8443)
注意可信链路与后端读取逻辑
Header 只是传递载体,真正起作用靠后端解析:
- Nginx 不会自动替换后端的
request.getRemoteHost()或req.hostname,必须在代码里主动读X-Forwarded-Host - 不能无条件信任该头——确保 Nginx 是唯一入口,或后端只接受来自你 Nginx IP 的该字段
- 如果前面还有 CDN 或 WAF,需用
set_real_ip_from和real_ip_header先还原真实客户端 IP,再传 Host










