学习 nftables 时,容易一开始就陷入命令细节:怎么添加规则、怎么删除 handle、怎么写端口匹配。命令当然重要,但如果先把框架概念理清楚,后面读规则、排查问题和设计规则集都会轻松很多。
可以把 nftables 理解成一套分层结构:
table负责隔离规则空间。family决定规则处理哪类网络协议。chain决定规则在什么阶段执行。rule负责具体匹配和动作。set、map、verdict map用来减少重复规则,让规则集更易维护。
下面按概念逐层说明。
table:规则的命名空间
table 是 nftables 里最外层的规则容器。不同 table 之间相互隔离,因此常见做法是把一组相关规则放进同一个 table。
例如,你可以把过滤规则、NAT 规则或自定义测试规则分开放。这样做的好处是边界清晰:调试时知道自己在改哪一组规则,清理时也不容易误删无关内容。
table 本身不会直接处理数据包。真正参与数据包处理的是 table 里面的 chain 和 rule。
family:规则面对哪类协议
创建 table 时需要选择 family。它决定这张表里的规则适用于哪类数据包。
常见 family 可以这样理解:
ip:只处理 IPv4。ip6:只处理 IPv6。inet:同时处理 IPv4 和 IPv6。arp:处理 ARP。bridge:处理桥接层流量。netdev:更靠近网络设备入口,适合较早阶段处理流量。
日常写普通防火墙规则时,inet 很常用。它可以把 IPv4 和 IPv6 规则放在同一个 table 里,避免维护两套结构相似的规则。
chain:规则执行的位置
chain 是 rule 的列表。数据包进入某个 hook 后,会按顺序经过 chain 里的规则。
chain 大致可以分为两类:
- 基本 chain:挂到内核网络路径的某个 hook 上,会被数据包流程主动调用。
- 常规 chain:不直接挂 hook,需要被其他规则跳转调用。
基本 chain 通常会指定几个关键属性:
type:这条 chain 的用途,例如filter、nat、route。hook:挂在哪个处理阶段,例如prerouting、input、forward、output、postrouting。priority:同一个 hook 上有多条 chain 时,谁先执行。policy:没有规则匹配时的默认动作,常见是accept或drop。
理解 chain 的关键是:规则不是“随便写在哪里都能生效”。同一条规则放在 input、forward 或 output,含义完全不同。
rule:匹配条件加动作
rule 是 nftables 里真正做判断的地方。它通常由两部分组成:
- 匹配条件:例如源 IP、目标 IP、协议、端口、接口、连接状态。
- 动作:例如
accept、drop、reject、counter、jump、return。
规则会按顺序求值。数据包命中某条会终止流程的动作后,就不会继续执行后面的规则。没有命中时,则继续往下走,直到 chain 结束或触发默认策略。
这也是为什么规则顺序很重要:更具体的规则通常要放在更宽泛的规则前面,否则可能永远没有机会被执行。
set:把一组值放在一起
如果有很多 IP、端口或接口需要匹配,直接写多条规则会很难维护。set 用来把一组同类型的值集中管理。
例如,一组可信 IP、一组禁止访问的端口、一组需要限速的地址,都可以放进 set。规则只需要判断某个值是否属于这个 set。
set 的好处是:
- 规则数量更少。
- 可读性更好。
- 后续增删元素更方便。
当规则里出现大量重复条件时,通常就该考虑用 set。
map:把匹配值映射成结果
map 可以理解成“查表”。它根据一个输入值返回一个结果。
例如,不同端口映射到不同标记,不同地址映射到不同处理参数,都可以通过 map 表达。相比写多条 if/else 式规则,map 更集中,也更容易维护。
set 关心的是“是否在集合里”,map 关心的是“这个值对应什么结果”。
verdict map:把匹配值映射成动作
verdict map 是 map 的一个重要用法:它把匹配值映射成 verdict,也就是规则动作。
例如,不同 IP 段可以对应 accept、drop 或跳转到不同 chain。这样可以把很多分支判断压缩到一个结构里。
当规则集开始变复杂时,verdict map 很有用。它能减少重复规则,也能把策略表达得更像一张表,而不是一长串判断语句。
从概念看规则设计
设计 nftables 规则时,可以按这个顺序思考:
- 先确定规则属于哪个
family。 - 再决定放进哪个
table。 - 然后选择合适的
hook和chain。 - 最后编写具体
rule。 - 如果重复条件很多,再引入
set、map或verdict map。
这样写出来的规则会更容易维护,也更容易排错。
小结
nftables 的概念并不复杂,但层级很重要:
- table 管规则边界。
- family 管协议范围。
- chain 管执行位置。
- rule 管匹配和动作。
- set、map、verdict map 管复杂度。
先理解这些概念,再去看具体命令,会比直接背命令更稳。尤其是在规则集变多以后,概念清楚能帮助你判断:问题到底出在协议范围、执行阶段、规则顺序,还是匹配条件本身。