首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Linux-影响TCP连接建立和断开的配置

作者系水厂开发专家:数据转发面研发专家

https://zhuanlan.zhihu.com/p/619329949

1 前言

如果在Linux做网络相关的开发工作,经常会处理很多的问题,有时候单从业务角度很难理解业务的一些行为表现,以TCP/IP协议为例子,我们尝试理解一个网络连接受哪些因素影响。

2 TCP连接建立过程相关配置

TCP三次握手过程中相关参数

图上是一个TCP连接建立过程,TCP连接的建立是在Client调用connect()到Server侧的accept()返回成功的过程。

2.1 tcp_syn_retries

熟知三次握手的我们都知道Client段会发送一个SYN包给Sever端,由于SYN包可能会在传输过程中丢失等原因导致Server无法处理,此时Client这一侧就会触发超时重传,重传的次数就受tcp_syn_retries这个配置来决定。

如果tcp_syn_retries次数设为3,那么SYN包重传的时序大概如下:

SYN包三次重传超时

Client发出SYN后,如果过了1s,没有从Server收到响应,就会进行重传;

如果经过2s,没有从Server收到响应,就会进行2次重传;

如果经过4s,没有从Server收到响应,就会进行3次重传;

因为重传次数设定为3,所以一共会重传三次,也就是从第一次发出SYN包后,会一直等待(1+2+4+8)共计15秒,如果还没有收到Server响应,connect就会产生ETIMEOUT错误。

2.2 tcp_max_syn_backlog

还有一种情况,除了SYN包被丢弃的可能,Server可能是太忙处理不过来了,或者Server积压了很多的半连接而无法即使处理。

什么是半连接呢?就是Server收到了SYN还没有回复SYNACK的连接,Server每收到一个新的SYN包,都会创建一个半连接,然后把该半连接加入到半连接队列(syn queue)中,syn queue的长度就是tcp_max_syn_backlog这个值来决定的,当系统中的半连接数超过了该值后,新的SYN包会被丢弃。对于Server而言,可能瞬间会有非常多的新连接,所以我们可以适当调大这个值,以免因为syn queue满了而丢弃SYN包导致的Client收不到SYN ACK。

2.3 tcp_syncookies

Server瞬时收到的SYN过多还有一种情况是SYN Flood攻击导致的,攻击Client高频次发送SYN包,并且不停的变换源IP和源端口,那么Server每次收到一个新的SYN包后都会分配一个半连接,由于是错误的Client IP,所以无法收到客户端的ACK包,导致无法正常简历TCP连接,产生了大量的半连接,就会耗尽队列资源,无法响应正常的连接SYN包。

所以为了防止这种攻击,Linux引入了SYN Cookie机制。啥是SYN Cookie呢?

在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器再根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接,建议开启该选项。

2.4 tcp_synack_retries

Server向Client发送的SYNACK包也是有可能被丢弃的,因为网络故障或者其他原因收不到Client的响应,这个时候Server会重传SYNACK包,同样的重传次数受tcp_synack_retries影响。

2.5 somaxconn

Client收到Server的SYNACK后,握手的ACK包恢复送给Server,Server收到ACK后,三次握手即完成,产生了一个全连接,它会被添加到accept queue中。Server就可以调用accept来完成TCP连接的建立。

但是就如syn queue一样,accept queue的长度也是有限的,全连接的长度是由,listen(socket,backlog)中的backlog控制的,该backlog的最大值是由somaxconn控制的。

2.6 tcp_abort_on_overflow

当服务器中积压的全连接个数超过该值后,新的连接就会被丢弃了。Server在丢弃新连接时,有的需要发送reset来通知Client,这样Client就不会重试了。默认是不会回RST通知Client的,发不发是由这个选项控制的。

所以可以根据自己的情况来选择是否开启该选项。

3 TCP断开连接过程受哪些配置影响

accept()成功返回后,一个新的TCP连接就建立完成了,TCP连接进入到了ESTABLISHED状态,Client和Server就可以正常通信了,接下来看看TCP连接断开过程中受哪些系统配置影响。

tcp连接断开过程3.1 tcp_fin_timeout

Client调用close()时,会向Server发送FIN包,Server会回复一个ACL,然后Server也会调用close()发送FIN,然后Client回复一个ACK,这就是TCP的四次挥手过程。

先调用close()的一方是主动关闭,而收到对段FIN再调用close的一方是被动关闭。按图中的时序我们假定主动关闭的一方是Client段。

Client段在发出FIN后,收到Server的ACK包后连接状态会进入FIN_WAIT_2状态。TCP进入到这个状态后,如果Client迟迟没有收到Server的FIN包,通常认定对方机器出了问题,所以因为太忙不能及时close()。所以tcp_fin_timeout就是超时等待的时间。

来看TIME_WAIT状态,TIME_WAIT状态存在的意义是:最后发送的这个ACK包可能会被丢弃掉或者有延迟,这样对端就会再次发送FIN包。如果不维持TIME_WAIT这个状态,那么再次收到对端的FIN包后,本端就会回一个Reset包,这可能会产生一些异常。

3.2 tcp_max_tw_buckets

TIME_WAIT状态存在这么长时间,也是对系统资源的一个浪费,所以系统也有配置项来限制该状态的最大个数,该配置选项就是tcp_max_tw_buckets。

3.3 tcp_tw_reuse

Client关闭跟Server的连接后,也有可能很快再次跟Server之间建立一个新的连接,而由于TCP端口最多只有65536个,如果不去复用处于TIME_WAIT状态的连接,就可能在快速重启应用程序时,出现端口被占用而无法创建新连接的情况。所以建议打开复用TIME_WAIT的选项:

3.4 tcp_tw_recycle

还有另外一个选项tcp_tw_recycle来控制TIME_WAIT状态,但是该选项是很危险的,因为它可能会引起意料不到的问题,比如可能会引起NAT环境下的丢包问题。所以建议将该选项关闭:

写在最后:

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230601A000B300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券