通过本地网络连接到 WSL2 服务器

Posted

技术标签:

【中文标题】通过本地网络连接到 WSL2 服务器【英文标题】:Connecting to WSL2 server via local network 【发布时间】:2020-07-15 01:54:41 【问题描述】:

我正在我的 Windows 10 机器上使用 WSL2/Ubuntu 开发一个 rails 应用程序,这太棒了! 问题是我无法从同一网络中的另一台计算机连接到我的服务器

为了更清楚,我在 localhost:3000 上运行 Puma 服务器

我尝试了以下方法:

    直接连接到分配给以太网适配器 vEthernet (WSL) 的 IP 地址 -> 172.26.208.1:3000 直接连接宿主机的IPv4地址->192.168.0.115 添加防火墙例外(使用 Bitdefender) 绑定以上IP地址rails s -b 172.26.208.1 -p 3000

到目前为止,上述方法都没有奏效......我想做的是:

在另一台笔记本电脑/平板电脑/手机上测试网站 在另一台计算机上使用 VScode

为了至少能正确查看网站,我有什么遗漏吗? (以及 VScode 部分的任何 cmets 将不胜感激)

【问题讨论】:

【参考方案1】:

WSL2-PortForward.cmd

@ECHO OFF
REM ** Set WSL Distro, Distro Port, Host Port
SET LXDISTRO=WinKDE
SET WSL2PORT=3389
SET HOSTPORT=13389
REM ** Reset any existing port proxies and delete any stale firewall rule
NETSH INTERFACE PORTPROXY RESET & NETSH AdvFirewall Firewall delete rule name="%LXDISTRO% Port Forward" > NUL
REM ** Get IP from WSL2 instance and write it out to IP.tmp
WSL -d %LXDISTRO% -- ip addr show eth0 ^| grep -oP '(?^<=inet\s)\d+(\.\d+)3' > IP.TMP
REM ** Read IP.tmp back into batch variable
SET /p IP=<IP.TMP
REM ** Create the port proxy
NETSH INTERFACE PORTPROXY ADD v4tov4 listenport=%HOSTPORT% listenaddress=0.0.0.0 connectport=%WSL2PORT% connectaddress=%IP% 
REM ** Create a new firewall rule for the port listening on the LAN
NETSH AdvFirewall Firewall add rule name="%LXDISTRO% Port Forward" dir=in action=allow protocol=TCP localport=%HOSTPORT% > NUL
REM ** Summary
ECHO WSL2 Virtual Machine %IP%:%WSL2PORT%now accepting traffic on %COMPUTERNAME%:%HOSTPORT%

输出::

WSL2 Virtual Machine 172.17.109.95:3389 now accepting traffic on MYCOMPUTER:13389

【讨论】:

【参考方案2】:

所以,过去两天我为此苦苦挣扎了一段时间,在这个线程或其他地方似乎没有任何效果。我终于通过拼凑我看到的一些东西来解决它,我想我会在这里发布我的解决方案,以防它帮助任何人。不过有一些注意事项。首先,我绝对不是 Linux 专家,所以“它可以工作”只是我真正唯一考虑的 :) 其次,这是在家庭开发服务器上,这意味着安全不是我最关心的问题(服务器不是以任何方式暴露在我的局域网之外),所以我做了一些我不会在真正重要的机器上做的事情。最后,我并不需要它一直工作,这意味着我可以在服务器重新启动后自己做一些事情以使其全部工作。

考虑到所有这些,第一步是,如上所述,将 WSL 适配器与服务器的物理适配器桥接。在我的例子中,服务器有一个静态 IP,所以我配置了网桥适配器,结果是 IPv4 的静态 IP、网关和 DNS 服务器。

之后,我在我的主目录中编写了以下名为 startup_tasks.sh 的脚本:

#!/bin/bash

clear
echo Running startup tasks...

# Clear existing IP config
sudo ip addr flush eth0
echo .
sleep 2
# Add static IP
sudo ip addr add 192.168.1.100/24 dev eth0
echo .
sleep 2
# Remove existing default gateway
sudo ip route del default
echo .
sleep 2
# Add default gateway
sudo ip route add default via 192.168.1.1
echo .
sleep 2
# Remove existing name resolution config file
sudo rm /etc/resolv.conf
echo .
sleep 2
# Create name resolution config file
sudo touch /etc/resolv.conf
echo .
sleep 2
# Update permissions on file so we can edit it
sudo chmod 777 /etc/resolv.conf
echo .
sleep 2
# Add name servers
sudo echo "nameserver 8.8.8.8" >> /etc/resolv.conf
echo .
sleep 2
sudo echo "nameserver 1.1.1.1" >> /etc/resolv.conf
echo .
sleep 2

echo - Static IP set
echo .
echo ...done!

为此,我还必须确保我的用户帐户在没有密码的情况下具有 sudo 权限,因此将其添加到 sudoer 的文件中:

devuser=(ALL) NOPASSWD:ALL

我只是在服务器重新启动后运行该脚本,结果是 WSL 获得了一个静态 IP 地址,并且我运行的所有服务器(都在 Docker 容器中,尽管我从上面的脚本中删除了所有这些)都可以访问。

对我来说,就是这么简单。

我还考虑过编写一个简单的 .vbs 文件并将其放在我的启动文件夹中,以便在自动重启后运行该脚本。这应该可以正常工作并使其完全自动化,但我还没有这样做。

【讨论】:

【参考方案3】:

另一种解决方案是将 WSL2 直接桥接到相关的网络适配器。我尝试在 Hyper-V 中执行此操作,但无法使其正常工作。然而,起作用的是Control Panel\Network and Internet\Network Connections,选择网卡(在我的例子中是Ethernet 3)和vEthernet (WSL),然后通过右键单击并选择“桥接”来桥接它们:

你应该得到这样的结果:

在桥设置好之后,让 Windows 做一分钟左右(说真的!),然后再继续。

接下来打开 WSL 并让它运行 dhcp 以获取新地址:

sudo ip addr flush dev eth0 && sudo dhclient eth0

此时,WSL 和 Windows 都应该具有连接性。通过 ping 一些 IP 地址(如 1.1.1.1 或 8.8.8.8)进行检查。如果这不起作用,请拆除桥并重试。请记住在 Windows 配置所有内容时等待一两分钟。

此外,请确保 eth0 具有来自您的 LAN (ip addr sh eth0) 的地址。

现在的问题是 WSL 可能无法解析域名,因为 WSL 在启动时创建 /etc/resolv.conf 指向不再存在的虚拟网关。这可以通过要求 wsl 不要创建 /etc/resolv.conf 来解决,方法是将以下内容附加到 /etc/wsl.conf (如果文件不存在,则创建文件):

[network]
generateResolvConf=false

然后通过重启LxssManager windows 服务来重启wsl。 唯一剩下的就是在 WSL 中设置备用 DNS 服务器。而不是生成的/etc/resolv.conf,只需创建一个/etc/resolv.conf,如下所示:

nameserver 1.1.1.1
nameserver 1.0.0.1

就是这样! WSL 现在应该已桥接到您的网络,并在其上拥有自己的唯一地址。

【讨论】:

【参考方案4】:

这是我发现的完整的三个步骤,可用于 LAN 开发访问在 WSL2 中运行的东西(Windows 10 20H2 上的 Ubuntu 20):

1。一开始:在 Windows 防火墙中打开 Expo 端口入站

Windows 防火墙应该打开——不要关闭它!——默认情况下它应该阻止入站尝试。

以下将打开端口 19000–19001,入站,但仅在您配置为“私有”的网络上(即-Profile Private 部分,如果您在域中,请替换为 Domain):

19000-19001 替换为您需要的端口。 将DisplayName 替换为适合您的。方便以后查找规则。

(powershell 作为管理员)

New-NetFireWallRule -Profile Private -DisplayName 'Expo ports for LAN development' `
    -Direction Inbound -LocalPort 19000-19001 -Action Allow -Protocol TCP

(您可以在之后使用 Get-NetFirewallRule |Where-Object $_.DisplayName -Match "Expo.*" 进行检查 - 将 -Match 参数替换为您选择的 DisplayName)

2。将portproxy指向WSL;重新运行“每次 WSL 有一个新的 IP 地址”

(我还不确定 WSL IP 地址多久更改一次,但我怀疑只有重新启动才会)

我在网上看到了一些东西,包括这里的其他答案,说 portproxy 到 connectaddress=127.0.0.1,但它确实对我有用(WSL2、Windows 10 20H2)。 我不能说为什么其他人发现它有效,我只能说重复测试为我确认127.0.0.1 无效,但 WSL IP 地址有效。

所以这里有一个可重用的命令来自动将连接地址设置为正确的 WSL 地址:(powershell — 仅用于简单的内联 Trim() — 作为管理员)

netsh interface portproxy add v4tov4 listenport=19000 listenaddress=0.0.0.0 `
    connectport=19000 connectaddress=$($(wsl hostname -I).Trim());

netsh interface portproxy add v4tov4 listenport=19001 listenaddress=0.0.0.0 `
    connectport=19001 connectaddress=$($(wsl hostname -I).Trim());

3。 (可选)如果您的 WSL 需要知道您的开发机器 LAN IP 地址

(例如 Expo 等二维码移动应用)

您需要在 WSL 中重新运行以下命令“每次开发主机都有一个新的 IP 地址”

这可能是变化最频繁的一个。当您更改网络(例如家庭/办公室)时,您的笔记本电脑本地网络 IP 肯定会发生变化,并且在其他时间也会发生变化。

幸运的是,它也是可粘贴/可别名的:WSL2 shell

netsh.exe interface ip show address "Wi-Fi" | grep 'IP Address' | sed -r 's/^.*IP Address:\W*//'

# e.g. for Expo, I used:
export REACT_NATIVE_PACKAGER_HOSTNAME=$(netsh.exe interface ip show address "Wi-Fi" | grep 'IP Address' | sed -r 's/^.*IP Address:\W*//')

echo Meteor will use dev machine IP address: $REACT_NATIVE_PACKAGER_HOSTNAME

我“希望我不必重新运行,一切都可以自动化”, 但同样的懒惰让我很高兴至少让命令 2(和 3)易于“重新运行”并始终如一地获得我需要的 WSL2 托管服务的 LAN 访问权限。

【讨论】:

这是唯一有效的答案! 顺便说一句,它在 HTTP 服务器上工作得很好。但是我无法让我的 DNS 服务器正常工作。 Pi-Hole 在 WSL2 中运行,我进行了端口转发设置。我可以看到端口 53 TCP 正在侦听 Windows 和 WSL2。但是外部客户端不能使用 DNS 服务器......有什么想法吗? "我可以看到端口 53 TCP 正在侦听... windows .... 但是外部客户端无法使用 DNS 服务器" 有趣的场景! @ShinebayarG 你是说你 are 能够在 wsl 中使用 pihole 作为你的 Windows 名称服务器吗?即问题是即使您为5380 配置了windows portproxy,当您将其他网络内设备的名称服务器配置为指向您的Windows 设备(它将使用这些端口)时,这不会'不作为名称服务器为他们工作? @ShinebayarG 你没有错过什么,我粘贴了错误的链接!我打算从 serverfault 分享这个:serverfault.com/a/472692/117183 正确@Abdull;关于Domain profile 是另一个安全的选择,我将把它添加到答案中。对于Public 个人资料,您需要真的 强调一个关于“......这也工作,但是你正在打开一个端口 - 运行“dev”软件 — 在公共网络上。”... 真的要问一个问题,为什么我要在我无法信任的网络上进行基于网络的开发工作,所以我将其配置为“公共”?但是,如果有理由说明这是一个安全和良好的情况,可以这样做。【参考方案5】:

WSL2 在本地接口上公开端口(这就是为什么在 Windows 中,当您的 8080 服务在 WSL2 中运行时,您可以访问 localhost:8080),但它们侦听 127.0.0.1(这就是您无法访问的原因) yourhostname:8080 在您 LAN 的其他计算机上)。

有一个名为 WSLHostPatcher 的工具可以解决此问题,您可以在此处找到(通过“发布”部分下载):https://github.com/CzBiX/WSLHostPatcher

WSLHostPatcher 将行为更改为侦听所有 IP,将任何 WSL2 服务暴露给您网络上的所有计算机。

    从https://github.com/CzBiX/WSLHostPatcher/releases下载最新版本(我测试了v0.1.0) 解压文件 运行WSLHostPatcher.exe (重新)在 WSL2 中启动您的服务

现在应该可以通过网络上的其他计算机访问该服务了。

【讨论】:

这听起来不错,但说明不起作用。没有 WSLHostPacher.exe 文件。回购中没有多少明星......这是合法的吗? WSLHostPatcher.exe 位于 release.zip 文件中。如果您持怀疑态度,您可以在检查源代码后自己从 repo 编译它。不是我的回购所以我不能保证! 在这里和那里花了几个小时之后,这对我来说就像一个魅力。非常感谢。 这不适用于 udp 端口​​【参考方案6】:

首先,您需要在您的机器上打开一个端口,以便能够从您的网络访问它。

netsh advfirewall firewall add rule name="Allowing LAN connections" dir=in action=allow protocol=TCP localport=5000

打开端口(在我的例子中为 5000)后,您需要将此端口转发到您的应用在 WSL 中侦听的端口。

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=5000 connectaddress=localhost connectport=<the port that your app is listening on>

注意:我将 connectaddress 设置为 localhost 而不是 WSL 的 IP 地址,因为默认情况下,转到 localhost 的请求是转发到 WSL。通过这样做,您无需在每次重新启动计算机时都设置端口转发,因为 WSL 的 IP 地址是动态的。

【讨论】:

我不知道为什么这不是最佳答案。它基本上是两个 PowerShell 粘贴,无需下载。 嗯,localhost 对我不起作用 - 我必须直接指定 WSL ip 地址。 这是否适用于相同的端口?编辑:似乎没有。 (本地主机到 0.0.0.0)。 是的,这里也一样。 localhost 不起作用,必须使用 WSL 的实际 IP。 (Ubuntu WSL 中的命令 'ip addr' 给了我相关地址) 只有 localhost 或 127.0.0.1 对我有用。在我的情况下,指定 WSL ip 不起作用。【参考方案7】:

最后我得到了一个解决方案,它必须在 Windows 主机启动后运行一次,同时与多个 WSL2 实例一起工作,并且在 WSL2 实例重新启动时不必重新运行!

缺点:无法在 0.0.0.0 上收听;您必须指定 IP 或适配器才能显式侦听。 (此版本仅侦听一个 IP 地址,但可以轻松扩展为使用列表)。

$ports = @(8000,8001);     # ports to forward
$iface = "Ethernet";       # alias of the Adapter to listen on

# if your host has a fixed IP, you can specify it here explicitly
# and remove the ping-and-if safeguard;
# but 0.0.0.0 won't work!
$external_ip = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias $iface).IPv4Address;

ping -n 1 "$external_ip" > $null

if( !$?  ) 
    echo "error: cannot determine the external IP address";
    exit 1;


$firewall_rule_name = "WSL2 Firewall Hole"
Remove-NetFireWallRule -DisplayName "$firewall_rule_name"

New-NetFireWallRule -DisplayName "$firewall_rule_name" -Direction Outbound -LocalPort $ports -Action Allow -Protocol TCP
New-NetFireWallRule -DisplayName "$firewall_rule_name" -Direction Inbound -LocalPort $ports -Action Allow -Protocol TCP

ForEach( $port in $ports ) 
    netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$external_ip
    netsh interface portproxy add v4tov4 listenport=$port listenaddress=$external_ip connectport=$port connectaddress=127.0.0.1

学分:

起点是 edwindijas 在 WSL Github 问题 #4150 上的 this script。 Charl Botha 在此处从 this answer 收集到使用 localhost 而不是获取正在运行的 WSL2 实例的 IP 地址的想法。

原始 edwindijas 的脚本对我不起作用,因为我在受限用户下运行 WSL2,脚本必须以管理员身份运行,并且以管理员身份运行 bashwsl -e 获得一个具有不同 IP 的新 WSL2 实例地址。

【讨论】:

好的,你转发 8000,8001 端口并且...?接下来是什么?有什么实际用途?【参考方案8】:

看这个视频,它对我有帮助:

https://www.youtube.com/watch?v=yCK3easuYm4

netsh interface portproxy add v4tov4 listenport=<port-to-listen> listenaddress=0.0.0.0 connectport=<port-to-forward> connectaddress=<forward-to-this-IP-address>

例如

netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=172.30.16.3

微软已经在他们的WSL1 to WSL2 comparison page上发布了一些关于这方面的信息

不要忘记在之后提出反馈。

【讨论】:

谢谢,这很好用。对于不想观看整个视频的任何人,这需要在提升的 powershell 提示符下运行,而不是来自 WSL,connectaddress 应该是您的 WSL IP,您可能需要允许端口通过 windows防火墙。旁注,这与顶部答案中的脚本所做的相同,但很高兴只看到必要的命令而不是整个脚本。 不幸的是对我不起作用。我正在尝试用我的 iPhone 连接到我的本地网络服务器(以测试网站的移动版本)。我的代码在 WSL 机器上运行,并在端口 1337 上的 npm start 之后打开服务器。所以我输入了这个netsh interface portproxy add v4tov4 listenport=1337 listenaddress=0.0.0.0 connectport=1337 connectaddress=127.22.240.165。我虽然可以在我的 iPhone 上尝试:192.168.1.32:1337 但也许我误解了程序.. 有什么帮助吗? 你能从本地机器访问你的服务器吗?它应该是:127.22.240.165:1337,如果不是,那是你的问题与你的服务器应用程序有关。如果是,请尝试禁用防火墙,或者您的 wsl ip 地址错误,请仔细检查。试试桥接模式,因为这个方法是临时用的,因为每次重启主机时ip地址都会改变。 是的,我可以通过 http://127.22.240.165:1337 从 Windows 访问该应用程序。我试图禁用 Windows 防火墙并在手机上再次测试,但它仍然没有响应。另一方面,netsh ... 命令没有输出任何东西;我预计它会在第一次尝试时唤醒防火墙,但没有。也许“portproxy”没有任何效果。如何检查 Powershell 上设置了哪些代理? 不要忘记将监听端口添加到防火墙以便能够连接:netsh advfirewall firewall add rule name= "Open Port 3000" dir=in action=allow protocol=TCP localport=3000【参考方案9】:

考虑到上述(正确)解决方案,这是一个适用于我的简化单衬版本:

    使用“ifconfig”查找您的 wsl2 公共 IP 地址。请记住,每次 Windows 重新启动时,Hyper-V 交换机 IP 都会发生变化,因此 wsl2 中的公共 IP 也会发生变化。

    使用上一步在connectaddress参数中找到的IP运行以下命令:

    netsh interface portproxy add v4tov4 listenport= listenaddress=0.0.0.0 connectport= connectaddress=172.24.26.277

参数说明:

listenport:Windows 将监听的端口

listenaddress:您的 Windows 将监听的地址。通常 0.0.0.0 应该可以。

connectport:您的 Linux Distro 通过 wsl2 将连接的端口 听。

connectaddress:你的 Linux wsl2 实例的公网 IP (在步骤 1 中找到)

以管理员身份使用 cmd 或 PowerShell 运行上述命令。

【讨论】:

您必须允许该端口通过 Windows 防火墙,并将其转发到您的路由器上。请注意,每次重新启动实例时都会重新分配 WSL2 IP 地址。 而且你不需要做ifconfighostname --all-ip-addresses 完成这项工作。【参考方案10】:

这里的解决方案可能比已提供的许多其他解决方案更简单。除了您正在使用的 WSL2 实例之外,您还需要一个安装了 socat 的 WSL1 实例。

在 WSL1 实例上,像这样启动 socat

socat -d TCP-LISTEN:3000,reuseaddr,fork TCP:localhost:3000

当您像这样启动 socat 时,Windows 会询问您是否要允许网络访问该端口。确认。

确保您的 puma 绑定到所有接口上的端口 3000。

您现在可以从 LAN 访问您的开发服务器。这里发生的情况是,socat 将请求转发到您的以太网端口上的 3000 到 localhost 上的端口 3000,这将神奇地被 Windows 转发到 WSL2。

(我目前正在使用这个确切的设置从我 LAN 上的 ios 应用程序访问我在 WSL2 上的 Django 开发服务器。)

【讨论】:

虽然有基于socat 的solutions 对我有用,但这会导致“分叉风暴”,因为端口3000 连接分叉到3000 的连接,这会分叉到3000 的另一个连接,并且以此类推,直到我运行了这么多socat,然后我才能打断它,以至于我的 Windows 主机被带到了爬行状态(这不是一个懒散的状态)。 这很奇怪,我使用这个精确的公式,但使用端口 8000,来自 WSL1,以便使用我的 iPhone 访问在我的 WSL2 上运行的 Django。我们的两种配置之间肯定还有其他区别。 同意。我在想这可能与之前尝试(在我的)中的一些剩余转发规则有关,但我认为我清除了所有内容(例如netsh interface portproxy)。我将在另一个端口上尝试以确保,但失败几乎意味着重新启动,所以我必须等到我准备好。【参考方案11】:

让您的 WSL2 发行版像您网络上的任何其他客户端一样运行

在 Roelofs 建议 2 的基础上,这就是我的案例中所有内容的原因。不幸的是,我太新鲜了,不能发表评论。

我的出发点: 赢 10 专业版 WSL2下的Ubuntu (带有 Linux 容器的 Docker)

我的目标: 从网络上的客户端获取 rtmp 流进出运行在 Ubuntu 机器上的 nginx 服务器。

搭建桥梁

就我而言,我无法让 Hyper-V 正确设置网桥。在 Hyper-V 管理器的虚拟交换机部分中为 WSL 交换机选择 外部网络 并点击应用后,它最终失败并出现错误 0x80070490。不知道为什么,也没有时间调查。 WSL 没有运行,Docker 服务也没有运行。

相反,我只是将设置保留在 内部网络 上,并在网络连接 (run->ncpa.cpl) 下以手动方式桥接接口。就我而言,WiFi 连接和 vEthernet (WSL)。 这样做之后,我立即失去了互联网连接,我花了很长时间才发现需要重新启动。 (Windows 曾经没有要求我这样做!)

让虚拟机成型

重启后,我现在可以从主机访问互联网,网桥设置为 DHCP,并继承了 WiFi 接口的 IP (192.168.1.246)。太好了。

然而,VM 仍在获取虚拟交换机的 IP(或者您想查看它,windows 似乎分配给交换机和 VM 的随机 172.x.x.x 地址)。

启动 Ubuntu,我决定做一个:

sudo ip addr flush dev eth0

继续:

sudo dhclient eth0

自从我使用 Windows 商店的香草 Ubuntu 发行版以来,我遇到了一些错误,没有 systemd,没有乐趣。尽管如此,它还是设法将网桥的 IP 添加到 eth0。由于这不是很方便,我摆脱了它:

sudo ip addr del 192.168.1.248/24 dev eth0

但在偷看路由表之前:

user@vm:~$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0

删除旧 IP 后,我从我的 DHCP 范围之外添加了一个唯一的 IP:

sudo ip addr add 192.168.1.50/24 dev eth0

我再次检查了路由表,第一个条目不见了。在这个阶段,我可以 ping LAN 但不能 WAN。

将条目添加回:

sudo ip route add default via 192.168.1.1 dev eth0

现在可以 Ping WAN IP,但无法解析 DNS。 LMGTFM:Adding permanent DNS 万一解决方案丢失,这归功于非静态

创建一个文件:/etc/wsl.conf。
将以下行放入文件中

[网络]
generateResolvConf = false

在 cmd 窗口中,运行 wsl --shutdown
重启 WSL2
创建一个文件:/etc/resolv.conf。如果存在,则用这个新文件替换现有文件。
将以下行放入文件中

名称服务器 8.8.8.8

或者您要使用的任何 DNS 服务器的 IP,重复步骤 3 和 4。

所以,总而言之,检查您的路由并正确设置您的 DNS-conf。不幸的是,每次重新启动 WSL 时都会恢复 IP 设置。如果您每次都在讨论如何自动化它here 和here 时手动执行此操作不满意。我没有时间找到我最喜欢的。

最好的问候 亚历山大

【讨论】:

【参考方案12】:

关于桥接模式 - 当任何 Linux 发行版运行时,Windows 会阻止修改 WSL 虚拟交换机(访问被拒绝错误)。另一方面,WSL 开关是在第一个 Linux 发行版启动时创建的。 我做了如下:

    已启动 wsl 离开 wsl shell 并检查所有发行版是否已停止 (wsl -l -v) 修改了 WSL 虚拟交换机 再次启动wsl

【讨论】:

对我来说,这还不够。我必须取消选中我的网卡上的Hyper-V Extensible Virtual Switch 设置,如下所述:theitways.blogspot.com/2018/01/…【参考方案13】:

    在 WSL 上安装 ssh 服务器

    在 windows 上找一些 ssh 客户端

    在windows上执行:(Windows的IP为192.168.x.x,WSL ip为172.28.x.x)

    ssh -L 192.168.x.x:3000:172.28.x.x:3000 someuser@172.28.x.x

如果不起作用,请尝试使用另一个本地端口,例如 (192.168.x.x:3001:172.28.x.x:3000)

【讨论】:

只是想说,在尝试所有可能的修复 > 6 小时后,绝对没有任何效果(甚至完全禁用防御者/防火墙),最终为我做了什么。我根本无法以任何其他方式从主机外部访问 WSL2 的 IP 地址。谢谢!! ?? 也可以直接在windows上安装netcat来转发端口,不需要在WSL上安装ssh服务器unix.stackexchange.com/questions/293304/…【参考方案14】:

选项 1:使用端口转发

这个对我有用:

    通过脚本从 xmeng1 运行端口转发:https://gist.github.com/xmeng1/aae4b223e9ccc089911ee764928f5486

该脚本中的防火墙命令在我的系统上不起作用。所以我完全停用了 Windows 防火墙并使用以下剥离版本。 (最终用户无论如何都会使用 3d 方防火墙,所以没关系)。

$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
$found = $remoteport -match '\d1,3\.\d1,3\.\d1,3\.\d1,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=@(123,456);

#[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 ",";

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";


#Then so something, e.g.
#bash.exe -c "cd /g-inverter; ./start_docker.sh"

您可能需要在脚本中为 ifconfig “apt install net-tools”。互联网上还有一个“ip addr”的解决方案,它不需要ifconfig”在一个很棒的线程中,我现在没有链接。

警告

这仅适用于 TCP 流量。 netsh interface portproxy 不支持 UDP 流量的端口转发。

选项 2:桥接模式

解决方案:从 NAT 切换到桥接模式

WSL2 默认处于 NAT 模式。 wsl2 系统在另一个子网中有另一个 IP,而不是主机。 PC 来自外部对等方,只有 windows IP 可见,wsl2 ip/net 是隐藏/内部的。所以所有流量都需要被windows IP接受,然后转发到wsl2 ip(端口转发)。

还有另一种模式称为桥接模式。在桥接模式下,您的网络接口卡将与 wsl2 系统共享,并且它将在 wsl2 中获得自己的 IP/Net。所以实际上你的网卡是共享给两个系统(windows / wsl2)并且有两个IP,就好像你有两个系统,每个系统都有自己的网卡。很酷的事情:当 Windows 使用与 wsl2 应用程序(如 111)相同的端口时,您将永远不会发生端口冲突。

启用桥接模式

以管理员身份打开 Hyper-V 管理器

选择你的电脑,打开虚拟交换机管理器

选择 WSL

设置为外网

选择流量经过的网卡

然后登录wsl2终端并配置IP地址。例如

sudo ip addr add 192.168.0.116/24 dev eth0

您需要使用另一个免费 IP(不是您的 Windows IP)。如果您的网络有 DHCP 服务器,您的 wsl 可以通过以下方式获得:

sudo ip addr flush dev eth0
sudo dhclient eth0

警告

我还没有详细说明,如果您希望仍然能够访问互联网(apt 等),如何让 DNS 在这种情况下工作。 MS 有一些文档写在 /etc/resolv.conf 中,可能执行那里写的内容并安装 resolvconf(在上述所有步骤之前,因为一旦开始桥接就没有互联网)可能会奏效。

【讨论】:

更新:这种方法变得乏味,互联网上的线程变得越来越长,人们与之斗争。我们认为 WSL2 对于稳定的服务器托管还不够成熟,最终决定将所有服务器安装在 Windows 上。 WSL2 docker 实例将文件放到 Windows 文件夹中,然后由 Windows 服务器托管。这意味着我们需要在每台 PC 上许可、安装和维护 3d 派对产品。但我们对 WSL2 是否已为行业做好准备的信心不足。我相信这会在几年内变得更好。我们现在 100% 长期稳定。 桥接模式听起来可能是一个很好的解决方案,但我运行 WSL2 的机器没有启用 Hyper-V Windows 扩展,阅读 Hyper-V 文档会担心此功能可能会导致问题。 @Roelof 好吧,选项 1 实际上不起作用:执行上述脚本后(与发布的完全相同)我在 Windows 防火墙上看不到任何其他规则,端口转发也没有工作。此外,我尝试完全关闭 Windows 防火墙 - 仍然没有效果。请问有什么帮助吗?谢谢! “防火墙脚本对我不起作用,所以我完全关闭了防火墙”是个糟糕的建议。防火墙脚本确实对我有用,所以请让您的防火墙完好无损! 选项 2 是不可能的,因为虚拟交换机管理器无法将 wsl 交换机更改为外部。它会抛出一个错误 switch port delete failed ...【参考方案15】:

不幸的是,对我来说,这是一个简化的案例,因为我的家庭网络是由我的路由器定义的。由于我的家庭设备不使用背靠背连接进行通信,并且我的网络受到路由器防火墙的保护,因此我必须尊重路由器的配置。

    有一个 DNS 列表 - 8.8.8.8、8.8.4.4、9.9.9.9 支持我的 ISP DNS。这意味着必须精心制作 resolv.conf。 nslookup 反映了正确的配置。 可以将 DHCP 中继配置为外部 DHCP 我可以定义和配置设备如何获取包括静态租约在内的动态 IP。它假定设备使用正确的 DHCP IP 地址。 当然,我可以为路由器设备配置端口转发。

【讨论】:

【参考方案16】:

试试-b 0.0.0.0 这就是在其他操作系统上的工作原理

【讨论】:

以上是关于通过本地网络连接到 WSL2 服务器的主要内容,如果未能解决你的问题,请参考以下文章

远程访问 WSL2 Jupyter notebook

C# - 连接到 (RAS) *** 时如何获取 IP 地址

vivo手机连不上网显示“无法连接到服务器(1,-10087),请检查你的网络

将 Socket.io 浏览器客户端连接到本地 Node.js 网络服务器

vmware workstation无法连接到虚拟机 怎么解决

通过 WSS 连接到在本地网络上运行的 Polkadot Full Node 失败