QUIC协议

1、QUIC 简介

QUIC 全称:Quick UDP Internet Connections,是一种基于 UDP 的传输层协议。由 Google 自研,2012 年部署上线,2013 年提交 IETF,2021 年 5 月,IETF 推出标准版 RFC9000。

从协议栈可以看出:QUIC = HTTP/2 + TLS + UDP

2、QUIC 实现原理

2.1、数据格式

一个 QUIC 数据包的格式如下:

由 header 和 data 两部分组成。

header 是明文的,包含 4 个字段:Flags、Connection ID、QUIC Version、Packet Number;

data 是加密的,可以包含 1 个或多个 frame,每个 frame 又分为 type 和 payload,其中 payload 就是应用数据;

数据帧有很多类型:Stream、ACK、Padding、Window_Update、Blocked 等,这里重点介绍下用于传输应用数据的 Stream 帧。

Frame Type: 帧类型,占用 1 个字节

(1)Bit7:必须设置为 1,表示 Stream 帧

(2)Bit6:如果设置为 1,表示发送端在这个 stream 上已经结束发送数据,流将处于半关闭状态

(3)Bit5:如果设置为 1,表示 Stream 头中包含 Data length 字段

(4)Bit432:表示 offset 的长度。000 表示 0 字节,001 表示 2 字节,010 表示 3 字节,以此类推

(5)Bit10:表示 Stream ID 的长度。00 表示 1 字节,01 表示 2 字节,10 表示 3 字节,11 表示 4 字节

Stream ID: 流 ID,用于标识数据包所属的流。后面的流量控制和多路复用会涉及到

**Offset:**偏移量,表示该数据包在整个数据中的偏移量,用于数据排序。

Data Length: 数据长度,占用 2 个字节,表示实际应用数据的长度

Data: 实际的应用数据

2.2、建立连接

先分析下 HTTPS 的握手过程,包含 TCP 握手和 TLS 握手,TCP 握手:

从图中可以看出,TCP 握手需要 2 个 RTT。

TLS 握手:密钥协商(1.3 版本)

从图中可以看出,TLS 握手需要 1 个 RTT,也就是 1 次 RTT 就把通信密钥协商好了,这是怎么做到的?

(1)客户端:生成随机数 a,选择公开的大数 G 和 P,计算 A=a*G%P,将 A 和 G 发送给服务器,也就是 Client Hello 消息

(2)服务器:生成随机数 b,计算 B=b*G%P,将 B 发送给客户端,也就是 Server Hello 消息

(3)客户端:使用 ECDH 算法生成通信密钥 KEY = aB = ab*G%P

(4)服务器:使用 ECDH 算法生成通信密钥 KEY = bA = ba*G%P

所以,这里的关键就是 ECDH 算法,a 和 b 是客户端和服务器的私钥,是不公开的,而其他参数是公开的。ECDH 算法有个非常重要的特征:即使知道 A、G、P,通过 A = a*G%P 公式也是无法推到出 a 的,保证了私钥的安全性。

综上所述,HTTPS 建立连接需要 3 个 RTT,由于 QUIC 的握手是基于 TLS1.3 实现的,所以首次建立连接时也是需要 1 次 RTT,那 QUIC 是如何做到 0-RTT 握手的呢?

2.2.1、0-RTT 握手

其实原理很简单:客户端缓存了 ServerConfig(B=b*G%P),下次建连直接使用缓存数据计算通信密钥:

(1)客户端:生成随机数 c,选择公开的大数 G 和 P,计算 A=c*G%P,将 A 和 G 发送给服务器,也就是 Client Hello 消息

(2)客户端:客户端直接使用缓存的 ServerConfig 计算通信密钥 KEY = cB = cb*G%P,加密发送应用数据

(3)服务器:根据 Client Hello 消息计算通信密钥 KEY = bA = bc*G%P

也就是说,客户端不需要经过握手就可以发送应用数据,这就是 0-RTT 握手。再来思考一个问题:假设攻击者记录下所有的通信数据和公开参数(A1=aG%P,A2=cG%P,......),一旦服务器的随机数 b(私钥)泄漏了,那之前通信的所有数据就都可以破解了。

为了解决这个问题,需要为每次会话都创建一个新的通信密钥,来保证前向安全性

2.2.2、前向安全

前向安全:是指用来产生会话密钥的长期密钥泄露出去,不会泄漏以前的通讯内容。

(1)客户端:生成随机数 a,选择公开的大数 G 和 P,计算 A=a*G%P,将 A 和 G 发送给服务器,也就是 Client Hello 消息

(2)客户端:客户端直接使用缓存的 ServerConfig 计算初始密钥 initKey = aB = ab*G%P,加密发送应用数据 1

(3)服务器:根据 Client Hello 消息计算初始密钥 initKey = bA = ba*G%P

(4)服务器:生成随机数 c,计算 C=c*G%P,使用 initKey 加密 C,发送给客户端,也就是 Server Hello 消息

(5)客户端:使用 initKey 解码获取 C,计算会话密钥 sessionKey = aC = ac*G%P,加密发送应用数据 2

(6)服务器:计算会话密钥 sessionKey = cA = ca*G%P,解密获取应用数据 2

客户端缓存的 ServerConfig 是服务器静态配置的,是可以长期使用的。客户端通过 ServerConfig 实现 0-RTT 握手,使用会话密钥 sessionKey 保证通信数据的前向安全。

2.3、可靠传输

QUIC 是基于 UDP 协议的,而 UDP 是不可靠传输协议,那 QUIC 是如何实现可靠传输的呢?

可靠传输有 2 个重要特点:

(1)完整性:发送端发出的数据包,接收端都能收到

(2)有序性:接收端能按序组装数据包,解码得到有效的数据

问题 1:发送端怎么知道发出的包是否被接收端收到了?

解决方案:通过包号(PKN)和确认应答(SACK)

(1)客户端:发送 3 个数据包给服务器(PKN = 1,2,3)

(2)服务器:通过 SACK 告知客户端已经收到了 1 和 3,没有收到 2

(3)客户端:重传第 2 个数据包(PKN=4)

由此可以看出,QUIC 的数据包号是单调递增的。也就是说,之前发送的数据包(PKN=2)和重传的数据包(PKN=4),虽然数据一样,但包号不同。

问题 2:既然包号是单调递增的,那接收端怎么保证数据的有序性呢?

解决方案:通过数据偏移量 offset

每个数据包都有一个 offset 字段,表示在整个数据中的偏移量。

接收端根据 offset 字段就可以对异步到达的数据包进行排序了。为什么 QUIC 要将 PKN 设计为单调递增?解决 TCP 的重传歧义问题:

由于原始包和重传包的序列号是一样的,客户端不知道服务器返回的 ACK 包到底是原始包的,还是重传包的。但 QUIC 的原始包和重传包的序列号是不同的,也就可以判断 ACK 包的归属。

2.4、流量控制

和 TCP 一样,QUIC 也是利用滑动窗口机制实现流量控制:

发送端的窗口大小由接收端告知,包括发送窗口和可用窗口,如果发送端收到了接收端的 ACK 确认应答(比如 ACK 36),那整个窗口就会向右滑动,发送新的数据包。

和 TCP 不同的是,QUIC 的滑动窗口分为 Connection 和 Stream 两种级别。Connection 流量控制:规定了所有数据流的总窗口大小;Stream 流量控制:规定了每个流的窗口大小。

假设现在有 3 个 Stream,滑动窗口分别如下:

则整个 Connection 的可用窗口大小为:20+30+10 = 60

2.5、拥塞控制

拥塞控制是通过拥塞窗口限制发送方的数据量,避免整个网络发生拥塞。那拥塞窗口(cwnd)和滑动窗口(发送窗口:swnd,接收窗口:rwnd)有什么关系呢?

swnd = min(cwnd,rwnd)

也就是说,发送窗口的大小是由接收窗口和拥塞窗口共同决定的。那拥塞窗口的大小是如何计算的?通过 4 个拥塞控制算法:慢启动、拥塞避免、拥塞发生、快速恢复

2.5.1、慢启动

初始拥塞窗口大小 cwnd=1,也就是可以传输 1 个 MDS(Max Datagram Size)大小的数据包,一般网卡允许传输的最大数据单元 MTU 的大小是 1500 字节。对于 UDP 数据报而言:MDS = 1500(MTU)- 20(IP 首部)- 8(UDP 首部) = 1472 字节

慢启动算法: 当发送方每收到一个 ACK,拥塞窗口就加 1(cwnd++)

由此可以看出,慢启动阶段,拥塞窗口呈指数增长,那增长到多少是个头?

有一个上限值:ssthresh(slow start threshold),从源码看,这个值是 2000 * MDS

const QuicPacketCount kDefaultMaxCongestionWindowPackets = 2000;

  • 当 cwnd < ssthresh 时,使用慢启动算法
  • 当 cwnd >= ssthresh 时,使用拥塞避免算法

2.5.2、拥塞避免

当拥塞窗口大小超过慢启动上限后,就会进入拥塞避免阶段。

拥塞避免算法: 当发送方每收到一个 ACK,拥塞窗口就加 1/cwnd

假设现在的 cwnd=8,可以发送 8 个数据包,当收到这 8 个包的 ACK 时,拥塞窗口才会加 1,由此可知,在拥塞避免阶段,拥塞窗口是线性增长的。

那啥时候是个头呢?不管,让它继续增长,直到网络发生拥塞,出现丢包,这时就会触发重传机制,进入拥塞发生阶段

2.5.3、拥塞发生

重传有 2 种:超时重传和快速重传

如果发生超时重传,使用的拥塞发生算法为:

  • ssthresh = cwnd / 2
  • cwnd = 1

重新使用慢启动和拥塞避免算法增加拥塞窗口的大小。

如果发生快速重传(发送方收到 3 个相同的 ACK),使用的拥塞发生算法为:

  • cwnd = cwnd / 2
  • ssthresh = cwnd

接下来就会进入快速恢复阶段。

2.5.4、快速恢复

快速恢复算法:cwnd = ssthresh + 3(因为收到 3 个 ACK),然后进入拥塞避免阶段。

2.5.5、常见算法

  • New Reno:基于丢包检测
  • CUBIC:基于丢包检测
  • BBR:基于网络带宽

和 TCP 不同的是,QUIC 是在用户空间实现的拥塞控制,可以非常灵活的设置,甚至可以为每一个请求都设置一种拥塞控制算法。

2.6、多路复用

多路复用是 HTTP/2 的主要特性之一。

概念:单条 TCP 连接上可以同时发送多个 HTTP 请求,解决了 HTTP1.1 中单个连接 1 次只能发送 1 个请求的性能瓶颈。HTTP/2 能实现多路复用的根本原因是采用了二进制帧格式的数据结构。

  • Length:表示 Payload 的长度
  • Type:表示帧类型
  • Flags:帧标识
  • Stream ID:数据帧所属的流
  • Payload:应用数据,长度由 Length 字段指定

一个请求就对应一条流,通过 Stream ID 就可以判断该数据帧属于哪个请求,假设有 A 和 B 两个请求,对应的 Stream ID 分别为 1 和 2,那这个 TCP 连接上传输的数据大概如下:

虽然在 HTTP 应用层,可以同时发送多个请求,但是在 TCP 传输层,仍然只有 1 个滑动窗口来发送这些数据包,考虑下面的情形:

客户端发送的 5 个数据包(56789)服务器都收到了,并且回应了 5 个 ACK,但是第 5 个数据包的 ACK 丢失了,导致客户端的发送窗口无法向前移动,也就无法发送新的数据,这就是 TCP 层的队头阻塞问题。

HTTP/2 虽然通过多路复用解决了 HTTP 层的队头阻塞,但仍然存在 TCP 层的队头阻塞。那 QUIC 是如何解决 TCP 层的队头阻塞问题的呢?其实很简单,HTTP/2 之所以存在 TCP 层的队头阻塞,是因为所有请求流都共享一个滑动窗口,那如果给每个请求流都分配一个独立的滑动窗口,是不是就可以解决这个问题了?

QUIC 就是这么做的:

A 请求流上的丢包不会影响 B 请求流上的数据发送。但是,对于每个请求流而言,也是存在队头阻塞问题的,也就是说,虽然 QUIC 解决了 TCP 层的队头阻塞,但仍然存在单条流上的队头阻塞。这就是 QUIC 声明的无队头阻塞的多路复用。

2.7、连接迁移

连接迁移:当客户端切换网络时,和服务器的连接并不会断开,仍然可以正常通信,对于 TCP 协议而言,这是不可能做到的。因为 TCP 的连接基于 4 元组:源 IP、源端口、目的 IP、目的端口,只要其中 1 个发生变化,就需要重新建立连接。但 QUIC 的连接是基于 64 位的 Connection ID,网络切换并不会影响 Connection ID 的变化,连接在逻辑上仍然是通的。

假设客户端先使用 IP1 发送了 1 和 2 数据包,之后切换网络,IP 变更为 IP2,发送了 3 和 4 数据包,服务器根据数据包头部的 Connection ID 字段可以判断这 4 个包是来自于同一个客户端。QUIC 能实现连接迁移的根本原因是底层使用 UDP 协议就是面向无连接的。

3、QUIC 小结

本文尽量用通俗易懂的语言介绍了 QUIC 协议实现原理,目的是让大家对 QUIC 有一个基本的了解,当然,这只是 QUIC 协议的冰山一角,更详细具体的内部实现还需要深入研究标准文档和源码,如果文中有描述不对的地方,欢迎批评指正,多多交流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/158228.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PDM篇 | SOLIDWORKS 2024新功能

改进的视觉内容 优点 重要数据和系统信息一目了然。 • 通过装配体可视化功能&#xff0c;在 SOLIDWORKS 中以图形方式查看零部件数据&#xff0c;如工作流程状态。 • 使用特定图标迅速识别焊件切割清单零部件。 增强的数据保护和跟踪功能 优点 通过附加的审计跟踪信息&am…

C++智能指针(二)——weak_ptr初探

文章目录 1. shared_ptr 存在的问题2. 使用weak_ptr2.1 初始化 weak_ptr2.2 访问数据 3. 附录4. 参考文献 1. shared_ptr 存在的问题 与 shared_ptr 的引入要解决普通指针存在的一些问题一样&#xff0c;weak_ptr 的引入&#xff0c;也是因为 shared_ptr 本身在某些情况下&…

焦炭反应性及反应后强度试验方法

声明 本文是学习GB-T 4000-2017 焦炭反应性及反应后强度试验方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 7— 进气口&#xff1b; 8— 测温热电偶。 图 A.1 单点测温加热炉体结构示意图 A.3 温度控制装置 控制精度&#xff1a;(11003)℃。…

JS数组方法map 和 forEach 的区别

一、定义&#xff1a; forEach(): 针对每一个元素执行提供的函数。 map(): 创建一个新的数组&#xff0c;其中每一个元素由调用数组中的每一个元素执行提供的函数得来。 二、区别 1、map 方法返回一个新的数组&#xff0c;而 forEach 方法不会返回任何值&#xff0c;仅仅是遍…

ChatGPT,AIGC 数据库应用 Mysql 常见优化30例

使用ChatGPT,AIGC总结出Mysql的常见优化30例。 1. 建立合适的索引:在Mysql中,索引是重要的优化手段,可以提高查询效率。确保表的索引充分利用,可以减少查询所需的时间。如:create index idx_name on table_name(column_name); 2. 避免使用select * :尽可能指定要返回的…

恒温区检测热电偶

声明 本文是学习GB-T 4000-2017 焦炭反应性及反应后强度试验方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 7— 进气口&#xff1b; 8— 测温热电偶。 图 A.1 单点测温加热炉体结构示意图 A.3 温度控制装置 控制精度&#xff1a;(11003)℃。…

文件上传 [MRCTF2020]你传你呢1

题目来源&#xff1a;buuctf [MRCTF2020]你传你&#x1f40e;呢1 打开题目 我们随便上传个木马文件上去 我们bp抓包看看

Linux 系统中提供CPU性能分析工具整理

Linux 系统中提供CPU性能分析工具整理 汇总 查看CPU信息 在linux操作系统中&#xff0c;CPU的信息在启动的过程中被装载到虚拟目录/proc下的cpuinfo文件中&#xff0c;我们可以通过 cat /proc/cpuinfo 查看一下&#xff1a; cat /proc/cpuinfo显示如下&#xff1a; rootthe…

gitlab docker部署,备份,恢复。附踩坑记录

本次安装在CentOS7下进行 1、安装yum 检查是否已经安装yum yum --version如果未安装 sudo yum install -y yum-utils添加镜像源&#xff1a; 国外镜像源&#xff1a;yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo阿里镜像源&am…

Xshell7和Xftp7超详细下载教程(包括安装及连接服务器附安装包)

1.下载 1.官网地址&#xff1a; XSHELL - NetSarang Website 选择学校免费版下载 2.将XSHELL和XFTP全都下载下来 2.安装 安装过程就是选择默认选项&#xff0c;然后无脑下一步 3.连接服务器 1.打开Xshell7&#xff0c;然后新建会话 2.填写相关信息 出现Connection establi…

香港服务器选纯国际线路上网稳定吗?

​  关于香港服务器的线路&#xff0c;我们平时接触较多的分三大类&#xff0c;即纯国际线路、回国专线和香港本地线路。三者价格上存有差距&#xff0c;原因体现在线路和网络质量上&#xff0c;当然这些会关系到服务器的速度和稳定性。譬如&#xff0c;有些用户在选择了纯国…

说明书MS2721A频谱分析仪7.1GHz

安立Anritsu MS2721A 频谱分析仪 MS2721A 是 Anritsu 的 7.1 GHz 频谱分析仪。频谱分析仪测量已知和未知信号的频谱功率。频谱分析仪收集信息&#xff0c;例如输入信号与其频率相比的幅度。作为频率分析仪&#xff0c;频谱分析仪的主要用途是记录和分析电输入信号以及其他信号的…

[23] IPDreamer: Appearance-Controllable 3D Object Generation with Image Prompts

pdf Text-to-3D任务中&#xff0c;对3D模型外观的控制不强&#xff0c;本文提出IPDreamer来解决该问题。在NeRF Training阶段&#xff0c;IPDreamer根据文本用ControlNet生成参考图&#xff0c;并将参考图作为Zero 1-to-3的控制条件&#xff0c;用基于Zero 1-to-3的SDS损失生成…

【想法】取代NI的 PCIe-8371

PCIe-8371 涨价非常厉害。 PCA3 https://www.terasic.com.tw/cgi-bin/page/archive.pl?LanguageEnglish&CategoryNo65&No1143 PCA3 (PCIe Cable Adapter, Gen 3) is a conversion card to connect boards with your host PC. It can support up to PCIe Gen 3 x4. …

文字与视频结合效果

效果展示 CSS 知识点 mix-blend-mode 属性的运用 实现整体页面布局 <section class"sec"><video autoplay muted loop><source src"./video.mp4" type"video/mp4" /></video><h2>Run</h2><!-- 用于切…

ChatGPT或将引发现代知识体系转变

作为当下大语言模型的典型代表&#xff0c;ChatGPT对人类学习方式和教育发展所产生的变革效应已然引起了广泛关注。技术的快速发展在某种程度上正在“倒逼”教育领域开启更深层次的变革。在此背景下&#xff0c;教育从业者势必要学会准确识变、科学应变、主动求变、以变应变&am…

小谈设计模式(28)—解释器模式

小谈设计模式&#xff08;28&#xff09;—解释器模式 专栏介绍专栏地址专栏介绍 解释器模式角色分析抽象表达式&#xff08;Abstract Expression&#xff09;终结符表达式&#xff08;Terminal Expression&#xff09;非终结符表达式&#xff08;Non-terminal Expression&…

【爬虫实战】用pyhon爬百度故事会专栏

一.爬虫需求 获取对应所有专栏数据&#xff1b;自动实现分页&#xff1b;多线程爬取&#xff1b;批量多账号爬取&#xff1b;保存到mysql、csv&#xff08;本案例以mysql为例&#xff09;&#xff1b;保存数据时已存在就更新&#xff0c;无数据就添加&#xff1b; 二.最终效果…

visual studio设置主题和背景颜色

visual studio2019默认的主题有4种&#xff0c;分别是浅白色、深黑色、蓝色、蓝(额外对比度)&#xff0c;背景颜色默认是纯白色RGB(255,255,255)。字体纯白色看久了&#xff0c;眼睛会感到酸痛、疲劳&#xff0c;建议改成浅白RGB(250,250,250)、豆沙绿RGB(85,123,105)、透明蓝白…

语言模型编码中/英文句子格式详解

文章目录 前言一、Bert的vocab.txt内容查看二、BERT模型转换方法(vocab.txt)三、vocab内容与模型转换对比四、中文编码总结 前言 最近一直在学习多模态大模型相关内容&#xff0c;特别是图像CV与语言LLM模型融合方法&#xff0c;如llama-1.5、blip、meta-transformer、glm等大…