TCP三次握手第三次握手时ACK丢失怎么办

《TCP三次握手第三次握手时ACK丢失怎么办》

Server 端

    第三次的ACK在网络中丢失,那么Server 端该TCP连接的状态为SYN_RECV,并且会根据 TCP的超时重传机制,会等待3秒、6秒、12秒后重新发送SYN+ACK包,以便Client重新发送ACK包。

    而Server重发SYN+ACK包的次数,可以通过设置/proc/sys/net/ipv4/tcp_synack_retries修改,默认值为5.

    如果重发指定次数之后,仍然未收到 client 的ACK应答,那么一段时间后,Server自动关闭这个连接,并从半连接队列(syns queue)移除。

Client 端

    在linux c 中,client 一般是通过 connect() 函数来连接服务器的,而connect()是在 TCP的三次握手的第二次握手完成后就成功返回值。也就是说 client 在接收到 SYN+ACK包,它的TCP连接状态就为 established (已连接),表示该连接已经建立。那么如果 第三次握手中的ACK包丢失的情况下,Client 向 server端发送数据,Server端将以 RST包响应(用于强制关闭tcp连接),方能感知到Server的错误。client端接收到服务端发送SYN+ACK包,会尝试发送ACK包进行重连,如果服务端收到ack进入全连接队列(accept queue) 全连接队列默认大小backlog值是50

第三次握手时server具体的处理方式

《TCP三次握手第三次握手时ACK丢失怎么办》

场景1:当全连接未满

当server收到client的ack后会先判断全连接队列accept queue是否已满,如果队列未满则从半连接队列拿出相关信息存放入全连接队列中,之后服务端accept()处理此请求。

场景2:当全连接已满且tcp_abort_on_overflow = 0

server会扔掉client 发过来的ack。之后隔一段时间server会重发握手第二步的syn+ack包给client,如果客户端连接一直排队不上等待超时则会报超时异常。

场景3:全连接已满且tcp_abort_on_overflow = 1时

server会发送一个reset包给client,表示废除这个握手过程和这个连接(客户端会报connection reset by peer异常)

1.为什么要三次握手,而不是二次握手?

     为了避免已失效的连接报文段又到达可服务器。考虑这样一个正常的情况:

   假设TCP连接是两次握手。当客户端发送了一个请求连接的报文时,由于网络原因这个报文丢失了,那么客户端一段时间内没有收到服务器的确认就会再次发送请求连接报文,这次服务器收到了,双方都建立了连接,然后数据传输,最后关闭连接。

  但是考虑一下,上文中的丢失数据包若没有丢失,只是在一个网络节点长时间滞留了,这时双方都已经关闭了连接,此时服务器又收到了丢掉了的数据包请求,认为客户端又要建立连接,因为是两次握手所以服务器向客户端发送了确认报文,并变为建立连接状态。

   可想而知客户端并没有发起连接所以会忽略服务器的确认,则服务端一直等待客户端发送数据,这样就浪费了服务器的资源。

2.Server端易受到SYN攻击?

     服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪泛攻击,SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复SYN+ACK确认包,并等待Client确认回复ACK,而这些大量的IP是不存在的,并不会向服务端发送ack确认包,所以会大量的占领半连接队列资源,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。

3.预防SYN攻击? 

   开启SYN cookies技术、增加最大半连接和缩短超时时间。

SYN cookies应用于linux、FreeBSD等操作系统,当半连接队列满时,SYNcookies并不丢弃SYN请求,而是通过加密技术来标识半连接状态。

在TCP实现中,当收到客户端的SYN请求时,服务器需要回复SYN+ACK包给客户端,客户端也要发送确认包给服务器。通常,服务器的初始序列号由服务器按照一定的规律计算得到或采用随机数,但在SYN cookies中,服务器的初始序列号是通过对客户端IP地址、客户端端囗、服务器IP地址和服务器端囗以及其他一些安全数值等要素进行hash运算,加密得到的,称之为cookie。当服务器遭受SYN攻击使得半连接状态队列满时,服务器并不拒绝新的SYN请求,而是回复cookie(回复包的SYN序列号)给客户端, 如果收到客户端的ACK包,服务器将客户端的ACK序列号减去1得到cookie比较值,并将上述要素进行一次hash运算,看看是否等于此cookie。如果相等,直接完成三次握手(注意:此时并不用查看此连接是否属于半连接状态队列)。

    原文作者:Code@Z
    原文地址: https://blog.csdn.net/MrLiar17/article/details/118893121
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞