サブスクリプションURLは設定を取得するための入口、Base64はエンコード方式、共有リンクは個々の接続情報を表し、ネイティブJSONにはコア全体の実行設定が含まれる場合があります。サブスクリプションの移行やインポートエラーの解消、カスタム設定の保持が必要な方に向けて、入力形式の見分け方、項目ごとの変換方法、接続・トランスポート・ルーティングの確認手順を解説します。
1. URL・エンコード・設定データの違いを理解する
「V2Rayのサブスクリプション形式」に統一されたファイル仕様があるわけではありません。一般的なサブスクリプションAPIはHTTPSでテキストを返します。内容は複数の共有リンク、またはそれらをまとめてBase64エンコードしたデータの場合があります。サブスクリプションURL自体がノード設定なのではなく、クライアントがURLにアクセスしてレスポンスを解析します。
ファイル名だけでは内容の形式を判断できません。.jsonで終わるURLがエラーページを返すこともあれば、拡張子のないURLが正しいJSONを返すこともあります。まずレスポンスの内容を確認し、「サブスクリプション更新」「クリップボードからインポート」「カスタム設定のインポート」のどれを使うか判断してください。
サービス提供元のクライアント対応サブスクリプション
おすすめノードを継続的に更新したい場合は、利用するクライアントへの対応が明記されたサブスクリプションを優先しましょう。一般的には共有リンク一覧をBase64でエンコードした形式ですが、サービス提供元の説明と実際のレスポンスを確認してください。
用途:定期的な更新、複数端末への個別インポート、ノードアドレスの変更
共有リンク(単数または複数)
vmess://やvless://などのリンクを使えば、接続情報を個別に移行できます。複数のリンクは通常、1行ずつ並びます。リンク自体に自動更新の仕組みはありません。
用途:一時的なテスト、単一ノードの移行、接続項目の確認
ネイティブJSON設定
完全な設定には、インバウンド、アウトバウンド、DNS、ルーティングを記述できます。JSONは構文上の入れ物にすぎません。各項目が対象コアとそのバージョンに対応している必要があり、構文解析できるだけで動作するとは限りません。
用途:固定ルーティング、カスタムDNS、実行環境全体の移行
2. Base64形式のサブスクリプションを見分けてデコードする
従来のリンク一覧形式では、通常、共有リンクを1行ずつ並べたテキストをUTF-8のバイト列に変換し、全体をBase64エンコードします。デコード後に現れるのは判別可能なプロトコル接頭辞であり、コア全体の設定がそのまま出てくるわけではありません。
以下のJavaScriptは、ローカルでの文字列処理を示す例です。標準Base64に加え、一般的なURLセーフ文字も扱います。取り除くのはエンコード文字列中の空白であり、共有リンク内の文字ではありません。長さの異常や不正なバイトが見つかった場合は確認を中断してください。修復目的で何度もデコードするのは避けましょう。
function decodeSubscription(encoded) {
const text = encoded.trim()
.replace(/\s/g, "")
.replace(/-/g, "+")
.replace(/_/g, "/");
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(text) ||
text.length % 4 === 1) {
throw new Error("Base64テキストの形式が正しくありません");
}
const padded = text + "=".repeat((4 - text.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);
}
- デコード後に
vmess://やvless://が現れた場合は、共有リンクを1行ずつ確認してください。 - 元のデータが
{または[で始まる場合は、まずJSONかどうかを確認してください。先にBase64デコードを試さないでください。 - HTMLタグ、ログイン案内、APIエラーが表示される場合は、サブスクリプションの利用権限や有効期限、ネットワークリクエストの結果を確認してください。
- 外側のデコード後も、
vmess://リンクのペイロードがBase64のままの場合があります。これはリンク自体に含まれるエンコードであり、外側のサブスクリプションのデコード失敗ではありません。
3. 共有リンクをJSONに変換する:項目の意味に沿って対応付ける
リンク変換は接頭辞を置き換えるだけではありません。一般的なVMess共有リンクは、JSONをエンコードした文字列をvmess://の後ろに付けます。VLESS共有リンクはURI形式が多く、ユーザー識別情報、ホスト、ポート、クエリパラメーター、備考で構成されます。拡張パラメーターへの対応状況はクライアントによって異なります。
vless://[email protected]:443?encryption=none&security=tls&type=tcp&sni=example.com#format-demo
これは各項目を説明するための架空の接続情報です。example.comはドキュメント用のドメインで、実際の接続には使えません。encryption=noneはVLESSのユーザー層の設定であり、TLSを無効にする指定ではありません。トランスポートのセキュリティはsecurity=tlsで表します。
| リンクの情報 | 一般的なJSONでの対応項目 | 確認ポイント |
|---|---|---|
| ホストとポート | settings.vnext[].address、port | ポートは数値で指定し、ドメイン名を備考欄に誤入力しない |
| ユーザー識別情報 | settings.vnext[].users[].id | UUID全体を保持し、URIの区切り文字を含めない |
encryption=none | users[].encryption | これはVLESSの項目です。VMessには適用できません |
security=tls | streamSettings.security | VMessユーザーの暗号化設定と混同しない |
sni=example.com | tlsSettings.serverName | サーバーが指定するTLS名を保持する |
type=tcp | streamSettings.network | トランスポート名と利用可能な別名は、コアのバージョンを確認する |
以下は、これらの項目に対応するXrayコア向けの構造例です。10808はループバックアドレスにのみバインドし、443はリモートポートとして使います。両者を取り違えないでください。ここでは従来のtcp表記を使っています。トランスポート名や互換エイリアスは、各コアのバージョンに対応するドキュメントを確認してください。
{
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "example.com",
"port": 443,
"users": [
{
"id": "7c9c1f0b-4bd8-4b44-8eb2-3eb2ac702783",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "example.com"
}
}
}
]
}
4. JSONを共有リンクに変換する:失われる設定に注意
完全な設定から共有リンクを書き出す際、変換ツールは通常、プロキシのアウトバウンドを1つだけ抽出します。1つのJSONに複数のoutboundsが含まれる場合があり、その中には直接接続やブロック用のアウトバウンドもあります。変換前に対象プロキシのtagを選択してください。配列の先頭を無条件にノードとして扱ってはいけません。
変換方針:接続情報と完全な設定を分けて移行する
接続情報だけを移行
- 対象アウトバウンドから、プロトコル、サーバー、ポート、認証情報を取り出す。
- TLS名、トランスポートのパス、サーバーが要求するフロー制御を保持する。
- 共有リンクを作成し、移行先のクライアントでローカルプロキシとルーティングを再設定する。
設定全体の動作を保持
- ネイティブJSONを保持し、移行先のコアで読み込めることを確認する。
- インバウンドのポート、DNS、ルーティングルール、外部データファイルを確認する。
- クライアントのカスタム設定から読み込み、設定が書き換えられないか確認する。
共有リンクは接続情報の受け渡しに適しています。実行時の動作全体を保つには、設定ファイル、依存リソース、コアの機能も合わせて移行する必要があります。
routing.rules、dns、ローカルの待ち受けアドレス、アプリごとの設定は、通常のノード共有リンクには含まれません。JSONをリンクに変換し、そのリンクからJSONに戻しても、元のファイルと同等の設定になるとは限りません。接続できても、ルーティング結果が一致するとは限りません。
- 元のJSONのコピーを保存し、移行対象のアウトバウンドの
tagを記録する。 - ノード名だけでなく、サーバーアドレス、ポート、認証情報、トランスポート、TLS、フロー制御を項目ごとに比較する。
- 備考とクエリパラメーターはURIの規則に沿ってエンコードします。特にパス内の
?、&、#がリンクの区切り文字として誤認されないよう注意してください。 - 変換ツールが未対応の項目を示した場合は、自動移行を中断して手動で確認してください。項目を黙って削除したまま使わないでください。
5. 共有リンクをサブスクリプションにまとめる:更新機能は自動では引き継がれない
複数の共有リンクを1行ずつ並べたテキストにし、全体をBase64エンコードすると、従来形式のリンク一覧サブスクリプションのデータを作成できます。ただし、これは一時点のスナップショットです。クライアントが定期的に取得できるようにするには、自分または信頼できるサービス提供元が管理し、継続してアクセス可能なサブスクリプションURLが別途必要です。
- 入力を整理:1行に完全なリンクを1つだけ残し、空行を削除します。Webページのタイトルや説明文は一緒にエンコードしないでください。
- エンコード:UTF-8に統一し、日本語の備考が正しくエンコードされているか確認します。1バイト文字しか扱えない方法で日本語文字列を処理しないでください。
- 出力を確認:エンコード結果を再度デコードし、リンク数、行の順序、パラメーターが変わっていないことを確認します。
- 更新方法:ノードアドレスや認証情報が変更されても、静的なスナップショットは元のサブスクリプションに連動しません。内容を再生成して公開する必要があります。
ネイティブJSONも、全体を一度Base64エンコードするだけで、どのクライアントでも使えるサブスクリプションになるわけではありません。エンコードしても内部のデータ構造は変わりません。共有リンク一覧しか受け付けないインポート先では、デコード後の完全なJSONを読み込めず、失敗する場合があります。
6. v2rayN・v2rayNGで変換結果を確認する
既存の手動設定がサブスクリプション更新で上書きされないよう、まず専用のテストグループにインポートしてください。以下は一般的なメニュー名です。バージョンによって配置や表記が異なる場合があるため、実際の操作では現在の画面に従ってください。完全なJSONをサブスクリプションURL欄に入力しないでください。
- v2rayNのサブスクリプション:「サブスクリプショングループ」→「サブスクリプショングループ設定」を開き、テスト用グループを追加して信頼できるサブスクリプションURLを入力し、そのグループの更新コマンドを実行します。
- v2rayNの共有リンク:リンクをコピーし、メイン画面で「クリップボードからURLを一括インポート」を実行します。追加された項目がどのグループに入ったか確認してください。
- v2rayNGの共有リンク:右上の「+」→「クリップボードからインポート」をタップします。追加された項目を編集し、サーバー、ポート、トランスポートの設定を確認してください。
- v2rayNGのサブスクリプション:メニューの「サブスクリプショングループ設定」でURLを追加し、戻ってから「サブスクリプションを更新」を実行します。テスト用グループが更新されたことを確認してください。
- ネイティブJSON:現在のバージョンに用意されているカスタム設定ファイルのインポート機能を使います。まずログで設定の解析結果を確認してから接続を開始してください。
起動後は3段階で確認します。1つ目はコアが設定を解析し、ローカルポートを待ち受けているか。2つ目はリモートとのハンドシェイクが完了するか。3つ目はアプリの通信がプロキシを通り、想定したルーティングルールに一致するかです。ノードが一覧に表示されても、データが解析され保存されたことしか確認できず、後半2つの確認にはなりません。
デコードしてリンクが見えるのに、インポートに失敗するのはなぜ?
複数のリンクが1行に連結されていないか、引用符やカンマまで一緒にコピーしていないか確認してください。まず1つだけインポートし、プロトコルとトランスポートが対象コアに対応しているか確認します。1つのリンクで失敗する場合、一覧全体を再エンコードしても解決しません。
インポートは成功したのに、起動時にポート使用中と表示された場合は?
カスタムJSONのinbounds[].portを確認してください。例の10808が別のプロセスに使われている場合は、そのプロセスを停止するか別のポートに変更し、アプリ側のプロキシアドレスも合わせて更新します。リモートポートの443を変更する必要はありません。
変換後にTLSハンドシェイクが失敗した場合、証明書検証を無効にすればよい?
まずサーバーアドレス、serverName、システム時刻、トランスポート設定を比較してください。変換時にSNIが欠落したり、TLSの種類が誤って変更されたりしていないか確認します。不一致を隠すために証明書検証を無効にするのではなく、設定項目を修正してください。
ノードには接続できるのに、日本国内・国外のルーティングが変わったのはなぜ?
共有リンクには通常、元のroutingやdnsの設定が含まれません。移行先のクライアントでルーティング設定を選び直し、ルールの順序とデータファイルを確認してください。元の設定を再現するには、ネイティブJSON全体を移行し、コアとの互換性も確認する必要があります。
サブスクリプションを更新したら、手動で修正した項目が元に戻ってしまうのはなぜ?
サブスクリプションに紐づく項目は、更新時に再作成される場合があります。保持したい設定は専用の手動グループにコピーし、元のサブスクリプション項目についてはサービス提供元に確認してください。サブスクリプションから生成された項目を、ローカルでの変更を長期保存する場所として使わないでください。
最終的に保存しておくべきものは3つです。元の入力データの安全なコピー、変換時に使った項目の対応関係、移行先クライアントでの確認結果です。後で問題が起きても、サブスクリプションのレスポンス変更、変換時の項目欠落、ローカルのルーティングやポート設定の変更を切り分けられます。