TLS SNI 是什么?为什么 HTTPS 多域名部署需要它?
简化版
SNI 是 TLS 的 Server Name Indication 扩展,客户端在 TLS 握手早期告诉服务器自己要访问哪个域名。它解决同一 IP 部署多个 HTTPS 站点时,服务器不知道该返回哪张证书的问题。
详细版
没有 SNI 时,TLS 握手先于 HTTP 请求发生,服务器在看到 HTTP Host 之前就必须发证书。如果同一个 IP 上有多个域名,服务器不知道该选哪张证书。
有了 SNI:
- 客户端在 ClientHello 中带上目标域名。
- 服务器根据 SNI 选择对应证书和 TLS 配置。
- 证书域名与用户访问域名匹配,握手继续。
- HTTP 请求里仍然会带
Host,用于应用层路由。
SNI 是现代 HTTPS 虚拟主机、CDN、多租户网关的基础能力。注意传统 SNI 明文可见,ECH 是为隐藏 ClientHello 中敏感信息而设计的新机制。
完整版教学
一、为什么 HTTP 的 Host 解决不了 HTTPS 证书选择
HTTP 明文请求里有 Host,服务器可以等请求进来后按域名路由。但 HTTPS 先做 TLS 握手,握手成功后才有 HTTP 请求。服务器必须在握手阶段就发证书,此时还没看到 HTTP Host。
HTTPS 顺序:
TCP connect
TLS ClientHello
TLS ServerHello + Certificate <- 这里就要选证书
HTTP GET / Host: example.com <- 这时太晚了
所以仅靠 HTTP Host 无法解决“同一 IP 多 HTTPS 域名选证书”的问题。
记忆钩子:Host 是 HTTP 层的门牌号,SNI 是 TLS 握手阶段提前递过去的门牌号。
二、SNI 在握手里怎么工作
客户端发 ClientHello 时,在扩展字段里带上 server_name。服务器读到这个域名后,选择匹配证书、私钥、TLS 参数,再继续握手。
ClientHello:
extensions:
server_name = www.example.com
Server:
choose certificate for www.example.com
send Certificate
举例:1.2.3.4:443 同时服务 a.com 和 b.com。客户端访问 b.com 时带 SNI=b.com,服务器返回 b.com 的证书;否则可能默认返回 a.com 证书,浏览器报证书域名不匹配。
三、SNI 和 Host 的区别
SNI 和 Host 都携带域名,但层次、时机和用途不同。SNI 用于 TLS 层选择证书,Host 用于 HTTP 层虚拟主机和应用路由。
| 字段 | 所在层 | 发送时机 | 主要用途 |
|---|---|---|---|
| SNI | TLS | ClientHello | 选择证书/TLS 配置 |
| Host | HTTP | TLS 建立后 | HTTP 虚拟主机路由 |
:authority | HTTP/2 | TLS 建立后 | 类似 Host 的语义 |
二者通常应该一致。若 SNI 是 a.com,Host 是 b.com,网关可能拒绝、路由错乱或触发安全策略。
四、CDN 和网关为什么依赖 SNI
CDN 节点会承载海量域名。它不可能给每个域名单独占一个 IP,所以必须靠 SNI 在 TLS 握手时选择证书。企业 API 网关、多租户 Ingress 也类似。
CDN edge IP: 203.0.113.10
├─ img.a.com -> cert A
├─ static.b.com -> cert B
└─ api.c.com -> cert C
如果客户端太旧不支持 SNI,CDN 只能返回默认证书,这就是很多老设备访问现代 HTTPS 站点失败的原因之一。
五、SNI 的隐私问题和 ECH
传统 SNI 在 ClientHello 中是明文的,中间网络设备能看到用户要访问的域名。即使 HTTPS 加密了 HTTP 内容,SNI 仍可能泄露访问目标。
可见信息:
IP = 203.0.113.10
SNI = private.example.com
不可见信息:
URL path、Cookie、HTTP body
ECH(Encrypted ClientHello)尝试加密 ClientHello 中的敏感扩展,包括真实 SNI。但它依赖客户端、DNS、服务端/CDN 支持,部署还在逐步推进。
六、排障时怎么判断 SNI 问题
SNI 错误常表现为证书域名不匹配、默认站点证书、某些客户端访问失败。排查时可以用 openssl s_client -servername 指定 SNI 对比结果。
openssl s_client -connect 1.2.3.4:443 -servername www.example.com
如果不带 -servername 和带上后证书不同,就说明服务器按 SNI 选择证书。负载均衡、Nginx、Ingress 配置错误时,SNI 是排查重点。
七、常见误区与追问
- 误区:Host 能决定 HTTPS 返回哪张证书。 证书在 HTTP 请求前就要发出,必须靠 TLS 层的 SNI。
- 误区:SNI 会加密隐藏域名。 传统 SNI 明文可见,ECH 才是加密 ClientHello 的方向。
- 误区:SNI 和 Host 可以随便不一致。 不一致会导致证书、路由和安全策略问题。
- 追问:不支持 SNI 的客户端会怎样? 服务器通常返回默认证书,可能造成证书域名不匹配。
- 追问:CDN 为什么需要 SNI? 一个边缘 IP 承载多个域名,必须在握手时选择正确证书。
- 追问:如何排查 SNI? 用
openssl s_client -servername、抓包 ClientHello 或查看网关访问日志。
八、加强记忆
SNI 记成“TLS 版 Host,但更早出现”:它在 ClientHello 里告诉服务器目标域名,用来选证书;HTTP Host 在 TLS 之后才出现,用来做应用路由。多域名 HTTPS、CDN、Ingress 都离不开它。