本文介绍 TLS 1.3 中的 Encrypted Client Hello (ECH) 扩展,如何解决 SNI 明文泄露隐私问题。
SNI 隐私问题
在 TLS 握手过程中,客户端发送的 ClientHello 消息包含 Server Name Indication (SNI) 扩展,用于告知服务器希望连接的域名。问题在于:SNI 是明文传输的,任何中间设备(如 ISP、代理、防火墙)都可以看到用户正在访问哪个域名。
|
|
这意味着即使流量本身被加密,网络观察者仍能知道你访问了哪些网站。
ECH 解决方案
Encrypted Client Hello (ECH) 是 RFC 8446 的扩展,旨在加密 SNI 及其他敏感的 ClientHello 扩展。ECH 在 ClientHello 外层使用 ECH公钥 加密敏感的内部 ClientHello,只有目标服务器能解密。
工作原理
- DNS 配置:服务器在 DNS 的 HTTPS 记录中发布 ECH 公钥
- 客户端加密:客户端使用 ECH 公钥加密敏感的 ClientHello 信息
- 服务器解密:服务器用私钥解密,确认 ECH 隧道建立成功
- 握手继续:后续握手正常进行,SNI 已被加密
|
|
验证 ECH 支持
主流 CDN 提供商(如 Cloudflare)已支持 ECH。以下命令检查服务器是否支持 ECH:
|
|
实际输出示例:
|
|
客户端启用 ECH
Chrome 和 Firefox 已默认启用 ECH 支持。验证方法:
- 访问
chrome://flags/#encrypted-client-hello查看状态 - 访问 https://www.cloudflare.com/ssl/encrypted-sni/ 可测试 ECH 是否生效
DNS HTTPS 记录
ECH 公钥通过 DNS 的 HTTPS 记录(RFC 9460)分发。查看 cloudflare.com 的 HTTPS 记录:
|
|
输出包含 ECH 公钥信息:
|
|
ECH 配置格式
ECH 公钥以 Base64 编码的 ECHConfigList 形式存储在 DNS 中:
|
|
服务器端配置
Nginx 配置(需要支持 ECH 的后端)
Nginx 本身不直接处理 ECH,ECH 终止通常由上游 CDN 或代理完成。如果你使用 Cloudflare:
|
|
确保 DNS 正确配置 HTTPS 记录,CDN 提供商通常会自动处理。
自托管服务器配置
如果你需要自托管 ECH:
- 生成 ECH 密钥对
- 配置 DNS HTTPS 记录
- 在 TLS 握手时处理 ECH 扩展
使用 OpenSSL 可以生成 X25519 密钥(ECH 所需的 KEM):
|
|
ECH 安全性
防止的攻击
- 网络监控:攻击者无法看到用户访问的具体域名
- 流量分析:减少基于 SNI 的流量分类
- ** censorship**:部分绕过基于 SNI 的审查
限制
- 首包延迟:首次连接需要额外的 DNS 查询
- 兼容性:旧客户端回退到明文 SNI
- 部署复杂:需要正确的 DNS 配置
安全级别
ECH 提供与 TLS 加密同等级别的安全保障。即使攻击者拦截所有网络流量,也无法确定用户访问的具体域名。
验证 ECH 连接
使用 curl 测试
|
|
使用 Wireshark 观察
- 启动 Wireshark 并捕获 TLS 流量
- 筛选
tls.handshake.type == 1(ClientHello) - 观察 SNI 扩展是否被加密
常见问题
Q: ECH 和 ESNI 有什么区别?
A: ESNI 是 ECH 的前身,已被 ECH 取代。ESNI 仅加密 SNI,而 ECH 加密更多 ClientHello 扩展,并解决了前向安全性问题。
Q: ECH 是否会影响性能?
A: 首次连接需要额外 DNS 查询,后续连接可缓存 ECH 配置。总体影响可忽略不计。
Q: 如何确认我的网站已启用 ECH?
A: 使用 https://www.cloudflare.com/ssl/encrypted-sni/ 或运行 openssl s_client 检查服务器响应中的 ECH 扩展。
总结
ECH 是 TLS 1.3 的重要扩展,解决了长期存在的 SNI 隐私泄露问题。通过加密 ClientHello 中的敏感信息,用户访问的域名对网络观察者不可见。主流 CDN 已支持 ECH,自托管用户也逐步部署中。
随着隐私需求增长,ECH 将成为 TLS 标配。
参考来源