这篇文章上次修改于 2348 天前,可能其部分内容已经发生变化,如有疑问可询问作者。 TLS1.3已经正式发布有段时间 ,cloudflare等cdn厂商已经率先支持。很多文章提到了TLS1.3以及QUIC协议可以有效的降低传输层的延迟,改善用户体验。而TLS1.3和QUIC降低用户延迟有一个共同点,那就是在提供同等功能特性下,减少Round-Trip Time (RTT)次数。你甚至会经常听到QUIC和TLS1.3的拥趸说TLS1.3和QUIC可以做到0-RTT,基本消灭了(安全)传输层的延迟。事实真的是这样吗? # TLS RTT 我们先看一下TLS1.2 (以ECDH为例)的建立加密连接的过程: ![tls1.3-1.jpg](/usr/uploads/2018/07/2504306728.jpg) 从上图可以看出,在发送应用数据之前,TLS安全传输层需要经过2-RTT才能完成握手。如果是恢复会话,TLS1.2可以采用[Session ID][1]或[Session Ticket] [2]进行快速握手: ![tls1.3-2.jpg](/usr/uploads/2018/07/3880904974.jpg) 从上图可以看到,在使用Session Ticket的情况下,需要1-RTT。 那么TLS1.3是如何进一步优化的呢? ## TLS 1.3完全握手: ![tls1.3-3.jpg](/usr/uploads/2018/07/212950117.jpg) 在完全握手情况下,TLS 1.3需要1-RTT建立连接。与TLS1.2有两点不同:握手过程中移除了ServerKeyExchange和ClientKeyExchange, DH (Diffie-Hellman) 参数通过 key_share 传输。 ## TLS1.3恢复会话握手 ![tls1.3-4.jpg](https://blog.37hi.com/usr/uploads/2018/07/972208614.jpg) TLS1.3恢复会话可以直接发送加密后的应用数据,不需要额外的TLS握手。因此,我们常说的TLS1.3 0-RTT握手其实是指恢复加密传输层会话不需要额外的RTT。但是,在第一次进行完全握手时,是需要1-RTT的。 与TLS1.2比较,无论是完全握手还是恢复会话,TLS1.3均比TLS1.2少1-RTT。因此,TLS1.3从被提上draft草案开始获得了各方面的好评。从nginx和Chrome支持此特性的速度可见一斑。 但是TLS1.3也并不完美。TLS 1.3 O-RTT无法保证前向安全性(Forward secrecy). 简单讲就是,如果当攻击者通过某种手段获取到了Session Ticket Key,那么该攻击者可以解密以前的加密数据。 这个问题不是TLS1.3独有,TLS1.2也存在这个问题。对于TLS1.3来说,要缓解该问题可以通过设置ServerConfiguration中的Expiration Date字段,使得与Session Ticket Key相关的DH静态参数在短时间内过期(一般几个小时)。 使用TLS最多的场景是HTTPS和HTTP/2. 以HTTP/2为例,一个完整的 HTTP Request需要经历的RTT如下: ![tls1.3-rtt.jpg](/usr/uploads/2018/07/3634514871.png) 从上表可以看出: - 首次连接发起HTTP请求是非常昂贵的。因此,如果你是用HTTPS作一些不可告人的代理应用的话,一定尽量保持长连接,避免频繁建立新连接。 - 连接的multlplexing(多路复用)可以有效减少RTT次数,降低延迟。在连接复用的情况下,TLS1.3将整个http request的RTT降低到了1个,达到理论的最小值。 ![tls1.3-5.jpg](/usr/uploads/2018/07/3617325227.jpg) - 当客户端首次发起QUIC连接时,客户端想服务器发送一个client hello消息,服务器回复一个server reject消息。该消息中有包括server config,类似于TLS1.3中的key_share交换。这需要产生1-RTT. 事实上,QUIC加密协议的作者也明确指出当前的QUIC加密协议是「注定要死掉的」(destined to die), 未来将会被TLS1.3代替。只是在QUIC提出来的时候,TLS1.3还没出生呢,这只是一个临时的加密方案。 - 当客户端获取到server config以后,就可以直接计算出密钥,发送应用数据了,可以认为是0-RTT。密钥推导可以参见Key derivation. - 因此,QUIC握手除去首次连接需要产生1-RTT,理论上,后续握手都是0-RTT的。 - 假设1-RTT=100ms, QUIC建立安全连接连接的握手开销为0ms, 功能上等价于TCP+TLS, 但是握手开销比建立普通的TCP连接延迟都低: ![tls1.3-6.jpg](/usr/uploads/2018/07/887151484.jpg) (正常体为首次建立连接的延迟,粗体部分为后续握手的延迟) ## HTTP/2 over TLS 1.3 vs QUIC 当前,QUIC普遍的应用场景是 HTTP/2 over QUIC. 我们以一个完整的 HTTP Request需要经历的RTT为例,比较TLS1.3与QUIC的RTT开销: ![quic-tls-rtt](/usr/uploads/2018/07/1949001209.png) 从上表可以看出:HTTP/2 over QUIC相比HTTP/2 over TLS 1.3最大的优势是首次连接是的RTT开销降低了1-RTT(25%)。在连接复用的情况,QUIC的RTT开销与TLS1.3相等。 前面我们提到,QUIC(UDP+QUIC Crypto)在功能层面等价于TCP+TLS, 并且其加密协议(QUIC Crypto)未来会被TLS1.3代替。而在连接复用的情况下QUIC与TLS1.3的RTT开销旗鼓相当,那么是否意味着在HTTP/2的应用场景下,TCP+TLS1.3就可以完全替代QUIC呢?答案是否定的,主要原因如下: - QUIC从数据包级别解决了队头阻塞的问题,而TCP+TLS只能解决http request级别的队头阻塞问题。具体原理可以参见[《当我们在谈论HTTP队头阻塞时,我们在谈论什么》](https://liudanking.com/arch/what-is-head-of-line-blocking-http2-quic/ "《当我们在谈论HTTP队头阻塞时,我们在谈论什么》"). - QUIC与HTTP/2结合更加紧密,比如HTTP/2的stream, frame, Header Compression都可以直接映射到QUIC的stream, packet, Header Compression. 从协议分层看这会使得应用层和传输层紧耦合,但是在HTTP/2这个具体场景下,QUIC可以接管HTTP/2的拥塞控制,相较于HTTP/2 over TLS 1.3会受到TCP和HTTP/2两层的拥塞控制来说,无疑具有更直接有效的控制策略。并且,QUIC的拥塞控制是应用层可插件化的。虽然你也可以为TCP编写拥塞控制模块,但那是一个内核模块,稍不注意就会让系统崩溃。如果你有兴趣的话,实现一个QUIC的[BBR](https://en.wikipedia.org/wiki/TCP_congestion_control#TCP_BBR "BBR")拥塞控制模块是很容易的。 - QUIC支持连接迁移(Connection Migration),即在客户端切换网络IP以后,也能够保持连接不间断。这对于移动网络这种漫游网络特别友好,再加上QUIC在首次连接上RTT比TLS1.3低25%,因此会有更好的用户体验。虽然[Multipath TCP, MPTCP](https://en.wikipedia.org/wiki/Multipath_TCP "Multipath TCP, MPTCP")也可以吃支持连接迁移,但这受限于操作系统和网络协议栈,要想普及,任重道远。 - QUIC支持Forward Error Correction,利用一定的数据包冗余,提供丢包时恢复丢包数据的能力。减少了包重传的数量,进而减少延迟,提高带宽利用率。如果你使用过[kcptun](https://github.com/xtaci/kcptun "kcptun"),你会发现它也采用了FEC,对于弱网和高丢包环境下,效果尤其好。 当然,QUIC也是有缺点的。比如很多运营商对UDP的QoS级别是比TCP低的,甚至只允许DNS 53端口的UDP包,其他UDP包都是被封掉的。在IDC中,UDP的优先级一般也比TCP低。因此,即使以后大规模普及QUIC,也不会完全替代TCP+TLS,毕竟需要确保在QUIC不可用时,可以回落到TCP+TLS. # 总结 在首次连接的时候,无论是TLS1.3还是QUIC都需要1-RTT,在连接复用的情况下,两者才能做到0-RTT. 在HTTP/2的应用场景中,QUIC可以有效的降低首次连接的RTT次数,并且支持连接迁移、FEC以及更加灵活高效的拥塞控制,因此可以在移动网络、弱网环境提供低延迟的用户体验。 # 参考: - [Improved Handshakes in TLS version 1.3](https://timtaubert.de/blog/2015/11/more-privacy-less-latency-improved-handshakes-in-tls-13/ "Improved Handshakes in TLS version 1.3") - [An overview of TLS 1.3 and Q&A](https://blog.cloudflare.com/tls-1-3-overview-and-q-and-a/ "An overview of TLS 1.3 and Q&A") - [QUIC Wire Layout Specification](https://docs.google.com/document/d/1WJvyZflAO2pq77yOLbp9NsGjC1CHetAXV8I0fQe-B_U/edit# "QUIC Wire Layout Specification") - [QUIC Crypto](https://docs.google.com/document/d/1g5nIXAIkN_Y-7XJW5K45IblHd_L2f5LTaDUDwvZ5L6g/edit# "QUIC Crypto") - [QUIC FEC v1](https://docs.google.com/document/d/1Hg1SaLEl6T4rEU9j-isovCo8VEjjnuCPTcLNJewj7Nk/edit "QUIC FEC v1") - [QUIC: next generation multiplexed transport over UDP](https://www.youtube.com/watch?v=hQZ-0mXFmk8 "QUIC: next generation multiplexed transport over UDP") [1]: https://en.wikipedia.org/wiki/Transport_Layer_Security#Session_IDs "Session ID" [2]: https://en.wikipedia.org/wiki/Transport_Layer_Security#Session_tickets "Session Ticket" 转自:https://liudanking.com/network/tls1-3-quic-%E6%98%AF%E6%80%8E%E6%A0%B7%E5%81%9A%E5%88%B0-0-rtt-%E7%9A%84/
没有评论