前言(碎碎念):每次发布文章时,我都是一个纠结的过程。因为我给自己写笔记时,只需要记录自己不清晰或者易忘的知识点就可以了,但一旦想要作为文章发布,那么我就得考虑到很多人是纯新手(就像我当初一样)。然后我就会一直想着怎么写才能对新手友好。但这样一来,就导致我太贪心了,结果文章越写越不满意,或者越写越繁多。很多太过简单的知识点我是真的一点也不想再记录了(比如最经典的配置环境变量……)。>
_
所以,考虑到本次的文章,本身的内容就已经足够多了,如果还有照顾到那些纯新手的话,文章内容就会变得更多。
_
所以,这篇文章就我就任性一点,只写给自己。
背景
遇到的问题:
- 在 wsl ubuntu 中,发现无法与本机通信
- 能通信后,发现无法访问 github
- 搭建项目后,发现手机无法访问
文章按照顺序看就可以,推荐先简单的简单过一遍,因为其中的有些内容不是必需的,但我觉得很值得分享,所以就保留写来了。
速览 - 直接解释解决方案
想了想,还是提供一个速览吧,如果只想感觉解决问题,可以直接查看速览。
解决问题:在 wsl ubuntu 中,发现无法与本机通信
原因:本机的防火墙策略阻止了 wsl 的入站请求
解决方案:
win+r 允许 WF.msc
,然后放开对 wsl 和以太网的保护策略
解决问题:能通信后,发现无法访问 github
最终原因:国内禁止访问, DNS 解析失败
解决方案一:配置代理:
export https_proxy=http://172.28.160.1:7890 http_proxy=http://172.28.160.1:7890
# 配置代理环境变量,注意 IP 要设置为本机中的 以太网适配器 vEthernet (WSL) IP 地址
curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh -o nvm.sh
# 再次请求,就能够访问了
解决方案二:修改 DNS
sudo sh -c 'rm /etc/resolv.conf && echo "nameserver 114.114.114.114" > /etc/resolv.conf'
解决问题:手机无法访问 wsl 中搭建的服务器,但本机可以
原因:大概率又是防火墙,或者路由解析相关问题。
这里直接使用简单的解决方案:配置 nginx 代理。在 window 中使用 nginx 可以查看 这篇文章
# C:\nginx-1.25.4\conf\nginx.conf
events {
worker_connections 1024;
}
http {
server {
listen 5555;
server_name localhost;
location / {
# 这里要改为你的 wsl 的 ip 地址
proxy_pass http://172.28.172.197:5555;
}
}
}
前提:
- 已经
wsl --shutdown
过,发现无用。 - 手机和电脑使用 USB 网络共享或使用热点
- 已经安装并能正常使用 wsl ubuntu (版本为 22)
- 系统已经开启 Hype-V 选项,参考 这篇文章
- 查看 wsl 版本。如果不一致,那么我的解决方案可能对你无效
$ wsl --version
# WSL version: 2.0.14.0
# Kernel version: 5.15.133.1-1
# WSLg version: 1.0.59
# MSRDC version: 1.2.4677
# Direct3D version: 1.611.1-81528511
# DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
# Windows version: 10.0.19045.3803
先来查看 wsl ubuntu 和本机的 ip
- pwsh 运行 ipconfig
$ ipconfig
# 以太网适配器 vEthernet (Default Switch):
#
# 连接特定的 DNS 后缀 . . . . . . . :
# 本地链接 IPv6 地址. . . . . . . . : fe80::224b:c4d1:4186:5ef%49
# IPv4 地址 . . . . . . . . . . . . : 172.24.48.1
# 子网掩码 . . . . . . . . . . . . : 255.255.240.0
# 默认网关. . . . . . . . . . . . . :
#
# 以太网适配器 vEthernet (WSL): 我们想要的是这个
#
# 连接特定的 DNS 后缀 . . . . . . . :
# 本地链接 IPv6 地址. . . . . . . . : fe80::eb1c:ea3f:60ef:1e01%61
# IPv4 地址 . . . . . . . . . . . . : 172.28.160.1
# 子网掩码 . . . . . . . . . . . . : 255.255.240.0
# 默认网关. . . . . . . . . . . . . :
#
# 以太网适配器 以太网 2:
#
# 连接特定的 DNS 后缀 . . . . . . . :
# IPv4 地址 . . . . . . . . . . . . : 192.168.234.34
# 子网掩码 . . . . . . . . . . . . : 255.255.255.0
# 默认网关. . . . . . . . . . . . . : 192.168.234.99
- ubuntu 运行
ifconfig
,或者ip addr
$ ip addr
# 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
# link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# inet 127.0.0.1/8 scope host lo
# valid_lft forever preferred_lft forever
# inet6 ::1/128 scope host
# valid_lft forever preferred_lft forever
# 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc mq state UP group default qlen 1000
# link/ether 00:15:5d:8e:fd:12 brd ff:ff:ff:ff:ff:ff
inet 172.28.172.197/20 brd 172.28.175.255 scope global eth0
# valid_lft forever preferred_lft forever
# inet6 fe80::215:5dff:fe8e:fd12/64 scope link
# valid_lft forever preferred_lft forever
# 重点查看 inet 的值
$ ip addr | grep inet
# inet 127.0.0.1/8 scope host lo
# inet6 ::1/128 scope host
inet 172.28.172.197/20 brd 172.28.175.255 scope global eth0
# inet6 fe80::215:5dff:fe8e:fd12/64 scope link
可以看到,本机和 ubuntu 是位于同一个局域网(网段)中的(网络号相同)
主机:
IPv4 地址 . . . . . . . . . . . . : 172.28.160.1
子网掩码 . . . . . . . . . . . . : 255.255.240.0
网络编号/网络号为:172.28.160/20
主机号为:1
wsl ubuntu:
inet 172.28.172.197/20 brd 172.28.175.255 scope global eth0
网络编号/网络号为:172.28.160/20
主机号为:12.197
如果两者不再同一个局域网内,则需要修改修改 wsl ubuntu 中的网卡 eth0
sudo ifconfig eth0 172.28.172.197 netmask 255.255.240.0
# 未测试
主机 ping 一下 wsl ubuntu 的 ip,查看是否可以通信
$ ping 172.28.172.197
# 正在 Ping 172.28.172.197 具有 32 字节的数据:
# 来自 172.28.172.197 的回复: 字节=32 时间<1ms TTL=64
# 来自 172.28.172.197 的回复: 字节=32 时间<1ms TTL=64
# 来自 172.28.172.197 的回复: 字节=32 时间<1ms TTL=64
# 来自 172.28.172.197 的回复: 字节=32 时间<1ms TTL=64
可以看到,是能够通信的。
然后,在 wsl ubuntu 中 ping 一下本机,查看能否通信
$ ping 172.28.160.1
# ...
可以发现 ping 不通
排查:先关闭防火墙测试一下是否是防火墙问题
先测试一下是否是防火墙问题。将本机的防火墙统统关闭,然后重新 ping,可以发现成功 ping 通。
然后选择关闭
如果发现还 ping 不同,再尝试关闭 ubuntu 中的所有防火墙。
$ sudo ufw status
# Status: inactive
$ sudo ufw enable
# Firewall is active and enabled on system startup
$ sudo ufw disable
# Firewall stopped and disabled on system startup
总之,我这里的情况是将本机的防火墙关闭后,就可以 ping 通了,
并且 wsl ubuntu 中可以 ping 通本机中的“以太网适配器 vEthernet (WSL)”和“手机提供的 USB 网络”
$ ping 172.28.160.1
# PING 172.28.160.1 (172.28.160.1) 56(84) bytes of data.
# 64 bytes from 172.28.160.1: icmp_seq=1 ttl=128 time=0.236 ms
# 64 bytes from 172.28.160.1: icmp_seq=2 ttl=128 time=0.297 ms
# 64 bytes from 172.28.160.1: icmp_seq=3 ttl=128 time=1.05 ms
# 64 bytes from 172.28.160.1: icmp_seq=4 ttl=128 time=0.631 ms
$ ping 192.168.234.34 # 这个是手机提供的 USB 网络
# PING 192.168.234.34 (192.168.234.34) 56(84) bytes of data.
# 64 bytes from 192.168.234.34: icmp_seq=1 ttl=127 time=0.299 ms
# 64 bytes from 192.168.234.34: icmp_seq=2 ttl=127 time=0.773 ms
# 64 bytes from 192.168.234.34: icmp_seq=3 ttl=127 time=0.555 ms
# 64 bytes from 192.168.234.34: icmp_seq=4 ttl=127 time=0.571 ms
找到原因:关闭防火墙后就能通信,所以大概率是“入站连接”被禁止
本机能够连通 wsl ubuntu,但 wsl ubuntu 却不能连通本机,说明是“入站”被禁止了。
实际上,防火墙中的配置(域、专用、公用),默认都是允许出站连接,阻止入站连接的,所以配置时基本就是配置允许入站连接,或者是禁用出站连接。
放行 wsl ubuntu 的 ip 地址,步骤如下:
- 打开防火墙(win+r 允许
WF.msc
),新建一个入站规则 - 选择自定义规则
- 所有程序
- 直接下一步(协议类型为任何)
- 将规则应用于以下远程 IP 地址。
配置 以太网适配器 vEthernet (WSL),可以两种添加方式
172.28.160.0/20
# 可以添加子网/网段
172.28.172.197
# 也可以直接添加 ip
同理,配置以太网适配器 以太网 2 (也就是手机热点),也可以有两种方式:
192.168.234.0/24
或 192.168.234.34
- 直接下一页(允许连接)
- 直接下一页(包含域、专用、公用)
- 名称 允许 wsl2 入站
再次测试,发现可以 ping 通
$ ping 172.28.160.1
# PING 172.28.160.1 (172.28.160.1) 56(84) bytes of data.
# 64 bytes from 172.28.160.1: icmp_seq=1 ttl=128 time=0.225 ms
# 64 bytes from 172.28.160.1: icmp_seq=2 ttl=128 time=0.531 ms
# 64 bytes from 172.28.160.1: icmp_seq=3 ttl=128 time=0.237 ms
$ ping 192.168.234.34
# PING 192.168.234.34 (192.168.234.34) 56(84) bytes of data.
# 64 bytes from 192.168.234.34: icmp_seq=1 ttl=127 time=0.242 ms
# 64 bytes from 192.168.234.34: icmp_seq=2 ttl=127 time=0.594 ms
# 64 bytes from 192.168.234.34: icmp_seq=3 ttl=127 time=0.568 ms
ubuntu 能和本机通信,并不意味着能上网。
# TODO 未测试
$ ip route # 查看路由
# default via 172.28.160.1 dev eth0 proto kernel
# 172.28.160.0/20 dev eth0 proto kernel scope link src 172.28.172.197
$ ip route del default # 删除默认路由
$ ip route add default via 172.28.160.1 dev eth0 # 添加默认路由
附加知识点: ICMP 和分组分组跟踪
ping 发送的是 ICMP 报文,也就是 IP 数据报中的数据部分为 ICMP 报文。
|--- ICMP Message ---|
↓ ↓
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
┃ Header ┃ Data ┃
┗━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━┛
↑ ↑
└---------------- IP Datagram -----------┘
可以 traceroute
(window 中为 tracert
)跟踪一个分组从源点到终点的路径。
如果没有 traceroute
命令,ubuntu 应该会提示你可以安装
sudo apt install inetutils-traceroute # version 2:2.2-2ubuntu0.1, or 或者
sudo apt install traceroute # version 1:2.1.0-2
wsl ubuntu 中跟踪分组路径:
$ traceroute 192.168.234.34
# traceroute to 192.168.234.34 (192.168.234.34), 64 hops max
# 1 172.28.160.1 0.244ms 0.136ms 0.150ms
# 2 192.168.234.34 0.181ms 0.089ms 0.095ms
# 如果出现 * 则表示超时
安装 nvm,但网络拒绝连接 Connection refused
curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh -o nvm.sh
curl: (7) Failed to connect to raw.githubusercontent.com port 443 after 76 ms: Connection refused
方案一:使用代理解决
前提:你的本机电脑支持代理,并且配置了 7890 端口
export https_proxy=http://172.28.160.1:7890 http_proxy=http://172.28.160.1:7890
# 注意 ip 地址是 wsl ubuntu 中的默认路由/网关,也就是本机中的 以太网适配器 vEthernet (WSL) IPv4。
# 临时环境变量
# 重启后失效
echo -e 'export https_proxy=http://172.28.160.1:7890\nexport http_proxy=http://172.28.160.1:7890' >> ~/.bashrc
source ~/.bashrc
# 永久生效
然后通过 ping 测试一下,可以发现是连通的了
$ ping raw.githubusercontent.com
# PING raw.githubusercontent.com (127.0.0.1) 56(84) bytes of data.
# 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.012 ms
# 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.058 ms
# 64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.041 ms
# 可以看到,所有的数据都是通过代理传进来的(虽然图中没有显示端口 7890)。
先了解 wsl ubuntu 中的 DNS 相关内容
首先,DNS 服务器的配置信息是在 /etc/resolv.conf
中。但在 wsl 的ubuntu 中,该文件其实是软连接:
$ file /etc/resolv.conf # file 命令查看文件类型
# /etc/resolv.conf: symbolic link to /mnt/wsl/resolv.conf
$ ls -l /etc/resolv.conf # ls -l 命令查看详细信息
# lrwxrwxrwx 1 root root 20 Mar 17 08:55 /etc/resolv.conf -> /mnt/wsl/resolv.conf
查看文件内容(cat /etc/resolv.conf
)可以看到:
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.28.160.1
可以看到,文件中的注释信息告诉我们,该文件是 wsl 自动生成的,想要禁用自动生成,可以在 /etc/wsl.conf
文件中添加以下信息
[network]
generateResolvConf = false
这个自行选择。
我们这里想要做的工作其实只是修改 DNS 服务器
方案二:配置 DNS 解决域名解析错误
修改 DNS 步骤如下
先删除文件,因为原文件是软连接
sudo rm /etc/resolv.conf
然后重新创建文件。
注意要使用 sudo 权限,不然保存时会提示 “/etc/resolv.conf” E212: Can’t open file for writing
sudo vim /etc/resolv.conf
键入 i
写入下面信息,然后键入 ESC
,键入 :wq
回车,保存退出
nameserver 114.114.114.114
如果你熟悉命令的话,上面步骤可以直接简化为:
sudo sh -c 'rm /etc/resolv.conf && echo "nameserver 114.114.114.114" > /etc/resolv.conf'>
然后再次测试。可以看到,虽然速度变慢了很多(因为是使用国内网络),但至少能够使用。
$ curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh -o nvm.sh
# % Total % Received % Xferd Average Speed Time Time Time Current
# Dload Upload Total Spent Left Speed
# 100 16555 100 16555 0 0 3176 0 0:00:05 0:00:05 --:--:-- 4275
附加:使用 nslookup 测试一下域名解析
此时,你还可以通过 nslookup 命令测试一下域名解析。
$ nslookup raw.githubusercontent.com
# Server: 114.114.114.114
# Address: 114.114.114.114#53
#
# Non-authoritative answer:
# Name: raw.githubusercontent.com
# Address: 185.199.110.133
# Name: raw.githubusercontent.com
# Address: 185.199.108.133
# Name: raw.githubusercontent.com
# Address: 185.199.111.133
# Name: raw.githubusercontent.com
# Address: 2606:50c0:8002::154
# Name: raw.githubusercontent.com
# Address: 2606:50c0:8001::154
# Name: raw.githubusercontent.com
# Address: 2606:50c0:8003::154
如果你是使用代理,你会发现解析域名是可能是无效果的。
$ nslookup raw.githubusercontent.com
# Server: 172.28.160.1
# Address: 172.28.160.1#53
#
# Non-authoritative answer:
# Name: raw.githubusercontent.com
# Address: 0.0.0.0
# Name: raw.githubusercontent.com
# Address: ::
解决网络问题后,安装 nvm
前面的 curl 命令仅仅只是下载脚本,并没有安装,想要安装,我们可以根据官方文档来:
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
$ source ~/.bashrc
$ nvm install node
$ nvm current
# v21.7.1
创建一个简单的服务器项目
由于太过简单,这里就不详细说明了。直接给出命令
$ sudo mkdir /test-node-demo
# 创建一个测试文件夹
$ whoani
# 查看当前用户名。比如是 kee
# 可以通过 cat /etc/passwd | column -t -s ':' 查看所有用户
$ sudo chown -R kee /test-node-demo/
# 将新创建的文件夹拥有者交给当前用户
$ sudo chmod -R u+rw /test-node-demo
# 为当前用户提供 /text-node-demo 文件夹的读取权限
$ mkdir /test-node-demo/demo && cd $_
# 新建 demo 文件夹
$ npm init -y
$ npm i express
$ echo '
const express = require("express")
const app = express()
app.get("/", (req, res) => {res.send("hello, world")})
app.listen(5000, () => {console.log("listen 5000")})
' > server.js
# 写入内容到 server.js 中
$ node server.js
# listen 5000
在主机打开 http://172.28.172.197:5000/
可以成功访问到 hello, world!
手机热点无法访问 wsl 搭建的服务器
推荐直接使用 nginx 进行反向代理。在 window 中使用 nginx 可以查看 这篇文章
配置内容如下:
# C:\nginx-1.25.4\conf\nginx.conf
events {
worker_connections 1024;
}
http {
server {
listen 5555;
server_name localhost;
location / {
# 这里添加刚刚能够在主机上访问的 ip 路径
proxy_pass http://172.28.172.197:5000;
}
}
}
参考文章
- nginx 基本使用、借助 nginx 和 mkcert 实现本地 https://localhost 测试。
- win家庭版安装 docker,用于运行 vscode 上的 GitHub 案例容器
- WSL2 网络异常排查 ping 不通、网络地址异常、缺少默认路由、被宿主机防火墙拦截 - 简书 (jianshu.com)
- Failed to connect to raw.githubusercontent.com:443 - 知乎 (zhihu.com)
- Node Version Manager