【每天学习一点新知识】带你读懂TCP三次握手和四次挥手

目录

前言

1、TCP传输头格式

2、三次握手

 2.1 为什么是三次握手,而不是两次或者四次?

 2.2 三次握手可以携带数据吗?

2.3 什么是半连接队列?

2.4 tcp三次握手失败,服务端会如何处理?

 2.5 ISN是什么?是固定不变的吗?ISN为何要动态随机?

3、四次挥手

 3.1 为什么握手是三次,而挥手时需要四次呢?

3.2 TIME_WAIT状态有什么作用,为什么主动关闭方没有直接进入CLOSED状态释放资源?

3.3 为什么TIME_WAIT状态需要经过2MSL才能进入CLOASE状态?

3.4 一台主机上出现大量的TIME_WAIT是什么原因?应该如何处理?

3.5 一台主机上出现大量的CLOSE_WAIT是什么原因?应该如何处理? 

4、tcp连接管理中的保活机制

5、 SYN泛洪


 

前言

前阵子也是浅浅在网上看了一些渗透测试的面经,发现基本上都会问到TCP三次握手和四次挥手,可见它已经属于一个经典面试问题了,这还能不早点准备起来?咱们趁早打牢基础,就不怕到时大脑一片空白了。如果还有问题或者遗漏,我也会努力查资料进行补充的!


1、TCP传输头格式

TCP只有一种类型的PDU,叫做TCP段,段头(也叫TCP头或传输头)的格式如下:

这里写图片描述 

(1)源端口(16位):说明源服务访问点。

(2)目的端口(16位):说明目标服务服务点。

(3)发送顺序号(32位):也叫Seq序号,本段中第一个数据字节的顺序号 。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始。

(4)确认序号(32位):也叫Ack序号,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。表示接收方期待接收的下一个数据字节的顺序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701。

(5)偏置值(4位):传输头中32位字的个数。因为传输头有任选部分,长度不固定,所以需要偏置值。它指出TCP报文的数据距离TCP报文段的起始处有多远。

(6)保留(6位):未用,保留今后使用,这个字段都置为0。
(7)紧急URG:当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据。
(8)确认ACK:仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1。
(9)推送PSH:当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1。
(10)复位RST:当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接。
(11)同步SYN:在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1。
(12)终止FIN:用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放。
(13)窗口(16位):为流控分配的信息量。

(14)校验和(16位):校验首部和数据这两部分,段中所有16位字按模2的16次方-1相加的和,然后取1的补码。

(15)紧急指针(16位):指出本报文段中的紧急数据的字节数。

(16)op选项(长度可变):定义一些其他的可选的参数。

需要注意的是:

  (1)不要将确认序号Ack与标志位中的ACK搞混了。

  (2)确认方Ack=发起方Seq+1,两端配对。 

 

2、三次握手

服务端新建套接字,绑定地址信息后开始监听,进入LISTEN状态。

客户端新建套接字绑定地址信息后调用connect,发送连接请求SYN=1,随机发送seq=x,并进入SYN_SENT状态,等待服务器的确认。此时处于半连接状态。

服务端一旦监听到连接请求,就会将连接放入内核等待队列中,并向客户端发送SYN=1和确认报文段ACK=1,并且返回seq=y,ack=x+1(表明前一个数据段已收到且没有错误),进入SYN_RECD状态。

客户端收到SYN+ACK报文后向服务端发送确认报文段ACK=1,seq=x+1,ack=y+1,并进入ESTABLISHED状态,开始读写数据。

服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,三次握手完成,就可以进行读写数据了。
 

在这里插入图片描述 举一个通俗易懂的例子:

这就相当于两个人打电话的过程,俩个人需要都确定双方的发送和接收没有问题,才会开始传输信息和数据。

 2.1 为什么是三次握手,而不是两次或者四次?

        两次不安全,四次没必要。tcp通信需要确保双方都具有数据收发的能力,得到ACK响应则认为对方具有数据收发的能力,因此双方都要发送SYN确保对方具有通信的能力。

        第一次握手是客户端发送SYN,服务端接收,服务端得出客户端的发送能力和服务端的接收能力都正常;第二次握手是服务端发送SYN+ACK,客户端接收,客户端得出客户端发送接收能力正常,服务端发送接收能力也都正常,但是此时服务器并不能确认客户端的接收能力是否正常;第三次握手客户端发送ACK,服务器接收,服务端才能得出客户端发送接收能力正常,服务端自己发送接收能力也都正常。

 2.2 三次握手可以携带数据吗?

        第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。假设第一次可以携带数据,如果有人恶意攻击服务器,每次都在第一次握手中的SYN报文放入大量数据,重复发送大量SYN报文,此时服务器会花费大量内存空间来缓冲这些报文,服务器就更容易被攻击了。

2.3 什么是半连接队列?

        服务器第一次收到客户端的SYN之后,就会处于SYN_RECD状态,此时双方还没有完全建立连接。服务器会把这种状态下的请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起来连接的就会放在全连接队列中,如果队列满了就有可能出现丢包现象。

2.4 tcp三次握手失败,服务端会如何处理?

        握手失败的原因有两种,第一种是服务端没有收到SYN,则什么都不做;第二种是服务端回复了SYN+ACK后,长时间没有收到ACK响应,则超时后就会发送RST重置连接报文,释放资源 。

 2.5 ISN是什么?是固定不变的吗?ISN为何要动态随机?

ISN全称是Initial Sequence Number,是TCP发送方的字节数据编号的原点,告诉对方我要开始发送数据的初始化序列号,也就是Seq。ISN如果是固定的,攻击者很容易猜出后序的确认号,为了安全起见,避免被第三方猜到从而发送伪造的RST报文,因此ISN是动态随机生成的。

3、四次挥手

客户端主动调用close时,向服务端发送结束报文段FIN=1,seq=u,同时进入FIN_WAIT_1状态。

服务器会收到结束报文段FIN报,服务器返回确认报文段ACK=1,seq=v,ack=u+1,并进入CLOSE_WAIT状态,此时客户端停止发送数据,如果服务端有数据要发送的话,客户端依然需要接收。此时TCP连接处于半关闭的状态。

客户端收到服务器对结束报文段的确认,就会进入到FIN_WAIT_2状态,开始等待服务器的结束报文段。

服务器端数据发送完毕后,当服务器真正调用close关闭连接时,会向客户端发送结束报文段FIN=1,seq=w,ack=u+1,此时服务器进入LAST_ACK状态,等待最后一个ACK的带来。

客户端收到服务器发来的结束报文段, 进入TIME_WAIT, 并发出送确认报文段ACK。

服务器收到了对结束报文段确认的ACK,进入CLOSED状态,断开连接。

而客户端要等待2MSL的时间,才会进入到CLOSED状态。
在这里插入图片描述

 

 3.1 为什么握手是三次,而挥手时需要四次呢?

        其实在TCP握手的时候,接收端将SYN包和ACK确认包合并到一个包中发送的,所以减少了一次包的发送。对于四次挥手,由于TCP是全双工通信,主动关闭方发送FIN请求不代表完全断开连接,只能表示主动关闭方不再发送数据了。而接收方可能还要发送数据,就不能立即关闭服务器端到客户端的数据通道,所以就不能将服务端的FIN包和对客户端的ACK包合并发送,只能先确认ACK,等服务器无需发送数据时在发送FIN包,所以四次挥手时需要四次数据包的交互。

3.2 TIME_WAIT状态有什么作用,为什么主动关闭方没有直接进入CLOSED状态释放资源?

        如果主动关闭方进入CLOSED状态后,被动关闭方发送FIN包后没有得到ACK确认,超时后就会重传一个FIN包。如果客户端没有TIME_WAIT状态而直接进入CLOSED状态释放资源,下次启动新的客户端就可能使用了与之前客户端相同的地址信息,有两个危害,第一种是这个刚启动的新的客户端绑定地址成功时,就会收到了一个重传的FIN包,对新连接就会造成影响。第二种是如果该新客户端向相同的服务端发送SYN连接请求,但是此时服务端处于LAST_ACK状态,要求收到的是ACK而不是SYN,因此就会发送RST重新建立请求。

3.3 为什么TIME_WAIT状态需要经过2MSL才能进入CLOASE状态?

        MSL指的是报文在网络中最大生存时间。在客户端发送对服务端的FIN确认包ACK后,这个ACK包有可能到达不了,服务器端如果接收不到ACK包就会重新发送FIN包。所以客户端发送ACK后需要留出2MSL时间(ACK到达服务器器+服务器发送FIN重传包,一来一回)等待确认服务器端缺失收到了ACK包。也就是说客户端如果等待2MSL时间也没收到服务器端重传的FIN包,则就可以确认服务器已经收到客户端发送的ACK包。

3.4 一台主机上出现大量的TIME_WAIT是什么原因?应该如何处理?

        TIME_WAIT是主动关闭方出现的,一台主机出现大量的TIME_WAIT证明这台主机上发起大量的主动关闭连接。常见于一些爬虫服务器。这时候我们应该调整TIME_WAIT的等待时间,或者开启套接字地址重用选项。

3.5 一台主机上出现大量的CLOSE_WAIT是什么原因?应该如何处理?

        CLOSE_WAIT是被动关闭方收到FIN请求进行回复之后的状态,等待上层程序进一步处理,若出现大量CLOSE_WAIT,有可能是被动关闭方主机程序中忘了最后一步断开连接后调用close释放资源。这是一个 BUG,只需要加上对应的 close 即可解决问题。

 

4、tcp连接管理中的保活机制

        tcp通信中,若两端长时间没有数据往来,则这时候每隔一段时间,服务端会向客户端发送一个保活探测数据报,要求客户端进行回复。若连续多次没有收到响应,就认为连接已经断开。长时间默认为7200s,每隔一段时间默认为75s,连续多次无响应默认为9次。这些数据都可以在套接字中修改,接口:Setsockopt

5、 SYN泛洪

SYN泛洪具体发生在三次握手过程中

·攻击者发送TCP的SYN,服务器返回ACK后,该攻击者就不对其进行确认,那么这个TCP连接处于挂起状态,所谓的半连接状态。
·服务器收不到再确认的话,还会重复发送ACK给攻击者,这样就更加浪费服务器资源。
·攻击者如果发送非常大量的这种TCP连接,由于每一个都无法完成三次握手,所以服务器上这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机,就无法为正常用户提供服务。

SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:

  #netstat -nap | grep SYN_RECV 

如何防御SYN泛洪

其实最常用的一个手段就是优化主机系统设置。比如降低SYN timeout时间,使得主机尽快释放半连接的占用或者采用SYN cookie设置,如果短时间内收到了某个IP的重复SYN请求,我们就认为受到了攻击。我们合理的采用防火墙设置等外部网络也可以进行拦截。

参考文章:

网络 卧槽!牛皮了,面试官居然把TCP三次握手四次挥手问的这么详细_WhiteShirtI的博客-CSDN博客一、为什么握手是三次,而不是两次或者四次?答:两次不安全,四次没必要。tcp通信需要确保双方都具有数据收发的能力,因此双方都要发送SYN确保对方具有通信的能力二、为什么挥手是四次而不是三次?答:发送FIN包只能表示对方不再发送数据了,不代表对方不再接收数据,因此被动关闭方进行ACK回复之后有可能还会继续发送数据,等到不再发送数据了才会发送下一个FIN包,因此FIN包和ACK包是分开的...https://blog.csdn.net/qq_44443986/article/details/115966274?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166607490716781432911907%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166607490716781432911907&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-115966274-null-null.142^v58^new_blog_pos_by_title,201^v3^add_ask&utm_term=%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E5%92%8C%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B&spm=1018.2226.3001.4187

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RexHarrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值