如何自动替换 nftables 规则?

Ten*_*ken 1 linux firewall debian nftables

我正在尝试自动替换 nftables 规则。Nftables 的官方 wiki指出-f 是实现此目的的推荐方法。然而,当我nft -f /path/to/new/rules在 Debian Buster 上运行时,新规则会添加到当前规则中,而不是替换它们,最终我会得到一个同时执行两个规则集的系统。

当我尝试通过systemd's重新加载配置时,也会发生同样的事情nftables.service

如何nft在单个原子操作中丢弃当前规则集,同时添加新规则集?

A.B*_*A.B 6

完成的操作nft -f /path/to/new/rules 原子的:这意味着它要么完全完成,要么根本没有完成(即:恢复),并且只有在提交后才会立即影响下一个符合规则的数据包。它不会结束(因为错误),只是完成了一半。因此,如果您之前没有删除之前的规则集,它会按预期运行:它会再次原子地添加规则,如wiki 中原子规则替换的注释中所述:

重复规则:如果您在过滤表flush table filter文件的最开头添加该行,则可以实现与 iptables-restore 所提供的等效的原子规则集替换。内核在一个事务中处理文件中的规则命令,因此基本上新规则的刷新和加载一次性发生。如果您选择不刷新表,那么每次重新加载配置时您都会看到重复的规则。

为此,您必须在同一事务中删除旧规则,然后再重新添加规则集。最简单的(但影响所有nftables,包括iptables-nft如果也使用的话)就是简单地,类似于上面描述的,在你的规则集前面加上/path/to/new/rules

flush ruleset
Run Code Online (Sandbox Code Playgroud)

如果您在不同时间加载不同的表以保持逻辑功能分离(在nftables中,表可以包含任何类型的基本链(对于给定的系列),它不是直接相当于iptables中具有固定集的表可能的链)它变得有点复杂,因为flush ruleset在一个规则文件中会删除其他表(包括iptables-nft规则,如果与nftables一起使用)。那么这应该在表级别完成,例如(但在执行之前请进一步阅读):

delete table inet foo
Run Code Online (Sandbox Code Playgroud)

接下来是对其的重新定义(table inet foo {...)。按原样,这会产生另一个先有鸡还是先有蛋的问题:第一次读取该文件时(例如在启动时),删除操作将失败,因此所有内容都会自动失败,因为该表不存在。由于声明一个已经声明的表的名称被认为是无操作,因此不会失败,最终可以这样做:

table inet foo
delete table inet foo

table inet foo {
[...]
Run Code Online (Sandbox Code Playgroud)
  • 注意 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通过将“管道工”声明保留在实际规则之外来克服这个问题。