QUIC协议详解
声明
本文可以自由转载但需注明原始链接。本文为本人原创,作者LightningStar,原文发表在博客园。本文主体内容参考论文[1]完成。
介绍
QUIC,发音同quick,是"Quick UDP Internet Connections"的简称,是一种通用的传输层网络协议。QUIC与TCP相同,是一种有连接的传输协议。但是与TCP不同的是QUIC是建立在UDP传输层协议之上的,实现了在两个端点之间的多路复用。QUIC的是在用户空间实现的,TCP/UDP则是在内核空间实现的。[2]
QUIC所处的网络层次如下图所示。图源文献[1:1]。
优势
Quic 相比现在广泛应用的 http2+tcp+tls 协议有如下优势:
1、减少了 TCP 三次握手及 TLS 握手时间。
2、改进的拥塞控制。
3、避免队头阻塞的多路复用。
4、连接迁移。
5、前向安全。
建立连接(握手)
QUIC实现了快速握手,并把握手过程分为两种情况,分别是1-RTT和0-RTT。在介绍这两种握手过程之前,读者需自行熟悉Diffie-Hellman算法的基本原理[3]。
在上图(文献[1:2])中显示了三种不同情况的连接过程。其中最左边的图表示的是第一次连接时的情况,中间的图表示重复连接的情况(在一定条件下,客户端可以重新连接服务器而不需要从初始化情况连接),最右边的图则是重连失败之后从初始话连接的情况。最后一种情况是第一种情况的组会,0-RTT也是1-RTT的一部分,后文中将重点介绍1-RTT的连接过程。
1-RTT
第一次握手:
- 客户端主动向服务器发送Inchoate CHLO报文
- 服务器会向客户端发送REJ报文。REJ报文包含了服务器的配置信息,如长期的Diffie-Hellman值,服务器配置的签名,source-address-token(stk, 用于验证的加密块,包含有服务器看到的客户端的IP地址和服务器当前的时间戳,之后客户端会将该stk发回)等,为了进行身份证明还会使用私钥进行签名,同时也可以防篡改;
- 在收到服务器的配置信息后,客户端会通过证书链机制验签,并实现对服务器的身份认证。
第二次握手:
- 客户端在通过对服务器的验证之后,客户端会生成一个Diffie-Hellman值。此时客户端有了自身和对方的Diffie-Hellman值,就可以计算出初始密钥(initial key, ik);
- 客户端将包含有DH公开之的明文Complete CHLO发送至服务器;
- 客户端使用ik对请求数据加密,发送至服务器;
- 服务器收到Complete CHLO之后就可以获得客户端的Diffie-Hellman的值,就可以计算出初始密钥。
- 服务器立即向客户端发送SHLO报文(ik加密的)。SHLO报文含有一个服务器临时Diffie-Hellman值,可以用于计算前向安全的密钥(会话密钥);
- 服务器收到加密的请求数据,使用初始密钥进行解密;
- 服务器使用会话密钥对响应数据进行加密,发回给客户端。
- 客户端在收到SHLO之后使用初始密钥解密得到服务器的临时DH公开值,根据该临时值计算出会话密钥;
- 客户端收到加密的响应数据后,使用会话密钥进行解密。
整个握手过程会在2个RTT内完成。
0-RTT
客户端在重连同一个服务器时,会使用已经缓存的服务器相关配置信息(stk,DH公开值等信息),并直接向服务器发送Complete CHLO报文,并使用ik对请求报文进行加密。但是服务器方面会标识相应的stk等信息已经过期,这时服务器会发送REJ信息,客户端需要重新与服务器进行连接。
如果没有过期的话,就可以直接建立连接,省下了重新建立连接的开销。
前向安全性
所谓前向安全性就是指,在最后一次握手时,会生成一个会话密钥sk。这样即使服务器的长期DH值被破获,且生成了初始密钥ik,也无法对会话中的数据进行解密。
多路复用机制
基于TCP的应用程序会在TCP单字节流抽象层中实现多路复用。为了避免由于TCP顺序传递导致的头部阻塞(head-of-line blocking)[4],QUIC支持在单个UDP连接中复用多个流,并保证UDP报文的丢失仅影响相应的流,而不会影响其他的流(stream)。
可以在QUIC流上构建任意大小的应用程序报文,最多支持\(2^{64}\)的字节。并且stream的实现是轻量级的,即使消息报文很小也可以为它们使用单独的流。每一个Stream都有stream ID唯一标识。这些流ID由客户端/服务器进行静态分配。客户端主动发起的流的ID永远是奇数,服务器发起的流的ID是偶数。这样可以避免冲突。当在一个未使用过的流上发送数据时,流会自动创建;当需要关闭时,就会在最后一帧数据上设置一个FIN的标志指示接收方关闭流。如果发送方或接收方确定不再需要流上的数据,则可以取消流,而无需断开整个 QUIC 连接。尽管流是可靠的抽象,但 QUIC 不会为已取消的流重新传输数据。
一个QUIC包是由一个公共的头后面跟着一个或多个帧组成的,如下图(图源[1:3])所示。QUIC流复用是通过将流数据封装在一个或多个流帧中来实现的,单个QUIC包可以携带来自多个流的流帧.
报文丢失重传
TCP 序列号有助于提高可靠性,并表示在接收方传送字节的顺序。这种混淆会导致“重传模糊”(retransmission ambiguity)问题,因为重传的 TCP 段携带与原始数据包相同的序列号 。 TCP ACK 的接收者无法确定 ACK 是为原始传输还是为重传而发送,并且通常通过昂贵的超时来检测重传段的丢失。每个 QUIC 数据包都携带一个新的数据包编号,包括那些携带重传数据的数据包。这种设计不需要单独的机制来区分重传的 ACK 和原始传输的 ACK,从而避免了 TCP 的重传模糊问题。流帧中的流偏移用于传递排序,数据包编号表示一个明确的时间顺序,这使得丢失检测比 TCP 更简单、更准确。
QUIC的ACK显示地记录了接收的数据报文和ACK之间的延迟。单调增加的报文编号一起,可以精确估算RTT,有助于丢失检测。QUIC的确认报文支持多达256个ACK,这是使得QUIC比带有SACK的TCP更能适应重新排序或丢失的情况下在线路上保留更多字节。
更多内容参见[5]。
流量控制(Flow Control)
当应用程序从QUIC的接收缓冲区中读取数据较慢时,留恋控制就会限制接收者必须保持的接收缓冲区大小。一个缓慢耗尽的stream会逐渐耗尽整个连接connection的缓冲区,因此必须要限制QUIC连接上的每个流可以消耗的缓冲区大小,避免消耗其他流的缓冲区的大小。这样可以改善流之间潜在的队头阻塞(head-of-line blocking)。因此QUIC采用连接级别的流量控制(connection-level flow control),这样可以限制发送者在所有流中接收者使用的聚合缓冲区;采用流级别的流量控制(stream-level flow control)可以限制发送者在任何给定流上使用的缓冲区。
与HTTP/2类似,QUIC采用基于信用的流量控制。QUIC接收器在每个流中通告接收器愿意接收数据的绝对字节偏移量。在特定流上发送、接收和传递数据时,接收器会定期发送窗口更新帧,以增加该流的窗口偏移限制,从而允许对等方在该流上发送更多数据。连接级流量控制的工作方式与流级流量控制相同,但传递的字节数和接收到的最高偏移量是所有流的。
拥塞控制(Congestion Control)
QUIC支持的拥塞控制算法有:
Reno(TCP用的)、基于Pacing的拥塞控制算法(PBCCA)、TCP CUBIC等。
连接迁移
QUIC连接使用随机生成的64bit的cid唯一确定。cid允许客户机在网络之间漫游,而不受网络或传输层参数变化的影响。
cid使得客户端能够独立于网络地址转换(network address translation, NAT)之外。cid 在路由中起着重要作用,特别是用于连接标识的目的。此外,使用 cids 可以通过探测连接的新路径实现多路径。
在连接迁移期间,端点假设对等方愿意在其当前地址接受数据包。因此,端点可以迁移到新的 IP 地址,而无需首先验证对等方的 IP 地址。新的路由路径可能不支持端点的当前发送速率。在这种情况下,端点需要重新构建它的拥塞控制器。另一方面,从一个新的对等地址接收非探测包 ,确认对等地址已迁移到新的 IP 地址。
实现参考
- Google Quic Project[6]
拓展阅读
Implementation and analysis of QUIC for MQTT[7]
RFC 9000 QUIC: A UDP-Based Multiplexed and Secure Transport
QUIC的初步标准定义。
参考文献
LANGLEY A, RIDDOCH A, WILK A, 等. The QUIC Transport Protocol: Design and Internet-Scale Deployment[C/OL]//Proceedings of the Conference of the ACM Special Interest Group on Data Communication. Los Angeles CA USA: ACM, 2017: 183-196[2022-03-05]. https://dl.acm.org/doi/10.1145/3098822.3098842. DOI:10.1145/3098822.3098842. ︎ ︎ ︎ ︎
J. Iyengar and I. Swett. 2016. QUIC Loss Detection and Congestion Control.IETF Internet Draft, draft-ietf-quic-recovery ︎
KUMAR P, DEZFOULI B. Implementation and analysis of QUIC for MQTT[J/OL]. Computer Networks, 2019, 150: 28-45. DOI:10.1016/j.comnet.2018.12.012. ︎
QUIC协议详解的更多相关文章
- QUIC协议详解之Initial包的处理
从服务器发起请求开始追踪,细说数据包在 QUIC 协议中经历的每一步.大量实例代码展示,简明易懂了解 QUIC. 前言 本文介绍了在 QUIC 服务器在收到 QUIC 客户端发起的第一个 UDP 请求 ...
- HTTP协议详解(转)
转自:http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey 引言 HTTP是一个属于应用层的面向对象的 ...
- HTTP协议详解
Author :Jeffrey 引言 HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展. ...
- 动态选路、RIP协议&&OSPF协议详解
动态选路.RIP协议&&OSPF协议详解 概念 当相邻路由器之间进行通信,以告知对方每个路由器当前所连接的网络,这时就出现了动态选路.路由器之间必须采用选路协议进行通信,这样的选路协议 ...
- ASP.NET知识总结(3.HTTP协议详解)
引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...
- 接口测试之HTTP协议详解
引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...
- 计算机网络(12)-----HTTP协议详解
HTTP协议详解 http请求 http请求由三部分组成,分别是:请求行.消息报头.请求正文 (1)请求行 请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:Metho ...
- OSPF协议详解
CCNP OSPF协议详解 2010-02-24 20:30:22 标签:CCNP 职场 OSPF 休闲 OSPF(Open Shortest Path Fitst,ospf)开放最短路径优先协议,是 ...
- HTTP协议详解(真的很经典)
HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展.目前在WWW中使用的是HTTP/1.0 ...
随机推荐
- 「IOI2009」旅行商
题目传送门 首先,看到这道题感觉就像dp(然鹅没什么用). 一个美好的设想 假如没有两个展销会在同一天开展:前途光明 暴力dp,复杂度o(\(n^2\)). 没有同一天的展销会 暴力dp慢,是因为本质 ...
- Git refusing to merge unrelated histories (拒绝合并不相关仓库)
感谢原文作者:lindexi_gd 原文链接:https://blog.csdn.net/lindexi_gd/article/details/52554159 本文讲的是把git在最新2.9.2,合 ...
- git clone 命令
感谢原文作者:寻芝彬 原文链接:https://www.jianshu.com/p/c992c799f2dd 描述 拷贝一个 Git 仓库到本地 实例 拷贝一个 Git 仓库到本地,本地目录名称与Gi ...
- git reset HEAD 与 git reset --hard HEAD的区别
感谢原文作者:天地逍遥 原文链接:https://www.jianshu.com/p/aeb50b94e6c0 git reset HEAD 是将咱暂存区和HEAD的提交保持一致 git reset ...
- 对JSP中的Session 简单理解
我的理解: 简单来说,要使用服务器端的session对象,就是要有其对应的key,即sessionid,它只认识sessionid. 下面我说的cookie,url重写或者隐藏表单,都是为了将其对应的 ...
- JSP、Servlet和Spring MVC
感谢原博主!!!https://blog.csdn.net/whut2010hj/article/details/80874008 版权声明:本文为博主原创文章,遵循CC 4.0 BY版权协议,转载请 ...
- UIImageView的frame设置
- (void)viewDidLoad { [super viewDidLoad]; /* // 设置frame的方式 // 方式一 UIImageView *imageView = [[UIImag ...
- PHP操作Mysql疑问?
1.Mysql控制台乱码 set character_set_results = 'utf8';
- HMS Core助力宝宝巴士为全球开发者展现高品质儿童数字内容
本文分享于HMS Core开发者论坛<宝宝巴士携HMS Core为全球家庭用户提供优质儿童数字内容>采访稿整理 宝宝巴士是国内有着十多年出海经验的开发者,其旗下有超过200多款儿童益智互动 ...
- 有手就行8——项目构建细节3-Jenkins的参数化构建
有手就行8--项目构建细节3-Jenkins的参数化构建 有时在项目构建的过程中,我们需要根据用户的输入动态传入一些参数,从而影响整个构建结果,这时 我们可以使用参数化构建. Jenkins支持非常 ...