nftables 中的“iifname”和“iif”有什麼區別?
https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Meta
iifname
(名稱之外是字元串)和推薦的內容之間有什麼區別iif
嗎?
iif
查找並比較接收到的數據包的介面索引,同時iifname
與介面名稱進行字元串比較。兩者都有優點和缺點。使用更少的資源也是如此
iif
,因為介面索引是一個簡單的數字,已經儲存在穿過網路堆棧和 nftables 的數據包中,因此可以立即用於比較。但它的缺點是,如果介面被刪除(並且很可能重新創建,但使用更新的索引值),則 nftables 中的相應規則將不再匹配。唯一保證的介面索引始終是回環介面(lo
預設命名):它始終是在命名空間中創建的第一個並且不能刪除(也不能第二次添加),因此它的索引值始終為1
.
iifname
另一方面,就像 iptables’--in-interface
與目前介面的名稱進行字元串比較。這使用了更多資源,但允許預先為不存在的介面創建規則,並使用確定的名稱,這iif
並不容易。iifname
還可以進行萬用字元匹配,例如 iniifname "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 的規則是“失去”的(它再也沒有機會匹配了)。下一個創建的介面dummy4被分配了索引 3,現在解析為
dummy4
規則集中。dummy0 收到索引值 4,在任何iif
規則中都沒有引用,但仍會與iifname
規則匹配。推薦什麼?
我的建議:
在應用規則之前,您應該使用
iif
一旦創建就不會更改的“穩定”介面,例如啟動時可用的物理乙太網介面(如果使用較新的物理介面穩定命名約定,如果列舉順序更改,則不會更改) ,當然還有lo介面。它沒有在範例中顯示,但您仍然可以匹配介面列表iif
,例如iif { lo, dummy4 }
. 所以你仍然可以讓一個iif
語句匹配多個介面。您應該使用
iifname
在啟動時(和創建規則時)未知但預計稍後會出現的動態介面,或者在使用萬用字元匹配時將一組介面與命名約定匹配。不是很清楚,要優化而不是使用萬用字元,您可以為每個新創建的介面分配一個組(例如使用
ip link set dev interface group 99
),然後使用iifgroup
而不是iifname
+ 萬用字元匹配介面組。但這需要一些額外的機制來對新創建的介面進行分組標記。您還可以使用介面命名集,從而保持通用規則使用
iif
和iifname
更改命名集的內容,而不是規則本身。請注意,之前的 wiki 連結沒有說明如何在集合中使用介面,但它根本不是最新的。有關此問題的 UL SE 回答中的更多資訊:How do I create a named set of strings in nftables (for interface names)? .