文章目录
- 深入理解 SNI(Server Name Indication)
- 一、为什么需要 SNI
- 二、SNI 的核心原理
- 三、SNI 工作流程
-
- 没有 SNI
- 有 SNI
- 四、SNI 在 TLS 中的位置
- 五、SNI 最大的价值
-
- 1. 一个 IP 支持多个 HTTPS 网站
- 2. 降低 HTTPS 部署成本
- 3. CDN 的基础能力之一
- 六、Nginx 中的 SNI
- 七、Kubernetes Ingress 中的 SNI
- 八、SNI 与 Host Header 的区别
-
- SNI
- Host Header
- 对比
- 九、如何查看 SNI
-
- 示例
- 不带 SNI 的情况
- 十、SNI 的安全问题
- 十一、ESNI / ECH
-
- ESNI(Encrypted SNI)
- ECH(Encrypted Client Hello)
- 十二、SNI 与 TLS 终止
- 十三、典型应用场景
-
- CDN
- API Gateway
- Kubernetes
- 云负载均衡
- 十四、SNI 与 HTTP/2 / HTTP/3
- 十五、抓包观察 SNI
- 十六、常见面试题
-
- 1. 为什么 HTTPS 需要 SNI?
- 2. SNI 在哪一层?
- 3. SNI 和 Host Header 区别?
- 4. SNI 是否加密?
- 十七、总结
- 最后一句话
深入理解 SNI(Server Name Indication)
在现代 HTTPS 通信中,一个 IP 地址往往需要承载多个 HTTPS 网站。 但 TLS 握手发生在 HTTP 请求之前,服务器还不知道客户端到底想访问哪个域名。
这时候,SNI(Server Name Indication)就登场了。
SNI 是 TLS 协议中的一个扩展,用于让客户端在 TLS 握手阶段提前告诉服务器:
“我要访问的域名是哪个。”
它是现代 HTTPS 虚拟主机能力的核心基础之一。
一、为什么需要 SNI
先看一个经典问题。
假设:
同一个服务器 IP:
203.0.113.10
托管两个 HTTPS 网站:
example.com
api.example.com
HTTPS 连接建立时:
于是问题来了:
服务器该返回哪个 TLS 证书?
如果没有 SNI:
- 一个 IP 基本只能对应一个 HTTPS 证书
- 多 HTTPS 虚拟主机难以实现
这就是早期 HTTPS 部署成本高的重要原因之一。
二、SNI 的核心原理
SNI 的思路非常简单:
客户端在 TLS ClientHello 中携带目标域名。
这样服务器在握手阶段就能知道:
客户端想访问:
example.com
于是服务器就可以:
- 选择正确证书
- 选择正确 TLS 配置
- 路由到对应虚拟主机
三、SNI 工作流程
下面是 HTTPS 建立连接时的流程。
没有 SNI
Client —- TLS Handshake —-> Server
Server:
“你访问哪个域名?”
Client:
“还没说……”
服务器无法正确选择证书。
有 SNI
Client —- ClientHello(SNI=example.com) —-> Server
Server:
“哦,你要访问 example.com”
“这是对应证书”
服务器可以正确返回:
- example.com 的证书
- 对应 TLS 配置(注:不同域名必须有独立的 TLS 配置,“正确 TLS 配置” = 与目标域名匹配的证书 + 协议参数 + 安全策略)
四、SNI 在 TLS 中的位置
SNI 位于:
TLS ClientHello Extension
也就是说:
客户端在 TLS 握手第一阶段就会发送。
大致结构:
ClientHello
├── TLS Version
├── Cipher Suites
├── Extensions
│ └── server_name (SNI)
│ └── example.com
五、SNI 最大的价值
1. 一个 IP 支持多个 HTTPS 网站
这是最核心价值。
例如:
203.0.113.10
├── a.com
├── b.com
├── c.com
每个域名:
- 都有独立证书
- 都能正常 HTTPS
没有 SNI 基本无法实现。
2. 降低 HTTPS 部署成本
以前:
一个 HTTPS 网站
≈ 一个独立 IP
IPv4 非常昂贵。
SNI 出现后:
多个 HTTPS 网站共享同一 IP
极大推动 HTTPS 普及。
3. CDN 的基础能力之一
CDN 边缘节点通常:
一个 IP 承载成千上万域名
例如:
- CDN
- 云负载均衡
- API Gateway
- Ingress Controller
都严重依赖 SNI。
六、Nginx 中的 SNI
Nginx 会根据 SNI 自动选择 server block。
例如:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate example.crt;
}
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate api.crt;
}
客户端:
SNI=api.example.com
Nginx:
返回 api.crt
七、Kubernetes Ingress 中的 SNI
Ingress Controller 本质也依赖 SNI。
例如:
spec:
tls:
– hosts:
– api.example.com
secretName: api–cert
Ingress Controller:
因此:
TLS Host Routing
本质上就是 SNI Routing
八、SNI 与 Host Header 的区别
很多人容易混淆:
- SNI
- HTTP Host Header
它们完全不是一个层次。
SNI
发生在:
TLS 层
发送时间:
TLS 握手阶段
用途:
选择证书
Host Header
发生在:
HTTP 层
发送时间:
TLS 建立完成后
用途:
路由 HTTP 请求
对比
| 所属层 | TLS | HTTP |
| 发送时间 | TLS 握手时 | HTTP 请求时 |
| 作用 | 选择证书 | 路由请求 |
| 是否加密 | 明文(传统 TLS) | HTTPS 下会被加密 |
九、如何查看 SNI
可以使用 OpenSSL。
示例
openssl s_client \\
-connect example.com:443 \\
-servername example.com
其中:
-servername
就是显式指定 SNI。
不带 SNI 的情况
openssl s_client -connect example.com:443
有些网站会:
- 返回错误证书
- TLS 握手失败
- 返回默认站点
因为服务器不知道你访问哪个域名。
十、SNI 的安全问题
这里有个重要知识点:
传统 SNI 是明文的。
即使使用 HTTPS:
TLS ClientHello
中的 SNI 仍然可见
因此:
- ISP
- 防火墙
- 中间网络设备
仍然能看到:
你访问了哪个域名
虽然看不到:
- 完整 URL
- Cookie
- HTTP 内容
但域名本身仍会暴露。
十一、ESNI / ECH
为了解决 SNI 明文问题:
后来提出:
ESNI(Encrypted SNI)
后来演进为:
ECH(Encrypted Client Hello)
目标:
加密 TLS ClientHello
包括:
- SNI
- 扩展信息
这样网络中间人无法看到目标域名。
十二、SNI 与 TLS 终止
很多网关都会做 TLS Termination:
Client
↓ HTTPS
Load Balancer / Gateway
↓ HTTP
Backend Service
在 TLS 终止阶段:
- 网关读取 SNI
- 选择证书
- 建立 TLS
例如:
- Nginx
- Envoy
- HAProxy
- Kong
- AWS ALB
都 heavily 使用 SNI。
十三、典型应用场景
CDN
Cloudflare
Fastly
CloudFront
API Gateway
Kong
APISIX
Traefik
Kubernetes
Ingress Controller
Gateway API
云负载均衡
AWS ALB
GCP Load Balancer
Azure Front Door
十四、SNI 与 HTTP/2 / HTTP/3
SNI 与 HTTP 版本无关。
即使:
- HTTP/2
- HTTP/3
底层 TLS 仍然需要:
SNI
尤其:
HTTP/3 使用 QUIC + TLS 1.3:
ClientHello 中依旧存在 SNI
十五、抓包观察 SNI
使用 Wireshark:
过滤:
tls.handshake.extensions_server_name
即可看到:
Server Name: example.com
这是分析 TLS 流量时非常常见的方法。
十六、常见面试题
1. 为什么 HTTPS 需要 SNI?
因为:
TLS 握手先于 HTTP 请求
服务器需要提前知道域名来选择证书。
2. SNI 在哪一层?
TLS 层
3. SNI 和 Host Header 区别?
- SNI:TLS 阶段选证书
- Host Header:HTTP 阶段路由请求
4. SNI 是否加密?
传统 TLS 中:
不加密
ECH 才会加密。
十七、总结
SNI 本质上是:
TLS 握手阶段的“域名提示机制”
它解决了:
一个 IP 承载多个 HTTPS 网站
的问题。
现代互联网大量基础设施都依赖 SNI:
- CDN
- Ingress
- API Gateway
- 云负载均衡
- Service Mesh
可以说:
没有 SNI,就没有今天低成本、大规模 HTTPS 的普及。
最后一句话
记住这句话:
Host Header 决定 HTTP 路由
SNI 决定 TLS 证书
这是理解现代 HTTPS 网关体系的关键。




