Vagrant反向端口转发?

130

我正在研究 Web 服务架构。我有一些软件需要在本机主机上运行,而不是在 Vagrant 上运行。但我希望在客户端上运行一些服务。

Vagrant 的 config.vm.forwarded_port 参数将在主机上打开一个端口并将数据发送到客户端。但如何在客户端上打开一个端口并将数据发送到主机?(仍然是端口转发,但方向相反。)


由于 Vagrant 使用 SSH,理论上是可能的,并且 Ruby SSH 实现 gem 支持此功能,但在 Vagrant 文档中从未看到过类似的内容。 - cmur2
参见:https://dev59.com/jmIj5IYBdhLWcg3wv3i2 - Ajedi32
5个回答

142

当你运行vagrant ssh时,实际上是在使用以下基础命令:

ssh -p 2222 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o IdentitiesOnly=yes -i ~/.vagrant.d/insecure_private_key vagrant@127.0.0.1

SSH支持使用-R guestport:host:hostport选项在所需方向上转发端口。因此,如果你想连接到客户端上的端口12345并将其转发到localhost:80,则应使用以下命令:

ssh -p 2222 -R 12345:localhost:80 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o IdentitiesOnly=yes -i ~/.vagrant.d/insecure_private_key vagrant@127.0.0.1

正如Eero所指出的,你也可以使用vagrant ssh -- -R 12345:localhost:80命令,这个命令有相同的效果,而且更为简洁。


72
你可以更简单地使用 vagrant ssh -- -R 12345:localhost:80 来运行此操作。这遵循了ssh选项语法 -R _[bind_address:]port:host:hostport_,其中第一个数字是在虚拟机内部监听的端口号,最后两个数字是从主机机器可见的服务地址。 - Eero
2
据我了解,反向转发只在相应的ssh shell中起作用。我认为丹·法伯里奇想要一种无需通过ssh登录到虚拟机的解决方案。 - Alp
2
@Alp 我相信这是整个系统可用的端口,而不仅仅是ssh进程可用的端口。对我来说运行得很好! - Henrik Heimbuerger
1
对于使用PuTTy的人来说,配置GUI中的SSH/Tunnels部分允许远程端口转发(因此在命令中使用-R)或本地端口转发(在命令行中使用-L)。 - Titou
3
如果您有多个Vagrant设置,或者需要考虑流浪者的潜在不同配置,请使用以下命令:vagrant ssh-config | ssh -F /dev/stdin $BOX -R $PORT_VM:localhost:$PORT -N - ibizaman
谢谢你救了我的一天!! - haotang

107
在由Vagrant创建者编写的书籍《Vagrant:上手指南》(出版日期:2013年6月12日)中,他提到了虚拟机无法访问运行在主机上的服务,而不是使用“转发端口”,可以使用“Host-Only Networks”来建立一个私有网络。
使用“Host-Only Networks”优于“Forwarded Ports”的优点:
1. 客户机可以访问运行在主机上的服务。此功能可解决您的问题。 2. 客户机可以访问其他客户机上运行的服务。此功能非常有用,可以将服务分离到多台机器上,以更准确地模拟生产环境。 3. 安全。外部计算机无法访问运行在客户机上的服务。 4. 工作量较小。无需配置每个“Forwarded Port”。
如何配置“Host-Only Networks”:
在您的“Vagrantfile”中添加以下行将指示Vagrant创建具有静态IP地址192.168.0.0的私有网络:
"config.vm.network :\"hostonly\", \"192.168.0.0\"" # Vagrant Version #1

"config.vm.network :private_network, ip: \"192.168.0.0\"" # Vagrant Version #2
主机的IP地址始终为同一IP地址,但最后一个八位数为1,在前面的例子中,主机机器的IP地址将为“192.168.0.1”。

2
同样地(也来自于《Vagrant: Up and Running》),你可以设置一个桥接网络。在桥接网络中,本地网络中的其他机器可以访问你的虚拟机,反之亦然。但由于IP地址是通过DHCP分配的,你需要在虚拟机中使用ifconfig命令来查找其IP地址。 - nucleartide
32
在设置 config.vm.network :private_network, ip: "192.168.50.4" 时,重要的信息是客户机将通过访问 "192.168.50.1" 来访问主机。我无法在任何地方找到这个小细节的文档记录。 - Owen Allen
1
我发现使用答案地址192.168.0.0是不起作用的 - 对主机进行curl / ping操作会导致连接超时。使用@Nucleon的地址(与Vagrant文档上的主题一致)按照广告运作。 - markdsievers
8
使用您的配置行config.vm.network :private_network, ip: "192.168.0.0"并在192.168.0.1上进行curl / ping测试时,结果是连接超时。将网络配置为192.168.50.4解决了这个问题,即主机现在可通过192.168.50.1访问。 - markdsievers
4
"192.168.0.0" 不是一个好的例子,x.x.x.0 通常用于广播。 - number5
显示剩余5条评论

83

您可以通过虚拟机内部的默认网关(通常具有IP地址10.0.2.2)访问主机上的端口。

例如,如果您的主机上有一个运行在8000端口的 Web 服务器...

echo 'Hello, guest!' > hello
python -m SimpleHTTPServer 8000

您可以从Vagrant VM内部访问它,地址为10.0.2.2:8000(前提是10.0.2.2是guest的默认网关的IP地址):

vagrant ssh
curl http://10.0.2.2:8000/hello # Outputs: Hello, guest!

要在虚拟机操作系统中查找默认网关的IP,请运行netstat -rn命令(或在Windows虚拟机上运行ipconfig命令),然后查找目标IP为0.0.0.0(或在Windows上标记为“默认网关”的字段)的行:

$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.0.2.2        0.0.0.0         UG        0 0          0 eth0
10.0.2.0        0.0.0.0         255.255.255.0   U         0 0          0 eth0
192.168.33.0    0.0.0.0         255.255.255.0   U         0 0          0 eth1
您可以使用 netstat -rn | grep "^0.0.0.0 " | tr -s ' ' | cut -d " " -f2 命令程序化地提取此IP。

来源:如何从vagrant virtualbox机器连接到主机PostgreSQL; 如何从VirtualBox客户机操作系统连接到主机


1
我也非常喜欢这个解决方案,因为它甚至不需要停止我的当前vagrant ssh会话就能正常工作。谢谢! - Rubix
太棒了!这正是我在寻找的。 - Khan Shahrukh
太好了!ifconfigip address都不能给我我需要的信息,但是netstat -rn可以。 - geerlingguy

10

在主机上,请将以下内容添加到您的~/.ssh/config文件中:

Host 127.0.0.1
RemoteForward 52698 127.0.0.1:52698

只要您通过vagrant ssh登录,就可以从Vagrant访问主机端口52698上的服务。

您可以在Vagrant虚拟机上运行netstat -lt并注意以下行来确认其是否有效:

tcp      0    0 localhost:52698         *:*                 LISTEN
tcp6     0    0 ip6-localhost:52698     [::]:*              LISTEN

2
+1 这对我帮助很大。我添加了给定的文本,将端口 5037 替换,以便我的虚拟机箱能够监听运行在主机箱上的 Android 模拟器。 - rob

2
我可以通过主机的本地IP地址(而不是回环地址)访问运行在主机上的服务。我测试了在端口80(然后是端口987)上创建了一个http服务器,然后使用curl命令访问197.45.0.10:80和197.45.0.10:987(实际IP地址更改以保护隐私)。两次都成功了,我没有进行任何特殊的vagrant配置(没有public_network,没有forwarded_port),虽然我确实通过PuTTY转发了一些端口,但我没有转发80和987端口。因此,您可以尝试使用主机机器的本地或公共IP地址。
如果您想从一个客户vagrant实例访问(ssh)另一个客户vagrant实例,则可以在Vagrantfile中启用public_network,并将22端口转发,如下所示:
config.vm.network "public_network"
config.vm.network "forwarded_port", guest: 22, host: 2200

只要该端口开放(即在路由器配置中进行更多端口转发),您就可以从任何地方访问该计算机,甚至从外部世界访问。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接