先釐清系統代理、終端機代理與 TUN 的差異
Clash 用戶端顯示「系統代理已啟用」,表示用戶端嘗試將代理設定寫入 macOS,不代表所有應用程式的流量都已接管。Safari 通常會使用系統代理;Chrome 預設也會讀取系統代理,但擴充功能、啟動參數或組織政策可能改變其行為。終端機中的命令列程式則各有代理設定方式,不能只憑瀏覽器能否開啟網頁來判斷。
圖形化用戶端負責匯入設定、切換策略組及管理系統設定;核心負責監聽代理連接埠、比對規則並轉送請求。即使用戶端介面仍在執行,核心也可能因設定錯誤而未能成功啟動。排查時應分開確認「代理設定已寫入」與「本機連接埠確實可用」。
| 連線方式 | 主要檢查位置 | 適用範圍 |
|---|---|---|
| 系統代理 | macOS 目前網路服務的代理欄位 | 應用程式必須主動遵循這些設定 |
| 終端機明確指定代理 | 命令參數、環境變數、工具設定 | 通常只影響指定程序及其子程序 |
| TUN 模式 | 虛擬網卡、路由、DNS 與權限 | 須有用戶端與核心支援,屬於另一種連線方式 |
確認核心正在執行,且本機連接埠有在監聽
查看執行設定,不要只看訂閱檔
先在用戶端確認目前設定是否成功載入,以及 HTTP、SOCKS 或混合連接埠的實際數值。不同用戶端的介面名稱與覆寫方式不盡相同,無法套用同一套選單路徑。訂閱檔中的連接埠也可能被用戶端設定覆寫,因此應優先查看執行設定與啟動記錄。
支援混合連接埠的核心可用同一連接埠接收 HTTP 與 SOCKS 請求。以下僅為部分欄位範例,並非包含節點與策略組的完整訂閱內容,排查時也不必覆寫原始檔案:
mixed-port: 7890
allow-lan: false
mode: rule
allow-lan: false 不影響本機使用 127.0.0.1。只排查目前這台 Mac 時,不必為了讓系統代理生效而開放區域網路存取。若要檢查 TCP 監聽狀態,可執行:
lsof -nP -iTCP:7890 -sTCP:LISTEN
- 若有監聽記錄:確認程序是否屬於預期的用戶端或其核心,並確認監聽位址允許本機回環連線。
- 若沒有記錄:檢查連接埠是否記錯、核心是否啟動失敗,以及設定記錄中是否有解析錯誤。必要時再以管理員權限確認程序是否可見。
- 若連接埠被其他程式占用:先排除衝突,再同步修改用戶端的監聽連接埠與系統代理連接埠,不要只改其中一處。
略過系統設定,直接測試代理連線
curl -I -v --connect-timeout 10 --max-time 20 \
--noproxy "" \
--proxy http://127.0.0.1:7890 \
https://example.com/
此命令會透過明確指定的 HTTP 代理存取 HTTPS 網址;--noproxy "" 可排除目前略過清單的影響。example.com 只是連線測試目標,也應換成實際出問題的網站重新測試。回應狀態碼不一定要是 200,重點是區分本機連線失敗、代理通道失敗、TLS 錯誤與遠端 HTTP 回應。
若顯示無法連線至 127.0.0.1:7890,先修復本機監聽;若已連上本機代理但逾時,再查看用戶端連線記錄、規則比對結果與節點記錄。明確指定代理後能正常存取,但瀏覽器仍失敗時,再進一步檢查 macOS 寫入代理設定的流程。
瀏覽器無法使用代理:檢查目前網路服務的代理欄位
確認目前使用的 Wi-Fi 或乙太網路服務
使用「系統設定」介面的 macOS,請前往「系統設定」→「網路」→目前使用的網路服務→「詳細資訊」→「代理」。Wi-Fi 也可以從「系統設定」→「Wi-Fi」→目前網路的「詳細資訊」進入。舊版「系統偏好設定」通常位於「網路」→目前服務→「進階」→「代理」。請以這台 Mac 上顯示的介面為準。
檢查「網頁代理(HTTP)」與「安全網頁代理(HTTPS)」:伺服器應指向 127.0.0.1,連接埠則應與用戶端的 HTTP 或混合連接埠一致。這裡的 HTTPS 代理設定是供 HTTPS 目標請求使用,不表示本機代理位址必須寫成 https://127.0.0.1。
macOS 會依網路服務分別儲存代理設定。剛從 Wi-Fi 切換到 USB 乙太網路時,舊服務上的設定正確,不代表新服務也設定正確。先列出服務,再查詢目前使用的服務:
networksetup -listallnetworkservices
networksetup -getwebproxy "Wi-Fi"
networksetup -getsecurewebproxy "Wi-Fi"
networksetup -getproxybypassdomains "Wi-Fi"
networksetup -getautoproxyurl "Wi-Fi"
networksetup -getproxyautodiscovery "Wi-Fi"
如果服務名稱不是 Wi-Fi,請以第一個命令列出的實際名稱取代,並保留引號。以下僅為預期欄位範例,並非這台 Mac 的檢測結果;HTTP 與 HTTPS 兩項都應分別檢查:
Enabled: Yes
Server: 127.0.0.1
Port: 7890
Authenticated Proxy Enabled: 0
排除 PAC、略過清單與瀏覽器設定覆寫
- 自動代理設定:PAC 指令碼可依目標決定使用代理或直接連線。記下原始值後,暫時只保留正在驗證的一種代理方式,避免將 PAC 的分流結果誤判為手動代理失效。
- 略過清單:
localhost、127.0.0.1、*.local常用於本機存取。檢查是否誤加目標網域或過於寬泛的萬用字元規則,不必清除所有本機略過項目。 - 瀏覽器擴充功能:在 Chrome 中停用代理切換擴充功能後重新測試;若裝置受組織管理,也要檢查相關政策,不要直接覆寫受管理的設定。
- 多個用戶端:避免同時讓兩個代理工具寫入系統設定。若設定反覆跳回舊連接埠,先確認是哪個程序仍在接管。
修改後重新載入網頁,必要時完全結束並重新開啟瀏覽器。優先選擇先前未載入過的頁面,避免快取影響判斷。同時觀察用戶端的連線記錄:完全沒有新連線,通常表示應用程式未進入代理流程;若出現連線卻被規則導向 DIRECT,問題則在規則選擇。
瀏覽器正常、終端機失敗:設定 shell 代理變數
在終端機啟動的 curl、Git、套件管理工具並不會一律遵循 macOS 系統代理。有些工具會讀取環境變數,有些使用自己的設定,也有些使用系統網路 API。建議先針對單一命令暫時測試,再決定是否設定整個 shell。
先為單一命令指定代理
http_proxy=http://127.0.0.1:7890 \
https_proxy=http://127.0.0.1:7890 \
curl -I --connect-timeout 10 --max-time 20 https://example.com/
這裡的 https_proxy 仍使用 http://,因為它指的是本機 HTTP 代理入口。存取 HTTPS 網站時,工具通常會透過 HTTP CONNECT 建立通道。不要只因目標是 HTTPS,就把變數值改成 TLS 代理位址。
為目前的終端機工作階段匯出變數
export http_proxy="http://127.0.0.1:7890"
export https_proxy="http://127.0.0.1:7890"
export no_proxy="localhost,127.0.0.1,::1"
env | grep -iE '^(http|https|all|no)_proxy='
curl -I --connect-timeout 10 --max-time 20 https://example.com/
這些匯出設定只影響目前的 shell 及之後啟動的子程序,不會自動變更其他已開啟的終端機視窗,也不會套用到所有從 Dock 啟動的圖形化應用程式。不同工具對變數大小寫的支援方式各異;例如 curl 的 HTTP 代理變數使用小寫 http_proxy,不能只設定大寫 HTTP_PROXY。
若使用 SOCKS 入口,可以單獨測試以下命令。只有在連接埠確實支援 SOCKS 時才使用;本例中的混合連接埠同時支援兩種請求。socks5h 會將目標主機名稱交由代理端解析,有助於區分本機 DNS 解析問題與代理連線問題。
curl -I --noproxy "" \
--proxy socks5h://127.0.0.1:7890 \
--connect-timeout 10 --max-time 20 \
https://example.com/
永久設定前,先處理舊變數
確認暫時測試成功後,可將需要的 export 行加入互動式 zsh 的 ~/.zshrc,再開啟新視窗或執行 source ~/.zshrc。其他 shell 請使用相應的啟動檔。關閉用戶端後,這些變數仍會指向本機連接埠,因此視需要啟用,通常更容易排查。
# 取消目前 shell 常見的代理變數
unset http_proxy https_proxy all_proxy no_proxy
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY
如果變數已寫入啟動檔,也必須刪除或註解相應行,否則新視窗會再次載入。檢查 all_proxy 是否指向舊連接埠,以及 no_proxy 是否包含目標網域;不同程式的優先順序與比對語法可能不同,不宜同時堆疊多組代理變數。
只有 Git 或套件管理工具失敗:檢查工具本身的設定
若同一個終端機中的 curl 已能正常連線,但 Git 仍失敗,接著應查看 Git 的設定來源,而不是反覆切換系統代理。舊的全域代理、儲存庫區域代理或依 URL 設定的代理,都可能讓 Git 使用不同的連線路徑。
git config --show-origin --get-regexp '.*proxy.*'
# 僅為本次 HTTPS 儲存庫連線指定代理
git -c http.proxy=http://127.0.0.1:7890 \
ls-remote https://github.com/git/git.git HEAD
第二個命令是公開儲存庫的連線測試,不會修改全域設定。若查詢結果包含帳號、密碼或私人位址,分享記錄前請先遮蔽敏感資訊。只有確認全域 http.proxy 設定有誤時,才使用 git config --global --unset http.proxy;儲存庫區域與 URL 專用設定則應在各自的設定範圍內處理。
- 使用 HTTPS 網址的 Git 請求與
git@主機:儲存庫格式的 SSH 請求,使用的是兩種不同的通訊協定入口,不能以 HTTP 代理測試結果直接推斷 SSH 是否可用。 - npm 可透過
npm config get proxy和npm config get https-proxy檢查個別設定,修改前請先記下原始值。 - 使用
sudo後,環境變數可能會被清除。不要為了傳遞代理設定就直接保留所有環境變數,應確認該工具實際需要的最少設定。
請求已進入 Clash:檢查規則、DNS 與 TUN
連線記錄中出現目標請求,表示至少這筆請求已抵達核心。此時「系統代理無效」往往不是精確描述,應進一步查看比對到的規則、策略組目前的選擇,以及最終出口。規則模式通常依設定順序比對,末尾的 MATCH 只會處理前面未比對到的請求;選取某個策略組,也不代表該組目前的成員就是代理節點。
- 規則出口:記下目標網域比對到的規則,以及最後使用的是節點、
DIRECT還是REJECT。若設定了直連規則,請求經過核心後仍可能直接連線。 - 節點與線路:針對同一個目標,換用其他可用節點重新測試。用戶端內的延遲測試只反映測試位址的結果,不能取代目標網站的實際連線測試。
- DNS:區分本機解析失敗、核心上游解析失敗與遠端連線失敗。不要把啟用
fake-ip當成通用解法;這也會涉及 DNS 接管與應用程式相容性。 - TUN:只有確實需要接管不遵循明確代理設定的應用程式時,才檢查用戶端支援、權限、路由與 DNS 設定。基於 mihomo 的用戶端也可能提供不同的 TUN 控制選項,請勿混用其他用戶端的操作步驟。
重新測試順序與結束後的還原
完成調整後,依照以下順序驗證。瀏覽器與終端機都測試成功,才能確認兩種連線方式設定正確;只要能開啟單一網頁,並不能證明所有應用程式都會透過代理。
- 使用
lsof確認實際連接埠正在監聽。 - 使用
curl --proxy明確指定代理進行測試,確認本機入口與目標網站都能連線。 - 檢查目前網路服務的 HTTP 與 HTTPS 欄位,再於瀏覽器重新載入目標頁面。
- 檢查終端機變數與工具本身的代理設定,並在同一個終端機中分別測試 curl 和實際使用的命令。
- 結束用戶端前,先關閉由其接管的系統代理;結束後再次檢查網路設定,避免代理仍指向已停止監聽的連接埠。
若用戶端異常結束後所有網頁都無法存取,請前往目前網路服務的「代理」頁面,記下並關閉殘留的本機手動代理,接著取消終端機變數,再測試直接連線。受組織管理的代理與 PAC 設定應依管理要求還原,不要一併刪除。若仍需定位問題,整理實際連接埠、服務名稱、明確代理測試失敗的階段,以及已遮蔽敏感資訊的連線記錄,會比只描述「代理沒反應」更有幫助。
連接埠與規則欄位可參閱 YAML 手冊;設定匯入與 TUN 的平台操作可參考 使用教學。排查的核心始終是將應用程式入口、本機核心與遠端出口分段檢查。