一、為什麼 Windows 有代理,WSL2 裡卻像「沒開」

WSL2 本質上是在輕量虛擬機裡跑 Linux 核心,透過虛擬交換器與 Windows 主機通訊。你在瀏覽器裡看到的「系統代理」只影響 Windows 使用者空間內遵循系統 Proxy 的程式;預設並不會自動把同一組設定灌進子系統。因此,在 WSL 的 Bash 裡執行 curl https://example.com,若未手動指定 Proxy,流量會嘗試從子系統預設路由直連,自然出現逾時或 DNS 解析異常。

另一個高頻誤解是:既然 Clash 監聽在 127.0.0.1:7890,在 WSL 裡也填 127.0.0.1:7890 應該可以吧?在傳統預設組態下通常不行,因為此處的 127.0.0.1 是 Linux 端的本機回環,上面並沒有你的 Clash 行程。正確做法是連到Windows 主機在 WSL 視角下的位址(常見為預設閘道 IP,或舊版環境中 /etc/resolv.conf 內的 nameserver)。少數新組態若啟用了微軟文件的鏡像網路(mirrored)等模式,localhost 轉發行為可能不同,下文會單獨提醒你如何驗證。

最後補一句邊界:本文假設你已在 Windows 端成功跑起 Clash、訂閱與規則正常。若連 Windows 本機都尚未設定完成,建議先依《Clash Verge Rev 設定教學》把基礎流程跑通,再回到 WSL2 串接。

二、取得「主機」IP:預設閘道與 resolv.conf

在大多數 WSL2 預設網路下,從子系統連到 Windows 最穩定的查法之一,是讀取預設路由的下一跳,它通常就是主機在虛擬區網中的位址:

ip route show | grep -i default | awk '{ print $3}'

將輸出記為 HOST_IP(例如 172.22.128.1,實際數字依環境而異)。你也可以把它寫進 shell 函式,開機後自動匯出代理字串。

在較舊或特定組態中,有些人習慣從 /etc/resolv.conf 讀取 nameserver 那一行當作主機 IP;在部分 WSL 版本這與閘道一致,但在自訂 DNS systemd-resolved 介入後可能不再代表主機,因此建議以 ip route 結果為準,並用實際連線測試交叉驗證。

取得 IP 後,可用下列指令快速測試主機上的 Clash 混合埠是否從 WSL 可達(請替換埠號):

curl -I --proxy "http://HOST_IP:7890" https://www.google.com

若此處仍失敗,請先不要調整 WSL,而是回到 Windows 檢查 Clash 是否只綁在 127.0.0.1、以及防火牆是否擋住來自 WSL 虛擬網段的連入,下一節會說明。

三、Windows 端 Clash:監聽範圍與防火牆

要讓 WSL2 連進主機上的代理埠,Clash 必須在 Windows 上監聽一個可被該虛擬區網存取的介面。僅綁 127.0.0.1 時,只有 Windows 本機行程能連;子系統從另一張虛擬介面連過來會被拒絕。實務上與「手機連電腦代理」類似,常見作法是開啟允許區域網路allow-lan: true)並搭配適當的 bind-address,讓混合埠在正確介面上開放。細節可參考《Clash 開啟區域網路代理》;概念上可把 WSL 虛擬網卡視為「本機的另一塊區網」,同樣需要埠對該路徑可達。

Windows Defender 防火牆可能攔截從 WSL 指向主機 TCP 埠的連入。若測試連線逾時,可在「私人」網路設定檔下為你的 Clash 埠新增輸入規則放行(不建議在公用網路環境放寬)。第三方安全軟體若有網路過濾層,也需一併檢查。

請在客戶端介面確認實際的 mixed-port(或分開的 HTTP/SOCKS 埠),下文範例以 7890 表示;若你使用不同埠號,請全文替換為自己的設定。

四、環境變數:讓 shell、curl、多數 CLI 立刻走代理

~/.bashrc~/.zshrc 末尾,可依主機 IP 動態寫入(範例以 Bash 語法取得閘道):

export HOST_IP=$(ip route show | grep -i default | awk '{ print $3}')
export http_proxy="http://${HOST_IP}:7890"
export https_proxy="http://${HOST_IP}:7890"
export ALL_PROXY="http://${HOST_IP}:7890"
export no_proxy="localhost,127.0.0.1,::1"

說明:http_proxyhttps_proxy 請對齊 Clash 實際提供的協定與埠;多數使用混合埠時,三者可一併指向同一個 http://HOST_IP:7890。若你另外啟用了獨立的 socks-port,少數工具會改讀 ALL_PROXY 並要求 socks5:// 前綴,屆時再依設定檔調整即可。no_proxy 用於排除本機服務,避免繞一圈又回到代理。

修改後執行 source ~/.bashrc,再以 curl -I https://deb.debian.orgwget 測試。若只有 https_proxy 而部分工具只讀 http_proxy,可能仍失敗,建議兩者一併設定。

五、apt:單獨設定 Acquire,避免與全域變數打架

Debian/Ubuntu 系列的 apt 除了讀環境變數,也建議寫入專用設定檔,行為較可預期。建立 /etc/apt/apt.conf.d/95proxies(檔名可自訂,需 root):

Acquire::http::Proxy "http://HOST_IP:7890/";
Acquire::https::Proxy "http://HOST_IP:7890/";

HOST_IP 換成實際位址。完成後執行 sudo apt update 觀察是否仍出現連線逾時。若你使用公司內部鏡像或僅部分套件需要代理,可再拆成更細的 Acquire::http::Proxy::mirror.example.com 語法,此屬進階需求,本文不展開。

提醒:apt 錯誤訊息中的 “Could not resolve” 有時是 DNS 問題而非代理;若代理已通但解析仍失敗,需同步檢查 WSL 的 DNS 設定或 Clash 側的 DNS/fake-ip 策略,必要時參考《Clash 常見報錯與排除》中的 DNS 相關段落。

六、Git 與 npm:常見參數與一次性指令

Git 可設定全域代理(HTTP/HTTPS):

git config --global http.proxy http://HOST_IP:7890
git config --global https.proxy http://HOST_IP:7890

若僅在單一 repo 需要,可拿掉 --global 並在該目錄執行。結束後可用 git config --global --unset http.proxy 還原。

npm 建議使用:

npm config set proxy http://HOST_IP:7890
npm config set https-proxy http://HOST_IP:7890

若套件註冊表走 HTTPS,兩者通常都要設。使用 yarnpnpm 時,多半同樣尊重 http_proxy 環境變數,但若遇特例可查各工具文件中的 proxy 欄位名稱。

七、Docker Desktop 與 WSL2:引擎代理與建置情境

Docker Desktop for Windows 啟用 WSL2 後端時,映像拉取與容器網路仍可能走 Docker 自己的路由,不一定繼承你在 WSL shell 裡的 http_proxy。實務上可從三個層次處理:

  • Docker Desktop 設定 UI:在資源或 Docker Engine 相關頁面(依版本而異)填入 HTTP/HTTPS 代理,讓守護行程在拉取映像時使用與 Windows 一致的出口。代理位址可填 http://127.0.0.1:7890(因為請求發起端是 Windows 上的 Docker 服務)或依官方文件建議的格式。
  • daemon.json:進階使用者可直接在 Docker 設定 JSON 中宣告 proxies 區塊(鍵名隨 Docker 版本演進,請對照你安裝版本的文件),確保 docker pull 與背景服務一致。
  • 容器內與 docker build:執行中容器若要出網,需傳入 -e http_proxy=... 或使用 ~/.docker/config.json 的建置參數;多階段建置時常要在 Dockerfile 內暫時設定 ARGENV,建置完成後再取消,避免把敏感位址寫進最終映像層。

若你同時在 WSL 裡用 docker CLI 連到 Desktop 提供的 socket,遇到問題時請分清楚:是 CLI 與守護行程通訊失敗,還是守護行程對外拉映像失敗;兩者的錯誤訊息與修正方式不同。

八、鏡像網路與 localhost:新組態下的差異

微軟在較新的 WSL 版本中提供網路鏡像等實驗/正式選項,使 localhost 在 Windows 與 WSL 之間的轉發行為與早期預設不同。若你在 .wslconfig 中啟用了相關模式,可能會發現直接連 127.0.0.1:7890 也能通。這並非否定上文「閘道 IP」做法——後者仍是最通用、最易除錯的基線;建議以實際 curl 測試為準,並在文件或團隊 Wiki 註明團隊成員的 WSL 版本與網路模式,避免「在我機上可以」的溝通落差。

九、除錯清單:仍連不上時依序核對

  • 主機 IP 是否變動:WSL 重啟或虛擬交換器更新後,閘道偶爾改變;不要把舊 IP 寫死在腳本裡超過必要時間。
  • 埠號是否對齊 mixed-port:客戶端若因占用改埠,WSL 側必須同步更新。
  • Clash 是否只聽 127.0.0.1:此時必須調整監聽或開 allow-lan,否則 WSL 永遠連不上。
  • 防火牆與第三方軟體:暫時建立規則測試,確認根因後再收斂為最小放行範圍。
  • 規則與 DNS:代理已通但特定網域失敗時,回到 Clash 日誌看是否命中正確策略與 DNS 解析路徑。

十、小結

WSL2 Clash 串接的本質,是把子系統視為區網內的另一台客戶端:先取得 Windows 主機代理在虛擬區網中的可達位址,再確保本機監聽與防火牆允許該路徑,最後分別為 apt 代理、CLI 環境變數與 Docker Desktop WSL 選好正確層級的設定。相較於在 Linux 裡再裝一套核心,共用主機 Clash 能維持同一套訂閱與分流規則,對日常開發較省事;缺點是主機必須常駐開啟代理,且網路模式升級時要重新驗證。整體而言,只要依序完成「位址—監聽—環境—套件工具—Docker」五步,多數「只有 Windows 能翻、WSL 裡不行」的狀況都能對症排除。

若你希望用圖形介面統一管理系統代理、TUN、區域網路與訂閱更新,減少手動對檔案的來回修改,可優先選擇持續維護的桌面客戶端體驗。→ 立即免費下載 Clash,開啟流暢上網新體驗