登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux nftables counter 如何定位规则命中

来源:17golang原创

时间:2026-09-15 11:07:10 436浏览 收藏

Linux nftables 里想知道“到底哪条规则命中了”,先不要盯着整条链的默认策略。给目标规则显式加上 counter,再用 nft -a list 同时查看匹配条件、packets/byteshandle;如果计数仍然无法解释,才用限定范围的 nftrace 追踪一条测试流量。这样可以把“规则没有匹配”和“数据包根本没到这条链”区分开。

官方地址:https://www.netfilter.org/projects/nftables/

要点速览
  • counter 统计的是它在规则中所在位置之后能看到的 packets 和 bytes,位置放错会让计数范围变大。
  • -a 显示的 handle 用于稳定指认规则;重复列出规则,比凭肉眼猜命中更可靠。
  • nftrace 要只匹配目标报文,并在排查结束后删除临时链,避免输出泛滥和长期跟踪。

先看规则本身:counter 统计的不是整条链

nftables 的 counter 是规则里的一个状态语句,记录 packets 和 bytes。它不会自动覆盖所有规则,必须写在需要观察的规则中,而且同一条规则里语句的位置有意义:前面的匹配条件先把数据包筛掉,后面的 counter 才只统计通过这些条件的报文;如果把 counter 放在匹配条件前面,计数范围就会扩大。

例如,下面的示例只想观察进入本机的 HTTPS 新连接。命令是排查用的示例,不代表已经在本文环境执行。

# 先明确表、链和匹配条件,再让 counter 记录目标流量
sudo nft add rule inet fw input ct state new tcp dport 443 counter accept

# 用数字化输出并显示 handle,便于后续锁定同一条规则
sudo nft -nn -a list chain inet fw input

若规则已有 acceptdrop,不要把 counter 放到终止语句之后。终止语句已经结束当前规则路径,后面的状态语句不会按你预期工作。对于跨多条规则汇总的场景,可以声明 named counter;但定位单条规则时,先看匿名 counter 往往更直观。

用 handle 和计数把命中规则圈出来

第一次查看建议缩小范围,不要直接把整机所有表混在一起:

# 只列出目标链;-n 避免名称翻译干扰比对,-a 显示规则 handle
sudo nft -n -a list chain inet fw input

# 规则数量较多时,用 JSON 保留 family、table、chain 和 expr 字段
sudo nft -j list chain inet fw input
Linux nftables 规则集、input 链、tcp dport 443、counter packets/bytes 与 handle 的静态关系示意图
图1:规则定位示意图,把 nftables 的匹配条件、计数器字段和 handle 放在同一条规则边界中。

接着制造一小段明确属于目标条件的流量,再重复同一条 list 命令。判断重点不是某个绝对数字,而是变化位置:

观察结果更可能的结论
目标规则 packets 和 bytes 都增加报文匹配到该规则,handle 可作为定位证据
上游粗粒度规则增加,目标规则不变已到达该链,但没有满足目标条件,或在前面被终止
整条链计数都不变先检查 family、hook、接口方向和实际路径
规则显示没有 counter该规则没有显式计数器,不能拿它判断命中次数

如果用 named counter 汇总多个端口或多条规则,可单独查看它:

# named counter 的读取对象是 family、table 和 counter 名称
sudo nft list counter inet fw https_hits

计数不变时,用 nftrace 判断数据包走到哪里

counter 只告诉你某个状态点是否被经过,不能完整解释数据包之前经过了哪些链。此时可以临时建立一个优先级合适的 trace chain,并让它只给目标报文设置 meta nftrace set 1。官方 nftables wiki 建议用 nft monitor trace 读取事件;trace id 用来关联同一条报文的多个记录。

# 临时链放在目标 prerouting 链之前;条件可再收窄到目标接口或地址
sudo nft add chain inet fw trace_chain { type filter hook prerouting priority -301; policy accept; }
sudo nft add rule inet fw trace_chain tcp dport 443 meta nftrace set 1

# 在另一个会话观察 trace id、chain、rule 和 verdict
sudo nft monitor trace

# 排查结束立即删除临时链,避免继续产生跟踪事件
sudo nft delete chain inet fw trace_chain
Linux nftables nftrace、trace_chain、input 链、匹配规则、counter 与 verdict 的静态依赖关系示意图
图2:nftrace 关系示意图,展示跟踪开关如何连接到链、规则和最终 verdict。

示意性的关键行通常类似 trace id ... input rule ... counter ... (verdict accept)。它说明的是该报文在这条规则上继续到了什么 verdict,不等同于一份长期审计日志。若输出过多,优先把入口规则的匹配条件收窄;不要为了“看得全”给所有报文打开 trace。

把一次排查收束成可复查清单

最后再做一次前后比对:记录规则的 family、table、chain、handle、匹配条件和计数变化;若用 JSON 解析,则保存对应的 rule expr。确认结果后恢复正式规则,删除 trace_chain。需要清零 named counter 时要意识到 reset 会丢失当前统计;匿名 counter 的 reset 行为还存在不同版本与实现边界,生产环境不要用“清空整套 ruleset 再导回”作为随手操作,因为它可能连其他有状态对象一起影响。

  • 先问方向:报文是 input、output 还是 forward?
  • 再问条件:协议、端口、地址和 ct state 是否与测试流量一致?
  • 最后问状态:counter 是否放在匹配条件之后、终止语句之前?

相关问题

为什么 nft list ruleset 看不到某条规则的计数?

常见原因是规则没有显式写 counter,或者查看的 family/table/chain 不是实际挂载路径。先用 nft -a list ruleset 确认对象边界。

counter 增加能证明数据包最终被放行吗?

不能。它只证明报文经过了 counter 所在状态点;后续规则仍可能 drop、reject 或跳转。要判断最终结论,用受限 nftrace 看 verdict。

什么时候应该使用 named counter?

当多个规则需要共享同一统计口径时使用 named counter;只定位一条规则时,匿名 counter 和 handle 更容易把证据绑定到具体规则。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>