linux TCP连接失败(不回复SYN,ACK)问题分析

问题现象

在某一台服务器无法访问另一台服务器的https服务,telnet检测端口发现端口无法连接:

[root@020113 ~]# telnet 192.168.5.27 443
Trying 192.168.5.27...

问题分析

第一步:网络检查

同网段其他主机访问服务端是正常的,因此网络问题可以排除

第二步:查看防火墙

步骤略,这里检查双方iptables规则均无问题

第三步:抓包分析

服务端抓包并将结果保存,因为443端口连接较多,有一些其他干扰,因此抓22端口:

  root@005027  tcpdump host 192.168.20.113 and port 22 -w dump.pcap

客户端同时连接服务端的22端口:

[root@020113 ~]# telnet 192.168.5.27 22

dump.pcap文件拿到本地用wireshark打开分析:
在这里插入图片描述
抓包的结果可以看出,客户端(20.113)发起SYN请求后,即使多次重传,服务端也没有回复过带SYN, ACK标志位的响应,那么看来问题出现在服务端。这时隐隐有了一些猜测,很有可能是之前碰到过的一个问题导致的,在此前的文章也有写过:
Kubernetes踩坑(二): Service IP(LVS)间断性TCP连接故障排查

为了印证自己的猜测,检查一下状态:

root@005027:~# netstat -s | grep timestamp
    2984 packets rejects in established connections because of timestamp

果然,提示有一些包因为时间戳问题丢弃了。

解决:

查看内核参数配置:

net.ipv4.tcp_tw_recycle = 1

果然是打开状态,将其改成0, sysctl -p使其生效后,问题解决。

深挖

为什么会出现这种情况呢?这里再次回顾一下linux内核时间戳相关的3个参数:

# 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1

# 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_tw_recycle = 1

# tcp缓存时间戳,RFC1323中描述了,系统缓存每个ip最新的时间戳,后续请求中该ip的tcp包中的时间戳如果小于缓存的时间戳(即非最新的数据包),即视为无效,相应的数据包会被丢弃,而且是无声的丢弃。在默认情况下,此机制不会有问题,但在nat模式时,不同的ip被转换成同一个ip再去请求真正的server端,在server端看来,源ip都是相同的,且此时包的时间戳顺序可能不一定保持递增,由此会出现丢包的现象,因此,如果是nat模式工作,建议关闭此选项。
net.ipv4.tcp_timestamps = 0

说明:
设计这几个参数是为什么呢?在tcp四次挥手完成之后,服务端会有一个TIME_WAIT的时间等待释放sock连接的端口,默认为2*MSL(60s),而端口资源是有限的,在繁忙的服务器了,等待这么长的时间是非常低效的,因此为了加速这个效率,linux内核设计了tcp_tw_reuse和tcp_tw_recycle这两个参数,这两个参数一般都是一起使用的,开启后允许time_wait状态(后面简写tw)的端口被回收并重用。但是,回收重用容易引发一个问题,就是可能导致回收的端口收到了来自之前的对端连接的数据,因此为了避免这个问题,又设计了另一个参数tcp_timestamps,在上面的注释中也说明了,非最大时间戳的包会丢弃。

因此,郑重建议: 这3个参数建议不要同时开启,要么干脆不开启回收重用,要开启的话,建议不要开始时间戳标记。

展开阅读全文
©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值