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

时间:2020-04-02 23:14:26

标签: ruby-on-rails windows-subsystem-for-linux puma wsl-2

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

为进一步清楚起见,我在localhost:3000上运行Puma服务器

我尝试了以下操作:

  1. 直接连接到分配给以太网适配器vEthernet(WSL)的IP地址-> 172.26.208.1:3000
  2. 直接连接到主机的IPv4地址-> 192.168.0.115
  3. 添加防火墙例外(使用Bitdefender)
  4. 绑定myMap.insert({pts.at<Point>(5), true});以上的IP

到目前为止,以上方法均无效...我想做的是:

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

我是否缺少至少可以正确看到该网站的内容? (以及对VScode部分的任何评论都将受到赞赏)

13 个答案:

答案 0 :(得分:12)

观看此视频,对我有帮助:

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

不要忘记在此之后发表反馈。

答案 1 :(得分:10)

选项1:使用端口转发

这个为我工作:

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

该脚本中的防火墙命令在我的系统上不起作用。因此,我完全停用了Windows防火墙,并使用以下剥离的版本。 (最终用户还是会使用3d派对防火墙,这样就可以了。)

$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=@(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接口portproxy不支持UDP通信的端口警告。

选项2:桥接模式

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

WSL2默认为NAT模式。那里的wsl2系统在除主机之外的另一个子网中具有另一个IP。 PC来自外部对等方,只有Windows IP才可见,而wsl2 ip / net是隐藏/内部的。因此,所有流量都需要Windows IP接受,然后转发到wsl2 ip(端口转发)。

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

启用桥接模式

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

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

选择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

注意事项

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

答案 2 :(得分:9)

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

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

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

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

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

答案 3 :(得分:4)

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

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 地址是动态的。

答案 4 :(得分:3)

让您的WSL2发行版具有与网络上其他任何客户端相同的行为

在Roelofs建议2的基础上,这是使我的情况不停变化的原因。我太新鲜了,只可惜发表评论。

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

我的目标:
从网络上的客户端获取rtmp流,使其往返于Ubuntu计算机上运行的nginx服务器。

建造桥梁

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

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

使虚拟机保持健康状态

重新启动后,我现在可以从主机访问Internet,网桥设置为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,但不能ping广域网。

将条目添加回:

sudo ip route add default via 192.168.1.1 dev eth0

现在可以Ping WAN IP,但没有DNS解析。 LMGTFM:Adding permanent DNS 万一解决方案丢失了,这里就是归功于非静态

Create a file: /etc/wsl.conf.
Put the following lines in the file

[network]
generateResolvConf = false

In a cmd window, run wsl --shutdown
Restart WSL2
Create a file: /etc/resolv.conf. If it exists, replace existing one with this new file.
Put the following lines in the file

nameserver 8.8.8.8

Or the IP of whatever DNS server you want to use, repeat step 3 and 4.

因此,最后,请检查路由并正确设置DNS-conf。不幸的是,每次重启WSL时IP设置都会恢复。如果您不确定每次手动执行此操作,都将讨论如何herehere使其自动化。我没有时间找到我的最爱。

最好的问候 亚历山大

答案 5 :(得分:1)

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

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

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

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

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

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

(我目前正在使用此精确设置从LAN上的iOS应用访问WSL2上的Django开发服务器。)

答案 6 :(得分:0)

不幸的是,对我来说,这是一种简化的情况,因为我的家庭网络是由路由器定义的。由于我的家庭设备无法使用背对背连接进行通信,并且我的网络受到路由器防火墙的保护,因此我必须遵守路由器的配置。

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

答案 7 :(得分:0)

  1. 在WSL上安装ssh服务器

  2. 在Windows上找到一些ssh客户端

  3. 在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)

答案 8 :(得分:0)

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

  1. 开始使用wsl
  2. 保留wsl shell,并检查所有发行版是否已停止(wsl -l -v)
  3. 修改后的WSL虚拟交换机
  4. 再次启动wsl

答案 9 :(得分:0)

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

  1. 使用“ ifconfig”查找您的wsl2公共IP地址。请记住,Windows每次重新启动时,Hyper-V交换机IP都会更改,因此wsl2中的Public IP也将更改。 enter image description here
  1. 使用上一步在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发行版通过wsl2将使用的端口 听。

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

使用cmd或PowerShell作为管理员来运行上述命令。

答案 10 :(得分:0)

这是我发现要进行局域网开发以访问在WSL2(Windows 10 20H2上的Ubuntu 20)上运行的程序的全部步骤:

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

Windows防火墙处于打开状态-请勿将其关闭!-并且默认情况下它应阻止入站尝试。

以下内容将打开端口19000–19006(入站), ,但仅在您配置为“专用”的网络上 (即-Profile Private部分):

19000-19006替换为您需要的端口。

(以powershell作为管理员)

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

(您可以在以后使用Get-NetFirewallRule |Where-Object {$_.DisplayName -Match "Expo.*"}进行检查)

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

(我不确定WSL IP地址多久更改一次,但我怀疑只有重启才能实现)

我在网上看到了东西,包括此处的其他答案,对connectaddress=127.0.0.1说了portproxy,但对我来说(没有)有用(WSL2,Windows 10 20H2)。 我不能说为什么其他人发现它起作用,我只能说重复测试对我来说证明127.0.0.1不起作用,但是WSL IP地址起作用了。

因此,这是一个可重用的命令,用于将connectaddress自动设置为正确的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地址

(例如,世博会的QR码移动应用)

您需要在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访问权限。

答案 11 :(得分:0)

最后我得到了一个解决方案,它必须在 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
  • 使用 localhost 而不是获取正在运行的 WSL2 实例的 IP 地址的想法是由 Charl Botha 在这里从 this answer 收集的。

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

答案 12 :(得分:-4)

尝试-b 0.0.0.0 那就是在其他操作系统上能用的