什么是 SNI?

SNI 是 TLS 握手时客户端告诉服务器"我要访问哪个域名"的扩展。它解决了一个 IP 地址托管多个 HTTPS 网站时,服务器不知道该发哪张证书的问题。SNI 的存在,是虚拟主机在加密时代继续运转的前提。

第 50 期介绍过,一个 IP 地址可以承载多个网站,靠的是请求里携带域名信息。在 HTTP 场景下,浏览器通过 Host 头告诉服务器访问哪个域名;但在 HTTPS 场景下,连接要先完成 TLS 握手、建立加密通道,之后才会发送 HTTP 请求和 Host 头。如果握手阶段服务器不知道客户端要访问哪个域名,就无法选择正确的证书,多个网站也就无法共用同一个 IP。

SNI(Server Name Indication,服务器名称指示)就是为解决这个问题设计的。它是 TLS 握手阶段的一个扩展:客户端在握手的第一条消息里,明文带上自己要访问的域名,服务器据此选择对应的证书完成握手。有了 SNI,同一 IP 上不同域名的证书可以分开配置,每个网站用自己的证书。

SNI 也有一个已知的问题:域名在握手阶段是明文发送的,没有加密,中间的观察者可以看到用户访问了哪个域名,尽管之后传输的数据内容已经加密。为此出现了加密客户端问候(Encrypted Client Hello)等方案,尝试把 SNI 中的域名也加密起来,不过目前尚未全面普及。