訂閱網址與訂閱格式

訂閱網址是取得設定的入口,格式則是伺服器回傳內容的結構。以 HTTPS 開頭的網址,可能回傳 Clash YAML、經 Base64 編碼的節點清單,也可能回傳登入頁面。不能只憑連結副檔名判斷格式;沒有 .yaml 副檔名的網址,也可能提供完整設定。

實際排查時,先分辨三個層面:HTTP 是否成功、回傳文字採用哪種格式,以及目前核心是否支援其中的協定。將訂閱轉成 YAML,只能解決設定結構的相容問題,不會讓舊核心自動支援新協定,也無法修復已失效的節點憑證。

三種常見格式的結構差異

格式 辨識線索 通常包含 無法據此推斷
URI 節點連結 ss://、trojan://、vmess:// 單一節點的位址、驗證資訊與部分傳輸參數 不代表包含分流規則、DNS 設定或策略群組
Base64 節點清單 解碼後可看到逐行排列的 URI 多個節點連結組成的編碼文字 不代表解碼後就是 Clash YAML
Clash YAML proxies:、proxy-groups:、rules: 等鍵 節點、策略群組、規則,以及可選的 DNS、監聽設定 不代表所有 Clash 系列核心都支援相同欄位

URI:分享單一節點的表示方式

URI 常見結構包含「協定、驗證資訊、伺服器、連接埠、查詢參數、備註」。不同協定採用的欄位規則不盡相同。例如,常見的 vmess:// 分享內容會以 Base64 包裝 JSON;Shadowsocks 的分享方式則可能只編碼驗證資訊。不要用同一套字串拆分函式處理所有協定。

以下是用來說明欄位的虛構 Trojan 連結。example.com 是文件範例網域,密碼為示範文字,無法用來連線代理服務。查詢參數中的 sni 是 TLS 伺服器名稱,井字號後方則是節點備註。

trojan://[email protected]:443?security=tls&type=tcp&sni=example.com#Lab-Trojan

Base64:包裝清單的編碼層

常見訂閱會以換行分隔多個 URI,再將整段文字進行一次 Base64 編碼。正確流程是先解開外層編碼,再逐行交給對應協定的解析器。如果解碼後某一行仍包含 Base64,可能是該協定本身的分享格式,不要再對整份文字盲目重複解碼。

部分來源使用 URL 安全變體,以 -、_ 分別取代 +、/,也可能省略結尾的 =。這些差異屬於編碼處理,並非另一種代理協定。

YAML:完整設定與節點提供器要分開看

完整設定可以包含 proxies、proxy-groups、rules、dns 等設定區段。只含 proxies: 的檔案,常用作節點提供器檔案;它不等於已具備策略群組、規則和監聽設定的用戶端設定。將這類檔案當成完整設定匯入,可能會出現節點存在、規則卻仍直連的情況。

用戶端能否直接匯入

Clash 系列用戶端通常以 YAML 設定為主,但圖形介面的匯入能力取決於用戶端本身。Clash Verge Rev、FlClash 等用戶端的設定匯入功能,與 mihomo 核心讀取設定檔,是不同層面的功能。介面支援掃描 URI、貼上節點或轉換訂閱,不代表核心能直接載入任意 Base64 文字作為設定。

不要把「Clash 格式」視為永久不變的相容保證。傳統 Clash、Clash Premium 與 Clash Meta(現多稱為 mihomo)的功能範圍並不相同。遇到 unsupported proxy type 或未知欄位錯誤時,請記下用戶端版本、實際核心版本與協定類型,再查詢相容範圍;只更新介面程式,不一定會更換目前使用的核心。

本機轉換:先解碼,再對應節點欄位

步驟一:確認取得的是訂閱本文

將回應內容儲存為本機檔案,並用文字編輯器檢查開頭。若內容是 <!DOCTYPE html>、登入提示或 JSON 錯誤物件,應先處理請求失敗的問題。HTTP 200 只表示伺服器有回應,不保證回應內容是有效訂閱;401、403 通常與驗證或存取限制有關。

部分服務會根據請求參數或 User-Agent 回傳不同格式。瀏覽器下載到節點清單、用戶端卻取得 YAML,可能是伺服器進行了格式協商。請以服務文件為準,不要隨意加上網路搜尋到的轉換參數。

步驟二:在本機解碼清單

以下 Node.js 指令碼只使用內建模組,僅執行 Base64 解碼,不會轉換協定。將已儲存的編碼本文命名為 subscription.txt,並將指令碼另存為 decode-subscription.cjs。輸入與輸出都留在本機;輸出檔仍含有敏感憑證。

const fs = require('node:fs');
const { TextDecoder } = require('node:util');

const input = fs.readFileSync('subscription.txt', 'utf8').trim();
const compact = input.replace(/\s+/g, '');

if (!compact || !/^[A-Za-z0-9+/_-]+={0,2}$/.test(compact)) {
  throw new Error('輸入不是預期的 Base64 清單,請先檢查回應本文');
}

const normalized = compact.replace(/-/g, '+').replace(/_/g, '/');
const bare = normalized.replace(/=+$/, '');

if (bare.length % 4 === 1) {
  throw new Error('Base64 長度異常,輸入內容可能不完整');
}

const bytes = Buffer.from(bare, 'base64');
if (bytes.toString('base64').replace(/=+$/, '') !== bare) {
  throw new Error('Base64 內容無效或結尾位元異常');
}

const text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
fs.writeFileSync('nodes.txt', text, { mode: 0o600 });
console.log('已寫入 nodes.txt;請在本機檢查協定與行數');
node decode-subscription.cjs

如果原始內容已是 URI 清單或 YAML,請勿執行這個步驟。不同作業系統對檔案權限參數的處理方式不一;輸出檔應放在個人目錄,避免存入會自動同步或公開分享的資料夾。解碼後,請確認每個節點各占一行,且沒有混入流量說明等非節點文字。

步驟三:將 URI 欄位轉成 YAML

以先前的 Trojan 範例為例,可以產生以下最精簡的示範設定。此設定將本機混合代理連接埠設為 7890、模式設為 rule,並將所有未預先符合規則的連線交由 出口選擇 處理。這段設定僅用來說明結構,示範伺服器無法用於連線測試。

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info

proxies:
  - name: "Lab-Trojan"
    type: trojan
    server: example.com
    port: 443
    password: "training-only"
    sni: example.com
    skip-cert-verify: false

proxy-groups:
  - name: "出口選擇"
    type: select
    proxies:
      - "Lab-Trojan"
      - DIRECT

rules:
  - MATCH,出口選擇

server 對應連線位址,port 是整數,password 對應 URI 的驗證資訊,sni 對應 TLS 名稱。範例中的 type=tcp 並未直接照搬成 YAML 的 type: tcp,因為此處的 type 指的是代理協定,應設為 trojan。這正是不能只靠相同欄位名稱替換來完成轉換的原因。

如果實際連結使用 WebSocket、gRPC 或 Reality,還需要依目標核心的語法對應路徑、Host、服務名稱、公鑰與短 ID 等參數。只保留伺服器與密碼,可能會產生語法正確卻無法連線的節點。不清楚欄位用途時,請選擇明確支援該協定及傳輸方式的本機轉換工具,不要直接刪除報錯欄位。

如何保留規則、策略群組與節點欄位

來源欄位或設定區段 轉換檢查項目 遺漏後常見影響
節點名稱 名稱不可重複,群組引用必須完全相符 策略群組引用失敗或出現歧義
TLS 與傳輸參數 SNI、憑證驗證、路徑與協定擴充欄位 交握失敗、連線遭到關閉
proxy-groups 群組名稱、群組類型、成員與測試設定 無法選擇出口,或自動選擇行為改變
rules 原有順序、目標名稱與最後的兜底規則 原本應走代理的連線變成直連
dns、tun 由本機設定或用戶端覆寫繼續管理 解析方式與流量接管方式改變

將 URI 清單轉成 YAML 時,分流規則與策略群組通常是由轉換範本建立,而不是從節點中還原。若範本產生了 DOMAIN-SUFFIX,example.org,DIRECT,那只是範本規則;原始節點連結並未包含這條規則。遷移前後應分別比較節點參數與路由策略,不能只比較節點數量。

從完整 YAML 匯出 URI,則會遺失大量設定脈絡。策略群組的巢狀關係、rule-providers、DNS 策略與 TUN 設定,都沒有通用的單節點 URI 表示方式。再次轉換回來時,也只能依範本重新產生,無法還原原檔的註解、排序或所有功能。

使用節點提供器,減少重複轉換

如果服務提供節點型 YAML,就能將節點更新與本機規則分開管理。以下示範 mihomo 設定中的本機 proxy-providers 用法:先透過外部流程更新 ./providers/lab.yaml,再由策略群組透過 use 引用。該檔案必須是受支援的提供器格式,不能仍是經 Base64 編碼的清單。

proxy-providers:
  lab:
    type: file
    path: ./providers/lab.yaml

proxy-groups:
  - name: "出口選擇"
    type: select
    use:
      - lab

rules:
  - MATCH,出口選擇

提供器檔案採用以下節點包裝結構,內部項目的欄位與 proxies 中的節點相同。相對路徑會依核心的工作目錄或用戶端管理方式解析,不一定相對於手動開啟的 YAML 所在目錄;找不到檔案時,請查看核心記錄中的實際路徑。

proxies:
  - name: "Lab-Trojan"
    type: trojan
    server: example.com
    port: 443
    password: "training-only"
    sni: example.com
    skip-cert-verify: false

若改用 HTTP 提供器,更新網址仍須回傳目標核心可接受的節點內容。更新間隔不等於格式轉換器。也請一併檢查完整設定中的遠端規則與自動更新 URL;不希望被訂閱覆蓋的本機設定,可透過用戶端提供的覆寫或合併機制管理。實際設定位置依用戶端而異。

匯入失敗與轉換後的檢查清單

先判斷錯誤發生在哪個層面

依序重新測試

  1. 備份原始設定,並記錄原有節點數、群組名稱與規則模式。不要直接覆寫唯一可用的設定檔。
  2. 檢查轉換結果是否包含驗證資訊與傳輸參數。比對敏感欄位時請在本機進行,不要將完整截圖傳到公開討論區。
  3. 若有 mihomo 命令列環境,可執行 mihomo -t -f ./config.yaml 檢查設定;測試期間仍可能讀取外部檔案或請求遠端資源,請先檢視設定內容。
  4. 載入後手動選擇一個節點,確認目前使用規則模式,並查看連線記錄中實際命中的策略。
  5. 若使用範例連接埠 7890,可透過 curl --proxy http://127.0.0.1:7890 https://example.com/ 測試本機代理入口。測試時須換成實際可用的節點設定,而且這不代表 TUN、UDP 或所有規則都已通過驗證。
  6. 最後執行一次訂閱更新並重新啟動用戶端,確認節點仍存在、覆寫設定仍生效,且規則目標沒有指向不存在的名稱。

選擇轉換方式時,可依以下優先順序處理:先請服務提供目標 YAML,其次使用用戶端明確支援的本機匯入功能,最後才考慮可檢視的本機轉換。需要長期更新時,分開管理節點來源與本機規則,比反覆將整份設定轉成 URI 再轉回來更容易排查問題。欄位語法可參閱設定大全;用戶端與核心的選擇可參考橫向評測。