典型現象:Windows 能翻牆,WSL2 裡 apt 與 git 卻像「沒代理」

Clash 在 Windows 上工作正常時,瀏覽器往往已經走了系統代理或 TUN。但 WSL2 運行在輕量級虛擬機與虛擬網卡背後,默認並不共享你對「本機環回地址」的直覺。在子系統的 shell 裡寫 export https_proxy=http://127.0.0.1:7890,請求會打到 WSL 自己的環回接口,而不是 Windows 上正在監聽的那個埠,於是表現為超時、連接被拒絕,或仍然按直連去訪問被牆資源。

另一方面,aptgit 並不總是尊重你在交互式 shell 裡臨時 export 的變量:sudo 會清掉部分環境;apt 還有獨立的 Acquire::http::Proxy 系列配置;git 則常用 http.proxy / https.proxy。只有把宿主地址、Clash 監聽範圍、變量名與持久化位置對齊,才能穩定復現「同一份 Clash,Windows 與 WSL2 共用」的體驗。

先建立心智模型:127.0.0.1 在 WSL2 裡指向誰

在經典 WSL2 NAT 網絡模型下,子系統有獨立的網絡棧。127.0.0.1 指向的是 Linux 發行版自身,而不是 Windows 宿主。要讓流量進入 Windows 上的 Clash,必須讓 TCP 連接的目標地址變成「從 WSL 能路由到的、Windows 一側的 IP」,通常是默認網關或微軟文檔中描述的宿主機地址。社區裡最常用的做法之一,是讀取 /etc/resolv.conf 裡的 nameserver 欄位——在不少構建中它與通往宿主的地址一致(請以你當前 WSL 版本為準,升級後若行為變化應重新核對)。

你也可以用 ip route show default 查看默認路由的下一跳,把該地址當作 WIN_HOST 使用。下文示例統一寫作 <WIN_HOST>,請替換為你機器上實測的值。取得地址後,用 curl -v --proxy http://<WIN_HOST>:埠 https://www.example.com 做一次探活,比盲目改配置更快定位問題。

與「Linux 無頭部署」的區別 本站Linux 無頭部署文講的是代理進程直接跑在 Linux 裡;本文則是代理在 Windows、消費端在 WSL2,埠與監聽地址的約束完全不同。

Windows 側 Clash:混合埠、允許區域網與綁定地址

即使 WSL2 已經能 ping 通宿主 IP,若 Clash 只在 127.0.0.1 上監聽、且未開啟「允許區域網」(Allow LAN),來自 WSL 網段的入站連接仍會被拒絕。請在圖形客戶端或配置中確認:HTTP(S) 或 mixed 埠對區域網開放,且防火牆規則未攔截該埠(首次開啟時 Windows 防火牆可能彈出提示,需要允許專用網絡訪問)。

混合埠(mixed-port)同時承載 HTTP CONNECT 與 SOCKS,適合作為 ALL_PROXY 的統一入口。若你分別暴露 HTTP 與 SOCKS,請在環境變量裡對應填寫 http://...socks5://...,避免協議與埠錯配。Clash 規則本身仍只在 Windows 內核或 WinTun 路徑上生效;WSL2 通過 HTTP 或 SOCKS 把流量主動送給宿主上的 Clash 後,再由 Clash 按規則出網,這與「在 Linux 裡直連 TUN」是兩條鏈路。

若你使用 TUN 模式接管 Windows 全局流量,仍可為 WSL2 單獨保留上述「顯式代理埠」方案;TUN 不會自動讓 WSL2 裡的未配置進程 magically 走代理。更系統的模式對比見TUN 專文

Shell 環境變量:http_proxy、HTTPS_PROXY、ALL_PROXY 與 no_proxy

大多數命令行工具會識別小寫與大寫兩套變量,為減少歧義,建議成對寫入 http_proxy / HTTP_PROXYhttps_proxy / HTTPS_PROXY。若工具走 SOCKS,可設置 ALL_PROXY=socks5://<WIN_HOST>:埠,並同樣提供大寫形式。對於僅需 HTTP CONNECT 的場景,只設 http_proxy 指向混合埠通常也可工作,具體取決於工具實現。

no_proxy(或 NO_PROXY)應列出無需走代理的主機與域,例如 localhost,127.0.0.1,::1,以及公司內網後綴。否則訪問本地構建的 registry、Kubernetes API 或私有 Git 時,請求會被錯誤轉發到 Clash。與 Node、pnpm 等開發工具鏈協同設置時,可參考《Cursor 與 npm 開發者代理》中的 NO_PROXY 思路,在 WSL 側同樣適用。

將 export 寫入 ~/.bashrc~/.zshrc 可實現登錄自動生效。注意:sudo apt 默認會重置環境,下一節單獨處理。

# Replace <WIN_HOST> and <PORT> with your values (example: 7890)
export HTTP_PROXY="http://<WIN_HOST>:<PORT>"
export http_proxy="$HTTP_PROXY"
export HTTPS_PROXY="$HTTP_PROXY"
export https_proxy="$HTTP_PROXY"
export ALL_PROXY="socks5://<WIN_HOST>:<PORT>"
export all_proxy="$ALL_PROXY"
export NO_PROXY="localhost,127.0.0.1,::1"
export no_proxy="$NO_PROXY"

apt:sudo 場景與 Acquire::http::Proxy

Debian 系發行版中,apt 優先讀取 /etc/apt/apt.conf/etc/apt/apt.conf.d/ 下的指令。僅對當前用戶 export 變量,在執行 sudo apt update 時常常傳不進去。穩妥做法是在 /etc/apt/apt.conf.d/ 中 drop 一份僅包含代理的小文件,例如 95proxy,內容指向 http://<WIN_HOST>:<PORT>。使用 HTTP 代理訪問 HTTPS 軟體源是常見模式,apt 會通過 CONNECT 建立隧道。

若你同時使用國內鏡像與海外源,可在規則層用 Clash 分流;apt 側仍建議保持單一代理出口,由 Clash 決定直連或走節點,避免在 apt 配置裡硬編碼多套代理。編輯完配置後執行 sudo apt update 觀察是否還有 「Could not resolve」 或 「Connection timed out」;DNS 若仍走不理想的路徑,可結合 Clash 的 DNS 與 fake-ip 設置統籌,詳見《DNS fake-ip 與 redir-host》中與解析相關的討論。

# File: /etc/apt/apt.conf.d/95proxy (example)
Acquire::http::Proxy "http://<WIN_HOST>:<PORT>/";
Acquire::https::Proxy "http://<WIN_HOST>:<PORT>/";

不需要代理時,刪除該文件或注釋其中行即可恢復直連,避免長期把 apt 綁在已關閉的 Clash 埠上。

git:http.proxy、https.proxy 與 SSH 的界限

https://http:// 遠程倉庫,git 通常遵循 http.proxyhttps.proxy。推薦用 git config --global 寫入,地址仍填 http://<WIN_HOST>:<PORT>。若僅克隆公開倉庫,HTTP 代理足夠;若遇到大倉庫低速,多半是出口節點或單一連接帶寬問題,而非 git 配置語法本身。

[email protected]:... 這類 SSH 協議不會自動消費 http_proxy,除非通過 nc 等工具配置 ProxyCommand 或在 SSH config 中指向專用跳板。許多用戶誤以為設置了 ALL_PROXY 後 SSH 一定走代理,實際上要區分協議棧。若你希望統一走 Clash 提供的 SOCKS,可在高級場景中讓 SSH 經過 ProxyCommand 連接 <WIN_HOST> 上的 SOCKS 埠,具體命令因客戶端而異,此處不展開,以免與入門清單混淆。

# Git reads http(s) proxy for HTTPS remotes
git config --global http.proxy  http://<WIN_HOST>:<PORT>
git config --global https.proxy http://<WIN_HOST>:<PORT>

鏡像網絡(mirrored):讓 localhost 與 Windows 埠對齊

從較新的 WSL 版本開始,微軟提供鏡像網絡(mirrored / networkingMode=mirrored)選項:在用戶目錄下的 .wslconfig 中為指定發行版啟用後,環回與部分本機埠的語義更接近「與 Windows 共享視圖」,從而在不少場景下可以直接用 127.0.0.1:埠 訪問 Windows 上監聽的 Clash 混合埠,而不必每次解析 <WIN_HOST>。是否啟用取決於你的 Windows 與 WSL 版本、以及團隊對內網隔離的要求;啟用後若出現與 VPN、其他虛擬網卡衝突,應回退到顯式宿主 IP 方案並閱讀發行說明。

典型 .wslconfig 片段如下(欄位名與可用值請以微軟當前文檔為準,升級 Windows 後宜複查):

# %UserProfile%\.wslconfig (snippet, verify against Microsoft docs)
[wsl2]
networkingMode=mirrored

修改後通常需要執行 wsl --shutdown 再啟動子系統。鏡像模式與經典 NAT 並存於不同用戶配置中,不要假設每臺機器行為一致;寫成團隊文檔時,建議同時記錄「宿主 IP + 允許區域網」與「鏡像 + localhost」兩套路徑,便於新人按環境選用。

安全提示 開放區域網入站、或在鏡像模式下放寬本機邊界,都會擴大暴露面。僅在受信任網絡啟用,並在不使用時關閉 Clash 的 Allow LAN 或收緊防火牆。

驗證與快速自檢順序

建議按下列順序排查,每一步通過後再進入下一步:第一,在 WSL 內 ping 或 curl 宿主機 IP(僅測連通,不代表代理可用);第二,對混合埠做 curl -I --proxy http://<WIN_HOST>:埠 https://example.com;第三,在未 sudo 的 shell 中驗證變量是否生效;第四,單獨跑 sudo -E apt update(若你堅持用環境變量方式)或改 apt drop-in;第五,git ls-remote https://github.com/... 驗證 HTTPS 克隆鏈路。

若第二步失敗而第一步成功,優先回頭檢查 Clash 是否監聽 0.0.0.0 或等價允許遠程、以及 Windows Defender 防火牆入站規則。若只有瀏覽器可用而 curl 不可用,常見原因是瀏覽器走了系統代理,而終端未 export 變量——這與「WSL2 與 Windows 環回」問題不同,需分開判斷。

常見問題對照表

現象 可能原因 建議
127.0.0.1:7890 Connection refused 代理在 Windows 上,WSL2 的 127 不是宿主 改用 <WIN_HOST>;或啟用鏡像網絡後用 localhost
普通用戶 curl 可走代理,sudo apt 不行 sudo 丟棄代理環境 使用 apt.conf.d 或 sudo -E 並保留配置
git HTTPS 仍直連失敗 未設置 http.proxy / https.proxy git config --global 指向宿主代理
間歇性宿主 IP 變化 路由或 resolv 行為更新 腳本化探測默認網關;或依賴鏡像網絡固定 localhost
開啟 Allow LAN 後仍拒絕 防火牆或監聽地址過窄 檢查入站規則與 Clash 綁定地址

寫在最後:把「宿主 Clash」當成 WSL2 的顯式上遊

把 Windows 上的 Clash 當作 WSL2 的 HTTP/SOCKS 上遊,而不是期待子系統自動繼承瀏覽器代理,是排錯時最重要的一步。通過正確的 <WIN_HOST>、允許區域網與(可選的)鏡像網絡,你可以讓 aptgit 與日常腳本共用同一出口,再交給 Clash 做規則分流與 DNS 策略,整體體驗會比在 WSL 內再跑一份內核更省維護成本。相比其他同類工具,Clash 在規則可讀性、日誌與多協議支持上的組合,對需要同時照顧瀏覽器、終端與子系統的桌面用戶往往更順手。

若你希望少在埠與防火牆細節上反覆試錯,可以優先選擇帶圖形界面、能一鍵開關 Allow LAN 與查看 mixed 埠的客戶端,把精力放在節點質量與規則命中驗證上;全平臺安裝包可從本站下載中心獲取。

立即免費下載 Clash,開啟流暢上網新體驗;在 Windows 上配好混合埠與區域網訪問後,按本文清單對齊 WSL2 的 http_proxyALL_PROXY 與 apt/git,子系統裡的更新與克隆也能穩定走同一套規則。

需要深入 YAML 分流與策略組設計時,請繼續閱讀《Clash YAML 規則分流完全指南》;更多文章見技術專欄