HTTPS 请求的大概过程及其工作原理
HTTPS 请求的大概过程及其工作原理
HTTPS是HTTP协议的安全扩展版本,它通过加密传输数据来确保互联网通信的安全性。然而,HTTPS请求的建立过程相对复杂,首次连接需要经过多次握手才能完成。本文将详细介绍HTTPS请求的全过程,包括TCP三次握手、TLS四次握手以及HTTP协议的数据交换,并分析为什么这个过程需要4.5倍的往返延迟(RTT)。
HTTPS是对HTTP协议的扩展,我们可以使用它在互联网上安全地传输数据。然而,HTTPS请求的发起方第一次从接收方获取响应需要经过4.5倍的往返延迟(Round-Trip Time,RTT)。本文将详细介绍请求发起和响应的过程,分析为什么HTTPS协议需要通过4.5-RTT的时间获得服务提供方的响应:
- TCP协议——通信双方通过三次握手建立TCP连接
- TLS协议——通信双方通过四次握手建立TLS连接
- HTTP协议——客户端向服务端发送请求,服务端发回响应
这里的分析建立在特定版本的协议实现以及常见场景上,随着网络技术的发展,我们能够减少需要的网络通信次数,本文会在对应章节中提到一些常见的优化方案。
TCP 三次握手
- 客户端向服务端发送带有SYN的数据段以及客户端开始发送数据段(Segment)的初始序列号SEQ = 100;
- 服务端收到数据段时,向客户端发送带有SYN和ACK的数据段;
- 通过返回ACK = 101确认客户端数据段的初始序列号;
- 通过发送SEQ = 300通知客户端,服务端开始发送数据段的初始序列号;
- 客户端向服务端发送带有ACK的数据段,确认服务端的初始序列号,其中包含ACK = 301;
TLS 1.2 建立连接
- 客户端向服务端发送Client Hello消息,其中携带客户端支持的协议版本、加密算法、压缩算法以及客户端生成的随机数;
- 服务端收到客户端支持的协议版本、加密算法等信息后;
- 向客户端发送Server Hello消息,并携带选择特定的协议版本、加密方法、会话ID以及服务端生成的随机数;
- 向客户端发送Certificate消息,即服务端的证书链,其中包含证书支持的域名、发行方和有效期等信息;
- 向客户端发送Server Key Exchange消息,传递公钥以及签名等信息;
- 向客户端发送可选的消息CertificateRequest,验证客户端的证书;
- 向客户端发送Server Hello Done消息,通知服务端已经发送了全部的相关信息;
- 客户端收到服务端的协议版本、加密方法、会话ID以及证书等信息后,验证服务端的证书;
- 向服务端发送Client Key Exchange消息,包含使用服务端公钥加密后的随机字符串,即预主密钥(Pre Master Secret);
- 向服务端发送Change Cipher Spec消息,通知服务端后面的数据段会加密传输;
- 向服务端发送Finished消息,其中包含加密后的握手信息;
- 服务端收到Change Cipher Spec和Finished消息后;
- 向客户端发送Change Cipher Spec消息,通知客户端后面的数据段会加密传输;
- 向客户端发送Finished消息,验证客户端的Finished消息并完成TLS握手;
TLS握手的关键在于利用通信双方生成的随机字符串和服务端的公钥生成一个双方经过协商后的密钥,通信的双方可以使用这个对称的密钥加密消息防止中间人的监听和攻击,保证通信的安全。
在TLS 1.2中,我们需要2-RTT才能建立TLS连接,但是TLS 1.3通过优化协议,将两次往返延迟降低至一次,大幅度减少建立TLS连接所需要的时间,让客户端可以在1-RTT之后就能向服务端传输应用层数据。
这里就不展开介绍TLS 1.3建立连接的过程了,除了减少常规握手下的网络开销,TLS 1.3还引入了0-RTT的连接建立过程;60%的网络连接都是用户在第一次访问网站或者间隔一段时间后访问时建立的,剩下的40%可以通过TLS 1.3的0-RTT策略解决,然而该策略与TFO的实现原理比较相似,都是通过重用会话和缓存来实现的,所以存在一定的安全风险,使用时也应该结合业务的具体场景。
HTTP
在已经建立好TCP和TLS通道上传输数据是比较简单的事情,HTTP协议可以直接利用下层建立的可靠的、安全的通道传输数据。客户端通过TCP的套接字接口向服务端写入数据,服务端在接收到数据、进行处理后通过相同的途径返回。因为整个过程需要客户端发送请求以及服务端返回响应,所以耗时是1-RTT。
图 5 - HTTP 请求和响应
HTTP协议的数据交换只会消耗1-RTT,当客户端和服务端仅处理一次HTTP请求时,从HTTP协议本身我们已经无法进行优化。不过随着请求的数量逐渐增加,HTTP/2就可以复用已经建立的TCP连接减少TCP和TLS握手带来的额外开销。
总结
当客户端想要通过HTTPS请求访问服务端时,整个过程需要经过7次握手并消耗9倍的延迟。如果客户端和服务端因为物理距离上的限制,RTT约为40ms时,第一次请求需要180ms;不过如果我们想要访问美国的服务器,RTT约为200ms时,这时HTTPS请求的耗时为900ms,这就是一个比较高的耗时了。我们来总结一下HTTPS协议需要9倍时延才能完成通信的原因:
- TCP协议需要通过三次握手建立TCP连接保证通信的可靠性(1.5-RTT);
- TLS协议会在TCP协议之上通过四次握手建立TLS连接保证通信的安全性(2-RTT);
- HTTP协议会在TCP和TLS上通过一次往返发送请求并接收响应(1-RTT);
需要注意的是,本文对往返延时的计算都基于特定的场景以及特定的协议版本,网络协议的版本在不断更新和演进,过去忽略的问题最开始都会通过补丁的方式更新,但是最后仍然会需要从底层完成重写。
HTTP/3就是一个这样的例子,它会使用基于UDP的QUIC协议进行握手,将TCP和TLS的握手过程结合起来,把7次握手减少到了3次握手,直接建立了可靠并且安全的传输通道,将原本900ms的耗时降低至500ms,我们会在后面的文章介绍HTTP/3协议相关的内容。到最后,我们还是来看一些比较开放的相关问题,有兴趣的读者可以仔细思考一下下面的问题:
- 作为传输层协议,QUIC协议和TCP协议之间有什么异同?
- 为什么可以通过0-RTT建立客户端和服务端的连接?
如果对文章中的内容有疑问或者想要了解更多软件工程上一些设计决策背后的原因,可以在博客下面留言,作者会及时回复本文相关的疑问并选择其中合适的主题作为后续的内容。
参考资料
- Walls, Colin (2005). Embedded Software: The Works. Newnes. p. 344. ISBN 0-7506-7954-9. Archived from the original on 2019-02-09. Retrieved 2018-10-20. https://books.google.com.hk/books?id=FLvsis4_QhEC&pg=PA344&redir_esc=y#v=onepage&q&f=false
- What is an SSL Certificate?https://www.websecurity.digicert.com/security-topics/what-is-ssl-tls-https
- Wikipedia: HTTPShttps://en.wikipedia.org/wiki/HTTPS
- RFC793 Transmission Control Protocol, September 1981 RFC793https://tools.ietf.org/html/rfc793
- RFC5246 The Transport Layer Security (TLS) Protocol. Version 1.2. Aug 2008 RFC5246https://tools.ietf.org/html/rfc5246
- 为什么 TCP 建立连接需要三次握手https://draveness.me/whys-the-design-tcp-three-way-handshake
- 为什么 TCP/IP 协议会拆分数据https://draveness.me/whys-the-design-tcp-segment-ip-packet
- Cheng, Y., Chu, J., Radhakrishnan, S., and A. Jain, “TCP Fast Open”, RFC 7413, DOI 10.17487/RFC7413, December 2014,https://www.rfc-editor.org/info/rfc7413.
- The First Few Milliseconds of an TLS 1.2 Connectionhttps://tlseminar.github.io/first-few-milliseconds/
- TLS 1.3 Handshake: Taking a Closer Lookhttps://www.thesslstore.com/blog/tls-1-3-handshake-tls-1-2/
- Introducing Zero Round Trip Time Resumption (0-RTT)https://blog.cloudflare.com/introducing-0-rtt/