Nginx反向代理HTTPS后端时需同时启用proxy_ssl_server_name on并设置proxy_ssl_name $host(或$http_x_forwarded_host),才能正确传递SNI信息,确保上游服务器选用匹配域名的证书;否则TLS握手失败。

要让 Nginx 在反向代理 HTTPS 后端时正确传递 SNI 信息,关键不是 proxy_ssl_server_name 本身“解决”问题,而是它配合 proxy_ssl_name 才能实现精准的证书匹配。默认情况下,Nginx 用 proxy_pass 中写的域名(如 https://10.0.0.100)作为 SNI 值,这在后端是单域名或固定证书时没问题;但当后端一个 IP 绑定多个域名、每个域名配了独立证书(比如 CDN 回源目标、多租户网关、SaaS 后端),就必须显式告诉 Nginx:“这次请求用户要的是哪个域名”,否则上游无法选出对应证书,TLS 握手直接失败。
必须开启 SNI 支持并动态传 Host
proxy_ssl_server_name on 是前提,它启用 TLS 握手阶段发送 SNI 扩展的能力。但仅开启还不够——SNI 字段内容必须与客户端原始请求一致:
- 添加 proxy_ssl_server_name on; 到 location 或 upstream 块中
- 设置 proxy_ssl_name $host;(推荐)或 proxy_ssl_name $http_host;,确保 SNI 值等于用户请求头中的 Host 域名
- 避免写死静态字符串(如 proxy_ssl_name "api.example.com"),除非所有请求都指向同一后端域名
应对 CDN 回源时 Host 被覆盖的情况
很多 CDN(如 Cloudflare、阿里云全站加速)回源时会强制改写 Host 头为源站配置域名,导致 $host 变成源站名而非用户原始域名。此时 SNI 就会错配:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- 在 CDN 控制台开启“透传原始 Host”功能,通常表现为传递 X-Forwarded-Host 头
- Nginx 中改用 proxy_ssl_name $http_x_forwarded_host;
- 同时建议加一句 proxy_set_header X-Forwarded-Host $host;,方便后端日志和逻辑识别真实请求来源
验证是否真正生效
光看配置是否正确不够,得确认 TLS 握手时发出的 SNI 值确实是预期域名:
- 在上游服务器(如另一台 Nginx 或测试用的 OpenSSL 服务端)开启 debug 日志:error_log /var/log/nginx/error.log debug;
- 触发一次请求,搜索日志中类似 "SSL_do_handshake() failed ... SSL alert number 40" 或 "client sent server name ..." 的条目
- 更直接的方式:用 openssl s_client -connect 上游IP:443 -servername your-domain.com 模拟请求,观察返回的证书是否匹配该域名
常见失效原因排查
即使配置看起来正确,仍可能因底层依赖不满足而失败:
- 确认 Nginx 编译时启用了高版本 OpenSSL(≥1.0.2h),且运行时加载的是该版本(nginx -V | grep OpenSSL)
- 检查上游服务是否真正支持 SNI(老版本 Nginx、某些硬件负载均衡器默认关闭或不兼容)
- 确保 CDN 回源协议确实是 HTTPS —— 若回源走 HTTP,proxy_ssl_* 系列指令完全不生效
- 注意变量作用域:$host 在 server 块中可用,但在 upstream 块中不可用,proxy_ssl_name 必须放在 location 或 server 内

















