quic协议go语言 quit协议( 四 )


QUIC在握手过程中使用Diffie-Hellman算法协商初始密钥,初始密钥依赖于服务器存储的一组配置参数,该参数会周期性的更新 。
初始密钥协商成功后 , 服务器会提供一个临时随机数,双方根据这个数再生成会话密钥 。
具体握手过程如下:
(1) 客户端判断本地是否已有服务器的全部配置参数,如果有则直接跳转到(5),否则继续
(2) 客户端向服务器发送inchoate client hello(CHLO)消息,请求服务器传输配置参数
(3) 服务器收到CHLO,回复rejection(REJ)消息 , 其中包含服务器的部分配置参数
(4) 客户端收到REJ,提取并存储服务器配置参数,跳回到(1)
(5) 客户端向服务器发送full client hello消息 , 开始正式握手,消息中包括客户端选择的公开数 。此时客户端根据获取的服务器配置参数和自己选择的公开数,可以计算出初始密钥 。
(6) 服务器收到full client hello,如果不同意连接就回复REJ,同(3);如果同意连接,根据客户端的公开数计算出初始密钥,回复server hello(SHLO)消息,SHLO用初始密钥加密 , 并且其中包含服务器选择的一个临时公开数 。
(7) 客户端收到服务器的回复,如果是REJ则情况同(4);如果是SHLO,则尝试用初始密钥解密,提取出临时公开数
(8) 客户端和服务器根据临时公开数和初始密钥,各自基于SHA-256算法推导出会话密钥
(9) 双方更换为使用会话密钥通信,初始密钥此时已无用 , QUIC握手过程完毕 。之后会话密钥更新的流程与以上过程类似,只是数据包中的某些字段略有不同 。
QUIC包含三种报文包类型:
协商Package、公用复位package、普通帧信息Package
Version Negotiation Packets and Public Reset Packets, and regular packets containing frames.
如果客户端的版本不被服务器接受,则将导致1-RTT的延迟 。服务器将发送一个版本协商包给客户端 。这个包将设置版本标记,并将包含服务器支持的版本的集合 。
当客户端从服务器收到一个版本协商包,它将选择一个可接受的协议版本并使用这个版本重发所有包 。
为了避免流ID冲突,流 ID 必须是偶数 , 如果流是由服务器初始化的话,如果流由客户端初始化则必须为奇数 。
0不是一个有效的流 ID 。流 1 被保留用来加密握手,它应该是第一个客户端初始化的流 。当基于QUIC使用HTTP/2时,
流 3 被保留来为其它流传输压缩的首部,以确保首部的处理和传送可靠且有序 。
各种帧格式参考:QUICWireLayoutSpecification.pdf
官方参考地址:
quic 协议分析 HTTP 3,它来了,QUIC(quick udp internet connection “快速 UDP 互联网连接”)正如其名一样,它就是快 。其正在标准化为新一代的互联网传输协议 。是由google提出的使用udp进行多路并发的传输协议 。
QUIC解决了什么问题呢?从上世纪90年代至今,互联网一直按照一成不变的模式发展着 。使用ipv4进行路由,使用tcp进行连接层面的拥塞控制 , 并保证其传输的可靠性,使用tls层进行安全加密和身份验证 , 使用http进行应用的数据传输 。
这么多年的发展 , 这些协议只是小部分或者细节上有了改变,tcp提出了几个新的拥塞控制算法,tls改变了加密方式 , http层进化出了h2 。但是互联网发展至今,网络传输的内容越来越大,用户对传输的时延 , 带宽提出越来越大的要求 。
tcp虽然也在拥塞控制上提出了一些优秀的拥塞控制算法,如BBR但是限制于其对操作系统内核版本的要求,tcp 的 TFO,windows操作系统又支持不好等 。导致想要切换成更高效的协议成本巨大 。

推荐阅读