QUIC的那些事 | 包类型及格式

目录

报文头

特殊报文

版本协商报文

Public Reset报文

普通报文(Regular Packet)

帧包(Frame Packet)

FEC包(FEC Packet)

参考资料


QUIC 的 packet 除了个别报文比如 PUBLIC_RESET 和 CHLO,所有报文头部都是经过认证的,报文 Body 都是经过加密的。这样只要对 QUIC 报文任何修改,接收端都能够及时发现,有效地降低了安全风险。

如图 1所示,红色部分是 Stream Frame 的报文头部,有认证。绿色部分是报文内容,全部经过加密。

QUIC的那些事 | 包类型及格式_第1张图片 图 1 QUIC报文格式

QUIC报文分为特殊报文和普通报文。特殊报文又分为两类:版本协商报文(Version Negotiation Packets)及公共重置报文(Public Reset Packets)。普通报文也分为两类:帧报文及FEC(Forward Error Correction)报文。

QUIC报文的大小需要满足路径MTU的大小以避免被分片。当前QUIC在IPV6下的最大报文长度为1350,IPV4下的最大报文长度为1370.

报文头

QUIC报文都有一个公共的头部,大小在2-19字节之间,格式如图 2所示:

 

QUIC的那些事 | 包类型及格式_第2张图片 图 2 Public Header 格式

其中,图 2中的长度是以Bit为单位,如Connection ID的0,8,32,64,单位均为Bit.

第一字节为:Public  Flags

Public Flag的8位如下所示,左边为高位,右边为低位

Bit7

Bit6

Bit5

Bit4

Bit3

Bit2

Bit1

Bit0

如果Bit0被置上(0x01 = PUBLIC_FLAG_VERSION = 0x01),该字段的含义取决于报文是客户端还是服务端发送。如果是客户端发送,这一位被置上表示QUIC Version字段不为空,且QUIC Version字段被填充为客户端的QUIC版本信息。在客户端收到服务端同意建立该版本的连接报文抵达之前,客户端发送的所有报文的这一位必须都要被设置。如果服务端同意建立该版本的连接,那么这一位不用设置。如果这一位被服务端置上,那么表示该报文是版本协商报文(Version Negotiation Packet)。

如果Bit1被置上(0x02 = PUBLIC_FLAG_RESET),表明该报文是公共重置报文(Public Reset packet)

Bit2、Bit3两位表示报文中的Connection ID的长度。直至协商另外一个值之前,在所有的报文中,这两位必须设置被设置为相同(客户端可能请求更少的数据,所以ConnectID的长度需要变化)

0x0C(Bit3及Bit2均为1)表示Connection ID长度是8字节

0x08(Bit3位1,Bit2为0)表示Connection ID长度是4字节

0x04(Bit3位0,Bit2为1)表示Connection ID长度是1字节

0x00(Bit3及Bit2均为0)表示无Connection ID

Bit4、Bit5两位表示每个数据包中存在的数据包编号的字节数。对于帧数据,这两位才使用,对于Public Reset报文及Version Negotiation报文,这两位必须为0

0x30(Bit5及Bit4均为1)表示:包序号是6个字节

0x20(Bit5为1,Bit4为0)表示:包序号是4个字节

0x10(Bit5为0,Bit4为1)表示:包序号是2个字节

0x00(Bit5及Bit4均为0)表示:包序号是1个字节

Bit6:预留给多路径使用

Bit7:未使用,必须为0

Connection ID:客户端随机选择的最大长度为64位的无符号整数。但是,长度可以协商。

QUIC Version:QUIC协议的版本号,32位的可选字段。如果Public Flag & FLAG_VERSION != 0,这个字段必填。客户端设置Public Flag中的Bit0为1,并且填写期望的版本号。如果客户端期望的版本号服务端不支持,服务端设置Public Flag中的Bit0为1,并且在该字段中列出服务端支持的协议版本(0或者多个),并且该字段后不能有任何报文。

Packet Number:长度取决于Public Flag中Bit4及Bit5两位的值,最大长度6字节。发送端在每个普通报文中设置Packet Number。发送端发送的第一个包的序列号是1,随后的数据包中的序列号的都大于前一个包中的序列号。

Public Flags的解析流程如图3所示:

QUIC的那些事 | 包类型及格式_第3张图片  图3 Public Flag解析过程

 

特殊报文

版本协商报文

版本协商报文(version negotiation packet)只由服务端发送。版本协议报文以1字节的Public Flag及8字节的Connection ID开始。必须设置PUBLIC_FLAG_VERSION且标识Connection ID长度为8字节,最后面就是服务端支持的协议版本(4字节)。

 

QUIC的那些事 | 包类型及格式_第4张图片 图 4 协议协商报文格式

 

Public Reset报文

Public Reset报文以1字节的Public Flag及8字节的Connection ID开始。必须设置PUBLIC_FLAG_RESET且标识Connection ID长度为8字节,剩余的部分是QUIC Tag。

 

QUIC的那些事 | 包类型及格式_第5张图片 图 5 Public Reset报文格式

        

         Tag value map包含如下的tag-values:

         RNON (public reset nonce proof):64位的无符号整数,必填

         RSEQ (rejected packet number) :64位的无符号整数,必填

         CADR (client address):客户端的IP地址及端口。当前用于调试用途,可选        

普通报文(Regular Packet)

普通的报文被验证(authenticated)且被加密。公有头被验证但是没有加密,从Private Flags字段开始的报文被加密。普通的报文包含AEAD(authenticated encryption and associated data)报文。普通报文必须被解密,并且密文被解密后,明文以Private Header开始。

普通报文中私有头格式如图 6所示:

 

QUIC的那些事 | 包类型及格式_第6张图片 图 6 普通报文中私有头格式

Private Flags解析

当Bit0被置为1时(0x01 = FLAG_ENTROPY): 对于数据包,表示该包包含1位熵;对于FEC(Forward Error Correction)包,表示包含受保护包熵的异或。

当Bit1被置为1时(0x02 = FLAG_FEC_GROUP):表示是否有FEC 字段(Forward Error Correction)

当Bit2被置为1时(0x04 = FLAG_FEC):表示是FEC包

FEC(FEC Group Number offset):可选字段,8位的无符号整数,是相对值。

QUIC帧数据包由帧填充,通过Frame Type确定到底是何种数据。

帧包(Frame Packet)

除了私有头外,帧包有一系列的基于类型的帧数据的负载,通用的帧包的格式如图 7所示:

图 7 Frame packet格式

 

FEC包(FEC Packet)

FEC包(FLAG_FEC标志被置为1)的负载只包含位于FEC组中的每个数据包的空填充负载的XOR值。每个FEC包的FLAG_FEC_GROUP标志也必须被置为1。格式如图8所示

 

图 8 FEC包格式

 

参考资料

https://tools.ietf.org/html/draft-tsvwg-quic-protocol-02#ref-3

QUIC的那些事 | 包类型及格式_第7张图片 扫描二维码,关注“清远的梦呓”公众号,在手机端查看文章

 

你可能感兴趣的:(网络通信,QUIC)