必须用 raw 表,因为其 prerouting 和 output 链在 conntrack 初始化前执行,-j notrack 可跳过连接跟踪;filter/nat 表生效时 conntrack 已创建,无法规避资源消耗。

要用 iptables 的 raw 表 + NOTRACK 规避高并发下 conntrack 耗尽,关键不是“加规则”,而是**在连接跟踪发生前就切断它**——只有 raw 表的 PREROUTING 和 OUTPUT 链能做到这点,其他表都太晚。
为什么必须用 raw 表,而不是 filter 或 nat
conntrack 模块在数据包进入 Netfilter 流程的最早阶段就被触发。raw 表是唯一位于该阶段之前的表:
- PREROUTING 链在路由决策和 conntrack 初始化前执行,-j NOTRACK 可让匹配包直接跳过状态记录
- filter 表的 INPUT/ FORWARD 链生效时,conntrack 条目早已创建;此时 -j DROP 只是“建完再删”,仍消耗内存和 CPU
- nat 表(如 DNAT)会强制激活 conntrack,哪怕你前面写了 ACCEPT,也无法绕过
哪些流量适合 NOTRACK —— 安全与性能的交界点
NOTRACK 不是万能加速开关,只适用于明确无状态、可信、且不依赖连接跟踪机制的流量:
- 本地回环通信:iptables -t raw -A PREROUTING -i lo -j NOTRACK
- 已知可信监控流量(如 Zabbix Agent 端口):iptables -t raw -A PREROUTING -p tcp --dport 10050 -s 10.0.20.0/24 -j NOTRACK
- UDP 协议响应类流量(DNS/NTP):iptables -t raw -A PREROUTING -p udp --sport 53 -m state --state ESTABLISHED -j NOTRACK(注意:仅限响应方向,需配合 OUTPUT 链)
- 高吞吐但无状态的入口端口(如 CDN 回源 UDP 流):iptables -t raw -A PREROUTING -p udp --dport 443 -s 203.0.113.0/24 -j NOTRACK
⚠️ 禁止对公网入向 TCP 新连接(如 --dport 80 --state NEW)、未过滤的 UDP Flood 目标端口、或任何需要 NAT 的流量启用 NOTRACK。
NOTRACK 后必须做的事:显式放行/丢弃 + 规则重写
NOTRACK 不等于放行,也不等于丢弃,它只是“不记账”。后续 filter 表仍按默认策略处理,因此必须补上明确动作:
- 先打标记:iptables -t raw -A PREROUTING -p udp --dport 53 -j NOTRACK
- 再放行(否则会被默认 DROP):iptables -A INPUT -p udp --dport 53 -j ACCEPT
- 禁用基于状态的规则:所有 -m conntrack --ctstate ESTABLISHED 规则对 NOTRACK 流量失效,应改用无状态方式控制,例如:
• 限速:iptables -A INPUT -p tcp --dport 80 -m limit --limit 100/sec -j ACCEPT
• IP 级控频:iptables -A INPUT -p tcp --dport 80 -m hashlimit --hashlimit-above 5/sec --hashlimit-name http_perip -j DROP
配套调优:让 bypass 更彻底、更可持续
单靠 NOTRACK 不足以一劳永逸,还需同步优化 conntrack 底层行为:
- 临时调大上限(应急):echo 1048576 > /proc/sys/net/nf_conntrack_max
- 永久生效(写入 /etc/sysctl.conf):net.nf_conntrack_max = 1048576
- 加快 TIME_WAIT 回收:net.netfilter.nf_conntrack_tcp_timeout_time_wait = 60
- 缓解 TCP 状态误判:net.netfilter.nf_conntrack_tcp_be_liberal = 1
- 验证效果:watch -n1 'cat /proc/sys/net/nf_conntrack_count',确认数值明显低于上限










