新建规则不该再用 iptables,因内核3.13起nftables已是官方默认框架,2026年主流发行版将停用iptables原生后端,仅通过兼容层运行,带来性能损耗与行为差异。

为什么现在新建规则不该再用 iptables
内核从 3.13 开始,nftables 就已是官方推荐的默认防火墙框架;2026 年主流发行版(如 RHEL 9、Debian 12+、Ubuntu 22.04 LTS 及更新)已默认停用 iptables 命令的原生后端,转而通过 iptables-compat 层模拟运行——这层翻译不仅引入额外开销,还屏蔽了连接跟踪状态、计数器精度等底层行为差异。
- 线性匹配 vs 哈希/树结构:iptables 的
INPUT链规则是纯顺序遍历,1000 条规则平均要检查 500 次才能命中;nftables 在内核中用高效数据结构索引,同规模下匹配延迟可压到亚微秒级 - UDP 高频场景尤其明显:DNS、QUIC、gRPC-Web 等服务依赖无状态快速放行,iptables 的 conntrack 强制介入常导致 CPU 占用突增,而 nftables 支持
ct state invalid drop+udp dport @allowed_ports这类原子组合,避免状态表膨胀 -
iptables-save导出的规则无法直接复用于 nftables;反向转换要用iptables-translate,但该工具不处理自定义模块(如ipset替代方案需手动重写为set)
nftables 中 inet 表怎么真正实现 IPv4/IPv6 双栈统一
很多人以为加个 inet 地址簇就能“自动兼容双栈”,实际不是:它只表示“此表可同时注册 IPv4 和 IPv6 hook”,但规则本身仍需显式声明协议上下文。漏掉这点,会导致 IPv6 流量静默丢弃。
- 正确写法是:在匹配条件中明确使用
ip或ip6,或用meta nfproto区分;例如tcp dport 22不生效,必须写成ip tcp dport 22或ip6 tcp dport 22 - 若想一条规则覆盖双栈,得用
inet表 + 协议无关匹配,比如:nft add rule inet filter input meta nfproto { ip, ip6 } tcp dport 22 accept - 回环地址也要分开处理:
ip saddr 127.0.0.1和ip6 saddr ::1不能合并;更稳妥的做法是用meta iifname "lo",它不依赖地址族
添加 INPUT 规则时最容易被忽略的三个 hook 依赖
nftables 的基链(base chain)不是“摆设”,它绑定到 netfilter 的具体 hook 点,而某些关键动作(如连接跟踪初始化、raw 表 bypass)只在特定 hook 才生效。跳过它们,ct state established 类规则可能永远不匹配。
本书以培养高级网站建设与管理人才为目标,内容循序渐进,由浅入深,通过大量的实例系统全面地介绍了Linux+PHP+MySQL环境下的网络后台开发技术。本书详尽分析了近30个典型案例。包括计数器、网站流量统计、留言板、论坛系统、聊天室、投票与调查、用户管理、新闻发布系统、广告轮播、购物系统等等,力求让读者通过对案例的学习,轻松掌握PHP和MySQL的编程精要,迅速掌握网络后台开发技巧。 本书适
-
preroutinghook 是 conntrack 初始化必经之路:没在这里注册ct相关 chain,后续所有ct state判断都会返回invalid -
inputhook 处理本机接收包,但若你启用了nf_conntrack_helper(如 FTP、SIP),helper 模块必须在raw表的prerouting中启用,否则 ALG 不工作 - 策略(policy)设置有陷阱:执行
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }后,所有未显式accept的包立即被丢弃——包括你还没来得及加的 SSH 规则。建议先设policy accept,规则就位后再改
从 iptables 迁移时最痛的三处语法断层
翻译工具能搞定 80% 的基础规则,但以下三类必须手改,否则运行时报错或逻辑错位:
-
-m multiport --dports 22,80,443→ 必须转为 nftablesset:nft add set inet filter ssh_http { type inet_service \; },再用tcp dport @ssh_http引用;直接写逗号列表会报错 -
-j LOG --log-prefix "DROP: "→ nftables 没有内置 log prefix,得用log prefix "DROP: " level warn,且level参数不可省略,否则日志不输出 -
-j REJECT --reject-with icmp-host-prohibited→ nftables 中reject是独立表达式,写法是reject with icmp type host-prohibited(注意type关键字和连字符位置)
复杂点在于:nftables 的规则是“原子提交”的,但它的错误提示极其简陋——比如少一个分号、括号不匹配,nft 命令只会报 Error: syntax error,连第几行都懒得说。建议用 nft -f /tmp/rules.nft 分文件调试,别硬敲长命令。









