【计算机网络】TCP / TLS 握手原理及实践

1,362 阅读15分钟

TCP / TLS 握手实践

参考文章:

  1. HTTPS - 揭秘 TLS 1.2 协议完整握手过程
  2. TLS协议分析(二)架构总

TCP 建立连接的三次握手过程

TCP 三次握手基本上是计算机网络最常见的面试题了,更进一步的问题就是 HTTPS 和 HTTP 的加密机制。首先我们回顾一下三次握手的标准答案:

  • 第一次:客户端向服务器发送 SYN 字段请求建立连接;客户端发送SYN包(seq=j)到服务器,并进入 SYN_SEND 状态,等待服务器确认;
  • 第二次:服务器收到带有 SYN 的请求,通过返回带有 SYN + ACK 的数据包(ack = syn + 1),表示同意建立连接,并发送向客户端建立连接端请求,SYN 用来测试从服务器到客户端的连接通道是否畅通,此时服务器进入 SYN_RECV 状态;
  • 第三次:客户端收到 SYN + ACK 后,回复服务器 ACK = SYN + 1,确认建立从客户端到服务器的连接;服务器收到后,双方都进入 ESTABLISHED 状态,表示连接建立成功。

三次握手是为了验证连接的双向数据传输是否能够正常工作。

TCP 握手实践

下面通过 WrieShark 来验证一下,这是一次请求 https://www.baidu.com 抓取到的网络请求信息:

StepsourcedestinationProtocolLengthInfo
1182.24.42.37110.242.68.4TCP7859115 → 443 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=64 TSval=4120303113 TSecr=0 SACK_PERM=1
2110.242.68.4182.24.42.37TCP78443 → 59115 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1380 WS=32 SACK_PERM=1
3182.24.42.37110.242.68.4TCP5459115 → 443 [ACK] Seq=1 Ack=1 Win=262144 Len=0

在此次握手过程中,客户端 IP 为 182.24.42.37:59115;服务器 IP 为 110.242.68.4:443。进行了三个步骤:

  • Step.1 ,客户端发起 TCP 请求,标识为 [SYN],Seq = 0;
  • Step.2 ,服务器返回信息给客户端,标识为 [SYN, ACK],Seq = 0,Ack = 1;
  • Step.3 ,客户端确认收到来自服务器消息,标识为 [ACK],Seq = 1,Ack = 1。

经过验证,的确是如经典答案所述。但这次是一个 HTTPS 请求 ,实际在 TCP 三次握手后,会建立 TLS 链接,下面介绍 TLS 的四次握手过程。

TLS 连接过程

上面请求的网址是 https://www.baidu.com,这是一次 HTTPS 请求。HTTPS 是由 HTTP 加上 TLS/SSL 协议构建的可进行加密传输、身份认证的网络协议,主要通过 数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。

TLS协议的优势是与高层的应用层协议(如HTTPFTPTelnet等)无耦合应用层协议能透明地运行在TLS协议之上,由TLS协议进行创建加密通道需要的协商和认证。应用层协议传送的数据在通过TLS协议时都会被加密,从而保证通信的私密性。 -- from 百度百科

HTTPS 是经过 TLS/SSL 传输层安全性协议包装后的 HTTP 协议。

TLS 加密算法

单向加密过程

5b2790b067b440e7c506145dbc4dfc48.png

第一次握手

客户端 -> 服务器: Client Hello

客户端连接到服务器请求创建安全的连接,此时的消息携带客户端支持的加密算法列表信息和一个随机数,握手开始。

第二次握手

服务器 -> 客户端: Server Hello

服务器从客户端支持的加密算法列表中选出一种,通知客户端,此时服务器发出的消息携带一个服务器生成的随机数。

服务器 -> 客户端: Certificate

服务器向客户端发送数字证书,证书包含服务器的名称、CA 机构和服务器的公钥信息。

服务器 -> 客户端: Server Key Exchange

客户端无法自行计算预主密钥,需要服务器的参与,此时服务器发送带有密钥交换算法需要的额外数据,以便客户端可以计算出预主公钥。

服务器 -> 客户端: Server Hello Done

服务器发送 Server Hello Done ,并开始等待客户端的响应。

第三次握手

客户端 -> 服务器: Client Key Exchange

此时,客户端需要验证证书的有效性,验证通过取出公钥,生成一个随机数用公钥加密,发送给服务器,因为公钥是来自于服务器的证书中,所以服务器能够使用私钥进行解密。

计算预主密钥:此时,客户端开始计算预主密钥,服务器收到消息后,解析出随机数,也开始计算预主密钥,两个预主密钥用来后续的通信。

计算主密钥:通过预主密钥和服务器随机数、客户端随机数,计算出主密钥。

计算会话密钥:通过主密钥、服务器随机数、客户端随机数生成会话密钥。

这个最终的会话密钥包括:对称加密密钥(symmetric key)、消息认证码密钥(mac key)、初始化项量(iv key,只在必要时生成)。

客户端完成会话密钥计算后,发消息通知服务器:客户端已生成加密密钥,并切换到加密模式。

服务器收到该消息后,就同样地开始计算预主密钥、主密钥、生成会话密钥。

客户端 -> 服务器: Encrypted Handshake Message

将之前的握手数据做一个摘要,通过会话密钥加密(对称加密),发送 Encrypted Handshake Message 消息给服务器进行校验。

第四次握手

服务器 -> 客户端: Change Cipher Spec

服务器发消息通知客户端:服务器已生成加密密钥,请求客户端切换加密模式。

服务器 -> 客户端: Encrypted Handshake Message

将之前的握手数据做一个摘要,通过会话密钥加密(对称加密),发送 Encrypted Handshake Message 消息给客户端进行校验。

双向加密过程

双向加密过程前两次握手和单向加密过程相同,不在赘述。区别是第三次握手,客户端会先发送证书给服务器,服务器会验证客户端证书的合法性。

第三次握手

客户端 -> 服务器: Client Certificate

客户端将包含客户端公钥的数字证书发送给服务器。

服务器拿到客户端证书后,进行验证,验证通过获取到了客户端的公钥。

Client Certificate 消息是客户端收到 Server Hello Done 后,可以发送的第一条消息。仅当服务器要求了一个证书的情况下,客户端才发送 Client Certificate 消息,如果没有可用的合适证书,客户端必须发送一条不包含任何证书的 Client Certificate 消息。

客户端 -> 服务器: Client Key Exchange

此时,客户端需要验证证书的有效性,验证通过取出公钥,生成一个随机数用公钥加密,发送给服务器,因为公钥是来自于服务器的证书中,所以服务器能够使用私钥进行解密。

计算预主密钥:此时,客户端开始计算预主密钥,服务器收到消息后,解析出随机数,也开始计算预主密钥,两个预主密钥用来后续的通信。

计算主密钥:通过预主密钥和服务器随机数、客户端随机数,计算出主密钥。

计算会话密钥:通过主密钥、服务器随机数、客户端随机数生成会话密钥。

这个最终的会话密钥包括:对称加密密钥(symmetric key)、消息认证码密钥(mac key)、初始化项量(iv key,只在必要时生成)。

客户端完成会话密钥计算后,发消息通知服务器:客户端已生成加密密钥,并切换到加密模式。

此时的服务器

服务器收到该消息后,与单向加密不同的是,会额外使用客户端的公钥来计算预主密钥,进一步计算出会话密钥。

就同样地开始计算预主密钥、主密钥、生成会话密钥。

客户端 -> 服务器: Encrypted Handshake Message

将之前的握手数据做一个摘要,通过会话密钥加密(对称加密),发送加密消息给服务器进行校验。

后续步骤与单向加密相同。

TLS 协议栈

TLS 由多种协议一起组成,是在 TCP 传输层之上的传输层安全性协议,这些组成部分包括:

  1. Handshake Protocol,握手协议,用于建立 TLS 连接。
  2. Change Cipher Spec Protocol,密钥规格变更协议,用于协商客户端与服务器的密钥处理。
  3. Application Data Protocol,应用数据协议,例如 HTTP 。
  4. Alert Protocol,警报协议,用于表示关闭信息和错误信息。
  5. Record Layer,记录层,用于日志记录。

图片

Wireshark TLS 握手实践

在完成 TCP 三次握手后,连接建立成功,开始通过 TLSv1.2 安全传输层协议对消息进行加密:

StepsourcedestinationProtocolLengthInfoRecord Layer
1182.24.42.37110.242.68.4TLSv1.2571Client HelloHandshake Protocol: Client Hello
2110.242.68.4182.24.42.37TLSv1.21414Server Hello,Handshake Protocol: Server Hello
3110.242.68.4182.24.42.37TLSv1.21215Certificate, Server Key Exchange, Server Hello DoneHandshake Protocol: Certificate Handshake Protocol: Server Key Exchange Handshake Protocol: Server Hello Done
4182.24.42.37110.242.68.4TLSv1.2105Client Key Exchange, Change Cipher Spec, Encrypted Handshake MessageHandshake Protocol: Client Key Exchange Change Cipher Spec Protocol: Change Cipher Spec Handshake Protocol: Encrypted Handshake Message
5182.24.42.37110.242.68.4TLSv1.21154Application DataApplication Data Protocol: http-over-tls // 此时已经是加密消息了
6110.242.68.4182.24.42.37TLSv1.2280New Session Ticket, Change Cipher Spec, Encrypted Handshake MessageHandshake Protocol: New Session Ticket Change Cipher Spec Protocol: Change Cipher Spec Handshake Protocol: Encrypted Handshake Message
7110.242.68.4182.24.42.37TLSv1.21262Application DataApplication Data Protocol: http-over-tls

第一次握手

Step.1 Client Hello

客户端向服务器发送请求,发送 TLS 版本,发送客户端支持的加密算法列表和一个随机数:

image-20230222172106170.png

第二次握手

Step.2 Server Hello

服务器返回消息给客户端,握手协议:在客户端提供的加密算法中选择一种进行加密后,返回服务器端随机数和选择的算法以及版本信息:

image-20230222172302947.png

Step.3 Certificate, Server Key Exchange, Server Hello Done

Certificate,服务器向客户端发送证书给客户端:

image-20230222172833211.png

Server Key Exchange,传递密钥交换算法参数信息给客户端:

image-20230222181737221.png

Server Hello Done 服务器将之前所有的握手数据做一个摘要,供服务器校验。

image-20230222181805178.png

第三次握手

Step.4 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message

Step.4,客户端回复握手消息:

Client Key Exchange,将加密算法参数信息(生成客户端公钥信息)发送给服务器:

image-20230222182727730.png

Change Cipher Spec 通知服务器切换加密模式:

image-20230222182810469.png

Encrypted Handshake Message, 生成会话密钥后通知服务器:

image-20230222183848499.png

Step.5 Application Data

此时客户端到服务器到链路已经打通,发送一条加密数据消息供服务器校验:

image-20230222193257518.png

第四次握手

Step.6 New Session Ticket, Change Cipher Spec, Encrypted Handshake Message

New Session Ticket,服务器返回新的 session ticket,通知客户端切换加密算法,并验证会话密钥后返回消息给客户端:

image-20230222193454549.png

Change Cipher Spec,通知客户端切换加密模式:

image-20230222193511048.png

Encrypted Handshake Message,服务器确认完成握手:

image-20230222193530685.png

Step.7 Application Data

服务器到客户端的链路打通,确认协议为 http-over-tls ,发送一条消息供客户端校验。

image-20230222193742764.png

Note

TLS 协议对数据进行了加密,所以这里看不到 HTTP 协议的相关信息(也就是 Application Data 中的信息),需要通过密钥解密,才能看见此次请求中 HTTP 协议的内容,下面是个解密后的例子:

img

总结

TCP 连接建立过程

  • 第一次:客户端向服务器发送 SYN 字段请求建立连接;客户端发送SYN包(seq=j)到服务器,并进入 SYN_SEND 状态,等待服务器确认;
  • 第二次:服务器收到带有 SYN 的请求,通过返回带有 SYN + ACK 的数据包(ack = syn + 1),表示同意建立连接,并发送向客户端建立连接端请求,SYN 用来测试从服务器到客户端的连接通道是否畅通,此时服务器进入 SYN_RECV 状态;
  • 第三次:客户端收到 SYN + ACK 后,回复服务器 ACK = SYN + 1,确认建立从客户端到服务器的连接;服务器收到后,双方都进入 ESTABLISHED 状态,表示连接建立成功。

TLS 连接建立过程

单向验证

第一次握手

客户端 -> 服务器: Client Hello

客户端连接到服务器请求创建安全的连接,此时的消息携带客户端支持的加密算法列表信息和一个随机数,握手开始。

第二次握手

服务器 -> 客户端: Server Hello

服务器从客户端支持的加密算法列表中选出一种,通知客户端,此时服务器发出的消息携带一个服务器生成的随机数。

服务器 -> 客户端: Certificate

服务器向客户端发送数字证书,证书包含服务器的名称、CA 机构和服务器的公钥信息。

服务器 -> 客户端: Server Key Exchange

客户端无法自行计算预主密钥,需要服务器的参与,此时服务器发送带有密钥交换算法需要的额外数据,以便客户端可以计算出预主公钥。

服务器 -> 客户端: Server Hello Done

服务器发送 Server Hello Done ,并开始等待客户端的响应。

第三次握手

客户端 -> 服务器: Client Key Exchange

此时,客户端需要验证证书的有效性,验证通过取出公钥,生成一个随机数用公钥加密,发送给服务器,因为公钥是来自于服务器的证书中,所以服务器能够使用私钥进行解密。

计算预主密钥:此时,客户端开始计算预主密钥,服务器收到消息后,解析出随机数,也开始计算预主密钥,两个预主密钥用来后续的通信。

计算主密钥:通过预主密钥和服务器随机数、客户端随机数,计算出主密钥。

计算会话密钥:通过主密钥、服务器随机数、客户端随机数生成会话密钥。

这个最终的会话密钥包括:对称加密密钥(symmetric key)、消息认证码密钥(mac key)、初始化项量(iv key,只在必要时生成)。

客户端完成会话密钥计算后,发消息通知服务器:客户端已生成加密密钥,并切换到加密模式。

服务器收到该消息后,就同样地开始计算预主密钥、主密钥、生成会话密钥。

客户端 -> 服务器: Encrypted Handshake Message

将之前的握手数据做一个摘要,通过会话密钥加密(对称加密),发送 Encrypted Handshake Message 消息给服务器进行校验。

第四次握手

服务器 -> 客户端: Change Cipher Spec

服务器发消息通知客户端:服务器已生成加密密钥,请求客户端切换加密模式。

服务器 -> 客户端: Encrypted Handshake Message

将之前的握手数据做一个摘要,通过会话密钥加密(对称加密),发送 Encrypted Handshake Message 消息给客户端进行校验。

双向验证

双向加密过程前两次握手和单向加密过程相同,不在赘述。区别是第三次握手,客户端会先发送证书给服务器,服务器会验证客户端证书的合法性。

第三次握手

客户端 -> 服务器: Client Certificate

客户端将包含客户端公钥的数字证书发送给服务器。

服务器拿到客户端证书后,进行验证,验证通过获取到了客户端的公钥。

Client Certificate 消息是客户端收到 Server Hello Done 后,可以发送的第一条消息。仅当服务器要求了一个证书的情况下,客户端才发送 Client Certificate 消息,如果没有可用的合适证书,客户端必须发送一条不包含任何证书的 Client Certificate 消息。

客户端 -> 服务器: Client Key Exchange

此时,客户端需要验证证书的有效性,验证通过取出公钥,生成一个随机数用公钥加密,发送给服务器,因为公钥是来自于服务器的证书中,所以服务器能够使用私钥进行解密。

计算预主密钥:此时,客户端开始计算预主密钥,服务器收到消息后,解析出随机数,也开始计算预主密钥,两个预主密钥用来后续的通信。

计算主密钥:通过预主密钥和服务器随机数、客户端随机数,计算出主密钥。

计算会话密钥:通过主密钥、服务器随机数、客户端随机数生成会话密钥。

这个最终的会话密钥包括:对称加密密钥(symmetric key)、消息认证码密钥(mac key)、初始化项量(iv key,只在必要时生成)。

客户端完成会话密钥计算后,发消息通知服务器:客户端已生成加密密钥,并切换到加密模式。

此时的服务器

服务器收到该消息后,与单向加密不同的是,会额外使用客户端的公钥来计算预主密钥,进一步计算出会话密钥。

就同样地开始计算预主密钥、主密钥、生成会话密钥。

客户端 -> 服务器: Encrypted Handshake Message

将之前的握手数据做一个摘要,通过会话密钥加密(对称加密),发送加密消息给服务器进行校验。

后续步骤与单向加密相同。