将连接转发到 Docker 容器内的虚拟机

将连接转发到 Docker 容器内的虚拟机

我想要实现的目标

在工作中,我们使用特定的操作系统,我们(开发人员)在 virtualbox 中运行该操作系统。虚拟化操作系统正在运行 Samba 服务器和 rsh,我们用它们来访问操作系统。此外,虚拟化操作系统需要访问我们网络上的多个服务器。

我希望实现的是,在 Docker 设置过程中找到一种快速启动虚拟机的方法。这个想法是拥有一个 Docker 容器,它可以提供对虚拟机的访问,一个在虚拟机上运行测试的容器,以及将来提供系统分析等功能的其他容器。

问题是什么

我有一个 docker 容器,它设置了一台具有桥接网络的 VirtualBox 机器。我可以使用 rsh 从启动它的容器访问虚拟机,没有任何问题。但是,我无法使用 rsh 从其他容器访问虚拟机(好吧,我找到了一个解决方案,我将在下面描述,但我认为这不是一个好的解决方案)。有趣的是,ping 工作正常。

现在设置如下:

虚拟容器

  • 包含虚拟机的 Docker 容器
  • IP地址:172.18.0.5
  • 网关:172.18.0.1
  • 网络掩码:255.255.0.0

VirtualBox 计算机

  • 在里面跑虚拟的容器
  • IP地址:172.18.1.5
  • 网关:172.18.0.1
  • 网络掩码:255.255.0.0

工作容器

  • 我想要连接到 VirtualBox 机器的容器
  • IP地址:172.18.0.6
  • 网关:172.18.0.1
  • 网络掩码:255.255.0.0

到目前为止,我只找到了一种使用 rsh 连接到 VirtualBox 机器的解决方案,那就是添加一条路由:

ip route add 172.18.1.5 via 172.18.0.5

然后 rsh 到 172.18.1.5。但是,这有一个严重的问题。由于我需要知道分配给虚拟机的地址,我必须将 virtualbox 地址设置为可以从其运行的容器的地址轻松猜出的地址。更改容器内的路由也意味着容器需要具有特权,我希望将具有特权的容器数量保持在最低限度。

我更希望的是能够 rsh 到虚拟的容器(172.18.0.5)直接。这样我就不用猜测虚拟机的 IP,但我可以使用虚拟的感谢docker-compose。

我认为可以使用 NAT 来实现这一点。我所做的是:

  • 将虚拟机的网关更改为虚拟的
  • 暴露所有端口虚拟的
  • 将以下两条规则添加到虚拟的容器:
iptables -t nat -A PREROUTING --目标 172.18.0.5 -j DNAT --到目标 172.18.1.5
iptables -t nat -A POSTROUTING --源 172.18.1.5 -j SNAT --到源 172.18.0.5

但是,它似乎根本不起作用。注意:我不在乎所有端口是否都是转发器。显然,最好只转发 rsh 和 Samba,但 rsh 存在问题,因为服务器选择端口进行通信的方式类似于被动 FTP。

有什么想法我做错了什么或者我还能怎样实现我的目标?

更新

iptables nat表的内容:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       all  --  anywhere             4f04152f8562         to:172.18.1.5

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER_OUTPUT  all  --  anywhere             127.0.0.11          

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER_POSTROUTING  all  --  anywhere             127.0.0.11          
SNAT       all  --  anywhere             anywhere             to:172.18.0.5

Chain DOCKER_OUTPUT (1 references)
target     prot opt source               destination         
DNAT       tcp  --  anywhere             127.0.0.11           tcp dpt:domain to:127.0.0.11:43467
DNAT       udp  --  anywhere             127.0.0.11           udp dpt:domain to:127.0.0.11:39285

Chain DOCKER_POSTROUTING (1 references)
target     prot opt source               destination         
SNAT       tcp  --  127.0.0.11           anywhere             tcp spt:43467 to::53
SNAT       udp  --  127.0.0.11           anywhere             udp spt:39285 to::53A

另外,我已经在容器中安装了 wireshark,我认为问题是由于 iptables 规则导致了循环。

我可以看到从 172.18.0.6 到 172.18.0.5 的数据包被发送到 172.18.1.5,所以这是正确的。此外,来自 172.18.1.5 的回复将源地址转换为 172.18.0.5,然后发送到 172.18.0.6,这也是正确的。但是,有一个从 172.18.1.5 到 172.18.0.5 的连接。我认为问题就在这里,因为连接应该是到 172.18.0.6。但是,我不知道如何确保虚拟机知道要连接的正确地址。

在此处输入图片描述

更新 2

现在我考虑了一下 - DNAT 不是应该保持源地址不变吗?根据 wireshark,它被更改为虚拟的。因此,虚拟机创建与虚拟的代替工人

答案1

所以解决方案非常简单:

移动虚拟的进入另一个子网,并将其网关设置为容器

就是这样。问题中提到的 NAT 规则是正确的。

因为工人虚拟的位于同一子网,虚拟的连接到工人直接在创建连接时工人RSH 使用的,从而绕过 NAT。


不幸的是,我在使用 wireshark 调试此问题时又犯了一个错误。我实在无计可施,将 iptables 规则更改为:

-t nat -A PREROUTING -j DNAT --to-destination 172.18.1.5
-t nat -A POSTROUTING -j SNAT --to-source 172.18.0.5

有了这样的规则,它似乎部分奏效了,因为突然间容器成为使初始握手成功的源头。然而,它切断了 RSH 连接虚拟的因为原始连接的信息来自工人已经迷失了。

相关内容