HTTPS 握手与 ECH 详解:SNI 为什么会泄露访问目标,ECH 如何加密它
导读摘要:图解 TLS 1.2 与 TLS 1.3 的握手过程,说明哪些信息是明文(SNI、TLS 1.2 的证书),网络设备如何据此识别和阻断;再讲 ESNI 到 ECH 的演进、DNS HTTPS 记录如何分发 ECH 公钥,以及如何检测浏览器是否启用了 ECH。
简短回答:HTTPS 握手时,客户端在第一个包(ClientHello)里用明文写上要访问的域名,这个字段叫 SNI。网络设备读取 SNI 就能知道你在访问哪个网站,并据此阻断。ECH(Encrypted Client Hello)用网站提前在 DNS 中公布的公钥加密真实的 ClientHello,外部只能看到一个公共的「外层」域名。
一、TLS 握手过程:哪些是明文
TLS 1.3(目前主流)的握手大致是:
- ClientHello(明文):支持的加密套件、密钥交换参数(key_share)、SNI、ALPN(如 h2、http/1.1);
- ServerHello(明文):选定的套件和服务器的密钥交换参数。此时双方已能算出会话密钥;
- 之后的 EncryptedExtensions、证书、Finished 都已加密。
TLS 1.2 中服务器证书是明文发送的,观察者还能直接看到证书上的域名。TLS 1.3 把证书加密了,但 SNI 仍然是明文,这就是 ECH 要解决的「最后一块拼图」。
用 Wireshark 抓包时,过滤 tls.handshake.type == 1 就能看到 ClientHello,展开 Extension: server_name 即可看到明文域名。
二、SNI 如何被用来识别和阻断
因为 SNI 在加密之前发送,网络中间设备不需要解密就能读取。常见做法是匹配域名名单,命中后发送 TCP RST 中断连接,或直接丢弃后续数据包。表现为:IP 能连通,但浏览器提示「连接已重置」。
三、从 ESNI 到 ECH
早期方案 ESNI 只加密 SNI 一个字段,但 ClientHello 里的其他扩展仍会泄露信息,而且 ESNI 本身容易被识别。于是标准改为 ECH,加密整个 ClientHello:
- 外层 ClientHello(明文):使用公共域名(例如 CDN 的通用域名),不含敏感信息;
- 内层 ClientHello(用 HPKE 加密):包含真实 SNI、ALPN 等全部参数。
四、ECH 公钥从哪里来:DNS HTTPS 记录
客户端连接前,先查询网站的 HTTPS 资源记录(DNS 类型 65),其中的 ech 字段就是加密用的公钥配置:
$ dig cloudflare-ech.com HTTPS +short
1 . alpn="h3,h2" ipv4hint=... ech=AEX+DQBB...
如果这一步 DNS 查询是明文的,攻击者可以篡改或删除 ech 字段,让客户端退回普通握手。所以 ECH 要和加密 DNS(DoH)一起使用,见 DoH / DoT / DoQ 详解。
五、在浏览器中启用和检测
- Chrome、Edge、Firefox 的较新版本已默认支持 ECH,但通常要求同时开启「安全 DNS」(DoH);
- 在浏览器设置里开启安全 DNS,选择一个可用的 DoH 服务;
- 访问
https://crypto.cloudflare.com/cdn-cgi/trace,看到sni=encrypted即说明 ECH 生效。
六、ECH 的局限
- 需要网站(或其 CDN)支持,目前主要是部署在 Cloudflare 等支持 ECH 的 CDN 上的网站;
- 目标 IP 仍然可见,如果某个 IP 只服务一个网站,加密 SNI 意义有限;
- 网络设备可以选择阻断所有使用 ECH 的连接,迫使客户端回退。
与之相关的另一种技术是「域前置」,它通过伪造 SNI 而不是加密 SNI 来隐藏目标,原理和现状见域前置详解。
常见问题
HTTPS 不是加密的吗,为什么还能知道我访问了哪个网站?
HTTPS 加密的是网页内容,但握手第一个包里的 SNI(服务器名称)是明文的,另外 DNS 查询和目标 IP 也可能暴露访问目标。ECH 加密 SNI,加密 DNS 保护查询,两者配合才更完整。
怎么知道浏览器是否启用了 ECH?
访问 Cloudflare 的 crypto.cloudflare.com/cdn-cgi/trace,结果中出现 sni=encrypted 表示本次连接使用了 ECH;只有对方网站也支持 ECH 时才会生效。
💡 机场情报局精选推荐:高品质海外节点与 IEPL 专线是流畅访问的基础,欢迎查阅我们的实时评测:【2026 稳定高速机场推荐榜单】。