我的 iptables 脚本非常复杂且很长。无法通过手动插入/替换或删除来操作现有的 iptables 配置。我有一个脚本,它只是刷新所有规则和自定义链,然后从头开始重新加载所有内容。这种方法在某种程度上很有效。
我有很多敏感流量,比如封装在 IP 数据包中的 E1 线路和许多其他流量。我不能放弃所有规则并重新插入它们,因为这实在太慢了。如果超过 50 毫秒没有规则,很多东西都会中断。除此之外,一些高吞吐量流量会进入部分恢复的防火墙,最终导致非常糟糕的 conntrack 条目,需要手动干预才能恢复功能。
解决方案是在当前规则末尾附加新规则,然后删除旧规则,理论上这可以形成连续的规则集。问题是,带有自定义链、ipset 等的脚本变得非常复杂且容易出错。
问题是 - 您是否知道任何现有的解决方案(iptables 之上的额外层)可以处理我在此处提到的问题?
提前致谢。
答案1
您是否尝试过使用iptables-restore
命令加载新规则?理论上,这是一个原子操作,可以解决您的大部分问题。但这确实要求您以 使用的格式编写规则iptables-save
。
答案2
如果您使用链条,这应该非常容易。
创建一个或两个链并将所有规则添加到其中。当您需要重新应用规则时,您所要做的就是刷新、删除并重新创建链。
因此,在更新期间,您会在顶部插入一条允许已建立连接的规则(也许您希望这条规则本身始终处于启用状态且永远不会被触及),刷新链,然后将新规则添加到链中。这假设您尽可能使用有状态规则。
答案3
实现此目的的唯一可行的方法是要么重新编写现有脚本以使用 iptables-restore 格式,要么修改现有脚本以将命令转储到 stdout 而不是执行它们,然后生成第二个脚本将其转换为 iptables-restore 格式。
iptables-restore 保证是原子的,因此是进行无缝规则替换的唯一可靠方法。
关于获取 iptables-restore 格式,我对您的建议是在虚拟机上或实时机器上的单独网络命名空间中运行脚本,然后使用 iptables-save 来获取它。
答案4
我建议修改脚本,以便它根据调用方式使用同一链的两个名称之一(使用前缀是有意义的)。因此,链 dropthis 应该改为 set0_dropthis 或 set1_dropthis。
这样,您就可以创建新的规则集而不会干扰流量。之后,默认链将被刷新并以新集为目标重新创建。最佳方法是在每个默认链中只设置一条规则,该规则只会将流量引导到旧集或新集。替换这条规则会很快(甚至安全iptables -A; iptables -D ... 1
)。之后,旧集的链将被刷新并删除。
包装脚本将检测哪个集合当前处于活动状态并使用相应的参数调用真实脚本。