眾所周知,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=4000
。listenaddress=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
值的條目後面必須跟上大小的單位,例如 8GB
或 512MB
。
值型別後帶有 * 的條目僅在 Windows 11 中可用。
值型別後顯示 ** 的條目需要 Windows 版本 22H2 或更高版本。
作者:Sxrhhh
部落格園:Sxrhhh - 部落格園 (cnblogs.com)
轉載請註明出處.
在個人網站持續更新中……