如何将所有流量转发/NAT到一个接口/IP到远程IP?

如何将所有流量转发/NAT到一个接口/IP到远程IP?

我有一个“服务器 A”,它连接了多个 IP,如下所示:

eth0:0 1.1.1.1
eth0:1 1.1.1.2
eth0:2 1.1.1.3

我还有另一个“服务器 B”,它也连接了多个 IP,如下所示:

eth0:0 2.2.2.1
eth0:1 2.2.2.2
eth0:2 2.2.2.3

现在,我想在“服务器 A”上设置 iptables,以将“eth0:2”上的所有传入流量转发/NAT 到“服务器 B”上的 IP 2.2.2.3。

我已经验证“服务器 A”能够通过 IP 2.2.2.3 与“服务器 B”进行“通信”。Ping 和 telnet 打开端口工作正常,并且我已打开转发标志 (net.ipv4.ip_forward=1)

我尝试了多种不同的方法,DNAT、SNAT、MASQUERADE 等,但都无法奏效。

如果我尝试在同一台服务器上的 IP 之间转发流量,此行可以正常工作:

iptables -t nat -A PREROUTING -d 1.1.1.3 -j DNAT --to-destination 1.1.1.2

但是如果我将“1.1.1.2”换成“2.2.2.3”,它就不起作用。

我认为我需要第二个 iptable 规则来解决这个问题。我尝试过以下 POSTROUTING 规则,但没有成功(不是同时尝试):

iptables -t nat -A POSTROUTING -d 2.2.2.3 -j MASQUERADE
iptables -t nat -A POSTROUTING -d 2.2.2.3 -j SNAT --to 1.1.1.3
iptables -t nat -A POSTROUTING -j MASQUERADE

我错过了什么?

编辑1:

我最终通过使用以下命令使其工作:

net.bridge.bridge-nf-call-iptables=0

iptables -t nat -A PREROUTING -d 1.1.1.3 -j DNAT --to-destination 2.2.2.3
iptables -t nat -A POSTROUTING -d 2.2.2.3 -j SNAT --to 1.1.1.3

但是现在又出现了另一个问题。服务器 2.2.2.3 上的所有日志等都显示所有流量现在都来自 1.1.1.3,如 apache 日志、邮件日志等。我认为这是 NAT 的本质。

但是,当我在家用路由器上对运行 Apache 的笔记本电脑进行标准端口转发时,我在日志中看到了原始的“请求者 IP”。那么,路由器是如何做到这一点的?我如何在服务器设置上做同样的事情?

底线是,我想将所有流量从服务器 A(1.1.1.3)转发到服务器 B(2.2.2.3),但我还希望能够看到流量来自服务器 B(2.2.2.3)的哪个位置,即 apache 日志应该显示请求者的原始 IP。

我认为我应该使用 NAT 以外的其他方式来实现这一点,而且这应该是可能的,因为即使是我的简单家用路由器也可以做到这一点。

另外,服务器 A 和服务器 B 所连接的 IP 被锁定到各自的服务器。因此,服务器 A 无法从 IP 2.2.2.3 发送流量。它被我的提供商在路由器中锁定。

答案1

对你修改后的问题的简短回答是,有两种方法可以做到这一点;两者都需要你删除第二个 NAT 步骤(这会破坏你正在寻找的信息)。完成此操作后,你的选择是:

1) 将服务器 A 设置为所讨论流量的服务器 B 的下一跳,这就是它适用于您的路由器的原因。这可以通过将服务器 A 设置为服务器 B 的默认路由来实现,或者使用策略路由或使用一些花哨的 iptables或者使用某种隧道。

2) “手动”在服务器 B 上反转服务器 A 的 NAT,导致流量不对称(一般不建议这样做)。例如iptables -t nat -I POSTROUTING -j SNAT -s 2.2.2.3 --to 1.1.1.3

我对选项 (1) 有 100% 的信心。我对选项 (2) 有 90% 的信心。

要理解这一点,您需要了解流量流。

  1. 客户端 X 向 1.1.1.3 发送数据包。
  2. 服务器 A 在路由前将该数据包的目标 NAT 为 2.2.2.3,然后将流量路由到 2.2.2.3,在路由后将该数据包的源 NAT 为 1.1.1.3,然后将数据包发送到服务器 B。
  3. 服务器 B 在 2.2.2.3 上接收数据包,并根据第二个 NAT 步骤看到源地址为 1.1.1.3。它处理数据包并将回复发送回其源(1.1.1.3)。
  4. 服务器 A 在 1.1.1.3 上接收数据包,反转源 NAT,路由数据包,反转目标 NAT,并将数据包发送回客户端 X。
  5. 客户端 X 收到来自 1.1.1.3 的响应

现在让我们想象一下如果没有第二个 NAT 会发生什么:

  1. 客户端 X 向 1.1.1.3 发送数据包。
  2. 服务器 A 将该数据包的目标 NAT 为 2.2.2.3 预路由,然后将流量路由到 2.2.2.3,但在将数据包发送到服务器 B 时将源地址保留为 X。
  3. 服务器 B 在 2.2.2.3 上接收数据包并看到源地址 X。它处理该数据包并将答复发送回其源 X。
  4. 客户端 X 收到来自 2.2.2.3 的响应并将其丢弃,因为它不知道来自 Adam 的 2.2.2.3!

为了让客户端 X 能够理解该数据包,它需要使用与原始数据包的目的地相同的源地址到达客户端 X。

正常情况下,服务器 B 有机会逆转预路由 NAT。要做到这一点,您需要让数据包稍后再通过它。目前,您可以通过更改数据包的源地址来实现这一点,但这会破坏您在修改后的问题中要求的信息。

所以你答案的第一步是,你不能在服务器 A 上运行第二个 NAT 步骤(后路由 SNAT)iptables -t nat -D POSTROUTING -j SNAT --to 1.1.1.3:。

现在您面临的挑战是逆转第一步 NAT。

如果服务器 B 要执行此操作,则需要服务器 B 接收数据包。

  • 如果服务器 A 在与服务器 B 相同的 LAN 上具有地址 C,则这相对容易。在服务器 B 上:ip route replace default via C,或ip route add default via C table a; ip rule add from 2.2.2.3 table a
  • 否则你就得用隧道做一些奇特的事情。

但是,如果服务器 B 处的路由器不是特别复杂(状态检查数据包并拒绝不符合已知流量顺序的数据包),则您有一个稍微简单(但非常丑陋)的选择:根据您对服务器 A 上所做工作的了解,在服务器 B 上反转 NAT:在服务器 B 上iptables -t nat -I POSTROUTING -j SNAT -s 2.2.2.3 --to 1.1.1.3应该执行建议的示例。这将使 A 和 B 上的 Linux 连接跟踪系统有些困惑(服务器将无法将返回流量与传入流量关联,因此它们的连接跟踪将使连接处于未回复状态),但它应该可以很好地处理数百兆位的大多数流量。

在这种情况下,最后一次穿过交通流:

  1. 客户端 X 向 1.1.1.3 发送数据包。
  2. 服务器 A 将该数据包的目标 NAT 为 2.2.2.3 预路由,然后将流量路由到 2.2.2.3,但在将数据包发送到服务器 B 时将源地址保留为 X。
  3. 服务器 B 在 2.2.2.3 上接收数据包并看到源地址 X。它处理该数据包并将答复路由回其源 X,但在发送之前,会将源地址的后路由 NAT 执行为 1.1.1.3。
  4. 客户端 X 收到声称来自 1.1.1.3 的响应并且很高兴。

答案2

由于您希望服务器充当路由器,因此您需要检查以下几件事:

首先,必须在内核中启用数据包转发(默认情况下不启用):

echo "1" > /proc/sys/net/ipv4/ip_forward

您还需要确保 iptables 允许转发流量(查看您的 FORWARD 链)。

此规则和 DNAT 规则应该足以使数据包单向流动。但是,如果您需要 TCP 流,您还必须确保您还具有您提到的 SNAT 规则(否则,远程主机会认为存在问题,因为位于 2.2.2.3 的服务器正在以 1.1.1.3 的身份回复他发送的数据包)。

顺便说一句,出于性能原因,如果您有静态 IP,最好使用 SNAT 代替 MASQUERADE。

相关内容