為什麼開發者只設定一個 Proxy 變數,仍然會遇到連線問題
對長時間使用 GitHub、npm、pip、Homebrew 與 Docker 的工程師來說,「在終端機 export 一個 HTTPS_PROXY」看似簡單,實際上往往只能解決其中一部分流量。不同工具使用的網路函式庫、子程序與憑證機制不完全相同:Git 可能透過 libcurl 建立 HTTPS 連線,npm 會讀取自己的設定檔,pip 通常同時受到環境變數與 index 設定影響,Homebrew 會啟動額外的下載程序,而 Docker CLI 與 Docker daemon 更可能分屬兩個不同的網路環境。
這也是開發者常遇到「瀏覽器可以開 GitHub,但 git clone 失敗」、「npm install 卡在某個套件」、「pip 能連官方索引卻抓不到 wheel」、「Docker pull 一直逾時」的原因。問題未必是節點本身失效,而是請求根本沒有走進 Clash,或不同工具分別套用了互相矛盾的代理設定。若只在某一個 Shell 視窗裡設定變數,IDE 內嵌終端、GUI 啟動的 Docker Desktop、遠端 SSH 工作階段與 CI 執行器也不一定能繼承相同設定。
本篇採用「先讓 Clash 接管,再按工具確認」的思路。你可以在 Clash Verge Rev 或其他支援 Mihomo 的用戶端中啟用 TUN 模式,讓較多不理會系統 Proxy 的程序進入同一個路由決策點;同時保留 Git、npm 或 pip 的顯式代理設定,作為可追蹤、可在團隊文件中重現的補充方案。TUN 並不是把所有流量無條件送往代理,而是讓流量先被 Clash 看見,再由規則決定代理、直連或拒絕。
開始前請先確認你的使用方式符合所在地法規、公司資安政策與各服務的使用條款。本文只討論一般開發環境的網路分流、設定與故障排查,不涉及繞過存取控制或未經授權的系統操作。
TUN 模式與規則分流:先建立正確的責任邊界
在 Clash 裡,TUN 模式與規則模式負責的事情不同。TUN 解決的是「封包如何進入 Clash」;規則解決的是「進入之後要走哪一個策略」。如果 TUN 已開啟,但規則把 github.com、套件 CDN 或容器 registry 判成 DIRECT,結果仍然可能是逾時。反過來,如果規則寫得很完整,卻有工具透過特殊網路堆疊繞過系統路由,連線紀錄中就可能完全看不到請求。
| 方案 | 適合情境 | 優點 | 需要留意 |
|---|---|---|---|
| 環境變數 Proxy | 快速驗證單一 CLI 或單一專案 | 設定明確,容易暫時開關 | 不同 Shell、IDE、子程序可能沒有繼承 |
| 系統 Proxy | 瀏覽器、一般 GUI 與支援系統設定的工具 | 日常操作簡單,影響範圍容易理解 | 不少開發工具與背景服務不會讀取 |
| Clash TUN | 需要涵蓋不讀 Proxy 變數的程序或子程序 | 接管範圍廣,可在連線列表集中觀察 | 可能與 VPN、公司零信任軟體及容器網路衝突 |
| TUN 加顯式 Proxy | 需要同時處理 CLI、GUI 與特殊服務 | 可用 TUN 補足漏網流量,並保留工具層可讀設定 | 要避免重複代理、迴圈路由與錯誤的 NO_PROXY |
實務上建議先用規則模式與系統 Proxy 做最小驗證,再開啟 TUN。啟用後,觀察 Clash 的連線列表是否出現 GitHub、套件來源、registry 或相關 CDN。若列表裡完全沒有目標請求,先檢查 TUN 的系統權限、虛擬網卡狀態、DNS 設定與其他 VPN;若請求已出現但策略顯示 DIRECT,則應優先調整規則,而不是立刻更換節點。
在 Clash 用戶端啟用 TUN:用最小範圍完成第一輪驗證
先開啟 Clash 用戶端,確認目前載入的是你真正使用中的設定檔,而不是僅下載完成但尚未啟用的訂閱。接著確認模式為 Rule,不要在排錯初期直接使用 Global。Rule 模式能讓你從連線紀錄看出每個目的地套用了哪個策略,較容易分辨是代理出口問題、規則順序問題,還是本機工具根本沒有送出請求。
啟用 TUN 前,先關閉其他會改寫系統路由的 VPN、舊版 Clash 客戶端與企業網路代理。某些平台需要 Service Mode 或系統管理員權限,macOS 可能要求允許網路擴充功能,Windows 則可能需要核准虛擬網卡或服務。這些權限不是「節點設定」,但缺少其中任何一項,都可能造成 TUN 開關看似已開、實際上沒有封包經過。
- 確認混合埠與 DNS 狀態:記下目前的
mixed-port,並確認 DNS 沒有被另一套軟體強行接管。顯式 Proxy 會使用混合埠,但 TUN 主要依靠虛擬介面與路由表。 - 啟用 TUN 與必要權限:按下開關後,檢查系統是否出現新的虛擬網路介面,以及 Clash 狀態頁是否顯示已運作。
- 保留 Rule 模式:先不要使用全域代理,讓 GitHub、套件站與本機服務按照規則分流。
- 測試一個簡單目的地:使用瀏覽器或
curl發出請求,再回到 Connections 查看目標網域與命中的策略。 - 記錄結果:把「目的地、策略、節點、是否成功、耗時」記下來。這比只描述「網路很慢」更有助於後續定位。
TUN 的 DNS 行為尤其值得注意。若 DNS 請求在本地解析、HTTPS 流量卻走另一條路,可能出現網域解析成功但連線到錯誤 IP 的狀況;若 DNS 被代理後又被系統安全軟體攔截,也可能表現為所有套件來源都無法解析。排錯時不要同時修改 DNS、策略組與節點,否則每次測試都改變多個變數,很難知道哪一項真正有效。
完成第一輪測試後,再決定哪些網域應該代理、哪些服務應該直連。GitHub 的程式碼與 Release 下載可能需要不同的 CDN;npm、PyPI 與 Homebrew 的官方網域也可能跳轉到其他主機。規則應以連線列表中實際出現的目的地為準,並注意規則順序:較具體的網域規則要放在廣泛的 GEOIP、MATCH 或直連規則之前。
Git、npm、pip 與 Homebrew:按工具建立可重現的代理層
Git:分辨 HTTPS、SSH 與憑證問題
Git 使用 HTTPS 下載時,通常能讀取 HTTP_PROXY、HTTPS_PROXY 或 Git 自身的設定;但 SSH remote 使用的是另一套連線方式,不能因為 HTTPS clone 成功,就推論 [email protected] 一定能通。建議先用 HTTPS remote 做基準測試,確認 Clash 連線列表看得到 GitHub,再決定是否需要為 SSH 設定獨立的 ProxyCommand 或改用公司允許的跳板方式。
Git 的顯式設定可讓單一專案或單一使用者範圍內的行為更清楚,但不要把帶有帳號密碼的 Proxy URL 直接寫入公開 repository。若公司有內部 Git、鏡像站或私有 registry,應透過 NO_PROXY 或更精準的 Git host 設定讓內網資源直連,避免原本可用的內部服務被送到外部節點。
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
git config --global --get-regexp 'http.*proxy'
如果 Git 顯示憑證錯誤,不要先關閉 SSL 驗證。先檢查系統時間、企業 TLS 檢查、CA 憑證與代理節點是否重新簽發憑證。把安全檢查關掉只能掩蓋問題,也會讓原始碼與套件下載暴露在不必要的風險中。
npm、pip 與 Homebrew:留意索引、跳轉與快取
npm 除了套件索引,還會下載 tarball、查詢 audit 或連接套件作者指定的額外來源。一次 npm install 失敗,不代表只要代理 registry.npmjs.org 就足夠。先用 npm 的設定查出目前 registry 與 proxy 值,再在 Clash 連線列表中對照實際命中的網域。若專案使用 lockfile,還要留意 lockfile 內是否固定了另一個 registry 或私有鏡像。
pip 的情況類似。你可能同時設定了 HTTPS_PROXY、index-url、extra-index-url 與憑證選項。私有套件來源與 PyPI 不一定應使用相同策略;若公司內部索引只能在 VPN 內存取,應讓它維持直連或走公司 VPN,而不是把所有 Python 下載一律轉到同一個代理出口。當 pip 顯示找不到相容版本時,也要區分「網路沒有取到索引」與「目前 Python 版本沒有可用 wheel」這兩種完全不同的問題。
Homebrew 會下載 formula、cask 與預編譯套件,來源可能分散在 GitHub、物件儲存服務與 CDN。只為 brew 設一個 Proxy 不代表所有下載都會使用相同路徑;如果更新索引成功、安裝 cask 卻失敗,應查看失敗時最後一個實際網域。Homebrew 的快取也可能讓你誤以為代理已修好,因此排錯時可先記錄完整錯誤,再在不破壞既有環境的前提下重試。
對這三類工具,最穩定的做法不是無限制增加網域白名單,而是先定義清楚的邊界:公開套件來源依規則走代理,企業內部來源依公司網路直連,開發機上的本機服務使用 NO_PROXY 排除。localhost、127.0.0.1、內部網域與私有 IP 是否要排除,應按你的拓樸確認;錯誤的萬用字元可能讓真正需要代理的網域也被略過。
Docker 與 TUN 的交集:CLI、daemon、容器內流量不是同一件事
Docker 是整條開發鏈中最容易被誤判的部分。你在宿主機終端執行 docker pull 時,實際可能是 Docker CLI 呼叫背景中的 Docker daemon;如果 daemon 跑在 Docker Desktop、虛擬機或遠端伺服器裡,它不一定會讀取目前 Shell 的 HTTPS_PROXY。因此,宿主機的 Git 與 npm 已經成功,不代表 Docker registry 也會沿用相同出口。
第一步是分辨 Docker 的執行位置。Linux 上常見 daemon 由 systemd 管理;macOS 與 Windows 的 Docker Desktop 則通常在虛擬化環境中運作。你應先確認 daemon 到 registry 的連線是否能在 Clash Connections 中被看見。若完全沒有記錄,代表流量可能在另一個虛擬網路層,單靠宿主機 TUN 未必能直接接管;這時應依 Docker Desktop 或公司網路架構設定 daemon 層代理,而不是重複修改宿主機的 Git 設定。
第二步是區分 docker pull 與容器執行時的外連。拉取映像檔是 daemon 對 registry 發出請求;容器內執行 apt、npm install、pip install 或呼叫 API,則是容器網路命名空間發出的另一批流量。即使映像能成功拉下來,建置階段仍可能因容器沒有代理變數、DNS 不可用或公司內部來源無法解析而失敗。
若 Dockerfile 需要在建置期間下載套件,應透過建置參數或專案文件明確傳入必要的代理,而不是把含有認證資訊的 Proxy URL 寫死在 image layer。執行容器時,也要把宿主機的 127.0.0.1 觀念與容器內部區分開來:容器中的 localhost 指向容器自己,不是宿主機上的 Clash。若要讓容器使用宿主機代理,需依作業系統與 Docker 網路提供的 host gateway 方式處理,並確認防火牆與 Allow LAN 設定沒有造成額外暴露。
| 測試對象 | 實際發出請求的一方 | 優先檢查位置 |
|---|---|---|
git clone |
目前 Shell 中的 Git 程序 | Git proxy、環境變數、Clash 連線列表 |
docker pull |
Docker daemon | Docker Desktop 或 daemon 層代理 |
| Dockerfile 的套件安裝 | 建置程序與暫時容器 | build args、DNS、容器內環境 |
| 容器啟動後 API 請求 | 執行中的容器程序 | 容器環境變數、網路模式與 TUN 可見性 |
連不上、很慢或偶發逾時:一套不靠猜的排錯順序
當某個工具失敗時,先不要同時切換節點、改 DNS、改模式與刪快取。建議按照以下順序縮小範圍,每次只改一個變數:
- 確認請求是否發出:在 Clash 連線列表中以 GitHub、registry、PyPI 或錯誤訊息中的主機名搜尋。如果完全沒有紀錄,檢查工具是否使用另一個程序、另一台主機或另一個虛擬網路。
- 確認命中策略:請求出現後,看它是 PROXY、DIRECT、REJECT 還是某個策略群組。先處理明顯錯誤的 DIRECT 或 REJECT,再討論節點品質。
- 確認 DNS 與實際 IP:同一網域在不同 DNS 下可能得到不同 CDN 位址。若只有某一個來源失敗,查看是否為解析、SNI、IPv6 或 CDN 路由差異。
- 確認工具實際讀到的設定:檢查目前 Shell 的環境變數、Git config、npm config、pip 設定與 Docker daemon 狀態。不要只看你曾經編輯過的檔案。
- 確認長連線特性:下載大型映像、Git LFS、串流 API 與套件 tarball 對節點穩定度要求不同。短暫的 HEAD 測試成功,不等於長時間傳輸不會重置。
- 排除本機衝突:暫時停用第二套 VPN、企業安全代理或過時的 Clash 服務,確認是否存在埠號、路由表與 DNS 接管衝突。
可以使用簡單的分層測試來建立基準:先測試本機混合埠是否可用,再測試一個公開 HTTPS 目的地,接著測試實際套件來源,最後才測試 Docker daemon 或容器內的請求。若第一層就失敗,問題在 Clash 本機服務;若第一層成功、第二層失敗,檢查節點與規則;若只有特定工具失敗,才把焦點移到該工具的設定、憑證或程序繼承。
當你確定規則與 TUN 都正常,仍然出現間歇性逾時,請記下時間、目的地、節點、IPv4/IPv6 情況與錯誤類型。TLS handshake、HTTP 407、connection reset、context deadline exceeded 與 DNS failure 的處理方向不同。把它們全部統稱為「代理不穩」會讓後續維護失去線索,也容易在團隊中反覆重做同一輪嘗試。
相較於只靠某個終端工具的隱藏設定,部分舊式代理程式常見的不足是只支援 HTTP、對 Docker daemon 或子程序繼承不完整,遇到 CDN 跳轉時也不容易觀察實際目的地;而 Clash 的 TUN、規則分流與即時連線列表能把 Git、套件管理器和容器流量放到同一個可檢查的路由框架中,讓你既能為開發工具保留明確的顯式設定,也能補足忽略環境變數的程序。如果你希望把這套全鏈路流程落地到自己的工作站,接下來可依作業系統取得合適的 Clash 用戶端。