我想要实现的目标
在工作中,我们使用特定的操作系统,我们(开发人员)在 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 连接虚拟的因为原始连接的信息来自工人已经迷失了。