base64 サブスクリプション、ネイティブ JSON 設定、vmess・vless 共有リンクの3形式を分解して比較し、「サブスクリプション → リンク一覧 → 単一ノードのフィールド → ネイティブ JSON」という完全な変換経路を示したうえで、変換中に最も失われやすいフィールドを列挙します。すでにノードに接続できており、設定を手作業で編集したり、クライアント間で移行したりする必要がある読者向けです。
3つの形式とは何か
同じノード情報でも、載せる器が違えば見た目はまったく変わります。base64 サブスクリプションは一括リスト、ネイティブ JSON は完全な設定、共有リンクは1件分のレコードです。
3者の情報量は等価ではありません。サブスクリプション内の1本のリンクは通常1つのアウトバウンド(outbound)しか記述しませんが、ネイティブ JSON はさらにインバウンド、ルーティング、DNS、ログといったクライアント側の設定も担います。ここを混同することが、以降の変換トラブルすべての出発点です。
| 項目 | base64 サブスクリプション | ネイティブ JSON | 共有リンク |
|---|---|---|---|
| 含まれる内容 | 複数行の共有リンク | アウトバウンド・インバウンド・ルーティングを含む完全な設定 | 単一ノードの接続パラメータ |
| 自動更新 | クライアントが定期的に取得 | ファイルを手動で差し替え | 非対応 |
| 主な入手元 | パネルからの一括エクスポート | サーバー側の設定ファイル、または手書き | クライアントやパネルから1件ずつコピー |
| 向いている用途 | 複数端末で1つのノードリストを共有 | 細かい振り分けとローカルポートの固定 | 一時的なインポート、クライアント間の移行 |
base64 サブスクリプションのエンコード規則
base64 サブスクリプションはエンコードが1層増えるだけです。サーバー側が複数行の共有リンクをプレーンテキストとして連結し、全体を一度 base64 にして HTTP レスポンスとして返します。クライアントは取得後にまずデコードし、1行1件のリンク一覧を得ます。
デコードに失敗した場合、クライアントは平文として処理する動作にフォールバックするため、同じ解析ロジックで base64 と平文の両方のサブスクリプションを扱えます。自分でデコードするときは、次のコマンドだけ覚えておけば十分です。
# サブスクリプションが返す原文を sub.txt に保存し、全体を一度デコード
base64 -d sub.txt > nodes.txt # GNU coreutils
base64 -D sub.txt > nodes.txt # macOS / BSD
wc -l nodes.txt # 行数は通常ノード数と一致
head -n 2 nodes.txt
デコード結果の各行の先頭がプロトコルのプレフィックスです。よく見るのは vmess:// と vless:// です。1つのサブスクリプション内で複数のプレフィックスが混在していても正常で、クライアントは行ごとに解析します。
- URL-safe 変種:一部のパネルは
+と/を-と_に置き換えます。デコード前に戻すか、URL-safe に対応したデコーダを直接使います。 - padding:末尾の
=は省略されていることが多いので、長さが4の倍数でない場合は手動で補ってからデコードします。 - 行単位か全体か:一部のサブスクリプションは各行のリンクを個別にエンコードしています。この場合は行ごとにデコードが必要で、全体を一度にデコードしても文字化けするだけです。
デコード結果の1行目が vmess:// でも vless:// でもない場合、元データはもともと平文のサブスクリプションなので、これ以上デコードする必要はありません。
共有リンクのフィールド構造
vmess と vless の違いはエンコード方式にあります。vmess リンクは「base64 で JSON を包んだもの」、vless リンクは「URI にクエリパラメータを付けたもの」です。前者をデコードするとフィールド名はすべて略号ですが、後者はアドレスバーでそのまま読めます。
vmess:// の後ろの base64 全体を一度デコードすると、次のオブジェクトが得られます。
{
"v": "2", // リンク形式のバージョン、常に 2
"ps": "香港-01", // 備考。インポート後はノード名になる
"add": "example.com", // サーバーアドレス
"port": "443", // ポート。ここでは文字列
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
"aid": "0", // alterId。VMess のみ
"scy": "auto", // 暗号化方式
"net": "ws", // トランスポート層
"type": "none", // 偽装タイプ
"host": "example.com", // WS の Host ヘッダー
"path": "/ws", // WS のパス
"tls": "tls" // TLS を有効にするか
}
vless リンクには内側の base64 がなく、すべてのパラメータが ? 以降のクエリ文字列に書かれ、# の後ろが備考です。パラメータ名は vmess の略号より直感的ですが、URI の規則に従って URL エンコードが必要です。
vless://[email protected]:443?encryption=none&security=reality&sni=www.example.com&fp=chrome&pbk=UuMBgl8KtNqHqY7p&sid=0123abcd&flow=xtls-rprx-vision&type=tcp#香港-01
2つのリンクが表しているのは同じ内容で、違うのはフィールド名と配置だけです。以下の4枚のカードで、よく使うフィールド、ネイティブ JSON のトップレベル構造、ローカルポートの取り決めを並べて対照します。
vmess リンクのフィールド
- add / port
- アドレスとポート。port は文字列
- id / aid
- UUID と alterId
- scy
- 暗号化方式。通常は auto か none
- net / type
- トランスポート層と偽装タイプ
- path / host
- WS のパスと Host ヘッダー
全体が base64(JSON)なので、一度デコードすれば読めます。
vless リンクのパラメータ
- encryption
- 常に none。省略不可
- security
- none / tls / reality
- sni
- TLS 証明書のドメイン
- flow
- Reality ノードでは xtls-rprx-vision を指定
- pbk / sid
- Reality の公開鍵とショート ID
パラメータはクエリ文字列に書く。URL エンコードに注意。
ネイティブ JSON のトップレベル
- inbounds
- ローカル待ち受け。例:SOCKS 10808
- outbounds
- アウトバウンドノード。tag と streamSettings を含む
- routing
- 振り分けルール。outboundTag でアウトバウンドを指定
- dns
- 解決方式と上流サーバー
- log
- ログレベル。調査時は debug
フィールド名は大文字小文字を区別し、port は数値でなければなりません。
ローカルポートの取り決め
- SOCKS
- 10808
- HTTP
- 10809
- ログレベル
- warning / debug
- アウトバウンドの tag
- proxy、direct、block の3つがよく使われる名前
ポートと tag はローカル設定で決まるもので、サブスクリプションとは無関係です。
3つの形式を相互変換する方法
変換経路は4ステップで固定です。サブスクリプションからリンク一覧をデコードし、リンクをフィールドに戻し、フィールドをネイティブ JSON に組み立てます。逆にたどればエクスポートになります。
サブスクリプションの原文を取り出す
ブラウザでサブスクリプションのURLを開き、返ってきた内容を丸ごと sub.txt として保存します。返ってくるのは base64 の塊の場合もあれば、平文のリンク一覧の場合もあります。
リンク一覧をデコードする
base64 -d sub.txt > nodes.txtを実行すると、1行1件の共有リンクが得られます。プロトコルのプレフィックスは行頭に、備考は行末の#の後にあります。単一ノードを復元する
vmess は
vmess://の後ろをもう一度 base64 デコードして JSON を得ます。vless は?以降のクエリパラメータをそのまま読めばよく、追加のデコードは不要です。ネイティブ JSON に組み立てる
フィールドを
outboundsのvnextとstreamSettingsに埋め込みます。portは数値に変更し、tagは自分で命名し、addressにはプロトコルのプレフィックスを付けません。
4ステップ目で組み立てたアウトバウンドはおおよそ次のようになります。フィールドは上記の vless リンクと1対1で対応しています。
{
"outbounds": [{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "example.com",
"port": 443,
"users": [{
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
"encryption": "none",
"flow": "xtls-rprx-vision"
}]
}]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "www.example.com",
"publicKey": "UuMBgl8KtNqHqY7p",
"shortId": "0123abcd",
"fingerprint": "chrome"
}
}
}] // アウトバウンドの配列
}
逆変換も同じ理屈です。ネイティブ JSON の settings.vnext[0] と streamSettings はリンクパラメータを展開した形なので、address、port、id を取り出し、プロトコルの規則に従って URI にエンコードし直せば済みます。VMess の場合は alterId を aid に書き戻す必要もあります。
クライアント側にはもっと手軽な経路も2つあります。v2rayN は「カスタム設定」タイプのサーバーに対応しており、完全な JSON を設定欄に貼り付けるとカーネルが直接読み込み、クライアントがアウトバウンドを組み立てる必要がなくなります。逆に、サブスクリプション一覧から単一ノードの共有リンクをコピーし、別の端末の v2rayNG にそのまま貼り付けて「⋮」→「クリップボードから設定をインポート」で取り込むこともできます。
変換時に最も失われやすいフィールド
フィールドの欠落はほぼすべて手作業の受け渡しで起きます。コピー&ペースト時の切れ、文字列と数値の混用、略号の1文字見落としなどです。以下の箇所を順に照合すれば、「インポートは成功したのに接続できない」ケースの大半をカバーできます。
flow=xtls-rprx-vision:Reality ノードでは必須です。抜けるとクライアントは通常の VLESS として処理し、サーバー側のハンドシェイクがそのまま失敗します。pbkとsid:Reality の公開鍵とショート ID はペアで機能するので、片方だけ写しても意味がありません。encryption=none:VLESS の固定値で、書き漏らすと一部のクライアントはこのリンクのインポートを拒否します。aid:VMess の alterId で、リンク内では文字列、ネイティブ JSON では数値です。古いサーバーでは 2 や 64 がよく使われ、未記入で 0 として扱われるとハンドシェイクに失敗します。portの型:リンクの JSON では"443"、ネイティブ JSON では443でなければならず、引用符が付いているとカーネルに無効な設定と判定されます。serviceName:type=grpcのときはpathの代わりにこれを使います。両者を取り違えるとリクエストパスが一致しません。hostとsni:前者は WS の Host ヘッダー、後者は TLS の SNI です。CDN 環境では両者が異なるのは正常ですが、取り違えると 403 が返ります。outboundTag:routing.rules内の値はoutboundsのtagと一字一句一致している必要があり、大文字小文字も区別されます。
注意
ネイティブ JSON を手で編集するときは、保存前にエディタで JSON の構文チェックを1回かけてください。末尾のカンマと引用符の欠落が最も多い2大エラーです。調査段階ではまず log.loglevel を debug に設定し、カーネルにエラーのあるフィールドをログへ出力させ、特定できたら warning に戻します。
どの場面でどれを使うか
3つの形式に優劣はなく、役割分担があるだけです。判断基準は2つだけです。ノード一覧が変わるかどうか、そしてローカルに振り分けルールが必要かどうか。
選定基準:ノードが変わるか、ローカル振り分けが必要か
base64 サブスクリプション
- 1つのアドレスで全ノードを管理
- 端末を変えても入力は1回だけ、リストは自動同期
- ノードの追加・削除はサーバー側が決め、ローカルは変更不要
- 複数端末でノードが調整される場面向け
ネイティブ JSON
- routing の振り分けルールと DNS ポリシーを書ける
- ローカルの SOCKS 10808、HTTP 10809 ポートが固定
- ノードの変更時はファイルを手動で差し替え
- 単一端末で細かい制御が必要な場面向け
両者は併用できます。サブスクリプションがノード一覧を担い、ネイティブ JSON の routing がどの通信をプロキシ経由にするかを決めます。
共有リンクはその中間に位置します。サブスクリプションより一時的なインポートに向き、ネイティブ JSON よりクライアント間のコピーに向いています。同じリンクを v2rayN と v2rayNG に貼り付けても、得られるアウトバウンドのパラメータは同じで、違いはローカルポートと振り分けルールをクライアント自身の設定に持たせる点だけです。
実際によく使われる組み合わせは、サーバー側で1つのサブスクリプションURLを維持し、クライアント側でローカルのルーティングルールを追加する形です。ノードはサブスクリプションに追従して更新され、振り分けロジックはローカルに残るので、双方が干渉しません。
よくある質問
サブスクリプションのURLをブラウザで開くと文字化けする?
それは base64 の原文であり、エラーではありません。丸ごとコピーして一度デコードするか、そのままアドレスをクライアントのサブスクリプション設定に入力して更新してください。
vmess リンクをインポートするとノード名が「?」になる?
ps フィールドは UTF-8 の中国語なので、デコードツールが GBK として処理すると文字化けします。UTF-8 でデコードし直してからインポートしてください。
vless リンクをインポートすると flow が不足していると表示される?
Reality ノードでは flow に xtls-rprx-vision を指定し、あわせて pbk、sid、fp の3つのパラメータを補ってください。
自分で書いた JSON が無効な設定と判定される?
まず末尾のカンマと引用符を確認し、次に port を文字列から数値に直し、最後に routing.rules[].outboundTag とアウトバウンドの tag が一致しているかを照合してください。
3つの形式の変換関係はそれほど複雑ではありません。サブスクリプションを1層デコードするとリンクが得られ、vmess リンクをもう1層デコードするとフィールドが得られ、フィールドを展開すればネイティブ JSON になります。本当に時間がかかるのはデコードではなく、フィールドを1つも落とさず正しい位置に移す作業です。
v2rayN / v2rayNG をダウンロード
Windows、macOS、Linux のデスクトップ版と Android 版の入口はダウンロードページにあります。サブスクリプションのインポートと振り分け設定はチュートリアルをご覧ください。