QUIC协议
QUIC
Quick UDP Internet Connections 快速UDP网络连接
QUIC出现的背景
QUIC的提出源自于HTTP存在的问题:关于HTTP存在的问题查看此篇
- HTTP1.0存在的问题:无状态、明文传输、无认证、无完整性校验、非持续连接、串行发送、队头阻塞
- HTTP1.1(1997)遗留的问题:队头阻塞、串行发送、数据包头无压缩且重复发送、服务器只能被动响应客户端的请求
- 无状态:使用Cookie来解决(严格意义来讲,无状态不是一个缺点,是HTTP的特性)
- 明文传输、无认证、无完整性校验:结合TLS解决(即HTTPS)
- 非持续连接:使用
Connection:Keep-Alive
解决 - 队头阻塞:使用管道网络传输解决,可以无需等待响应就可以发送第二个请求,但是接收的响应必须是按顺序的,这意味着,如果返回的其中一个响应出现意外,之后的响应仍然不能接受。(管道网络解决了,但是没有解决)
- HTTP2.0(2015)仍存在的问题:队头阻塞(只解决了应用层面的队头阻塞,TCP的队头阻塞依然存在,如果出现丢包,就需要等待TCP重传)
- 头部压缩:HPACK算法解决,在客户端与服务端维护关于数据包头的表,每次发送的包头将不再发送重复部分
- 二进制化:HTTP2.0下的消息头和消息体都是二进制格式,加快了识别的速度,称为帧:头信息帧和数据帧
- 并行发送:2.0使用多路复用解决,可以在一个连接中并行发送多个请求
- 队头阻塞:2.0对于响应无需再按顺序,报文拆分为首部帧和数据帧,数据帧有流标识符标记顺序,以此实现无序接收的问题
- 服务器推送:服务器可以主动推送静态资源给客户端(对于客户端:如果用户只是点错了,那么他的浏览器也会承担巨多的资源响应,增大负担;对于服务端:可能会带来DDoS攻击)
- HTTP3.0(2019):仅仅四年就推出了3.0,说明克服TCP的性能障碍刻不容缓
- 基于QUIC:QUIC整合了TCP与TLS,总的来说有
问题1:QUIC的提出是为了解决TCP存在的问题的,为什么不修改TCP协议呢?
市面上所有的OS内核,均设计了TCP的实现,修改TCP原有的实现不太现实,而恰好传输层还有一个UDP,就可以依赖于UDP实现TCP的功能了
TLS1.2与1.3
这里插一点额外的知识,介绍一下TLS1.2与1.3的区别
TLS1.2握手细则
在TCP连接建立后,在TLS协议中,DH用于密钥交换,RSA用于数字签名和证书验证:
RSA与DH算法的区别:
RSA也可以进行秘钥交换,只不过不满足前向安全特性,这意味着一旦私钥暴露,这意味着之前的所有消息都暴露;而DH算法却不会。
“Diffie-Hellman Key Exchange”(迪菲-赫尔曼密钥交换协议):通过每次设置不同的随机数来保证即使密钥暴露,也不会暴露之前的消息内容
下面是TLS1.2的握手细则:
- 客户端发起握手:客户端向服务器发送一个ClientHello消息
- 消息包含:TLS版本(客户端支持的版本)、加密套件、Client Random第1随机数(32字节的随机数)
- 服务器回应:收到ClientHello后,向客户端发送一个ServerHello消息
- 消息包含:TLS版本(服务端选择具体使用什么版本)、加密套件、Server Random第2随机数(32字节随机数)
- 服务器发送数字证书给客户端(可选):服务端发送Certificate消息,证书包含公钥与证书信息(注意:这一步与上一步是两条响应消息)
- 浏览器收到Certificate消息,对照信任证书列表,确认证书是否可信
- 服务器端发送ServerKeyExchange消息(可选):
- 对于RSA算法,它的公钥在数字证书内,因此不需要发送ServerKeyExchange
- 对于DH算法或是ECDH算法,服务器将在ServerKeyExchange消息中发送DH协商参数,包括DH公共参数和DH签名等信息
- 服务器端发送ServerHelloDone消息:告诉自己发完了
- 客户端认证证书与密钥交换:Client Key Exchange、Change Ciper Spec、Encrypted Handshake Message消息
- 验证数字证书是否合法:如果认证通过,客户端生成一个48字节的随机数作为预主秘钥(Pre-Master Secret,第3随机数)且使用公钥加密,然后发送给服务器,服务器使用自己的私钥解密,得到预主秘钥
- 计算获得会话秘钥:服务器和客户端都使用第1、2随机数生成一个对称加密密钥,该密钥将用于后续通信的加密和解密。
解释一下第1随机数、第2随机数、预主密钥、主密钥之间的关系:
预主密钥的生成依赖于客户端和服务器的随机数,而主秘钥的生成依赖于预主密钥;
预主密钥是一个临时的对称秘钥,为了临时密钥交换和生成后续加密所需密钥;
主秘钥是一个对称秘钥,加密会话。
换句话说:预主密钥就是临时使用一下,之后可以升级为主秘钥
解释一下这里的安全套件:
安全套件是在客户端与服务器进行握手时,协商的一些加密的具体细则,TLS1.2中有37种不同的组合,这里给出其中一种:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS:表示协议
- ECDHE:表示秘钥交换协议,ECDHE是椭圆曲线的DH算法
- RSA:证书验证、数字签名使用RSA
- AES_256:对称加密算法
- GCM:GCM是一种加密模式,它结合了加密和认证,并提供高效的加密性能
- SHA384:哈希算法(散列算法)
TLS1.3优化
TLS1.3在方方面面对1.2进行了优化
- 前向安全问题:
- 1.2:静态的(即每次不设置随机数来生成秘钥)RSA算法和DH算法均存在前向不安全问题
- 1.3:移除了静态的RSA密钥交换算法和静态的DH密钥交换算法(即现在只能使用动态的DH做密钥交换)
- 握手建立:
- 1.2:一开始的握手消息,即
ClientHello
与ServerHello
是明文的,因此如果黑客截获ClientHello
,通知服务器使用低版本的TLS协议,安全性就会变差 - 1.3:优化了握手步骤
- 1.2:一开始的握手消息,即
- 加密套件:
- 1.2:给出了37种不同组合的加密套件,格式为协议、秘钥交换、对称加密、哈希算法
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- 1.3:建议支持五种,格式为协议、对称加密、哈希
TLS_AES_256_GCM_SHA384
(去掉了密钥交换算法的部分)
- 1.2:给出了37种不同组合的加密套件,格式为协议、秘钥交换、对称加密、哈希算法
- 秘钥交换算法:
- 1.3:只支持三种密钥交换算法,分别是(EC)DHE、PSK-only(类似一种对称加密的方式)、PSK with (EC)DHE,而且去掉了很多不安全的加密算法
- 0-RTT恢复(一个RTT代表一次往返时间)
- 1.2:2RTT
- 1.3:1RTT
TLS1.3握手细则:
- 客户端ClientHello消息:第一随机数、密码套件、直接生成DH随机参数
- 由于减少了加密套件的可选策略,因此1.3的握手可以在第一次就决定DH参数
- 服务器发送ServerHello:第二随机数、DH参数
- 服务器发送证书给客户端
- 客户端收到证书,验证证书合法性,生成预主秘钥,发送给服务器
- 客户端和服务器通过预主秘钥得到主秘钥,即会话秘钥(对称秘钥)
总结:TLS1.3主要优化掉了协商DH参数的部分来加快连接的建立
0-RTT
TLS 1.3中引入了0-RTT(零往返时间)的优化机制。
如果客户端和服务器之前已经建立过TLS 1.3连接并拥有有效的会话票据(session ticket),在后续的重连时,可以使用0-RTT模式来加快连接的建立
注意:0-RTT是存在安全性问题的
QUIC网络模型
QUIC的特点:
- 整合了HTTP2.0的多路复用、流量控制
- 整合了TLS1.3的安全加密方式
- 整合了TCP的握手、拥塞控制、流量控制
- 依托于UDP
QUIC虽然是应用层协议HTTP3依赖的协议,但QUIC本质还是一个应用层协议,其依托于运输层的UDP,设计的核心思想都是来源于TCP和TLS
QUIC的数据包裹在UDP的用户报内发送:如图所示
每一个QUIC包都有独立的编号,丢失某一个只需重传那一个,依次解决了TCP存在的队头阻塞问题
QUIC和TLS1.3一样,首次需要1RTT,重新建立连接只需要0RTT
并且,QUIC规定了连接ID:
- 在TCP连接中,一个TCP连接的建立依赖于源IP、源端口、目的IP、目的端口,只要一个发生变化,就需要重新建立TCP连接
- 在QUIC定义连接ID,只要连接ID不变,就不会重新建立连接
QUIC总结
QUIC的优点:
- QUIC连接建立快:QUIC与TLS1.3一样,有1RTT和0RTT的设计,QUIC还有连接ID,这些都是为了减少连接交互,减少连接次数而设计的
- QUIC扛丢包能力强
- 自带加密,多路复用:因为融合了TLS和HTTP2
缺点:
- 兼容性与部署问题:一种新型协议,对中间设备、运营商、浏览器都需要支持
- 比较耗CPU性能
- 报文头部比较大
- 0RTT将没有前向安全性