我在 CentOS 上使用 docker 容器来模拟网络上的设备,并且有两个工具将在每个容器内运行,以模拟与实际网络设备的通信。单独来看,这两个工具都可以在 docker 容器内工作,并且可以通过一个端口(我们在此称为 8000)与外界通信,但由于两者都试图使用 8000,因此它们无法同时运行。为了解决这个问题,我希望将 8000 上的流量镜像到另一个端口(我们在此称为 8001),以便一个工具可以在 8000 上运行,而另一个工具可以在 8001 上接收其数据包。在我的 Dockerfile 中,我同时使用了EXPOSE
这两个工具(尽管没有在运行命令中发布它们)。
在网上搜索后,我发现这。为了使它适应我的目的,我最终得到了下面的代码,我从 内部执行docker exec -it <container> bash
。根据我最初的理解,它应该将消息复制到另一个本地主机 IP 的端口 8000,同时让原始消息通过,然后将重复的数据包传回 127.0.0.1:8001。
iptables -t mangle -A PREROUTING -p UDP --dport 8000 -j TEE --gateway 127.0.0.2
iptables -t nat -A PREROUTING -d 127.0.0.2 -p UDP --dport 8000 -j DNAT --to 127.0.0.1:8001
这似乎不起作用。在 8001 上运行工具导致它错过我从外部世界向 8000 发送的所有数据包。
同样地,我发现这个,并尝试使其适应下面的情况,但它似乎也不起作用,而且尝试让 netcat 在容器中正常运行已被证明是相当令人头痛的事情。
iptables -A PREROUTING -t mangle -p tcp ! -s 127.0.0.1 --dport 8000 -j TEE --gateway 127.0.0.1
iptables -A OUTPUT -t nat -p tcp -s 127.0.0.1/32 --dport 8000 -j DNAT --to 127.0.0.1:8001
我对 docker 和 iptables 都很陌生,因此,如果能对这里出现的问题的底层机制进行任何解释,我将非常感激。
答案1
经过一番努力,发现了如下需要在容器内运行的解决方案:
sysctl -w net.ipv4.conf.eth0.route_localnet=1
iptables -t mangle -A PREROUTING -i eth0 -p UDP --dport 8000 -j TEE --gateway 127.0.0.1
iptables -t nat -A PREROUTING -p UDP --dport 8000 -j DNAT --to-destination 127.0.0.1:8001
缺少的关键是首先要在容器内运行 sysctl 命令以允许一切。然后,它需要是 eth0,而不是以前的解决方案,否则您将陷入无限循环。