サブスクリプションリンクとは本質的に何か
プロキシサービス側が発行する「サブスクリプションリンク」はノード情報そのものではなく、何度でもアクセスできる HTTP(S) アドレスです。クライアントは定期的にこのアドレスへリクエストを送り、返ってきたテキストをノードリストや(存在する場合の)振り分けルールに解析します。同じサブスクリプションアドレスでも、返される内容の形式は統一されておらず、プロキシサービスが使っているパネルソフトやクライアント種別の判定ロジック、変換サービスを経由しているかどうかによって変わります。だからこそ、同じサブスクリプションリンクを Clash に貼ると使えるのに、別の単純なノード専用クライアントに貼るとエラーになる、という現象が起きます。リンクが壊れているわけではなく、クライアントが返ってきた内容の形式を認識できていないだけです。
形式の違いを理解しておくと、サブスクリプションの取り込みに失敗したときに、リンク自体が失効しているのか、プロキシサービスがそのクライアントに未対応なのか、あるいは変換サービスを一段経由する必要があるのか、原因を素早く見極められます。
よく見る3種類の形式と見分け方
Base64 ノードリスト
最も古くから使われている、汎用性の高い形式です。サブスクリプションリンクにアクセスすると Base64 でエンコードされた文字列が返され、デコードすると vmess://、ss://、ssr://、trojan:// のような単一ノードのリンクが1行1件並んでいます。この形式にはプロキシグループや振り分けルールは含まれず、クライアントはノードリストを受け取ったあと自身の既定ポリシーでグループを生成します。ほとんどの純粋なプロキシクライアント(Clash 系に限らず)がこの形式を認識できるため互換性は最も高いですが、機能はシンプルです。
Clash YAML サブスクリプション
返される内容は完全な YAML 設定ファイルで、proxies、proxy-groups、rules などのブロックを含み、手書きの config.yaml と同じ構造になっています。プロキシサービス側のバックエンドが Clash の規格に沿ってこの設定を生成し、クライアントはダウンロードしてそのまま使うだけです。振り分け戦略やプロキシグループの構成はあらかじめプロキシサービス側が設計済みで、受け取ったらすぐ使えます。判別方法は単純で、ブラウザやコマンドラインツールでリンクにアクセスし、先頭が port:、mode:、proxies: といった YAML のキーワードなら、この形式です。
sing-box JSON 設定
sing-box カーネルの普及に伴い、一部のプロキシサービスは JSON 形式のサブスクリプションも提供するようになりました。構造は sing-box の outbounds、route フィールドに対応しています。この形式は sing-box カーネル、あるいは sing-box の設定構造に対応したクライアントでしか認識できず、Clash カーネン系のクライアントにそのまま渡すことはできません。返される内容が { で始まり、"outbounds" フィールドが見える点が特徴です。
同じプロキシサービスでも、クライアントの種類によって返す形式を変えていることがよくあります。リクエストヘッダーに Clash という識別子があれば YAML を返し、なければ Base64 ノードリストを返す、といった仕組みです。そのため、ブラウザで直接サブスクリプションリンクを開いたときに見える内容と、クライアントが実際に受け取る内容が一致しない場合があります。
サブスクリプション変換サービスの仕組み
サブスクリプション変換サービス(オープンソース実装として subconverter がよく知られています)は、本質的には中間プロキシです。適切なリクエストヘッダーで元のサブスクリプションリンクへアクセスし、ノードデータを取得したあと目的の形式に合わせて設定ファイルを再生成し、クライアントに返します。全体の流れは「クライアント → 変換サービス → 元のサブスクリプションアドレス → 変換サービス → クライアント」となり、変換サービスは中間で2つのことをしています。形式の変換と、ルールの適用です。
形式の変換は、Base64 ノードリストや sing-box の JSON などをクライアントが認識できる Clash YAML に統一して「翻訳」する作業です。ルールの適用は、変換サービスに別途分流ルールテンプレート(ACL4SSR のようなルールセット)を指定できる機能で、素のノードにあらかじめ用意された振り分け戦略を組み合わせ、生成されたサブスクリプションリンクにはプロキシグループやルールがそのまま含まれるため、手書きする必要がありません。使うときは元のサブスクリプションアドレスをパラメータとして変換サービスのエンドポイントに埋め込み、返ってきた新しいリンクをクライアントに登録するだけで、通常のサブスクリプションを登録する操作と変わりません。
https://変換サービスのドメイン/sub?target=clash&url=元のサブスクリプションリンク&config=ルールテンプレートのURL
注意点として、変換サービス自体も元のサブスクリプションアドレスにアクセスできる必要があります。元のサブスクリプションが特定のネットワーク環境でしかアクセスできない場合、変換の段階でネットワーク要因により失敗することがあり、これはサブスクリプションリンクの期限切れとは無関係です。
変換サービスを自前で構築する基本的な考え方
公開されている変換サービスには、安定性とプライバシーの両面で不安が残ります。エンドポイントがレート制限されたり停止されたりする可能性があり、元のサブスクリプションアドレス(通常アカウントに紐づくトークンを含む)も第三者のサーバーを経由します。安定性やプライバシーを重視するなら、変換サービスを自前で構築するとよいでしょう。基本的な流れは次のとおりです。
実行環境を準備する
長期間オンラインにできるサーバー、またはローカルで常時起動している端末を用意し、対応する実行環境を整えます(subconverter はビルド済みバイナリを提供しているため、追加の言語ランタイムは不要です)。
変換プログラムとルールテンプレートを取得する
subconverter の本体プログラムと、長期的に使う予定の振り分けルールテンプレートファイルを取得し、同じディレクトリに置いて、プロジェクト付属の設定手順に従いリスニングポートを設定します。
サービスを起動して動作確認する
プログラムを起動したあと、自分のブラウザから
http://127.0.0.1:ポート番号/sub?target=clash&url=テスト用サブスクリプションURLにアクセスし、正常に YAML が返ってくることを確認します。自前の変換アドレスに切り替える
公開の変換サービスのドメインを自分のサーバーのアドレスに差し替えます(リバースプロキシと組み合わせて HTTPS 化することを推奨)。以降のすべてのサブスクリプションはこの自前サービス経由で変換されるため、元のサブスクリプションアドレスが第三者を経由することはなくなります。
変換サービスを自前で運用する際の主な手間は、ルールテンプレートの更新です。振り分けルールはサービスの変化に合わせて継続的に調整が必要で、長期間テンプレートを更新しないと振り分けの精度が下がってしまいます。上流のルールリポジトリと定期的に同期することを推奨します。
各形式のクライアント別対応状況
下表は、変換サービスを経由しない前提で、代表的なクライアントが3種類のサブスクリプション形式をどこまで直接サポートしているかをまとめたものです。
| クライアント / カーネル | Base64 ノードリスト | Clash YAML | sing-box JSON |
|---|---|---|---|
| Clash(オリジナルカーネル) | 変換が必要 | ネイティブ対応 | 非対応 |
| Clash Meta / mihomo カーネル | 変換が必要 | ネイティブ対応、拡張フィールドも可 | 非対応 |
| 単純なプロキシクライアント(単一ノードリンクのみ対応) | ネイティブ対応 | 非対応 | 非対応 |
| sing-box カーネルクライアント | 変換が必要 | 非対応 | ネイティブ対応 |
表からわかるように、Clash YAML は Clash カーネン系の中でしか通用せず、sing-box カーネルのクライアントに渡すとそのまま解析エラーになります。反対に sing-box の JSON サブスクリプションも Clash クライアントに直接インポートすることはできません。カーネルをまたいでノードを使う場合、サブスクリプション変換は省略できる工程ではなく、必須のステップです。
クライアントのカーネル種別を変更する場合(たとえば Clash から sing-box 系のクライアントへ移行する場合)は、まずプロキシサービスが両方の形式のサブスクリプション入口を用意しているか確認してください。同じリンクがカーネルをまたいで通用すると決めつけないようにしましょう。