iptables连接跟踪状态表conntrack爆满网络故障处理[已解决]

iptables连接跟踪状态表conntrack爆满网络故障处理[已解决]

2024-09-15 / 0 评论 / 108 阅读 / 正在检测是否收录...

iptables连接跟踪状态表conntrack爆满网络故障处理[已解决]

本文记录了Openwrt 软路由,由于iptables连接跟踪状态表conntrack达到最大限制,触发一系列奇怪的网络。从故障现象到排查过程,
到优化方案都做了详细的总结

首先介绍下公司的网络设备连接方式:

问题描述:某天接到公司同事反馈 IOS端的 Appstore应用打不开。一开始以为是同事电脑问题。
报错如下:

m0yr91h9.png

故按照管理,重启大法伺候,

重启完之后,故障仍在。没多久,又有其他同事陆续范围,MAC笔记本电脑打不开 Appstore,断网重连,重启电脑都不行。
看来网络确实有问题。

开始排查

排查接入点网络

先尝试有线和无线,2.4G和5G两个WIFI频段都尝试一次,以上问故障都会出现。初步定位为和WIFI热点无关。应该是上层网络节点出问题。

排查路由防火墙设置

排查了常规的iptables防火墙,端口转发,行为管理行为策略。发现都正常。

路由器tcpdump抓包

登录openwrt路由器命令行界面,使用tcpdump -vn 192.168.24.31 抓包debug
这里的 192.168.24.31 是其中的一台苹果手机IP,我们用这台手机访问appstore抓包测试。经排查发现打开appstore 这个app时网络数据包异常,从app服务器发来的udp数据包,无法被手机端接收,服务器发来的3次同样的Udp数据包,均没有被手机端接收到。
问题就出在这里。那么是什么原因导致的呢?

考虑到既然是网络数据包进不来,重置一下网络连接是否有效呢?
然后在openwrt上面重载iptables,再测试发现app store可以正常访问了。

然而。。。,过了1分钟之后,app store就又无法访问了,一脸懵逼。。。
看来这个问题确实跟防火墙有关。
防火墙上配置了一系列端口转发规则,都是业务在用的,无法通过关闭Iptables解决。

在这里卡了大半天,实在找不到解决办法。并且在这期间app store有时候是能访问的,大部分时间都无法访问。看起来相当不稳定,很奇怪的问题。

这里就想着如何追踪iptables工作状态,经过查资料发现。
openwrt 网络连接主要和iptables有关,并且记录在 /proc/net/nf_conntrack 中,这个文件中。

nf_conntrack详解

nf_conntrack(在老版本的 Linux 内核中叫 ip_conntrack)是一个内核模块,用于跟踪一个连接的状态的。连接状态跟踪可以供其他模块使用,最常见的两个使用场景是 iptables 的 nat 的 state 模块。
iptables 的 nat 通过规则来修改目的/源地址,但光修改地址不行,我们还需要能让回来的包能路由到最初的来源主机。这就需要借助 nf_conntrack 来找到原来那个连接的记录才行。而 state 模块则是直接使用 nf_conntrack 里记录的连接的状态来匹配用户定义的相关规则。例如下面这条 INPUT 规则用于放行 80 端口上的状态为 NEW 的连接上的包。

iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT。
iptables中的状态检测功能是由state选项来实现iptable的

/proc/net/nf_conntrack内容详解

cat /proc/net/nf_conntrack
ipv4     2 tcp      6 8 CLOSE src=115.231.78.3 dst=107.173.34.159 sport=64904 dport=443 src=107.173.34.159 dst=115.231.78.3 sport=443 dport=64904 [ASSURED] mark=0 zone=0 use=2
ipv4     2 tcp      6 119 TIME_WAIT src=115.231.78.3 dst=107.173.34.159 sport=45761 dport=443 src=107.173.34.159 dst=115.231.78.3 sport=443 dport=45761 [ASSURED] mark=0 zone=0 use=2
ipv4     2 tcp      6 6 CLOSE src=115.231.78.3 dst=107.173.34.159 sport=57985 dport=443 src=107.173.34.159 dst=115.231.78.3 sport=443 dport=57985 [ASSURED] mark=0 zone=0 use=2

每一列表达的意思
第一列:网络层协议名字。
第二列:网络层协议号。
第三列:传输层协议名字。
第四列:传输层协议号。
第五列:无后续包进入时无效的秒数,即老化时间。
第六列:不是所有协议都有,连接状态。
其它的列都是通过名字的方式(key与value对)表述,或和呈现标识([UNREPLIED], [ASSURED], …)。一行的不同列可能包含相同的名字(例如src和dst),第一个表示请求方,第二个表示应答方。
呈现标识含义
[ASSURED]: 在两个方面(即请求和响应)方向都看到了流量。
[UNREPLIED]: 尚未在响应方向上看到流量。如果连接跟踪缓存溢出,则首先删除这些连接。
请注意,某些列名仅出现在特定协议中(例如,TCP和UDP的sport和dport,ICMP的type和code)。 仅当内核使用特定选项构建时,才会显示其他列名称(例如mark)。

经检查发现,这个文件现在有16000行左右。这个值刚好和当前配置的
net.netfilter.nf_conntrack_max=16000 值接近,并且一直在这个值左右徘徊。查阅资料发现这个值是系统用来记录跟踪所有网络连接状态的表。已经超过了最大值。我们修改并添加一下参数再试试:
在 /etc/sysctl.conf 文件中新增以下内容

net.netfilter.nf_conntrack_buckets=262144
net.netfilter.nf_conntrack_generic_timeout=600
net.netfilter.nf_conntrack_udp_timeout=30
net.netfilter.nf_conntrack_udp_timeout_stream=180
net.netfilter.nf_conntrack_tcp_timeout_syn_recv=60
net.netfilter.nf_conntrack_tcp_timeout_syn_sent=120
net.netfilter.nf_conntrack_tcp_timeout_time_wait=120

然后:

sysctl -w net.netfilter.nf_conntrack_buckets=262144
sysctl -w net.netfilter.nf_conntrack_generic_timeout=600
sysctl -w net.netfilter.nf_conntrack_udp_timeout=30
sysctl -w net.netfilter.nf_conntrack_udp_timeout_stream=180
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_syn_recv=60
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_syn_sent=120
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=120

使之生效。
再运行 sysctl -p

以防万一。找个业务低峰期重启一下openwrt,重启速度openwrt硬件有关。我们的硬件为inter 10代i7,30秒左右就重启好了。

经过2天的观察,发现app store已经完全正常, /proc/net/nf_conntrack 文件记录数也从1.6w,涨到了2w看起来确实生效了。收工。

0

评论 (0)

取消