我有一个网络网关系统,使用 iptables 来允许/拒绝往返内部网络的流量。我必须iptables
根据内部网络中实体的要求手动添加和删除规则,包括对其流量进行 NAT。内部网络上的受信任实体可以根据需要请求添加和删除规则。最终结果是和表中的一堆规则nat
,filter
包括POSTROUTING
带有目标的规则SNAT
,将源 IP 设置为网关系统的 IP,以及其他表中将网关外部 IP 地址设置为的规则dst
。
我希望能够动态设置网关系统的 IP。这当然会对 TCP 会话等造成破坏性后果,但我们先不考虑这一点。系统使用其他机制来处理这些问题。
问题是防火墙表中未知数量的规则仍然引用这个旧的源 IP 地址。
有没有办法轻松地更改所有这些规则以使用新的 IP 地址而不是旧的 IP 地址?当然,如果您比我更熟悉 bash,我也可以使用 sed/awk 或类似程序接受一些花哨的脚本......
答案1
如果被 SNAT 的流量始终使用出站接口的 IP 地址,请将其替换-j SNAT
为-j MASQUERADE
。这将使用相同的基于 conntrack 的 SNAT,但会自动选择替换源地址。
iptables-save
您可以使用和批量编辑 iptables 规则iptables-restore
:
例如,以交互方式编辑规则集(特别是如果您的编辑器具有良好的搜索和替换功能):
iptables-save > /tmp/rules vim /tmp/rules iptables-restore < /tmp/rules
使用 moreutils 中的‘vipe’:
iptables-save | vipe | iptables-restore
要将一个确切的 IP 地址批量替换为另一个 IP 地址(请记住,
.
在正则表达式中是一个通配符,同时使用它\b
来确保“12.34”不会意外匹配“112.34”):iptables-save | sed 's/\b12\.34\.56\.78\b/12.34.56.99/g' | iptables-restore
但我认为,任何编辑 iptables 规则(包括基于脚本的“iptables -A”设置)是一种不好的方法。相反,保留一个iptables.rules
文件(采用 iptables-save 格式)作为“源”,并始终从该文件加载规则集。然后,您可以开始使用某种形式的宏/模板语言来定义一次 IP 地址并在任何地方引用它 - 类似于通过 Salt/Ansible 部署配置文件时的操作(如果仍有人使用的话)。
例如(实际上不要这样做;它会很快演变成难以控制的事情):
cat /etc/iptables.rules | sed 's/%CUST_IP%/12.34.56.78/g' | iptables-restore
我还建议您看一下 Ferm,它为 iptables 规则实现了另一种语法 —— 总体来说更易读,而且还内置了宏,因此您
@def $cust_ip
只需一次引用它就可以在任何地方引用它。domain (ip ip6) { @def dns_host4 = 10.10.0.53; @def ntp_host4 = 10.10.0.123; table filter { chain FORWARD { daddr ($dns_host4 $ntp_host4) accept; } } table nat { chain PREROUTING { proto (tcp udp) dport 53 DNAT to-destination $dns_host4; proto udp dport 123 DNAT to-destination $ntp_host4; } } }
它的工作原理类似于 iptables-restore – 无需实时更改,只需编辑
/etc/ferm.conf
并运行ferm
即可在完成后重新加载整个规则集。如果 IP 地址发生变化,只需编辑 ferm.conf 中的 @def 宏并重新加载即可。(此外,如果您最终切换到 nftables,最好习惯这一点,因为它的工作原理与 Ferm 几乎相同 - 当然语法有点不同,但它也有 $macros,您可以编辑 /etc/nftables.conf 并一次重新加载整个内容。)
答案2
我建议将 iptables 与 ipset 结合使用。
在 iptables 中,你会有你的规则,然后添加 --match-set setname src
iptables -I PREROUTING -s whatever ... --match-set setname src
iptables -I PREROUTING -s whatever ... --match-set setname dst
然后,为了禁用规则,您需要从名为“setname”的集合中删除 IP 地址。要启用它,您只需向 setname 添加一个 IP 地址。
然后 iptables 保持不变,你只需从 setname 中添加和减去条目
根据需要,每条规则可以有不同的名称。