【计网】1、TCP三次握手与四次挥手详解

一、TCP简介及报文格式

1、简介

TCP提供面向连接、可靠的字节流服务。

2、报文格式

【计网】1、TCP三次握手与四次挥手详解

重点字段

  1. 序号:Seq序号,32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
  2. 确认序号:ACK序号,32位,只有ACK标志位为1时,确认序号字段才有效,Ack = Seq + 1。
  3. 标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等。
标志位 具体含义
URG 紧急指针(urgent pointer)有效
ACK 确认序号有效
PSH 接收方应尽快将报文交给应用层
RST 重置连接
SYN 发起一个新连接
FIN 释放一个连接
  • 注意
  • (a)不要将确认序号Ack与标志位ACK搞混;
  • (b)确认方Ack = 发起方Req + 1,两端配对。

二、三次握手(Three-way Handshake)

1、含义

建立TCP连接时,客户端和服务器总共发送3个包。

2、目的

连接服务器指定窗口,建立TCP连接,并同步连接双方序列号和确认号并交换。TCP窗口大小信息在socket编程中,客户端执行connect()时,将触发三次握手。

  • 注意:下图要达到熟练默写程度。
    【计网】1、TCP三次握手与四次挥手详解
    【计网】1、TCP三次握手与四次挥手详解

3、过程

  • 1st 握手 - SYN 报文:SYN=1,seq=x
客户端发送一个TCP的SYN标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序列号X,保存至包头的序列号(Sequence Number)字段里。

【计网】1、TCP三次握手与四次挥手详解

  • 2nd 握手 - SYNACK 报文:SYN=1, ACK=1, seq=y, ACKnum=x+1
服务器发回确认包(ACK)应答,即SYN标志位均为1,同时将确认序号(Acknowledgment Number)设置为客户的ISN+1,即x+1.

【计网】1、TCP三次握手与四次挥手详解

  • 3rd 握手 - ACK 报文:ACK=1,ACKnum=y+1
客户端再次发送确认包(ACK),SYN标志位为0,ACK标志位为1,并把服务器发来ACK序号字段+1,放在确定字段中发送给对方,并在数据段放写的ISN+1.

【计网】1、TCP三次握手与四次挥手详解

4、SYN攻击

在三次握手过程中,服务器发送SYN-ACK之后,收到客户端ACK之前的TCP连接称为半连接half-open connect)。此时服务器处于SYN-RECV。当收到ACK后,服务器转入ESTABLISHED状态。

SYN攻击就是攻击客户端,在短时间内伪造大量不存在的IP地址,向服务器不断发送SYN包,服务器回复确认包,并等待客户确认。 由于源地址不存在,服务器需要不断重发直至超时,这些伪造SYN包将长时间占用未连接队列,正常SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪

SYN攻击是典型的DDOS攻击,检测SYN攻击非常方便,当你在服务器上看到大量半连接状态时,特别是IP地址是随机的,基本可用断定这是一次SYN攻击,在Linux上可用如下命令检测是否被SYN攻击:

netstat -n -p TCP | grep SYN_RECV

一般较新的TCP/IP协议都会对这一过程进行修正来防范SYN攻击,修改TCP协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等,但不能完全防范。

追问1:为什么两次握手不行?

三次握手是为了让双方验证各自接收能力和发送能力。

  • 1st:A发送SYN给B,B接收到。这里B能确认A的发送能力和B的接收能力
  • 2nd:B发送SYNACK给A,A收到。这里A能确认A的接收能力和B的发送能力。此外,A收到SYNACK,说明前面A的SYN成功到达B,也能确认A自己的发送能力和B的接收能力。至此,A已经确认双方各自发送能力和接收能力OK,因此转为ESTABLISHED状态。
  • 3rd:A发送ACK到B,B接收。这里B能确认A的发送能力和B的接收能力。由于B能收到ACK,说明前面发送的SYNACK已经被接受了,说明A的接收能力和B的发送能力正常。

若使用两次握手,就不能确认上述四种能力,可能有问题。

  • 假定A发的SYN报文没消失,而是在某网络节点长时间滞留了,以至于到连接释放后的某个时间才到达B。

  • 本来这是一个早已失效的报文段,但B收到此失效连接请求报文段后,却误以为是A又发出一次新的连接请求,于是A就发出确认报文段,同时建立连接

  • 由于现在A并没有发出建立连接请求,因此不理睬B的SYNACK报文,也不会向B发送数据,但B却以为新连接已经建立,并一直等待A发来的数据,B的许多资源被白白浪费。

追问2:三次握手过程中可以携带数据吗?

前两次不行,第三次可以携带。

追问3:为什么?

假如第一次可以,如果有人恶意攻击服务器,那他在第一次SYN 报文中放入大量数据。因为攻击者根本不理会服务器的接收、发送能力是否正常,只是疯狂重复发 SYN 报文,这会让服务器花费很多内存与时间来接收这些报文。
也就是说,第一次握手不能放数据,1个简单原因服务器会更容易受到攻击。而对于第三次,此时客户端处于 ESTABLISHED 状态,已经建立起连接,知道服务器接收与发送能力正常,所以携带数据也没毛病。

追问4:ISN(Initial Sequence Number)是固定的吗?

不固定,client_isn是随机生成的,而server_isn则需要根据SYN报文中的源、IP和端口,加上服务器本身密码数进行相同散列得到,显然也不固定。

追问4:第三次握手失败了怎么办?

  1. 在第2次握手中,serverclient发送SYN+ACK报文后,就会启动一个定时器,等待client返回的ACK报文。
  2. 如果第三次失败,clientserver返回了ACK报文server并不能收到这个ACK报文。那server就会启动超时重传机制,超过规定时间会重新发起第2次握手,向client发送SYNACK。重传次数默认5次。
  3. 如果到重传指定次数,仍未收到ACK应答,那一段时间后server会关闭这个连接。但client认为这个连接已建立,如果它向server写数据,server将回应RST包、强制关闭TCP连接,以防止SYN攻击

追问5:什么是SYN攻击?如何防范?

在三次握手过程中,服务器发送SYN-ACK之后,收到客户端ACK之前的TCP连接称为半连接half-open connect)。此时服务器处于SYN-RECV。当收到ACK后,服务器转入ESTABLISHED状态。

SYN攻击就是攻击客户端,在短时间内伪造大量不存在的IP地址,向服务器不断发送SYN包,服务器回复确认包,并等待客户确认。 由于源地址不存在,服务器需要不断重发直至超时,这些伪造SYN包将长时间占用未连接队列,正常SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪

SYN攻击是一种典型的DoSe/DDoS攻击。

追问6:如何检测SYN攻击?

检测SYN攻击非常方便,当你在服务器上看到大量半连接状态时,特别是IP地址是随机的,基本可以断定这是一次SYN攻击,在Linux/Unix可用netstat命令检测。

追问7:如何防御SYN攻击?

SYN攻击不能完全被阻止,除非重新设计TCP协议。能做的就是就是尽可能减轻SYN攻击危害,常见防御方法有:缩短超时(SYN Timeout)时间、增大最大半连接数、过滤网关防护、SYN cookies技术

追问8:服务器为什么使用特殊的初始序号server_isn?

服务器使用特定初始序列号server_isn(从源和目的地IP和端口的散列中获取) 可以用来抵御SYN洪水攻击

三、 四次挥手(four-way handshake)

1、含义

TCP连接拆除需要发送四个包,因此称为四次挥手.

Client或Server均可主动发起。在socket编程中,执行close()操作即可产生挥手操作。

2、过程

【计网】1、TCP三次握手与四次挥手详解
【计网】1、TCP三次握手与四次挥手详解

  • 1st: 先由ClientServer发送 1 个FIN报文,用来关闭Client到Server的数据传送;
  • 2nd: 当Server收到Client的FIN时,会回复一个ACK,其中ACK值=FIN+SEQ
  • 3rd: 然后Server向Client发送一个FIN,用来关闭Server到Client的数据传送;
  • 4th: 当Client收到Server的FIN时,回复 1 个ACK给Server,其中ACK值=FIN+SEQ

【计网】1、TCP三次握手与四次挥手详解

上面是一方主动关闭,另一方被动关闭情况,实际还会出现同时发起主动关闭的情况,具体如下:
【计网】1、TCP三次握手与四次挥手详解

追问1:为什么建立连接是三次握手,而关闭连接却是四次挥手呢?(*2)

关键在中间两步:

  • 这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
  • 而关闭连接时,收到对方的FIN报文时,仅表示对方不再发送,但还能接收数据,己方也未必全部发送完毕
    所以只能先回复一个ACK报文,告诉客户端“你发的FIN报文已收到”。等服务器所有报文发送/接收完,才能发送FIN报文。因此ACK和SYN分开发送,要四次握手。

追问1:为什么会有第二次、第三次、第四次挥手?(*2)

确保数据能完整传输。

  1. 当服务器收到客户端的FIN报文通知时,它仅仅表示客户端没有数据再发送给服务器了。
  2. 服务器未将所有数据都发给了主动方,所以服务器不会马上关闭SOCKET,可能还需要发完数据后,再发FIN给主动方,表示同意关闭连接。

所以这里ACK报文和FIN报文大多数情况下是分开发送。

追问2:四次挥手释放连接时,等待2MSL的意义?(*2)

  1. 保证客户端发送的最后1个ACK报文能到达服务器。假设网络不可靠,ACK报文丢失。如果服务端发出FIN报文后没收到ACK报文,就会重发FIN报文(收到不再发),此时处于TIME-WAIT的客户端就会重发ACK报文。
    当然,客户端也不能无限等待这个FIN报文,需要设置一个定时器,2MSL正好,因为1个最大发送和1个回复最长时间没收到ACK,可以推断ACK报文已经被服务器接收,所以结束TCP连接。

  2. 防止已失效的连接请求报文段出现在新连接中。客户端发完最后1个ACK报文后,再经过2MSL时间,就可以使网络不通畅产生的滞留报文段失效,这样下一个新连接中就不会出现旧的连接请求报文。

补充:

MSL—Maximum Segment Lifetime,指报文在网络中最大存活时间,2MSL就是1个发送和1个回复所需最大时间。

追问3:为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSE状态?

理论上,四个报文都发送完毕,就可以直接进入CLOSE状态。但网络如果不可靠,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文

追问4:四次挥手过程中服务端的哪几种状态,哪几种包?

……

四、参考

1、TCP的三次握手四次挥手
2、阿里面试: HTTP、HTTPS、TCP/IP、三次握手四次挥手过程?(附全网最具深度讲解)
3、(转)TCP为什么需要3次握手与4次挥手
4、TCP三次握手/四次挥手 及 状态变迁图
5、面试官,不要再问我三次握手和四次挥手
6、“三次握手,四次挥手”你真的懂吗?
7、TCP为什么需要第三次握手?第三次握手失败了会怎么样?

上一篇:TCP三次握手


下一篇:TCP