最常见原因是规则未提交到内核或table/chain不存在:nft add rule需确保table和chain已预先创建,且命令无语法错误;优先级冲突、firewalld/iptables干扰或模块未加载也会导致规则不显示。

为什么 nft list ruleset 不显示刚添加的规则
最常见原因是规则没真正提交到内核——你可能用了 nft add rule 但漏掉了 flush 或事务未提交,也可能规则被后续同优先级/同链的规则覆盖。nftables 是原子性加载的,临时添加的规则若不在当前活跃 ruleset 中,nft list ruleset 就不会显示。
检查方式很简单:nft -a list ruleset(带句柄)看是否真没加载;再用 nft list chain inet filter input(替换成你的 table/chain)确认该链是否存在、是否为空。
- 确保用的是
nft add rule而非nft insert rule后忘记指定位置,否则可能插到空链末尾但链本身未创建 - 如果从文件加载(
nft -f),确认文件语法无误,且没有flush操作清掉了刚加的规则 - 某些 systemd-nftables 服务会自动 reload,覆盖掉你手动加的规则——检查
systemctl status nftables是否在接管
table 或 chain 不存在导致规则“消失”
nftables 不会自动创建 table 或 chain。如果你直接写 nft add rule ip filter input tcp dport 22 accept,而 ip filter 这个 table 或 input chain 根本没定义过,命令会静默失败(不报错但也不生效)。
验证方法:nft list tables 看 table 是否在;nft list table ip filter 看 chain 是否列出。没看到?那就得先建:
nft add table ip filter
nft add chain ip filter input { type filter hook input priority 0 \; }
注意:priority 必须是整数,不能写成 0 以外的浮点或字符串;花括号里分号要转义(\;),否则 shell 会截断。
优先级(priority)冲突让规则不可见或不生效
同一 hook(如 input)下多个 chain 共享 priority。如果两个 chain 都设为 priority 0,内核按注册顺序执行,后注册的可能“遮住”前面的规则——不是规则丢了,而是它根本没机会匹配。
- 用
nft list chain inet filter input -a查看实际生效的 handle 和 priority 值 - 不同功能建议用不同 priority:filter 类用 0,mangle 类用 -150,nat 类用 -100,避免混用
- priority 相同的 chain,执行顺序取决于它们被
add chain的先后;想控制顺序,就显式 flush + 重载整个 ruleset
规则被其他工具(iptables-legacy、firewalld)覆盖
如果你系统启用了 firewalld 或残留了 iptables-legacy 规则,nftables 和 legacy 内核接口共存时,nft list ruleset 只显示原生 nft 规则,但 netfilter 实际执行路径可能被 legacy 规则截断——看起来像你的规则“没生效”,其实是压根没走到那一步。
快速排查:iptables-save -c 和 ip6tables-save -c 是否输出非空?systemctl is-active firewalld 是否为 active?
- 停用 firewalld:
systemctl stop firewalld && systemctl disable firewalld - 清除 legacy 规则:
iptables -F && iptables -t nat -F && iptables -t mangle -F(同样处理 ip6tables) - 确认模块加载状态:
lsmod | grep nf_tables应存在,而nf_nat_ipv4等 legacy 模块尽量不加载
真正麻烦的从来不是加一条规则,而是搞清它到底在哪一层被吞掉了——优先级、table 生命周期、工具栈混用,三者叠加最容易让人反复怀疑命令敲错了。










