サブスクリプションURL、応答本文、ノード共有リンクを区別し、VLESS + WebSocket + TLSの例でURIとXray JSONの各フィールドを比較します。「サブスクリプションは開けるのに読み込めない」「Base64をデコードしても設定ファイルにならない」といった問題の解決や、ノード移行に役立つ内容です。適切な読み込み方法と、変換時に失われるルーティング・DNS・ローカル待ち受け設定を確認できます。
サブスクリプションURL・Base64・JSONの違い
サブスクリプションURLは通常HTTPSのURLで、クライアントがアクセスするとノード情報を取得できます。URL自体はBase64でもノード設定でもありません。確認すべきなのはサーバーが返す応答本文です。同じURLでも、リクエストのパラメーターやクライアント識別情報によって内容が異なる場合があるため、URLの末尾だけで形式を判断することはできません。
| 内容の形式 | 見分けるポイント | 利用する読み込み方法と注意点 |
|---|---|---|
| サブスクリプションURL | https://で始まり、アクセストークンを含む場合がある | サブスクリプション設定に追加すれば、以後の更新も可能 |
| Base64形式のサブスクリプション本文 | デコードすると、共有リンクが行ごとに並んでいることが多い | 通常はクライアントのサブスクリプション更新機能で解析する。実行用の完全な設定ではない |
| 単一ノードの共有リンク | vless://または一般的なvmess://で始まる | クリップボードからのノード読み込みに適している。通常、ローカルのルーティング設定は含まれない |
| コアネイティブのJSON | inboundsやoutboundsなどのフィールドを含む | 使用するコアに対応したカスタム設定の読み込み機能を使う。利用できるフィールドはコアの対応範囲による |
Base64はバイト列を表現するためのエンコードであり、暗号化ではありません。サブスクリプション本文を入手できれば、通常はサーバーアドレスや識別情報を復元できます。JSONも単なるデータ形式です。波括弧で始まるテキストでも、ノード情報、APIのエラーメッセージ、コアの完全な設定のいずれかは中身を確認しないと分かりません。「有効なJSON」だからといって、そのまま実行できるとは限りません。
Base64形式のサブスクリプションをデコード・再エンコードする
一般的なBase64形式のサブスクリプションは、複数の共有リンクを改行で連結し、UTF-8テキスト全体をエンコードしています。デコード結果に複数行のvless://やvmess://があれば、外側のサブスクリプションは復元できています。各VLESSリンクをさらにBase64デコードする必要はありません。サービスによってはリンク一覧をそのまま返すため、その場合は外側のデコードを省略してください。
- 取得したものが応答本文であり、ブラウザーのログイン画面、アクセス制限の案内、ステータスコード付きのエラーではないことを確認します。
- Base64と思われる本文から空白と改行を取り除き、URLセーフ形式の
-と_に対応したうえで、末尾のパディングを補います。 - デコードしたバイト列をUTF-8として読み込み、各行のプロトコル接頭辞を確認します。各リンク内のパラメーターはそのまま保持してください。
- 再エンコードする前に、クライアントがBase64形式のリストを必要としているか確認してください。ローカルでエンコードしても静的なテキストができるだけで、自動更新可能なHTTPSサブスクリプションが作られるわけではありません。
以下は、ローカルのブラウザー開発者ツールで使える純粋なJavaScript関数です。バイト配列を使って日本語のメモを処理するため、btoaで日本語を直接エンコードしたときのエラーを防げます。関数は渡されたテキストを変換するだけで、ネットワーク通信は行いません。信頼できる内容を入力してください。
function decodeSubscription(source) {
const compact = source.trim().replace(/\s+/g, "")
.replace(/-/g, "+").replace(/_/g, "/");
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(compact)) {
throw new Error("有効なBase64文字列ではありません");
}
const padded = compact + "=".repeat((4 - compact.length % 4) % 4);
const bytes = Uint8Array.from(atob(padded), ch => ch.charCodeAt(0));
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
}
function encodeSubscription(linkText) {
const bytes = new TextEncoder().encode(linkText);
let binary = "";
for (const byte of bytes) binary += String.fromCharCode(byte);
return btoa(binary);
}
const sampleText = "サンプルノード";
console.log(decodeSubscription(encodeSubscription(sampleText)));
デコード関数でエラーが出ても、変換を何度も重ねないでください。まず本文が途中で切れていないか、引用符やHTMLタグが含まれていないか、通常のリンク一覧ではないかを確認します。デコードに成功しても、各リンクのプロトコル、必須フィールド、通信設定はクライアントで検証する必要があります。
vless://とvmess://のフィールド構成
VLESS共有リンクは一般にURI形式です。ユーザー情報の位置にUUID、ホストとポートにサーバー情報、クエリパラメーターに通信方式とセキュリティ層が入り、シャープ記号以降にはノード名が記載されます。以下の例では、説明用ドメインとサンプルUUIDを使用しています。各フィールドの確認用であり、接続可能なサーバーではありません。
vless://[email protected]:443?encryption=none&security=tls&type=ws&host=example.net&path=%2Fws&sni=example.net#WS-TLS-demo
path=%2Fwsをデコードすると/wsになります。クエリパラメーター内のパス、メモ、特殊文字はパーセントエンコードしてください。URI全体をまとめてエンコードしたり、全体をデコードしてから手作業で分割したりしないでください。パス中の&などがパラメーターの区切りとして誤認されるおそれがあります。IPv6アドレスをホスト部分に指定する場合は、角括弧で囲む必要があります。
VLESS共有リンク
- 識別情報
- UUIDは@より前に記載
- 通信方式
- type=ws
- セキュリティ層
- security=tls
- パス
- path=%2Fws
この例ではWebSocketとTLSを使用します。Vision flowを追加で設定しないでください。
一般的なVMess共有形式
- 外側の形式
- vmess://の後にBase64データが続く
- サーバー
- JSONのadd、port
- 識別情報
- JSONのid
- 通信方式
- JSONのnet、path
これは一般的なクライアント間の共有形式であり、コアにそのまま渡して実行できるJSONではありません。
一般的なVMess共有JSONのvは共有形式のバージョンを表し、VMessプロトコルのバージョンではありません。psは通常、ノードのメモです。この形式は、コアのアウトバウンドで使われるsettings.vnextとは構造が異なります。VMessの共有形式には複数のバリエーションがあるため、移行時は両方のクライアントにある読み込み・書き出し機能を使い、すべてのvmess://が同一の構造だと決めつけないでください。
VLESSリンクからXrayネイティブJSONを作成する
共有リンクを完全なJSONに変換するには、リンクに含まれていないローカルのインバウンドとアウトバウンドのタグを追加する必要があります。以下は先ほどのVLESS例に対応したXray形式の設定で、ローカルでは127.0.0.1:10808のみで待ち受けます。実際に使用する前に、利用許可を得た実サーバーの情報に置き換えてください。例示ドメインではプロキシ接続できません。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "example.net",
"port": 443,
"users": [
{
"id": "9f2a54d1-8bc6-4d71-a903-0be458e623fd",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "example.net"
},
"wsSettings": {
"path": "/ws",
"headers": {
"Host": "example.net"
}
}
}
}
]
}
example.net:443は、アウトバウンドのaddressとportに対応します。UUIDはusers[0].idに対応します。type=wsはstreamSettings.networkに、security=tlsは通信のセキュリティ層に対応します。sniはtlsSettings.serverNameに、hostはWebSocketのHostリクエストヘッダーに対応します。用途は異なります。encryption=noneはVLESSのユーザーフィールドであり、TLSが無効という意味ではありません。TLSを使うかどうかはstreamSettings.securityで確認します。- この例に追加のルーティングルールはなく、通信には最初のアウトバウンドが使われます。OSやアプリのプロキシ設定も自動では有効になりません。
v2rayN・v2rayNGで適切な読み込み方法を選ぶ
「サブスクリプションを維持する」方法と「ノードを1つ読み込む」方法を区別してください。サブスクリプションをデコードしてリンクを1件ずつ読み込むこともできますが、通常はサブスクリプション元との紐付けや自動更新が失われます。今後もサーバー一覧を更新したい場合は、現在の共有リンクを書き出すだけでなく、元のサブスクリプションURLを保存してください。
v2rayN:サブスクリプション・クリップボード・カスタム設定を使い分ける
- サブスクリプションURL:「サブスクリプショングループ」→「サブスクリプショングループ設定」を開き、新しいグループを追加して名前とURLを入力します。保存後、「サブスクリプショングループ」から更新を実行してください。更新後はノードが追加されたか確認します。URLを単一ノードのアドレス欄に入力しないでください。
- 共有リンク:
vless://またはvmess://から始まるテキスト全体をコピーし、「サーバー」→「クリップボードから複数のURLをインポート」を選択します。読み込み後にノードを編集し、アドレス、ポート、TLS、SNI、通信パスを確認してください。 - 完全なJSON:「サーバー」→「カスタム設定サーバーを追加」などのカスタム設定用メニューを開き、ファイルに合ったコアを選択して、画面の案内に従って設定ファイルを指定します。JSON全体をサブスクリプションURLの入力欄に貼り付けないでください。
v2rayNG:サブスクリプショングループを作成してから更新する
- メイン画面のメニューから「サブスクリプショングループ設定」を開き、追加ボタンでサブスクリプション名とURLを入力します。保存してメイン画面に戻り、「サブスクリプションを更新」を実行してください。
- 共有リンクを1件読み込む場合は、テキスト全体をコピーし、メイン画面の「+」→「クリップボードからインポート」をタップします。生成された設定の種類が元のリンクと一致していることを確認してから接続してください。
- XrayネイティブJSONを読み込む場合は、「+」メニューにあるカスタム設定のインポート機能を使い、使用中のバージョンに応じてファイルまたはクリップボードを選択します。一般的なVMess共有JSONを完全なカスタム設定として読み込まないでください。
リリースによってメニュー名が多少異なる場合があります。「サブスクリプショングループ」「クリップボードのリンク」「カスタム設定」に相当する項目を探してください。v2flyNGを使う場合は、サブスクリプション内のプロトコルと通信方式が対応しているかも確認が必要です。v2rayNGで認識できるXrayノードが、別のコアを使うクライアントでも動作するとは限りません。
JSONからの書き出しと形式変換で失われる情報
「相互変換」ができても、3つの形式を常に完全な状態で往復できるわけではありません。単一ノードのリンクが主に表すのはリモート接続情報ですが、完全なJSONには複数のインバウンドやアウトバウンド、DNS、ルーティング、ポリシー、ログ設定が含まれることがあります。JSONからVLESSリンクを1件作る場合、実質的にはアウトバウンドを1つ選び、接続情報を抜き出します。その他のローカル設定は通常リンクに含められません。
| 変換の方向 | 通常保持できる情報 | 別途対応が必要な情報 |
|---|---|---|
| リンク一覧とBase64の相互変換 | 元のリンクテキストと順序 | 文字エンコーディング、改行、URLセーフ形式 |
| VLESSリンクからJSON | アドレス、識別情報、一般的な通信・セキュリティ設定 | インバウンド、アウトバウンドのタグ、ローカルルーティングを追加 |
| JSONのアウトバウンドから共有リンク | 対象クライアントが対応する単一ノードのフィールド | アウトバウンドの選択、拡張フィールドの処理、DNSとルーティングルールの別保存 |
| VMessからVLESSへの変換 | 共通するアドレス情報と通信情報を参考にできるだけ | サーバーが実際にVLESSを提供している必要があります。接頭辞を書き換えてもプロトコルは切り替わりません。 |
移行時は、まず移行元クライアントでノードを選び、共有リンクのエクスポート機能を使ってください。その後、移行先クライアントで各フィールドを確認します。複数のアウトバウンドを含むJSONしかない場合は、outbounds内のtagとprotocolを確認して対象を特定してください。直接接続用や通信遮断用のアウトバウンドをサーバーと取り違えないようにします。拡張パラメーターを使う場合は、元のJSONをバックアップし、移行先で実際に生成された設定を確認してください。
- ノードを1つだけ移行する:クライアントから共有リンクを書き出し、通信方式とセキュリティ設定を確認します。
- サブスクリプション全体を移行する:元のサブスクリプションURLを保存し、移行先クライアントでサブスクリプショングループを作成し直します。
- 設定全体を移行する:ルーティング、DNS、カスタム設定を別途バックアップし、ローカルポートの競合も確認します。
サブスクリプションのデコード・読み込みでよくある質問
ブラウザーではサブスクリプションURLを開けるのに、クライアントの更新が失敗するのはなぜですか?
返された内容が本当にノード一覧なのか、ログインページやAPIエラーのJSONではないかを確認してください。次に、トークンやクエリパラメーターを含む完全なURLが設定されているか確認します。現在のネットワークからURLに直接アクセスできない場合は、すでに利用可能なノードがあれば、プロキシ経由で更新できます。まだ読み込んでいないノードだけを、更新に必要な唯一のネットワーク経路として使わないでください。
Base64のデコードに成功したのに、読み込み可能なサーバーがないと表示されるのはなぜですか?
デコード結果の各行がどのプロトコルで始まっているか確認してください。外側のBase64をデコードできても、内容がクライアントに対応しているとは限りません。結果がJSONなら、共有用フィールドのオブジェクトか完全な設定かを見極めます。HTMLならサブスクリプションのリクエスト自体を確認してください。それ以上エンコードを続けないでください。
共有リンクは読み込めるのに接続がタイムアウトする場合、どうすればよいですか?
ノードの編集画面を開き、元の情報と照らし合わせてポート、通信パス、TLS、SNIを確認してください。この記事の例ではリモートポートは443です。ローカルの10808はSOCKSの待ち受けポートで、相互に置き換えることはできません。次にコアのログを確認し、名前解決エラー、接続タイムアウト、TLSハンドシェイクエラーを切り分けます。「読み込み成功」は、解析機能が各フィールドを受け付けたことを示すだけです。
変換後に中国本土向けの直接接続ルールが消えたのはなぜですか?
ノード共有リンクには通常、ローカルのルーティング設定一式は含まれません。移行先クライアントでルーティング設定を別途復元してください。カスタムJSONを使う場合は、routing.rulesとアウトバウンドのタグが対応しているか確認します。domainStrategyを設定する場合は、単一のルール内ではなくrouting階層に記述してください。
最終確認では、一度に変更する階層を1つに絞りましょう。まず内容の形式を正しくし、次にフィールドの不足を確認し、最後にネットワークとコアの動作をチェックします。「サブスクリプション取得の失敗」「リンク解析の失敗」「ノード接続の失敗」を切り分けられるため、エンコードツールとプロキシ設定を行き来して試行錯誤せずに済みます。