关键是要开启 proxy_ssl_server_name on 并配置 proxy_ssl_name $host,使 Nginx 将客户端真实域名作为 SNI 值传给 SaaS 存储,否则因证书不匹配导致 TLS 握手失败或 502 错误。

要让 Nginx 在静态回源到 SaaS 存储(如对象存储、多租户文件服务)时正确完成 TLS 握手,关键不是只开 proxy_ssl_server_name on,而是让它把用户请求的真实域名作为 SNI 值传过去——否则 SaaS 后端无法识别该返回哪张证书,连接直接中断或报 502。
必须开启 SNI 并指定准确的域名值
Nginx 默认不发送 SNI 字段,而多数 SaaS 存储(如阿里云 OSS、Cloudflare R2、自建 MinIO 多域名网关)依赖 SNI 区分租户或 bucket 绑定的证书。仅配置 proxy_pass https://storage.example.com 不够,它会让 Nginx 固定用 storage.example.com 当 SNI,但实际请求可能是 assets.shop-a.com。
- 在
location块中添加proxy_ssl_server_name on; - 紧接着配置
proxy_ssl_name $host;——$host是标准化后的 Host 头(小写、无端口),比$http_host更可靠 - 确保
proxy_pass指向的是 HTTPS 地址,例如https://10.0.1.200或https://s3-api.internal;HTTP 回源下该指令完全不生效
应对 SaaS 存储要求严格匹配的常见情况
部分 SaaS 存储(如某些私有 MinIO 部署、定制化对象网关)不仅校验证书域名,还校验 SNI 是否与 Host 头一致。若不匹配,可能直接拒绝连接,而非返回错误证书。
- 保持 Host 头与 SNI 一致:
proxy_set_header Host $host; - 避免在
upstream块里写死proxy_ssl_name,它必须放在location中才能继承请求上下文 - 如果 SaaS 存储使用泛域名证书(如
*.cdn.example.com),确认请求域名落在该通配符覆盖范围内;否则仍会失败
CDN 回源到 SaaS 存储时的特殊处理
当 CDN(如阿里云全站加速、Cloudflare)将请求回源至你的 Nginx,再由 Nginx 转发给 SaaS 存储时,CDN 往往会重写 Host 头为源站域名(如 origin.yourdomain.com),导致 $host 失真,SNI 错配。
- 在 CDN 控制台启用「透传原始 Host」功能,通常表现为传递
X-Forwarded-Host头 - Nginx 中改用
proxy_ssl_name $http_x_forwarded_host; - 同时补上
proxy_set_header X-Forwarded-Host $host;,方便 SaaS 存储侧做租户路由
验证配置是否真正起效
配置写对 ≠ 实际发出的 SNI 正确。需从上游视角确认:
- 在 SaaS 存储后端(如另一台 Nginx 或支持 debug 的网关)开启 TLS debug 日志:
error_log /var/log/nginx/error.log debug;,搜索client sent server name - 用 OpenSSL 手动测试:运行
openssl s_client -connect 10.0.1.200:443 -servername assets.shop-a.com,看返回证书的 SAN 是否含该域名 - 检查 OpenSSL 版本:
nginx -V | grep OpenSSL,确保 ≥ 1.0.2h 且编译时启用了 TLS extension











