文/ 克里斯托弗·巴顿 译/ 林恩、ChatGPT

现代互联网上的大多数通信都是加密的,以确保其内容只能被端点(即客户端和服务器)理解。然而,加密需要一个密钥,因此端点必须在不向潜在攻击者透露密钥的情况下达成对加密密钥的协议。为此任务而广泛使用的密码协议叫做密钥交换,是传输层安全协议 (TLS)的握手过程。

在这篇文章中,我们将深入探讨Encrypted Client Hello (ECH),这是 TLS 的一个新扩展,它有望显著增强这个关键互联网协议的隐私保护。如今,TLS 连接的许多对隐私敏感的参数都是明文协商的。这使网络观察者可以获取大量的元数据,包括端点的身份、它们如何使用连接等。

ECH 加密完整的握手过程,以保密这些元数据。关键的是,它通过保护服务器名称指示 (SNI)免受网络上的窃听者的侵犯,从而解决了一个长期存在的隐私泄露问题。加密 SNI 很重要,因为它是客户端与特定服务器通信的最明确信号。然而,或许更重要的是,ECH 为将来向 TLS 添加安全特性和性能增强提供了基础,同时最大程度地减少了它们对最终用户隐私的影响。

ECH 是学术界和技术产业领袖之间紧密合作的产物,由 IETF 促成,包括 Cloudflare、我们在 Fastly 和 Mozilla 的朋友(两者都是标准的合作者),以及许多其他人。这个特性代表了对 TLS 协议的重大升级,它依赖于一些尖端技术,比如DNS-over-HTTPS,这些技术现在才刚刚开始展现它们的价值。目前,该协议还没有准备好进行互联网规模的部署。本文旨在作为实现完整握手加密道路上的一个指示标志。

背景

TLS的故事就是互联网的故事。随着我们对互联网的依赖不断加深,这个协议也在不断地演进,来满足日益变化的操作需求、使用场景和威胁模型。客户端和服务器不仅仅是在交换一个密钥。他们协商了许多功能和参数:确切的密钥交换方式;加密算法;谁进行身份验证以及如何验证;握手之后使用哪个应用层协议等等。这些参数都以某种方式影响通信通道的安全性。

SNI是一个对通道安全产生重要影响的参数。客户端使用SNI扩展来告诉服务器它想要访问的网站。对于现代互联网来说,这是至关重要的,因为如今很多源服务器都位于同一个TLS运营商后面。在这种情境下,运营商使用SNI来确定谁将对连接进行身份验证:如果没有SNI,就不知道向客户端展示哪个TLS证书了。问题是,SNI泄露了客户端想要连接的源服务器的身份,可能使窃听者推断出他们通信的许多信息。(当然,网络观察者还有其他方法来识别源头,例如源的IP地址。但是,将多个源放在同一个IP地址上会使这种识别方法变得更加困难。)

尽管保护SNI是推动ECH发展的动机,但这并不是客户端和服务器协商的唯一涉及隐私的握手参数。另一个是ALPN扩展,它用于确定一旦建立了TLS连接,要使用哪种应用层协议。客户端发送其支持的应用程序列表,无论是HTTPS、电子邮件、即时通讯还是其他众多使用TLS进行传输安全的应用程序,服务器从这个列表中选择一个,并将其发送给客户端。通过这样做,客户端和服务器向网络泄露了关于它们能力以及连接可能用于何种用途的明确信号。

有些功能非常关心隐私,所以在握手中包括它们是不可能的。有一个提议是用密码认证的密钥交换(PAKE)替代TLS的核心的密钥交换。这将允许基于密码的身份验证与(或替代)基于证书的身份验证一起使用,使TLS更加稳健,适用于更广泛的应用程序。这里的隐私问题与SNI类似:服务器通常给每个客户端分配一个唯一标识符(例如,用户名或电子邮件地址),用于检索客户端的凭证;在握手过程中,客户端必须以某种方式将此身份传达给服务器。如果明文发送,那么这些个人身份信息将容易被任何网络观察者获取。

解决所有这些隐私泄露的必要条件是握手加密,也就是除了应用数据之外的握手消息的加密。听起来很简单,但这个解决方案提出了另一个问题:如果握手本身是一种交换密钥的方式,那么客户端和服务器如何选择加密密钥呢?当然,某些参数必须明文发送,所以ECH的目标是加密所有握手参数,除了那些完成密钥交换所必需的参数。

为了理解ECH以及支撑它的设计决策,了解一下TLS中握手加密的历史是很有帮助的。

TLS握手加密

在最新版本TLS 1.3之前,TLS根本没有握手加密功能。在2013年Snowden的爆料之后,IETF社区开始考虑如何对抗大规模监控对开放互联网的威胁。当2014年开始标准化TLS 1.3的过程时,其设计目标之一是尽可能加密握手过程。遗憾的是,最终的标准并没有达到完全的握手加密,包括SNI在内的几个参数仍然是明文传输。让我们更深入地了解其中的原因。

TLS 1.3协议流程如图1所示。握手加密开始于客户端和服务器计算出一个新的共享秘密之后。为此,客户端在其ClientHello消息中发送一个密钥分享,服务器在其ServerHello中响应自己的密钥分享。交换了这些分享后,客户端和服务器可以推导出一个共享的秘密。每一个随后的握手消息都使用从共享秘密中推导出的握手流量密钥加密。应用数据使用另一个密钥加密,称为应用流量密钥,它也是从共享秘密中推导出来的。这些派生的密钥有不同的安全属性:为了强调这一点,它们用不同的颜色表示。

第一个被加密的握手消息是服务器的EncryptedExtensions。这个消息的目的是保护服务器的敏感握手参数,包括服务器的ALPN扩展,其中包含从客户端的ALPN列表中选出的应用程序。密钥交换参数在ClientHello和ServerHello中未加密传输。

图1:TLS 1.3的握手过程。

客户端的所有握手参数,无论是否敏感,都会在ClientHello消息中发送。从图1中可以看出,您可能会考虑重新设计握手方式,以增加延迟为代价,使其中一些参数可以加密(即进行更多往返)。然而,像SNI这样的扩展产生了一种"先有鸡还是先有蛋"的问题。

客户端在验证服务器的身份(这是证书和CertificateVerify消息的工作)并且服务器确认知道共享密钥(这是Finished消息的工作)之前不会加密任何内容。这些措施确保密钥交换是经过身份验证的,从而防止中间人攻击(MITM),在这种攻击中,攻击者以允许客户端解密客户端发送的消息的方式将服务器模拟给客户端。由于服务器需要 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所示。

img

图2:具有ESNI扩展的TLS 1.3握手。它与TLS 1.3握手完全相同,只是SNI扩展被ESNI替代。

对于密钥分发,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可以将DNS查询加密到提供DoH服务的解析器(1.1.1.1就是这样一个服务)中。DoH的另一个重要特性是,它提供了一个经过身份验证的通道,用于将ESNI公钥从DoH服务器传输到客户端。这可以防止源自客户端本地网络的缓存污染攻击:在没有DoH的情况下,本地攻击者可以通过返回空的TXT记录阻止客户端提供ESNI扩展,或者迫使客户端使用它们控制的密钥。

虽然ESNI迈出了重要的一步,但它没有达到我们实现完全握手加密的目标。除了不完整(仅保护SNI),它还容易受到一些复杂攻击的影响,虽然实施难度较大,但指向了协议设计上的理论弱点,需要解决。

2018年,Cloudflare在Firefox上进行了ESNI部署,并以自愿选择的方式启用,这一经历揭示了依赖DNS进行密钥分发的一些挑战。Cloudflare每小时更换其ESNI密钥,以尽量减少密钥被泄露时的附带损害。DNS的参数有时会被缓存更长时间,结果是客户端可能具有过期的公钥。虽然Cloudflare的ESNI服务在一定程度上可以容忍这种情况,但每个密钥最终都必须过期。ESNI协议留下的问题是,如果解密失败并且无法访问当前的公钥(通过DNS或其他方式),客户端应该如何继续进行。

依赖DNS进行密钥分发的另一个问题是,多个端点可能是同一源服务器的授权端点,但具有不同的功能。例如,对"example.com"的A记录的请求可能返回两个不同的IP地址,每个IP地址由不同的CDN操作。"_esni.example.com"的TXT记录将包含这些CDN之一的公钥,但肯定不会包含两者的公钥。DNS协议没有提供一种将对应于同一端点的资源记录原子地绑定在一起的方法。特别是,客户端可能无意中将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按照通常的方式明文发送,而ClientHelloInner则作为ClientHelloOuter的扩展进行加密发送。服务器只需用其中一个ClientHello完成握手:如果解密成功,则使用ClientHelloInner进行握手;否则,使用ClientHelloOuter进行握手。

img

图3:具有ECH扩展的TLS 1.3握手。

ClientHelloInner由客户端用于连接的握手参数组成。这包括敏感值,例如客户端想要连接的源服务器的SNI(在ECH术语中称为"backend server"),ALPN列表等等。虽然ClientHelloOuter也是一个完整的ClientHello消息,但它不用于预期的连接。相反,握手由ECH服务提供商本身(称为"client-facing server")完成,向客户端发出信号,告知由于解密失败而无法到达预期的目的地。在这种情况下,服务提供商还会发送正确的ECH公钥,客户端可以使用该公钥重试握手,从而"纠正"客户端的配置(这个机制类似于在TLS 1.3早期阶段服务器分发公钥用于0-RTT模式的方式)。

至少,两个ClientHello都必须包含用于服务器身份验证的握手参数。特别是,ClientHelloInner包含真实的SNI,而ClientHelloOuter也包含一个SNI值,客户端在ECH解密失败的情况下(即client-facing server)期望进行验证。如果使用ClientHelloOuter建立连接,客户端应立即中止连接,并使用服务器提供的公钥重试握手。客户端不需要在ClientHelloOuter中指定ALPN列表,也不需要包含任何用于指导握手后行为的其他扩展。所有这些参数都由加密的ClientHelloInner封装。

这个设计相当优雅地解决了之前机制在安全部署握手加密时遇到的大部分挑战。重要的是,ECH的设计不是孤立的。该协议反映了IETF社区的多元化观点,并与其他对ECH的成功至关重要的IETF标准的发展相互配合。

第一个是一个重要的新DNS功能,称为HTTPS资源记录类型。在高层次上,此记录类型旨在允许为同一域名授权的多个HTTPS端点广告不同的TLS功能。这使得依赖DNS进行密钥分发成为可能,解决了初始ESNI部署中发现的部署挑战之一。如果您想深入了解这个新的记录类型以及它对互联网的更广泛意义,请查看Alessandro Ghedini最近的博文

第二个是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.2相比,连接失败率显著增加。这些失败的根本原因是网络的僵化,中间盒(位于客户端和服务器之间的网络设备)会监视并拦截流量,使期望流量呈现特定方式的展示。若在中间盒有机会更新其软件之前更改协议,会导致中间盒尝试解析它们时,遇到无法识别的数据包,触发软件错误,有时会导致连接完全中断。

译者注:中间盒是指在网络上的客户端和服务器之间运行的设备或软件组件。它们可能包括防火墙、负载均衡器、入侵检测系统和其他负责监视、过滤或操纵网络流量的设备。

这些中间盒通常需要检查和理解通过它们的流量。然而,如果网络协议发生变化,而中间盒软件没有相应地更新,它可能无法正确解释新的流量模式。这种对协议变化缺乏适应性被称为“网络僵化”。

这个问题如此普遍,以至于在等待网络运营商更新其软件的过程中,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的广泛部署。如果ECH成功部署并广泛使用,那么这个新功能将有助于减轻未来TLS升级对网络运营的影响。加密整个握手过程减少了僵化的风险,因为这意味着软件可以僵化的可见协议特性变少。我们相信这将对互联网的整体健康有益。

结论

旧的TLS握手(无意中)泄漏了信息。客户端和服务器的操作需求导致涉及隐私的参数,如SNI,完全明文进行协商,并可供网络观察者获取。ECH扩展旨在通过启用完整握手的加密来填补这一漏洞。这代表了TLS的重大升级,将在协议不断发展的过程中帮助保护终端用户的隐私。

ECH标准是一个正在进行的工作。在这个工作继续进行的过程中,Cloudflare致力于履行自己的责任,确保TLS的这一重要升级达到互联网规模的部署。