quic协议浅析
认识quic
- QUIC ,即 快速UDP网络连接( Quick UDP Internet Connections), 是由Google 提出的实验性网络传输协议 ,位于 OSI 模型传输层。
- 值得一提的是,quic协议通常在tcp/ip模型中的应用层去实现,有两点原因:
- 新的传输层协议为了保证正确性和对其他协议的公平性,从研发到在操作系统中部署,往往需要数年时间。
- 用户与服务器之间需要经过防火墙和NAT,路由器等其他网络设备,这些设备往往只认TCP和UDP,使用新的传输层协议可能会造成通信问题或者安全问题。
- QUIC 旨在解决TCP 协议的缺陷,并最终替代 TCP 协议, 以减少数据传输,降低连接建立延迟时间,加快网页传输速度
- QUIC诞生于2012年
- quic的rfc
quic的开源库与应用
- gquic是谷歌用c++写的,且集成到了chromium里
- msquic是微软用c写的,2020年开始,还不成熟
- facebook的quic是c++写的,暂不考虑
- nginx也有quic服务,但是没有自带的client
- lsquic是litespeed基于MIT的c版本quic,比较稳定,各大平台都通过了测试
- ngtcp2是一个实验行的quic客户端,代码简洁性上是做的最好的,目前srs流媒体服务器,curl等开源项目基于其做二次开发比较多。
quic协议分析
quic中的重要概念
- quic连接:client发起连接,server接收连接,一个连接标记了一次会话;
- 流(stream):一个quic连接内,单向或者双向的有序字节流,一个quic连接可以包含多个stream;
- 帧(frame):quic链接内的最小通信单元,一个quic数据包中包含一个或多个帧。
quic与tcp的比较
比较项 | TCP | QUIC |
---|---|---|
握手延迟 | TCP需要三次握手+TLS握手(v1.3一次,V1.2两次) | 传输层与TLS握手放到一起 |
再次连接 | 有本地cookie,TCP+TLS需要一次到两次 | quic有本地cookie,不需要再次握手 |
头阻塞问题 | tcp的seq与连接关联,丢一个包影响所有应用数据 | 基于UDP封装传输层的stream,stream内部保序所以没有头部阻塞问题 |
链接迁移 | 内核在五元组中维持会话,五元组改变则重建连接 | quic基于cid标识连接,五元组变化不影响cid |
特性迭代速度 | 内核中实现,迭代慢 | 用户态实现,可以灵活实现更好的quic方案 |
安全性 | TCP头部是明文传输的 | 除了一些必要字段,quic头部也是加密的 |
quic与tcp相似的地方
- 传输方式借鉴了HTTP2,在一条tcp连接中传输多个逻辑上独立的流,因为多条流之间不会互相影响,所以基于quic的http3没有队头堵塞。
- 拥塞控制:quic默认启用和tcp一样的cubic丢包检测算法,但是可以插拔。
- 连接迁移:由于逻辑流不与四元组关联,可以方便的在应用层实现流量迁移而不需要重新握手。
- 身份认证:相较于tcp需要结合TLS增加安全性,quic内置安全策略,使用一个初始密钥一个会话秘钥,恶意环境表现与TCP+TLS相当,友好环境表现更佳。
quic的报文字段
首部
字段名 | 解释 |
---|---|
flags | 用于指示该数据包的类型和属性。例如,FIN标志表示该数据包是流结束标记,ACK标志表示该数据包是确认报文。 |
connection ID | 一个随机生成的64位整数,用于标识该连接。 |
QUIC version | 指定使用的QUIC协议版本。 |
Packet Number | 这个数字用于确定包保护的密码nonce,实际上是个序列号。 |
Frame Type用于标识帧类型,有PADDING,PING,ACK,STREAM等等
帧格式
详情可以参考上面的rfc链接70页。控制帧比较繁杂,这里重点说下用于传输数据的stream帧;
frame Type
- Bit7必须设置为 1,表示 Stream 帧,一个udp通道可以发送多个流
- Bit6设置为 1,表示发送端在这个 stream 上已经结束发送数据,流将处于半关闭状态
- Bit5: 如果设置为 1,表示 Stream 头中包含 Data length 字段
- Bit4,3,2: 表示 offset 的长度。000 表示0字节,001表示2字节,010 表示3 字节,以此类推
- Bit1和0: 表示 Stream lD 的长度。00 表示1字节,01表示2字节,10 表示3字节,11 表示4字节
Stream ID:流 ID ,用于标识该包所属的流,流量控制和多路复用会涉及到。
Offset:表示该数据包在整个数据中的偏移量,用于排序。
Data Length:数据长度,标识实际应用数据长度。
Data:实际数据。
如何看待quic
quic面临的挑战
- 路由器限制443端口
- udp包过多可能会因为qos的限制被服务器商认为是网络攻击
- 协议太新,网络设备还没有兼容
- 标准尚未落地,开源库还没有经过充分验证,不建议直接跟进。
本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对c/c++linux课程感兴趣的读者,可以去零声官网查看详细的服务;