TCP三次握手、四次挥手以及SSL的四次握手过程你都弄清楚了吗?

590 阅读8分钟

TCP连接:三次握手

简单理解

简单的理解就是:

scss
复制代码
客户端:hello,你好,你是server吗?
服务端:hello,你好,我是server,你是client吗
客户端:yes,我是client
开始数据传输.....
——————————————————————————————————————————
客户端(男人):我喜欢你,咱俩处对象吧
服务端(女人):我也喜欢你,我答应你
客户端(男人):太棒了,我们现在去看电影吧
开始数据传输.....

然后双方就正确建立连接,开始传输数据

详细分析

image-20230803012906562.png

  • 第一次握手:客户端发送一个带 SYN=1,Seq=x 的数据包到服务器端口

    • 第一次握手,由浏览器发起,告诉服务器我要发送请求了
    • SYN(synchronous):请求建立连接
    • seq(sequence):随机序列号
    • 请注意TCP规定SYN被设置为1的报文段不能携带数据但要消耗掉一个序号。
  • 第二次握手:服务器发回一个带 SYN=1, ACK=1, seq=y, ack= x+1 的响应包以示传达确认信息

    • 第二次握手,由服务器发起,告诉客户端我准备接受了,你赶紧发送吧
    • ACK(acknowledgement):确认,是一个确定字符
    • ack:ack=上一次的seq+1,作用是接受上一次远端主机传来的seq,加一然后再传给客户端,提示客户端已经成功接收上一次所有数据
    • 请注意这个报文段不能携带数据,因为它是SYN被设置为一的报文段但同样要消耗掉一个序号
  • 第三次握手:客户端再回传一个带 ACK,seq = x + 1, ack = y + 1 的数据包,代表“握手结束”

    • 第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧
    • 确认报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下所发送的下一个数据报文段的序号仍是x + 1

然后双方就正确建立连接,开始传输数据

SSL/TLS四次握手

HTTPS 建立连接的过程,先进行 TCP 三次握手,再进行 TLS 四次握手(仅对https)

因为 HTTPS 都是基于 TCP 传输协议实现的,得先建立完可靠的 TCP 连接才能做 TLS 握手的事情。

第一次握手:客户端发出请求Client Hello

  • 首先,客户端先向服务器发出加密通信的请求,这被叫做clienthello请求。

  • 在这一步,客户端主要向服务器提供以下信息:

    • 支持的协议版本,比如TLS1.0版本
    • 支持的加密方法,比如RSA公钥加密
    • 一个客户端生成的随机数(client random) , 稍后用于生成对话密钥(session key)

第二次握手:服务器回应Server Hello

  • 服务器收到客户端请求后,向客户端发出回应,这叫做serverhello

  • 这一步服务器主要干三件事:

    • 确认使用的加密通信协议版本,比如TLS1.00版本。如果游览器与服务器支持的版本不一致,服务器关闭加密通信
    • 确认使用的加密方法(客户端所支持),比如RSA公钥加密
    • 将服务器证书、非对称加密的公钥,以及一个随机数(Server random)发送给客户端游览器

客户端验证证书

客户端收到服务器回应以后,首先验证服务器证书,验证手段就是执行如下三种检查:

  • 检查证书是否已过期;
  • 检查证书中的域名与实际域名是否一致
  • 检查证书是否是可信机构颁布的

如果,上述过程中有任何一个环节发现问题,那么浏览器就会向访问者显示一个警告,由其选择是否还要继续通信。如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串新的随机数(Premaster secret )

第三次握手:客户端回应

此时,浏览器会根据前三次握手中的三个随机数:

  • Client random
  • Server random
  • Premaster secret

通过一定的算法来生成 “会话密钥” (Session Key) ,这个会话密钥就是接下来双方进行对称加密解密使用的密钥!

第四次握手:服务端回应

服务端收到客户端的回复,利用已知的加密解密方式进行解密,服务器收到客户端的第三个随机数( Premaster secret) 之后,使用同样的算法计算出 “会话密钥” (Session Key)。

至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用 “会话密钥” 加密内容。(非对称加密解密将不再使用,接下来完全由对称加密接手了,因为密钥已经安全的传送给了通信的双方)

总结

  1. 客户端请求建立SSL链接,并向服务发送一个随机数–Client random客户端支持的加密方法,比如RSA公钥加密,此时是明文传输

  2. 服务端回复一种客户端支持的加密方法一个随机数–Server random、授信的服务器证书非对称加密的公钥

  3. 客户端收到服务端的回复后利用服务端的公钥,加上新的随机数–Premaster secret 通过服务端下发的公钥及加密方法进行加密,发送给服务器

  4. 服务端收到客户端的回复,利用已知的加解密方式进行解密,同时利用Client random、Server random和Premaster secret通过一定的算法生成HTTP链接数据传输的对称加密key – session key

断开连接:TCP 四次挥手

在渲染完成后,浏览器可能会继续加载页面中的其他资源,如异步加载的内容或者通过JavaScript生成的动态内容。

而在此过程中,如果没有其他资源需要加载,浏览器将与服务器之间的TCP连接断开。

简单理解

复制代码
主动方:我已经关闭了向你那边的主动通道了,这是我最后一次给你发消息了,之后只能被动接收你的信息了
被动方:收到你通道关闭的信息
被动方:那我也告诉你,我这边向你的主动通道也关闭了
主动方:最后收到你关闭的信息,OK结束
断开连接,结束通讯
————————————————————————————————————————————————————————————————————————————
提出分手的可能是男生(客户端),也可能是女生(服务端)
主动方:分手吧,我不喜欢你了!
被动方:行,你等我忙完手上的工作我在收拾你!
被动方:我忙完了,分手就分手!
主动方:好,好聚好散,拜拜!
断开连接,结束通讯

详细分析

由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

任何一方都可以在数据传送结束后发出连接释放的通知,所有主动发起关闭请求可以是客户端,也可以是服务端

这里我们假设是由客户端先主动发起关闭请求

image-20230803014026984.png

  • 第一次挥手:TCP客户进程会发送TCP连接释放报文段,并进入终止等待1(FIN-WAIT-1)状态。

    • FIN:终止位,表示断开TCP连接
    • TCP规定终止位FIN等于1的报文段即使不携带数据,也要消耗掉一个序号
  • 第二次挥手:TCP服务器进程收到TCP连接释放报文段后,会发送一个普通的TCP确认报文段并进入关闭等待(CLOSE-WAIT)状态。

    • 序号seq字段的值设置为v,与之前收到的TCP连接释放报文段中的确认号匹配
    • TCP客户进程收到TCP确认报文段后就进入终止等待2(FIN-WAIT-2)状态,等待TCP服务器进程发出的TCP连接释放报文段
    • 这时的TCP连接属于半关闭状态,也就是TCP客户进程已经没有数据要发送了。但如果TCP服务器进程还有数据要发送,TCP客户进程仍要接收,也就是说从TCP服务器进程到TCP客户进程这个方向的连接并未关闭,这个状态可能要持续一段时间。
  • 第三次挥手:TCP服务器进程发送TCP连接释放报文段

    • 假定序号seq字段的值为w,这是因为在半关闭状态下,TCP服务器进程可能又发送了一些数据。
    • 确认号ack字段的值为u+1,这是对之前收到的TCP连接释放报文段的重复确认。
  • 第四次挥手:TCP服务器进程收到确定报文段后就进入关闭状态,而TCP客户进程还要经过2MSL后才能进入关闭状态。

之后断开连接,结束通讯

写在最后

作者:前端实习生鲸落

github地址:github.com/xiaojunnany…

个人博客:鲸落 (xiaojunnan.cn)