首页 / 内容指南 / 当前文章

Linux nf_conntrack table full:丢包、容量与超时排查

发布于 2026-08-26 · xieyipai.com 编辑部

Linux 网关、Kubernetes 节点或 NAT 主机突然出现新连接超时,内核日志包含 nf_conntrack: table full, dropping packet;已有长连接仍可能正常,重启网络后短暂恢复。这通常表示 Netfilter 连接跟踪表无法为新流分配条目,不是应用监听队列或远端服务单独故障。排查要先证明表确实饱和,再找到是哪类流、哪个 namespace、哪组超时或异常流量消耗容量。

本文目录(19 节)

先确认是否真的满表

读取当前数量与上限:

sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
conntrack -C
conntrack -S

nf_conntrack_count 是当前已分配流条目数,只读;nf_conntrack_max 是允许的最大数。持续接近上限、内核日志同时增长、conntrack -S 的 insert_failed 或 drop 计数上升,才构成强证据。单次日志可能来自已经结束的突发,应把指标按时间对齐。

为什么旧连接正常而新连接失败

连接跟踪为 TCP、UDP、ICMP 及 NAT 流维护状态。表满时,内核可能无法为新流建立条目,因此新 TCP SYN、首个 UDP 数据报或新的 NAT 映射被丢弃;已有条目仍能命中并继续转发。

这解释了“SSH 现有会话正常,但新 SSH/HTTP 连接超时”。客户端可能只看到 SYN 重传或 UDP 无响应,应用服务器甚至收不到包。不要因此在应用端盲目扩容 worker 或 accept queue。

count 与 max 的口径

内核文档说明,nf_conntrack_max 默认通常与 nf_conntrack_buckets 有关;连接会以原方向和回复方向放入哈希结构,因此满表时平均哈希链长度的解释不能简单按“一条连接等于一个 bucket”理解。count 代表流条目数量,不是当前 TCP socket 数量。

同一主机上的容器、转发流、NAT 和本机连接可能共同使用连接跟踪资源。读取 sysctl 和 conntrack 视图时要确认所在 network namespace;只看宿主或某个容器的视角可能漏掉实际占用者。

建立协议与状态分布

用 conntrack -L 的过滤与统计能力,按协议、源/目的网段、端口、TCP 状态、zone 和 mark 聚合。大型表不要频繁完整 dump 到终端,因为输出本身可能消耗 CPU、锁竞争和 Netlink 缓冲;优先采样、计数或在副本环境分析。

重点找:大量未回复 UDP、长时间 ESTABLISHED TCP、SYN_SENT/SYN_RECV 激增、TIME_WAIT 相关条目、单一源地址扫描、DNS/NTP 突发、负载均衡健康检查,以及容器创建的短连接。连接跟踪状态与主机 ss socket 状态不是同一张表,应交叉验证。

UDP 最容易被忽略

UDP 没有连接关闭握手,内核依赖超时回收。内核文档列出 nf_conntrack_udp_timeout 和 nf_conntrack_udp_timeout_stream;当检测到双向 UDP 流时,可能使用更长的 stream 超时。高基数 DNS、日志、监控或 QUIC 流量会快速创建大量条目。

比较单向和双向 UDP 占比,检查是否有随机源端口、随机目标或扫描流。不要只按字节数找大流:大量低流量五元组更容易消耗条目数量。

TCP 长超时与异常状态

内核默认的 TCP established 连接跟踪超时可能很长。应用已经崩溃、路由单向中断或客户端消失时,缺少 FIN/RST 的条目会依赖超时清理。SYN_SENT、SYN_RECV、CLOSE_WAIT、FIN_WAIT 和 TIME_WAIT 也各有独立 conntrack 超时。

先按 TCP 状态和最近流量定位,再评估是否调整。不能把 established 超时全局降到几分钟来“清表”,否则低频但合法的长连接可能失去 NAT 状态并被中断。应用 keepalive、负载均衡 idle timeout 和 conntrack timeout 应协同设计。

NAT 与端口耗尽是两个问题

NAT 流需要 conntrack 状态,但表满不等于 SNAT 临时端口用尽。前者看 nf_conntrack_count/max 和插入失败;后者通常表现为特定出口地址/端口范围无法分配,即使表仍有容量。

分别统计 NAT 映射、出口 IP、目标和源端口。扩展 conntrack 表不会增加可用 SNAT 端口;增加出口地址也不会自动解决全局条目泄漏。两类容量必须分别监控。

buckets 与查找性能

nf_conntrack_buckets 控制哈希表大小。内核文档指出,若模块加载时未指定,会根据内存计算并限制在一定范围;该 sysctl 只可在初始 network namespace 写入。提高 max 而 buckets 不匹配,会增加哈希链和查找成本。

调参前记录内核版本、RAM、当前 buckets、max、峰值 count、CPU softirq 和 conntrack -S 统计。容量规划要同时考虑条目内存、扩展字段、哈希查找与最坏流量,而不是只把 max 乘十。

accounting 与 timestamp 的成本

nf_conntrack_acct 可为每条流增加 64 位包/字节计数,nf_conntrack_timestamp 可记录时间;它们提升诊断能力,也会为新条目增加扩展和内存。内核文档说明 accounting 默认关闭,events 通常为 auto。

开启前评估表规模和监控需求。若只为一次事故临时打开,要注意已有条目未必补齐历史计数;不要用部分数据推断全部流量生命周期。

日志、统计与抓包怎样关联

保存 dmesg/journal 中满表时间,按 CPU 查看 /proc/net/stat/nf_conntrack 或用 conntrack -S,再对入口流量做短时受控抓包。lnstat 文档列出的 conntrack 统计包括 entries、searched、found、new、invalid 等,可辅助判断查找与创建压力。

抓包只能看到数据包,不能直接证明条目是否成功插入。把首包时间、insert_failed 增量和客户端重传关联,才能确认丢包路径。避免全接口长时间无过滤抓包造成二次资源问题。

紧急处置的优先级

先限速或阻断明确的异常来源、扫描、反射流量和失控健康检查,减少新条目增长;再为关键业务保留路径。若内存和性能预算允许,可临时提高 nf_conntrack_max 争取恢复窗口,但必须同步监控 slab/内存与 CPU。

不要把 conntrack -F 全表清空当成默认修复。它会破坏现有 NAT 和有状态防火墙会话,可能造成更大中断。需要删除时按源、目的、协议或状态精确筛选,并先验证命令范围和回滚方式。

NOTRACK 何时适用

iptables 的 raw 表可通过 CT --notrack/NOTRACK 让匹配流量跳过连接跟踪。它适合明确不需要 NAT 和 stateful firewall 的高频无状态流,但会使这些包成为 UNTRACKED,并失去基于连接状态、NAT、部分 helper 与统计能力。

规则必须放在连接跟踪之前,并同时考虑请求和响应方向。不要为了降 count 对任意生产业务全面 NOTRACK;先在隔离流量上验证安全策略和可观测性。

容器与 Kubernetes 节点

Kubernetes 节点的 Service、NAT、Pod 出站、健康检查和东西向流量可能共同进入 conntrack。单个异常 Pod 能制造大量五元组,但事故表现在整台节点的新连接失败。按源 Pod IP、目标、协议和节点分布聚合,确认是否集中在少数节点。

扩容 Pod 若仍落到同一节点,可能反而增加流量;节点替换会短暂释放表,但不消除应用连接风暴。根因修复应包含连接池、重试退避、DNS 查询模式和服务发现行为。

高可用防火墙的额外检查

使用 conntrackd 同步状态时,内核表、内部缓存、外部缓存和 Netlink 事件队列是不同层。事件 socket overrun 或同步落后不等于内核表一定已满,但切换后可能造成状态缺失和重新建连风暴。

分别检查 conntrack -S 与 conntrackd -s,记录 overrun、resync、cache 和同步链路。主备双方应有一致容量与超时策略,故障切换演练要覆盖接近峰值表规模。

推荐排查顺序

  1. 对齐满表日志、count/max、插入失败和用户超时时间。
  2. 确认 network namespace、节点与流量方向。
  3. 按协议、状态、源/目的和 NAT 聚合连接条目。
  4. 查明增长是合法峰值、重试风暴、扫描还是超时积压。
  5. 分别检查 UDP、TCP 各状态和应用连接生命周期。
  6. 核算 max、buckets、内存、CPU 与扩展字段成本。
  7. 先控制异常新流,再谨慎临时扩容或精确删除。
  8. 修复应用连接模式与容量监控,完成峰值压测。

容量规划与验收

用业务峰值的并发五元组数量而非 QPS 单独估算,加入 DNS/监控、发布、故障重试、节点漂移和攻击余量。监控 count/max 比例、创建/删除速率、insert_failed、drop、协议/状态分布、内存和 softirq。

修复后做受控突发测试:新连接应成功,表能够在流量下降后按预期回落,已有 NAT 会话不被误删,CPU 与内存保持预算内。还要验证告警早于 table full,而不是等用户超时才触发。

常见问题

直接增大 nf_conntrack_max 就能解决吗?

只能临时增加容量。若流量泄漏、攻击、超时过长或重试风暴仍在,表还会再次填满,并消耗更多内存和查找成本。

nf_conntrack_count 等于 TCP 连接数吗?

不等于。它包含被跟踪的多种协议、转发/NAT 流和不同状态,也可能涵盖容器流量;应使用 conntrack 维度分析。

可以把所有 UDP 都设为 NOTRACK 吗?

不建议。NOTRACK 会失去有状态规则、NAT 和相关能力。只应对明确无状态、无需这些功能的流量按双向规则受控使用。

清空 conntrack 表会发生什么?

现有 NAT 和有状态防火墙会话可能中断或重新建立。生产环境应避免全表 flush,优先限流、扩容和精确删除异常条目。

为什么表未到 100% 也有丢包?

采样可能错过瞬时峰值,或不同 namespace/节点的视图不一致;还可能是内存分配、哈希/CPU 压力或其他网络故障。结合每 CPU 统计、日志和时间序列判断。

总结

nf_conntrack: table full 是新流状态分配失败的结果,而不是单一应用故障。先以 count/max、内核统计和时间线证明饱和,再按协议、状态、源目的、NAT 与 namespace 找出占用者。临时扩容只能争取时间,长期修复依赖合理超时、连接生命周期、异常流量控制、哈希与内存容量,以及提前告警。

来源资料