Nginx多租户反向代理需动态传入租户域名作为SNI:必须同时启用proxy_ssl_server_name on和proxy_ssl_name $host(或$http_x_forwarded_host),配合upstream中域名映射及租户维度缓存键,确保证书匹配、路由正确与缓存隔离。

要让 Nginx 在反向代理到多租户负载均衡环境时正确建立 TLS 连接、避免证书错配或握手失败,关键不是只加 proxy_ssl_server_name on,而是必须用 proxy_ssl_name 动态传入客户端真实请求的租户域名——这个值会作为 SNI 字段发给后端负载均衡器,从而触发正确的证书选择和租户路由。
必须启用 SNI 并绑定租户域名
Nginx 默认不发送 SNI,即使 proxy_pass 指向 HTTPS 地址,也会用后端地址(如 https://10.0.0.5)作为 SNI 值。在多租户负载均衡场景下,这会导致:
- 后端返回默认证书,浏览器提示“证书不匹配”
- 租户网关无法识别归属,把 tenant-b 的请求路由到 tenant-a 的服务实例
- 登录失败、API 返回 404 或 403,但静态资源仍能加载(因不校验证书或走缓存)
解决方法是两步同时生效:
- 在
location块中添加proxy_ssl_server_name on; - 紧跟着写
proxy_ssl_name $host;——$host已标准化为小写且不含端口,比$http_host更稳定
应对负载均衡器改写 Host 头的情况
当上游是云厂商负载均衡器(如阿里云 SLB、AWS ALB)或 API 网关时,它们常会覆盖原始 Host 头,导致 $host 变成源站配置名(如 origin-prod.internal),而非用户访问的 shop-123.tenant.com:
- 在负载均衡控制台开启“透传原始 Host”,通常会自动注入
X-Forwarded-Host请求头 - Nginx 中改用
proxy_ssl_name $http_x_forwarded_host; - 同时加上
proxy_set_header X-Forwarded-Host $host;,方便后端日志和鉴权逻辑读取
配合 upstream 使用时的注意事项
如果用了 upstream 定义后端集群(如多个网关实例),Nginx 解析域名后只保留 IP,proxy_ssl_name 就不能依赖变量自动推导:
- 不能只写
proxy_pass https://gateway_pool;然后指望$host生效 - 需在
upstream中定义带域名的 server,例如:server gateway.tenant-a.com:443; - 再用
map指令将租户域名映射到对应网关名:
map $host $sni_target {
default "gateway.default.com";
"app.tenant-b.io" "gateway.tenant-b.com";
} - 最后在 location 中写
proxy_ssl_name $sni_target;
缓存与 SNI 必须对齐
如果启用了 proxy_cache,而缓存键没包含租户维度,不同租户的响应会互相覆盖:
- 错误写法:
proxy_cache_key "$scheme$proxy_host$request_uri";——$proxy_host是后端固定地址 - 正确写法:
proxy_cache_key "$host$request_uri$is_args$args";—— 保证每个租户有独立缓存空间 - 建议搭配
proxy_cache_valid 200 302 10m;,避免缓存过期策略干扰租户隔离


















