我在 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
看来航海是正确的
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(使用-n
both)将得到:
*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 命令是更好的选择。