config.yaml 參考手冊

mihomo 設定檔參考

YAML 結構、連接埠、DNS、節點與分流規則。先確認欄位所在層級,再檢查引用關係與執行結果。

本頁適合已能啟動用戶端、想進一步了解設定行為的使用者。首次安裝、匯入訂閱與連線驗證,請先閱讀快速入門;遇到特定欄位、覆寫順序或服務執行差異時,再回到本頁依章節查閱。範例以在 Linux 上直接執行 mihomo 為準;圖形用戶端可能會額外產生連接埠、權限與覆寫設定。

YAML 結構與設定目錄

映射、清單與縮排

config.yaml 是具有階層結構的設定檔,不是逐行執行的指令稿。頂層的 dns、tun 是映射,其下再放置欄位;proxies、proxy-groups、rules 通常是清單,以連字號標示項目。縮排決定項目的所屬層級,建議統一使用兩個空格,不要混用定位字元。欄位拼字正確,卻縮排在錯誤的父項下方時,可能無法通過解析,也可能只呈現預期設定沒有生效。

冒號後留一個空格,布林值直接寫成 true 或 false,連接埠與間隔則使用數字。密碼、含特殊符號的名稱,以及看起來像日期的文字,建議加上引號。井字號在一般純量值中可能會開始註解,因此含井字號的密碼必須以字串表示。雙引號字串會處理反斜線跳脫;需要保留反斜線時,單引號通常更合適。不要習慣性地為所有內容加上雙引號,以免路徑中的反斜線被意外解讀為跳脫字元。

同一個映射中不要重複宣告相同的鍵。在檔案上方寫一段 dns,下方再寫另一段,不代表兩段會自動合併。不同解析器可能會拒絕重複鍵,也可能只保留其中一項,不能依賴這種行為。新增規則時,應找到原有的 rules 清單並繼續加入項目,不要再建立第二個同名清單。YAML 錨點可以減少重複文字,但不等於用戶端的覆寫機制,也不能取代對最終設定的檢查。

先建立可供驗證的最小設定檔

以下是一份僅使用直連的最小設定。它可用來驗證檔案路徑、解析器與監聽連接埠,不依賴訂閱或代理伺服器。這裡關閉 TUN,並明確將控制介面與混合連接埠綁定至迴路位址。測試成功只代表本機入口可用,不代表代理出口已建立。之後新增節點時,請保留這份最小設定作為疑難排解基準;複雜設定若無法啟動,可用它區分問題出在執行檔、系統環境或設定內容。

mixed-port: 7890
bind-address: 127.0.0.1
allow-lan: false
mode: rule
log-level: info
external-controller: 127.0.0.1:9090

tun:
  enable: false

rules:
  - MATCH,DIRECT

直接執行核心時,建議明確指定工作目錄與設定檔,避免從不同終端機啟動時讀取不同檔案。以下指令中的 -d 指定資料目錄,-f 指定設定檔路徑,-t 則用來測試設定。目錄中也可能有快取、Provider 下載內容與地理資料,不應把它們都視為設定本文。相對路徑通常依核心的工作目錄解析,而不是依終端機目前所在目錄推測;移轉服務時請重新確認這一點。

mkdir -p "$HOME/.config/mihomo"
mihomo -t -d "$HOME/.config/mihomo" \
  -f "$HOME/.config/mihomo/config.yaml"
mihomo -d "$HOME/.config/mihomo" \
  -f "$HOME/.config/mihomo/config.yaml"

區分來源檔與執行檔

圖形用戶端可能會分別管理訂閱原文、使用者覆寫與產生後的執行檔。編輯快取目錄中的產生檔,常會在下次切換設定或更新訂閱時被重建。請先從用戶端記錄確認核心實際載入的路徑,再決定要修改哪個來源。不要同時啟動圖形用戶端內建核心與獨立服務,監聽同一個連接埠;即使兩個程式讀取同名檔案,也可能位於不同目錄,使用不同的工作目錄、執行使用者與環境變數。

設定報錯時,先讀取第一則錯誤訊息與附近的行號,不要從最後一行開始猜。前一個清單項目少了縮排,可能讓解析器直到後面的合法欄位才停止。複製網頁範例後,請檢查是否混入全形冒號、彎引號或不可見空格。建議每次只新增一個完整模組,再執行測試並保留可還原的副本。若要依檔案自然順序複習,可搭配閱讀逐段拆解 config.yaml;但最終仍以本機核心的解析結果為準。

監聽連接埠、存取範圍與模式

連接埠是應用程式連入核心的入口

port 提供 HTTP 代理入口,socks-port 提供 SOCKS 入口,mixed-port 則可在同一個連接埠接受這兩種協定。一般桌面部署選用混合入口即可,不必為了欄位齊全而全部開啟。應用程式連線時必須選用正確的協定與位址;若把 HTTP 代理設定成控制介面的連接埠,或讓程式使用已關閉的 SOCKS 連接埠,核心正常執行也不會自動修正。

allow-lan 決定是否允許區域網路連線,bind-address 則限制監聽位址。僅供本機使用時,建議維持迴路位址綁定;要提供其他裝置使用時,再依實際網卡位址、防火牆與存取控制開放入口。綁定位址不是所有連接埠通用的安全策略,尤其不能假設控制介面與 DNS 監聽也會一併變更。修改後使用系統工具查看實際監聽狀態,比只看介面上的開關更可靠。

欄位用途本機範例
mixed-portHTTP 與 SOCKS 共用入口7890
allow-lan是否接受區域網路連線false
bind-address代理入口綁定位址127.0.0.1
external-controller管理介面監聽位址127.0.0.1:9090
log-level記錄詳細程度info

規則、全域與直連模式的差異

mode: rule 依規則選擇出口,是較容易說明與維護的長期使用模式。global 會將一般流量交由全域策略處理,direct 則主要用於直連驗證。模式控制的是核心如何處理已進入核心的流量,不會讓瀏覽器、命令列與背景程序自動接入。因此切換至全域模式後,完全沒有使用系統代理的程式仍可能直接連線;遇到這類情形,應先檢查流量接管路徑,而不是繼續更換規則。

圖形用戶端的模式切換可能透過管理介面立即變更執行狀態,但不一定會同步改寫訂閱來源檔。重新啟動後恢復舊模式時,應檢查用戶端的持續性設定與設定檔產生邏輯,不要在多個檔案中重複加入 mode。同樣地,策略組目前的選項可能來自快取,不一定是清單中的第一個項目。疑難排解時,請分別記錄檔案值、介面值與實際連線記錄,避免混淆這三個層面的狀態。

mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: info
external-controller: 127.0.0.1:9090
secret: "your-controller-secret"

管理介面可用來讀取狀態、選擇策略與載入設定,不是瀏覽器代理。若需要使用控制功能,應設定專用的存取金鑰,並將真實值留在本機。不要將管理介面直接暴露於公網,也不要把金鑰放進螢幕截圖、公開設定檔或問題回報中。若確實需要遠端管理,請先使用受控的存取通道,並分別檢查介面綁定、驗證機制與防火牆;只換成冷門連接埠,不能取代存取控制。

透過明確測試排除環境差異

先檢查監聽狀態,再讓單一指令明確使用代理。HTTP 入口與 SOCKS 入口應分別驗證;使用 socks5h 時,目標網域會交由代理端解析,方便與本機解析路徑區分。測試目標、網路與出口不同,結果也可能不同,因此請保留完整錯誤訊息,例如連線遭拒、交握失敗或網域解析失敗。不要只記錄「無法開啟」,否則很難判斷問題發生在接入之前還是出口之後。

ss -lntp | grep -E ':(7890|9090)\b'
curl --proxy http://127.0.0.1:7890 \
  --connect-timeout 10 --head https://example.com
curl --proxy socks5h://127.0.0.1:7890 \
  --connect-timeout 10 --head https://example.com
env | grep -iE '^(http|https|all|no)_proxy='

環境變數只會對繼承這些變數的程序生效,桌面設定也不保證會被所有命令列工具採用。大寫、小寫變數與 NO_PROXY 可能共同影響結果;需要隔離測試時,請清除目前指令的變數或使用明確參數,不要永久修改整個系統。暫時開啟詳細記錄後應及時還原,避免輸出過多目標資訊。連接埠已在監聽但仍無法連線時,可前往疑難排解,依序檢查代理入口、DNS、規則與節點。

DNS 上游、fake-ip 與解析路徑

先確認查詢是否進入核心

dns.enable 會啟用內建解析器,但不會單獨改變系統的 DNS 指向。桌面解析服務、路由器提供的位址,以及瀏覽器的加密 DNS,都可能繼續處理查詢。只有系統明確使用核心的監聽位址,或透過 TUN 等接管機制將查詢導入核心,相關 DNS 設定才有機會生效。疑難排解時,先整理應用程式、系統解析器、核心與上游之間的路徑,再評估上游是否合適;跳過這一步,容易反覆修改未被使用的欄位。

listen 是 DNS 服務的監聽位址,與混合代理入口不同。範例使用迴路位址上的高位連接埠,方便一般使用者進行隔離測試,不需要直接接管系統標準 DNS 連接埠。系統網路設定通常只接受伺服器位址,不支援填入任意連接埠,因此這段範例不能直接貼進桌面 DNS 位址欄。實際接管需要採用本機轉送、TUN 劫持或其他明確方案,並檢查系統解析服務是否已占用目標連接埠。

dns:
  enable: true
  listen: 127.0.0.1:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "*.lan"
    - "*.local"
  default-nameserver:
    - 223.5.5.5
  nameserver:
    - https://dns.alidns.com/dns-query
  proxy-server-nameserver:
    - 223.5.5.5

了解三種解析工作

nameserver 負責解析一般目標網域;default-nameserver 主要用來解析 DNS 上游本身的網域,讓加密解析服務能先取得位址;proxy-server-nameserver 則用於解析代理伺服器網域。分開考量這些工作,可避免代理連線依賴 DNS,而 DNS 又依賴尚未建立的代理,形成循環。範例中的公共解析服務只是可供測試的設定選項,部署時仍應考量所在網路是否可連線,以及自身的解析策略。

fake-ip 會回傳用來映射網域的合成位址;連線進入核心後,再還原網域並進行分流。這些位址不是目標網站的真實伺服器位址,看到它們本身不代表 DNS 遭到污染。用於映射的網段也不應與本機網路規劃衝突。若應用程式取得合成位址後繞過核心發起連線,可能無法抵達目標;因此 fake-ip 是否有效,取決於 DNS 路徑與連線路徑是否一致,不能只驗證一次查詢就認定整條鏈路正常。

fake-ip-filter 可讓指定網域取得真實解析結果,常用於區域網路探索或對位址行為敏感的應用程式。它不會決定流量直連,也不能取代規則清單。網域列入過濾清單後,後續連線仍須依分流規則選擇出口。疑難排解區域網路裝置問題時,應一併檢查名稱解析、真實位址、區域網路路由與規則,不要把所有連線失敗的網域都加入過濾清單;例外範圍過大會讓設定行為更難理解。

策略解析與快取的適用範圍

需要讓部分網域使用指定上游時,可考慮 nameserver-policy;需要上游連線遵循分流規則時,再研究 respect-rules。後者會改變 DNS 連線本身的路由依賴,因此也要明確設定代理伺服器網域的解析方式,避免形成自我依賴。不要把 fallback 簡化理解為主要伺服器失敗後才啟用的備用位址,它會與過濾判斷一起決定結果。初次部署時,建議先保留清楚且可驗證的單一路徑,再逐項增加複雜策略。

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA
resolvectl status
resolvectl query example.com

直接查詢核心與查詢系統解析器是兩種不同的測試。前者正常、後者異常時,應優先檢查系統指向與轉送;兩者都正常但瀏覽器異常時,還要檢查瀏覽器自己的加密 DNS、快取與代理設定。修改設定後,應用程式快取、系統快取與核心映射可能仍保留舊結果,必須確認要清除的是哪一層。長連線也可能繼續使用原本的位址,重新開啟頁面不一定代表建立了全新連線。

dns.ipv6 與頂層的 ipv6 適用範圍不同,不能只修改其中一項,就保證所有應用程式都不使用 IPv6。在雙堆疊環境中發生故障時,請分別測試 A、AAAA 記錄與實際連線位址,確認出口是否支援相應能力。更多逐項驗證方式,請參閱已連線卻無法瀏覽網頁的疑難排解清單。調整 DNS 應有明確目標,不建議同時更換上游、增強模式與路由設定,再僅憑網頁是否開啟來判斷原因。

代理節點欄位與訂閱 Provider

節點定義的是出口連線參數

proxies 用來儲存個別節點定義。每個項目至少需要可供引用的 name 與協定類型 type,其餘欄位則依協定補齊。名稱不只用於介面顯示,也會被策略組與規則引用,因此應保持穩定、唯一且易於辨識。名稱相似不代表節點相同;實際連線取決於伺服器位址、連接埠與驗證參數。變更名稱後,應同步檢查所有使用該名稱的清單,不能只確認節點項目本身通過解析。

以下以 Shadowsocks 說明最基本的欄位關係。伺服器使用保留的範例網域,密碼也是教學文字,必須換成服務提供者提供的真實參數才能連線。cipher 必須與伺服器設定一致,不能只因某個演算法看起來較新就自行替換。udp 是相關功能的開關,但無法讓不支援 UDP 的伺服器或網路自動取得這項能力;應用程式協定、核心實作、伺服器與傳輸路徑上的網路都必須支援。

proxies:
  - name: SS-Example
    type: ss
    server: proxy.example.com
    port: 443
    cipher: aes-128-gcm
    password: "your-password"
    udp: true

不同協定可能使用密碼、UUID、TLS 名稱、傳輸路徑或公開金鑰等欄位,不能將某種協定的參數原封不動套用到另一種協定。連線位址與 TLS 驗證名稱也可能不同,填入 IP 位址不代表可以省略憑證名稱。遇到憑證錯誤時,先檢查系統時間、伺服器憑證與名稱是否相符,不要把略過驗證當成通用修復方式。公開求助時,請移除驗證資訊與訂閱網址中的敏感參數,只保留必要的協定結構與錯誤訊息。

Provider 將節點更新與主設定分開管理

proxy-providers 適合用來讓主設定保留策略與規則,並將容易變動的節點清單交由外部檔案或訂閱更新。Provider 名稱與節點名稱屬於不同層級:策略組透過 use 引用 Provider,透過 proxies 引用具體節點或其他策略組。只宣告 Provider,不會讓所有規則自動使用它;仍須建立策略組,並將流量導向該組。這種分離方式方便更新,但也更需要檢查引用關係。

proxy-providers:
  local-nodes:
    type: file
    path: ./providers/local-nodes.yaml
    health-check:
      enable: true
      url: https://www.gstatic.com/generate_204
      interval: 600

proxy-groups:
  - name: PROXY
    type: select
    use:
      - local-nodes

本機 Provider 檔案必須符合節點集合格式,例如在檔案頂層放置 proxies 清單。主設定中的相對路徑依工作目錄解析,目錄必須存在,且服務執行使用者必須有讀取權限。不要任意將包含連接埠、DNS 與規則的完整用戶端設定檔當成節點檔案;即使某些輸入格式可相容,也不應依賴未確認的轉換行為。清單為空時,先開啟實際檔案,再檢查記錄中的讀取路徑、格式錯誤與節點篩選條件。

遠端更新、健康檢查與錯誤分類

HTTP 類型的 Provider 還需要 url、快取 path 與更新間隔 interval。更新間隔與健康檢查間隔是兩項獨立工作:前者重新取得節點定義,後者則測試既有節點連線至測試網址的結果。縮短其中一項,不會自動加快另一項。測試網址本身無法連線時,健康檢查可能大量失敗,但不代表所有節點的驗證參數都失效;應使用實際業務目標進一步驗證,避免只憑單一測試結果就大量刪除節點。

訂閱更新逾時、HTTP 狀態異常、內容不是 YAML,以及檔案缺少寫入權限,分屬不同故障類型。先確認請求是否收到回應,再檢查回傳內容與寫入檔案的結果。訂閱網址可能具備帳戶存取權限,備份與記錄檔應限制存取,不要上傳到公開儲存庫。若更新需要透過既有代理連線,必須安排可用的啟動路徑,避免初次安裝時因沒有節點而無法取得節點;本機快取有助於復原,但不能取代穩定的取得方式。

更新成功也可能改變節點名稱、地區標籤與可用協定,進而影響策略組篩選與手動選擇。維護時應比較節點清單的變化,不要把檔案下載成功等同於策略鏈完整。訂閱提供者與本站用戶端文件各有不同用途,用戶端不會憑空產生可用服務。需要安裝程式時,請前往用戶端頁面依平台選擇;Windows、macOS、Android 與 iOS 可先參考 Clash Plus,Linux 圖形介面部署則可參考 Clash Verge Rev。更新錯誤的詳細排查方式,請見訂閱失敗與定時更新設定。

策略組類型、引用與選擇狀態

策略組串接規則與實際出口

proxy-groups 用來定義出口決策。規則可以指向一個策略組,再由該組選擇節點、另一個策略組或內建出口。如此一來,規則只需引用穩定的用途名稱,不必在訂閱節點更名時逐條修改。策略組不只是節點的簡單資料夾;其類型會決定選擇方式。把所有節點放進同一組,不代表核心會同時使用它們。設計前先確認需求是手動選擇、依測試結果選擇、按順序容錯,還是分配連線,再選擇合適類型。

select 適合明確控制出口,由使用者或控制介面從清單中選擇一項。url-test 依測試結果選擇候選項目,fallback 主要依候選順序尋找可用出口,load-balance 則依策略分配連線。自動選擇是依據指定的測試網址,不代表所有業務的整體品質;某個節點測試速度快,仍可能無法連線至目標服務。檢視自動測試結果時,請將測試目標、測試方法與實際業務分開考量。

proxy-groups:
  - name: AUTO
    type: url-test
    use:
      - local-nodes
    url: https://www.gstatic.com/generate_204
    interval: 600
    tolerance: 50

  - name: PROXY
    type: select
    proxies:
      - AUTO
      - DIRECT
    use:
      - local-nodes

上方設定依賴前一章的 local-nodes Provider。AUTO 從 Provider 取得候選節點;PROXY 則可選擇自動組、手動選擇節點或直連。在組內保留 DIRECT 是明確提供手動選項,不代表代理節點失敗後一定會改為直連。若業務要求失敗時停止,而非切換出口,就應移除不符合要求的候選項,並確認容錯組的完整鏈路;不能只憑名稱中的「安全」或「固定」推測實際行為。

名稱引用形成有向關係

proxies 列出的名稱必須確實存在,大小寫與空格也都必須一致。策略組可以引用其他策略組,但不能形成循環,例如入口組引用自動組,而自動組又引用入口組。循環引用會讓選擇無法到達實際節點,可能在測試時被拒絕,也可能在執行時造成異常。可將設定畫成從規則到策略組、再到節點的箭頭圖;每條路徑最後都應到達具體節點或明確的內建出口。

組名與節點名稱不要重複,也不要將業務策略組命名成內建策略名稱。複雜名稱可加上引號,明確標示字串邊界,但引號無法修正名稱不一致的問題。Provider 更新後,若某個節點消失,手動選擇可能失效或改選其他候選項,應在用戶端查看目前實際選項。儲存選擇狀態的快取有助於重新啟動後還原,也可能造成「調整清單順序卻沒有切換出口」的誤解;清單第一項與執行時選中的項目是不同概念。

類型選擇依據注意事項
select手動選擇或由管理介面指定檢查目前儲存的選項
url-test候選節點對測試網址的結果測試結果不代表所有業務情境
fallback候選順序與可用性順序會影響出口優先順序
load-balance依設定的連線分配策略不會將單一連線的頻寬相加

控制自動切換的影響範圍

interval 控制定期測試,tolerance 可減少因細微差異而頻繁切換,但不保證連線品質。過於頻繁的測試會增加網路請求,節點數量多時尤其明顯。既有長連線通常不會只因策略組選擇改變,就無縫轉移至另一個出口;測試切換結果時,應建立新連線,並確認應用程式沒有沿用原本的連線工作階段。涉及登入狀態、地區判定或長時間工作時,應先確認是否能接受出口變更。

負載平衡通常依連線或目標的關聯分配,不會將同一個下載連線拆分至多個節點以累加頻寬。不同連線若從不同出口離開,可能觸發目標服務的工作階段限制,因此應依業務分組,而不是讓整個網站共用隨機出口池。需要固定出口的服務可引用獨立的選擇組,並在規則中優先比對;一般瀏覽流量則使用自動組。策略組越少越容易維護,但過度合併會讓一次切換影響不相關的業務。

策略組為空時,依序檢查 Provider 是否載入、篩選條件是否排除所有節點、引用是否指向正確的 Provider,以及協定支援限制是否排除了節點。若組內有候選節點但業務仍失敗,先手動選定一個節點並建立新連線,觀察規則最終指向與出口錯誤。不要同時修改組類型、測試網址與節點篩選條件,否則無法判斷是哪項變更造成結果。穩定的策略組應用途明確、選擇依據易於理解,並清楚定義失敗時的處理方式。

規則順序、比對語法與規則集

由上而下,先符合就先處理

rules 是有順序的清單,通常由上而下判斷,符合後便採用該條指定的策略。規則在檔案中的位置會直接影響結果,不是堆疊關鍵字後就會自動選出最精確的一條。常見的排列方式是將明確例外放在前面,業務網域與規則集放在中間,適用範圍較大的位址判斷放在後面,最後以 MATCH 作為兜底。若兜底規則放在前面,後面的項目通常就沒有機會參與比對。

DOMAIN 精確比對單一網域,DOMAIN-SUFFIX 比對網域本身及其子網域,DOMAIN-KEYWORD 則依字串關鍵字比對。關鍵字規則的涵蓋範圍容易超出預期,應謹慎使用,不能把短字串當成業務範圍界線。一般網域規則不包含網頁路徑;同一網域下的不同目錄,不能只靠網域規則區分。加密連線中可取得的目標資訊也會受應用程式行為、DNS 路徑與嗅探設定影響,不能假設每條連線都帶有完整 URL。

rules:
  - DOMAIN,example.com,DIRECT
  - DOMAIN-SUFFIX,example.org,PROXY
  - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR6,::1/128,DIRECT,no-resolve
  - IP-CIDR6,fc00::/7,DIRECT,no-resolve
  - MATCH,PROXY

這段範例依賴前面已有的 PROXY 策略組,目標網域僅用來展示比對範圍。私有位址直連規則適用於常見的本機網路,但是否涵蓋隧道網路、容器網路與企業網段,仍應依實際路由判斷。no-resolve 表示不為了這條位址規則主動解析目標網域,並非關閉整個 DNS 模組;若連線已取得目標 IP,仍可依位址進行比對。移除它可能增加解析依賴,應先理解需求再調整。

規則集格式必須符合內容

rule-providers 可將較長的規則集合獨立存放,再由主規則透過 RULE-SET 引用。Provider 的 behavior 說明項目屬於網域、位址或傳統規則語法,format 則說明檔案的編碼格式,兩者不是同一個欄位。若宣告為網域集合,卻填入完整規則行;或宣告為文字格式,卻提供含頂層映射的 YAML,都可能導致讀取失敗或無法依預期比對。應同時檢查宣告內容與實際下載的檔案。

rule-providers:
  business-domains:
    type: file
    behavior: classical
    format: yaml
    path: ./rules/business.yaml

rules:
  - RULE-SET,business-domains,PROXY
  - MATCH,DIRECT

對應的 business.yaml 檔案如下。規則集中的項目只描述比對條件,使用哪個出口則由主檔案中的 RULE-SET 規則決定。如此一來,同一份比對集合可在不同部署中採用不同策略,不必修改規則檔本身。維護時,本機檔案與遠端檔案應使用不同路徑,避免更新工作覆蓋手動編輯的內容。檔案存在卻沒有命中時,也要確認它在主規則中的位置,是否已被前面的寬泛規則提前攔截。

payload:
  - DOMAIN-SUFFIX,example.org
  - DOMAIN,api.example.net

先驗證比對結果,再調整規則集

遠端規則集更新失敗,不一定會立刻改變目前的行為;核心可能仍在使用既有快取。相反地,首次啟動時若沒有快取,某個規則集載入失敗可能影響設定載入或比對結果。因此應查看 Provider 載入狀態與錯誤記錄,不要只依本機檔案的修改時間判斷。使用地理資料類規則時,還須確認相關資料檔可用、格式受支援且更新機制明確;規則語法正確,不代表外部資料已準備就緒。

Linux 上的程序規則可能需要程序探索能力與相應權限;容器、轉送流量或以不同使用者執行的程式,也可能無法取得相同的程序資訊。程序規則沒有命中時,應先確認核心是否看得到該程序,而不是不斷修改程序名稱的拼字。來源位址規則也要區分本機應用程式與區域網路轉送來源。規則比對取決於實際可見資訊;路由或 NAT 改變來源後,原有規則的前提也可能不再成立。

疑難排解分流錯誤時,記錄目標網域、目標位址、命中的規則、最終策略組與實際出口。先在清單頂端加入一條範圍明確的暫時規則,驗證後再移回正確位置;不要一次刪除大量規則來「恢復網路」。規則更新後,請以新連線重新測試,必要時清除相關快取。若某個網站涉及多個網域,應依連線記錄逐一確認,避免只處理首頁網域,卻漏掉 API、靜態資源或驗證網域。

TUN 接管、Linux 權限與常駐服務

透明接管還需要核心以外的條件

tun.enable 會啟用虛擬網路裝置接管能力,auto-route 會要求設定相關路由,auto-detect-interface 則會嘗試識別出口網卡。這些欄位處理的是流量如何進入核心,不能取代節點、DNS 與規則設定。先確認明確指定代理的測試可正常運作,再啟用 TUN;否則入口、路由與出口同時改變,疑難排解範圍會變大。若桌面系統已執行其他 VPN 或透明代理,應先確認由哪個程式負責預設路由與 DNS。

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53

stack 決定 TUN 使用的協定堆疊方案,支援情形取決於平台、建置版本與核心實作。範例使用 mixed,但不應視為所有環境的固定最佳選項。dns-hijack 中的常見寫法適用於一般 DNS 查詢,不會自動解密瀏覽器或應用程式使用的 HTTPS DNS。啟用後仍須確認查詢路徑,尤其要留意系統本機解析服務、容器與自行設定上游的應用程式,不能只看介面上的 TUN 開關。

權限不足時,可能無法建立裝置或新增路由。先確認系統是否提供 /dev/net/tun,再檢查執行使用者與能力設定。容器還受裝置映射、網路命名空間與主機授權限制;在容器內使用管理員身分,不代表主機已授予所需的網路能力。在遠端伺服器上修改路由可能中斷管理連線,應準備主控台或還原通道,並先確認管理網段與既有 VPN 路由不會遭到錯誤接管。

授予的能力必須對應實際執行檔

直接部署核心時,可在評估權限範圍後授予必要的網路能力。以下以使用者目錄中的固定執行檔為例,請先確認路徑確實指向準備執行的檔案。能力會附加在該檔案上,更換或重新安裝執行檔後可能需要重新設定。不要授權來源不明的程式,也不要把授予網路能力視為已完成所有隔離;目錄寫入權限同樣重要,否則其他程序可能替換已獲授權的程式。

test -c /dev/net/tun
install -d "$HOME/.local/bin"
sudo setcap cap_net_admin,cap_net_bind_service=+ep \
  "$HOME/.local/bin/mihomo"
getcap "$HOME/.local/bin/mihomo"

cap_net_admin 涉及網路管理,cap_net_bind_service 用於綁定低位連接埠;是否需要後者,取決於實際監聽的連接埠。某些檔案系統或服務安全限制可能讓檔案能力無法如預期生效,因此查看能力輸出只是第一步,還應檢查啟動記錄。圖形用戶端可能透過自己的服務元件處理權限,不應同時套用另一套授權方式。若只需要明確指定 HTTP 代理,可保持 TUN 關閉,減少權限與路由變動。

使用者服務應維持路徑與記錄可追蹤

以下使用者服務採用固定工作目錄與絕對設定路徑,並在啟動前執行設定測試,適用於前文已安裝至使用者目錄的核心。systemd 不會以互動式 Shell 執行 ExecStart,因此不能依賴終端機中的別名、暫存變數或波浪號展開。範例中的 %h 會由 systemd 展開為使用者主目錄。若部署為系統服務,應另外規劃執行使用者、目錄權限與能力範圍,不能只把檔案移至系統目錄。

# 儲存為 ~/.config/systemd/user/mihomo.service
[Unit]
Description=mihomo user proxy service

[Service]
Type=simple
WorkingDirectory=%h/.config/mihomo
ExecStartPre=%h/.local/bin/mihomo -t -d %h/.config/mihomo -f %h/.config/mihomo/config.yaml
ExecStart=%h/.local/bin/mihomo -d %h/.config/mihomo -f %h/.config/mihomo/config.yaml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target

先建立服務目錄並儲存檔案,再重新載入單元。服務啟動後,檢查記錄中的實際路徑、權限錯誤與路由錯誤,不要只確認程序是否存在。使用者服務通常會隨使用者管理器的生命週期運作;若需要在登出後繼續執行,再評估是否啟用使用者常駐。常駐功能會改變背景工作的生命週期,應依電腦用途決定,不是所有桌面安裝都預設需要。

mkdir -p "$HOME/.config/systemd/user"
systemctl --user daemon-reload
systemctl --user enable --now mihomo.service
systemctl --user status mihomo.service
journalctl --user -u mihomo.service -n 80 --no-pager
ip route
ip rule

啟用 TUN 後若區域網路或另一條 VPN 失去連線,先停止服務並確認路由是否恢復,再比較啟用前後的路由表與策略路由。不要在不清楚路由來源時大量刪除項目,以免破壞系統網路管理器的狀態。服務停止後問題仍在,請確認是否還有其他核心執行個體、殘留的解析設定或用戶端背景服務。路由器部署還涉及轉送、防火牆與閘道關係,可參閱OpenWrt 旁路由部署說明;不要將本機 TUN 範例直接當成完整的旁路由方案。

覆寫合併、變更測試與還原

區分 YAML 語法與用戶端產生邏輯

覆寫是用戶端或外部工具加工設定的過程,不是所有 YAML 檔案本身都具備的功能。訂閱原文、本機覆寫與介面設定可能依不同順序合成執行檔,各用戶端的合併規則也可能不同。因此不要假設「後寫的欄位一定會覆蓋前面的欄位」,更不要把某個用戶端使用的擴充鍵直接交給獨立核心。應先確認由誰處理、輸入檔案有哪些,以及最終輸出位於何處,再追查特定項目為何被覆蓋。

純量、映射與清單需要分開檢查。連接埠數字通常容易替換;DNS 映射可能遞迴合併,也可能整段替換;規則與策略組清單則可能追加、插入前端或完全重建。若工具將覆寫中的 rules 整段替換到主設定,只有一條區域網路規則的覆寫就會移除原有代理規則。反過來說,若只是把新規則附加在兜底規則後方,新增項目也可能永遠不會命中。成功合併不代表順序符合預期。

維護訂閱設定時,建議由訂閱負責節點,本機設定則管理穩定的連接埠、安全範圍與業務策略。若可使用 Provider 分離,應優先讓節點獨立更新,減少每次更新整份檔案造成的衝突。但這不是所有用戶端都支援的通用操作步驟;圖形介面可能會重新產生相關段落,應使用其提供的覆寫或擴充入口設定,並透過最終執行檔確認結果,不能只看編輯器顯示儲存成功。

每次只變更一項行為來安排測試

變更前保留可還原的副本,並記錄目前模式、策略組選擇與接管方式。只備份 YAML 不一定能恢復執行狀態,因為用戶端快取、Provider 檔案與系統代理設定也可能影響結果。涉及 DNS 或 TUN 時,也應記錄原本的解析指向與路由資訊。備份若包含訂閱或驗證參數,應存放在限制存取的目錄,不要放進網站、共用同步目錄或公開問題附件;對外提交差異前,先移除敏感內容。

cd "$HOME/.config/mihomo"
cp -p config.yaml config.yaml.before-change
cp -p config.yaml config.candidate.yaml

# 編輯候選檔後,先檢查候選檔本身。
mihomo -t -d "$HOME/.config/mihomo" \
  -f "$HOME/.config/mihomo/config.candidate.yaml"

diff -u config.yaml.before-change config.candidate.yaml

候選檔應放在同一個工作目錄中測試,以便沿用預期的相對路徑;不過設定測試仍可能存取 Provider 或產生快取,不能視為完全隔離的沙箱。設定測試主要用來發現語法、欄位與引用問題,無法證明遠端節點可用、DNS 不會形成循環或路由不會衝突。測試通過後仍應檢查差異,確認沒有意外刪除策略組、擴大監聽範圍或將管理介面改成外部位址,再安排實際切換。

確認候選檔無誤後,再取代正式檔案,並依目前部署方式重新載入。使用本文的使用者服務時,可重新啟動服務,讓啟動前測試再次執行;若使用用戶端熱重載,則應確認載入的是目標設定,而不是另一份訂閱。重新載入成功後,應建立新連線進行驗證;舊連線可能仍沿用先前的出口與解析結果。若要主動中斷連線,請先考量正在進行的下載、遠端工作階段與其他使用者的工作,避免測試造成額外中斷。

cd "$HOME/.config/mihomo"
cp -p config.candidate.yaml config.yaml
systemctl --user restart mihomo.service
journalctl --user -u mihomo.service -n 80 --no-pager
curl --proxy http://127.0.0.1:7890 \
  --connect-timeout 10 --head https://example.com

# 需要還原時執行:
cp -p config.yaml.before-change config.yaml
systemctl --user restart mihomo.service

將驗證拆分成可判斷原因的層次

第一層檢查設定解析與程序啟動;第二層檢查代理、DNS 與控制介面的實際監聽狀態;第三層檢查節點交握與目標連線;第四層檢查規則命中與透明接管。只有上一層結果明確,下一層測試才容易解讀。若明確指定代理可用但 TUN 不可用,優先檢查接管與權限;若節點網域無法解析,先檢查引導解析;若連線成功但出口錯誤,則檢查規則順序與策略組選擇,不要反覆重新安裝用戶端。

還原後也要驗證結果。恢復檔案後,檢查服務是否確實重新載入、Provider 是否仍保留更新後的內容,以及用戶端是否再次覆寫連接埠與 DNS。若問題只在訂閱更新後出現,請保留已移除敏感資訊的結構差異,檢查節點名稱、協定欄位與策略組篩選條件,不要永久停用更新工作。找到具體原因後,維護記錄只需說明修改目的、相關欄位、測試結果與還原方式,不必保留含帳戶資訊的完整記錄。

長期維護應以實際需求為準,減少不必要的設定:未使用的入口保持關閉,業務例外範圍明確,遠端規則集來源可追蹤,啟動服務也只由一個元件負責。新增欄位前,先確認目前使用的核心是否支援,以及用戶端是否會在產生設定時移除該欄位。若仍無法確認行為,可回到快速入門中的最短驗證流程,或依疑難排解整理錯誤資訊。本手冊用於說明欄位與相依關係,最終仍應以本機載入的檔案、記錄與新建立連線的實際結果為準。