从WSL 2内部访问运行在Windows上的localhost

54

我在我的Windows机器上运行一个本地的AEM服务器。服务器正在localhost:4502上运行。我正在使用WSL 2中运行的Ubuntu分发版进行开发。我想在我的WSL 2 Ubuntu中访问运行在Windows机器上的localhost:4502

有没有办法做到这一点,或者是不可能的?


1
你的Windows机器IP加上4502应该足够了,不过你可能需要检查防火墙是否允许连接。 - ronnyfm
1
不,这完全是错误的!我也遇到了这个问题,很不幸你的答案是错误的。我尝试了 ssh -p <myCustomPort> <myWindowsIPstartingWith192.168..>,但连接立即被拒绝且一直如此!还有其他的建议吗? - SheppLogan
1
请执行以下步骤:
  1. 在WSL Ubuntu上通过运行命令行获取窗口的IP:cat /etc/resolv.conf。它将显示“nameserver <your_windows_mechine_ip>”。
  2. 关闭Windows防火墙。
  3. 连接到您的Windows主机。
- Hieu.Gi
对我来说,在PowerShell中执行以下命令解决了问题:netsh interface portproxy add v4tov4 listenport=4000 listenaddress=0.0.0.0 connectport=4000 connectaddress=192.168.101.100 ....其中connectaddress = resolv.conf中的nameserver。 - dmotta
7个回答

108

最新Windows版本的简短回答

mDNS已经成为WSL2的一个功能一段时间了。将你的WSL2 hostname(或者在你的编程/语言环境中等效的命令/函数)与".local"连接起来,即可获取访问权限。

例如,在Bash中尝试:

ping "$(hostname).local"
例如,如果您的hostname是"MyComputer",那么mDNS应该是MyComputer.local
如果ICMP被阻止(似乎在新的Windows 11安装中是这样),或者您想测试连接到实际端口的连接,则可以使用netcat。它默认情况下在WSL Ubuntu安装中可用,但可能需要在其他分发版中进行安装,例如openSUSE:
nc -zv "$(hostname).local" <portnumber>

为什么本地主机地址无法使用

WSL2使用由Windows虚拟机平台(Hyper-V的子集)创建的虚拟网络(vNIC)运行。在WSL2中,localhost是vNIC的地址。

你需要的内容

WSL2还在Windows主机上设置了一个虚拟路由器,以允许与外部世界和Windows主机进行连接。您可以通过以下方式查看此功能:

ip route

这是您需要在Windows主机上使用的地址。

当然,您可以从路由(或者如早期答案中所述,从/etc/resolv.conf)解析它,但WSL设置了一个方便的mDNS(.local域),使用Windows的“计算机名称”,也用作WSL实例的主机名。因此,将 $(hostname)(或其在编程/语言环境中的等效物)与“.local”连接起来,就可以访问它。

其他注意事项:

  • mDNS依赖于Windows主机来解析名称。如果您在WSL下更改了/etc/resolv.conf,则可能无法工作。

  • 记得打开任何必要的防火墙端口。WSL2被认为是与Windows主机不同的分离网络。 Windows将认为来自WSL2的网络连接来自外部源。(感谢@RamilGilfanov发表评论指出这一点)

    第一次从WSL2到特定端口进行连接时,Windows Defender(如果它是您的防火墙)通常会显示一个对话框,询问是否要授权访问。 但是,根据我的经验,由于鼠标单击,键盘等的时间关系,这个对话框经常被主窗口遮挡,因此很容易被忽略。

  • 记得让您的Windows服务接受来自远程主机的连接。

    许多服务器默认配置为绑定到localhost/127.0.0.1。由于WSL2对Windows来说看起来像远程网络,因此通常需要更新配置以绑定到0.0.0.0或特定地址。请注意,由于WSL2的地址在每次重新启动后都会更改,因此每次更新配置可能会很困难。如果可能,请使用0.0.0.0,除非存在安全问题。由于WSL是设计用于开发而不是生产,因此这不应该是问题。


1
在Windows防火墙中打开端口 - Ramil Gilfanov
2
我能够ping通Windows主机IP,但仍然无法从WSL2访问Windows上打开的任何端口(防火墙关闭),你有什么见解吗?谢谢! - nonemaw
如果您想要访问127.0.0.0/8范围内的其他地址,该怎么办? - leo
@leo,你能否提供更多关于你的用例的细节(可能通过新的超级用户问题)?简单的答案是,在Windows中,整个loopback子网无法从WSL2访问。这就是为什么我们需要mDNS地址的原因。 - NotTheDr01ds
1
@leo 同意 - 这是我通常的建议。在 Windows 中拥有 SSH 服务器可以使许多 WSL2 任务更加容易。有关详细信息,请参见我的 jumphost 答案。我在许多其他答案中也使用了它。 - NotTheDr01ds
显示剩余9条评论

12
我也在寻找解决办法,但目前还没有这样的选项可用。请查看这个GitHub问题:
[WSL 2] WSL 2无法通过localhost:port访问Windows服务 #4619
一个解决办法是这样的:
如果你有Windows(主机)的IP地址,那么它可以完成任务,但唯一的问题是IP地址每次都会变化。不过,WSL 2将你的Windows(主机)IP地址存储在/etc/resolv.conf文件中。因此,我们可以修改我们的etc/hosts文件,动态地将winhost映射到IP地址。
在~/.bashrc文件的末尾添加以下行。当你启动WSL时,它将提取IP地址并修改etc/hosts文件。
export winhost=$(cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }')
if [ ! -n "$(grep -P "[[:space:]]winhost" /etc/hosts)" ]; then
        printf "%s\t%s\n" "$winhost" "winhost" | sudo tee -a "/etc/hosts"
fi

然后运行以下命令以重新加载更改。
source ~/.bashrc

现在你可以在WSL 2(客户端)中使用winhost来代替localhost来访问运行在Windows(主机)上的服务器。在你的情况下,它将是winhost:4502,但这对于其他用例也适用,比如访问运行在Windows上的PostgreSQLMySQL服务器等。 注意:始终记得在Windows上配置防火墙以允许这些端口,以便WSL 2可以访问它。否则,你的连接可能会被防火墙阻止。

1
你好,我也有这个问题,但是你的答案不正确。我尝试使用ssh -p <myCustomPort> <myWindowsIPstartingWith192.168..>,但连接立即被拒绝!还有其他想法吗? - SheppLogan
@SheppLogan 我不确定你想要实现什么。你能详细说明一下吗? - Tarun Kumar
1
这是被接受的答案,但它意味着服务没有在本地主机上监听,而是在0.0.0.0上,并且有防火墙... - Andrea Ratto

5
这很简单,你只需要做两件事情。第一,在hosts文件中将IP地址设置为localhost,第二,允许Windows防火墙接受传入连接。
以下是逐步说明:
  1. 获取IP地址。打开cmd.exe并输入ipconfig /all。记下IP地址172.22.16.1。

    image

  2. 以管理员身份打开记事本,菜单文件打开,浏览到C:\Windows\System32\drivers\etc\hosts,添加一行172.22.16.1 localhost,保存并关闭。

  3. 最后一个选项是允许防火墙规则接受公共连接。为此,打开控制面板*→系统和安全Windows Defender防火墙高级设置入站规则新建规则

  4. 规则类型:选择端口,然后点击下一步

  5. 协议和端口:输入特定本地端口:4502,然后点击下一步

  6. 操作:允许连接,然后点击下一步

  7. 配置文件:勾选公用,然后点击下一步

  8. 名称:输入AEM服务器,然后点击完成

  9. 关闭其他窗口,然后再次打开cmd。输入wsl --shutdown以关闭Ubuntu子系统。

  10. 再次打开Ubuntu。

  11. 测试连接:在命令提示符中输入curl localhost:4502。如果返回结果,则表示一切正常。


1
只要不返回任何结果,也可以继续进行 - 但是只要不卡住或显示连接被拒绝的消息。我曾经有一个仅记录GET请求而不返回任何内容的测试服务 :) - howard
@Howard 不挂起的意思是它应该返回并让你输入另一个命令吗?那对我来说不起作用 :( - Bob the Builder
@sorabh86 将端口4502公开是否存在安全风险? - Bob the Builder
@BobtheBuilder 正确 - howard
@BobtheBuilder - 什么样的安全风险?嗅探攻击还是数据泄露?打开端口并不总是安全风险,我们允许我们托管的操作系统通过创建的虚拟专用网络访问虚拟操作系统。我认为没有任何安全风险。 - sorabh86
显示剩余2条评论

2

Windows 主机文件? - Arjen

-1

简单的方法:

在Ubuntu命令行中输入:

ip route

输出:

default via 172.23.96.1 dev eth0
172.23.96.0/20 dev eth0 proto kernel scope link src 172.23.97.122

在您的应用程序中,将主机配置为:172.23.97.122 现在您可以使用Windows浏览器访问它。

3
你好,欢迎来到Stack Overflow。提醒一下,在我的现有答案中我已经介绍了使用ip route命令获取IP地址的方法。应该避免重复回答,所以在编写新答案之前请确保阅读现有答案。另外请注意,每次重新启动WSL(或计算机)时,IP地址都会更改,所以这并不是“简单的方法”。正如我在答案中提到的那样,最好使用mDNS名称,因为只要启用了mDNS,它就始终可以解析到正确的地址。 - NotTheDr01ds
"Windows Browser" refers to the web browser developed by Microsoft for the Windows operating system. It is commonly used to access and navigate websites on the internet. As for File Explorer, it is a file management tool provided by Microsoft in Windows, allowing users to browse and manage files and folders on their computer. - Peter Mortensen

-4
Windows 10将localhost视为::1。 Ubuntu将localhost视为127.0.0.1。
因此解决方案是创建一个映射。在C:\Users\\.wslconfig中创建一个名为*.wslconfig*的文件。
将以下内容添加到其中。
[wsl2]
localhostForwarding=true

PS:我不知道这是否会影响其他内容,但它帮助我成功运行了升级到WSL 2后出现问题的Django服务器。

1
localhostForwarding 在 WSL2 上应该已经默认为 true,但有时似乎会出现问题,我还没有能够确定原因。通常只需执行 wsl --shutdown 并重新启动会话即可恢复大多数人的功能。 - NotTheDr01ds
3
这个答案真的需要至少一个更正。::1与127.0.0.1与Windows 10与Ubuntu完全无关。Windows 10可以很好地理解127.0.0.1,Ubuntu也可以很好地理解::1。真正的区别在于::1是IPv6地址,而127.0.0.1(或任何以127开头的IP地址)是IPv4。 - Kevin Keane
所以请解释一下为什么这样能够解决我的问题?因为据我所知,它确实解决了这个问题。而且显然对用户也是如此。 - Vipin Mohan
8
根据微软文档,localhostForwarding 意味着“在 WSL 2 VM 中绑定到 localhost 的端口应该可以从主机连接”,但不是“在主机中绑定到 localhost 的端口应该可以从 WSL 2 VM 连接”,因此这个答案行不通。 - ayanamist

-5
我怀疑你可以做到这一点。
步骤1:将你的AEM服务器运行在实际的IP地址上(或所有地址),而不仅仅绑定在本地主机上。
步骤2:你的Ubuntu WSL客户端实例不会与主机机器共享本地主机,但它会共享你的机器实际拥有的本地IP地址(例如10.0.0.2)。只需让你的客户端连接到该IP地址,而不是本地主机。
我对AEM一无所知,但如果你要将其暴露给更大的网络,可能需要对其进行安全保护。在上游防火墙上阻止4502端口,或使用Windows防火墙规则仅允许来自你自己IP地址的4502端口的入站连接。这肯定是可行的。

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