我正在端口上的 docker 容器内运行节点服务器8080
,我可以通过172.17.0.2:8080
(容器 ip)访问它,现在我想从localhost:9099
.
我尝试过使用 iptables 来重定向此流量,localhost:9099
但172.17.0.2:8080
所有措施都是徒劳的。
这是我正在使用的命令。请纠正我哪里出错了。提前致谢。
sudo iptables -t nat -A PREROUTING -p tcp --dport 9099 -j DNAT --to-destination 172.17.0.2:8080
我得到了帮助这回答但没有用。
答案1
您的尝试存在一些问题:
- using
localhost
表示连接是从主机发起的,而不是从其他主机路由的。因此它需要OUTPUT
链,而不是PREROUTING
链,因为最初不涉及路由。 - 源 IP,
127.0.0.1
一旦目标更改,源 IP 也必须更改。这需要额外的POSTROUTING
规则。可选的-m conntrack --ctstate DNAT
匹配将检查第一个匹配OUTPUT
是否首先匹配,并且这不是某种欺骗尝试。 - 至少在Linux上
127.0.0.0/8
是在路由堆栈中进行特殊处理的,并且数据包将在POSTROUTING
规则触发之前被丢弃。要删除特殊处理并允许在块“外部”进行路由127.0.0.0/8
,将发生重定向的接口必须具有标志route_localnet
设置为 1,否则以上都不够。
由于从问题中无法得知接口,因此从路由中检索接口名称并将其放入变量中。如果需要的话进行调整。您还可以使用all
伪接口来设置旗帜全球。
所以最后这归结为(作为 root 或使用sudo
):
iptables -t nat -A OUTPUT -p tcp --dport 9099 -j DNAT --to-destination 172.17.0.2:8080
iptables -t nat -A POSTROUTING -s 127.0.0.0/8 -d 172.17.0.2 -m conntrack --ctstate DNAT -j MASQUERADE
interface=$(ip -o route get 172.17.0.2 | grep -o 'dev [^ ][^ ]*'|sed 's/^dev //')
echo 1 > /proc/sys/net/ipv4/conf/$(interface)/route_localnet
综上所述,您应该尝试使用127.0.0.0/8
仍位于主机本地的非地址。这可以简化事情,不需要route_localnet
(有时可能不需要额外的POSTROUTING
规则)。