译者注:2024 年 9 月 25 日,Cloudflare 宣布再次推出 ECH 功能。借此契机,本人翻译了 Cloudflare 介绍 ECH 的博文 Good-bye ESNI, hello ECH!
,以便科普ECH的发展历程。
现代互联网上的大多数通信都经过加密,以确保其内容只有端点(即客户端和服务器)才能理解。然而,加密需要密钥,因此端点必须在不向潜在攻击者透露密钥的情况下就加密密钥达成一致。用于此任务(称为密钥交换)的最广泛使用的密码协议是传输层安全(TLS)握手。
在本文中,我们将深入探讨 ECH(Encrypted Client Hello,加密客户端问候),这是 TLS 的一个新扩展,有望显著增强这一关键互联网协议的隐私性。如今,TLS 连接的许多隐私敏感参数是在明文中协商的。这使得网络观察者可以获取大量元数据,包括端点的身份、它们如何使用连接等等。
ECH 对整个握手过程进行加密,从而使这些元数据保密。至关重要的是,这通过保护服务器名称指示(SNI)免受网络窃听者的攻击,填补了一个长期存在的隐私漏洞。加密 SNI 很重要,因为它是表明给定客户端正在与哪个服务器通信的最清晰信号。然而,也许更重要的是,ECH 还为在 TLS 中添加未来的安全特性和性能增强功能奠定了基础,同时将对最终用户隐私的影响降至最低。
ECH 是学术界和科技行业领导者密切合作的产物,由互联网工程任务组(IETF)促成,参与者包括 Cloudflare、我们在 Fastly 和 Mozilla 的朋友(他们都是该标准的共同作者的所属机构)以及许多其他机构。这一特性代表了对 TLS 协议的重大升级,它建立在前沿技术之上,比如仅现在才开始崭露头角的基于 HTTPS 的域名系统(DNS-over-HTTPS)。因此,该协议尚未准备好进行互联网规模的部署。本文旨在作为通往完全握手加密之路的一个路标。
背景
TLS 的故事就是互联网的故事。随着我们对互联网的依赖程度越来越高,协议也在不断发展,以应对不断变化的操作要求、使用案例和威胁模式。客户端和服务器不只是交换密钥。它们需要就各种功能和参数进行协商:密钥交换的具体方法;加密算法;谁来验证以及如何验证;握手后使用哪个应用层协议;等等。所有这些参数都会以这样或那样的方式影响通信通道的安全属性。
SNI 是影响通道安全的一个参数的主要例子。客户端使用 SNI 扩展来向服务器指示它想要访问的网站。这对现代互联网至关重要,因为如今许多源服务器位于单个 TLS 运营商之后是很常见的。在这种情况下,运营商使用 SNI 来确定谁将对连接进行认证:没有它,就无法知道要向客户端呈现哪个 TLS 证书。问题是 SNI 会将客户端想要连接的源服务器的身份泄露给网络,可能会让窃听者推断出关于他们通信的大量信息。(当然,网络观察者还可以通过其他方式来识别源服务器,例如源服务器的 IP 地址。但是,如果在同一 IP 地址上与其他源点共址,那么使用这一指标确定源点就比简单检查 SNI 难多了)。
虽然保护 SNI 是 ECH 的动力,但它绝不是客户端和服务器协商的唯一隐私敏感的握手参数。另一个是应用层协议协商(ALPN)扩展,它用于在 TLS 连接建立后决定使用哪个应用层协议。客户端发送它支持的应用程序列表 —— 无论是 HTTPS、电子邮件、即时通讯,还是使用 TLS 进行传输安全的无数其他应用程序 —— 服务器从该列表中选择一个,并将其选择发送给客户端。通过这样做,客户端和服务器向网络泄露了它们的能力以及连接可能用于何种用途的明确信号。
有些特性对隐私非常敏感,以至于它们在握手中的包含是不可行的。一个被提出的想法是用密码验证密钥交换(PAKE)取代 TLS 核心的密钥交换。这将允许基于密码的认证与基于证书的认证一起使用(或替代后者),使 TLS 更强大,适用于更广泛的应用。这里的隐私问题与 SNI 类似:服务器通常会为每个客户端关联一个唯一标识符(例如用户名或电子邮件地址),用于检索客户端的凭证;并且客户端必须在握手过程中以某种方式将此身份传达给服务器。如果在明文中发送,那么任何网络观察者都可以轻易获取这些个人身份信息。
解决所有这些隐私泄露问题的一个必要因素是握手加密,即除了应用数据之外,对握手消息进行加密。听起来很简单,但这个解决方案带来了另一个问题:如果握手本身就是一种交换密钥的方式,那么客户端和服务器如何选择加密密钥呢?当然,有些参数必须在明文中发送,所以 ECH 的目标是对除了完成密钥交换所必需的参数之外的所有握手参数进行加密。
为了理解 ECH 以及支撑它的设计决策,了解一下 TLS 中握手加密的历史会有所帮助。
TLS 中的握手加密
在最新版本 TLS 1.3 之前,TLS 根本没有握手加密。2013 年斯诺登事件曝光后,IETF 社区开始考虑应对大规模监控对开放互联网构成的威胁的方法。当 2014 年开始对 TLS 1.3 进行标准化时,其设计目标之一是尽可能多地对握手进行加密。遗憾的是,最终标准并未实现完全的握手加密,包括 SNI 在内的多个参数仍以明文方式发送。让我们仔细分析一下原因。
TLS 1.3 协议流程如图 1 所示。一旦客户端和服务器计算出一个新的共享密钥,握手加密就开始了。为此,客户端在其客户端问候(ClientHello)消息中发送一个密钥份额,服务器在其服务器问候(ServerHello)消息中用自己的密钥份额进行响应。交换这些份额后,客户端和服务器可以推导出一个共享密钥。随后的每个握手消息都使用从共享密钥派生的握手通信密钥进行加密。
应用数据使用一个不同的密钥进行加密,称为应用通信密钥,它也是从共享密钥派生的。这些派生的密钥具有不同的安全属性:为了强调这一点,它们用不同的颜色表示。
第一个被加密的握手消息是服务器的加密扩展(EncryptedExtensions)。此消息的目的是保护服务器的敏感握手参数,包括服务器的 ALPN 扩展,其中包含从客户端的 ALPN 列表中选择的应用程序。密钥交换参数在 ClientHello 和 ServerHello 中以未加密方式发送。
客户端的所有握手参数,无论是否敏感,都会在 ClientHello 中发送。看了图 1,你可能会想到重新设计握手过程的方法,以便对其中的一些参数进行加密,但代价可能是增加延迟(即增加网络往返次数)。然而,像 SNI 这样的扩展会产生一种 "先有鸡还是先有蛋 "的问题。
客户端在验证服务器的身份(这是证书(Certificate)和证书验证(CertificateVerify)消息的任务)并且服务器确认它知道共享密钥(这是完成(Finished)消息的任务)之前不会加密任何内容。这些措施确保了密钥交换是经过验证的,从而防止了中间人(MITM)攻击,在这种攻击中,对手会冒充服务器向客户端发送信息,从而解密客户端发送的信息。由于服务器需要 SNI 来选择证书,因此需要在验证密钥交换之前传输 SNI。
一般来说,只有在客户端和服务器共享加密密钥的情况下,才能确保用于身份验证的握手参数的保密性。但这个密钥从何而来呢?
TLS 1.3 早期的完全握手加密
有趣的是,完全握手加密曾经被提议作为 TLS 1.3 的一个核心特性。在协议的早期版本(大约 2015 年的草案 - 10)中,服务器会在握手期间向客户端提供一个长期有效的公钥,客户端会在后续的握手中使用该公钥进行加密。(这种设计来自一个名为 OPTLS 的协议,而该协议又借鉴了原始的 QUIC 提案。)这种模式被称为 “0 - RTT”,其主要目的是允许客户端在完成握手之前开始发送应用数据。此外,它还允许客户端对 ClientHello 之后的第一轮握手信息进行加密,包括加密扩展名(EncryptedExtensions),这些扩展名可用于保护客户端的敏感握手参数。
最终,这个特性没有被纳入最终标准(2018 年发布的 RFC 8446),主要是因为它的复杂性超过了它的实用性。特别是,它对保护客户端得到服务器公钥的初始握手没有任何作用。初始握手的服务器认证所需的参数,如 SNI,仍然会在明文中传输。
尽管如此,该方案仍是其他握手加密机制(如 ECH)的先驱,这些机制使用公钥加密来保护敏感的 ClientHello 参数。这些机制必须解决的主要问题是密钥分配。
在 ECH 之前有(并且仍然有!)ESNI
ECH 的直接前身是加密 SNI(ESNI)扩展。顾名思义,ESNI 的目标是提供 SNI 的保密性。为此,客户端会使用服务器的公钥对其 SNI 扩展进行加密,并将密文发送给服务器。服务器会尝试使用与其公钥对应的私钥对密文进行解密。如果解密成功,那么服务器会使用解密后的 SNI 继续进行连接。否则,它会直接终止握手。这个简单协议的流程如图 2 所示。
对于密钥分发,ESNI 依赖于另一个关键协议:域名解析服务(DNS)。为了使用 ESNI 连接到一个网站,客户端会在其标准的 A/AAAA 查询中附带一个对包含 ESNI 公钥的 TXT 记录的请求。例如,要获取 crypto.dance 的密钥,客户端会请求_esni.crypto.dance 的 TXT 记录:
$ dig _esni.crypto.dance TXT +short
"/wGuNThxACQAHQAgXzyda0XSJRQWzDG7lk/r01r1ZQy+MdNxKg/mAqSnt0EAAhMBAQQAAAAAX67XsAAAAABftsCwAAA="
这个 base64 编码的二进制大对象包含一个 ESNI 公钥以及相关参数,如加密算法。
但是,如果我们只是通过明文 DNS 查询向网络观察者泄露服务器名称,那么加密 SNI 又有什么意义呢?通过引入 DNS-over-HTTPS (DoH),这种部署 ESNI 的方式变得可行,它可以对提供 DoH 服务的解析器(1.1.1.1 就是此类服务的一个示例)的 DNS 查询进行加密。DoH 的另一个重要特点是,它为从 DoH 服务器向客户端传输 ESNI 公钥提供了一个经过验证的通道。这可以防止来自客户端本地网络的缓存投毒攻击:如果没有 DoH,本地攻击者可以通过返回空 TXT 记录来阻止客户端提供 ESNI 扩展,或胁迫客户端使用其控制的密钥来使用 ESNI。
虽然 ESNI 向前迈出了重要的一步,但它没有达到我们实现完全握手加密的目标。除了不完整 —— 它只保护 SNI—— 它还容易受到一些复杂攻击,虽然这些攻击很难实施,但指出了协议设计中的理论弱点,需要加以解决。
2018 年,Cloudflare 部署了 ESNI,Firefox 也在可选的基础上启用了它,这一经历暴露了依赖 DNS 进行密钥分发的一些挑战。Cloudflare 每小时轮换其 ESNI 密钥,以在密钥万一被泄露的情况下将附带损害降至最低。DNS 记录有时会被缓存很长时间,结果是客户端有很大可能拥有一个过时的公钥。虽然 Cloudflare 的 ESNI 服务在一定程度上容忍这种情况,但每个密钥最终都必须过期。ESNI 协议留下的问题是,如果解密失败并且客户端无法通过 DNS 或其他方式获取当前公钥,它应该如何继续。
依赖 DNS 进行密钥分发的另一个问题是,多个端点可能对同一源服务器具有权威性,但却具有不同的功能。例如,对 "example.com "的 A 记录的请求可能会返回两个不同 IP 地址中的一个,每个地址都由不同的 CDN 运营。_esni.example.com "的 TXT 记录将包含其中一个 CDN 的公钥,但肯定不会同时包含两个 CDN 的公钥。DNS 协议没有提供将对应于同一端点的资源记录原子绑定在一起的方法。特别是,客户端有可能无意中向不支持 ESNI 扩展的端点提供 ESNI 扩展,导致握手失败。要解决这个问题,需要修改 DNS 协议。(更多内容见下文)。
ESNI 的未来。 在下一节中,我们将描述 ECH 规范以及它如何解决 ESNI 的缺点。尽管有其局限性,然而,ESNI 提供的实际隐私益处是显著的。Cloudflare 打算继续支持 ESNI,直到 ECH 可以用于生产环境。
ECH 的细节
ECH 的目标是加密整个 ClientHello,从而弥补 TLS 1.3 和 ESNI 的不足,保护所有对隐私敏感的握手参数。与 ESNI 类似,该协议使用通过 DNS 分发并使用 DoH 获取的公钥,在客户端首次飞行时进行加密。但 ECH 对密钥分发进行了改进,使该协议在 DNS 缓存不一致的情况下更加稳健。ESNI 服务器会在解密失败时中止连接,而 ECH 服务器会尝试完成握手,并向客户端提供可用于重试连接的公开密钥。
但是,如果服务器无法解密 ClientHello,又如何完成握手呢?如图 3 所示,ECH 协议实际上涉及两个 ClientHello 信息:ClientHelloOuter,像往常一样以明文发送;ClientHelloInner,经过加密后作为 ClientHelloOuter 的扩展发送。服务器只用其中一个 ClientHello 完成握手:如果解密成功,则继续发送 ClientHelloInner;否则,继续发送 ClientHelloOuter。
ClientHelloInner 由客户端想要用于连接的握手参数组成。这包括敏感值,如它想要访问的源服务器的 SNI(在 ECH 术语中称为后端服务器)、ALPN 列表等等。ClientHelloOuter 虽然也是一个完整的 ClientHello 消息,但不用于预期的连接。相反,握手由 ECH 服务提供商本身完成(在 ECH 术语中称为面向客户端的服务器),向客户端表明由于解密失败无法到达其预期目的地。在这种情况下,服务提供商还会发送正确的 ECH 公钥,客户端可以用它重试握手,从而 “纠正” 客户端的配置。(这个机制类似于 TLS 1.3 早期服务器为 0 - RTT 模式分发其公钥的方式。)
至少,两个 ClientHellos 都必须包含服务器认证的密钥交换所需的握手参数。特别是,虽然 ClientHelloInner 包含真实的 SNI,但 ClientHelloOuter 也包含一个 SNI 值,客户端在 ECH 解密失败的情况下期望验证这个值(即面向客户端的服务器)。如果使用 ClientHelloOuter 建立连接,那么客户端应该立即终止连接并使用服务器提供的公钥重试握手。客户端在 ClientHelloOuter 中不需要指定 ALPN 列表,也不需要任何其他用于指导握手后行为的扩展。所有这些参数都被加密的 ClientHelloInner 封装。
这种设计非常优雅地解决了早期机制在安全部署握手加密时遇到的大部分难题。重要的是,ECH 的设计并非凭空想象。该协议反映了 IETF 社区的不同观点,其开发与 IETF 的其他标准相吻合,这些标准对 ECH 的成功至关重要。
第一个是一个重要的新 DNS 特性,称为 HTTPS 资源记录类型。从高层次上讲,这种记录类型旨在允许对同一个域名具有权威性的多个 HTTPS 端点宣传不同的 TLS 能力。这使得可以依赖 DNS 进行密钥分发,解决了最初 ESNI 部署所揭示的一个部署挑战。要深入了解这个新记录类型以及它对互联网更广泛的意义,请查看 Alessandro Ghedini 最近关于用 DNS 加速 HTTPS 的博客文章。
第二个是 CFRG 的混合公钥加密(HPKE)标准,它规定了一个可扩展的框架,用于构建适合各种应用的公钥加密方案。特别是,ECH 将其握手加密机制的所有细节都委托给了 HPKE,从而使规范更加简单、更易于分析。(顺便提一句,HPKE 也是 Oblivious DNS-over-HTTPS 的主要成分之一)。
前方的道路
当前的 ECH 规范是多年合作的成果。在这一点上,协议的整体设计相当稳定。事实上,规范的下一个草案将是第一个针对实现之间的互操作性测试的草案。然而,仍然有一些细节需要解决。让我们用前方道路的简要概述来结束这篇文章。
抗流量分析
最终,ECH 的目标是确保连接到同一个 ECH 服务提供商后面的不同源服务器的 TLS 连接彼此无法区分。换句话说,当你连接到比如说 Cloudflare 后面的一个源服务器时,在你和 Cloudflare 之间的网络上没有人应该能够辨别你到达了哪个源服务器,或者你和源服务器协商了哪些隐私敏感的握手参数。除了立即提升隐私之外,如果实现这个特性,将为 TLS 部署新特性铺平道路,同时不损害隐私。
加密 ClientHello 是实现这个目标的重要一步,但我们还需要做更多的工作。我们还没有讨论的一个重要攻击向量是流量分析。这指的是对通信通道的属性进行收集和分析,这些属性会泄露部分密文的内容,但不会破解底层的加密方案。例如,加密 ClientHello 的长度可能会泄露足够关于 SNI 的信息,让对手能够对其值做出有根据的猜测(对于特别短或特别长的域名,这种风险尤其高)。因此,确保每个密文的长度与隐私敏感参数的值无关是至关重要的。当前的 ECH 规范提供了一些缓解措施,但它们的覆盖范围不完整。因此,提高 ECH 对流量分析的抵抗力是未来工作的一个重要方向。
僵化的幽灵
ECH 的一个重要未决问题是它对网络操作的影响。
从部署 TLS 1.3 中吸取的教训之一是,升级核心互联网协议可能会引发意想不到的网络行为。Cloudflare 是首批大规模部署 TLS 1.3 的主要 TLS 运营商之一;当 Firefox 和 Chrome 浏览器开始试验性地启用 TLS 1.3 时,他们发现连接失败率明显高于 TLS 1.2。造成这些故障的根本原因是网络僵化,即中间件(middleboxes,客户端和服务器之间的网络设备,用于监控和拦截流量)倾向于编写软件,期望流量以某种方式出现和运行。在中间件有机会更新其软件之前更改协议,导致中间件试图解析它们无法识别的数据包,从而引发软件错误,在某些情况下导致连接完全中断。
这个问题非常普遍,因此,为了减轻网络僵化的影响,我们没有等待网络运营商更新软件,而是修改了 TLS 1.3 的设计。巧妙的解决方案是让 TLS 1.3 "看起来 "像另一种协议,而众所周知,中间件是可以容忍的。具体来说,电报格式甚至握手信息的内容都与 TLS 1.2 相似。当然,这两个协议并不完全相同–好奇的网络观察者仍然可以将它们区分开来–但它们在外观和行为上的相似性足以确保大多数现有中间件不会区别对待它们。经验表明,这种策略降低了连接失败率,足以让 TLS 1.3 的部署变得可行。
ECH 再一次代表了 TLS 的重大升级,网络僵化的阴影笼罩着它。ClientHello 包含的参数(如 SNI)已经在握手过程中存在了很长时间,我们还不知道加密这些参数会产生什么影响。考虑到僵化可能导致的部署问题,ECH 协议在设计上尽可能与标准 TLS 1.3 握手协议相似。最显著的区别在于 ECH 扩展本身:如果中间件忽略它(如果它们符合 TLS 1.3 标准,就应该忽略它),那么握手过程的其他部分看起来和行为都与往常一样。
这一战略是否足以确保 ECH 的大范围部署还有待观察。如果是这样,值得注意的是,这一新功能将有助于减轻未来 TLS 升级对网络运行的影响。加密完整的握手过程可以降低僵化的风险,因为这意味着可供软件僵化的可见协议功能更少了。我们相信这将有利于互联网的整体健康。
结论
老式的 TLS 握手方式(无意中)泄露了信息。客户端和服务器的操作要求导致对隐私敏感的参数(如 SNI)在完全透明的情况下进行协商,并提供给网络观察者。ECH 扩展旨在通过对完整握手过程进行加密来弥补这一缺陷。这代表着 TLS 的重大升级,随着协议的不断发展,这将有助于保护终端用户的隐私。
ECH 标准正在制定中。随着这项工作的继续,Cloudflare 将致力于尽自己的一份力量,确保 TLS 的这一重要升级在互联网上实现大规模部署。