什么是SNI?为何反向代理必须开启?

话题来源: 工作笔记,TLS错误导致安全连接失败

那个让无数运维抓狂的 ”TLS 错误导致安全连接失败 ”,十有八九是 SNI 在作祟。浏览器访问一切正常,换成小火箭、Clash 等客户端订阅却死活拉取不到数据——这种 ” 薛定谔的连通性 ” 问题,本质上是 Nginx 反向代理在握手阶段 ” 报错了身份 ”。

SNI 到底是什么?

SNI(Server Name Indication),服务器名称指示,是 TLS 协议的一个扩展。打个比方,一台服务器上托管了数十个 HTTPS 网站,它们共享同一个 IP 地址。当客户端发起连接时,服务器怎么知道该出示哪张 SSL 证书?答案就在 SNI——客户端在握手初期会明文发送想要访问的域名,服务器据此返回正确的证书。

没有 SNI 的年代,一个 IP 只能绑定一张证书,资源浪费严重。如今 SNI 已成 HTTPS 生态的基础设施,浏览器默认开启,我们习以为常。但问题来了:当 Nginx 作为反向代理站在中间时,事情就变得微妙了。

反向代理的 ” 身份危机 ”

场景很典型:前端 Nginx 反代后端面板,两端都上了 SSL。客户端请求 proxy.example.com,Nginx 收到后向 backend.panel.com 发起连接。关键点在于——Nginx 默认的 proxy_ssl_server_name 配置是 off

这意味着什么?Nginx 连接上游时, 不携带 SNI 信息 。后端服务器收不到域名标识,只能返回默认证书(往往是自签名或不匹配的证书),TLS 握手当场翻车。浏览器能正常访问,是因为浏览器发请求时自带 SNI;而订阅软件通过反代链路请求时,中间环节 ” 忘记 ” 了传递这个关键信息。

一行配置的修复

解决方案简单到让人怀疑人生:

proxy_ssl_server_name on;

这行配置让 Nginx 在连接上游时主动带上 SNI,后端服务器就能精确匹配证书,握手顺利完成。顺便提一句,proxy_ssl_name 也可以显式指定域名,适用于代理地址与证书域名不一致的场景。

这个坑藏得很深。宝塔、1Panel 等面板默认生成的反代配置,几乎都不会自动加上这条规则。只有当客户端严格校验证书链时,问题才会暴露——偏偏订阅软件都属于这类 ” 较真 ” 的客户端。

下次遇到 502、TLS 握手失败、订阅拉取异常,先别急着怀疑证书本身。查一下 Nginx 配置,看看 SNI 有没有被正确传递,往往比重新签发证书来得快得多。

各类账号ID
评论(没有评论)