首页 > 编程知识 正文

为什么三次握手和四次挥手,tcp协议三次握手四次挥手

时间:2023-05-04 04:57:40 阅读:33452 作者:2318

前言

TCP是一种面向连接的协议。 连接用于发送TCP消息,TCP连接的发送3个阶段分别为连接建立、数据传输、连接释放。

TCP连接的建立采用客户端-服务器模型。 积极启动连接建立的应用进程称为客户机,被动等待连接建立的应用进程称为服务器。

1建立TCP连接——次握手

TCP建立连接的过程称为握手。 握手要求在客户端和服务器之间交换三个TCP消息片段。 三次握手的过程如下图所示。

)第一握手)客户端TCP首先向服务器侧TCP发送连接请求消息段,其中标头中的同步位SYN=1,同时选择一个初始序号(随机序号) seq=x。 此时,客户端进程处于同步状态

在TCP中,规定的SYN段(即SYN=1的段)不能携带数据,但是消耗一个序列号。

如上所述,同步SYN控制位是建立连接时的同步序列号。 如果SYN=1,ACK=0,则表示这是连接请求消息段。 由于SYN=1,连接请求消息也被称为SYN段。

)第二次握手)服务器接收到SYN段,同意连接后,服务器为此TCP连接分配缓存和变量,并向客户端返回确认段,在确认段中同步位SYN=1和确认位ACK=1, 此时,TCP服务器进程将进入同步接收(SYN-RCVD )状态。

该确认消息段也不能携带数据,同样需要消耗序列号。

如上所述,其中ack=x 1指示服务器成功接收到客户端进程的序列号为x的消息段,服务器预期客户端进程的下一个消息段的第一个字节数据的序列号x 1。 此确认消息段也称为同步消息段。

)第三次握手)客户端进程从服务器进程接收到确认消息后,客户端为此TCP连接分配缓存和变量,并向服务器端分配ACK=1、确认号seq=y 1、自己的编号x 1 发送ACK消息段后,客户端将进入已建立TCP连接的“已建立”状态。

服务器收到客户端的确认后,将进入ESTABLISHED状态。

TCP标准规定,ACK段可以携带数据,但是如果不携带数据则不消耗序列号,在这种情况下,下一个数据消息段的序列号保持为seq=x 1。

完成上述三次握手后,客户端服务器便可以发送相互包含数据的消息段。

23次握手的几个问题

2.1为什么在三次握手过程中初始化序列号,为什么要使用随机序列号,不能使用固定的序列号?

这样选择序号的目的是为了防止一个连接侧错误地解释它,因为网络路由的TCP分组可能存在延迟到达和排序混乱的问题。

下图显示了使用固定序列号建立连接时出现的问题。

从上图可以看出,如果客户端-服务器都使用固定的序列号来建立连接,并且在三次握手之后建立TCP连接,则在传输数据时出现网络问题而数据未到达,并且所述段停留在网络上

然后,如果由于客户机主机故障等原因,该TCP连接被释放,在客户机主机恢复后使用同一序列号重新建立连接,并且在随后的某个时间段内,以前有网络问题的段到达服务器端,则服务器将

由于一个TCP连接由四组端点表示,包括两个IP地址和两个端口号,因此同一连接可能会出现不同的实例。 如果一条消息以长延迟关闭,然后以相同的四对重新打开,则延迟的消息段被认为有效地重新访问了新连接的数据流,这可能会打乱数据的顺序。

为了避免这些问题,可以通过避免连接实例之间的序列号重复来将风险降到最低。

如上所述,只有同时拥有连接的四对TCP段和当前活动窗口的序列号时,通信中对方才会认为是正确的。 但是,这也反应了TCP连接的脆弱性。 只要选择合适的序列号、IP地址和端口号,任何人都可以伪造TCP消息段以中断TCP的正常连接。 因此,使用初始化序列号的方法(通常是随机生成的)会使序列号更难猜测,也可以使用加密来防止利用此缺点进行攻击。

因此,在发送建立连接的SYN之前,通信双方都会选择初始序列号。 初始序列号随时间的推移而变化。 每4ms加1。 其目的是在一个连接的字段中放置序列号,以防止与其他连接的序列号重叠。 特别是在同一连接的两个不同实例中,新序列号不会重复。

在前一实例中,在同一连接再次建立连接实例之后,由于服务器两次使用不同的序列号,因此在服务器接收到由于该网络延迟而引起的数据消息块时,其不再具有新的TCP段序列号的TCP连接

因此,在建立TCP连接时,可以看到在客户端和服务器端初始化序列号

,就避免了上述的问题。前面说过,TCP序号占32位,范围是0~232 - 1,并且可以重用。

2.2 为什么客户端第一次握手不能携带数据而第三次握手可以携带数据?

假如 第一次握手可以携带数据的话,如果有人使用伪TCP报文段恶意攻击服务器,那么每次都在第一次握手中的SYN报文中携带大量的数据,因为它不会理会服务器的发送和接收能力是否正常,不断地给服务器重复发送这样携带大量数据的SYN报文,这会导致服务器需要花费大量的时间和内存来接收这些报文数据,这会将导致服务器连接资源和内存消耗殆尽。

所以,之所以第一次握手不能携带数据,其中的一个原因就是避免让服务器受到攻击。而对于第三次握手,此时客户端已经建立了连接,通过前两次已经知道了服务器的接收正常,并且也知道了服务器的接收能力是多少,所以可以携带数据。

2.3 为什么连接建立需要三次握手,而不是两次握手?

根据前面描述,在第一次握手,客户端向服务发送建立连接请求,第二次握手,服务器同意建立连接,并向客户端返回一个确认报文,至此客户端已经知道了服务器同意建立连接,为什么客户端还需要对服务器的允许连接报文段进行确认?

第三个ACK报文段的目的简单来说主要是为了实现可靠数据传输。

三次握手的目的不仅在于让通信双方了解一个连接正在建立,还在于利用数据包的选项来承载特殊的信息,交换初始序列号(Initial Sequence,ISN)。为了实现可靠传输,TCP协议通信双方,都必须维护一个序列号,以标识发送出去的数据报中,哪些是已经被对方收到的。三次握手的过程是通信双方想要告知序列号起始值,并确认已经收到序列号的必经过程。

如上图,在两次握手过程中,通信双方都随机选择了自己的初始段序号,并且第二次握手的时候客户端收到了自己的确认序号,确认了自己的序列号,而服务器端还没有确认自己的序列号,没有收到确认序号, 如果这时候两次握手下就进行数据传递, 序号没有同步,数据就会乱序。即如果只是两次握手,最多只有客户端的起始序列号能被确认,而服务器断的序列号则得不到确认。

简单的来说:

1) 客户端在发出第一次报文段后,它既不知道自己的发送能力和服务器方的接收能力是否正常。

2) 在收到服务器端的确认报文后,客户端知道了自己的发送能力正常(因为服务器收到了自己的请求报文并返回了确认报文了)和服务器的发送能力正常。而服务器知道客户端的发送能力没有问题,但是服务器不知道客户端的接收能力和自己的发送能力是否正常。

如果只有这两次握手,对于服务器来说还不知道它和客户端之间的通信是否可靠。而如果是三次握手时,服务器收到了客户端的确认后,服务器就知道了自己的发送能力和客户端的接收能力也都没有问题,即此时对于通信双方都知道对方及各自的之间的通信是没有问题的。

2.4 SYN 洪泛攻击以及如何解决SYN 洪泛攻击

在三次握手的过程中,服务器为了响应一个受到的SYN报文段,会分配并初始化连接变量和缓存,然后服务器发送一个SYNACK报文段进行响应,并等待客户端的ACK报文段。如果客户不发送ACK来完成该三次握手的第三步,最终(通常在一分多钟之后)服务器将终止该半开连接并回收资源。

这种TCP连接管理协议的特性就会有这样一个漏洞,攻击者发送大量的TCP SYN报文段,而不完成第三次握手的步骤。随着这种SYN报文段的不断到来,服务器不断为这些半开连接分配资源,从而导致服务器连接资源被消耗殆尽。这种攻击就是SYN泛供攻击。

为了应对这种攻击,现在有一种有效的防御系统,称为SYN cookie。SYN cookie的工作方式如下:

(1) 当服务器接收到一个SYN报文段时,它并不知道该报文段是来自一个合法的用户,还是这种SYN洪泛攻击的一部分。因为服务器不会为该报文段生成一个半开的连接。相反,服务器生成一个初始TCP序列号,该序列号是SYN报文段的源IP地址和目的IP地址,源端口号和目的端口号以及仅有服务器知道的秘密数的复杂函数(散列函数)。这种精心制作的初始序列号称为为“cookie”。服务器则发送具有这种特殊初始序号的SYNACK报文分组。服务器并不记忆该cookie或任何对应于SYN的其他状态信息。

(2) 如果该客户是合法的,则它将返回一个ACK报文段。当服务器收到该ACK报文段,需要验证该ACK是与前面发送的某个SYN相对应。由于服务器并不维护有关SYN报文段的记忆,所以服务器通过使用SYNACK报文段中的源和目的IP地址与端口号以及秘密数运行相同的散列函数。如果这个函数的结果(cookie值)加1和在客户的ACK报文段中的确认值相同的话,那么服务器就会认为该ACK对应于较早的SYN报文段,因此它是合法的。服务器则会生成一个套接字的全开连接。

(3) 另一方面,如果客户没有返回一个ACK报文段,说明之前的SYN报文段是洪泛攻击的一部分,但是它并没有对服务器产生危害,因为服务器没有为它分配任何资源。

3 释放连接——四次挥手

连接释放的四次挥手过程如下图所示:

(1) 第一次挥手:客户端应用进程先向服务器端发出连接释放报文段,并停止发送数据,主动关闭连接。其中报文段首部的终止控制为FIN = 1,其序号为seq = u(其值等于前面已传送的数据的最后一个字节的序号加1),此时客户端进入终止等待1(FIN-WAIT-1)状态,等待服务器端的确认。

(2) 第二次挥手:服务器收到连接释放报文段后即发出确认,确认为ACK = 1,确认号为ack = u + 1,序号seq = v(其值是服务器前面已传送过的数据最后一个字节的序号加1),然后服务器就进入了关闭等待(CLOSE-WAIT)状态。

这时TCP连接处于半关闭状态,即客户端到服务器端这个方向的连接就释放了,即客户端没有数据要发送了,但是如果服务器端要发送数据,客户端仍要接收。

客户端在收到服务器端的确认后,就进入终止等待2(FIN-WAIT-2)状态,等待服务器发出的连接释放报文段。

(3) 第三次挥手:如果此时服务器没有数据要发送了,此时服务器向客户端发出连接释放报文段,其FIN = 1,假设器序号为seq = w(在半关闭状态下服务器可能又发送了一些数据),服务器必须重复上次以发送的确认号ack = u + 1(因为客户端没有向服务器发送过数据,所以确认号和上次一致)。这时,服务器进入最后确认(LAST-ACK)状态,等待客户端的确认。

(4) 第四次挥手:客户端在收到服务器端发出的连接释放报文段后,必须对此发出确认,在确认报文段中将ACK置位1,确认号ack = w + 1,而自己的序号为seq = u + 1。之后客户端进入时间等待(TIME-WAIT)状态。在经过时间等待计时器设置的时间2MSL后,客户端才进入关闭(CLOSE)状态

只要服务器收到客户端发出的确认报文就进入关闭(CLOSE)状态。

MSL:最大报文段寿命(Maximum Segment Lifetime)

4 四次挥手的几个问题

4.1 为什么客户端需要等待2MSL时间后,才能进入关闭状态?

这是为了保证客户端发送的最后一个ACK报文段能够到达服务器端。

客户端发送的ACK报文段可能丢失,因而使服务器收不到对自己已发送的释放连接报文段的确认。服务器会重传连接释放报文段,重新启动2MSL计时器,最终,客户端和服务器端都能进入CLOSE状态。

如果客户端在TIME-CLOSE状态不等待而在发送完ACK报文端后直接释放连接,那么在ACK报文段丢失后就无法收到服务器重传的释放连接报文段,因而也不会再发送一次ACK报文段,这样服务器就不能正常进入CLOSE状态。

4.2 为什么建立连接需要三次握手而释放连接需要四次挥手?

在建立连接时,服务器端处于LISTEN状态时,当收到SYN报文段的建立连接请求后,它可以把ACK报文段和SYN报文段(ACK报文段起确认作用,即确认客户端的连接建立请求;SYN报文段起同步作用)放在一起发送,所以在连接建立时四次握手(即第二次握手时,服务器的ACK报文段和SYN报文段分开发送)可以合并为三次握手。

而在释放连接时需要四次是因为TCP连接的半关闭造成的。由于TCP是全双工的(即数据可在两个方向上同时传递),因此,每个方向都必须要单独进行关闭,这个单方向的关闭就叫半关闭。在关闭连接时,当服务器收到客户端的FIN报文通知时,它仅仅表示客户端没有数据发送服务器了;但服务器未必将所有的数据都全部发送给了客户端,所以服务器端未必马上也要关闭连接,也即服务器端可能还需要发送一些数据给客户端之后,再发送FIN报文给客户端来表示现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的,这也是为什么释放连接时需要交换四次报文了。

本文完

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。