新版本下如何透過外部網路訪問wsl

Sxrhhh發表於2023-12-14

眾所周知,wsl2是windows下的linux子系統,並且採用類似於虛擬機器NAT的管理方式。一般情況下,外部網路很難直接訪問到wsl上的服務,除非使用埠轉發。而現在,微軟更新了wsl 2.0.0,採用映象網路配置,完美解決了所有網路上的問題。

點此檢視原網站

研究起因

想直接看新版本解決方案的點這裡

由於在編譯他人程式碼時需要linux環境,我就放在了wsl下編譯執行,然後在本地,我就嘗試用ifconfig得到的虛擬機器ip,成功連線上了wsl伺服器。但是,當我試圖用區域網下其他裝置連線時,很顯然,根本不可能連線上。這是因為wsl2採用了類似於NAT的網路模式,windows作為宿主機,隔離了區域網下其他裝置和wsl的連線。為了外部訪問wsl,我也試過一些方法。

舊版本埠轉發方案

在舊版本,常用的方法是埠轉發,根據官方文件,在有管理員許可權的powershell下,輸入如下指令:

netsh interface portproxy add v4tov4 listenport=<yourPortToForward> listenaddress=0.0.0.0 connectport=<yourPortToConnectToInWSL> connectaddress=(wsl hostname -I)

在此示例中,需要更新 <yourPortToForward> 到埠號,例如 listenport=4000listenaddress=0.0.0.0 表示將接受來自任何 IP 地址的傳入請求。 偵聽地址指定要偵聽的 IPv4 地址,可以更改為以下值:IP 地址、計算機 NetBIOS 名稱或計算機 DNS 名稱。 如果未指定地址,則預設值為本地計算機。 需要將 <yourPortToConnectToInWSL> 值更新為希望 WSL 連線的埠號,例如 connectport=4000。 最後,connectaddress 值必須是透過 WSL 2 安裝的 Linux 分發版的 IP 地址(WSL 2 VM 地址),可透過輸入命令:wsl.exe hostname -I 找到。

---官方文件

然後,我將wsl中的8303埠對映在了windows下的8304埠下,我看到,在wsl中,伺服器照常執行。

netstat -ano | findstr 8304

也能看到8304埠正常監聽。但是,在我訪問wsl執行的遊戲伺服器(遊戲名:DDraceNetwork),客戶端顯示“udp疑似被攔截”。本來我認為這是埠轉發失敗了,但是我忽然注意到本地8304埠只有tcp。於是查詢了有關資料,得到了netsh只支援tcp的結論。因此,netsh方案失敗。

舊版本橋接模式方案

後來,我希望用hyper-v建立一個虛擬交換機,相當於一個可通外網的虛擬網路卡,並讓wsl連線。結果,出現了許多問題。

  • 當前版本下,wsl2已不支援更改連線方式為bridge橋接模式,從根本上杜絕了這一方法
  • 當我建立了虛擬交換機後並將其接入網橋,他直接把我Windows下的網路幹廢了
  • 試圖用Vmware建立交換機,結果根本找不到選項

最後,我發現了官網給出了新方案!

新版本映象網路模式方案

由於本人入坑wsl時間晚,在此之前,我對wsl1只是道聽途說。據我瞭解,wsl1建立在相容層上,與windows共存,因此wsl1的網路配置與windows一致,外部網路也可以很輕鬆地接入wsl。而wsl2則是基於hyper-v的虛擬機器,採用的是新一套的NAT方案,較為獨立。所以對於wsl2也要用和普通虛擬機器一樣的網路方案,如NAT轉發和橋接。

而現在,在Windows23H2更新中,或是22H2中的insider,wsl2更新了映象網路解決方案,這個方案將會解決幾乎一切wsl上的網路問題。而此方法,也將隨著時間推移,成為wsl2的預設解決方案

在此貼出微軟官方文件:

使用 WSL 訪問網路應用程式 | Microsoft Learn

wsl版本檢測

要啟用映象網路模式,首先要保證你的windows系統是23H2以上,或是加入了windows體驗計劃。除此之外,由於版本更新已有一段時間,如果你不確定是否可以使用,可以在cmd輸入wsl --version檢視wsl版本是否是2.0.0以上。如果是,那就可以。

配置wsl檔案

在windows使用者根目錄下,新建個名為.wslconfig的檔案,選擇合適的編輯器開啟它。

如果不知道自己的使用者根目錄,可以在cmd下輸入echo %USERPROFILE%,即可看到路徑

經過實驗,我甚至發現上面的命令只能在cmd命令提示符下執行,powershell還不行!!!

在檔案中輸入如下內容:

[experimental]
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true

然後,執行wsl --shutdown,等待大約8秒後重新啟動wsl,即可成功改變網路策略。

你可以透過在wsl虛擬機器內執行ifconfig,看到原本有的IP地址現在沒了,即可證明mirrored模式啟用成功。現在你可以用phpstudy等軟體在windows下建立一個網站,然後用linux訪問,會發現linux可以訪問windows的服務。

比如說:我在windows下用80埠建立的網站,在linux下執行curl localhost,顯示的是windows的網站。

再比如說:我在linux下用apache在81埠建立了個網站,在windows下用瀏覽器訪問http://localhost:81,可以看到linux的網站。

那麼,wsl的新版本網路配置也就成功了…………

…………

嗎?

解決遺留的坑

很遺憾地告訴大家,我上面給出的配置檔案少了一句話,而這句話才是本文的重點。為什麼會單獨拿出來講,這是因為我在20分鐘查詢資料的過程,沒有一篇文章講到這個。現在我們先來看看問題在哪裡。

首先,我們要先知道windows的IP地址,不要求上百度看公網IP,只要一個區域網內的外部IP,也就是你電腦直連路由器分配給你的IP,假設是192.168.1.101,那麼我現在在瀏覽器訪問http://192.168.1.101,可以成功看到宿主機建立的網站。

現在在讓我們訪問http://192.168.1.101:81,也就是linux下的網站埠,結果發現,無法訪問!

也就是說:

  • localhost:81 可以!
  • 192.168.1.101:81 不行!

那就奇了怪了,我也是成功在官網找到響應的配置選項,只要在最後加上那麼一行:hostAddressLoopback=true就行了。

最後的配置檔案:

[experimental]
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true
hostAddressLoopback=true

重啟wsl,問題解決,我的遊戲伺服器也能進入了,只是伺服器列表不顯示[滑稽]

尾聲

我在這裡貼出wsl2關於mirrored模式的一些其他配置選項,可以更好的幫助各位配置wsl。

設定名稱 預設值 說明
useWindowsDnsCache** bool false 僅當 experimental.dnsTunneling 設定為 true 時才適用。 如果此選項設定為 false,則從 Linux 隧道傳輸的 DNS 請求將繞過 Windows 中的快取名稱,以始終將請求放在網路上。
bestEffortDnsParsing** bool false 僅當 experimental.dnsTunneling 設定為 true 時才適用。 如果設定為 true,Windows 將從 DNS 請求中提取問題並嘗試解決該問題,從而忽略未知記錄。
initialAutoProxyTimeout* string 1000 僅當 experimental.autoProxy 設定為 true 時才適用。 配置啟動 WSL 容器時,WSL 等待檢索 HTTP 代理資訊的時長(以毫秒為單位)。 如果代理設定在此時間之後解析,則必須重啟 WSL 例項才能使用檢索到的代理設定。
ignoredPorts** string Null 僅當 experimental.networkingMode 設定為 mirrored 時才適用。 指定 Linux 應用程式可以繫結到哪些埠(即使該埠已在 Windows 中使用)。 透過此設定,應用程式能夠僅偵聽 Linux 中的流量埠,因此即使該埠在 Windows 上用於其他用途,這些應用程式也不會被阻止。 例如,WSL 將允許繫結到 Linux for Docker Desktop 中的埠 53,因為它只偵聽來自 Linux 容器中的請求。 應在逗號分隔列表中設定格式,例如:3000,9000,9090
hostAddressLoopback** bool false 僅當 experimental.networkingMode 設定為 mirrored 時才適用。 如果設定為 True,將會允許容器透過分配給主機的 IP 地址連線到主機,或允許主機透過此方式連線到容器。 請注意,始終可以使用 127.0.0.1 環回地址 - 此選項也允許使用所有額外分配的本地 IP 地址。

具有 path 值的條目必須是帶有轉義反斜槓的 Windows 路徑,例如:C:\\Temp\\myCustomKernel

具有 size 值的條目後面必須跟上大小的單位,例如 8GB512MB

值型別後帶有 * 的條目僅在 Windows 11 中可用。

值型別後顯示 ** 的條目需要 Windows 版本 22H2 或更高版本。


作者:Sxrhhh

個人網站:https://www.sxrhhh.top

部落格園:Sxrhhh - 部落格園 (cnblogs.com)

轉載請註明出處.

在個人網站持續更新中……

相關文章