如何以原子方式替換 nftables 規則?
我正在嘗試以原子方式替換 nftables 規則。Nftables 的官方 wiki聲明-f 是實現此目標的推薦方法。但是,當我
nft -f /path/to/new/rules
在 Debian Buster 上執行時,新規則會添加到目前規則中,而不是替換它們,我最終會得到一個同時執行兩個規則集的系統。當我嘗試通過
systemd
‘s重新載入配置時,也會發生同樣的事情nftables.service
。我怎樣才能
nft
丟棄目前的規則集,同時在單個原子操作中添加新的規則集?
完成的操作
nft -f /path/to/new/rules
是原子的:這意味著它要麼完全完成,要麼根本沒有完成(即:恢復),並且只會在送出後立即影響下一個符合規則的數據包。它不會只完成一半(因為錯誤)。因此,如果您之前不刪除之前的規則集,它的行為將如預期:它再次原子地添加規則,如wiki中原子規則替換的註釋中所述:重複規則:如果您在過濾表
flush table filter
文件的最開頭添加該行,您將實現等同於 iptables-restore 提供的原子規則集替換。核心在一個事務中處理文件中的規則命令,因此基本上刷新和載入新規則是一次性發生的。如果您選擇不刷新表,那麼每次重新載入配置時都會看到重複的規則。為此,您必須在同一事務中刪除舊規則,然後再添加您的規則集。最簡單的(但會影響所有的nftables,包括iptables- nft如果也使用)是簡單的,類似於上面描述的,在你的規則集前面加上
/path/to/new/rules
:flush ruleset
如果您在不同時間載入不同的表以保持邏輯特徵分離(在nftables中,表可以包含任何類型的基鏈(對於給定的系列),它不是**iptables中具有固定集合的表的直接等價物可能的鏈)它變得有點複雜,因為
flush ruleset
在一個規則文件中會刪除其他表(包括iptables- nft規則,如果與nftables一起使用)。然後這應該在表級別完成,例如(但在做之前請進一步閱讀):delete table inet foo
其次是它的重新定義(
table inet foo {
…)。照原樣,這會產生另一個先有雞還是先有蛋的問題:第一次讀取該文件時,例如在啟動時,刪除操作將失敗,因此由於該表不存在,所有內容都將作為一個整體自動失敗. 由於聲明已經聲明的表名被認為是空操作,因此不會失敗,最後可以這樣做:table inet foo delete table inet foo table inet foo { [...]
- 注意 1:為了在所有情況下都能正常工作,核心 >= 3.18 是必需的,否則最好堅持
flush ruleset
.- 注意 2:上面的 wiki 註釋建議在這種情況下使用,
flush table inet foo
但可能應該避免這種情況,因為如果存在集合,這不會刪除集合中的元素,如果規則集添加了元素,則會再次導致添加而不是替換元素,並且在那裡被改變了。它也不允許重新定義基鏈的類型/鉤子。使用table inet foo
+delete table inet foo
沒有這些缺點。當然如果需要在重載規則時將元素保持在集合中,可以考慮使用flush table inet foo
並適應這種方法的局限性。在所有情況下,使用將目前規則轉儲到規則文件時都應該小心
nft list {ruleset, table inet foo, ...} > /path/to/new/rules
:它不會包含任何刷新或刪除命令,您必須手動將它們添加回來。您可以include
通過將“水管工”語句保持在實際規則之外來克服這個問題。