从本地网络访问在 WSL(适用于 Linux 的 Windows 子系统)上运行的 Web 服务器

2024-11-12 08:36:00
admin
原创
25
摘要:问题描述:将Ubuntu安装为WSL(适用于 Linux 的 Windows 子系统)后,我以 root 身份运行:cd ~ python3 -m http.server 输出:Serving HTTP on 0.0.0.0 port 8000 ... http://0.0.0.0:8000我尝试从我的 Wi...

问题描述:

将Ubuntu安装为WSL(适用于 Linux 的 Windows 子系统)后,我以 root 身份运行:

cd ~
python3 -m http.server

输出:

Serving HTTP on 0.0.0.0 port 8000 ...

http://0.0.0.0:8000我尝试从我的 Windows 计算机或访问此 Web 服务器http://192.168.1.178:8000,但没有任何成功。Web 服务器仅可通过地址http://127.0.0.1:8000或访问http://localhost:8000。这意味着我无法从网络中的另一台 PC 连接到此 Web 服务器。是否可以从外部访问 WSL?


解决方案 1:

在您的虚拟机中,执行ifconfig

您将在第一部分 (eth0:) inet xxxx 中看到您的 IP 地址

这个 xxxx 是您必须在浏览器中输入的 IP 地址。

解决方案 2:

现有的答案都不适合我,因为 WSL2 在自己的 VM 中运行,并且有自己的网络适配器。您需要某种桥接或端口转发才能使非本地主机请求正常工作(即来自同一网络上的另一台主机)。

我在https://github.com/microsoft/WSL/issues/4150中找到了一个可以解决该问题的脚本:

$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
$found = $remoteport -match 'd{1,3}.d{1,3}.d{1,3}.d{1,3}';

if( $found ){
  $remoteport = $matches[0];
} else{
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

#[Ports]

#All the ports you want to forward separated by coma
$ports=@(80,443,10000,3000,5000);


#[Static ip]
#You can change the addr to your ip config to listen to a specific address
$addr='0.0.0.0';
$ports_a = $ports -join ",";


#Remove Firewall Exception Rules
iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";

#adding Exception Rules for inbound and outbound Rules
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";

for( $i = 0; $i -lt $ports.length; $i++ ){
  $port = $ports[$i];
  iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$addr";
  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$remoteport";
}

从提升/管理员权限的 Powershell 会话运行此脚本对我来说很管用。这样就可以从同一端口上的 Windows 主机 IP 访问在端口上运行的 WSL2 服务。

解决方案 3:

这意味着我无法从网络中的另一台 PC 连接到此 Web 服务器。是否可以从外部访问 WSL?

值得注意的是,在所有答案中,这个问题最初是针对 WSL1 的(在询问时给出),并且OP自我回答为是 WSL 或 Windows 问题,已通过 Windows 更新解决。

具有讽刺意味的是,由于 WSL2 的网络通常工作方式(NAT),这是一个已知问题,因此多年后,人们开始在这种背景下发现它(并回答它)。

WSL2 上有多种解决方案。出于历史原因,我将在下面保留两个较旧的解决方案,但现在首选和官方支持的版本是第一个列出的版本:

WSL2 “镜像”网络模式

从 2023 年 9 月的 WSL2 和 Windows 11 更新开始,可以使用新的网络模式设置 - “镜像”。启用后,此模式会将 Windows 网络接口镜像到 Linux 中,从而实现(根据公告):

  • IPv6 支持

  • 使用本地主机地址 127.0.0.1 从 Linux 内部连接到 Windows 服务器

  • 直接从局域网 (LAN) 连接到 WSL

  • 改进了 VPN 的网络兼容性

  • 多播支持

好极了!

要启用此模式:

  1. .wslconfig编辑位于Windows用户配置文件目录中的文件。默认情况下,此文件不存在。如果您对确保拥有正确的文件有任何疑问,请使用 PowerShell 中的以下命令(以普通、非提升/管理员用户的身份):

notepad ($env:USERPROFILE+".wslconfig")
  1. 确保存在以下几行:

[wsl2]
networkingMode=mirrored

旁注:我的理解是,添加firewall=false应该可以让你跳过一些后续步骤,但我无法做到这一点,所以也许我的理解是错误的。如果我了解更多信息,我会更新。目前...

  1. 退出所有正在运行的 WSL 实例

  2. 提升的管理员PowerShell 测试 WSL2 防火墙是否可用:

Get-NetFirewallHyperVVMCreator

如果此命令返回空值,则您可能使用的是较旧的、不受支持的 Windows 版本,或者您的 WSL 需要更新(建议使用 2.0.9.0 或更高版本(wsl --version))。

  1. 假设您从上一个命令收到了一个值,那么(仍然在提升的管理员 PowerShell 中):

* 最简单(完全禁用 WSL2 防火墙):


Set-NetFirewallHyperVVMSetting -Name ((Get-NetFirewallHyperVVMCreator).VMCreatorId) -Enabled False
* 最安全(仅允许来自私有网络的流量):


New-NetFirewallHyperVRule `
-DisplayName 'Allow All Inbound Traffic to WSL in Private Network' `
-Name 'WSL Private Inbound Rule' `
-Profiles Private `
-Direction Inbound `
-Action Allow `
-VMCreatorId ((Get-NetFirewallHyperVVMCreator).VMCreatorId) `
-Enabled True

注意:要删除此规则,请运行`Remove-NetFirewallHyperVRule -Name 'WSL Private Inbound Rule'`。^ 感谢这位 Github 用户和评论
  1. 退出管理 PowerShell 会话并返回到正常 PowerShell:

wsl --shutdown
  1. 重新启动 WSL 实例并使用问题中的原始命令进行测试:

python3 -m http.server

从本地网络上的另一台设备,您现在应该能够使用以下方式访问该服务:

* IPv4 或 IPv6:`http://<ip_address>:8000`
* 广播本地网络上的 IPv6 mDNS:`http://<windows_system_name>.local:8000`
* DNS 名称

较旧的解决方案

  • WSL1:首先,只需使用 WSL1。对于大多数(但不是全部)需要从网络上的另一台计算机访问应用程序的 Web 开发任务,WSL1 的网络性能会更好,并且可以很好地运行您的应用程序和工具。WSL2 引入了真正的虚拟化 Linux 内核,但 WSL1 的“假内核”(系统调用转换层)目前仍可很好地完成大多数任务。

在 WSL1 下运行时python3 -m http.server,您将能够通过 Windows 主机的 IP 地址(或 DNS 名称)自动从网络上的其他计算机访问它。正如 OP 在自我回答中提到的那样,那个讨厌的 WSL1 错误已经修复多年了。


  • SSH 反向隧道如果您确实需要使用 WSL2,这里有一个选项,它不需要端口转发或任何高级防火墙规则,每次 WSL 重新启动时都需要更新这些规则。这些规则的问题在于,每次重新启动时 WSL 的 IP 地址都会发生变化,这意味着必须不断删除并重新创建这些规则。

另一方面,我们可以在 WSL2 中使用 SSH 连接到 Windows,其中名称甚至 IP 地址都是恒定的。

一次性设置:启用 SSH

虽然需要进行一些一次性设置,但无论如何它都很有用:

首先,安装/启用 Windows OpenSSH 服务器。这是 Windows 内置的功能,只需启用即可。您可以在此处找到完整说明,但通常只需执行以下操作(从管理员 PowerShell 中):

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
    Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
    New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
} else {
    Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
}

编辑C:ProgramDatasshsshd_config并设置GatewayPorts yes。这使我们能够使用 SSH 作为网络上其他设备的网关。

最后,当然,您需要在 Windows 中设置防火墙规则,以允许您使用的 HTTP(s)(或其他)端口。示例(来自 Admin PowerShell):

New-NetFirewallRule -DisplayName "WSL Python 8000" -LocalPort 8000 -Action Allow -Protocol TCP

并重新启动 OpenSSH Server 服务:

Restart-Service sshd

创建隧道

有了这个,创建我们需要的隧道就很简单了:

ssh -R 8000:localhost:8000 NotTheDr01ds@$(hostname).local

当然,NotTheDr01ds如果与 WSL 用户名不同,请用你自己的 Windows 用户名替换

由于 SSH 在 Windows 端运行,因此这将使用您的Windows用户名和密码。

一旦确保它可以正常工作,还有另外两个建议:

+ 设置基于密钥的身份验证,这样您就不需要每次都输入密码
+ 将 SSH 连接更改为:
ssh -fN -R 8000:localhost:8000 NotTheDr01ds@$(hostname).local

这会将 SSH 会话置于后台并且不为其分配终端。

解决方案 4:

请按照erazerbrecht分享的链接中提到的步骤,通过提供您的 IP 地址(而不是使用localhost)和端口号来运行您的 HTTP 服务器。

示例(以 root 身份):

cd ~
python3 -m http.server -b 192.168.1.178 8000

输出:

Serving HTTP on 192.168.1.178 port 8000 (http://192.168.1.178 :8000/) ...

否则,您也可以这样做,而不是点击链接:

  1. 从左侧菜单进入Windows Defender防火墙 →高级设置

  2. 选择入站

  3. 创建新规则Next

  4. 选择程序作为规则类型;Next

  5. 选择所有程序Next

  6. 选择允许连接Next

  7. 检查所有三个(私人公共);Next

  8. 为规则提供名称

  9. Finish

  10. 你可以走了

解决方案 5:

避免使用网络上某些答案中使用的防火墙规则。我看到其中一些创建了某种允许所有防火墙规则(允许来自任何 IP 地址和任何端口的任何流量)。这可能会导致安全问题。

只需使用此答案中的这一行,它对我来说非常有效(它只是创建一个端口代理):

netsh interface portproxy add v4tov4 listenport=<windows_port> listenaddress=0.0.0.0 connectport=<WSL_port> connectaddress=<WSL_IP>

其中是WSL<WSL_IP>的 IP 地址。您可以通过在 WSL 上运行来获取它。此外, 是 Windows 将监听的端口,是服务器在 WSL 上运行的端口。ifconfig`<windows_port>`<wsl_port>

您可以使用以下命令列出当前端口代理:

netsh interface portproxy show all

解决方案 6:

目前(2022 年 3 月),要从外界访问在 WSL 2 上运行的应用程序,我们需要执行以下操作:

  • 在防火墙中制定规则,以接受应用程序正在运行的协议和端口上的传入(和传出)连接(例如TCP/80

  • 获取 WSL 的 VM IP 地址:hostname -I

  • 正如本页 (从局域网 (LAN) 访问 WSL 2 发行版) 所述,使用此 IP 地址在 Windows 中添加一个代理,该代理侦听端口并重定向到 WSL 的 VM。这可以通过以管理员身份运行的 PowerShell 中的以下命令完成:

netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=192.168.101.100

192.168.101.100VM 的 IP 地址来自哪里hostname -I以及80我们想要向外部开放的端口。

由于 WSL 的 IP 地址在重新启动时会发生变化,因此应在 PowerShell 脚本中自动执行此操作,其中删除以前的代理并将新代理设置为当前 IP 地址。所有功劳都归功于 GitHub 上的 Edwindijas,此脚本深受他的启发:

$ports=@(80,21,22) # the ports you want to open
$addr='0.0.0.0';

$wslIP = bash.exe -c "hostname -I"

if(! $wslIP -match 'd{1,3}.d{1,3}.d{1,3}.d{1,3}') {
  echo "WSL's IP cannot be found. Aborting";
  exit;
}

$portsStr = $ports -join ",";
iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $portsStr -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $portsStr -Action Allow -Protocol TCP";

for ($i = 0; $i -lt $ports.length; $i++) {
  $port = $ports[$i];
  iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$addr";
  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$wslIP";
}

解决方案 7:

与countach 的答案类似,但使用iproute2:

如果使用 Ubuntu,请在 WSL 终端中输入。查找显示某个小数字在哪里的ip address条目。那里有一个 IP 地址。使用它。#: eth0 ...`#`

解决方案 8:

我遇到了同样的问题,我必须从我的 WSL 机器(ubuntu)访问本地主机

在 wsl 中运行的服务器

因此,由于这是一个虚拟机,因此无法在浏览器中直接访问该 URL,但您可以将其想象为在同一本地网络上运行的机器,并以此方式访问它,为此只需在 ubuntu 中打开一个新终端并运行

是否配置

如果你的 wsl 中没有安装,只需运行

sudo apt 安装 net-tools

您可以在那里看到可以通过浏览器直接访问的 inet 地址

![广播地址

例如,在我的情况下,我可以通过以下方式在浏览器中访问服务器:

http://172.23.157.59:8000/

解决方案 9:

在此处输入图片描述

目前有一个适用于该情况的 npm 包:

npx expose-wsl@latest

解决方案 10:

看一下 Microsoft 文档,从 Windows(localhost)访问 Linux 网络应用程序

根据文档,如果你运行的是旧版本的 Windows(Build 18945 或更低版本),则需要获取 Linux 主机虚拟机的 IP 地址

在 Windows 10 Build 18945 (2019-07-19)发布后,这应该不是一个问题。

解决方案 11:

我编写了一个 PowerShell 脚本,其中使用了两个对我来说非常有效的简单命令。

# Get the IP address of the WSL
$str = wsl -- ip -o -4 -json addr list eth0 | ConvertFrom-Json | %{ $_.addr_info.local } | ?{ $_ }
echo "WSL IP address: $str"

# Establish the connection with the WSL
# listenport,connectport ports can be changes as per the needs
netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=$str

使用此代码创建一个.ps1文件并从 PowerShell 终端执行它。它可以添加到调度程序中,以便每次 Windows 启动时都会运行该脚本。

解决方案 12:

我按照@toran-sahu 的回答向 Windows Defender 防火墙添加了入站规则,但最近(添加第二个 wsl2 实例后)它又停止工作了。我遇到了这个问题线程,在 cmd 提示符中运行以下命令使它再次正常工作。

wsl --shutdown

更新:看来此问题是由于启用了快速启动而引起的https://stackoverflow.com/a/66793101/8917310

解决方案 13:

对我有用的修复(cisco vpn 连接后无法访问网络)。使用 windows regedit 路径 -> HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss 更改 NatNetwork 和 NatGatewayIpAddress 中的值(例如 192.168.77.1 和该范围内的子网)

解决方案 14:

您可以使用此工具添加所需的netsh防火墙规则,以便从 Windows 和网络中的其他主机访问该服务。

简单写一下:

pfwsl add 8000

在 PowerShell 中,它将使您指定的端口可访问。

要禁用它,请写入pfwsl rm。要列出当前启用的,请写入pfwsl ls

我是作者

解决方案 15:

我已经在重新安装的 WSL上测试了Microsoft Windows 更新(KB4532132) ,并且它可以按预期运行。

该问题似乎与旧的 Windows 版本或旧的 WSL 版本有关。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用