https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Meta
iifname
(名称之外的字符串)和iif
推荐的之间有什么区别吗?
答案1
iif
查找并比较收到的数据包的接口索引,而iifname
与接口名称进行字符串比较。两者都有优点和缺点。
使用更少的资源也是如此iif
,因为接口索引是数据包中已存储简单数字遍历网络堆栈和 nftables,因此可以立即进行比较。但它的缺点是,如果删除了接口(很可能重新创建,但索引值较新),则 nftables 中的相应规则将不再匹配。唯一保证始终匹配的接口索引是环回接口(默认命名lo
):它始终是命名空间中第一个创建的接口,不能被删除(也不能再次添加),因此其索引值始终为1
。
iifname
另一方面,就像 iptables 一样,--in-interface
将字符串与当前接口的名称进行比较。这会使用更多资源,但允许预先为不存在的接口创建具有确定性名称的规则,这iif
并不容易。iifname
也可以进行通配符匹配,例如,在 中iifname "ppp*"
,这iif
无法做到,并且在经常创建和删除接口时会很方便,但要保持命名约定(例如以ppp
PPP 链接开头)。
示例(使用 nftables 0.9.2):
$ unshare -r -n
# ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# nft add table ip filter
# nft add chain ip filter input '{ type filter hook input priority 0; policy accept; }'
# nft add rule ip filter input iif lo counter
# nft add rule ip filter input iif dummy0 counter
Error: Interface does not exist
add rule ip filter input iif dummy0 counter
^^^^^^
# nft add rule ip filter input iifname dummy0 counter
# ip link add name dummy0 type dummy
# ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 4a:09:68:3a:34:91 brd ff:ff:ff:ff:ff:ff
# nft add rule ip filter input iif dummy0 counter
# nft list ruleset
table ip filter {
chain input {
type filter hook input priority filter; policy accept;
iif "lo" counter packets 0 bytes 0
iifname "dummy0" counter packets 0 bytes 0
iif "dummy0" counter packets 0 bytes 0
}
}
# ip link delete dev dummy0
# nft list ruleset
table ip filter {
chain input {
type filter hook input priority filter; policy accept;
iif "lo" counter packets 0 bytes 0
iifname "dummy0" counter packets 0 bytes 0
iif 2 counter packets 0 bytes 0
}
}
接口消失后,会显示其索引值。同样,在添加规则时,甚至可以提前使用索引值:
# nft add rule ip filter input iif 3 counter
# nft list ruleset
table ip filter {
chain input {
type filter hook input priority filter; policy accept;
iif "lo" counter packets 0 bytes 0
iifname "dummy0" counter packets 0 bytes 0
iif 2 counter packets 0 bytes 0
iif 3 counter packets 0 bytes 0
}
}
# ip link add name dummy4 type dummy
# ip link add name dummy0 type dummy
# nft list ruleset
table ip filter {
chain input {
type filter hook input priority filter; policy accept;
iif "lo" counter packets 0 bytes 0
iifname "dummy0" counter packets 0 bytes 0
iif 2 counter packets 0 bytes 0
iif "dummy4" counter packets 0 bytes 0
}
}
由于接口索引值不会在命名空间内循环使用,而只会增加,因此有关索引 2 的规则“丢失”(它再也没有机会匹配)。下一个创建的接口,假人4被分配了索引 3,现在解析dummy4
为规则集。虚拟0 收到索引值 4,该值未在任何iif
规则中引用,但仍会与iifname
规则匹配。
有什么推荐的?
我的建议:
您应该使用iif
“稳定”接口,这些接口一旦创建就不会改变,比如启动时可用的物理以太网接口,在应用规则之前(如果使用较新的物理接口稳定命名约定,即使枚举顺序发生变化也不会改变),当然洛接口。示例中未显示,但您仍然可以使用 匹配接口列表iif
,例如iif { lo, dummy4 }
。因此,您仍然可以使用单个iif
语句匹配多个接口。
您应该使用iifname
在启动时(以及在创建规则时)未知但预计稍后出现的动态接口,或者在使用通配符匹配时使用命名约定来匹配一组接口。
不太为人所知,为了优化,您可以为每个新创建的接口分配一个组(例如使用ip link set dev interface group 99
),而不是使用通配符,然后用iifgroup
而不是iifname
+ 通配符匹配接口组。但这需要一些额外的机制来对新创建的接口进行分组标记。
您还可以使用界面命名集,从而保留使用和的通用规则iif
并iifname
更改命名集的内容,而不是规则本身。请注意,之前的 wiki 链接没有提到在集合中使用接口,但它根本不是最新的。有关此问题的更多信息,请参阅我的 UL SE 回答:如何在 nftables 中创建一组命名的字符串(用于接口名称)?。
答案2
这不是一个答案,只是对上一个答案。(我的坏名声不允许我发表评论。)
但这需要一些额外的机制来对新创建的接口进行分组标记。
我曾经systemd-networkd
这样做过^^^。它有一个[Link]
部分,您可以在其中为每个接口设置接口组。(这是从文件[Link]
中读取的部分,而不是从文件中读取的部分。).network
systemd-networkd
[Link]
.link
systemd-udevd
因此,我会在/etc/systemd/network/something.network
...中设置类似这样的内容。
[Match]
MACAddress=my:in:te:rf:ac:e0
...
[Link]
Group=99
...
...然后ip link show group 99
可用于检查接口是否(确实)标记正确。(没有组的接口位于组中0
。)(还ip link show
打印组号。)
这使得在 中使用iifgroup
和成为可能。oifgroup
nftables.conf