先用明確指定代理的請求定位問題,再調整系統代理或 DNS。用戶端顯示「已連線」,通常只代表核心或接管功能已啟動,不代表瀏覽器請求確實經過該核心,也不代表目前的節點能連上目標網站。請依「監聽連接埠 → 指定代理請求 → 應用程式代理 → DNS → 規則與節點 → TUN」的順序檢查,每次只調整一項。

1. 確認核心正在監聽,而不只是介面有開啟

先檢查程序與連接埠。以下兩個指令只會讀取狀態,不會修改設定。ss 顯示程序資訊可能需要管理員權限;若沒有權限,仍可先確認監聽位址與連接埠。

pgrep -af 'mihomo|clash'
sudo ss -lntp 'sport = :7890'
  • 沒有監聽結果:檢查核心是否啟動失敗、設定檔是否解析錯誤,或實際使用的連接埠是否不是 7890。
  • 監聽於 127.0.0.1:7890:本機程式可以連線,區域網路中的其他裝置無法直接使用此入口。
  • 監聽於 0.0.0.0:7890:入口涵蓋 IPv4 本機網路介面,還須檢查區域網路存取權限與防火牆。
  • 連接埠由其他程序占用:先確認是哪個程序,再停用衝突的執行個體,請勿直接批次結束所有代理程序。

mixed-port 可同時接受 HTTP 和 SOCKS 請求。若設定只使用 port 或 socks-port,就必須分別使用對應的協定與連接埠;external-controller 則是管理介面,不能當作瀏覽器代理連接埠。

# 僅檢查此目錄中的設定,不會啟動第二個常駐執行個體
mihomo -t -d "$HOME/.config/mihomo"

測試通過只代表目前的二進位檔能解析該設定,不保證服務實際使用這份設定。若是自建的 systemd 使用者服務,可執行以下指令確認啟動參數;系統層級服務則應改用 sudo systemctl,並移除 --user。

systemctl --user cat mihomo.service
systemctl --user status mihomo.service --no-pager
journalctl --user -u mihomo.service -b -n 80 --no-pager

若顯示找不到服務,請回到圖形用戶端查看核心記錄,不要為了排查而額外啟動另一個使用相同連接埠的服務。請優先搜尋 address already in use、設定解析失敗、權限不足及 Provider 載入錯誤。

2. 用 curl 明確指定代理,區分應用程式與核心問題

先測試 HTTP 代理入口。--noproxy "" 會清空這次請求的略過清單,避免環境變數中的 NO_PROXY 讓測試意外直接連線。範例使用相同的 HTTPS 位址,方便比較結果;實際排查時,也應對無法開啟的目標執行相同測試。

curl --noproxy "" -x http://127.0.0.1:7890 \
  --connect-timeout 5 --max-time 20 \
  -v -o /dev/null https://example.com/
結果說明下一步
Connection refused本機 TCP 連線遭拒確認監聽連接埠與位址
407代理要求驗證確認設定中的驗證方式與應用程式憑證
已建立 CONNECT,之後逾時代理入口已有回應,但後續連線尚未完成檢查規則、節點與目標連線記錄
certificate verify failedTLS 驗證失敗檢查系統時間、憑證存放區與中間代理
收到目標 HTTP 回應此請求路徑已可正常往返檢查瀏覽器與系統代理設定

HTTP 403 或 429 代表目標網站或中間服務已回應,不應直接判定為連接埠失效。單次成功也只能證明目前目標與規則路徑可用,不能據此認定所有網站、UDP 或 IPv6 都正常。

再比較一次不使用明確代理的請求

curl --proxy "" --noproxy "*" \
  --connect-timeout 5 --max-time 20 \
  -I https://example.com/

此指令會停用 curl 的明確代理,但不會略過系統中的 TUN、策略路由或透明轉送。若要比較真正的直接連線基準,請先在可復原的本機環境中關閉 TUN,再重複測試。若明確指定代理後請求成功、瀏覽器卻失敗,請優先查看下一節,不要立刻更換 DNS。

3. 確認系統代理、瀏覽器設定與終端機環境變數一致

Linux 桌面代理、終端機環境變數與瀏覽器本身的設定是不同入口。啟用其中一項,不代表另外兩項也會自動生效。以 GNOME 桌面為例,前往「設定」→「網路」→「網路代理」,選擇「手動」,將 HTTP 與 HTTPS 的代理主機設為 127.0.0.1、連接埠設為 7890;不同發行版的選項名稱可能略有差異。

HTTPS 欄位代表「HTTPS 請求要使用哪個代理」,不表示代理協定必須設為 HTTPS。使用本機 mixed-port 時,終端機中的 https_proxy 通常仍應填入 http://127.0.0.1:7890。

# 查看目前 shell 中的代理變數;輸出可能含有憑證,請勿直接公開
env | grep -iE '^(http|https|all|no)_proxy='

# 僅為這次 curl 請求設定代理
http_proxy=http://127.0.0.1:7890 \
https_proxy=http://127.0.0.1:7890 \
curl --noproxy "" --max-time 20 -I https://example.com/

檢查略過清單與重複接管

  • NO_PROXY=* 會讓支援此變數的程式略過代理。測試時請清空此變數,再逐一加回本機與內部網路例外。
  • 可在 Firefox 的「設定」→「一般」→「網路設定」→「設定」中確認使用的是系統代理還是手動代理。擴充套件也可能會接管這項設定。
  • 舊的 shell、已啟動的 IDE 與背景服務不會自動取得新終端機中的變數。修改後,應在相關程序的環境中重新驗證。
  • 容器中的 127.0.0.1 指向容器本身,而不是主機。主機連接埠正常,不代表容器也能連線。

若懷疑舊變數造成干擾,可用以下指令進行一次乾淨的測試。這只會影響此次子程序,不會刪除 shell 設定檔中的持久設定。

env -u http_proxy -u https_proxy -u all_proxy -u no_proxy \
  -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY -u NO_PROXY \
  curl --noproxy "" -x http://127.0.0.1:7890 \
  --max-time 20 -I https://example.com/

4. 區分系統 DNS、核心 DNS 與 fake-ip

網域名稱解析失敗,不一定是系統 DNS 出問題。HTTP CONNECT 可以將目標主機名稱交給代理;SOCKS 則可透過選項選擇由哪一端解析。請用以下兩個指令比較:第一個由 curl 在本機解析,第二個則將網域名稱交由 SOCKS 代理解析。

curl --noproxy "" --socks5 127.0.0.1:7890 \
  --max-time 20 -I https://example.com/

curl --noproxy "" --socks5-hostname 127.0.0.1:7890 \
  --max-time 20 -I https://example.com/

若本機解析失敗、代理端解析成功,應優先檢查系統解析器;但這只是線索,並非唯一結論,因為兩次連線可能命中不同的位址與規則。請繼續查看系統實際使用的解析設定。

getent ahosts example.com
ls -l /etc/resolv.conf
cat /etc/resolv.conf

# 僅適用於已啟用 systemd-resolved 的系統
resolvectl status
resolvectl query example.com

若 /etc/resolv.conf 指向由 systemd-resolved 或 NetworkManager 管理的檔案,直接覆寫可能在重新連線後失效。請透過對應的網路管理工具修改 DNS,不要讓 DHCP 更新設定的同時又手動寫入。

檢查 mihomo 的 DNS 監聽與 fake-ip 路徑

假設實際執行的設定中已有 dns.listen: 127.0.0.1:1053,可在已安裝 dig 的終端機直接查詢核心 DNS。若監聽連接埠不同,也要相應調整指令。

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA

使用 enhanced-mode: fake-ip 時,網域名稱可能會解析為設定範圍內的合成位址,常見範圍為 198.18.0.1/16。這不是公開網際網路上的目標位址,後續連線必須回到保有網域對應資料的代理核心。若應用程式取得 fake-ip,卻透過未受接管的路由直接連線,就可能一直逾時。

上游 DNS 本身也可能需要網域解析或代理連線。請檢查 default-nameserver、nameserver、proxy-server-nameserver 的用途與目前設定,避免節點網域的解析依賴尚未建立的代理連線。欄位說明可參考設定參考;請勿一次更換所有上游 DNS,再猜測是哪一項生效。

5. 檢查規則命中與節點狀態,別只看延遲數字

在用戶端的連線記錄中找到測試網域,確認最終出站是 DIRECT、某個代理節點,還是拒絕動作。規則由上往下比對,最後的 MATCH 是預設規則;若前面的網域或 IP 規則已命中,修改預設策略組不會改變這次請求。

  1. 記下測試時間與目標網域,再重新執行一次明確指定代理的 curl 請求。
  2. 在連線記錄或日誌中搜尋對應網域,確認命中的規則與策略組。
  3. 檢查策略組目前選用的項目,尤其是巢狀策略組最後使用的實際節點。
  4. 暫時改選另一個已知可用的節點,保持目標位址、請求方式與模式不變,再比較結果。

延遲測試成功,只代表當時能連上設定中的測試 URL,不代表所有網站都能使用。節點可能只在特定目標、協定或位址族上失敗。訂閱更新成功也只代表已取得設定,不能證明節點的驗證資訊、流量額度與服務端口都正常。

短時間提高日誌層級,完成後恢復

必要時可將實際設定中的 log-level 暫時設為 debug,重現一次問題後再恢復為 info。圖形用戶端應透過提供的設定覆寫或日誌選項修改,避免產生的執行設定在下次更新時被覆蓋。分享日誌前,請移除訂閱網址、驗證資訊與私人存取網域。

# 自建使用者服務:修改設定後先測試,成功再重新啟動
mihomo -t -d "$HOME/.config/mihomo" && \
  systemctl --user restart mihomo.service

journalctl --user -u mihomo.service --since "5 minutes ago" --no-pager

遇到憑證錯誤時,先執行 timedatectl status 檢查時間與同步狀態,再檢查憑證存放區與節點網域。請勿把停用憑證驗證當成一般修復方式,否則可能掩蓋位址錯誤或中間連線問題。

6. 明確指定代理正常但 TUN 失敗:檢查權限、路由與 IPv6

若 curl -x 正常,但啟用 TUN 後瀏覽器無法連線,且已有證據確認連接埠與節點可用,接下來應著重檢查透明接管。TUN 需要虛擬網卡、相應權限與路由;設定中的 tun.enable: true 不代表這些條件都已具備。

ls -l /dev/net/tun
ip -br link
ip rule show
ip route show table all
ip -6 route show table all
  • 找不到 /dev/net/tun:檢查系統是否支援並已啟用 TUN。容器或受限的虛擬化環境還需要主機授權。
  • 日誌顯示建立介面或修改路由失敗:請使用用戶端提供的服務模式,或確認自建服務的權限;請勿任意放寬執行檔權限。
  • 若同時執行其他 VPN:比較雙方的策略路由、預設路由與 DNS 接管設定。測試時一次只保留一條接管路徑。
  • IPv4 正常、IPv6 失敗:分別檢查 IPv6 預設路由、DNS 的 AAAA 回應,以及目前核心的 IPv6 處理設定。
# 關閉 TUN 後,比較主機原始 IPv4 / IPv6 連線能力
curl --proxy "" --noproxy "*" -4 --max-time 15 -I https://example.com/
curl --proxy "" --noproxy "*" -6 --max-time 15 -I https://example.com/

此處的 -4 與 -6 用來檢查直接連線的基準狀態。對本機 HTTP 代理使用相同選項,無法可靠控制遠端節點連線至目標時使用的位址族。若網路本身沒有 IPv6 出口,IPv6 測試失敗不代表節點故障。

7. 以最少變更恢復連線,並保留重現紀錄

排查完成後,請用相同目標重新測試終端機、瀏覽器與 TUN 這三條路徑。不要只憑系統匣圖示或單次測速判斷問題已解決。建議保留下列紀錄,方便問題再次發生時直接比較。

  1. 執行中的執行個體:記錄核心版本、實際設定檔路徑、監聽位址與 mixed-port。可用 mihomo -v 查看版本。
  2. 應用程式入口:記錄瀏覽器使用系統代理或手動代理,以及終端機是否保留代理變數。
  3. 解析路徑:記錄系統 DNS、核心 DNS 監聽連接埠、是否使用 fake-ip,以及瀏覽器是否啟用安全 DNS。
  4. 出站結果:記錄測試網域命中的規則、實際節點與錯誤發生時間,不要記錄訂閱金鑰。
  5. 復原設定:將 debug 日誌恢復為日常層級,並撤銷臨時全域模式與不再需要的測試變更。

最能區分問題來源的判斷方式是:明確指定代理後仍失敗,先檢查核心與出站;明確指定代理成功但瀏覽器失敗,先檢查應用程式入口;只有 TUN 失敗,先檢查透明接管;只有本機解析失敗,再沿著系統 DNS 路徑排查。若要重新建立基本設定,請依照快速入門先完成最精簡的可用連線,再逐項恢復規則、Provider 與 TUN。