1. 引言:HTTPS 的 “皇帝新衣”—— 你以为加密了,其实隐私还在裸奔

2026 年 3 月,IETF 正式发布RFC 9849,将 Encrypted Client Hello(ECH,加密客户端问候)确立为 TLS 1.3 协议的正式标准扩展。这一标准的落地,标志着互联网长达 20 年的 HTTPS 隐私漏洞终于被彻底填补 —— 在此之前,哪怕你访问的网站开启了 HTTPS,你的网络运营商、防火墙、中间网络设备,依然能精准知道你正在访问哪个网站,哪怕他们无法看到你和网站之间传输的具体内容。

1.1 一个所有人都忽略的 HTTPS 隐私缺口

HTTPS 的普及,让互联网进入了 “全加密时代”。截至 2026 年,全球超过 95% 的网站启用了 HTTPS,浏览器会对未加密的 HTTP 站点标记 “不安全” 警告。绝大多数用户都认为:只要地址栏有小锁图标,我的所有网络行为就是加密的,没人能窥探。

但事实并非如此。

我们可以用 Wireshark 抓一个最普通的 HTTPS 握手包,你会发现一个惊人的事实:在 TLS 握手的第一个报文 ——Client Hello中,你要访问的网站域名(SNI 字段)以完全明文的形式传输。比如你访问www.private-example.com,哪怕网站用了最顶级的 EV SSL 证书,中间的网络设备依然能清晰地看到这个域名,进而记录你的上网行为、构建用户画像、甚至针对性地进行内容过滤和流量劫持。

1.2 SNI 明文泄露的危害:比你想象的更严重

SNI(Server Name Indication,服务器名称指示)是 TLS 协议的核心扩展,诞生于 2003 年。它的出现解决了一个核心工程问题:一个 IP 地址对应多个域名的虚拟主机场景下,服务器需要知道客户端要访问哪个域名,才能返回对应的 SSL 证书

就像你给一栋有 100 个房间的公寓楼寄快递,必须在信封上写明具体的房间号,否则快递员不知道该送给谁。SNI 就是这个 “房间号”,但在 ECH 出现之前,这个房间号是完全写在信封表面的,所有经手的人都能看到。

这个看似不起眼的明文字段,带来了极其严重的隐私和安全风险:

  1. 用户上网隐私完全泄露:网络运营商、ISP、企业网管可以通过 SNI 完整记录用户的所有网站访问记录,哪怕内容是加密的。这些数据可以被用于广告投放、用户画像,甚至被非法售卖。
  2. 针对性的内容审查与阻断:全球范围内的网络防火墙,核心的网站阻断手段就是基于 SNI 字段。哪怕网站的 IP 地址可以访问,只要 SNI 是被封禁的域名,防火墙就可以直接阻断连接。
  3. 流量劫持与钓鱼攻击:中间人可以通过 SNI 获取用户要访问的域名,进而伪造对应的虚假证书,实施钓鱼攻击和流量劫持,尤其是在公共 Wi-Fi 场景下,这种攻击的门槛极低。
  4. 企业敏感信息泄露:企业内部的私有 API、管理后台域名,通过 SNI 明文泄露,会给攻击者提供精准的攻击目标,扩大攻击面。

1.3 从 ESNI 到 ECH:长达 8 年的隐私保护攻坚战

为了解决 SNI 明文泄露的问题,IETF 早在 2018 年就启动了相关标准的制定,第一个方案就是ESNI(Encrypted SNI,加密 SNI)。Cloudflare、Firefox 等厂商率先试点部署了 ESNI,但在实践过程中,IETF 发现 ESNI 存在致命的设计缺陷,无法满足工业级的安全和兼容性需求:

  • 只加密 SNI,治标不治本:ESNI 只加密了 SNI 字段,但 Client Hello 里的 ALPN、PSK、status_request 等扩展依然是明文,这些信息依然会泄露网站的服务类型、版本等敏感内容,攻击者依然可以通过这些字段进行指纹识别。
  • 兼容性极差:ESNI 的密钥通过 DNS TXT 记录分发,而 DNS 缓存的存在,会导致客户端拿到过期的密钥,进而握手失败,用户体验极差。
  • 抗降级攻击能力弱:中间人可以直接剥离 Client Hello 里的 ESNI 扩展,让客户端回退到明文 SNI 模式,而客户端无法感知这种攻击。
  • 错误处理机制缺失:如果服务端解密 ESNI 失败,会直接断开连接,没有重试机制,导致用户无法访问网站。

2020 年,IETF 正式废弃了 ESNI 草案,重新设计了一套全新的解决方案 ——Encrypted Client Hello(ECH)。和 ESNI 只加密 SNI 不同,ECH 的核心设计是加密整个 Client Hello 报文,彻底解决握手阶段的明文泄露问题。经过 6 年的迭代和 17 个草案版本,2026 年 3 月,ECH 正式发布为 RFC 9849 标准,成为 TLS 1.3 协议的官方扩展。

截至 2026 年 5 月,Chrome、Firefox、Edge、Safari 四大主流浏览器均已默认启用 ECH,Cloudflare、AWS、Azure 等云厂商已在全球节点部署 ECH,全球超过 30% 的 HTTPS 站点已启用 ECH,互联网正式进入了 “HTTPS 全链路加密” 的新时代。

2. 前置知识:TLS 1.3 握手与 SNI 的本质

要彻底搞懂 ECH,首先需要理解两个核心问题:TLS 1.3 的握手流程到底是怎样的?为什么 Client Hello 必须有明文内容?

2.1 什么是 SNI?为什么它必须存在?

在互联网早期,一个 IP 地址只对应一个网站,服务器只需要返回唯一的证书即可,不需要 SNI。但随着虚拟主机技术的普及,一个 IP 地址会承载几十、上百个不同的域名,每个域名都有自己独立的 SSL 证书。

这时问题就出现了:TLS 握手的第一步,客户端就需要服务器返回对应的 SSL 证书,来验证服务器的身份;但服务器不知道客户端要访问哪个域名,就不知道该返回哪个证书。这就形成了一个 “先有鸡还是先有蛋” 的死循环。

SNI 扩展就是为了解决这个问题诞生的:客户端在发起 TLS 握手的第一个报文 Client Hello 里,就明文带上自己要访问的域名,服务器根据这个域名,选择对应的 SSL 证书返回给客户端,完成握手。

这就是为什么 SNI 必须在 Client Hello 里以明文传输 —— 在握手完成之前,客户端和服务器还没有协商出加密密钥,无法对内容进行加密。这也是 HTTPS 诞生以来,一直无法解决的核心矛盾。

2.2 TLS 1.3 的完整握手流程:哪些内容在裸奔?

TLS 1.3 是目前最新的 TLS 协议版本,相比 TLS 1.2,它把握手从 2-RTT(往返)压缩到了 1-RTT,大幅提升了性能,同时加密了大部分握手内容。但它依然没有解决 Client Hello 的明文泄露问题。

我们先看一下标准的 TLS 1.3 1-RTT 握手流程,以及每个阶段的加密状态:

步骤 报文方向 报文内容 加密状态 核心敏感信息
1 客户端→服务端 Client Hello 完全明文 客户端随机数、支持的 TLS 版本、加密套件、SNI 域名、ALPN 扩展、支持的椭圆曲线、密钥共享、Session Ticket 等
2 服务端→客户端 Server Hello 明文 服务端随机数、选择的加密套件、密钥共享
3 服务端→客户端 Encrypted Extensions 加密 支持的 ALPN 协议、证书状态请求等
4 服务端→客户端 Certificate 加密 服务器 SSL 证书链
5 服务端→客户端 Certificate Verify 加密 服务器证书签名验证
6 服务端→客户端 Finished 加密 握手完成校验码
7 客户端→服务端 Finished 加密 客户端握手完成校验码
8 双向 应用数据 加密 HTTP 请求 / 响应等业务数据

可以清晰地看到:整个 TLS 1.3 握手流程中,只有 Client Hello 和 Server Hello 是明文传输的,其余所有报文都是加密的。而 Server Hello 里没有任何用户隐私信息,真正的隐私泄露点,完全集中在 Client Hello 报文里。

更关键的是,Client Hello 里泄露的不只是 SNI 域名,还有大量敏感扩展:

  • ALPN 扩展:明文告诉外界客户端和服务器支持的应用层协议,比如 HTTP/2、HTTP/3、WebSocket,攻击者可以通过这个字段推断服务的类型和用途。
  • status_request 扩展:OCSP 证书状态请求,泄露证书的 CA 机构信息。
  • supported_groups 扩展:客户端支持的椭圆曲线,泄露客户端的软件类型和版本。
  • PSK 扩展:会话复用的预共享密钥,泄露用户之前的访问记录。

这就是 ECH 要解决的核心问题:它要把整个 Client Hello 里的所有敏感内容,全部加密起来,让中间网络设备看不到任何隐私信息。

2.3 为什么 TLS 1.3 不直接加密 Client Hello?

看到这里,很多人会问:既然 Client Hello 明文泄露这么严重,为什么 TLS 1.3 设计的时候,不直接把它加密?

答案很简单:加密需要密钥,而密钥需要通过握手协商出来

TLS 的加密密钥,是通过客户端和服务端的密钥交换算法(比如 ECDH)协商出来的,而密钥交换的参数,必须在 Client Hello 和 Server Hello 里传输。也就是说,在客户端发送 Client Hello 的时候,双方还没有任何共享的加密密钥,根本无法对内容进行加密。

这就是 HTTPS 的核心悖论:你需要用握手来协商加密密钥,但握手的第一个报文,却无法用这个密钥来加密

而 ECH 的出现,完美地解决了这个悖论。它用一套全新的设计,让客户端在发送 Client Hello 之前,就提前拿到了服务端的公钥,进而对 Client Hello 进行加密,同时不破坏 TLS 协议的兼容性。

3. ECH 的核心设计原理:双层 Client Hello 与 HPKE 加密体系

ECH 的核心设计思想,可以用一个非常形象的比喻来解释:信封套信封

我们把 TLS 握手比作寄快递:

  • 传统的 TLS 握手,就像你把快递内容用密码锁锁在了箱子里(应用数据加密),但快递单上明文写了收件人的详细地址(SNI),所有经手的快递员都能看到你要寄给谁。
  • 而 ECH,就像你把写有真实收件地址的快递单,放在了一个加密的内层信封里;外层信封上只写了大楼的公共地址(比如 “XX 科技园 CDN 节点”),只有大楼的门卫(服务端)有内层信封的钥匙,能打开看到真实的收件地址,然后把快递转交给对应的收件人。所有经手的快递员,只能看到外层的公共地址,完全不知道真实的收件人是谁。

这个设计,就是 ECH 的核心:双层 Client Hello 结构,配合HPKE 混合公钥加密体系,实现了 Client Hello 的全加密,同时完美兼容现有的 TLS 1.3 协议和 CDN / 多租户场景。

3.1 双层 Client Hello:ECH 的核心结构

ECH 把传统的单个 Client Hello,拆分成了两个部分:ClientHelloOuter(外层客户端问候)ClientHelloInner(内层客户端问候)

3.1.1 ClientHelloInner:真实的、加密的请求

内层 ClientHelloInner,是客户端真正要发送给目标服务的握手报文,包含了所有敏感信息:

  • 真实的目标域名 SNI;
  • 真实的 ALPN 扩展、supported_groups 扩展等所有敏感扩展;
  • 客户端随机数、密钥共享等握手必须的参数。

整个 ClientHelloInner 会被完整加密,只有持有对应私钥的服务端才能解密,中间网络设备完全看不到里面的任何内容。

3.1.2 ClientHelloOuter:明文的、伪装的外层信封

外层 ClientHelloOuter,是一个完全合规的、标准的 TLS 1.3 Client Hello 报文,它的作用是作为 “外层信封”,承载加密后的 Inner 报文,同时保证和现有网络设备的兼容性:

  • 它的 SNI 字段,填写的是public_name(公共域名),比如 CDN 厂商的公共域名,或者服务端的默认域名,是完全明文的;
  • 它包含了非敏感的握手参数,比如支持的 TLS 版本、加密套件,和 Inner 里的参数保持一致;
  • 它包含了一个ech 扩展,里面存放了加密后的 ClientHelloInner 密文,以及 HPKE 加密所需的参数。

对于中间的防火墙、网络设备来说,它们看到的是一个完全标准的、合规的 TLS 1.3 Client Hello 报文,访问的是 public_name 对应的公共域名,不会有任何兼容性问题。只有目标服务端,才能用自己的私钥,解密 ech 扩展里的 Inner 密文,拿到真实的握手参数和目标域名。

这个设计,完美解决了 TLS 的 “先有鸡还是先有蛋” 的悖论:

  • 客户端用服务端提前发布的公钥,加密 Inner 报文,放在 Outer 的 ech 扩展里;
  • 服务端用自己的私钥解密 Inner,拿到真实的 SNI 和握手参数,完成后续的握手流程;
  • 整个过程完全兼容 TLS 1.3 标准,不需要修改协议的核心流程。

3.2 加密基石:HPKE 混合公钥加密(RFC 9180)

ECH 的加密能力,完全依赖于HPKE(Hybrid Public Key Encryption,混合公钥加密),这是 IETF 在 RFC 9180 中标准化的通用混合加密体系,也是 ECH 的核心密码学基石IETF。

3.2.1 什么是 HPKE?为什么不用传统的 RSA 加密?

传统的公钥加密,比如 RSA,是用接收方的公钥直接加密数据,然后接收方用私钥解密。但这种方式有两个致命的缺陷,不适合 ECH 的场景:

  1. 性能差,无法加密长数据:RSA 非对称加密只能加密很短的数据(比如 2048 位 RSA 最多加密 245 字节),而 ClientHelloInner 的长度可能达到上千字节,无法直接用 RSA 加密。
  2. 没有前向安全性:如果服务端的长期私钥泄露,所有历史加密的报文都能被解密,隐私完全泄露。
  3. 抗攻击能力弱:传统的 RSA 加密容易受到选择密文攻击,安全性无法满足工业级需求。

而 HPKE 是一套标准化的混合加密方案,结合了非对称加密和对称加密的优势,完美解决了这些问题:

  • 非对称加密仅用于协商临时会话密钥,不直接加密业务数据,性能极高,支持任意长度的明文加密;
  • 每次加密都生成全新的临时密钥对,保证前向安全性,即使长期私钥泄露,历史流量也无法解密;
  • 原生支持认证加密,具备抗选择密文攻击的能力,安全性经过严格的密码学证明;
  • 模块化设计,支持任意的 KEM、KDF、AEAD 算法组合,兼容椭圆曲线、后量子密码等多种密码学体系。
3.2.2 HPKE 的核心组件与工作流程

HPKE 由三个核心密码学组件构成,三者配合完成完整的加密解密流程:

  1. KEM(Key Encapsulation Mechanism,密钥封装机制):负责生成临时会话密钥。发送方生成临时密钥对,和接收方的公钥进行密钥协商,生成共享密钥,同时输出一个封装密钥(enc),发送给接收方。接收方用自己的私钥和封装密钥,解封装出相同的共享密钥。
  2. KDF(Key Derivation Function,密钥派生函数):基于 KEM 生成的共享密钥,加上上下文信息,派生出最终的对称加密密钥,保证不同场景的密钥隔离。
  3. AEAD(Authenticated Encryption with Associated Data,带关联数据的认证加密):用 KDF 派生的对称密钥,对明文进行加密,同时生成认证标签,保证密文的完整性和真实性。接收方解密的同时,会验证认证标签,防止密文被篡改。

HPKE 的基础工作流程非常简单,分为发送方加密和接收方解密两个环节:

  • 发送方(客户端)加密流程
    1. 获取接收方(服务端)的长期公钥;
    2. 生成临时密钥对,通过 KEM 算法和接收方公钥,计算出共享密钥和封装密钥 enc;
    3. 通过 KDF 算法,从共享密钥中派生出 AEAD 加密密钥;
    4. 用 AEAD 算法加密明文(ClientHelloInner),生成密文和认证标签;
    5. 把封装密钥 enc、密文、认证标签一起发送给接收方。
  • 接收方(服务端)解密流程
    1. 收到发送方的封装密钥 enc、密文、认证标签;
    2. 用自己的长期私钥和 enc,通过 KEM 算法解封装出相同的共享密钥;
    3. 通过相同的 KDF 算法,派生出相同的 AEAD 解密密钥;
    4. 用 AEAD 算法解密密文,验证认证标签,确认密文没有被篡改,最终得到明文。

在 ECH 中,HPKE 的应用完全遵循这个流程:客户端用服务端提前发布的公钥,加密 ClientHelloInner;服务端用自己的私钥解密,拿到真实的握手报文。同时,ECH 严格规定了 HPKE 的加密套件,默认使用DHKEM(X25519, HKDF-SHA256) + AES-GCM的组合,保证了不同厂商实现的兼容性。

3.3 ECH 的两种部署拓扑:共享模式与分割模式

RFC 9849 定义了 ECH 的两种部署拓扑,分别适配不同的业务场景,这也是 ECH 相比 ESNI 的重大改进之一,完美兼容了 CDN、多租户等复杂的工业场景RFC Editor。

3.3.1 共享模式(Shared Mode)

共享模式是最简单的部署模式,客户端 - facing 服务器(面向客户端的前端服务器)和后端源站是同一个实体,既负责 ECH 的加解密,也负责 TLS 握手的终止和业务数据的处理RFC Editor。

这种模式适合单站点、中小企业的部署场景,比如一个独立的博客网站、小型企业官网,服务器自己管理 ECH 密钥和 SSL 证书,所有的 TLS 处理都在同一台服务器上完成。

共享模式的工作流程非常直接:

  1. 服务器生成 ECH 公私钥对,把公钥发布到 DNS 的 HTTPS 记录中;
  2. 客户端发送双层 Client Hello,Outer 的 SNI 是服务器的 public_name;
  3. 服务器用自己的 ECH 私钥解密 Inner,拿到真实的 SNI 和握手参数;
  4. 服务器用 Inner 的参数完成 TLS 握手,终止 TLS 连接,处理业务数据。
3.3.2 分割模式(Split Mode)

分割模式是为 CDN、反向代理、多租户场景设计的,客户端 - facing 服务器(前端 CDN 节点)和后端源站是分离的:前端节点只负责 ECH 的加解密,不持有源站的 SSL 证书,也不终止 TLS 连接;TLS 握手的终止和业务数据的处理,完全由后端源站完成。

这种模式是目前主流 CDN 厂商采用的部署方式,它有一个核心的安全优势:前端 CDN 节点无法看到客户端和源站之间的加密通信内容,哪怕 CDN 节点被攻破,也无法泄露用户的业务数据,完美符合隐私合规要求。

分割模式的工作流程如下:

  1. 源站生成 ECH 公私钥对,把公钥发布到 DNS 的 HTTPS 记录中,私钥仅自己持有;
  2. 客户端发送双层 Client Hello,Outer 的 SNI 是 CDN 的公共域名;
  3. 前端 CDN 节点收到 Client Hello 后,无法解密 Inner 内容,直接把整个报文转发给对应的后端源站;
  4. 后端源站用自己的 ECH 私钥解密 Inner,拿到真实的 SNI 和握手参数,完成 TLS 握手;
  5. 后续的加密业务数据,直接通过 CDN 节点转发,CDN 节点无法解密,只能作为流量转发的管道。

分割模式是 ECH 的核心创新之一,它解决了 CDN 场景下的隐私合规问题,让源站完全掌控 TLS 握手和加密密钥,同时利用 CDN 的全球节点加速,兼顾了性能和安全。

4. ECH 的完整工作流程:从 DNS 查询到握手完成

理解了 ECH 的核心设计之后,我们来完整拆解 ECH 的全流程工作步骤。整个 ECH 握手分为 5 个核心阶段,全程兼容 TLS 1.3 标准,同时保证了所有敏感内容的加密。

4.1 阶段 1:ECH 配置的安全分发(DNS HTTPS 记录)

ECH 的第一步,也是最关键的前提:客户端需要提前获取服务端的 ECH 公钥配置,才能对 ClientHelloInner 进行加密。这个配置的分发,是通过 DNS 的HTTPS 资源记录(Type 65) 完成的。

4.1.1 什么是 HTTPS RR 记录?

HTTPS RR 记录(也叫 SVCB 记录)是 IETF 新标准化的 DNS 记录类型,专门用于 HTTPS 服务的配置信息分发,相比传统的 A/AAAA 记录,它能承载更丰富的配置信息,包括 ECH 公钥、支持的 HTTP 版本、IP 地址等。

在 ECH 的场景中,服务端会把自己的 ECH 公钥配置,编码成ECHConfigList结构,放在域名的 HTTPS RR 记录中。客户端在发起连接之前,先通过 DNS 查询目标域名的 HTTPS 记录,获取 ECHConfigList,拿到服务端的公钥和加密参数。

4.1.2 ECHConfigList 的结构

RFC 9849 定义了 ECHConfig 的标准结构,核心包含以下字段:

字段 含义 作用
version 版本号 RFC 9849 正式版本的版本号为 0xfe0d
config_id 配置 ID 1 字节,用于标识这个 ECH 配置,方便服务端快速找到对应的私钥
kem_id KEM 算法 ID 指定 HPKE 使用的密钥封装算法,比如 X25519、P-256
public_key ECH 公钥 服务端的长期公钥,用于客户端加密 ClientHelloInner
cipher_suites 加密套件列表 支持的 KDF+AEAD 算法组合,比如 HKDF-SHA256 + AES-GCM
max_name_length 最大域名长度 用于填充机制,抹平不同域名长度带来的包长差异
public_name 公共域名 外层 ClientHelloOuter 使用的 SNI,必须是真实存在的域名

一个标准的 ECHConfigList,会被 base64 编码后,放在 HTTPS RR 记录的 ech 参数中,示例如下:

example.com. 3600 IN HTTPS 1 . ech=AEn+DQBFugD...ABiAA== alpn=h2,h3 ipv4hint=1.2.3.4
4.1.3 必须配合加密 DNS(DoH/DoT)使用

这里有一个极其关键的点:ECH 必须配合加密 DNS(DNS-over-HTTPS,DoH / DNS-over-TLS,DoT)使用,否则完全失去意义

原因很简单:如果你用明文 DNS 查询目标域名的 HTTPS 记录,那么在查询的时候,你要访问的域名就已经明文泄露给了 DNS 服务器和中间网络设备,后续的 ECH 加密就成了 “掩耳盗铃”。

只有通过 DoH/DoT 加密 DNS 查询,才能保证客户端获取 ECH 配置的过程,不会泄露目标域名,真正实现端到端的隐私保护。同时,建议启用 DNSSEC,对 HTTPS RR 记录进行签名验证,防止攻击者篡改 ECHConfig,实施中间人攻击。

4.2 阶段 2:客户端构造双层 Client Hello

客户端获取到 ECHConfigList 之后,会验证配置的有效性,选择和自身兼容的加密套件,然后构造双层 Client Hello 报文。这一步是 ECH 的核心,分为 6 个小步骤:

步骤 1:HPKE 密钥协商与会话密钥派生

客户端生成临时的 HPKE 密钥对,和服务端的 ECH 公钥进行 KEM 封装,计算出共享密钥,同时生成封装密钥 enc。然后通过 KDF 算法,从共享密钥中派生出 AEAD 加密密钥,用于加密 ClientHelloInner。

每次握手都会生成全新的临时密钥对,保证了前向安全性 —— 哪怕服务端的长期 ECH 私钥泄露,历史握手的会话密钥也无法被计算出来,历史流量无法解密。

步骤 2:构造 ClientHelloInner(内层真实请求)

客户端构造完整的、标准的 TLS 1.3 Client Hello 报文,里面包含所有真实的握手参数:

  • 真实的目标域名 SNI;
  • 真实的 ALPN、status_request、supported_groups 等所有敏感扩展;
  • 客户端随机数、密钥共享、加密套件列表等握手必须参数。
步骤 3:扩展压缩(Extension Compression)

为了减少报文长度,ECH 设计了扩展压缩机制:如果 Inner 里的某个扩展,和 Outer 里的扩展完全相同,那么 Inner 里就不需要重复存放这个扩展,只需要用一个引用标记即可。服务端解密后,会自动把 Outer 里的扩展填充到 Inner 中。

比如 Inner 和 Outer 的加密套件列表、支持的 TLS 版本完全相同,就可以在 Inner 里省略这些字段,大幅减少报文长度。

步骤 4:填充(Padding)

为了防止攻击者通过报文长度推断真实域名的长度和内容,ECH 要求客户端对 ClientHelloInner 进行填充,把它的长度补齐到固定值(由 ECHConfig 里的 max_name_length 决定)。

比如 max_name_length 设置为 64,那么不管真实域名是 10 个字符还是 50 个字符,填充后的 Inner 长度都是相同的,攻击者无法通过包长分析获取任何信息。

步骤 5:加密 ClientHelloInner

客户端用之前派生的 AEAD 加密密钥,对填充后的 ClientHelloInner 进行加密,生成密文和认证标签。AEAD 算法会同时保证密文的机密性和完整性,攻击者无法篡改密文,否则服务端解密时会直接校验失败。

步骤 6:构造 ClientHelloOuter(外层伪装请求)

最后,客户端构造外层的 ClientHelloOuter,这是一个完全标准的 TLS 1.3 Client Hello 报文:

  • SNI 字段填写 ECHConfig 里的 public_name(公共域名);
  • 包含非敏感的握手参数,和 Inner 里的参数保持一致;
  • 新增一个 ech 扩展,里面存放了 HPKE 的封装密钥 enc、config_id、加密后的 Inner 密文、认证标签等参数;
  • 其他非敏感扩展,和 Inner 保持一致,用于扩展压缩。

构造完成后,客户端就会把这个双层 Client Hello 报文,发送给服务端。

4.3 阶段 3:服务端的解密与响应

服务端收到客户端的 Client Hello 之后,首先会检查报文中是否包含 ech 扩展。如果有,就进入 ECH 处理流程,分为解密成功和解密失败两种场景。

场景 1:ECH 解密成功
  1. 服务端根据 ech 扩展里的 config_id,找到对应的 ECH 私钥;
  2. 用自己的私钥和 ech 扩展里的 enc 封装密钥,通过 HPKE 的 Decap 算法,解封装出共享密钥;
  3. 用相同的 KDF 算法,派生出 AEAD 解密密钥;
  4. 用解密密钥解密密文,验证认证标签,确认密文没有被篡改,得到 ClientHelloInner 明文;
  5. 解析 Inner 里的真实 SNI,找到对应的 SSL 证书,用 Inner 里的握手参数,继续完成 TLS 握手流程;
  6. 在 Server Hello 的 random 字段中,嵌入accept_confirmation(接受确认) 信号,这个信号是用握手派生的密钥计算出来的,只有客户端和服务端能生成,用于防止降级攻击。
场景 2:ECH 解密失败

如果服务端解密失败(比如 ECHConfig 过期、密钥不匹配、密文被篡改),ECH 不会像 ESNI 那样直接断开连接,而是设计了两种容错机制:

  1. grease 模式:服务端用 ClientHelloOuter 里的 public_name 继续完成 TLS 握手,同时在加密的 Encrypted Extensions 报文中,返回最新的 retry_configs(重试配置),里面包含了最新的 ECHConfigList。客户端收到后,会更新本地的 ECH 配置,用最新的配置重新发起握手。
  2. Hello Retry Request(HRR):服务端直接发送 HRR 报文,拒绝当前的握手,同时携带最新的 ECHConfig,让客户端用新的配置重新发起握手。

这种重试机制,完美解决了 ESNI 中 DNS 缓存不一致导致的握手失败问题,大幅提升了用户体验和兼容性。

4.4 阶段 4:握手确认与密钥协商完成

客户端收到服务端的 Server Hello 之后,会首先检查是否包含 ECH 接受确认信号:

  1. 客户端验证 accept_confirmation 信号的有效性,确认服务端确实成功解密了 ECH,并且没有被中间人降级到明文模式。如果验证失败,客户端会立即终止握手,防止降级攻击。
  2. 验证通过后,客户端和服务端继续完成后续的 TLS 握手流程:服务端发送加密的 Encrypted Extensions、Certificate、Certificate Verify、Finished 报文;客户端验证服务端的证书和签名,发送自己的 Finished 报文。
  3. 双方完成握手,协商出相同的会话密钥,用于后续应用数据的加密传输。

至此,整个 ECH 握手流程完成。整个过程中,中间网络设备只能看到 ClientHelloOuter 里的 public_name,完全看不到真实的目标域名和任何敏感扩展,彻底填补了 HTTPS 的明文隐私漏洞。

4.5 阶段 5:异常流程:ECH 解密失败的重试

如果客户端收到服务端返回的 retry_configs,说明当前的 ECH 配置已经过期,客户端会执行以下操作:

  1. 验证 retry_configs 的有效性,更新本地的 ECHConfigList;
  2. 用最新的 ECHConfig,重新构造双层 Client Hello,发起新的 TLS 握手;
  3. 为了防止攻击者通过 retry_configs 实施降级攻击,客户端会对重试次数和重试配置的有效期做严格限制,同时只信任通过加密 DNS 获取的、经过 DNSSEC 签名的 ECHConfig。

5. ECH 的核心安全设计与抗攻击能力

ECH 之所以能取代 ESNI,成为 IETF 的正式标准,核心在于它的安全设计经过了严格的密码学论证和工业级的攻防考验,能够有效抵御各种针对 TLS 握手的攻击。

5.1 全字段加密:彻底消除 Client Hello 的隐私泄露面

和 ESNI 只加密 SNI 不同,ECH 加密了整个 ClientHelloInner,包括所有敏感扩展:SNI、ALPN、PSK、status_request、supported_groups 等等,彻底消除了 Client Hello 的明文隐私泄露点。

这意味着,中间网络设备无法通过任何字段,推断出用户访问的目标服务、客户端的软件版本、访问历史等信息,把用户的握手隐私完全保护起来。

5.2 强抗降级攻击:让中间人无法剥离 ECH

ESNI 最致命的缺陷之一,就是无法抵抗降级攻击:中间人可以直接剥离 Client Hello 里的 ESNI 扩展,让客户端回退到明文 SNI 模式,而客户端完全无法感知。

ECH 通过accept_confirmation 确认机制,彻底解决了这个问题:

  • 服务端只有成功解密了 ECH,才能生成正确的 accept_confirmation 信号,这个信号是用握手派生的密钥计算出来的,中间人无法伪造;
  • 客户端如果发送了 ECH 扩展,但没有收到正确的 accept_confirmation 信号,就会立即终止握手,不会继续通信;
  • 这就意味着,中间人要么让握手成功,要么让握手失败,无法在客户端不知情的情况下,把 ECH 降级到明文 SNI 模式。

5.3 前向安全性:长期私钥泄露也不会影响历史流量

ECH 严格遵循前向安全性(Forward Secrecy)的设计原则:每次握手都会生成全新的 HPKE 临时密钥对,服务端的长期私钥只用于认证,不用于直接加密会话密钥IETF。

这意味着,哪怕攻击者在未来拿到了服务端的长期 ECH 私钥,也无法解密之前捕获的 ECH 握手流量,因为历史流量的会话密钥,是由当时的临时密钥对协商出来的,而临时密钥在握手完成后就被销毁了,无法恢复。

前向安全性是现代密码协议的核心设计原则,ECH 的这个设计,保证了用户的历史访问记录,不会因为未来的私钥泄露而被解密。

5.4 抗流量分析:填充机制抹平包长特征

流量分析攻击,是一种常见的隐私窃取手段:攻击者不需要解密报文,只需要通过报文的长度、发送时序、分片方式等特征,就能推断出用户的行为。

对于 ECH 来说,如果没有填充机制,攻击者可以通过加密后的 Inner 密文长度,推断出真实域名的长度,进而缩小猜测范围,甚至精准匹配目标域名。

为了抵御这种攻击,ECH 设计了标准化的填充机制:客户端会把 ClientHelloInner 填充到固定长度,不管真实域名和扩展的长度是多少,最终的密文长度都是相同的。这样一来,攻击者无法通过密文长度,获取任何关于 Inner 内容的信息,彻底抵御了基于包长的流量分析攻击。

5.5 匿名集保护:隐藏用户的具体访问目标

ECH 引入了匿名集(Anonymity Set) 的概念:同一个 public_name 对应的所有后端域名,构成了一个匿名集。

比如,Cloudflare 的 public_name 是cloudflare-ech.com,所有托管在 Cloudflare 上的几百万个网站,都属于这个匿名集。中间网络设备只能知道用户访问了 Cloudflare 的节点,无法知道用户具体访问的是几百万个网站中的哪一个。

匿名集越大,用户的隐私保护级别就越高。攻击者只能知道用户访问了某个服务商,无法精准定位到具体的网站,大幅提升了用户的上网隐私。

5.6 抗重放攻击:HPKE 的单例特性

ECH 使用的 HPKE 加密体系,原生具备抗重放攻击的能力:每次加密都会生成全新的临时密钥对,对应的封装密钥 enc 和密文都是唯一的,无法被重放IETF。

如果攻击者捕获了客户端的 ECH 握手报文,重新发送给服务端,服务端会在解密时校验失败,因为 HPKE 的封装密钥只能使用一次,无法重放。这就防止了攻击者通过重放握手报文,实施会话劫持攻击。

6. ECH 的常见误区与最佳实践

6.1 关于 ECH 的 8 个常见认知误区

误区 1:开了 ECH 就万事大吉,不用加密 DNS

纠正:这是最常见、最致命的误区。ECH 的前提是客户端通过 DNS 获取目标域名的 ECHConfig,如果你用明文 DNS 查询,那么在查询的时候,你要访问的域名就已经明文泄露了,后续的 ECH 加密完全失去了意义。ECH 必须强制配合 DoH/DoT 加密 DNS 使用,这是不可动摇的前提

误区 2:ECH 和 ESNI 没区别,只是换了个名字

纠正:ECH 和 ESNI 是完全不同的两个协议,安全级别天差地别。ESNI 只加密了 SNI 一个字段,而 ECH 加密了整个 ClientHelloInner,包括所有敏感扩展;ECH 解决了 ESNI 的所有核心缺陷:抗降级攻击、完善的重试机制、兼容 CDN 分割模式、强前向安全性,两者完全不是一个量级的解决方案。

误区 3:ECH 会严重影响握手性能,增加延迟

纠正:ECH 的额外开销,只有 HPKE 的一次封装和解封装操作,在现代 CPU 上,这个操作的延迟只有微秒级,完全可以忽略不计。同时,ECH 的扩展压缩机制,还能减少 Client Hello 的包长,在弱网环境下,甚至能提升握手成功率。根据 Cloudflare 的实测数据,启用 ECH 后,TLS 握手的平均延迟仅增加了 0.3ms,用户完全感知不到。

误区 4:ECH 可以绕过所有的网络封锁

纠正:ECH 只是加密了 TLS 握手的内容,并没有改变流量的基础特征。如果防火墙基于 IP 地址、端口、流量特征进行阻断,ECH 本身无法绕过。要实现抗阻断,需要配合 THO 握手混淆、流量隧道、代理等技术,ECH 只是隐私保护的一环,不是万能的翻墙工具。

误区 5:ECH 只能用于公网网站,内网场景用不了

纠正:ECH 完全可以在内网、私有网络中部署。企业内网可以通过内部的 DNS 服务器,分发 ECHConfig,配合私有 CA,实现内网 TLS 流量的全隐私保护,防止内网中的横向流量监听和信息泄露,尤其适合金融、政务等对内网安全要求极高的场景。

误区 6:ECH 会破坏负载均衡和 WAF 的能力

纠正:ECH 的分割模式,完美适配负载均衡和 WAF 场景。前端的负载均衡 / WAF 设备,可以通过 ClientHelloOuter 里的 public_name,进行基础的流量调度和安全防护,然后把流量转发给后端源站,由源站解密 ECH 内容,不会破坏现有的负载均衡和 WAF 架构。同时,RFC 9849 也定义了 ECH 的透明代理模式,让合规的安全设备可以在授权的情况下,解密 ECH 流量,满足企业的安全审计需求。

误区 7:ECH 的私钥和 SSL 证书私钥必须是同一个

纠正:ECH 的公私钥对,和 SSL 证书的公私钥对,是完全独立的两套密钥,不需要有任何关联。ECH 私钥只用于加密解密 ClientHelloInner,SSL 证书私钥用于证书签名和身份认证,两者分离的设计,进一步提升了安全性 —— 哪怕 SSL 证书私钥泄露,也不会影响 ECH 的加密安全。

误区 8:ECH 只支持 HTTP/HTTPS,无法用于其他 TCP 协议

纠正:ECH 是 TLS 1.3 的扩展,只要是基于 TLS 1.3 的协议,都可以使用 ECH,包括但不限于 HTTPS、IMAPS、SMTPS、FTPS、MQTTS、WebSocket over TLS 等。只要是基于 TLS 的应用层协议,都可以通过 ECH 保护握手阶段的隐私,适用范围极广。

6.2 生产环境部署 ECH 的 8 大最佳实践

  1. 强制绑定加密 DNS:在部署 ECH 的同时,必须引导用户使用 DoH/DoT 加密 DNS,同时在网站的 HSTS 头部中添加dnsschemes="https"参数,强制浏览器使用加密 DNS 查询你的域名。
  2. 优先使用 RFC 9849 正式版本:废弃所有草案版本的 ESNI 和 ECH,只使用 RFC 9849 正式版本的实现,避免兼容性问题和安全漏洞。
  3. 合理的密钥轮换与 DNS TTL 配置:ECH 密钥的轮换周期,建议设置为 1 小时到 1 天,同时 DNS 记录的 TTL 设置为和轮换周期一致,比如密钥 1 小时轮换,TTL 就设置为 3600 秒,避免 DNS 缓存不一致导致的握手失败。
  4. public_name 的合规配置:public_name 必须是服务端上真实存在的、有有效 SSL 证书的域名,不能是虚假域名;同时,public_name 对应的网站,应该和后端真实网站,具备一致的 TLS 配置(加密套件、支持的协议版本等),防止通过指纹识别区分。
  5. 强制开启填充机制:在 ECHConfig 中设置合理的 max_name_length,开启填充机制,把 ClientHelloInner 填充到固定长度,防止基于包长的流量分析攻击。
  6. 配合证书压缩特性:启用 RFC 8879 定义的 TLS 证书压缩特性,使用 Brotli/Zstandard 压缩证书链,减少握手包长,提升弱网环境下的 ECH 握手成功率。
  7. 完善的监控与告警:部署 ECH 后,需要监控 ECH 握手的成功率、解密失败率、重试次数等指标,设置告警,及时发现 ECH 配置过期、密钥不匹配等问题。
  8. 全链路的隐私保护:ECH 只是隐私保护的一环,需要配合 ESC、THO、HTTP/3、加密 DNS 等技术,构建端到端的全链路隐私保护体系,最大化用户的上网安全。

7. 总结与未来展望

2026 年 3 月 RFC 9849 的发布,标志着 ECH 正式成为互联网的官方标准,这是 HTTPS 发展史上,继 TLS 1.3 之后最重要的里程碑。它彻底填补了 HTTPS 最后一个明文隐私漏洞,让互联网终于实现了 “加密一切” 的愿景:不仅用户和网站之间的传输内容是加密的,用户要访问哪个网站这个行为本身,也得到了完善的隐私保护。

ECH 的普及,将对整个互联网行业产生深远的影响:

  • 用户隐私保护的全面升级:普通用户的上网行为,再也不会被运营商、ISP 轻易记录和售卖,用户的网络隐私得到了前所未有的保护;
  • 网络内容治理的范式转变:基于 SNI 的网站阻断方式,将逐渐失效,网络内容治理将从基于域名的阻断,转向基于 IP 地址、内容审核的更精细化的方式;
  • CDN 行业的隐私合规升级:ECH 的分割模式,让 CDN 厂商无法看到用户和源站之间的通信内容,完美适配全球各地的隐私合规法规(比如 GDPR、个人信息保护法),推动 CDN 行业从 “流量加速” 向 “隐私安全加速” 转型;
  • 企业内网安全的提升:ECH 可以用于内网的 TLS 流量保护,防止内网中的横向监听和信息泄露,提升企业内网的安全水位。
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐