SNI - Server Name Indication, TLS 握手时,客户端告诉服务器"我要访问哪个域名"的字段。
传统问题:
服务器 IP: 1.2.3.4
├── site-a.com (证书 A)
├── site-b.com (证书 B)
└── site-c.com (证书 C)
客户端连接 1.2.3.4 时:
服务器不知道该返回哪个证书
SNI 解决方案:
客户端 TLS ClientHello:
├── "我要访问 site-b.com" ← SNI 字段
│
服务器收到后:
└── "好的,返回 site-b.com 的证书"
正常情况:
客户端 ──► SNI: google.com ──► 真正的 google.com
SNI 欺骗:
客户端 ──► SNI: google.com ──► 实际连接恶意服务器
(防火墙看到 google.com,放行)
(但实际流量去了攻击者服务器)
攻击手法是攻击者利用防火墙只检查 SNI 不验证证书的漏洞:
1. 攻击者控制 malware.com(IP: 1.2.3.4)
2. 客户端被感染,发起连接:
- TCP 连接到 1.2.3.4
- TLS ClientHello 中 SNI 设为 "google.com"
3. 防火墙检查 SNI = google.com → 放行
4. 实际流量去了恶意服务器 1.2.3.4
| 防火墙检查 | 是否被欺骗 |
|---|---|
| 只检查 SNI | 容易被欺骗 |
| 检查 IP 黑名单 | 新 IP 无法检测 |
| 检查 SNI + 验证证书 | 无法欺骗 |
客户端 ClientHello
├── SNI: google.com
│
防火墙检查 ServerHello 中的证书
├── 证书 CN/SAN 是否匹配 google.com?
├── 证书是否由可信 CA 签发?
├── 证书是否过期?
│
如果不匹配 → 阻止连接
流程对比,无证书验证(易被攻击):
客户端 ──► SNI: google.com ──► 防火墙检查 SNI ──► 放行
│
只看 SNI,不管证书
│
实际连接恶意服务器 ✗
有证书验证(安全):
客户端 ──► SNI: google.com ──► 防火墙
│
┌───────────┴───────────┐
│ 检查服务器返回的证书 │
│ CN/SAN = google.com? │
│ CA 可信? │
└───────────┬───────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
证书匹配 证书不匹配 无效证书
(真正的 Google) (恶意服务器) (自签/过期)
│ │ │
▼ ▼ ▼
放行 阻止 阻止