当前位置:职场发展 > 解密TCP断线:四波秘密与数据传输安全

解密TCP断线:四波秘密与数据传输安全

  • 发布:2023-10-03 04:01

TCP断线

当今的数字时代,互联网已经成为人们生活中不可或缺的一部分。在互联网的基础上,TCP协议起着关键的作用,负责数据在网络中的可靠传输。在建立TCP连接的过程中,我们已经了解了三次握手的流程和原理。然而,连接的建立只是TCP协议的一部分。同样重要的是连接的断开过程。本文将重点介绍TCP连接的断开过程,包括四次挥手的过程和状态变化,以及为什么需要四次挥手以及为什么需要TIME_WAIT状态。通过深入理解TCP连接断开的过程,可以更好的理解网络通信的原理

TCP四波流程及状态变化

TCP 断开需要四次挥手。双方都有主动断开连接的能力。一旦断开连接,主机中的各种“资源”就会被释放。接下来我们就详细讲解一下TCP的四次挥手的原理和过程!

  • 当客户端打算关闭连接时,会发送一条TCP头中FIN标志位设置为1的报文,即FIN报文。随后,客户端进入FIN_WAIT_1状态。
  • 服务器收到消息后,会向客户端发送ACK响应消息,并进入CLOSED_WAIT状态。
  • 客户端收到服务器端的ACK响应消息后,进入FIN_WAIT_2状态。
  • 服务器等待处理数据后,也会向客户端发送FIN报文,然后进入LAST_ACK状态。
  • 客户端收到服务器端的FIN报文后,会回复ACK响应报文,并进入TIME_WAIT状态。
  • 服务器一旦收到ACK响应消息,就进入CLOSE状态,从而服务器完成连接的关闭。
  • 一段时间的2MSL后,客户端自动进入CLOSE状态,这样客户端也完成了连接的关闭。

在TCP连接的断开过程中,我们可以观察到每个方向都需要发送FIN报文并接收ACK报文,所以这个过程通常被称为四次挥手。

需要注意的一点是,只有主动发起关闭连接的一方才会进入TIME_WAIT状态。这是因为关闭连接后,客户端需要等待一段时间(通常是最大报文段生存时间的两倍,即2MSL),以确保服务器收到自己的ACK响应消息。这样做的目的是为了防止关闭的连接上出现延迟段,保证连接的可靠关闭。服务器不需要等待这段时间,因此不存在TIME_WAIT状态。

为什么要挥手四次?

为了更好地理解为什么需要四次挥手,我们回顾一下双方发送FIN数据包的过程。这样我们就可以理解为什么需要四波了。

当客户端在关闭连接时向服务器发送FIN,只是表示客户端不再发送数据,但仍然可以接收数据。

服务器收到客户端的FIN报文后,首先会回复ACK响应报文。但是,服务器可能仍然有数据需要处理和发送,因此它会等到不再发送数据时才向客户端发送FIN消息,以表示同意现在关闭连接。

通过上面的过程我们可以看到,服务器通常需要等待数据发送和处理完成,所以服务器的ACK和FIN通常是分开发送的,这就导致比三次握手多了一挥手。

为什么TIME_WAIT的等待时间是2MSL?

MSL是Maximum Segment Lifetime,即消息的最大生存时间。表示该消息在网络中存在的最长时间。过了这个时间,数据包将被丢弃。因为TCP协议是基于IP协议的,所以IP报头有一个TTL字段,它表示数据报可以通过的最大路由数。每经过一个路由器,TTL值就减1。当TTL值为0时,数据报将被丢弃,并发送ICMP报文通知源主机。

MSL和TTL的区别在于单位。 MSL的单位是时间,TTL是经过的路由跳数。因此,为了保证数据包自然死亡,MSL应该大于或等于TTL消耗达到0的时间。

TIME_WAIT 等待2倍MSL的合理解释是:网络中可能有来自发送方的数据包。当接收方处理这些数据包时,它会向对方发送响应,因此往返时间延长了 2 倍。是为了保证最后一个ACK被服务器收到。如果没有收到,必须给服务器足够的时间来重传第三波FIN。

例如,被动关闭方如果没有收到最后一条断开连接的ACK报文,就会触发超时,重新发送FIN报文。对方收到FIN报文后,会重新发送ACK给被动关闭方,因此往返需要2个MSL。

2MSL时间从客户端收到FIN后发送ACK开始计算。如果在TIME_WAIT时间内,由于客户端的ACK没有传送给服务器,而客户端又收到了服务器重新发送的FIN报文,那么2MSL的时间就会重新计时。

在Linux系统中,默认的2MSL时间为60秒,即1个MSL为30秒。 Linux系统处于TIME_WAIT状态的时间固定为60秒。
在Linux内核代码中,其定义名为TCP_TIMEWAIT_LEN:

#define TCP_TIMEWAIT_LEN (60*HZ) /* 等待多长时间销毁TIME-WAIT
                                    状态,约60秒*/

如果要修改TIME_WAIT的长度,只能修改Linux内核代码中TCP_TIMEWAIT_LEN的值,并重新编译Linux内核。

为什么需要TIME_WAIT状态?

TIME_WAIT 状态的存在是为了确保网络连接的可靠关闭。只有主动发起关闭连接的一方(即主动关闭方)才会有TIME_WAIT状态。

需要 TIME_WAIT 状态有两个主要原因:

  • 防止接收到具有相同“四元组”的“旧”数据包:在网络通信中,每个TCP连接都由四个源组成:源IP地址、源端口号、目的IP地址、目的端口号。元素的唯一标识符称为“quad”。当一方主动关闭连接并进入TIME_WAIT状态时,在一段时间内仍能收到对方发送来的延迟数据包。这是因为网络中数据包的传输可能存在延迟。如果没有TIME_WAIT状态,这些延迟的数据包可能会被错误地传递到新的连接,导致数据混乱。通过维持 TIME_WAIT 状态,可以防止旧数据包干扰新连接。
  • 确保“被动关闭连接”的一方能够正确关闭:当连接的被动关闭方收到主动关闭方的FIN报文(表示连接已关闭)时,需要发送一个向主动关闭方发送确认 ACK 消息。完成连接关闭。然而,网络不可靠,ACK消息在传输过程中可能会丢失。如果主动关闭方在收到ACK消息之前关闭连接,被动关闭方将无法正常完成连接关闭。 TIME_WAIT状态的存在保证了被动关闭方能够收到最后的ACK消息,从而帮助其正常关闭连接。

防止来自旧连接的数据包

假设TIME-WAIT状态没有合适的等待时间或者时间太短,延迟数据包到达后可能会出现严重问题。

例如,关闭连接之前服务器发送的SEQ = 301消息被网络延迟了。然后重用同一端口的 TCP 连接,延迟的 SEQ=301 到达客户端。这种情况下,客户端可能会正常收到过期消息,从而导致数据损坏等严重问题。

为了解决这个问题,TCP设计了一种机制,即在2MSL之后,足以将连接两个方向的数据包都丢弃。这样,原来连接的数据包在网络中自然消失,重新出现的数据包必然是新建立的连接产生的,从而避免了数据混乱等问题。

确保连接正确关闭

TIME-WAIT状态的作用是等待足够的时间,保证被动关闭方能够收到最后的ACK消息,帮助其正常关闭。

假设TIME-WAIT没有合适的等待时间或者时间太短,断开连接可能会导致以下问题:

例如,如果客户端发送的最后一个ACK消息在四次挥手期间在网络中丢失,并且客户端的TIME-WAIT状态太短或未设置,则客户端将直接进入CLOSE状态。服务器将始终处于 LAST-ACK 状态。在这种情况下,连接无法正常关闭。

另外,当客户端发起SYN请求建立连接时,如果服务器向客户端发送RST报文,则会终止连接建立过程。

如果TIME-WAIT等待时间足够长,会出现以下两种情况:

  • 服务器正常收到四次挥手的最后一个ACK消息,从而正常关闭连接。
  • 当服务器没有收到四次挥手的最后一个ACK报文时,会重新发送FIN关闭连接报文,并等待新的ACK报文。

因此,客户端在TIME-WAIT状态等待2MSL后,可以保证双方的连接能够正常关闭。

这里再科普一下相关知识。大多数三向握手和四向挥手都没有提到。为什么第三次挥手时会发送ack?直接送鳍不是很正常吗?

在 TCP 协议中,除了初始连接的第一个 SYN 数据包中 ACK 字段设置为 0 外,所有其他 TCP 数据包都会将 ACK 字段设置为 1。该 ACK 字段的作用是确认接收方已成功接收数据。如果有数据需要发送,TCP协议会在发送数据的同时发送一个ACK来确认对方的数据。如果数据在传输过程中丢失,TCP会重新传输数据。 TCP 报头中的 ACK 字段是必需的。如果这32位为空,则只需使除初始报文段之外的所有报文段的ACK字段都有效即可。

总结

TCP连接的断开需要通过四次挥手的过程来完成。双方都有主动断开连接的能力,断开连接后,各种资源都会被释放。四次挥手的过程涉及双方发送FIN和ACK报文的交互,以保证数据的可靠传输和连接的正确关闭。其中,主动关闭的一方会进入TIME_WAIT状态,等待一段时间,以确保对方收到了最终的ACK消息。 TIME_WAIT状态的存在是为了防止旧连接的数据包干扰新连接,并保证被动关闭方能够正常关闭连接。需要四次挥手的原因是为了确保数据的完整传输和连接的可靠关闭。 TIME_WAIT状态等待2倍MSL,以确保网络中的所有数据包都消失。

相关文章