如何在同一网络中从一个IP到另一个IP进行端口转发?

sat*_*sat 87 linux iptables port-forwarding

我想NATiptables. 这样,所有到达192.168.12.87和 port的数据包都80将被转发到192.168.12.77port 80

如何用 iptables 做到这一点?

或者

还有其他方法可以实现相同的目标吗?

kri*_*sFR 83

这些规则应该有效,假设它iptables在服务器上运行192.168.12.87

#!/bin/sh

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

iptables -F
iptables -t nat -F
iptables -X

iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.12.77:80
iptables -t nat -A POSTROUTING -p tcp -d 192.168.12.77 --dport 80 -j SNAT --to-source 192.168.12.87
Run Code Online (Sandbox Code Playgroud)

您必须对端口 80 上的传入流量进行 DNAT,但您还需要将流量 SNAT 返回。


替代(和最好的方法恕我直言):

根据您的 Web 服务器是什么(Apache、NGinx),您应该考虑在前端服务器(192.168.12.87)上使用 HTTP 代理:

  • “但您还需要将流量 SNAT 返回。” -> 你救了我的一天。谢谢 (4认同)
  • 很好的问题,很好的答案。另一个有用的用例是,如果您需要临时将所有流量重定向到一个服务,比如鱿鱼,到另一个 ip/端口,以便对原始服务进行一些维护,而无需重新配置所有客户端!非常便利! (2认同)
  • 小心使用此解决方案。我现在完全无法访问我的远程机器。 (2认同)

kas*_*erd 31

一个看似明显iptables -t nat -A PREROUTING -d 192.168.12.87 -p tcp --dport 80 -j DNAT --to-destination 192.168.12.77不起作用的原因是返回数据包将如何路由。

您可以设置规则,使发送到 192.168.12.87 的数据包简单地通过 NAT 转换到 192.168.12.77,但 192.168.12.77 将直接将回复发送回客户端。这些回复不会通过您的 iptables 规则正在执行 NAT 的主机,因此一个方向的数据包被转换,但另一个方向的数据包没有。

有三种方法可以解决这个问题。

  1. 在第一台主机上不仅要做 DNAT,还要做 SNAT,这样返回的流量将通过第一台主机发回。该规则可能看起来像iptables -t NAT -A POSTROUTING -d 192.168.12.77 -p tcp --dport 80 -j SNAT --to-source 192.168.12.87
  2. 从 DSR 负载平衡和 DNAT 数据包的以太网层而不是 IP 层中获取灵感。通过将数据包的目标 MAC 替换为 192.168.12.77 的 MAC 并将其发送到以太网上而不接触 IP 层,那么 192.168.12.77 可以在虚拟接口上配置 192.168.12.87,从而能够终止 TCP 连接使用客户端已知的服务器 IP。
  3. 在第一台主机上使用简单(但不工作)的解决方案。然后通过对返回流量执行 SNAT 来处理第二台主机上的返回数据包。规则可能看起来像iptables -t nat -A OUTPUT -p tcp --sport 80 -j SNAT --to-source 192.168.12.87

这三个解决方案中的每一个都有缺点,所以你需要仔细考虑,如果你真的需要做这个特定的转发。

  1. 使用 SNAT 会丢失客户端 IP,因此主机号 2 会认为所有连接都来自 192.168.12.87。此外,您将通过主机 1 为所有回复数据包使用带宽,这将采用其他方法的更直接路由。
  2. DSR 方法将中断两个节点之间的所有其他通信。DSR 方法仅适用于服务器地址不是任何主机的主要 IP 的情况。每个主机都需要有一个主 IP,它不是 DSR IP。
  3. 在一个主机上使用连接跟踪在一个方向上进行转换,在另一台主机上使用连接跟踪在另一个方向上进行转换是非常丑陋的,并且有多种方式可能会中断。例如,如果任一主机上的 NAT 修改了端口号,则无法重建这些端口号。如果它看到的第一个数据包是 SYN-ACK 而不是 ACK,连接跟踪将正常工作也不是给定的。

在这三种方法中,我认为第一种是最有可能奏效的。因此,如果您不需要知道客户端 IP 地址,那是我推荐的。

您也可以选择完全忘记 NAT,而不尝试在 MAC 或 IP 层解决问题。您可以一直到 HTTP 层并在那里寻找解决方案。在这种情况下,您将找到的解决方案是 HTTP 代理。如果您在 192.168.12.87 上安装了 HTTP 代理并对其进行了适当的配置,您可以让它将请求转发到 192.168.12.77 并将答案转发回来。此外,它可以插入一个 X-Forwarded-For 标头,保留原始客户端 IP。然后需要将 192.168.12.77 上的服务器配置为信任来自 192.168.12.87 的 X-Forwarded-For 标头。

  • @remram 我提到了 `SNAT` 而不是 `MASQUERADE`,因为文档就是这么说的。文档中的确切措辞是:`它应该只用于动态分配的 IP(拨号)连接:如果你有一个静态 IP 地址,你应该使用 SNAT 目标。` (5认同)