高并发下iptables丢包主因是nf_conntrack表耗尽,需协同调优nf_conntrack_max与hashsize、精简连接超时、禁用无用协议跟踪、防止模块卸载、跳过无需跟踪流量,并适配容器场景。

高并发下 iptables 连接变慢、丢包,核心瓶颈往往不是规则本身,而是 nf_conntrack 模块的资源耗尽。典型现象是系统日志反复出现:
kernel: nf_conntrack: table full, dropping packet
这说明连接跟踪表已满,新连接无法登记状态,iptables 只能静默丢弃数据包。优化关键不在“加规则”,而在“撑住连接账本”。以下是生产环境验证有效的配置要点:
调整 conntrack 表容量与哈希结构
conntrack 表大小(nf_conntrack_max)和底层哈希桶数量(hashsize)必须协同调优。仅改 nf_conntrack_max 不生效,是常见踩坑点。
- 在
/etc/sysctl.conf中设置最大连接数(按内存估算:每连接约 304 字节):net.netfilter.nf_conntrack_max = 1048576net.nf_conntrack_max = 1048576 - 在
/etc/modprobe.d/iptables.conf(或/etc/modprobe.conf)中设置哈希桶大小:options nf_conntrack hashsize=262144
(值应为 2 的幂,建议从 65536 起逐步测试;若启动报falling back to vmalloc,说明内存不足,需调小) - 执行
sysctl -p && modprobe -r nf_conntrack && modprobe nf_conntrack生效(注意:单纯sysctl -p不会重载模块参数)
精简并延长有效连接生命周期
避免短连接快速填满表。重点调优 TCP 已建立连接的超时时间,而非盲目拉长所有状态。
- 缩短无效连接等待时间:
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30 - 合理延长稳定连接存活期(减少重建):
net.netfilter.nf_conntrack_tcp_timeout_established = 1800(默认常为 432000 秒,对长连接服务可保留;但 Web/API 等短连接场景建议降至 900–1800 秒) - 禁用无意义协议跟踪(如 ICMP)可小幅减压:
net.netfilter.nf_conntrack_icmpv4_timeout = 5
规避模块自动卸载导致配置丢失
CentOS/RHEL 系统执行 service iptables stop 时,默认会卸载 nf_conntrack 模块,导致之前 sysctl 设置全部失效——重启 iptables 后仍用默认小表,问题复现。
- 修改
/etc/init.d/iptables脚本,找到NF_MODULES_COMMON行,移除nf_conntrack:
原:NF_MODULES_COMMON=(x_tables nf_nat nf_conntrack)
改为:NF_MODULES_COMMON=(x_tables nf_nat) - 确保
nf_conntrack由内核自动按需加载,不再被脚本强制管理 - 验证方式:
lsmod | grep nf_conntrack应始终存在;sysctl net.netfilter.nf_conntrack_count实时值应远低于 max 值
配合 iptables 规则减少无谓跟踪
不是所有流量都需要 conntrack。跳过无需状态检查的包,能显著降低表压力。
- 在
raw表中提前标记不跟踪的流量:iptables -t raw -A PREROUTING -p tcp --dport 8080 -j NOTRACKiptables -t raw -A OUTPUT -p tcp --sport 8080 -j NOTRACK - 仅对真正需要 NAT 或状态防火墙的链路启用跟踪(如 DNAT/SNAT、对外暴露服务)
- 避免在
INPUT链顶部写-m state --state ESTABLISHED,RELATED -j ACCEPT类规则——它强制所有包进 conntrack 流程;改用-m conntrack --ctstate ESTABLISHED,RELATED更精准
不复杂但容易忽略:conntrack 是共享资源,容器、K8s、Docker 都共用同一张表。单机跑数百 Pod 时,nf_conntrack_max 至少要设到百万级,并配合 hashsize 调整。调完记得用 watch -n1 'cat /proc/sys/net/netfilter/nf_conntrack_count' 观察水位变化。










