我们使用Linux作为服务器操作系统时,为了达到高并发处理能力,充分利用机器性能,经常会进行一些内核参数的调整优化,但不合理的调整常常也会引起意想不到的其他问题,本文就一次Linux服务器丢包故障的处理过程,结合Linux内核参数说明和TCP/IP协议栈相关的理论,介绍一些常见的丢包故障定位方法和解决思路。
问题现象
本次故障的反馈现象是:从办公网访问公网服务器不稳定,服务器某些端口访问经常超时,但Ping测试显示客户端与服务器的链路始终是稳定低延迟的。
通过在服务器端抓包,发现还有几个特点:
从办公网访问服务器有多个客户端,是同一个出口IP,有少部分是始终能够稳定连接的,另一部分间歇访问超时或延迟很高
同一时刻的访问,无论哪个客户端的数据包先到达,服务端会及时处理部分客户端的SYN请求,对另一部分客户端的SYN包“视而不见”,如tcpdump数据所示,源端口为56909的SYN请求没有得到响应,同一时间源端口为50212的另一客户端SYN请求马上得到响应。
Shell
1
2
3
4
5
6
7
8
9
10
11
$sudotcpdump-ieth0port22and"tcp[tcpflags] & (tcp-syn) != 0"
18:56:37.404603IPCLIENT.56909>SERVER.22:Flags[S],seq1190606850,win29200,options[mss1448,sackOK,TSval198321481ecr0,nop,wscale7],length0
18:56:38.404582IPCLIENT.56909>SERVER.22:Flags[S],seq1190606850,win29200,options[mss1448,sackOK,TSval198321731ecr0,nop,wscale7],length0
18:56:40.407289IPCLIENT.56909>SERVER.22:Flags[S],seq1190606850,win29200,options[mss1448,sackOK,TSval198322232ecr0,nop,wscale7],length0
18:56:44.416108IPCLIENT.56909>SERVER.22:Flags[S],seq1190606850,win29200,options[mss1448,sackOK,TSval198323234ecr0,nop,wscale7],length0
18:56:45.100033IPCLIENT.50212>SERVER.22:Flags[S],seq4207350463,win65535,options[mss1366,nop,wscale5,nop,nop,TSval821068631ecr0,sackOK,eol],length0
18:56:45.100110IPSERVER.22>CLIENT.50212:Flags[S.],seq1281140899,ack4207350464,win27960,options[mss1410,sackOK,TSval1709997543ecr821068631,nop,wscale7],length0
18:56:52.439086IPCLIENT.56909>SERVER.22:Flags[S],seq1190606850,win29200,options[mss1448,sackOK,TSval198325240ecr0,nop,wscale7],length0
18:57:08.472825IPCLIENT.56909>SERVER.22:Flags[S],seq1190606850,win29200,options[mss1448,sackOK,TSval198329248ecr0,nop,wscale7],length0
18:57:40.535621IPCLIENT.56909>SERVER.22:Flags[S],seq1190606850,win29200,options[mss1448,sackOK,TSval198337264ecr0,nop,wscale7],length0
18:57:40.535698IPSERVER.22>CLIENT.56909:Flags[S.],seq3621462255,ack1190606851,win27960,options[mss1410,sackOK,TSval1710011402ecr198337264,nop,wscale7],length0
排查过程
服务器能正常接收到数据包,问题可以限定在两种可能:部分客户端发出的数据包本身异常;服务器处理部分客户端的数据包时触发了某种机制丢弃了数据包。因为出问题的客户端能够正常访问公网上其他服务,后者的可能性更大。
有哪些情况会导致Linux服务器丢弃数据包?
防火墙拦截
服务器端口无法连接,通常就是查看防火墙配置了,虽然这里已经确认同一个出口IP的客户端有的能够正常访问,但也不排除配置了DROP特定端口范围的可能性。
如何确认
查看iptables filter表,确认是否有相应规则会导致此丢包行为:
Shell
1
$sudoiptables-save-tfilter
这里容易排除防火墙拦截的可能性。
连接跟踪表溢出
除了防火墙本身配置DROP规则外,与防火墙有关的还有连接跟踪表nf_conntrack,Linux为每个经过内核网络栈的数据包,生成一个新的连接记录项,当服务器处理的连接过多时,连接跟踪表被打满,服务器会丢弃新建连接的数据包。
如何确认
通过dmesg可以确认是否有该情况发生:
Shell
1
$dmesg|grepnf_conntrack
如果输出值中有“nf_conntrack: table full, dropping packet”,说明服务器nf_conntrack表已经被打满。
通过/proc文件系统查看nf_conntrack表实时状态:
Shell
1
2
3
4
5
6
# 查看nf_conntrack表最大连接数
$cat/proc/sys/net/netfilter/nf_conntrack_max
65536
# 查看nf_conntrack表当前连接数
$cat/proc/sys/net/netfilter/nf_conntrack_count
7611
当前连接数远没有达到跟踪表最大值,排除这个因素。
如何解决
如果确认服务器因连接跟踪表溢出而开始丢包,首先需要查看具体连接判断是否正遭受DOS攻击,如果是正常的业务流量造成,可以考虑调整nf_conntrack的参数:
nf_conntrack_max决定连接跟踪表的大小,默认值是65535,可以根据系统内存大小计算一个合理值:CONNTRACK_MAX = RAMSIZE(in bytes)/16384/(ARCH/32),如32G内存可以设置1048576;
nf_conntrack_buckets决定存储conntrack条目的哈希表大小,默认值是nf_conntrack_max的1/4,延续这种计算方式:BUCKETS = CONNTRACK_MAX/4,如32G内存可以设置262144;
nf_conntrack_tcp_timeout_established决定ESTABLISHED状态连接的超时时间,默认值是5天,可以缩短到1小时,即3600。
Shell
1
2
3
$sysctl-filter.nf_conntrack_max=1048576
$sysctl-filter.nf_conntrack_buckets=262144
$sysctl-filter.nf_conntrack_tcp_timeout_established=3600
如果觉得《linux如何查看丢弃数据包 导致Linux服务器丢弃数据包?》对你有帮助,请点赞、收藏,并留下你的观点哦!