假设安装如下:
old router 192.168.1.1 with NAT forward of tcp port 80 to 192.168.1.10:80
new router 192.168.1.2 with NAT forward of tcp port 80 to 192.168.1.10:80
web server 192.168.1.10 with default gateway 192.168.1.1
目前,我的服务的 DNS 条目指向旧路由器的外部地址。路由器将流量通过端口转发到 Web 服务器,Web 服务器将答案返回给旧网关。
为了无缝迁移到新的路由器(使用另一个外部 IP),我希望先设置一个新路由器,在两个连接都处于活动状态的情况下测试整个路由器,然后将 DNS IP 更改为新的外部地址。
现在,通过上述设置,旧路由器仍然有效。但发往新路由器的 TCP 连接也会被旧路由器应答,因为旧路由器无法处理这些连接。
我考虑过使用带有伪装的 nat,但这样一来,所有发往新路由器的流量都会看起来像本地流量。这会欺骗基于服务器 ip 的过滤器和日志记录。
现在,我的计划是使用装有 Debian 和 iptables 的辅助 PC 作为临时解决方案:
old router 192.168.1.1 with NAT forward of tcp port 80 to 192.168.1.10:80
new router 192.168.1.2 with NAT forward of tcp port 80 to 192.168.1.20:80
web server 192.168.1.10 with default gateway 192.168.1.20
helper pc 192.168.1.20
辅助 PC 现在负责找到正确的网关:
- 保留由 192.168.1.2 转发的连接状态并将其转发到 192.168.1.10 而不进行修改(我考虑通过它们的原始 mac 地址和 SYN 来识别它们)
- 将跟踪的连接的数据包转发到 192.168.1.2
- 将未跟踪的连接的数据包转发到 192.168.1.1
我在互联网上找到了很多意见,尤其是 serverfault.com (特别是这个),但它们都只涵盖了这个问题的一部分。我猜它需要基于 mac 地址的过滤规则-m mac --mac-source <mac>
、NAT、状态和 rt_tables的组合--set-mark
/ ip rule add fwmark
(--gw 似乎不受 Debian 支持)。
答案1
有两种有效的解决方案,具体取决于场景。
解决方案 1:Web 服务器是 Linux和完全由您控制。
首先,确保/etc/iproute2/rt_tables
包含以下行:
201 gw1
202 gw2
第二,填充表格
ip route add table gw1 default via $GW1_IP dev $ETH metric 100
ip route add table gw2 default via $GW2_IP dev $ETH metric 100
第三,创建两个 iproute2 规则来将处理“分流”到这些自定义表:
ip rule add prio 100 from all fwmark 1 lookup gw1
ip rule add prio 110 from all fwmark 2 lookup gw2
最后,创建一组 iptables 命令来正确标记相应的数据包:
# Make sure mark exists before routing happens
# The first handles incoming packets
-t mangle -A PREROUTING -j CONNMARK --restore-mark
# The second handles outgoing packets
-t mangle -A OUTPUT -j CONNMARK --restore-mark
# Mark packets and save the mark
-t mangle -A INPUT -m mac --mac-source $GW1_MAC -j MARK --set-mark 1
-t mangle -A INPUT -m mac --mac-source $GW2_MAC -j MARK --set-mark 2
-t mangle -A INPUT -j CONNMARK --save-mark
解决方案 2:网络服务器不是Linux 和/或不是完全由你掌控
此解决方案非常与上一个解决方案类似。不同之处在于 iptables 规则集:
# Make sure mark exists before routing happens
-t mangle -A PREROUTING -j CONNMARK --restore-mark
# Mark packets and save the mark
-t mangle -A FORWARD -m mac --mac-source $GW1_MAC -j MARK --set-mark 1
-t mangle -A FORWARD -m mac --mac-source $GW2_MAC -j MARK --set-mark 2
-t mangle -A POSTROUTING -j CONNMARK --save-mark
编辑:修改解决方案 2
仍然与上面相同,但添加:
ip rule add prio 10 to 192.168.1.0/24 lookup main
这确保了发往本地网络(我假设192.168.1.0/24
)的数据包将不会被网关处理。
另外,添加另一条iptables
规则:
-t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10
最后,两个都网关将端口 80 转发到“辅助 PC”;它将节省大量尝试排除“半开”连接故障的麻烦(因为在您当前的计划中,“辅助 PC”只能看到来自 Web 服务器的流量,而看不到双向的流量)。
答案2
如果仅用于本地测试,您可以使用 iptables 的 -s 选项告诉旧路由器,如果流量来自该源 IP,则将其转发到新路由器。然后,新路由器将把您的请求转发到 Web 服务器(基于您提供的配置)。
即使您从设置的外部进行测试,您仍然可以使用 -s 过滤源地址 ip。
例子:
iptables -I PREROUTING -i eth0 -s x.x.x.x -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.1.2:80