Dan*_*sta 7 networking linux firewall nat ip-forwarding
我有一个“服务器 A”,它附加了多个 IP,如下所示:
eth0:0 1.1.1.1
eth0:1 1.1.1.2
eth0:2 1.1.1.3
Run Code Online (Sandbox Code Playgroud)
我有另一个“服务器 B”,它也附加了多个 IP,如下所示:
eth0:0 2.2.2.1
eth0:1 2.2.2.2
eth0:2 2.2.2.3
Run Code Online (Sandbox Code Playgroud)
现在,我想在“服务器 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
Run Code Online (Sandbox Code Playgroud)
但是如果我把“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
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
编辑 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
Run Code Online (Sandbox Code Playgroud)
然而,现在出现了另一个问题。服务器 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 发出流量。它被我的提供商锁定在路由器中。
小智 6
对您修改后的问题的简短回答是有两种方法可以做到;两者都要求您删除第二个 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% 的信心。
要理解这一点,您需要了解交通流。
现在让我们想象一下如果没有第二个 NAT 会发生什么:
为了让客户端 X 理解数据包,它需要使用与原始数据包的目的地相同的源地址到达客户端 X。
发生这种情况的正常方式是服务器 B 有机会反转预路由 NAT。为此,您需要数据包在以后通过它。目前,您通过更改数据包的源地址来做到这一点,但这会破坏您在修改后的问题中要求的信息。
所以你的答案的第一步是,你不能做第二个 NAT 步骤(路由后 SNAT):在服务器 A 上运行iptables -t nat -D POSTROUTING -j SNAT --to 1.1.1.3。
现在,您将面临逆转第一个 NAT 步骤的挑战。
如果服务器 B 要这样做,您需要服务器 B 来接收数据包。
ip route replace default via C, OR ip route add default via C table a; ip rule add from 2.2.2.3 table a。但是,如果服务器 B 所在位置的路由器不是特别复杂(有状态地检查数据包并拒绝已知流量流中顺序不正确的数据包),那么您有一个稍微简单的,如果超级丑陋的选项:反转 NAT在服务器 B 基于您对服务器 A 所做操作的了解:在服务器 B 上iptables -t nat -I POSTROUTING -j SNAT -s 2.2.2.3 --to 1.1.1.3应该按照建议的示例进行操作。这将使 A 和 B 的 Linux 连接跟踪系统有些困惑(服务器将无法将返回流量与传入流量相关联,因此它们的连接跟踪将使连接处于 UNREPLIED 状态),但它应该可以正常工作到数百个兆位。
在这种情况下最后一次穿过交通流:
由于您希望服务器充当路由器,因此您需要检查一些事项:
首先,必须在内核中启用数据包转发(默认情况下不是):
echo "1" > /proc/sys/net/ipv4/ip_forward
Run Code Online (Sandbox Code Playgroud)
您还需要确保 iptables 允许转发流量(查看您的 FORWARD 链)。
这一规则和 DNAT 规则应该足以使数据包沿一个方向流动。但是,如果您需要 TCP 流,您还必须确保您还具有您提到的 SNAT 规则(否则,远程主机会认为存在问题,因为 2.2.2.3 的服务器正在回复他发送的数据包如 1.1.1.3)。
顺便说一句,出于性能原因,如果您有静态 IP,最好使用 SNAT 代替 MASQUERADE。