為什麼 WSL2 裡的 127.0.0.1 常常「不是」Windows 上的 Clash?
許多人在 Windows 桌面已用 Clash 類用戶端開好系統代理或 mixed-port,瀏覽器上網正常,但一進 WSL2 裡的 Ubuntu,執行 apt update、git clone 或 curl 卻仍失敗。最常見的誤解,是把 Linux 子系統裡的 127.0.0.1 當成「Windows 本機迴圈位址」:在 WSL2 架構下,子系統擁有獨立的網路命名空間,127.0.0.1 指向的是子系統自己,而不是正在監聽 mixed-port 的 Windows 行程。
因此,重點從來不是「再貼一次同樣的代理埠號」,而是把流量導向正確的 Windows 宿主位址,並確認 Windows 上的 Clash 真的在該位址上接受來自 WSL 虛擬網段的連入。另一條平行線是 DNS:即使 HTTP 連線已指到代理,若網域名稱仍在子系統內被送到不會走代理的解析路徑,你仍可能看到「連線逾時」「無法解析」或僅特定網域異常。接下來我們依序收斂:Windows 監聽 → 宿主位址 → 環境變數 → DNS → curl 自檢。
若你打算在裸機 Ubuntu 上長駐核心,流程與本文不同,可改讀 Clash Linux 與 systemd 自啟教學;Windows 圖形用戶端入門則可搭配 Clash for Windows 教學。用戶端安裝包請優先從本站 下載頁 取得,細部鍵位可對照 配置說明。
Windows 側:釐清 mixed-port、監聽位址與 allow-lan
Clash 系家族多在設定檔中使用 mixed-port(或分開的 port/socks-port)對外提供 HTTP 與 SOCKS 複合監聽。預設情境下,圖形用戶端可能只把服務綁在 127.0.0.1,這對「只在 Windows 本機連線」足夠,但對 WSL2 而言,來自子系統的連線相當於跨介面存取另一個主機,因此常需要其中一種作法:
- 在設定中啟用 Allow LAN(或等效的「允許區域網路連線」),讓 mixed-port 監聽
0.0.0.0或至少 Windows 在 WSL 橋接上的位址;或 - 維持僅本機監聽,但改以 Windows 提供的連接埠轉發/Proxy 共用機制(較進階,本文以第一種常見做法為主)。
實務上請在 Windows 端確認:系統防火牆是否允許 Clash 處理程式對該連接埠的私人網路入站連線;企業環境若鎖 GPO,也可能攔截虛擬交換器流量。若你曾讀過本站 區網共用代理與防火牆 一文,會發現 WSL2 與「同一 Wi‑Fi 下的手機」類似:重點都是「監聽範圍」與「防火牆是否放行該程式」。
Test-NetConnection 127.0.0.1 -Port 你的mixed埠 確認服務活著,再改從 WSL 用宿主 IP 測同一埠;兩步都通,才進入環境變數設定。
在 WSL2 內取得 Windows 宿主位址:hostname.local 與 resolv.conf
取得宿主 IP 的方式會隨 WSL 版本與組態略有差異,下列兩種在社群中最常見,建議都學會,以便在其中一種失效時快速切換。
以 $(hostname).local(mDNS)連線
在較新的 WSL 環境中,Windows 主機可能以 mDNS 名稱暴露,格式多為「電腦名稱.local」。你可以在 WSL 內執行 hostname 對照 Windows「關於」裡的裝置名稱,接著用 ping 或 getent hosts 你的電腦名稱.local 驗證是否解析到一個非 127.0.0.1 的位址。成功時,代理 URL 可寫成 http://你的電腦名稱.local:7890(埠請替換成實際 mixed-port)。
從 /etc/resolv.conf 讀 nameserver
傳統上,WSL2 會在子系統的 /etc/resolv.conf 內寫入一個指向Windows 宿主在虛擬網路上的位址的 nameserver 行。你可以用下列指令快速檢視(勿在未理解用途下覆寫此檔,WSL 有時會自動重建):
grep -E '^nameserver' /etc/resolv.conf
將看到的 IP 視為「當前環境下合理的 Windows 入口」,再與 mixed-port 組合成代理位址。若 Microsoft 日後調整預設行為,仍以你機器上實際檔案為準;關鍵觀念是:這個位址屬於宿主在 vSwitch 上的端點,而不是公網 IP。
代理環境變數:HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 與 no_proxy
大多數 CLI 工具會讀取大寫或小寫形式的 HTTP_PROXY/HTTPS_PROXY;需要 SOCKS 時可設定 ALL_PROXY(例如 socks5://宿主:埠)。建議在 ~/.bashrc 或 ~/.profile 末尾以可重複來源的方式匯出,並預留一鍵註解,方便切換公司網路與家用網路。
# example — replace HOST and PORT with your Windows Clash mixed-port listener
export HOST_IP="$(grep -m1 '^nameserver' /etc/resolv.conf | awk '{print $2}')"
export HTTP_PROXY="http://${HOST_IP}:7890"
export HTTPS_PROXY="http://${HOST_IP}:7890"
export ALL_PROXY="socks5://${HOST_IP}:7890"
export NO_PROXY="localhost,127.0.0.1,::1"
no_proxy(或 NO_PROXY)用於排除內部 Git、私有 PyPI、區網套件庫等不必出站的目標;清單過寬會讓部分網域意外直連失敗,過窄則可能把內網流量硬塞進代理。實務上可分段加入網域名稱後綴與內網 IP 段,並以實際 curl -v 觀察是否仍命中代理。
請注意:apt 不見得會完整繼承你 shell 的環境變數;長期穩定的做法往往是在 /etc/apt/apt.conf.d/ 以 Acquire::http::Proxy/Acquire::https::Proxy 明確指定,或在 apt-transport-https 已具備的前提下維持與 HTTP_PROXY 一致。若你只改了變數但 apt 仍直連,這不是「Clash 壞了」,而是套件管理器走另一條設定路徑。
git 與 curl:驗證真的走代理
Git 除環境變數外,亦可設定 http.proxy/https.proxy;若同時存在,請確認沒有舊的全域設定在覆寫。對 SSH 協定的 [email protected]:,環境變數中的 HTTP 代理不會自動套用,需要改走 HTTPS、或為 SSH 另行設定 ProxyCommand,這屬於另一主題;若你發現「HTTPS clone 可、SSH 不行」,先不要急著調 Clash 規則。
curl 是最佳除錯工具之一。下列幾個模式建議收藏:先用 curl -v http://宿主:埠 確認 TCP 可建立;再用 curl -v -x http://宿主:埠 https://www.example.com 驗證 TLS 與出口;若加上 --resolve 或 --connect-to 仍失敗,則偏向 DNS 或規則層,而非純連線。
DNS:代理已開,為何仍「解析不到」或只有部分網域壞掉?
Clash 若在 Windows 端啟用 fake-ip 或自管 DNS,而 WSL 內的解析器仍把查詢送往公共 DNS 或公司內 DNS,會出現兩種典型現象:一是解析結果與 Clash 內部狀態不一致,導致規則誤判;二是某些被封鎖或劫持的網域在「直連解析」階段就失敗,連帶讓後續代理無從發揮。這也是為什麼「只設 HTTP_PROXY」並不永遠足夠。
排查時請同時看兩端:Windows Clash 的 DNS 區塊與日誌,以及 WSL 內 resolvectl status(若使用 systemd-resolved)或 /etc/resolv.conf 的實際上游。若你必須讓敏感查詢也經過代理,通常要把系統解析行為與 Clash 的 redir-host/fake-ip 策略對齊;細部鍵位請以你實際核心版本與設定為準,並避免在不懂語意時混用多個 DoH 上游造成循環查詢。
external-controller 大範圍暴露在 0.0.0.0 又未設密鑰;WSL 能連到宿主,代表錯誤配置時的攻擊面也會跟著變大。管理介面與 mixed-port 的風險位階不同,請分開檢視。
curl 自檢矩陣:從 L2 到「真的出得去」
建議依序執行,任何一步失敗就停在該層,避免同時改規則又改 DNS:
- 宿主可達性:
ping -c 2你的宿主 IP 或.local名稱(ICMP 可能被擋屬正常,可改測 TCP)。 - 代理埠 TCP:
nc -vz 宿主 mixed埠或等效工具,確認三向交握成功。 - HTTP CONNECT/GET:
curl -v -x http://宿主:埠 https://1.1.1.1類探針,觀察是否拿到預期狀態碼或 TLS 錯誤類型。 - 真實網域:換成你實際要存取的 API 或套件庫網域,並開啟 Clash 日誌觀察規則命中與連線結果。
若第 1、2 步已失敗,請回到 Windows 防火牆與 allow-lan;若第 3 步失敗但第 2 步成功,偏向認證、協定或 Clash 本機規則;若第 4 步才失敗,請優先比對DNS 回應與策略組選路,而不是盲目更換節點。
重新開機後仍穩定:避免硬編碼與自動覆寫
WSL 與 Windows 更新後,虛擬網段偶爾會調整;因此不建議把某次量到的宿主 IP 永久寫死在腳本。較穩健的作法是每次登入 shell 時以 resolv.conf 或官方文件推薦的方式動態取得,或改以穩定的 .local 名稱(若你的環境可用)。若你使用 devcontainer 或 CI,請把這段邏輯收斂在專案文件,避免新同事複製到過期 IP。
另外,若你在 Windows 端同時開啟多個代理軟體或 VPN,可能出現路由表互相覆寫;症狀是「昨天可行、今天不行」。此時請先關閉多餘的虛擬介面,再在 Windows 路由表與 Clash 日誌中確認預設出口。
總結:把「能連到宿主代理」與「DNS 走對路」拆開思考
WSL2 Ubuntu 走 Windows Clash 的本質,是跨網路命名空間使用本機代理服務:先要 Windows 端監聽範圍與防火牆允許子系統連入,再在 Linux 側用正確的宿主位址組出 HTTP(S)_PROXY,最後才處理 apt/git 各自特有的設定入口。DNS 則常是第二個戰場:代理變數正確但解析仍直連時,症狀會表現為特定網域間歇失敗或 TLS 錯誤,這時應對照 Clash 的 DNS 與 fake-ip 行為,而不是反覆重裝用戶端。
相較於在原生 Linux 上維護長駐核心,WSL2 場景更考驗你對雙系統網路邊界的理解;一旦把「宿主位址+監聽範圍+環境變數+解析路徑」四件事拆開驗證,多數 apt/git/curl 問題都能在半小時內收斂。若你希望圖形用戶端與核心版本維持一致、並減少下載來源風險,採用固定更新節奏的官方發佈管道通常比四處找破解版更省心。