Skip to content

表与链

表是 nftables 规则集中的顶级容器;它们包含链、集合、映射、流表和有状态对象。

1 配置表

Table 是指没有特定语义的链容器,因此,您的规则集至少有一个表。

family 表类型之一:IP、ARP、IP6、bridge、inet、netdev。它默认为 ip。

family决定了要处理的数据包的类型。对于每个family类型,内核在数据包处理路径的特定阶段包含所谓的钩子,如果存在这些钩子的规则,这些钩子将调用 nftables。地址

地址族说明 [iptables工具]
ipIPv4 地址族 [iptables]
ip6IPv6 地址族 [ip6tables]
inet同时管理 IPv4、IPv6 地址族 [iptables、ip6tables]
arpARP地址族,处理IPv4 ARP报文 [arptables]
bridge桥接地址族,处理遍历桥接设备的数据包 [ebtables]
netdevNetdev 地址系列,处理入口和出口上的数据包 [新增]

IPv4/IPv6/Inet 地址族钩子

HookDescription
prerouting所有进入系统的数据包都由预路由钩子处理。它在路由过程之前调用,用于早期过滤或更改影响路由的数据包属性。
input传递到本地系统的数据包由输入钩子处理。
forward转发到不同主机的数据包由转发挂钩处理。
output本地进程发送的数据包由输出钩子处理。
postrouting离开系统的所有数据包都由路由后钩子处理。
ingress所有进入系统的数据包都由此钩子处理。它在第 3 层协议处理程序之前调用,因此在预路由钩子之前调用,可用于过滤和监管。Ingress 仅适用于 Inet 系列(从 Linux 内核 5.10 开始)。

ARP地址族钩子

网桥地址系列处理通过网桥设备的以太网数据包。

支持的钩子列表与上述 IPv4/IPv6/Inet 地址系列相同。

ARP地址族钩子

HookDescription
input传递到本地系统的数据包由输入钩子处理。
output本地系统发送的数据包由输出钩子处理。

NETDEV 地址族hook

HookDescription
ingress所有进入系统的数据包都由此钩子处理。它在网络分流(即 tcpdump)之后、tc 入口之后和第 3 层协议处理程序之前调用,可用于早期过滤和监管。
egress离开系统的所有数据包都由此钩子处理。它在第 3 层协议处理程序之后和 tc 出口之前调用。它可用于后期过滤和管制。

格式:

shell
{add | create} table [family] table [ {comment comment ;}]
list tables [family] [table]
delete table [family] handle handle # 删除表内指定规则
destroy table [family] handle handle # 销毁表内指定规则
delete table [family] table # 删除表
flush table [family] table # 清空表

提示

family:不指定默认为 ip

add | create 区别:如果创建的表已存在,add会跳过本次操作并且不会报错,create会返回一个错误信息

delete | destroy: 删除指定的表,destroy 表不存在,不会失败

1.1 创建表

nft add|create table 族类型 表名

shell
[root@localhost ~]# nft add table inet test
[root@localhost ~]# nft create table inet test
Error: Could not process rule: File exists
create table inet test
                  ^^^^
[root@localhost ~]# nft create table inet test5
[root@localhost ~]# nft add table inet test5
[root@localhost ~]#

根据创建结果可知 add对于已存在的表不会报错,而create 则会有一个错误提示

1.2 查看表

nft list tables [<族类型>]

nft [-n] [-a] list table [<family>] <name>

-n 显示使用数字格式名称的地址和其他信息。

-a 参数用于显示每个规则的数字标识符

shell
[root@localhost ~]# nft list tables
table inet test
table ip test3
table inet test5
[root@localhost ~]# nft list tables inet
table inet test
table inet test5
[root@localhost ~]#

1.3 查看指定表中所有规则

nft list table 族类型 表名

shell
[root@localhost ~]# nft list table inet test
table inet test {
	chain test2 {
		type filter hook input priority filter; policy accept;
		ip saddr 192.168.1.25 accept #
	}

	chain test1 {
		comment "测试插入"
		type filter hook input priority filter; policy accept;
	}
}
[root@localhost ~]#

1.4 刷新表/清空表

清空表内所有的规则,而不会删除chain:nft flush table 族类型 表名

shell
[root@localhost ~]# nft flush table inet test
[root@localhost ~]# 
[root@localhost ~]# nft list table inet test
table inet test {
	chain test2 {
		type filter hook input priority filter; policy accept;
		ip saddr 192.168.1.25 accept #
	}

	chain test1 {
		comment "测试插入"
		type filter hook input priority filter; policy accept;
	}
}
[root@localhost ~]#

1.5 删除表

nft delete table [族类型] 表名

shell
[root@localhost ~]# nft list tables
table inet test
table inet test5
table ip test2
[root@localhost ~]# nft delete table test2
[root@localhost ~]# nft delete table test5
Error: No such file or directory; did you mean table ‘test5’ in family inet?
delete table test5
             ^^^^^
[root@localhost ~]# nft delete table inet  test5
[root@localhost ~]#

有上面的执行结果可知,当族类型是 ip时是可以省略的,其他的类型不能省略

1.6 禁用表

禁用表 nft add table inet <table> '{ flags dormant; }'

解除禁用 nft add table inet <table>

2. 配置链

链的用途是包含#规则。与 iptables 中的链不同,nftables 中没有内置链。这意味着,如果没有链在网络过滤器框架中使用任何类型或钩子,则与 iptables 不同,nftables 将不会触及流经这些链的数据包。

您需要使用您选择的名称显式创建一个基础链,并将其附加到适当的 Netfilter 钩子。这允许非常灵活的配置,而不会减慢 Netfilter 使用规则集不需要的内置链的速度。

基本链:基础链是那些注册到 Netfilter 钩子中的链,即这些链可以看到流经您的 Linux TCP/IP堆栈的数据包。

常规链:为了更好地组织,可以使用常规链作为跳转目标。

2.1 基础链类型

TypeFamiliesHooksDescription
filterallall过滤数据
natip, ip6, inetprerouting, input, output, postrouting这种类型的链根据 conntrack 条目执行本地地址转换。只有连接的第一个数据包才能真正遍历此链 - 其规则通常定义创建的 conntrack 条目的详细信息(例如 NAT 语句)。
routeip, ip6,inetoutput如果数据包已遍历此类型的链并即将被接受,则如果 IP 报头的相关部分已更改,则将执行新的路由查找。这允许例如在nftables中实现策略路由选择器。

除了上述特殊情况(例如,nat 类型不支持正向钩子或路由类型仅支持输出钩子)外,还有三个特殊情况:

  • netdev 系列仅支持两种组合,即ingress hookfilter类型和egress hookfilter类型。该系列中的基础链还要求存在设备参数,因为它们仅存在于每个接口上。

  • arp 系列仅支持inputoutput 钩子,两者都位于filter类型的链中。

  • inet 系列还支持 ingress hook(从 Linux kernel 5.10 开始),用于在与 netdev ingress hook 相同的位置过滤 IPv4 和 IPv6 数据包。

2.2 创建链

格式:

基础链:nft add chain [<family>] <table_name> <chain_name> { type <type> hook <hook> priority <value> \; [policy <policy> \;] [comment \"text comment\" \;] }

常规链:nft add chain [<family>] <table_name> <chain_name>

可以看到 基础链跟常规链的最大的区别就是在于 没有后面括号指定的对象

基础链必须填写 type、 hook、priority,type跟hook之前已经介绍过了,接下来重点说明一下priority优先级

priority: 优先级是从小到大顺序依次执行,但如果同一钩子位置的具有相同优先级的基础链的则无法预知执行顺序,所以建议设计同一钩子优先级要慎重

预定义标准优先级变量

NameValueFamiliesHooks
raw-300ip, ip6, inetall
mangle-150ip, ip6, inetall
dstnat-100ip, ip6, inetprerouting
filter0ip, ip6, inet, arp, netdevall
security50ip, ip6, inetall
srcnat100ip, ip6, inetpostrouting

bridge family

NameValueHooks
dstnat-300prerouting
filter-200all
out100output
srcnat300postrouting

policy: 从 nftables 0.5 开始,基础链还允许人们设置链的默认策略,即在包含的规则中未明确accept或drop的数据包会发生什么情况。

​ 支持的策略值为 accept (默认值) 或 drop

创建基础链

shell
[root@localhost ~]# nft add table inet test
[root@localhost ~]# nft add chain inet test chain1 '{type filter hook input priority 0;comment "基础链";policy accept; }'
[root@localhost ~]# 
[root@localhost ~]# nft -a list table inet test
table inet test { # handle 21
	chain chain1 { # handle 1
		comment "基础链"
		type filter hook input priority filter; policy accept;
	}
}
[root@localhost ~]#

创建常规链

shell
[root@localhost ~]# nft add chain inet  test chain2 '{comment "常规链";}'
[root@localhost ~]# nft -a list table inet test
table inet test { # handle 21
	chain chain1 { # handle 1
		comment "基础链"
		type filter hook input priority filter; policy accept;
	}

	chain chain2 { # handle 2
		comment "常规链"
	}
}
[root@localhost ~]#

在入口钩上添加链条时,必须指定将连接链的设备:

nft 'add chain netdev foo dev0filter { type filter hook ingress device eth0 priority 0 ; }'

shell
[root@localhost ~]# nmcli dev
DEVICE  TYPE      STATE      CONNECTION 
ens33   ethernet  connected  ens33      
lo      loopback  unmanaged  --         
[root@localhost ~]# nft add chain inet test chain5 '{type filter hook ingress device eth0 priority 0;}'
Error: Could not process rule: No such file or directory
add chain inet test chain5 {type filter hook ingress device eth0 priority 0;}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[root@localhost ~]# nft add chain inet test chain5 '{type filter hook ingress device ens33 priority 0;}'
[root@localhost ~]# nft -a -n list table inet test
table inet test { # handle 21
	chain chain1 { # handle 1
		comment "常规链"
		type filter hook input priority 0; policy accept;
	}

	chain chain2 { # handle 2
		comment "常规链"
	}

	chain chain3 { # handle 3
		type filter hook input priority -300; policy accept;
	}

	chain chain4 { # handle 4
		type filter hook input priority 110; policy accept;
	}

	chain chain5 { # handle 5
		type filter hook ingress device "ens33" priority 0; policy accept;
	}
}
[root@localhost ~]#

2.3 修改链

修改创建链的规则,实际测试 只能修改policy

nft chain [<family>] <table_name> <chain_name> {[policy <policy> \;]}

2.4 清空链

清空链里面的规则

其实清空链与清空表,规则集的命令是一致的,只是后面跟的参数不一样罢了

nft flush chain ['family] <table> <chain>

2.5 重命名链

rename chain [family] <table> <chain> <newname>

shell
[root@localhost ~]# nft rename chain inet test chain3 aaaa
[root@localhost ~]# nft -a -n list table inet test
table inet test { # handle 21
	chain chain1 { # handle 1
		comment "常规链"
		type filter hook input priority 0; policy accept;
	}

	chain chain2 { # handle 2
		comment "常规链"
	}

	chain aaaa { # handle 3
		type filter hook input priority -300; policy accept;
	}

	chain chain4 { # handle 4
		type filter hook input priority 110; policy accept;
	}

	chain chain5 { # handle 5
		type filter hook ingress device "ens33" priority 0; policy accept;
	}
}
[root@localhost ~]#

2.6 删除链

nft delete chain ['family] <table> <chain>

nft delete chain [family] table handle handle