まず、受け取ったものがサブスクリプションURL、エンコードされたリンク一覧、完全なコア設定のどれなのかを確認し、適切な方法で読み込みましょう。「サブスクリプションを読み込んでも空」「JSONを認識できない」「変換後に設定が消えた」といった場合に向けて、VMess・VLESSの各項目から、ローカルでのBase64変換、クライアントへの読み込み、Xray設定へのマッピングまで解説します。共有リンクに引き継げない情報についても説明します。
1. サブスクリプションURL・Base64・JSONの違い
「V2Rayのサブスクリプション」は、特定のひとつのファイル形式を指す言葉ではありません。普段受け取るHTTPSのURLは、データを取得するための入口です。クライアントがアクセスすると、実際のレスポンスが返されます。レスポンスは、1行に1つの共有リンクが並ぶ形式の場合もあれば、リンク一覧全体をBase64でエンコードしたテキストの場合もあります。サービスによってはリクエストヘッダーに応じて返す内容が変わるため、URLの拡張子だけで形式を判断することはできません。
| 対象 | 見分け方 | 適した処理方法 |
|---|---|---|
| サブスクリプションURL | 通常はhttps://で始まり、アクセストークンを含む場合があります | サブスクリプショングループに登録して、必要に応じて更新 |
| プレーンテキストのリンク一覧 | 各行がvmess://やvless://などのプロトコルスキームで始まります | クリップボードからまとめて読み込む |
| Base64形式のサブスクリプション本文 | 長いエンコード文字列で、デコードすると共有リンクが現れます | サブスクリプションパーサーで処理するか、ローカルでデコード |
| VMessリンク内のJSON | よく使われる項目はv、add、id、netです | VMess共有リンク1件の生成・解析に使用 |
| Xrayネイティブ設定 | トップレベルにはinbounds、outbounds、routingなどがあります | 対応するコアに読み込ませるか、カスタム設定から読み込む |
どちらもJSONだからといって、相互に置き換えられるわけではありません。VMess共有オブジェクトはサーバーとその通信パラメーターを表します。一方、Xray設定は、コアがローカルポートを待ち受け、アウトバウンド接続を確立し、ルーティングを実行する方法を定義します。前者をconfig.jsonとして保存しても、後者に自動変換されるわけではありません。後者を丸ごとBase64にしても、クライアントが対応するサブスクリプションにはなりません。
2. VMess・VLESS共有リンクの項目構成
一般的なVMess共有形式は、vmess://の後にBase64文字列が続き、デコードするとJSONになります。以下はJSONの内容のみを示しています。ドメインとUUIDは説明用の架空データで、接続には使用できません。v: "2"は共有オブジェクトの形式を示す値であり、クライアントやコアのバージョンではありません。
{
"v": "2",
"ps": "VMess WSの例",
"add": "edge.example.com",
"port": "443",
"id": "00000000-0000-4000-8000-000000000001",
"aid": "0",
"scy": "auto",
"net": "ws",
"type": "none",
"host": "edge.example.com",
"path": "/ws",
"tls": "tls",
"sni": "edge.example.com"
}
addは接続先アドレス、portはリモートポート、idはユーザー識別子です。net、host、pathは、通信方式やWebSocketリクエストの設定に使われます。aid: "0"は、現在一般的なVMess AEAD設定に対応します。エラーを消すために、根拠なく別の数値へ変更しないでください。また、例のtype: "none"はTLSを無効にするスイッチではありません。
VLESS共有リンクは通常URI形式で、@より前に識別情報、その後にサーバーとポート、クエリ文字列に通信パラメーターを記述します。以下も接続できないサンプルです。リンクは1行のまま扱ってください。
vless://[email protected]:443?encryption=none&security=tls&type=tcp&sni=edge.example.com#demo-vless
VMessのサンプル項目
- アドレスとポート
addとport- 識別情報
id- 通信方式
net: "ws"- リクエストパス
path: "/ws"- TLS名
sni
これらは一般的な共有オブジェクトの項目です。コア設定にマッピングすると、キー名や階層が変わります。
VLESSのサンプルパラメーター
- ユーザー識別子
- URIの
@より前にあるUUID - プロトコルの暗号化
encryption=none- 接続のセキュリティ
security=tls- 通信方式
type=tcp- TLS名
sni=edge.example.com
encryption=noneはTLSを無効にするという意味ではありません。両者は異なる階層の設定です。
URIのパラメーター値はURLのルールに従ってエンコードします。たとえば、パス/ws?ed=2048をひとつの値として渡す場合は、path=%2Fws%3Fed%3D2048と記述します。こうすれば、含まれる疑問符が別のクエリ文字列として誤認されません。備考に日本語、空白、特殊記号を含める場合も、適切にエンコードしてください。URI全体を一括でパーセントエンコードすると、スキームや区切り文字まで壊れるため避けてください。
3. Base64形式のサブスクリプションをローカルでデコード・再エンコード
一般的な変換手順は「複数の共有リンクを改行でつなぐ → テキスト全体をBase64でエンコード」です。VMessが含まれる場合は、二重のエンコードになります。外側はリンク一覧全体、内側はVMessリンク1件分のJSONです。外側をデコードしてvmess://が現れたら、まず行ごとに分割してください。スキーム付きの文字列全体を、さらにBase64として扱う必要はありません。
以下のプレーンなJavaScriptは、ローカルの空白ページで開発者ツールのコンソールから実行できます。コードを確認してから、自分のデータだけをローカル変数に入れてください。ネットワークリクエストは発生しません。エンコード関数はUTF-8を使用するため、日本語の備考をそのままbtoa()に渡してもエラーになりません。デコード関数は標準Base64と、よく使われるURLセーフ文字の変種の両方に対応します。
function encodeSubscription(text) {
const bytes = new TextEncoder().encode(text);
let binary = "";
for (const byte of bytes) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
}
function decodeSubscription(text) {
let encoded = text.trim()
.replace(/\s+/g, "")
.replace(/-/g, "+")
.replace(/_/g, "/");
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) {
throw new Error("有効なBase64文字列ではありません");
}
encoded = encoded.replace(/=+$/, "");
if (encoded.length % 4 === 1) {
throw new Error("Base64の長さが不正です。全文をコピーしたか確認してください");
}
encoded += "=".repeat((4 - encoded.length % 4) % 4);
const bytes = Uint8Array.from(atob(encoded), char => char.charCodeAt(0));
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
}
const demoLink =
"vless://[email protected]:443"
+ "?encryption=none&security=tls&type=tcp&sni=edge.example.com#demo-vless";
const encodedDemo = encodeSubscription(demoLink);
console.log(encodedDemo);
console.log(decodeSubscription(encodedDemo));
- リンク一覧をサブスクリプション本文に変換:まず
links.join("\n")で1行ずつのテキストを作り、encodeSubscription()に渡します。各行を個別にエンコードしてから連結しないでください。 - サブスクリプション本文をリンク一覧に変換:一度デコードしてスキームを確認し、改行で分割して空行を取り除きます。結果がHTMLやエラーメッセージの場合は、取得手順に戻って原因を確認してください。
- VMessリンク1件をJSONに変換:まず
vmess://のプレフィックスを削除し、残りをデコードしてからJSON.parse()で構造を確認します。 - VMess JSONを共有リンクに変換:オブジェクトに
JSON.stringify()を実行し、得られたテキストをエンコードしてからvmess://を付けます。この手順は、該当する共有オブジェクトにのみ使えます。
4. v2rayN・v2rayNGの読み込み方法
手元にあるデータの種類に応じて読み込み方法を選びます。サブスクリプションURLはサブスクリプショングループに登録し、共有リンクはクリップボードから読み込み、コア設定全体のJSONはカスタム設定から読み込みます。デスクトップ版とAndroid版では、バージョンによってメニューの位置が変わることがあります。以下は一般的な日本語メニュー名です。表示が多少異なる場合は、該当する読み込み機能を使ってください。サブスクリプションURLをサーバーアドレス欄に入力しないよう注意してください。
v2rayN:グループを作成してからサブスクリプションを更新
-
グループを作成
メインウィンドウで「サブスクリプショングループ」→「サブスクリプショングループの設定」を開き、「追加」を選択します。備考とサブスクリプションURLを入力して保存し、サーバー一覧に戻ります。
-
データを取得
「サブスクリプショングループ」メニューから「現在のサブスクリプションを更新(プロキシを使用しない)」、またはプロキシ経由の更新項目を選びます。現在のネットワークからサブスクリプションサービスへ直接接続できる場合は、まず前者を使います。後者には、利用可能なプロキシと正しい接続経路が必要です。
-
リンクを読み込む
共有リンクのテキストしかない場合は、リンク全体をコピーし、「サーバー」→「クリップボードからURLを一括インポート」を実行します。一般的なデスクトップ画面では
Ctrl+Vでも読み込めます。この方法で追加されるのはノードのスナップショットで、リモートのサブスクリプション更新とは連携しません。 -
パラメーターを確認
読み込んだ項目の編集画面を開き、サーバーアドレス、ポート、通信プロトコル、TLS、SNIを確認します。一覧に表示されるだけでは十分ではありません。対象の項目を起動し、画面下部のコアログに設定解析エラーがないか確認してください。
v2rayNG:サブスクリプションとクリップボードを使い分ける
- サブスクリプションURL:メイン画面のメニューから「サブスクリプショングループの設定」を開き、「+」をタップして備考とURLを入力します。保存してメイン画面に戻り、メニューから「サブスクリプションを更新」を実行してください。
- 共有リンク:テキスト全体をコピーし、メイン画面の「+」→「クリップボードからインポート」をタップします。追加された項目の通信方式とセキュリティ設定を確認してから、項目を選んで接続を開始します。
- ネイティブJSON:「+」メニューにあるカスタム設定用の読み込み項目を使い、ファイルまたはクリップボードを選択します。通常の共有リンク用の読み込み機能が、任意のJSONに対応しているとは限りません。
- コアとの互換性:v2rayNGはXrayコアを、v2flyNGはV2Flyコアを使用します。あるクライアントで認識されるリンクでも、拡張パラメーターが別のコアで実行できるとは限りません。特にRealityやFlowの対応を確認してください。
サブスクリプションをデコードして手動で読み込んだ場合、サーバー側でアドレス、ポート、識別情報が変更されても、ローカルのスナップショットは自動更新されません。継続的な更新が必要なら、元のサブスクリプショングループを残してください。移行時は共有リンク一覧だけを保存するのではなく、サブスクリプションURLとローカルのカスタム設定をそれぞれバックアップします。
5. 共有リンクをXrayネイティブJSONにマッピング
クライアントがコア設定を生成するときは、単に項目名を置き換えるだけでなく、ローカルのインバウンド、アウトバウンドのタグ、ログ、ルーティングなど、実行に必要な情報も追加します。以下では、前述のVLESS TCP + TLSの例を、最小限のSOCKS設定にマッピングします。ローカル側は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": "edge.example.com",
"port": 443,
"users": [
{
"id": "00000000-0000-4000-8000-000000000001",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "edge.example.com"
}
}
}
]
}
| 共有リンクの内容 | JSONでの対応箇所 | 変換時の注意点 |
|---|---|---|
サーバーと:443 | settings.vnext[0].addressとport | JSONではポートを数値で指定 |
| UUID | settings.vnext[0].users[0].id | 内容をすべて保持し、備考で代用しない |
encryption=none | users[0].encryption | VLESSのユーザー設定にあり、TLS設定ではありません |
type=tcp | streamSettings.network | 使用中のコアが該当する通信方式名と構文に対応している必要があります |
security=tlsとsni | streamSettings.securityとtlsSettings.serverName | サーバーのIPアドレスからSNIを推測しないでください |
#demo-vless | 通常はクライアントの備考として保存 | 備考が実行設定に含まれるとは限りません |
ローカルポート10808は、この例で明示的に設定した値です。すべてのクライアントが現在このポートを使っているという意味ではありません。実行前に、ほかのプログラムが使用していないことを確認してください。ループバックアドレスだけで待ち受ければ、認証なしのSOCKSインバウンドがLANに公開されるのを防げます。リモート接続の問題を直すために、すべてのネットワークインターフェースで待ち受ける設定へ変更しないでください。
JSON全体を共有リンクにエクスポートする場合、通常取り出せるのは互換性のあるプロキシアウトバウンドひとつだけです。routing.rules、DNS、複数のインバウンドやアウトバウンドの組み合わせは、単一ノードの共有リンクでは完全に表現できません。元の設定がこれらに依存している場合は、JSONをそのまま保管してください。QRコードをひとつ出力しただけで、完全な移行が済んだと考えないようにしましょう。
- 相互変換できる可能性がある項目:サーバーアドレス、ポート、UUID、双方が対応する通信方式とTLSパラメーター。
- 追加で確認が必要な項目:クライアント固有のパラメーター、インポーターが認識しないクエリー項目、フィンガープリント、高度な通信設定。パーサーがこれらを無視しても、すぐにエラーが出るとは限りません。
- 個別にバックアップする項目:サブスクリプションの更新設定、ルーティングルール、DNSポリシー、ローカルポート、クライアントの画面設定。
6. 読み込み結果が空・デコードエラー・変換で項目が消える場合
「取得 → デコード → 解析 → 実行」の段階ごとに結果を記録して確認します。サブスクリプションの更新成功は、クライアントが何らかの処理を完了したことを示すだけです。項目が生成されたか、各項目が揃っているか、コアが起動したか、リモートに到達できるかは、それぞれ別に確認する必要があります。最初に失敗した段階から修正し、TLS、ポート、サブスクリプションURLを同時に変更して比較できなくなるのを避けてください。
サブスクリプションを開けるのに、読み込むと一覧が空なのはなぜ?
リクエストが成功したかだけでなく、実際のレスポンス内容を確認してください。Webページやアクセス権限の案内、現在のクライアントが対応していない形式が返っている場合は、サブスクリプションの提供元に対応形式を確認します。デコード結果が共有リンクなら、リンクを1件まるごとコピーしてクリップボードから読み込み、レスポンス形式の問題か、個別リンクの問題かを切り分けてください。
Base64のデコードで文字や長さが正しくないと表示されたら?
まず、サブスクリプションURLそのものをデコードしていないか、引用符・コードフェンス・省略記号が混ざっていないか確認します。本文に含まれる区切りの空白を取り除き、URLセーフ文字と末尾のパディングを確認してください。データが途中で切れている場合、イコール記号を追加しても欠落したデータは復元できません。本文全体を改めて取得してください。
JSONの構文チェックに通るのに、コアがエラーを出すのはなぜ?
構文が正しいというのは、カンマ、引用符、括弧の使い方に問題がないという意味にすぎません。項目構造がコアに対応しているとは限りません。まず、VMess共有オブジェクトではなくXrayの実行設定であることを確認します。次に、コアログに示された項目、通信方式、不足ファイルを確認し、読み込んだ設定と実際に使用するコアが合っているか調べてください。
エクスポートして再読み込みしたら、ノード名は同じなのに接続できないのはなぜ?
ノード名は接続パラメーターではありません。アドレス、ポート、UUID、通信方式、パス、Host、SNIに加え、設定されている場合はFlowやRealityのパラメーターも項目ごとに比較してください。証明書検証を無効にして確認の代わりにしないでください。エクスポーターが必須項目を落としている場合は、完全な設定のバックアップまたは元のサブスクリプションから復元します。
ローカルで編集したノードが、サブスクリプション更新後に元に戻るのはなぜ?
サブスクリプションを更新すると、通常はリモートの内容に合わせて対象の項目が更新されるため、ローカルでの変更が保持されるとは限りません。個別に管理したい項目は、サブスクリプションに属さないグループへコピーし、変更内容を記録してください。サーバー側で管理されているノードは、毎回手作業で変更せず、サブスクリプションの配信元で修正するのがおすすめです。
7. 変換後の確認とバックアップの順序
安全に移行するには、長い文字列ひとつではなく、用途の異なる3種類のデータを明確に分けて扱います。サブスクリプションURLは今後の更新に、共有リンクはノードの受け渡しに、完全な設定またはクライアントのバックアップはローカル環境の復元に使います。3種類を同時に保存してもかまいませんが、互いに代用はできません。識別情報を含むバックアップは、アクセス制限のあるローカル環境に保管してください。
- 元データを保存:変換前に元のレスポンスまたはファイルを保存し、何度も処理した結果しか残らない状態を避けます。
- 個別項目を確認:まず項目をひとつ選び、プロトコル、アドレス、ポート、通信パラメーターを比較します。UUID、Host、SNIを混同していないかも確認してください。
- 起動を確認:項目を有効にしてコアログを確認します。まず設定の解析エラーとポートの競合を解消し、その後に証明書、ハンドシェイク、リモート接続を確認してください。
- アプリの設定を確認:デスクトップアプリでは、システムプロキシまたは指定したローカルプロキシポートを正しく設定します。Androidでは、接続を開始し、システムから要求されるVPN権限を許可してください。
- 更新を確認:移行先でサブスクリプションを使う場合は、一度手動で更新し、新しい内容が想定したグループに追加されることを確認します。静的なノード一覧があるだけでは不十分です。