Iptables

nftables 中的“iifname”和“iif”有什麼區別?

  • December 11, 2020

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還可以進行萬用字元匹配,例如 in 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 的規則是“失去”的(它再也沒有機會匹配了)。下一個創建的介面dummy4被分配了索引 3,現在解析為dummy4規則集中。dummy0 收到索引值 4,在任何iif規則中都沒有引用,但仍會與iifname規則匹配。


推薦什麼?

我的建議:

在應用規則之前,您應該使用iif一旦創建就不會更改的“穩定”介面,例如啟動時可用的物理乙太網介面(如果使用較新的物理介面穩定命名約定,如果列舉順序更改,則不會更改) ,當然還有lo介面。它沒有在範例中顯示,但您仍然可以匹配介面列表iif,例如iif { lo, dummy4 }. 所以你仍然可以讓一個iif語句匹配多個介面。

您應該使用iifname在啟動時(和創建規則時)未知但預計稍後會出現的動態介面,或者在使用萬用字元匹配時將一組介面與命名約定匹配。

不是很清楚,要優化而不是使用萬用字元,您可以為每個新創建的介面分配一個組(例如使用ip link set dev interface group 99),然後使用iifgroup而不是iifname+ 萬用字元匹配介面組。但這需要一些額外的機制來對新創建的介面進行分組標記。

您還可以使用介面命名集,從而保持通用規則使用iifiifname更改命名集的內容,而不是規則本身。請注意,之前的 wiki 連結沒有說明如何在集合中使用介面,但它根本不是最新的。有關此問題的 UL SE 回答中的更多資訊:How do I create a named set of strings in nftables (for interface names)? .

引用自:https://serverfault.com/questions/985158