你听过HTTPS、HTTP2.0、SPDY,但是这些应用层协议都是基于可靠的传输层协议TCP来实现的。那么,基于高效的UDP协议有没有一种相对可靠的应用层协议呢?
Why QUIC?
你听过HTTPS、HTTP2.0、SPDY,但是这些应用层协议都是基于可靠的传输层协议TCP来实现的。那么,基于高效的UDP协议有没有一种相对可靠的应用层协议呢?
图1 why quic?
What is QUIC?
Quick UDP Internet Connection(QUIC)协议是Google公司提出的基于UDP的高效可靠协议。
说它高效,是因为使用了无连接的UDP而不是迭代周期更长的需要修改系统内核网络栈的TCP协议。
说它可靠,是因为将改进了的可靠TCP的协议特征用到了QUIC上。
同时,也复用和改进了HTTP2的典型特征,譬如二进制分帧,多路复用,header压缩等。
图2 what's quic?
How QUIC works?
建立连接
一、基于TCP+TLS的HTTP2建连
出于HTTP的明文和无法验证服务器的真实性,在TCP的基础上引入了TLS协议,目前广泛使用的HTTPS是基于TCP+TLS协议,HTTP2也被主流浏览器默认支持TLS。
但对于建立连接的耗时而言,TCP本身就需要握手时延,而TLS协议为了使得客户端和服务器端在不安全的网络通信中协商出后续安全通信所需的加密私钥,更是要经过额外2次RTT(RoundTrip Time往返时间)
图3 TCP+TLS建连过程
除了TCP建立连接过程,TLS握手过程要经过如下步骤:
1、客户端提供加密套件(算法)列表,版本等信息
2、服务器端提供自己的证书,选择的加密套件,非对称加密公钥(自己保留私钥)等
3、客户端提供自己的证书,用服务器公钥和加密套件加密的自己的私钥
4、服务端用保留的私钥解密客户端传来的加密私钥,得到的私钥即为后续加密传输使用的对称密钥,最后完成握手
此时,双方协商出了对称密钥。基于TCP+TLS的HTTP2建连过程结束,大约需要耗时200-300ms。
二、 QUIC建连
为了保证安全,QUIC也是加密传输数据的,所以在QUIC的建连过程中也需要双方协商出一个加密私钥。但与TLS不同,QUIC采用的加密算法仅需要一个RTT就能实现密钥交换,并且该算法也被用于目前正在草案阶段的TLS1.3协议。该就是Diffie-Hellman密钥交换算法。
图4 Diffie-Hellman算法
可以看到,客户端和服务端各自保留了自己的私钥a和b,通过交换各自的公钥B和A,以及基底G和很大的质数P,双方就能计算出相等的私钥S,这个S就是加密传输的对称密钥。
另外,根据离散对数的不可逆,即使拿到G,P,和质数B,也很难推导出私钥b(同理私钥a),也就保证了计算密钥的安全。
该过程对应到QUIC建连的过程中如下图。
图5 1RTT建连
1、客户端发起Inchoate client hello
2、服务器返回Rejection,包括密钥交换算法的公钥信息,算法信息,证书信息等被放到server config中传给客户端
3、客户端发起client hello,包括客户端公钥信息
此时,双方各自计算出了对称密钥。QUIC的1RTT建连过程结束,平均只耗时100ms以内。
后续发起连接的过程中,一旦客户端缓存或持久化了server config,就可以复用并结合本地生成的私钥进行加密数据传输了,不需要再次握手,从而实现0RTT建立连接。
协商升级
一般情况下,Chrome浏览器和服务器端协商使用QUIC协议要经过如下步骤:
1、客户端发出tcp请求
2、服务端如果支持quic可以通过响应头alt-svc告知客户端
3、客户端同时发起tcp连接和quic连接竞赛
4、一旦quic建立连接获胜则采用quic协议发送请求
5、如遇网络或服务器不支持quic/udp,客户端标记quic为broken
6、传输中的请求通过tcp重发
7、5min后尝试重试quic,下一次尝试增大到10min
8、一旦再次成功采用quic并把broken标记取消
其中,支持quic的alt-svc头部信息如下图示,ma为有效时间(单位秒),v为支持的quic版本信息。