跟坚哥学QUIC系列:版本协商(Version Negotiation)
QUIC 目前由 IETF 工作组 起草进行标准化设计,预计 2021 年初提交 RFC。IETF 工作组在设计过程中发布了多个版本的草案,目前最新的草案版本是 2020-10-20 发布的 draft-32。另外 QUIC 是在用户侧(User space)实现的,版本迭代会比较方便和快速,市面上的 QUIC 协议的实现 可能基于不同的版本(比如 draft-29, draft-30, ...)。这意味着客户端(client)和服务端(server)支持的 QUIC 协议版本可能不一样,它们建立连接时需要先进行版本协商(Version Negotiation),使用双方都支持的一个版本。
客户端和服务端创建连接时,客户端在首次发起请求时需要带上它支持的协议版本号。
发送版本协商数据包
当服务端收到新连接的数据包时,它会检查是否支持客户端的协议版本:
- 如果服务端可以支持客户端的版本, 服务端将为连接的整个生命周期使用这个协议版本。
- 如果服务端不支持该版本,服务端就响应版本协商包(Version Negotiation packet),附上它所支持的版本集合,这将增加 1-RTT(Round-Trip Time) 的延迟开销。
注意事项
- 为了减少放大攻击(amplification attacks),QUIC 协议要求客户端发送的初始数据包大小(Initial Datagram Size)最少为 1200 字节。如果初始数据包小于 1200 字节,需要使用 PADDING frame 填充,不然该数据包会被服务端丢弃。
- 只有服务端可以发送版本协商包(Version Negotiation packet),客户端不能发送。
- 服务端识别到 0-RTT 数据包(之前有成功连接过),可以选择不发送版本协商包,以减少额外的 1-RTT 版本协商延迟。
- 服务端响应发送的初始(Initial)数据包或版本协商数据包可能丢失,客户端可以继续发送新的数据包、直到它成功接收到服务端响应,或者放弃连接尝试。
处理版本协商数据包
客户端收到版本协商包后,从服务端所支持的版本集合里面挑选它所支持的版本。
- 如果所有的版本都不支持,则客户端需要丢弃连接。
- 如果有匹配到支持的版本,客户端尝试使用该版本创建新连接。新连接必须使用一个新的随机目标连接ID(Destination Connection ID)。
注意事项
- 如果客户端已接收并成功处理了任何其他包(包括早期的版本协商包),则客户端必须丢弃它后来新收到的版本协商包。
- 客户端需要检查协商数据包的连接ID是否匹配,确保不是攻击者伪造发送的。
- 当前版本没有防止降级攻击(downgrade attacks)的机制,不能在草案(draft)版本之外。如何防止版本降级攻击(downgrade attacks)将放在以后的版本里面定义。
版本号
QUIC 版本使用 32 位无符号数字标识。版本号 0x00000000 被保留用来表示版本协商。版本号 0x00000001 是为作为 RFC 发布的协议版本保留的。
0x?a?a?a?a 格式的版本号被保留(reserved)用于强制执行版本协商。也就是说,所有字节的低 4 位是 1010(二进制)的任何版本号。保留的版本号永远不会代表真正的协议,客户端可以使用其中一个保留版本号,并期望服务端启动版本协商,测试是否能正确处理不支持的协议版本。
0xff000000 用于标识 IETF 草案版本号。例如,draft-ietf-quic-transport-13 将被标识为 0xff00000d。
QUIC 协议实现者可以在 https://link.zhihu.com/?target=https%3A//github.com/quicwg/base-drafts/wiki/QUIC-Versions 注册用于私有实验的QUIC版本号。
版本协商数据包(Version Negotiation packet)
在客户端接收数据包时(packet),它将基于 Version 字段的值为 0 来标识版本协商包。
Version Negotiation Packet { Header Form (1) = 1, Unused (7), Version (32) = 0, Destination Connection ID Length (8), Destination Connection ID (0..2040), Source Connection ID Length (8), Source Connection ID (0..2040), Supported Version (32) ..., }
Unused:由服务端随机选择,客户端必须忽略此字段的值。服务端应将此字段的最高有效位(0x40)设置为1,以便版本协商数据包具有固定位(Fixed Bit)字段。
Version:必须设置为 0x00000000
Destination Connection ID:是服务端接收到的数据包(packet)里面的 Source Connection ID。
Source Connection ID:是服务端接收到的数据包(packet)里面的 Destination Connection ID,这个 ID 最初是由客户端随机选择的。
回显这两个连接 ID 可以让客户端确信服务端收到了数据包,并且版本协商数据包不是由攻击者生成的。
未来版本的 QUIC 可能对连接 ID 的长度有不同的要求。特别是,连接 ID 可能具有较小的最小长度或更大的最大长度。因此,特定版本规则的连接 ID 不能影响服务端关于是否发送版本协商包的决定。
Supported Version:服务端支持的 32 位版本号集合
注意事项
- 版本协商包不需要 ACK
- 版本协商包没有 Packet Number 和 Length 字段。因此,它将使用整个 UDP 数据报(datagram)。
- 服务端不能在单个 UDP 数据报(datagram)里面发送多个版本协商包。
QUIC 的全称是 Quick UDP Internet Connections protocol,由 Google 设计提出,目前由 IETF 工作组推动进展,其设计的目标是替代 TCP 成为 HTTP/3 的数据传输层协议。熹乐科技在物联网(IoT)和边缘计算(Edge Computing)场景也一直在打造底层基于 QUIC 通讯协议的边缘计算微服务框架YoMo,长时间关注 QUIC 协议的发展,本系列文章总结了学习 QUIC 协议时的知识点。
在线社区:discord/quic
维护者:YoMo

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
QUIC 协议简介
QUIC的全称是 Quick UDP Internet Connections protocol,由 Google 设计提出,目前由 IETF 工作组推动进展,其设计的目标是替代 TCP 成为 HTTP/3 的数据传输层协议。熹乐科技在物联网(IoT)和边缘计算(Edge Computing)场景也一直在打造底层基于 QUIC 通讯协议的边缘计算微服务框架YoMo,长时间关注 QUIC 协议的发展,本文章简单介绍了 QUIC 协议的特点和术语。 在线社区:discord/quic 维护者:YoMo QUIC 是一种多路复用和安全的通用传输协议,它提供: 流(stream)多路复用 流(stream)和连接(connection)级别的流量控制 建立低延迟连接(1-RTT 或者 0-RTT) 连接迁移(Connection migration)和弹性 NAT 重绑定 经过身份验证和加密的头部(header) 和有效载荷(payload) QUIC 建立了客户端(client)和服务端(server)之间有状态的交互连接。连接的主要目的是通过应用协议支持结构化的数据交换。 应用协议通过 Q...
- 下一篇
Vue3 的模板编译优化
Vue3 正式发布已经有一段时间了,前段时间写了一篇文章(《Vue 模板编译原理》)分析 Vue 的模板编译原理。今天的文章打算学习下 Vue3 下的模板编译与 Vue2 下的差异,以及 VDOM 下 Diff 算法的优化。 编译入口 了解过 Vue3 的同学肯定知道 Vue3 引入了新的组合 Api,在组件 mount 阶段会调用 setup 方法,之后会判断 render 方法是否存在,如果不存在会调用 compile 方法将 template 转化为 render。 //packages/runtime-core/src/renderer.tsconstmountComponent=(initialVNode,container)=>{constinstance=(initialVNode.component=createComponentInstance(//...params))//调用setupsetupComponent(instance)}//packages/runtime-core/src/component.tsletcompileexportfunctio...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- 设置Eclipse缩进为4个空格,增强代码规范