Encrypted Client Hello (ECH)
简介
本文介绍 TLS 1.3 的 Encrypted Client Hello (ECH) 扩展,它是 Encrypted Server Name Indication (ESNI) 的继任者,旨在加密 TLS 握手中的敏感信息以提升隐私保护。
本文回答
- ECH 是什么、解决什么问题
- ECH 的工作原理(ClientHelloInner/ClientHelloOuter 双重结构)
- ECH 与 REALITY 的关系和区别
- REALITY 中 ECH 的支持情况
本文在项目中的位置
本文属于背景知识层。ECH 是与 REALITY 同领域的隐私增强技术,但解决问题的方式不同。理解两者的区别对于理解 REALITY 的设计选择很重要。
适合读者
所有想理解 TLS 隐私增强技术的读者。
前置知识
TLS 1.3 握手流程,HPKE 基础概念,SNI 的作用。
文章理解难度
中等。需要理解 TLS 握手消息结构。
重点
- ECH 如何使用 HPKE 加密 ClientHello
- ECH 与 REALITY 在设计思路上的本质区别
- REALITY 中的 ECH 支持
上级文档和相关文档
主要证据
Cloudflare ECH 技术博客,RFC draft-ietf-tls-esni,wolfSSL ECH 实现文档,REALITY ech.go 源码。
SNI 的隐私问题
SNI(Server Name Indication)是 TLS 握手中的一个关键字段。当一台服务器托管多个 HTTPS 网站时,客户端在 ClientHello 中以明文发送 SNI,告知服务器需要哪个网站的证书。
SNI 明文的隐私问题:
- 网络路径上的任何观察者都可以看到用户正在访问哪个域名
- 审查方可以基于 SNI 实施域名级别的访问控制
- ISP 可以收集用户浏览的域名信息
ECH 的设计目标就是解决这个问题——加密 ClientHello 中的敏感字段。
ECH 工作原理
ECH 是 TLS 1.3 的一项扩展(RFC draft-ietf-tls-esni),其核心思想是使用双重 ClientHello 结构:
双重 ClientHello 结构
ClientHelloOuter(明文,发送到网络)
├── 版本、随机数等普通字段
├── SNI: cover.example.com(掩护域名)
├── 密码套件、扩展等(与正常 ClientHello 相同)
└── ECH Extension
└── ClientHelloInner(加密)
├── SNI: real-target.example.com(真实目标域名)
├── 真实的密码套件和扩展
└── 其他敏感字段ECH 握手流程
关键机制
HPKE 加密:ECH 使用 HPKE(Hybrid Public Key Encryption)加密 ClientHelloInner。HPKE 结合了非对称加密(密钥交换)和对称加密(AES-128/256-GCM 或 ChaCha20Poly1305),一次握手即可安全传输加密内容。
ECH 配置分发:客户端在连接前需要获取服务端的 ECH 公钥(ECHConfigList)。获取方式包括:
- DNS HTTPS 记录(通过 DoH/DoT 防止 DNS 层面的篡改)
- 前一次连接中的 retry_configs
回退机制:如果 ECH 被服务端拒绝,服务端会发送
ECHRetry消息,其中可能包含新的 ECHConfig 供客户端重试。客户端会收到ECHRejectionError。
ECH 的安全性
ECH 保护 ClientHello 中的敏感信息不被网络观察者读取,但:
- 客户端 IP 地址仍然暴露
- 服务端 IP 地址仍然暴露
- 数据包的大小和时序特征仍然可观察
- ECH 本身不阻止主动探测
ECH vs REALITY
| 维度 | ECH | REALITY |
|---|---|---|
| 问题 | 保护用户隐私,防止 SNI 泄露 | 对抗网络审查,防止代理流量被检测 |
| 方法 | 加密 ClientHello 中的敏感字段 | 将代理流量伪装成普通 HTTPS 流量 |
| 证书 | 使用真实 CA 签发的证书 | 使用临时自签 Ed25519 证书(带认证) |
| SNI 处理 | 加密真实 SNI,使用掩护域名 | 直接使用目标网站的真实 SNI |
| 部署要求 | 需要控制服务端(配置 ECH 密钥) | 不需要控制目标网站(指向任何网站即可) |
| 对审查方的可见性 | 能看到加密的 ClientHello(知道有人在使用 ECH) | 看到的完全就是普通 HTTPS 流量 |
| 标准化状态 | IETF 草案,接近最终标准 | 非标准协议,项目自有的实现 |
ECH 和 REALITY 解决的是不同层面的问题:
- ECH 是隐私增强技术,让审查方不知道你访问了哪个网站
- REALITY 是流量伪装技术,让审查方不知道你使用了代理
两者可以组合使用——REALITY 服务端的 TLS 实现确实包含了 ECH 支持。
REALITY 中的 ECH
源码位置:REALITY/ech.go(20,047 字节)
REALITY 的 TLS fork 实现了 ECH 草案的支持,包括:
- 客户端 ECH:当配置了
EncryptedClientHelloConfigList时,客户端会尝试使用 ECH - 服务端 ECH:当配置了
EncryptedClientHelloKeys时,服务端可以处理 ECH 请求 - HPKE 支持:
REALITY/hpke/目录包含 HPKE 的实现(hpye.go)
在 xray-core 的 TLS 传输层(xray-core/transport/internet/tls/ech.go)中,ECH 配置被映射到 TLS 连接配置:
// 客户端配置
tlsConfig.EncryptedClientHelloConfigList = ... // ECH Config
// 服务端配置
tlsConfig.EncryptedClientHelloKeys = ... // ECH 密钥使用场景
- REALITY + ECH:REALITY 负责流量伪装,ECH 额外加密 SNI——让审查方既看不到你的目标域名,也看不出你在使用代理
- TLS + ECH:在标准的 TLS 传输层中启用 ECH,适用于不需要 REALITY 级别伪装但需要 SNI 隐私的场景
外部参考资料
资料:Good-bye ESNI, hello ECH! 类型:技术博客(Cloudflare) 链接:https://blog.cloudflare.com/encrypted-client-hello 可信度:A,Cloudflare 是 ECH 标准的主要推动者之一
资料:wolfSSL ECH 实现和文档 类型:官方文档 链接:https://www.wolfssl.com/how-and-why-to-use-ech-encrypted-client-hello 可信度:A
资料:REALITY ech.go 源码 类型:源码 链接:
REALITY/ech.go可信度:A
读者自检
读完本文后应能回答:
- ECH 解决的核心问题
- ClientHelloInner/ClientHelloOuter 的区别
- HPKE 在 ECH 中的作用
- ECH 和 REALITY 的核心区别
- 两者如何组合使用
下一步阅读
- QUIC 协议:理解新一代传输协议
- REALITY 协议详解