TCP 三次握手和四次挥手

2020.10.10 15:30

TCP 全称是传输控制协议(Transmission Control Protocol),是一种面向连接的、可靠的、基于字节流的传输层通信协议。

连接是指各种设备、线路,或网络中进行通信的两个应用程序为了相互传递消息而专有的、虚拟的通信线路,也叫做虚拟电路。一旦建立了连接,进行通信的应用程序只使用这个虚拟的通信线路发送和接收数据,就可以保障信息的传输。应用程序可以不用顾虑提供尽职服务的 IP 网络上可能发生的各种问题,依然可以转发数据。TCP 则负责控制连接的建立、断开、保持等管理工作。

TCP 的建立连接就是靠三次握手,断开连接就是靠的四次挥手。

TCP 首部

先简单看一下 TCP 首部格式:

TCP 首部格式

本文主要讲一下和三次握手、四次挥手有关的字段。

标志位

标志位就是窗口字段前面的几个字段,每个字段只占 1bit。

  1. SYN(synchronous): 发送/同步标志,用来建立连接,和 ACK 标志位搭配使用。A 请求与 B 建立连接时,SYN=1,ACK=0;B 确认与 A 建立连接时,SYN=1,ACK=1
  2. ACK(acknowledgement):确认标志,表示确认收到请求
  3. PSH(push) :表示推送操作,就是指数据包到达接收端以后,不对其进行队列处理,而是尽可能的将数据交给应用程序处理
  4. FIN(finish):结束标志,表示关闭一个 TCP 连接
  5. RST(reset):重置复位标志,用于复位对应的 TCP 连接
  6. URG(urgent):紧急标志,用于保证 TCP 连接不被中断,并且督促中间层设备尽快处理

序列号(Sequence Number)和确认号(Acknowledge Number)

TCP 使用序列号来记录发送数据包的顺序,TCP 传送一个数据包发送数据包时,需要带上此次报文段的序列号,传送一个数据包后,只有在指定时间里收到这个包的确认信息,才会将其从队列中删除,否则会重新发送该数据包。TCP 接收到对方的数据包时,需要回传一个确认应答的报文,该报文首部 ACK 标志位置 1,并且确认号为下一次需要的报文段的序列号。

三次握手

三次握手过程:

三次握手过程

文字描述:

为什么需要三次握手?

确认双方都有正常的发送能力和接收能力:

确保服务器安全:如果只握手 2 次,那么意味着只要客户端发起一次请求即可以在服务打开一个连接,打开连接是需要消耗资源的,攻击者完全可以修改 IP 报文头部中的发送方 IP 地址,然后不停向服务端发起 TCP 连接请求(这也是 SYN 洪泛攻击 的原理)

如何检测和防范 SYN 洪泛攻击

检测:当在服务器上看到大量的半连接状态时,特别是源 IP 地址是随机的,基本上可以断定这是一次 SYN 攻击。

防范:使用 SYN cookie,原理是将客户端的目的 IP 地址、端口号、序列号、一个密钥数用散列函数计算,将其作为第二次握手的序列号发送给客户端,此时服务端不需要记录该 cookie 和客户端的任何状态信息,如果客户端合法,将正常回传第三次握手,然后服务端再次计算SYN cookie + 1,和确认号相同则打开连接。

四次挥手

四次挥手过程:

四次挥手过程

文字描述:

以下描述不讨论序号和确认号,因为序号和确认号的规则比较简单。并且不讨论 ACK,因为 ACK 在连接建立之后都为 1。

为什么要四次挥手?三次不行吗?

客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。

TIME_WAIT 为什么要等 2MSL

MSL 即报文最大生存时间(Maximum Segment Life),主要有两个原因:

  1. 确保最后一个确认报文能够到达

    等待 2MSL 时间,即「FIN 报文 1MSL 传输 + ACK 报文 1MSL 超时」。如果 B 没收到 A 发送来的 ACK 报文,那么就会重新发送 FIN 报文,A 等待一段时间就是为了处理这种情况的发生。

  2. 防止已失效的连接请求报文段出现在之后的连接中

    客户端在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以保证本连接持续的时间内产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。或者即使收到这些过时的报文,也可以不处理它。

参考资料