`iptables-restore` 不保留自定义链

`iptables-restore` 不保留自定义链

我在 Slackware 14.2 上使用iptables v1.6.0。我有一些使用自定义链的 iptables 过滤规则。示例输出 iptables-save可能看起来像

*filter
:INPUT DROP - [0:0]
:FORWARD DROP - [0:0]
:OUTPUT DROP - [0:0]
:custom_chain - [0:0]
-A INPUT -j custom_chain
-A OUTPUT -j ACCEPT
-A custom_chain -j ACCEPT
COMMIT

根据iptables-restore-n选项的手册页,应该保留当前规则集不变,只附加新规则。

-n, --noflush
    don't flush the previous contents of the table.  If  not
    specified,both commands flush (delete) all previous contents
    of the respective table.

但是,如果我尝试添加类似

# cat new_rules
*filter
:INPUT DROP - [0:0]
:FORWARD DROP - [0:0]
:OUTPUT DROP - [0:0]
:custom_chain - [0:0]
:new_chain - [0:0]
-A new_chain -j DROP
COMMIT

通过使用iptables-restore选项-n并检查规则集iptables-save

# iptables-restore -n < new_rules
# iptables-save
*filter
:INPUT DROP - [0:0]
:FORWARD DROP - [0:0]
:OUTPUT DROP - [0:0]
:custom_chain - [0:0]
:new_chain - [0:0]
-A INPUT -j custom_chain
-A OUTPUT -j ACCEPT
-A new_chain -j DROP
COMMIT

那么默认链保持不变,但自定义链会被清除,尽管有这个-n选项。有没有办法保留旧的自定义链?如果这不是一个错误,那么这种行为背后的原因是什么?

更新

进一步的调查显示,只有文件中明确提及自定义链时,才会刷新自定义链new_rules。但是,这并不能解决问题,因为仍然无法将规则附加到预先存在的自定义链中。iptables-restore -n < new_rules仍会刷新并丢失该自定义链中所有先前的规则,从而只留下应该附加的一条规则。

答案1

我遇到了同样的错误。https://git.netfilter.org/iptables/tree/iptables/ip6tables-restore.c?id=577b7e20c2af1e6ea2bbe72e0c01802334fa4069

看来航海是正确的

            if (ops->builtin(chain, handle) <= 0) {
            if (noflush && ops->is_chain(chain, handle)) {
                DEBUGP("Flushing existing user defined chain '%s'\n", chain);
                if (!ops->flush_entries(chain, handle))
                    xtables_error(PARAMETER_PROBLEM,
                           "error flushing chain "
                           "'%s':%s\n", chain,
                           strerror(errno));

由于这不是内置链并且 noflush 为 1,因此 iptables-restore 将刷新自定义表。

答案2

首先:您不应该像这里尝试的那样使用 iptables-restore,肯定有更好、更安全、更优雅的解决方案。也许可以参考 grawity 的建议,使用 ipset,或者使用可以删除的特定链。

我没有看到任何地方有 bug。

只需考虑:“链创建”定义。使用-n此链不会被破坏,因此无需再次定义它。如果它没有被重新定义,它就不会连同其内容一起被删除。

因此,为了保留旧的 custom_chain,请尝试将其作为 new_rules 文件:

*filter
:INPUT DROP - [0:0]
:FORWARD DROP - [0:0]
:OUTPUT DROP - [0:0]
:new_chain - [0:0]
-A new_chain -j DROP
-A custom_chain -j DROP
COMMIT

当您有了初始规则并应用新规则时的结果:

# iptables-restore -n < new_rules
# iptables-save
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:custom_chain - [0:0]
:new_chain - [0:0]
-A INPUT -j custom_chain
-A OUTPUT -j ACCEPT
-A custom_chain -j ACCEPT
-A custom_chain -j DROP
-A new_chain -j DROP
COMMIT

custom_chain 添加了更多内容并且保留了以前的内容:这就是您想要的。

当然,现在您不能单独使用 new_rules 文件(没有-n),您会收到错误,因为custom_chain未定义。

您甚至可以将使用的规则分割-n成一个文件,其中一个规则实际上会覆盖现有的链,而另一个规则则不会覆盖现有的链,如果它更易于管理的话(但同样......不要这样做)。

新规则1:

*filter
:new_chain - [0:0]
-A new_chain -j DROP
COMMIT

新规则2:

*filter
-A custom_chain -j DROP
COMMIT

在上一个 new_rules 之后应用 both(使用-nboth)将得到:

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:custom_chain - [0:0]
:new_chain - [0:0]
-A INPUT -j custom_chain
-A OUTPUT -j ACCEPT
-A custom_chain -j ACCEPT
-A custom_chain -j DROP
-A custom_chain -j DROP
-A new_chain -j DROP
COMMIT

但与此相反,也许直接使用普通的旧 iptables 命令是更好的选择。

相关内容