nftables 中“iifname”和“iif”有什么区别?

nftables 中“iifname”和“iif”有什么区别?

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无法做到,并且在经常创建和删除接口时会很方便,但要保持命名约定(例如以pppPPP 链接开头)。

示例(使用 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+ 通配符匹配接口组。但这需要一些额外的机制来对新创建的接口进行分组标记。

您还可以使用界面命名集,从而保留使用和的通用规则iifiifname更改命名集的内容,而不是规则本身。请注意,之前的 wiki 链接没有提到在集合中使用接口,但它根本不是最新的。有关此问题的更多信息,请参阅我的 UL SE 回答:如何在 nftables 中创建一组命名的字符串(用于接口名称)?

答案2

这不是一个答案,只是对上一个答案。(我的坏名声不允许我发表评论。)

但这需要一些额外的机制来对新创建的接口进行分组标记。

我曾经systemd-networkd这样做过^^^。它有一个[Link]部分,您可以在其中为每个接口设置接口组。(这是从文件[Link]中读取的部分,而不是从文件中读取的部分。).networksystemd-networkd[Link].linksystemd-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和成为可能。oifgroupnftables.conf

相关内容