使用 iptables 进行端口转发

使用 iptables 进行端口转发

我得到了lo( 127.0.0.1) 和eth0( 172.17.0.8)。我想将到达的数据包重定向127.0.0.1:80172.17.42.1:80(路由自eth0)。

我试过

iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.1 -j DNAT --to 172.17.42.1:80

但当我这样做时,curl localhost:80我没有得到任何回应,当我这样做时curl 172.17.42.1:80它就起作用了。

答案1

当你尝试访问本地主机时,你的源地址是 127.0.0.1,目标地址也是。因此,数据包看起来如下所示:

 | SRC        |  DST       |
 | 127.0.0.1  |  127.0.0.1 |

由于本地生成的数据包首先遍历 OUTPUT 链,因此您可以使用 DNAT 规则修改数据包:

iptables -t nat -A OUTPUT \
         -d 127.0.0.1 \
         -p tcp --dport 80 \
         -j DNAT \
         --to 172.17.42.1:80

经过OUTPUT链之后,数据包如下所示:

 | SRC        |  DST        |
 | 127.0.0.1  |  172.17.42.1 |

因此,您看到的第一个错误是,即使此数据包被路由到源设备之​​外,目标也不知道如何正确返回它。因此,您还需要添加额外的 SNAT 规则:

iptables -t nat -A POSTROUTING \
         -d 172.17.42.1 \
         -p tcp --dport 80 \
         -j SNAT \
         --to-source <your_ip_addr>

现在,数据包看起来几乎正确,可以退出网络(源地址将是该设备的公共地址而不是本地主机地址)。

但是,这还不能解决你的痛苦。

本地机器生成的数据包的路由决策在两个地方做出。

  • 在 OUTPUT 链之前
  • 在 OUTPUT 链之后和 POSTROUTING 之前

在 POSTROUTING 链中重写源 IP 之前,将在第二阶段对此数据包做出决定...

因此,内核安全机制将丢弃数据包,因为默认情况下内核拒绝路由源地址为 127.0.0.1 的数据包。这意味着即使将 mangle 与 fwmark 结合使用也无法帮助我们。要实现此功能,需要启用 route_localnet。这是 per-iface 变量,允许使用 127/8 进行本地路由(默认值为 0 - 即禁用)。

sysctl -w net.ipv4.conf.all.route_localnet=1

您可以放心地将“all”更改为您情况下的传出接口名称。

现在,数据包将按照表中的先前规则进行路由,并且由于我们有 POSTROUTING SNAT,我们将修复 127.0.0.1 的源 IP 并重写它。

希望这可以帮助。

附言:抱歉,在进行 2-3 次编辑之前,这里是凌晨 5 点,我还没睡 :)

答案2

在直接进入防火墙规则之前,还应该执行简单的转发检查。就像在拆开硬件之前检查电源线是否插好一样。

跑步:

cat /proc/sys/net/ipv4/ip_forward

如果结果为零,则 IPv4 将不会转发。您需要启用此功能。

要立即并暂时打开它来验证行为:

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

上述操作会为机器打开它,但只是动态修改内核设置,不会被“保存”。

编辑 sysctl.conf 文件以进行适当的永久更改并确保以下设置:

net.ipv4.ip_forward = 1

相关内容