svo*_*l13 1 networking iptables port-forwarding linux-networking dnat
我得到了lo(127.0.0.1)和eth0(172.17.0.8)。我想将登陆的数据包重定向127.0.0.1:80到172.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
Run Code Online (Sandbox Code Playgroud)
但是当我这样做时我没有curl localhost:80得到任何回应,当我这样做时curl 172.17.42.1:80它就起作用了。
当您尝试访问 localhost 时,您的源地址是 127.0.0.1,您的目标地址也是。所以,数据包看起来像这样:
| SRC | DST |
| 127.0.0.1 | 127.0.0.1 |
Run Code Online (Sandbox Code Playgroud)
由于本地生成的数据包首先遍历 OUTPUT 链,因此您可以使用 DNAT 规则修改数据包:
iptables -t nat -A OUTPUT \
-d 127.0.0.1 \
-p tcp --dport 80 \
-j DNAT \
--to 172.17.42.1:80
Run Code Online (Sandbox Code Playgroud)
在 OUTPUT 链之后,数据包如下所示:
| SRC | DST |
| 127.0.0.1 | 172.17.42.1 |
Run Code Online (Sandbox Code Playgroud)
所以,你看到的第一个错误是,即使这个数据包被路由到源设备之外,目的地也不知道如何正确返回它。因此,您还需要添加额外的 SNAT 规则:
iptables -t nat -A POSTROUTING \
-d 172.17.42.1 \
-p tcp --dport 80 \
-j SNAT \
--to-source <your_ip_addr>
Run Code Online (Sandbox Code Playgroud)
现在,在网络上退出的数据包看起来非常正确(源地址将是该设备的公共地址,而不是本地主机地址)。
但是,这还不能解决你的痛苦。
在本地机器上生成的数据包的路由决策在两个地方进行。
这个数据包的决定将在第二阶段做出,在源 IP 在 POSTROUTING 链中重写之前......
因此,内核安全机制将丢弃数据包,因为默认情况下内核拒绝路由 src 为 127.0.0.1 的数据包。这意味着即使 mangle 加上 fwmark 在这里也无济于事。要使其工作,需要启用 route_localnet。这是 per-iface 变量,它允许将 127/8 用于本地路由目的(默认值为 0 - 也称为禁用)。
sysctl -w net.ipv4.conf.all.route_localnet=1
Run Code Online (Sandbox Code Playgroud)
在您的情况下,您可以安全地更改传出接口名称的“全部”。
现在,数据包将按照表中之前的规则进行路由,并且由于我们有 POSTROUTING SNAT,我们将修复 127.0.0.1 的源 ip 并重写它。
希望这可以帮助。
附注。抱歉,在 2-3 次编辑之前,现在是凌晨 5 点,我还醒着:)
| 归档时间: |
|
| 查看次数: |
5436 次 |
| 最近记录: |