根本原因是流量未经过预期hook点或规则位置不当致提前终止;需确认路径、family、链挂载及conntrack状态,并用nftrace强制全链路追踪。

为什么 nft monitor trace 看不到你的规则匹配?
根本原因通常是流量没经过你预期的 hook 点,或者规则在链中位置不对导致提前终止。比如你在 input 链写了规则,但包实际走的是 forward(跨主机转发)或被前面某条 drop / accept 终止了,trace 就不会出现后续规则的记录。
实操建议:
- 先确认流量路径:
nft list chain inet filter input和nft list chain inet filter forward都要看,别只盯一个链 - 确保你监听的是正确 family(
inet、ip或ip6),IPv4 流量在ipfamily 下才可能被ip saddr匹配到 -
nft monitor trace默认只显示 kernel 实际执行过的规则,不显示“本该匹配但被跳过”的规则——它不是静态分析器
如何让 trace 输出更可靠?
默认 trace 可能漏掉早期 hook(如 prerouting)或被快速路径绕过(如 conntrack 已建立状态)。关键是要强制走慢路径并覆盖全链路。
实操建议:
- 临时清空 conntrack 表:
conntrack -F,避免 ESTABLISHED 流量被跳过规则直接放行 - 在
prerouting和postrouting链开头加一条无条件meta nftrace set 1,确保所有包都进 trace(注意:仅调试用,勿留在线上) - 用具体协议+端口触发,比如
curl -v http://localhost:8080,比泛泛 ping 更容易命中应用层规则
nft monitor trace 输出里关键字段怎么看?
每条 trace 记录是 JSON 格式,重点看 verdict、rule、chain 和 hook 字段。如果某条规则没出现在 trace 中,不代表它不存在,只代表没执行到它。
常见误读点:
-
"verdict":"jump"后跟着另一个链名,说明控制权移交了,得去对应链里找下一条匹配——别只盯着当前链 -
"rule":null表示 packet 被隐式策略(如policy drop)终结,此时要检查链的默认 policy,不是规则写错了 - 同一包可能出现多次 trace,分别对应不同 hook(如
prerouting → input → postrouting),需按pktid关联
为什么加了规则还是没 trace 到?检查这三件事
最常卡在这三个地方,而不是语法错误:
- 规则所在的链没被挂载到对应 hook:运行
nft list ruleset,确认输出里有类似hook input priority 0;这样的声明,没有就说明链没启用 - 规则用了
ip6 saddr却测试 IPv4 流量,或用了ct state invalid但 conntrack 模块没加载(lsmod | grep nf_conntrack) - 规则加在
inetfamily,但你的 nftables 配置里混用了ip和inet,导致规则实际注册到了另一个 namespace 下
真正难调的从来不是规则语法,而是流量路径和规则注册上下文是否对齐。多看 nft list ruleset -a 带句柄号的输出,再对照 trace 里的 handle 字段,才能确认“这条规则到底有没有被执行”。










