先判斷問題發生在哪一層
瀏覽器可以開啟網頁,但終端機中的 curl、git、套件管理工具或開發工具連線失敗,通常不代表 Clash 核心已經失效。更常見的原因是兩類程式採用不同的代理入口:瀏覽器可能讀取作業系統代理,也可能由擴充功能獨立接管;終端機程式則通常只讀取自身設定、代理環境變數或命令列參數。
排查時應將路徑拆成四層:用戶端介面是否正常管理核心、核心是否監聽本機連接埠、目標程式是否將請求送至該連接埠,以及 DNS 與規則在請求送入核心後是否正確處理。每次只驗證一層,才能確認問題邊界。
| 現象 | 優先檢查 | 常見原因 |
|---|---|---|
| 瀏覽器正常,curl 失敗 | 終端機代理環境變數 | curl 未讀取系統代理,或變數仍指向舊連接埠 |
| 瀏覽器與終端機都失敗 | 核心狀態與監聽連接埠 | 核心未啟動、設定載入失敗或連接埠遭占用 |
| 網域名稱失敗,IP 請求正常 | DNS 路徑 | 本機解析失敗、應用程式繞過 Clash DNS,或 fake-ip 不相容 |
| 只有 Git 或套件管理工具失敗 | 應用程式專用設定 | 應用程式覆寫環境變數,或仍保存舊代理位址 |
| 啟用 TUN 後終端機恢復正常 | 原本的系統代理路徑 | 程式原先不讀取系統代理,TUN 改由網路層接管流量 |
第一步:確認核心已啟動並監聽正確連接埠
從用戶端介面查看實際連接埠
不要先假設連接埠一定是 7890。許多 Clash 或 mihomo 設定會使用 mixed-port: 7890,但也可能分別設定 port: 7890 與 socks-port: 7891;用戶端也可能因連接埠衝突而改用其他數值。請在目前用戶端的「設定」→「參數設定」或「設定」→「連接埠設定」中查看 HTTP、SOCKS5、Mixed Port 的實際值;選單名稱會隨用戶端版本變動,請以介面顯示為準。
設定檔中的典型監聽設定如下。這裡僅用於辨認欄位,實際排查必須以目前已載入的設定與執行狀態為準。
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
mixed-port 可以在同一個連接埠接受 HTTP 與 SOCKS5 連線。若設定使用分離連接埠,HTTP 用戶端應連線至 port,SOCKS5 用戶端則應連線至 socks-port。協定與連接埠設定錯誤時,常見結果是連線立即中斷、收到空回應,或顯示代理交握失敗。
在本機檢查監聽狀態
Windows PowerShell 可以檢查指定連接埠是否處於監聽狀態:
Get-NetTCPConnection -State Listen |
Where-Object LocalPort -In 7890,7891 |
Select-Object LocalAddress,LocalPort,OwningProcess
macOS 與 Linux 可以使用:
lsof -nP -iTCP:7890 -sTCP:LISTEN
lsof -nP -iTCP:7891 -sTCP:LISTEN
如果系統提供 ss,也可以執行:
ss -lntp | grep -E ':(7890|7891)\b'
看到 127.0.0.1:7890 表示連接埠只接受本機連線;終端機與 Clash 位於同一台電腦時即可使用。若命令在 WSL、容器、虛擬機器或另一台區域網路裝置中執行,該環境中的 127.0.0.1 會指向自身,而不是主機。此時需要確認主機位址、虛擬網路邊界與 allow-lan 設定,不應直接將監聽位址改成整個網路都可連線後便停止檢查。
第二步:繞過系統設定,直接測試代理連接埠
確認連接埠正在監聽後,使用明確參數讓請求直接進入代理。如此可以區分「核心與節點是否可用」以及「作業系統是否正確分發代理設定」。
使用 curl 驗證 HTTP 代理
curl -v --connect-timeout 10 \
-x http://127.0.0.1:7890 \
https://example.com/
在 Windows PowerShell 中,如果 curl 是 Invoke-WebRequest 的別名,應明確呼叫 curl.exe:
curl.exe -v --connect-timeout 10 ^
-x http://127.0.0.1:7890 ^
https://example.com/
若明確指定代理的請求成功,但未帶 -x 的請求失敗,表示核心、監聽連接埠與目前策略大致可用,問題集中在終端機程式未使用代理。若明確指定代理的請求也失敗,應同時查看 Clash 日誌:日誌完全沒有連線記錄,通常表示請求未抵達該連接埠;若出現連線記錄,但策略命中 REJECT、節點逾時或 TLS 錯誤,則要繼續檢查規則、策略群組與上游連線。
驗證 SOCKS5,並區分本機解析與代理解析
curl -v --connect-timeout 10 \
--proxy socks5h://127.0.0.1:7891 \
https://example.com/
socks5h 中的 h 表示由代理端處理網域名稱,而 socks5 通常會先在本機解析網域名稱。若 socks5h 成功、socks5 失敗,排查重點就應從代理連接埠轉向本機 DNS。這項對照測試比直接更換節點更能說明問題。
測試目標應選擇穩定且符合目前規則預期的位址。若規則將某個網域名稱設為 DIRECT,該請求可能不會經過所選代理節點;若規則設為 REJECT,失敗就是設定決定的結果。規則模式會依序求值,第一條符合的規則決定流向,因此還要在日誌中核對實際命中的規則與策略。
第三步:為終端機設定正確的代理變數
macOS 與 Linux 的目前 Shell
對於使用 HTTP 或 Mixed Port 的本機 Clash,可以在目前的終端機工作階段設定:
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export ALL_PROXY=socks5h://127.0.0.1:7891
export NO_PROXY=localhost,127.0.0.1,::1
不少程式只識別小寫變數,也有程式會優先讀取大寫變數。為排除相容性差異,可以成對設定,但必須確保值一致:
export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export all_proxy="$ALL_PROXY"
export no_proxy="$NO_PROXY"
這些命令只會影響目前 Shell 及其後啟動的子程序,不會自動修改已開啟的編輯器、終端機分頁或背景服務。需要持久化時,再依使用的 Shell 寫入 ~/.zshrc、~/.bashrc 或對應的啟動檔案,並在修改後開啟新的終端機驗證。不要在多個啟動檔案中同時保留不同的連接埠。
Windows PowerShell 目前工作階段
$env:HTTP_PROXY = "http://127.0.0.1:7890"
$env:HTTPS_PROXY = "http://127.0.0.1:7890"
$env:ALL_PROXY = "socks5://127.0.0.1:7891"
$env:NO_PROXY = "localhost,127.0.0.1,::1"
使用 $env: 設定的變數只在目前 PowerShell 程序及其子程序中有效。透過系統設定寫入使用者環境變數後,已經執行中的終端機也不會自動更新,必須關閉後重新開啟。檢查實際值時請執行:
Get-ChildItem Env: |
Where-Object Name -Match '^(HTTP|HTTPS|ALL|NO)_PROXY$'
清除舊連接埠與錯誤變數
用戶端切換連接埠後,終端機裡可能仍保存舊值。例如 Clash 已改為 7897,而 HTTPS_PROXY 仍指向 7890。macOS 與 Linux 可使用以下命令暫時清除:
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY
unset http_proxy https_proxy all_proxy no_proxy
PowerShell 目前工作階段可使用:
Remove-Item Env:HTTP_PROXY -ErrorAction SilentlyContinue
Remove-Item Env:HTTPS_PROXY -ErrorAction SilentlyContinue
Remove-Item Env:ALL_PROXY -ErrorAction SilentlyContinue
Remove-Item Env:NO_PROXY -ErrorAction SilentlyContinue
清除後先執行一次不使用代理的請求,再依實際連接埠重新設定。如此可以確認問題不是多個來源彼此覆寫造成的。
第四步:檢查 Git、套件管理工具與開發工具的獨立設定
環境變數正確並不代表每個工具都會採用它。Git、npm、Python 工具鏈、Java 建置工具、編輯器與容器執行環境都可能保存自己的代理設定。排查順序應先查看設定來源,再決定刪除或修改,而不是同時寫入所有設定層。
Git 的全域與儲存庫設定
git config --show-origin --get-regexp 'http\..*proxy|https\..*proxy'
--show-origin 會顯示設定來自系統、使用者或目前儲存庫。若發現舊連接埠,可以更新全域設定:
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
如果希望 Git 改為跟隨環境變數,則刪除它自身的覆寫設定:
git config --global --unset http.proxy
git config --global --unset https.proxy
還要檢查儲存庫層級的設定,因為 .git/config 中的設定可能覆寫使用者設定。HTTPS 請求透過 HTTP 代理時,https.proxy 的值通常仍以 http:// 開頭,表示用戶端先連線至 HTTP 代理,再使用 CONNECT 建立 TLS 通道;這不代表最終網站使用明文 HTTP。
npm、pnpm 與 Python 工具
npm config get proxy
npm config get https-proxy
pnpm config get proxy
pnpm config get https-proxy
python -m pip config list -v
輸出仍是舊位址時,應在對應工具的使用者設定中修正。npm 可以透過以下命令刪除覆寫設定,讓它重新讀取環境變數:
npm config delete proxy
npm config delete https-proxy
Python 的 pip 可能讀取環境變數,也可能讀取使用者目錄或虛擬環境內的設定。使用 python -m pip,而不是單獨輸入 pip,可以確認目前檢查的是與當前 Python 解譯器對應的工具。
編輯器內建終端機與遠端開發
從桌面圖示啟動的編輯器,可能在修改終端機代理變數之前就已執行。其內建終端機繼承的是編輯器程序啟動時的環境,因此需要完全退出編輯器後再重新開啟。遠端 SSH、開發容器與 WSL 又是獨立環境:主機的系統代理不會自動成為遠端主機的代理,主機的 127.0.0.1:7890 對遠端主機也無法連線。
第五步:定位 DNS、規則模式與 TUN 差異
以網域名稱與 IP 對照 DNS 路徑
終端機錯誤包含 Could not resolve host、Name or service not known 或 getaddrinfo failed 時,連線甚至尚未進入目標網站。先執行系統解析測試:
nslookup example.com
curl -v https://example.com/
再對照使用 socks5h 的請求。如果代理端解析成功而一般請求失敗,應檢查作業系統 DNS、VPN 或網路擴充功能的解析路徑,以及應用程式是否自行指定 DNS。mihomo 的 fake-ip 模式會回傳保留位址並由核心對映網域名稱,這要求相關流量確實回到核心;某些略過系統網路堆疊、固定使用自訂 DNS 的程式可能會有不同表現。
no-resolve 只適用於帶有該參數的 IP 類規則,意思是對符合該 IP 規則的項目不主動解析網域名稱,並不是關閉整個 Clash 或 mihomo 的 DNS。看到設定中出現 IP-CIDR,...,no-resolve 時,不應將所有網域解析故障歸因於這個參數。
規則日誌比切換模式更有資訊
在 Rule 模式下,核心會依設定中的規則順序比對請求。日誌通常會顯示目標網域名稱或 IP、命中的規則、使用的策略群組與最終出口。若瀏覽器與終端機存取同一個網域名稱卻命中不同規則,常見原因包括終端機先將網域名稱解析為 IP、應用程式連線至不同子網域、IPv4 與 IPv6 結果不同,或兩者根本沒有進入同一個核心連接埠。
將模式暫時切換為 Global 只能用來縮小範圍:如果 Global 成功、Rule 失敗,應檢查規則與策略群組;如果兩種模式都失敗,則繼續檢查連接埠、DNS、節點與網路路徑。完成測試後應恢復原本的模式,不要將長期使用 Global 當成規則問題的修復方案。
TUN 能解決什麼,不能取代什麼
系統代理主要服務於願意讀取作業系統代理設定的應用程式。TUN 模式則透過虛擬網路介面接管更廣泛的 IP 流量,因此某些不支援 HTTP 或 SOCKS5 代理的終端機程式,在啟用 TUN 後可能恢復連線。這種現象表示原本的應用層代理入口未涵蓋該程式,不代表系統代理按鈕本身故障。
啟用 TUN 前,應在用戶端的「設定」→「TUN 模式」或對應網路設定中確認權限要求。Windows 可能需要服務模式或系統管理員權限,macOS 可能要求核准 VPN 設定或網路擴充功能,Linux 通常涉及網路管理權限、路由與 DNS 設定。不同用戶端基於 mihomo 的實作入口各異,應以用戶端目前的介面與日誌為準。
依結果收斂問題,而不是反覆切換開關
完成上述檢查後,可以依照以下順序形成可重現的結論。每一步都記錄命令、連接埠與日誌時間點,之後更換用戶端或設定時也能快速重新測試。
- 在用戶端確認目前核心正在執行,並記下 HTTP、SOCKS5 或 Mixed Port 的實際連接埠。
- 使用
lsof、ss或Get-NetTCPConnection確認該連接埠確實由預期的程序監聽。 - 使用
curl -x或curl --proxy socks5h://明確連線至代理,觀察 Clash 日誌是否出現對應請求。 - 明確指定代理成功後,再檢查
HTTP_PROXY、HTTPS_PROXY、ALL_PROXY與大小寫變數。 - 只有某個工具失敗時,查看 Git、npm、pip、編輯器或建置工具自身的設定來源。
- 網域名稱失敗而代理端解析成功時,轉向檢查系統 DNS、fake-ip 回流與應用程式自訂 DNS。
- 只有 TUN 成功時,確認目標程式原本是否支援系統代理,並檢查終端機、容器或遠端環境的網路邊界。
一個典型結果是:Clash 的 Mixed Port 實際為 7897,瀏覽器讀取了用戶端剛寫入的系統代理,因此存取正常;終端機中的 HTTPS_PROXY 仍指向 127.0.0.1:7890,Git 又在使用者設定中保存了相同的舊連接埠。修復順序應先將終端機變數改為 7897,再刪除或更新 Git 的覆寫設定,最後分別使用明確代理與一般 Git 請求重新測試。這個過程不需要反覆切換 Rule、Global 或 TUN。
另一個常見結果是:HTTP 代理測試失敗,但 socks5h://127.0.0.1:7891 成功。此時先確認 HTTP 連接埠是否存在,不要把 SOCKS5 連接埠當成 HTTP 連接埠;若一般 SOCKS5 失敗而 socks5h 成功,則繼續處理本機 DNS。透過這種分層對照,可以將「Clash 未生效」縮小為明確的連接埠、應用程式設定、解析或規則問題。