从网络上的另一台 PC 访问在 Ubuntu/WSL 中运行的 Web 应用程序

从网络上的另一台 PC 访问在 Ubuntu/WSL 中运行的 Web 应用程序

我在 WSL 中使用带有 Ubuntu 20.04.04 LTS(来自 Microsoft Store)的 Windows 10。

它运行具有 Web 界面的软件,我可以使用 Edge 连接到此 PC 上的 Windows 中毫无问题地访问此应用程序localhost:4040

遗憾的是,同一网络中的另一台 PC 无法实现这一点。

我必须进行什么配置,以便网络上的另一台 PC 也可以访问在 WSL 上的 Ubuntu 中运行的软件的 Web 界面?

如果我使用该软件的 Windows 版本,网络上的其他 PC 访问 Web 界面不会有问题。但是,该软件的 Windows 版本对我来说不是一个选择。

答案1

背景

原因是 WSL2 的网络在 Hyper-V 虚拟机管理程序创建的虚拟交换机中运行。WSL2 VM 的网络接口运行(NAT'd)里面(或者“后面”,取决于你如何看待它),Windows 主机本身。

这意味着 WSL2 内部运行的服务本质上是在一个单独的网络中运行,你的其他 PC/设备对此一无所知。

对于 Windows 主机本身,WSL2 提供了称为“localhostForwarding”的功能,默认情况下处于启用状态。正如您所注意到的,当您localhost:4040从本地 Windows 访问时,它首先检查是否有东西绑定到该端口视窗如果没有,则转身并将其转发到 WSL2 VM 中的端口 4040。

现在至少有四种方法可以解决这个问题:

选项 1:WSL1(对于许多用例而言是最佳/最简单的选项,但并非全部)

您可能会认为,WSL2 已经发布了近两年,它在各方面都会比 WSL1 更好,但事实并非如此。在某些情况下,WSL1 仍然表现更好,网络访问就是其中之一。

如果您运行的应用程序不需要 Linux 内核的所有功能,那么它很可能在 WSL1 下运行良好。WSL1 提供了一个“系统调用转换层”,可将 Linux API 映射到 Windows。从这个意义上讲,它就像一个“反向 WINE”。这种方法的优点之一是网络调用实际上使用 Windows 网络接口。因此,当应用程序绑定到 WSL1 中的端口 4040 时,它实际上是在 Windows 界面上执行此操作,并且可以从网络上的其他计算机访问。

您可以通过以下方式在 PowerShell(或 CMD,但实际上,为什么?;-) 中将 WSL2 实例转换为 WSL1:

wsl -l -v
# Confirm the distribution name is Ubuntu, adjust the next commands otherwise
wsl --export Ubuntu .\path\to\ubuntu_backup.tar # Optional, and you put the backup where ever you want
wsl --set-version Ubuntu 1

或者,你可以创建 Ubuntu 的第二个副本并使其成为 WSL1:

wsl -l -v 
# Confirm the distribution name is Ubuntu, adjust the next commands otherwise
wsl --export Ubuntu .\path\to\ubuntu_backuptar
mkdir .\location\for\new\Ubuntu\
wsl --import UbuntuWSL1 .\location\for\new\Ubuntu .\path\to\ubuntu_backup.tar --version 1

然后通过启动分发wsl ~ -d UbuntuWSL1并按照说明进行操作我的超级用户回答在新副本中设置您的用户名。

如果您发现您的应用由于某种原因无法在 WSL1 下运行,请继续阅读...还有其他选项。

选项 2:SSH 反向隧道转发

这是我个人的偏好,可以轻松转发到 Ubuntu 等 WSL2 发行版的连接。

  • 一次性设置:

    • 按照以下说明安装 Windows OpenSSH Server官方文件

    • 编辑C:\ProgramData\ssh\sshd_config并取消注释GatewayPorts yes

    • 打开管理 PowerShell。

    • 使用以下命令重启 Windows SSH 服务器Restart-Service sshd

    • 添加防火墙规则以允许您的端口(在您的情况下为 4040):

      New-NetFirewallRule -DisplayName 4040 -Direction Inbound -LocalPort 4040 -Protocol TCP -Action Allow
      # Set DisplayName to whatever you need to remember it
      

      注意:如果您需要删除此规则,那将是Remove-NetFirewallRule -DisplayName 4040(或无论您命名的任何名称)。

  • 然后,在 Ubuntu/WSL2 中建立转发,运行:

    ssh -fN -R 4040:localhost:4040 $(hostname).local
    

    用你的视窗(不是 Ubuntu/WSL2)用户名和密码。

    解释:

    • ssh$(hostname).local,应该解析为您的 Windows 计算机名称 + .local应该解析为 Hyper-V 交换机的正确 IP 地址。请参阅我的 Stack Overflow 答案关于 mDNS 解析的主题。

    • -f请求密码后将 ssh 会话置于后台(如果需要)

    • -N说“不要启动终端或在远程主机上运行任何命令,只需设置连接和转发”。

    • -R 4040:localhost:4040是关键,它设置了一个反向隧道,以便当有人连接到 Windows 端的端口 4040 时,该连接也会转发到端口 4040 上的 Ubuntu/WSL2 的本地主机。

此时,您可以使用一个命令来启动转发,也可以将其放入启动 Web 应用程序的脚本中。

选项 3:Windows 端口转发

虽然您可以从 Windows 端设置转发,但由于 WSL2/Ubuntu 的 IP 地址是动态设置的,并且每次重新启动(或关闭 WSL)时都会发生变化,因此这变得更加困难。

我会告诉你微软文档以获得确切的命令,但请注意,每次运行时您都必须确定要使用的 IP 地址。

您可以编写脚本(参见例子在有关该主题的原始 Github 问题中),但它比 SSH 方法复杂得多,所以我看不出有什么意义。

选项 4:使用 Bridge 进行 WSL2 预览

可能对于某些人来说(但不是你)是最佳选择,如果他们愿意运行 WSL2 的预览版并拥有 Windows 11 Pro/Education(或更高版本),而你没有。就我个人而言,预览版中单独的 SSH 错误/限制使我无法将其作为日常驱动程序运行。

在 Windows 11 上,您可以通过 Microsoft Store 安装更新的预览版 WSL。此版本将取代现有的 WSL,但您可以随时通过卸载 Store 应用恢复到原始版本。

此预览版具有一项新功能,允许您指定与 WSL2 一起使用的特定 Hyper-V 网络交换机,并且您可以创建并将该网络交换机配置为桥接。

虽然我还没有亲自测试过(我会在某个时候测试),但你可以按照这篇博文(不是我的)。一位微软开发人员的原始声明隐藏在我上面链接的 Github 问题(目前)的 650 多条评论中。

相关内容