我想在 Linux 3.x(目前为 3.2.52,但如果需要我可以升级)上设置从 127.0.0.1、端口 4242 到 11.22.33.44、端口 5353 的 TCP DNAT。
看起来简单的 DNAT 规则设置不起作用,telnet 127.0.0.1 4242
挂起一分钟Trying 127.0.0.1...
,然后超时。可能是因为内核正在丢弃返回的数据包(例如 SYN+ACK),因为它认为它们是火星的。我不需要解释为什么简单的解决方案不起作用,我需要一个解决方案,即使它很复杂(例如它涉及创建许多规则)。
我可以从网络外的另一个本地 IP 地址设置常规 DNAT 127.0.0.0/8
,但现在我需要 127.0.0.1 作为目标地址。我知道我可以设置用户级端口转发过程,但现在我需要一个可以使用iptables
且不需要辅助进程的解决方案。
我在 Google 上搜索了这个问题一个小时。这个问题被问过很多次,但我找不到任何可行的解决方案。
另外,关于 DNAT 到 127.0.0.1 也有很多问题,但我不需要那样,我需要相反的。
请注意,单个iptables -j REDIRECT
规则不起作用,因为我需要将传出数据包的 IP 地址从 127.0.0.1 更改为 11.22.33.44,但-j REDIRECT
无法更改 IP 地址。
答案1
这对我有用,将流量从localhost:8081
路由到172.17.0.1:80
,其中172.17.0.1
是桥接接口后面的 veth,名为docker0
。
sysctl -w net.ipv4.conf.docker0.route_localnet=1
iptables -t nat -A OUTPUT -o lo -p tcp -m tcp --dport 8081 -j DNAT --to-destination 172.17.0.1:80
iptables -t nat -A POSTROUTING -o docker0 -m addrtype --src-type LOCAL --dst-type UNICAST -j MASQUERADE
这个难题的一个关键部分是MASQUERADE
规则。
进一步的启发:
答案2
您必须运行以下三个命令才能使其工作:
iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 4242 -j DNAT --to 11.22.33.44:5353
sysctl -w net.ipv4.conf.eth0.route_localnet=1
iptables -t nat -A POSTROUTING -p tcp -s 127.0.0.1 -d 11.22.33.44 --dport 5353 -j SNAT --to $your-eth0-ip
以下是详细解释。
第一个命令将按预期执行 DNAT。但是,如果您尝试仅使用此规则集捕获数据包,您会发现什么也得不到:
tcpdump -i any -n port 5353
127.0.0.0/8
这是因为,如果数据包的一端是外部 IP 地址,另一端是外部 IP 地址,则 Linux 内核默认丢弃这种数据包。
第二条命令修改了内核参数,让这种数据包通过(当然,你应该eth0
相应地进行修改)。之后,当你在 eth0 上捕获数据包时,你会看到数据包被发出,但带有源地址127.0.0.1
和目标地址11.22.33.44
。无论这个数据包是否能到达目标服务器(中间路由器会丢弃这个数据包),这个数据包都无法返回。所以你应该添加一条SNAT
规则,将源地址更改为你的 eth0 的地址。现在它应该可以正常工作了。
答案3
您需要这样的东西吗?iptables 端口重定向不适用于本地主机
iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 443 -j REDIRECT --to-ports 8080
阿德里安