iptables 根据来源将数据包转发到两个网关之一

iptables 根据来源将数据包转发到两个网关之一

假设安装如下:

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

相关内容