QUIC 连接
协议有四个阶段,我们需要考虑性能效率:启动,稳定状态,闲置进入,闲置离开。第一个挑战是减少启动(连接建立) 期间的延迟。第二个挑战是确认在稳定状态下的有效的和低延迟的性能。第三个挑战是有效地且低延迟地确认平稳过渡到一个空闲状态。过渡是明显的,TCP 包丢失的尾部包丢失历来发生显著延迟,特别当最后一个包丢失时,发送端超时需要重新发送丢失的数据。
5.1 通过无连接的 UDP 建立连接:克服 NAT
一个最基本的问题是怎样将 UDP 转换成一个基于连接的协议。
例如,考虑一个中间框的情况下,如防火墙和 NAT,决定不再支持一个特定的 TCP 连接。中间框可以发送一个 TCP 重置(连接重置) 到两端作为一个断开连接通知的一部分。相反,当一个 NAT 服务决定丢弃一个使用 UDP 流量的绑定,没有通知,因为一个 UDP 数据报不希望是一个 连接。一旦一个 UDP NAT 释放发生,外部端点(通常是一个服务器) 无法发送流量到客户端。
更糟的是,来自服务器的流量通常是黑洞,没有否定确认响应。对 TCP,试图使用一个未绑定端口可能导致至少一个堪比否定确认的重置。作为进一步的并发症,如果一个 NAT 端口未绑定发生,然后客户端发送额外的 UDP 流量,NAT 服务可能创建一个新绑定。新端口绑定可能有不同的源端口(在服务器看来),尽管 QUIC 需要把流量看作一个现存连接的持续。
目前的估计表明,对现在已部署的 NAT 盒来说,在 30 到 120 秒的空闲时间之后释放一个 UDP 端口映射是非常常见的,并且释放可能会很快发生。
所以需要一个 GUID(全局唯一标识符) 来标识一个连接。
UDP 包分片
单个链路上大于 MTU 的 UDP 数据包有在 IP 层被分片的风险。我们是否把我们所有的数据包标记为 不分片 是待定的,如果超过 MTU 的话,这将导致包损失。但随着包分片的普遍,这可能不再是问题。
当一个包在 IP 层分片时,初始包将继续持有 UDP 源和目标端口说明符,以及一个全局唯一标识符,但所有后面的分片将缺乏这样的识别信息。重新组装的惟一手段将是 IP 层的 识别 字段,它只有 16 位长度。因此,如果超过(大约)2 ^ 16 的平方根的包同时在传输,碰撞(和破碎的重新组装) 的概率将是巨大的。
收集可能一次轻易有超过 256 包在传输,争夺唯一的 IP 标识符,造成重组碰撞(如果分片)。
碰撞,可能基于相同的 MTU 边界,将(面对包重新排序),几乎不可能重新组装正确。因此,接收方要么放弃重新组装工作(在一些分片包的一部分),要么它将提供一个错误的重新组装。错误组装的包将被探测为被一个认证过的哈希表歪曲了。因此,重新组装错误不会导致比丢弃可能分片了的包更坏的协议错误。
操作系统 API 不允许一个应用层代码探测 IP 分片是否已经发生。我们可能试图增强我们的服务器操作系统支持,以便检测分片。有这样一个 API,我们可以尝试在任何可见的 MTU 限制内运行。
5.2 连接建立和恢复
最小化启动时的延迟,加快第一次接触时的数据响应,第一次通过 QUIC 发送的数据包通常会包括会话协商信息以及一个或多个请求。QUIC 目的是推测性地假设客户端有可接受的至少需要一个初步加密请求的加密证书,它有足够的不需要反分布式拒绝服务挑战的连接凭证,而且它有足够的新证据表明重播攻击可以排除。如果服务器拒绝接受凭证,比得上 TCP 会话建立或 SSL 问候协商的额外的反复协商就会接踵而来。
启动 DDOS 攻击
关于快速启动的一个已知的问题是拒绝服务攻击。在这种攻击中,恶意客户端可能会提供一个错误的返回(响应) 地址,并可能会导致服务器耗尽重要的计算资源,和/或发送重要的流量给一个第三方地址。从历史观点上说,这些对 TCP 服务器的攻击已通过要求一个额外的往返(确认返回地址) 和同步 cookie 的利用被避免。最近围绕具有 TCP 快开放的 TCP 进行的扩展工作试图答应改良 TCP 的方案,使 TCP 包括在初始同步包中的数据,具有对 DOS 攻击的合理的可接受的控制。
QUIC 将不得不解决连接证书期满的问题,和/或其他机制来阻止重放攻击使用这些凭证。我们希望设计的协议,包括密码恢复,像 TCP 快速打开协议一样强健并且能处理这样的攻击。当一个服务器被攻击或出现过载时,论文包括源 IP(基于以前的连接历史) 所有权的证明和到 3 次握手式连接的自动回退 (re:增加一个额外的 RTT)。我们的协议始终包括端到端加密的这个事实使我们确信,所有权凭证不可能简单地通过偷听被偷走。
安全认证
客户机应该在与上述服务器的先前联系中保留关于一个服务器的信息。保留的信息应该至少足以支持 TLS 会话恢复的模拟,还应该包括服务器信息,比如服务器最近使用的公钥(历史性地保存在一个证书里,用一个到可信根的关联链)。客户应该推测性的假设,最后的已知服务器公钥仍在使用(除非有证据表明撤销或更换),并尝试利用这些信息实现加密初始载荷转移(请求) 的一个零 RTT 传输。
支持加密的没有往返的服务器将随机性添加到连接中,要求服务器维护状态以避免重放攻击。该状态可以通过假设一定数量的时钟同步及时被限制,在太空,给客户端一个 ID 标识碎片(称为一个快速启动的轨道)。服务器可能无法建立连接的唯一性,在这种情况下,客户机必须准备再加密和重传它乐观发送的每件事。
同样地,如果服务器密钥已经改变,客户端将不得不重加密和重传乐观的初始的数据流量。
在一个零 RTT 设置中的初始流量可能没有想象中安全,所以我们应该假设连接将升级到一个真正的在同一连接上的后续流的临时密钥。尽管支持 0RTT 连接建立的默认设置应该是默认的,服务器应该可能坚持,只有完全向前安全加密用于甚至最初的流量。
高水平连接情况的概述
本节旨在概述 QUIC 连接通常会如何进行。我们将着重概述导致每种情况的 RTT 数量。我们还将提供一些用来减轻可能发生的袭击的细节的动机。
第一次连接:通常 1RTT,有时 2RTT
第一次连接,客户端联系服务器,它的初始化问候消息表明,客户端从未访问服务器,因此它不能推测公钥。来自客户端的最初的消息可能包括一些加快一个会话协商的随机性。整个客户端消息将适合一个包,并且应该填补/填充这包。通过填写第一个客户端生成的包,我们保证服务器会发送一个完整的响应数据包,而且它通常不会超过客户端的第一个包。
当客户端收到上面的包,它可以尝试验证服务器证书。验证证书的第一步是解码证书链散列。如果客户无法充分地解码证书链散列,或证书链似乎没有验证服务器证书,然后客户端进入 2 RTT 的情况,并为了全面阐述证书链而被迫发送一个请求到服务器。随着请求发送的还有同步 Cookie,它允许服务器安全地将额外的数据包发送到客户机(没有误导放大攻击的风险)。
最终(1 或 2 个往返之后),客户端将有一个经过身份验证的服务器证书,也有一个短暂生存的同步 Cookie 模拟。有了这些信息,客户端可以进入到下面描述的 0 RTT 情况,并被立即作为可信的客户端返回的 IP 地址和端口所有者。
重复连接:通常 0RTT,有时 1RTT,很少 2RTT
在一个重复连接中,客户端将推测,服务器仍然使用那个可见且验证过的服务器证书。此外,客户端可能拥有证明,它控制了它的返回 IP 地址和端口。证明可能包括在上面的 首次连接 一节中描述过的 SYN Cookie 的模拟,也可能包括一个 TCP 快速打开 cookie 的模拟,这是生存更长的(有效期在更长的时间内)。
为了继续此连接,客户端会建造一个消息的 TLS 会话主秘钥的模拟。在 SSL 快速启动中使用的技术将用于这个结构,以减轻重播攻击。也包括在这个构造中的(加密) 消息将是控制客户机的 IP 地址的 证据 ,以及任何 QUIC 可转让项目,例如提出的拥塞避免算法等。加密的证据(如 TCP 的快速打开 cookie 模拟) 将确保一个偷听者不能偷和滥用这样的证据。
上面的加密问候消息将发送一个包到服务器。发送之后,客户端可以加密、验证和发送额外的数据包。
当服务器获取加密问候包时,它将评估其内容。如果被猜测的服务器公钥不再使用,或消息提出的谈判结果不被服务器所接受,那么服务器可能拒绝数据包的内容,而把它作为上面所描述的相同的 第一次连接 。在这种情况下,利用提议的主秘钥后到达的数据包将被丢弃(没有办法在服务器端解密)。
如果公钥仍然是可以接受的,问候消息是可以接受的,接下来的数据包可以解密、加工和采取行动。
客户端 IP 地址所有权的证明
客户端 IP 的所有权证明是不够的几个原因。许多这些原因与服务器多忙以及在资源利用攻击下的可能性有多大有关,这可能会提高或降低证明的标准。同样,如果证据更旧,它可能被视为不值得信赖的。最后,如果证据没有直接适用而是一个 附近 IP 的证明(实际 IP 证明备用 IP),那么它可能被视为比一个更加远的相关 IP 的证明更加值得信赖。如果证明不足够信任,那么服务器可能发送一个拒绝(探测) 包,以确保客户端返回的 IP 和端口是真实的。
生成客户端 IP 地址所有者/控制的证明
在一个连接中,一个 QUIC 服务器可能创建并发送一个声明,客户正在一个特定的时间使用一个特定的 IP 地址和端口。这样的声明将包括一个由服务器密钥生成的 MAC,这样服务器就可以验证这一说法的 0RTT 重复连接 证明。服务器可能会推动这个语句(具有最近的时间戳) 在这个连接中的更新。
客户端可以组装一个或多个这样的不同的 IP 地址证明列表。例如,它可能获得被家庭 WIFI 防火墙使用的 IP 所有权的证明,以及在一个 3G 移动连接中使用的 IP 地址。在漫游的情况下似乎是合理的,或可能的,客户端可能为服务器提供一个带有多个预期未来漫游的所有权证明。当服务器提前意识到可能漫游(和可能发挥作用的特定 IP 地址),它通常可以立即回复客户返回的 IP 地址的改变,没有拖延执行调查的过渡。
5.3 稳定状态
在 QUIC 连接中的每个流将有一个独特的相关联的流标识符。
连接结构
流将被划分成帧放入(UDP) 包中。只要有可能,任何特定的数据包的有效载荷应只来自于一个流。这样的奉献将减少这种概率,一个包丢失将阻碍不止一个流的进步。当没有足够的数据流来填充一个数据包,然后来自不止一个流的帧可能被打包进一个包。这种包装应减少数据包计数开销,减少序列化延迟。
安全:抗干扰、保密、真实性
给定一个包,我们需要一种方法来识别加密上下文。上下文将被关联到出现在每一个(UDP) 数据包中的全局唯一标识符。
数据包将被在加密上下文中使用共享密钥的 AEAD(与相关数据验证加密) 保护。我们预计在每个数据包大约需要 8 个字节的认证开销,但细节待定,基于艺术标准的状态。
每个数据包需要一些用于加密的初始化向量字节。现时标志需要每一个数据包是唯一的。AEAD 算法将被选择用来做一个简单的计数器(即,必须是唯一的,但初始化向量的可预测性是可以接受的),并将基于数据包序列号。
我们应该提供支持分组打包以减少流量分析的易损性。在这一点上,反流量分析可能没有被充分理解怎样设计使用这种能力的对策。
安全协议应该旨在往返。我们对零 RTT 安全协议有经验,我们明显地可以做的比(D)TLS 更好。
孤立包加密:
在任何孤立包加密模式中,我们避免加密增加延迟,除此之外,都是被一个延时包强制的。例如,如果一个数据包的解密需要其他包的明文或密文(如,一些密码块链接模式),那么我们就不会有一个孤立的包加密属性。没有那个属性,数据包的延迟(损失?) 将推迟另一个包的解码,并且是不可接受的。
包丢失
包丢失的主要原因被认为是拥塞,拥塞地点的路由器执行切换操作且输出缓冲区大小超标了。这个问题是 TCP 和互联网设计的根本,包丢失在那里被用作拥塞信号,协议需要通过减少经过拥塞路径的流来响应。
包丢失将由两个机制处理:包级别的纠错码和数据丢失重传。最终退却发生在其他所有失败都是丢失数据的重传。当以数据在 QUIC 转播来响应数据包丢失时,原包不转播。相反,封装数据被放置在一个新的包里,那个新包被发送。
为了减少短流的延迟,为了一些(所有?) 流的终端,按照协议添加冗余信息来促进纠错,并减少重传的需要。对于较大的流,序列化延迟被认为是主导因素(通过构造和发送流的应用程序),对大多数的流数据包来说前向纠错冗余的使用可能被减少或消除。
拥塞避免
包丢失将会被假设成连接中一些包经过的路径拥塞的标志,并将近似地处理目前 TCP 处理它的方式。接收器判定包丢失时,一个显式的否定确认(NACK) 将被传送到拥塞连接的来源处。
在响应一个否定确认时,发送器应该改变它的传输速率,如在 UDP 包匀速传输时通过减少拥塞窗口或添加额外的等待时间。调整了发送方的传输速率应该类似于 TCP 传达的精神。在总体影响上,如果所有多路复用流是单独的 TCP 连接且这些假设的 TCP 流中的一个收到包丢失通知,响应应该大致相当在 TCP 中发生的。例如,我们希望这些假想的 TCP 连接的拥塞窗口总和的改变与我们的单个 QUIC 拥塞窗口的变化有相似的方式。这种相似性的目的是 TCP 友好 ,既不支配流(阻碍 TCP 活动),也不放弃控制(允许 TCP 控制利用)。
使用同样对 TCP 友好的算法,仅当收到数据确认时拥塞控制窗口扩大之时,带宽利用率才可能会增加。
对乐观确认攻击的攻击缓解
一个已知的对 QUIC 来说可能更糟的 TCP 攻击是乐观确认攻击。在这种攻击中,一个畸形的或潜在的恶意客户端始终确认包,甚至包括那些没有真正收到的包。在 TCP 中,如果没有数据包(报告) 丢失,然后发送方(服务器?) 使用的带宽可能没有界限地增长。这种攻击的结果是,服务器可能无意中洪泛 ISP,当一个流氓客户端误导服务器时创建一个 DOS 攻击。对于 QUIC 来说,依赖一个接收机来评估潜在的可用带宽可能导致服务器更快 DOS 攻击一个 ISP。
防御这种攻击是相当简单的:客户端必须证明它已经收到了包,在服务器应该交付高层带宽传输之前并没有遇到包丢失。只要客户端证明正在接收所有的包,没有理由使服务器节流。一旦如实报告包丢失,QUIC 服务器将压制数据包发送速率(或未偿付的包窗口)。
为了支持收据的概率证明,每个数据包将包括大约一个比特的熵(存在于加密的有效负载中的一个不可预测的比特)。包的一个至少稍稍不可预测地因素是包的传输时间(实际上是包含在 MAC 区),而在每个数据包中的一个显式随机比特简化了证明确认。
实际接收证明将伴随每个 QUIC 确认,它将表现为一个可交换的校验和的形式(即,一个校验和不依赖于校验和被创建的顺序)。校验和将是 8 位长度,并将包括来自接收方声称它已经收到了所有数据包的熵。如果一个服务器检测到一个错误的校验和,它将推测原因是一个畸形的接收器,并将终止连接。
这种缓解的一个剩下的问题是,确认必须包括丢失的所有数据包的一个显式列表(因此不包括校验和)。
合理的误差校正模式
与传统的连续流误差校正不同,包丢失时的误差校正应该利用整个包通常是丢失或完好无损到达的这一事实。
关于一个简单的阻塞式误差校正方案的例子,发送 N 个数据包的有效载荷,然后发送所有有效载荷的奇偶性(按位求和)。那个方案可以视作支持 1 个包丢失的错误校正。虽然奇偶性在传统上只相当于 1 位错误检测能力(在这种情况下一个包丢失),事实上,丢失的比特(如果有的话) 在一个已知的位置,这允许恢复丢失的数据包(假设不超过 1 包丢了)。这样一个简单的奇偶校验计划的优点是可伸缩的冗余,因为一个小值 N 意味着高冗余(额外的带宽使用),而一个较大的值 N 意味着减少冗余和任意小的超额带宽。这样一个简单的方案的另一个优点是,N 值的大小可以晚一些做决定,也就是说当没有更多数据要发送或到了流的尾部时,发送方可以决定使用一个更小的值 N(并且发送一个奇偶校验包)。
[使用这种大 N 值的误差校正需要谨慎的一点是,包丢失的延迟影响及其相关的错误恢复可能与 N 成比例增长。因此,当需要有界延迟和/或抖动时,N 的大小应该受到 RTT * unidirectional_utilized_bandwidth / avg_packet_size 左右。方程中, 利用带宽 是预计使用的数据率,并可能小于最大可用带宽。从本质上讲,如果需要接收方超过 1 个 RTT 得到 N 个数据包块中第一个包的奇偶性比特,就没有减少延迟(在重传请求中)。]
上面的示例类似于 RAID 3 到 RAID 5 的配置。使用奇偶校验系统类似于基于里德所罗门码的 RAID 6,两个奇偶校验数据包发送后发送 N 个数据包,N + 2 个发送的数据包中有 2 个包丢失应该有可能纠正的(不需要一个数据包重传)。
在 Chrome 上进行的发送 UDP 数据包的实验表明,当数据包是快速的,损失足够去除相关,上述简单的异或 FEC 策略对组包可能是有价值的。不幸的是,有一些相关损失,并试图从大爆炸损失(2 个以上的包),对一个大的消耗来说收益递减。结果,我们将重点讨论基于 QUIC 中的 FEC 的异或。
当误差校正被使用时,收集明文有效负载,计算相应的误差校正有效负载,误差校正包传输加密有效负载。因此,当一个包含误差校正的包在传输时,不应该对一个偷听者来说是显而易见的。
逐步减少包丢失
Chrome 的实验已经表明,通常可以通过快速包来减少包丢失。
关于拥塞避免的当前计划是基于带宽估计和速度,并因此减速损失可能放弃设计。我们可能需要更好地深入操作系统,以更好地促进在操作系统级别的缓冲中准确的速度。
包丢失的重传恢复
按照系统,已收数据的确认会定期发送,当没有收到确认时,超时可以自发地掀起重传。
积极地推测重传
积极推测重传相比于 FEC 组(例如:拥有一个数据包和一个 FEC/冗余包的 FEC 组) 的优势在于,QUIC 中的 FEC 组将按顺序传送,虽然投机传输可能容易发生故障,进一步减少了机会,任何相关的包丢失将影响不止一组冗余数据包中的一个。
初始传输和加密数据包重传有这么一个差距,两者都丢失是非常不可能的。
缓冲溢出
缓冲溢出已经证明始终是一个困难的问题,不仅对 TCP 而且对等更高层的协议如 SPDY 同样如此。我们需要尝试整合控制,它将减少成为解决这个问题的贡献者的可能。
缓冲溢出可能对于要求及时交付的流来说更加是一个问题。
拥塞时,在任何包含我们流量的臃肿缓冲区减少流量比例,会最终导致我们都饿死。通过比例填充膨胀的队列,我们会是缓冲区膨胀的一个贡献者。所以,这是一个难题。
本地缓存控制
缓冲可能是可控的、可观察的一个地方是在与发送方端点相关联的机器上。发送方机器通常可能有非常高的本地带宽,作为衡量填充输出缓冲区的能力,这可能明显高于链路层出口带宽,如有线以太网或 WiFi。我们需要努力使这个协议了解到本地当前队列大小(硬件和操作系统将允许的范围内),努力将实际尺寸减小到最低,以避免本地出口链路由于缺乏有效的缓冲数据而饥饿。
基于流的流量控制
流量控制为接收端状态提供了一个基本能力,如过度使用(缓冲区) 内存,诱导一个发送端减少(或在极端情况下,停止) 传输的请求。用一个多路复用协议,接收端的流的消费者可能是缓慢的,或不消耗数据,而其他来源水槽对可能 正常 运行。我们乱序交付的事实保证我们不会阻止其他流,但我们可能因为未耗尽的流数据包而面临接收端(缓冲/内存) 资源枯竭。
5.4 空闲进入
某时,所有连接是闲置的,因为没有任何数据流等待传输。在 TCP 中,当我们进入空闲状态(又名,尾下降),落后的丢失数据包可能引发基于计时器的重传。这样的重发有可能添加显著的延迟,而且纠错冗余应该用于减少这样的重发的概率。
当我们接近一个闲置状态时,如果我们已经使用一个错误纠正模式,那么不需要做任何事情,因为一旦我们真正进入闲置状态(用光数据) 或之后不久,一个落后的误差校正包就可能被添加到连接中。如果我们在一个没有误差校正的模式中传输流,那么当我们接近闲置状态时我们可能需要开始使用误差校正。
从概念上讲,当我们接近任何流的闲置状态时我们应该添加误差校正冗余,即使相关流一般不会使用误差恢复。一旦我们预料我们可能在不到一 RTT 进入空闲状态,我们应该以最佳方式开始这个阶段。
5.5 闲置离开
NAT 表重置
NAT 盒可能有他们的超时或相反的到期条目,导致底层 UDP 传输的崩溃。如今,通常在静止 30-120 秒后到期。
全连接状态的延续
当客户端试图在之前建立的连接上继续传输数据时,第二个闲置离开的例子可能会出现。对于 TCP,在重置已经发送前这类延续是容许的,且目前许多服务器在大约 5 分钟静止后重置 TCP 连接。对于 QUIC,鉴于这样一个事实,通常可以在先前的连接中用获得的凭证建立一个 0RTT 的再连接,我们最初是打算只保持一个连接活着(没有流开放) 约 30 秒。这也应该允许我们更普通地避免 NAT 重新绑定的复杂性。
考虑到担心电池寿命且无用地唤醒接收机说 我们做完了 ,在连接进入闲置后我们协商这个连接的连接状态预期要在两端维持多久。这个谈判发送在连接的定期沟通期间,但当信道空闲时自动生效。在这个时间窗口内流量的恢复将确保连接的加密元素和任何其他会话状态(如压缩上下文) 是可用的/仍然是有效的。
5.6 加密元素
一个加密安全和认证信道的初始化协商,在之前从来没有被一个客户端访问过的网站上,将明显地模仿 TLS,且一个传统的 TLS 问候消息交换。同样地,在客户端的任何数据传输之前,绝对第一的交互需要一个完整的 RTT。首先介绍后,包括加密参数的协商,与证书链的交换等,客户端可以记录这些活动的结果,并使用它们来执行更快速的未来连接。
保留的加密通信流
所有密码交流倾向于使用一组消息的有序交付,这个事实对分析和修正协议证明是至关重要的。因此,我们将保留一个流 ID = 1 的加密流,作为加密信息元通信信道。
减少头阻塞可能性的第一种方法是投机/冗余关键包的传输。
第二种方法特别注重密码规范改变的时间点(如,加密密钥更改),类似于 TLS 变化密码信息被利用时的时间点。
加密和认证
通过为每个包得到一个来自 UDP 包序列号的初始化向量,我们将避免 QUIC 的序列化解码依赖(这将损害我们在包丢失时提供乱序传输的能力)。
会话密钥升级
一个连接的生命周期中,有几个改变会话密钥的原因。第一个变化是一个无效的加密(仅用一个已知的密钥验证) 传输。客户端发送的包含加密客户端问候的初始包必须无加密传输,但后续数据包的数据可能在每次协商后加密。第二个示例以投机连接为中心,这可能取决于一个完美前向安全是不保证的会话密钥。在推测性的连接建立之后,我们将改变成一个完美前向安全被保证的会话密钥。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论