我的机器上有大约 20 个 VPS(在本地 IP 上运行),我在这些 VPS 上使用 iptables 重定向某些端口,如下所示:
iptables -t nat -A PREROUTING -p tcp -d %hostIP% --dport %real_port% -i eth0 -j DNAT --to-destination %vps_local_ip%":%vps_destination_port%
为了刷新(创建或删除新的 vps),我必须运行 2000 个 iptables 命令,首先删除所有规则,然后再次插入它们,有时会跳过一些命令,因为 iptables 无法快速处理它,添加一个间隔不是一个选项,因为我需要快速完成这些命令。
对于这个问题有更好的解决方案吗?
答案1
我认为没有理由在一台 VPS 发生更改时重置所有规则。除非你的意思是每个 VPS 2000 个命令,但在这种情况下我会假设你做错了什么。
一般来说,我建议每个 VPS 有两条链,一条是活动链,一条是非活动链。如果您确实需要在两个命令之间等待,iptables
那么就在配置非活动链时执行此操作。完成此操作后,您可以将主链中的引用从活动链更改为非活动链(可能PREROUTING
)。
如果您使用许多iptables
命令来检查哪个 VPS 是目标,那么您可以开始使用,ipset
以便通过单个命令完成此操作。
例子
您为所有活动链和所有非活动链创建两个链。这允许在没有竞争条件的情况下进行更改。
iptables -t nat -I PREROUTING 1 -j chaingroup_a
iptables -t nat -A chaingroup_a -j vps_1a
iptables -t nat -A chaingroup_a -j vps_2a
iptables -t nat -A chaingroup_a -j vps_3a
iptables -t nat -A chaingroup_a -j ACCEPT # stop applying rules
iptables -t nat -A vps_1a -d 1.2.3.4 -p tcp --dport 42 -j DNAT --to-destination 10.1.2.3:4242
如果要更改配置,则重置非活动链并配置它们:
iptables -t nat -F chaingroup_b
iptables -t nat -F vps_1b
iptables -t nat -F vps_2b
iptables -t nat -F vps_3b
iptables -t nat -A chaingroup_b -j vps_1b
iptables -t nat -A chaingroup_b -j vps_2b
iptables -t nat -A chaingroup_b -j vps_3b
iptables -t nat -A chaingroup_b -j ACCEPT # stop applying rules
iptables -t nat -A vps_1a -d 1.2.3.4 -p tcp --dport 4321 -j DNAT --to-destination 10.1.2.3:12345
准备工作完成后,将非活动链组设为活动链组:
iptables -t nat -I PREROUTING 1 -j chaingroup_b
由于-j ACCEPT
末尾chaingroup_b
仍然存在的内容chaingroup_a
被忽略。但无论如何你都应该删除它,以防止PREROUTING
每次更改都导致增长:
iptables -t nat -D PREROUTING 2
答案2
事实上 iptables 可以足够快地做到这一点,我已经测试了近 1900 条规则。您所需要的只是在列表文件中跟踪 ip:ports,然后编写一个脚本,例如如下所示的 bash 脚本,并从该文件重新加载 ip:port
我假设文件中的每一行类似于 realport:vps-ip:port
#/bin/bash
HOST=100.200.100.200 # your public address
LIST=/path/to/file
iptables -t nat -F
cat "$LIST" | while read line
do
realport=`echo $line|cut -f1 -d:`
vpsip=`echo $line|cut -f2 -d:`
port=`echo $line|cut -f3 -d:`
iptables -t nat -A PREROUTING -p tcp -d $HOST --dport $realport -i eth0 -j DNAT --to-destination $vpsip:$port
done
iptables save
这样你只需要处理这个列表。您还可以使用其他格式代替 realport:vps-ip:port,例如以逗号分隔。然后将 -d: 更改为 -d 或其他。