事情本身不复杂,线索都在日志里。CentOS 7.9 网关机上 nf_conntrack_count 长期在六万上下,nf_conntrack_max 是 65536,dmesg 偶尔刷 nf_conntrack: table full, dropping packet,业务侧表现为新建连接偶发失败,重试一次又能通。
第一反应是「nginx 反代后端没开 keepalive,每个请求都占一条新连接」,验证下来不成立。
真正麻烦的地方在于,几个原因的现象几乎一样。DNS 查询走 UDP 短连接,每次查询都建一条跟踪记录,一分钟上千条。还有一种是udp 和 time_wait 的 timeout 用的都是默认值,记录要挂很久才回收。
少数情况下是有一条扫描流量在扫端口,未完成的握手也一直占着表项。
第一件事是统计表里到底是谁在占
conntrack -L 2>/dev/null | awk '{print $1, $5}' | sort | uniq -c | sort -rn | head
随后看当前用量和上限
sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
缩短 UDP 与 TIME_WAIT 的保留时间
sysctl -w net.netfilter.nf_conntrack_udp_timeout=30 net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
给本机 DNS 查询加 notrack 绕开跟踪
iptables -t raw -A OUTPUT -p udp --dport 53 -j NOTRACK
恢复的判定其实很直接。conntrack 计数回到两万以下,dmesg 里不再出现 table full,新建连接的失败率归零,DNS 查询耗时没有变差。
容易忽略的是,调大 nf_conntrack_max 只是把天花板抬高,每条记录还要占几百字节内存,十万条就是几十兆;更省事的是在本机放个 DNS 缓存,把查询量直接降下来。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
