了解 WSL NAT 模式運作原理
| | | 6 | |
由於 WSL 跟 Windows 整合得太緊密,常讓我有兩個作業系統是同一台機器的幻覺,以為在 Windows 用 http://localhost:5000 跑網站,從 WSL 可以用 curl http://localhost:5000 存取,結果踢到鐵板,WSL 的 localhost 不一定是 Windows 的 localhost。
WSL 有兩種網路模式:NAT 跟鏡像(Mirrored)模式。參考:使用 WSL 存取網路應用程式
預設安裝,WSL 會採用 NAT 模式,可想像成 WSL 位於一個虛擬網段,對外連線要透過 Windows 轉送。以我的機器為例,在 WSL 用 hostname -I 及 ip route 可以看到 WSL 的 IP 為 172.18.136.74,而 Gateway 是指向 172.18.128.1:

至於 172.18.128.1,你沒猜錯,它是 Windows 上的一張虛擬網卡,已設好路由及內部 IP 轉換,可將 WSL 的上網需求轉到 Windows 真正的對外網卡:

若要允許外部連上 WSL 的特定 Port,則需使用 netsh 設定 Port Proxy,例如以下指令可將 Windows 對外 IP 及 localhost 的 8080 Port 導向 WSL 的 80 Port:參考
netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=80 connectaddress=172.18.136.74
另外,WSL 有個內建機制,在 NAT 模式下,在 WSL 聽 localhost 的某個 Port,有支 wsrelay.exe 程式會扮演中繼站 (Relay) 串接 Windows 的 localhost 對映 Port。參考 例如:WSL 裡用 Docker 跑網站聽 localhost 5050,在 Windows 可直接用 http://localhost:5050 連上它。有時很方便,但有時這行為會跟 Windows 端 TCP Port 使用衝突,沒經驗的話可能會被迷惑一陣子。
因此在 NAT 模式下,WSL 的網路跟 Windows 的網路彼此獨立,Windows 擔任 Gateway 協助 WSL 上網,因此二者的 localhost 是完全不同的東西。
回到最開始的問題,WSL 要如何存取 Windows 的 localhost?
Windows 11 22H2 之後的 WSL2 加入所謂鏡像模式 Mirrored Mode,將 Windows 上的網路介面「鏡像」到 Linux,以新增網路功能並改善相容性。啟用後 WSL 可支援 IPv6、Linux 與 Windows 的 127.0.0.1/localhost 可互通、外部也可直接透過 Windows 對外 IP 連上 WSL、對 VPN 的支援也更好。參考
但我個人比較喜歡原本 NAT 模式明確區分兩個作業系統網路環境的做法,不會出現 Windows/WSL Port 衝突或混淆,管理或除錯時比較簡單明瞭,另外 WSL 不直接對外曝露感覺更安全些,所以還是會選用 NAT 模式。我想到的解法有二:一個是 Windows 端改聽 WSL Gateway IP,二是用 SSH Tunnel ssh -R 8888:localhost:8888 user@wsl 將 Windows localhost 的 8888 Port 導向 WSL localhost 的 8888 Port。
Comments
# by 小黑
原來是這樣,又學到了
# by Johnny
對吼~還有netsh可以設定Proxy Port 在有Mirror模式前 windows用nginx/caddy將windows IP轉到localhost:XXX wsl使用docker compose部屬服務 測試Redis, Postgres都很好用
# by cazz
wslrelay 應該是把 windows localhost tcp 轉送給 wsl localhost 才對 所以才有後面 localhost:5050 可以訪問,英文原文讀起來好像怪怪的 它會監聽 localhost:port 所以有其他程式也監聽這個位址就會打架,看誰先搶先贏 例如 netsh 0.0.0.0:port 就包含了 localhost 會衝突
# by Jeffrey
to cazz,看了一下,原寫法不精準,應回歸英文原文 Relay (中繼轉傳) 的意思較佳,謝謝回饋。
# by Chy
這邊是不是 """猜錯"""? XD """"至於 172.18.128.1,你沒猜測,它是 Windows 上的一張虛擬網卡""""
# by Jeffrey
to Chy,是的,你沒猜錯,錯了 :D 謝指正