為什麼「Windows 已開 Clash」,WSL2 終端仍像直連?
在 Windows 上,多數圖形化 Clash 用戶端可以一鍵開啟系統代理,讓願意遵守系統代理的應用程式把流量送到本機的 127.0.0.1:7890(或你自訂的埠)。這對 Edge、Chrome 這類程式通常很有效,因此你會先在瀏覽器裡看到「已走代理」的跡象。
但 WSL2 本質上是一個輕量虛擬機器環境:你在 Ubuntu/Debian 發行版裡開的終端機,網路堆疊與 Windows 主機並不是同一個「本機迴圈」語意。對 WSL2 裡的行程而言,127.0.0.1 指的是Linux 這一側的自己,而不是 Windows 上正在聽的 Clash。換句話說,就算你在 Windows 把系統代理寫得很漂亮,WSL2 內的 curl、apt、git 也不會自動把封包送去 Windows 的 Clash 埠,除非你另外做「橋接」。
另一個常見痛點是 DNS:WSL2 預設會從 Windows 繼承一份 /etc/resolv.conf,而 Clash 若啟用 Fake-IP 或特殊的 dns 區塊,解析結果可能與你在瀏覽器裡看到的「被 Clash 接管後的語意」不一致,外觀就像「能上網但解析怪怪的」「某些網域永遠指到假 IP」。這不是單一開關壞掉,而是路徑(封包往哪走)與解析(名字怎麼變成位址)兩件事要分開校準。
若你希望先把整體架構與名詞對齊,建議先瀏覽站內的說明文件總覽,再回到本文照順序操作。接下來我們會先解決「WSL2 如何連到 Windows 上的 Clash 埠」,再談環境變數持久化與 DNS 同步。
http_proxy 解;Windows 瀏覽器與 UWP 則常卡在系統代理寫入與回環限制。本篇補上Windows 主機 + WSL2 雙堆疊這個高頻場景,並建議搭配 Fake-IP/DNS 專文一起閱讀。
第一步:在 WSL2 內取得「能打到 Windows Clash」的主機位址
橋接的核心只有一句話:請把代理指向「Windows 主機在 WSL2 網路裡看得見的那個 IP」,而不是 127.0.0.1。實務上最常見、也最穩定的取法之一,是讀取 WSL2 自動產生的 /etc/resolv.conf 裡的 nameserver,它通常會指向 Windows 主機在虛擬區網中的位址。
你可以在 WSL2 終端機直接執行:
grep -m1 nameserver /etc/resolv.conf | awk '{print $2}'
把輸出記下來,暫且叫它 WIN_HOST。接著請用 ping 或 curl 快速確認「從 WSL2 真的能連到 Windows 上的 Clash 埠」。下面假設你的 Clash HTTP 或 mixed-port 是 7890(請務必替換成用戶端介面顯示的真實數字):
WIN_HOST=$(grep -m1 nameserver /etc/resolv.conf | awk '{print $2}')
curl -I --max-time 5 "http://${WIN_HOST}:7890" || true
若這裡連不上,先不要急著改規則集。請回到 Windows 端確認三件事:第一,Clash 是否真的在本機埠監聽;第二,是否只綁在 127.0.0.1 導致「只接受迴圈連線」;第三,防火牆是否擋下由 WSL2 虛擬介面來的連入。這些都屬於主機側前置條件,沒打通之前,WSL2 裡怎麼匯出 http_proxy 都不會生效。
少數環境(例如新版 Windows 的網路元件調整、或企業安全軟體介入)可能讓 resolv.conf 的 nameserver 不再是直覺的「主機閘道」。若你遇到可疑狀況,可以交叉比對 ip route show default 的預設閘道,或暫時在 Windows PowerShell 用 wsl.exe 反向檢查路由。重點是:請以「實際可連線」為準,不要硬背教學文的位址。
第二步:讓 Clash 願意接受「從 WSL2 過來」的連線
多數 Clash/Mihomo 用戶端預設只在本機監聽,這在純本機瀏覽器場景很合理,但對 WSL2 這種「跨邊界」連線就不友善。你需要讓代理服務至少在虛擬區網介面上可連,並搭配允許區網連線(allow-lan)或等價選項,否則即使 WIN_HOST 正確也會被拒絕。
實務檢查清單如下:
(1)用戶端介面:確認已開啟 allow-lan(名稱可能略有差異),並確認 HTTP/mixed-port 與你稍後要寫進環境變數的埠一致。
(2)設定檔層級:若你直接編輯 YAML,通常會看到 allow-lan: true 與 bind-address 或監聽位址相關欄位。目標是避免「只聽 127.0.0.1」造成跨邊界連不進來。不同用戶端對欄位命名不完全相同,請以你正在使用的分支文件為準。
(3)Windows 防火牆:若你確認 Clash 已在正確介面監聽,但 WSL2 仍逾時,下一個高機率原因是防火牆規則。此時請以「最小必要」原則放行本機埠,並保留可回溯的變更紀錄。企業裝置若被 MDM 鎖定,可能需要與 IT 協調例外規則。
若你同時也在排查「Windows 本機瀏覽器為何不生效」,可延伸閱讀站內的Windows 11 系統代理與 UWP 排查,避免把兩個層次的問題混在同一個結論裡。
第三步:在 WSL2 匯出 http_proxy/https_proxy/all_proxy
當你能從 WSL2 連到 ${WIN_HOST}:7890 之後,就可以把 Unix 世界約定俗成的代理環境變數指向「主機上的 Clash」。下面示範同時設定大小寫變數,因為不同工具讀取的慣例不一致:
WIN_HOST=$(grep -m1 nameserver /etc/resolv.conf | awk '{print $2}')
export http_proxy="http://${WIN_HOST}:7890"
export https_proxy="http://${WIN_HOST}:7890"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
若你的 SOCKS 埠與 HTTP 埠不同,且你希望某些工具走 SOCKS,可再補:
export all_proxy="socks5h://${WIN_HOST}:7891"
export ALL_PROXY="$all_proxy"
請把 7891 換成真實值;若你只用 mixed-port 且工具支援 HTTP 代理即可,未必需要 all_proxy。接著用最小化方式驗證:
curl -I https://www.google.com --max-time 15
env | grep -i proxy
若此時仍失敗,請先分辨兩類問題:第一類是根本連不到主機代理埠(回到前兩步);第二類是已連上代理,但規則把目標判成直連或節點不通,這就進入策略組與規則順序範疇,可延伸閱讀站內的規則分流教學。
git、apt 與其他工具:除了環境變數,還有哪些細節?
Git 多半會遵循 http_proxy/https_proxy,但你也可能曾設定過全域 http.proxy。建議用下列指令檢查是否另有覆寫:
git config --global --get http.proxy
git config --global --get https.proxy
若這裡有舊值,可能與你剛匯出的環境變數互相打架。處理方式很務實:要么兩邊對齊,要么在確認不再需要時清掉舊設定,避免留下難以追蹤的狀態。
APT 常見做法是寫入 /etc/apt/apt.conf.d/ 下的設定檔,或使用 Acquire::http::Proxy 語法。由於不同發行版預設目錄與權限略有差異,這裡給一個「方向正確」的範例(實際檔名與權限請依你的系統調整):
WIN_HOST=$(grep -m1 nameserver /etc/resolv.conf | awk '{print $2}')
printf 'Acquire::http::Proxy "http://%s:7890/";\nAcquire::https::Proxy "http://%s:7890/";\n' "$WIN_HOST" "$WIN_HOST" | sudo tee /etc/apt/apt.conf.d/95clash-proxy.conf
同樣地,請把埠換成真實值;若你公司內部還有額外的 APT 鏡像或快取,請確認代理語意與內網繞過清單不衝突。
第四步:讓設定在重開終端機後仍存在(Shell 與 systemd)
手動 export 只影響目前這個 Shell 及其子行程。實務上你可以選兩條路之一,或並存:
(1)使用者層級的 Shell 初始化檔:例如 ~/.bashrc 或 ~/.zshrc,在檔尾加入上一節的匯出指令。缺點是變得更「個人化」,且若 WIN_HOST 取得邏輯過於脆弱,可能偶發失敗;優點是簡單、容易還原。
(2)systemd user environment:若你在 WSL2 內啟用 systemd,並希望服務型行程也繼承代理,可評估使用 environment.d 或單元檔內的 Environment=。這條路較適合已熟悉 Linux 服務管理的讀者,並需要額外注意「取得 WIN_HOST 的時機」是否在開機流程中穩定可用。
無論選哪條路,都建議你把「可連線測試」寫成一個小函式或別名,例如固定執行 curl -I 與 env | grep -i proxy,讓未來的自己不必靠記憶除錯。
第五步:DNS 同步——resolv.conf、Fake-IP 與「解析看起來很怪」
很多人把「能上網」誤認為「DNS 也一定正確」。在 Clash 生態裡,Fake-IP 會讓你看到大量非典型位址,這不一定是壞事,但它會改變你對 dig/nslookup 輸出的直覺解讀。若你正在使用 Fake-IP 或複雜的 dns 區塊,建議先閱讀站內的Fake-IP 與 DNS 設定,再回到 WSL2 做對照實驗。
在 WSL2 內,你至少會遇到兩個層次:第一,/etc/resolv.conf 是否被自動覆寫,以及它指向的解析器是否真能回答你的查詢;第二,Clash 是否要求「解析也經過代理核心」,而你的工具鏈是否遵循同一條路徑。當 curl 已經走代理但某些應用仍解析失敗時,請優先懷疑解析走錯邊,而不是急著重裝發行版。
實務上很務實的作法,是把驗證拆成兩段:先用 curl -v 觀察「連線目標」與「是否嘗試走代理」;再用 getent hosts example.com 或 dig 觀察「名稱到 IP 的映射是否符合你對 Fake-IP 的預期」。兩邊結果不一致時,通常代表你還需要調整 dns 區塊、或釐清哪些程式繞過了 Clash。
第六步:可重現的驗證清單(建議照順序勾)
為了讓你把本文當檢核表使用,下面用「由淺入深」排列。每一項都請記錄結果,避免同時改太多變因而無法回溯。
(1)邊界確認:在 WSL2 內確認 127.0.0.1:你的代理埠 不等於 Windows 的 Clash;你必須用 WIN_HOST 這類位址連到主機。
(2)主機埠確認:從 WSL2 對 WIN_HOST:埠 做連線測試;失敗就先處理 allow-lan、bind 位址與防火牆。
(3)環境變數確認:env | grep -i proxy 是否如預期;並用 curl -I 驗證對外 HTTPS 是否恢復合理延遲與狀態碼。
(4)工具鏈確認:git 是否有獨立 proxy 設定;apt 是否另有代理檔案;是否需要 NO_PROXY 排除內網位址。
(5)DNS 確認:把 Fake-IP 的預期行為寫清楚,再用 curl -v 與解析指令交叉驗證。
什麼時候該改走「Windows 端 TUN」,而不是在 WSL2 硬撐環境變數?
環境變數方案的好處是可理解、可還原、對開發者工具鏈友善;缺點是它偏「逐行程約定」,遇到不讀標準變數的程式、或某些語言套件管理器自帶的 HTTP 客戶端,仍可能鑽洞出去。
若你的目標是「盡量讓整台 Windows(含多個子系統與容器)都走同一套路由語意」,可以評估在 Windows 端啟用 TUN,讓流量在更底層進入 Clash。站內的TUN 模式詳解已整理原理與常見風險;與本文並讀時,請特別注意 DNS 與路由的連動,錯誤設定可能讓整機「看似全斷線」。
相對務實的選擇策略是:若你主要在 WSL2 內做開發,且工具大多尊重 http_proxy,優先用本文橋接;若你長期被「某些行程怎麼都不走變數」折磨,再評估 TUN。
與 macOS 終端情境的差異:不要照抄同一組位址
站內的macOS 終端與 Homebrew 代理一文,核心是把本機埠指向 127.0.0.1;但在 WSL2,「本機」的語意不同,你必須改指向 Windows 主機在虛擬區網中的位址。把這個差異記清楚,能避免你在論壇碎片式搜尋時把兩種環境的教學混在一起。
結語:把「邊界」說清楚,WSL2 就會變得好調很多
WSL2 與 Windows 主機並列時,Clash 最常見的誤會是把「系統代理已開」當成「所有子系統都自動生效」。把邊界拆開後,你會發現大多數案例都能用很樸實的順序解掉:先找到 WIN_HOST,再讓 Clash 願意被跨邊界連線,最後才把 http_proxy 與 DNS 行為校準到同一套語意。
相較於到處複製來路不明的腳本,更重要的是選一個介面清楚、能把 allow-lan 與埠狀態講明白、並在出問題時容易還原預設的用戶端。當你把「可連線」當成底線、把「可驗證」當成習慣,長期使用代理工具的成本會明顯下降。你可以先從本站用戶端下載頁取得目前平台可用版本,再回來依序完成本文檢核。→ 立即免費下載 Clash,開啟流暢上網新體驗