最常见原因是规则挂载到错误hook或priority导致数据包未经过该链;需用nft list ruleset -a确认hook和priority,检查流量是否到达对应hook,并排查更高优先级规则提前终止匹配。

为什么 nftables 规则加载成功却完全不生效
最常见原因是规则挂载到了错误的 hook 或不匹配的 priority,导致数据包根本没经过这条链。nftables 不像 iptables 那样默认把规则塞进固定链里,它要求你显式指定 hook(如 input、forward)和 priority(决定在该 hook 中的执行顺序)。如果 priority 值被其他内核模块(比如 nf_tables 自带的连接跟踪、或第三方模块如 ebpf 程序)抢占,你的规则可能被跳过。
如何确认规则实际挂载在哪个 hook 和 priority
用 nft list ruleset -a 查看所有规则及其 handle,重点关注每条链的定义部分,例如:
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; }
其中 priority 0 表示该链在 input hook 中以优先级 0 插入。注意:priority 是整数,值越小越早执行;负数(如 -200)通常留给 conntrack,正数(如 100)常用于用户自定义策略。
-
priority -200:通常被nf_conntrack占用,做连接状态标记 -
priority -100:常用于nat相关链(如prerouting中的 DNAT) -
priority 0:标准过滤点,适合大多数filter场景 -
priority 100+:较晚执行,可能错过已 drop 的包(比如被前面的drop规则拦截了)
流量不匹配 hook 的典型场景
比如你写了这么一条规则:
nft add rule inet filter output tcp dport 8080 drop
但它对本机发出的 HTTP 请求完全没效果——因为该规则挂在 output hook,而本机访问 localhost:8080 实际走的是 output → loopback 路径,但某些内核版本或配置下,回环流量可能绕过 output hook 的部分子流程。更稳妥的做法是同时检查 output 和 postrouting,或改用 socket 层规则(type route 或 type filter + meta oifname "lo")。
- 本地进程访问
127.0.0.1:优先检查output+oifname "lo" - 容器间通信(如 docker bridge):注意
forwardhook 是否启用,且net.bridge.bridge-nf-call-iptables=1可能干扰 nftables - IPv6 流量误配 IPv4 链:确保链类型是
inet(支持双栈)或显式声明ip6表
调试时容易忽略的三个点
加载规则后不生效,别急着重写语法,先盯住这三处:
- 规则所在链是否绑定了正确的
hook和priority(用nft list chain ... -a确认) - 目标流量是否真的到达该 hook(用
tcpdump -i any port 8080看包是否存在,再结合nft monitor trace抓匹配路径) - 是否有更高优先级的
drop或jump规则提前终止了遍历(比如某条ct state invalid drop在你的规则之前)
hook 和 priority 不是“设了就完事”的配置项,它们决定了你的规则在内核网络栈中的物理位置。错一个值,规则就等于不存在。










