JSON構造と設定の範囲
まず編集対象のレイヤーを確認
V2Ray環境で「設定ファイル」と呼ばれるものは、単一のファイルとは限りません。v2rayNはサーバー情報、サブスクリプショングループ、ルール、各種設定を保存し、選択したコアに応じて実行用設定を生成します。v2rayNGやv2flyNGにも、アプリ独自のデータとコアの実行用設定という2つのレイヤーがあります。画面でポートを変更しても、サブスクリプションの元データが変わるわけではありません。一時生成されたJSONを編集しても、次回起動時に変更が残るとは限りません。項目を確認する前に、ファイルが手動管理のものか、クライアントからエクスポートしたものか、起動時の一時ディレクトリに生成されたものかを確認し、生成元のクライアントとコアも記録しておきましょう。
このページでは、V2Ray形式のJSONとXrayでよく使われる項目を中心に説明します。V2FlyとXrayには共通する設定の基盤がありますが、対応プロトコル、トランスポート名、拡張項目には違いがあります。sing-boxは別の設定構造を使うため、v2rayNでコアを切り替えられるからといって、ここで紹介するJSONをそのまま渡せるわけではありません。「未知の項目」と表示されたら、まず実際に起動しているコアを確認し、そのコアが受け付ける項目を調べてください。クライアント名だけで判断しないようにしましょう。クライアントは各プラットフォームのダウンロードページから選べます。
オブジェクト、配列、参照関係
JSONの最上位はオブジェクトで、項目名と文字列は半角の二重引用符で囲みます。配列は角括弧で、複数のインバウンド、アウトバウンド、ルールなどを格納するのに使います。オブジェクトは波括弧で、関連する項目をまとめます。ポート番号は通常数値、真偽値は小文字の true または false で記述します。標準JSONではコメント、末尾の余分なカンマ、シングルクォートは使えません。コメント付きの拡張構文に対応するツールであっても、共有や移行の前には標準JSONとして書き出してください。別のパーサーで読み込めない事態を防げます。
以下は、JSONの解析、ローカル待ち受け、ログ出力を確認するための、単独で起動できるローカル直結設定の基本例です。プロキシサーバーは含みません。ループバックアドレスのみで待ち受け、システムプロキシの設定やデスクトップメニューの作成は行いません。設定の読み込みに成功すると、ローカルのSOCKS入口からリクエストがdirectアウトバウンドに渡されます。この状態で特定のアドレスにアクセスできても、直結経路が使えることを示すだけで、サブスクリプション内のプロキシサーバーが使える証明にはなりません。クライアントに設定を渡す前に、カスタム設定の入口に対応しているか、ローカルポートが書き換えられないかも確認してください。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
}
]
}
構文の正しさから設定の意味の正しさへ
JSONの解析に成功しても、確認できたのは構文だけです。routingに存在しないoutboundTagを書いたり、ルールが参照するインバウンドのタグを間違えたりすると、エラーになったり、想定どおりに振り分けられなかったりします。タグは同じ実行設定内で使う参照名で、大文字と小文字を区別します。画面上のメモやサーバーのドメイン名ではありません。まずインバウンドとアウトバウンドのtagを一覧にし、ルールからの参照を照合しましょう。配列の順番にも意味があります。通常のルーティングルールは上から順に照合され、先頭のアウトバウンドが未一致リクエストの既定の出口になることも多いため、安易にアルファベット順へ並べ替えないでください。
| 項目 | 役割 | よくある誤解 |
|---|---|---|
inbounds | ローカル待ち受けと受信プロトコル | サーバーアドレスをlistenに設定する |
outbounds | 接続先またはプロキシサーバー | 既定の出口の順序を見落とす |
routing | リクエストを照合して出口を選択 | 存在しないtagを参照する |
dns | 内蔵DNSの設定 | システムDNSを自動で引き継ぐと思い込む |
policy | ユーザー単位の接続ポリシーと統計の設定 | 時間の設定を帯域幅制限と取り違える |
以降の部分設定例を使う際は、複数の完全なJSONオブジェクトを同じファイルに続けて貼るのではなく、該当するトップレベルの位置に統合してください。トップレベルオブジェクト内でroutingやdnsを重複して定義しないようにしましょう。重複キーの扱いはパーサーによって異なり、画面表示と実際の動作が食い違うおそれがあります。統合のたびに変更する機能は1つに絞り、変更前のコピーを残し、起動ログで読み込み結果を確認してください。サブスクリプションのインポートと通常の接続だけが目的なら、まずクライアントに設定生成を任せましょう。画面上で実現できない要件がある場合に限り、JSONを手動で管理してください。
inbounds:インバウンドとローカル待ち受け
listen、port、protocolの役割
インバウンドは、アプリのトラフィックがコアに入る入口です。listenは待ち受けるローカルアドレス、portはポート番号、protocolは受け付けるプロトコルを指定します。デスクトップのローカルプロキシは通常127.0.0.1で待ち受け、同じ端末上のプロセスだけが接続できます。0.0.0.0にすると通常はすべてのIPv4インターフェースで待ち受けるため、LAN内に入口が公開されるおそれがあります。「任意のサーバーを使う」という意味ではなく、外部から必ずアクセスできるわけでもありません。実際の可否はファイアウォールやネットワーク環境にも左右されます。共有する明確な理由がなければ、待ち受け範囲を広げないでください。
SOCKSとHTTPは異なるローカルプロキシプロトコルなので、アプリ側の設定も入口に合わせる必要があります。ブラウザーのHTTPプロキシに、SOCKSだけを受け付けるポートを指定してはいけません。コマンドラインツールでSOCKSを使う場合は、プロキシ経由の名前解決に対応しているかも確認しましょう。v2rayNの画面にローカルの混合ポートがあっても、実装を担うのはクライアントと選択中のコアです。任意のV2Ray形式の設定でmixedというprotocolを指定できるとは限りません。利用可否は現在のコアの設定仕様で確認してください。
SOCKSとHTTPをそれぞれ定義する
以下は2つのインバウンドオブジェクトからなる部分設定です。トップレベルのinbounds配列に追加するか、既存項目と置き換えてください。同じポートを使用中のインバウンドとは併用できません。どちらもループバックアドレスにバインドし、SOCKSではUDPを有効にし、HTTPプロキシ対応アプリ向けのHTTP入口を用意しています。udpを有効にしても、そのインバウンドが該当リクエストを受け付けるだけで、後段のアウトバウンドやサーバー、ネットワーク経路を通じてUDPが転送できるとは限りません。アプリからプロキシリクエストが届いていない場合、コアのルーティングを変えても自動的にこれらのポートへ流れることはありません。
{
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"tag": "local-http",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
]
}
ローカルポートとサーバー側のポートは別物です。前者はローカルアプリが接続するポート、後者はoutbounds内のサーバー設定にあるポートで、同じ番号にする必要は通常ありません。ポートが使用中の場合は、クライアントが重複起動していないかを確認し、バックグラウンドにコアのプロセスが残っていないかを調べてから、空いているポートに変更してください。インバウンドのポートを変えたら、アプリのプロキシ設定とクライアントのシステムプロキシ設定も合わせて変更する必要があります。JSONだけを変更してシステムプロキシを更新しないと、コアは正常に起動しているのにブラウザーは古いポートへ接続し続けることがあります。
sniffingの用途と限界
スニッフィングは、対応するトラフィックの特徴からドメイン名の取得を試み、ドメインベースのルーティングに利用する機能です。通信を復号する機能ではなく、すべての接続からドメイン名を特定できるわけでもありません。Xrayの場合、以下のオブジェクトはインバウンドオブジェクト内に配置できます。routeOnlyはスニッフィング結果をルーティング判定だけに使う指定です。この項目に対応しているか、どのプロトコルを識別できるかは、使用するコアの仕様を確認してください。アプリがドメイン名を指定してSOCKS入口に接続し、ルーティングに必要な情報がすでにあるなら、「設定を完全にする」ためだけにすべてのスニッフィング項目を有効にする必要は通常ありません。
{
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"],
"routeOnly": true
}
}
AndroidのVPNモードでは、システムが提供する仮想ネットワークインターフェースでトラフィックを受け取るため、通常はアプリごとにSOCKSポートを設定する必要はありません。v2rayNGの「アプリごとのプロキシ」では、どのアプリをこの経路に通すか、または除外するかを指定します。これはインバウンドJSONの待ち受けアドレスとは別のレイヤーの設定です。デスクトップで別のトラフィック制御機能を有効にした場合も、システム層とコア層を区別してください。まずトラフィックがコアに届いているかを確認し、その後でルールを調べます。「VPN接続済み」と表示されても、すべてのアプリが同じ入口を使っているとは限りません。
LAN内の端末からアクセスできるようにする場合は、認証、接続元、ファイアウォールの範囲も検討してください。認証なしのHTTPやSOCKS入口を、信頼できないネットワークに直接公開するのは避けましょう。接続する端末にはプロキシアドレスを明示し、ホスト側ではアクセス可能なネットワーク範囲を制限してください。listenだけを変更してネットワーク境界を考慮しないと、想定以上にアクセス可能な範囲が広がります。トラブル対処では、まずローカルのループバック接続を確認し、その後LAN接続を有効にして、最後にファイアウォールを確認しましょう。一度に複数のアドレスやルールを変更するより、段階的に範囲を広げるほうが原因を特定しやすくなります。
outbounds:アウトバウンドとプロトコル設定
既定の出口と明示的なタグ
アウトバウンドは、リクエストをコアがどのように処理するかを決めます。freedomは通常、直接接続に使われます。blackholeは通信を遮断し、VMessなどのプロトコルは対応するサーバー経由で転送します。tagはルーティングで出口を指定するための識別子であり、それだけで利用可能なサーバーになるわけではありません。proxyという名前のタグでも、どのプロトコルを使うかはさまざまです。出口の種類を判断するにはprotocolとsettingsの両方を確認してください。ルールに一致しないリクエストは通常、outboundsの先頭にあるアウトバウンドへ送られます。directを先頭に置けば、既定の経路は直接接続になります。
以下の部分設定では、直接接続用と遮断用の2つの出口を定義します。ルーティング参照の練習に使えますが、リモートプロキシ機能はありません。blackholeの空のsettingsでは、遮断するリクエストがプロトコルの既定動作に従って処理されます。特定の応答を返したい場合は、現在のコアにおけるプロトコル設定を確認してください。任意のHTTPテキストを汎用の応答として使えるわけではありません。複数のアウトバウンドには、direct、block、proxyのように明確で重複しないタグを付けましょう。番号だけのタグを避けると、ルーティングの確認時に出口の意味がすぐに分かります。数文字短くすることより、分かりやすさが重要です。
{
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
]
}
VMessでサーバー項目を確認する
VMessアウトバウンドでは、サーバーアドレス、リモートポート、ユーザー情報をsettings内のvnext配列に記述します。addressにはサーバーのドメイン名またはアドレス、portには実際の待ち受けポートを指定し、usersで認証ユーザーを定義します。以下は項目の構造を示す例です。example.netは説明用ドメインで、すべてゼロのUUIDも教材用の値です。実際のサービスには接続できません。実際に使う場合は、既存のサーバー設定または有効なサブスクリプションから対応する値を取得してください。ここに利用可能なノードはなく、UUIDをランダムに作ってサーバーの認証情報を推測することもできません。
{
"tag": "proxy",
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "example.net",
"port": 443,
"users": [
{
"id": "00000000-0000-0000-0000-000000000000",
"alterId": 0,
"security": "auto",
"level": 0
}
]
}
]
}
}
このオブジェクトだけでは接続設定として不完全です。サーバーに合わせたトランスポートとセキュリティ層の設定も必要になります。ポートが443でもTLSが自動で有効になるわけではありません。また、users内のsecurityとstreamSettings内のsecurityは別の階層の設定です。現在のVMess設定ではalterIdを0にするのが一般的ですが、古い設定を移行する場合はサーバー側の設定を優先してください。システム時刻が大きくずれていると認証に影響することがあります。ハンドシェイクエラーが出たら、ユーザー情報を確認する前に、まずシステム時刻とタイムゾーンを確認しましょう。
プロトコル間で項目を流用しない
VMess、VLESSなどのプロトコルでは、ユーザー情報の構造がそれぞれ異なります。あるプロトコルのusersオブジェクトを別のプロトコルにそのまま貼り付けると、解析エラーになったり、意味のない設定になったりする可能性があります。同様に、接続先アドレス、トランスポートのHost、TLSのserverNameも別々の項目です。それぞれネットワーク接続、アプリケーション層のリクエスト、証明書検証に使われます。サーバー側で指定がある場合に限り、該当項目を設定してください。3つの値を揃えるために、サブスクリプションに含まれる設定を上書きしないようにしましょう。
| 項目 | 配置場所 | 確認ポイント |
|---|---|---|
tag | アウトバウンドオブジェクト | outboundTagと完全に一致すること |
address / port | プロトコルのサーバー設定 | 実際のサーバーアドレスと待ち受けポート |
id | UUID対応プロトコルのユーザー項目 | 有効なサーバー情報を使う |
streamSettings | アウトバウンドオブジェクト | サーバー側のトランスポートとセキュリティ層に合わせる |
サブスクリプションの更新と手動編集には、設定が上書きされる関係もあります。クライアントは通常、サブスクリプション内のサーバー情報からアウトバウンドを再生成します。一時的なJSONを直接編集してもサブスクリプション側には反映されず、次回サーバーを切り替えたときに変更が失われることもあります。継続的にカスタマイズする場合は、クライアントのカスタム設定やテンプレート機能を使い、サーバー情報の出所も記録しておきましょう。ルーティングだけを変えたいなら、認証項目も同時に編集する必要はありません。ローカルポートの調整だけなら、アウトバウンド全体を書き換える必要もありません。変更範囲を絞ることで、正常な接続設定を壊すリスクを減らせます。
「接続テストに成功した」ことと「実際の通信が正常である」ことは同じではありません。テストの内容は、接続の確立、特定のURLへのアクセス、特定のリクエストの確認などに限られる場合があります。実際のアプリは、長時間接続や別ドメイン、UDPも使うことがあります。まずアウトバウンドがプロトコル接続を確立できるかを確認し、次にアクセスログでアプリのリクエストが該当タグを通っているかを調べ、最後に実際の用途でテストしましょう。共有リンクとサブスクリプションURLの違いについては、共有リンクとサブスクリプションのインポート方法も参照してください。誤ったデータ層の設定を変更しないために役立ちます。
streamSettings:トランスポートとセキュリティ層
プロトコル、トランスポート、TLSを分けて考える
アウトバウンドのプロトコルは、プロキシリクエストの構成と認証を担います。トランスポートは両端間でデータを運ぶ方法、TLSなどのセキュリティ層は接続の保護と認証を担います。これら3つには関連がありますが、互いに置き換えられるものではありません。同じVMessでも複数のトランスポートを組み合わせられますが、サーバー側がすべての組み合わせを受け付けるとは限りません。クライアントの画面に選択肢が表示されても、現在のサーバーが対応しているとは限りません。「プロトコル、トランスポート、セキュリティ層が一致しているか」の順に確認し、プルダウンの組み合わせを手当たり次第に試さないようにしましょう。
streamSettingsは対象のインバウンドまたはアウトバウンドオブジェクト内に配置します。任意のトップレベル項目ではありません。ここではクライアント側のアウトバウンドを対象に、WebSocketとTLSの組み合わせで構造を説明します。networkがwsの場合、対応する項目はwsSettingsに設定します。securityがtlsの場合はtlsSettingsに設定します。トランスポート名や利用可能な拡張項目は、コアや実装によって異なります。新しい名称や非推奨の警告が出た場合は、似た綴りの項目に置き換えるだけでなく、現在のコアが対応する範囲を確認してください。
{
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "example.net"
},
"wsSettings": {
"path": "/proxy",
"headers": {
"Host": "example.net"
}
}
}
}
アドレス、serverName、Host
例にあるexample.netとパスは項目を説明するためのものです。実際に接続するには、サーバーから指定された値を使ってください。アウトバウンドのaddressは接続先を決め、tlsSettings.serverNameはTLSのサーバー名と証明書検証に使われます。WebSocketのHostはHTTPリクエスト内のホスト名です。リバースプロキシ構成では、これらの値が異なる場合があります。手動編集時は項目ごとに記録し、サーバーのメモ欄の値ですべてを上書きしないでください。ドメイン名が同じになるのは一部の構成に限られ、設定形式全般のルールではありません。
pathは任意の説明文を入れる項目ではありません。リバースプロキシは、WebSocketリクエストをパスに応じてバックエンドへ転送することがあります。パスが一致しないと、通常のWebページやリダイレクト、エラーが返る場合があります。大文字・小文字、先頭のスラッシュ、追加のクエリ文字列もサーバーの動作に影響します。接続後すぐ切断される場合は、まずサーバー指定のパスとHostを確認し、次に中継プロキシが接続のアップグレードに対応しているかを調べましょう。ローカルのインバウンドポートを変更しても、リモート側のWebSocketパスの誤りは解決しません。両者はまったく別の場所の設定です。
接続段階ごとにエラーを切り分ける
接続タイムアウトは、所定の時間内に何らかの段階が完了しなかったことを示すだけで、認証パスワードが誤っているとは限りません。サーバーアドレスを解決できない場合は、まず名前解決を確認します。解決できても接続を確立できない場合は、サーバーの待ち受け、ファイアウォール、ネットワーク経路を調べます。TLSの段階まで進んでいれば、ログに証明書やハンドシェイクの手がかりが記録されることがあります。ユーザー情報を主に確認するのは、プロキシプロトコルの認証段階に進んでからです。この順序で確認すれば、ルーティング、DNS、認証項目を同時に変更して混乱するのを避けられます。
トランスポート層には、ソケットの動作、接続の多重化、特定のトランスポート拡張など、多くの高度な項目があります。初回設定で必須になるものではありません。異なる情報源の「最適化項目」をまとめて追加すると、接続のライフサイクルが変わったり、互換性のない組み合わせになったり、サーバーがリクエストを認識できなくなったりする可能性があります。まずサーバーの指定に合った最小限の設定で接続し、要件ごとに追加項目を検証してください。根拠のない問題に対して、項目を積み重ねれば速度が上がると期待するのは避けましょう。
REALITYなどの拡張機能は、tlsSettingsの値を自由に置き換えるものではありません。特定のコア要件と独自のパラメーター制約があります。v2rayNGはXrayコア、v2flyNGはV2Flyコアを使うため、対応するプロトコルや拡張機能が同じとは限りません。移行前に各サーバーで必要な機能を確認し、それに応じてクライアントとコアを選んでください。まずインポートしてからエラー項目を1つずつ削除する方法は避けましょう。デスクトップでv2rayNを使う場合も、そのサーバーが実際にどのコアで動作しているかを確認してください。
変更結果を比較する場合は、同じサーバー、同じネットワーク、同じテスト先を使い、1項目だけ変更してログ上の段階変化を記録してください。トランスポート、サーバーアドレス、ルーティング方式を一度に変更すると、接続が復旧しても、どの変更が効いたのか分からなくなります。ハンドシェイクエラーが繰り返される場合は、実行ログからエラーを特定する方法を参考にしてください。速度の問題は接続が正常になってから別途調べましょう。遅い接続をすべてTLSの問題と決めつけないでください。
routing:ルーティングとルールの順序
ルールが適用されるタイミングを知る
ルーティングは、すでにコアに届いたリクエストを条件に照らし、アウトバウンドを選択します。アプリのシステムプロキシを有効にしたり、クライアントに届いていない接続を自動で受け取ったりする機能ではありません。通常のfieldルールは配列の上から順に照合され、最初に条件を満たしたルールが出口を決めます。ルール内の異なる条件は通常すべて満たす必要があります。同じdomain配列またはip配列内の複数項目は、候補として一致判定に使われます。ルールを作る際は、まずトラフィックの送信元、宛先、出口を明確にしてから項目を選びましょう。先にリストを埋めて優先順位を後から推測する方法は避けてください。
以下は部分的なルーティング設定の例です。プライベートアドレスとgeosite:cnに該当するドメインをdirectへ送ります。この例を使うには、outboundsにdirectタグが必要です。geoipとgeositeの参照には、実行環境で互換性のあるルールデータが利用できることも必要です。どのルールにも一致しない場合、通常は先頭のアウトバウンドに戻ります。「proxy」というタグが自動的に選ばれるわけではありません。その他のリクエストをプロキシ経由にしたい場合は、有効なプロキシアウトバウンドを確認してから既定の出口を設定してください。ルール名だけで動作を判断しないようにしましょう。
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
}
]
}
}
domainStrategyと照合方法
routing.domainStrategyは、ルーティングの照合時にドメイン名とアドレスをどう扱うかを指定します。AsIsは通常、リクエストに含まれる情報だけで照合します。IPIfNonMatchはドメインルールに一致しなかった場合に名前解決を試み、アドレスルールの判定に進みます。IPOnDemandはアドレス情報が照合に必要になった時点で名前解決します。これはDNSサーバーのアドレスではなく、すべてのアウトバウンドで特定のアドレスファミリーを優先する設定でもありません。アドレスルールの有無、ドメインを正しく解決できるか、追加の名前解決がトラブル対処やリクエスト経路に与える影響を考慮して選んでください。
ドメインルールには、完全一致、ドメインとそのサブドメイン、キーワード、正規表現など、異なる範囲の照合方法があります。よく使われるfull:example.netは指定したドメインのみ、domain:example.netは該当するサブドメインも対象にします。regexp:を使う場合は、正規表現とJSON文字列のエスケープを理解しておく必要があります。1つのサイトだけを対象にするなら、範囲が明確な形式を優先しましょう。広すぎるキーワードは無関係なドメインにも一致するおそれがあり、複雑な正規表現は保守の負担になります。変更後は、対象に一致するケースと一致しないケースの両方をテストしてください。
{
"type": "field",
"domain": [
"full:example.net",
"domain:example.org"
],
"network": "tcp",
"outboundTag": "direct"
}
このルール例では、宛先ドメインが指定項目のいずれかに一致し、さらにネットワーク種別がTCPであることが条件です。リクエストにアドレスしか含まれない場合、ドメインルールを判定する情報が不足することがあります。スニッフィングでドメイン名を取得できた場合も、スニッフィングとルーティングの設定を確認してください。「サイトがドメイン名を使っていること」と「コアがそのドメイン名を受け取っていること」は別です。アプリが独自に名前解決する場合や、暗号化された名前解決を使う場合、アドレスへ直接接続する場合には、コアから見える情報が変わります。ドメイン項目をさらに追加するより、アクセスログの宛先形式を確認するほうが有効です。
例外ルールから既定の経路まで順に整理する
優先させたい範囲の狭いルールは、範囲の広いルールより前に置きます。たとえば、特定の内部サービスを先に処理し、その後に広いアドレスやドメインの集合を配置します。すべてのTCP通信に一致するルールが前にあると、後ろに記述した特定サイト向けのTCP例外は適用されないことがあります。ルールの用途はドキュメントやクライアントが対応するメモ欄に記録してください。標準JSONに日本語のコメントを直接書き込むのは避けましょう。不要な項目を削除する場合も、依存関係を一度に失わないよう、元に戻せるコピーを残してください。
「中国本土を除外」は、クライアントに用意されているルールセットの一般的な名称であり、JSONにあるだけで振り分けがすべて完了する真偽値のスイッチではありません。実際の動作は、ルールデータ、ルールの順序、既定の出口、DNSの挙動に左右されます。クライアントやコア、ルールデータの更新によって、境界にある宛先の結果が変わることもあります。正確に振り分けるには、メニュー名だけでなく実行時のroutingを確認してください。システムプロキシと「中国本土を除外」モードの関係は、システムプロキシと中国本土を除外するモードの解説を参照してください。
特定の宛先を調べるときは、まずリクエストがコアに届いているかを確認し、次にどの出口に一致したか、最後にその出口が接続できるかを調べます。比較用に完全一致するドメインルールを一時的に追加しても一致しない場合は、リクエストにドメイン名が含まれているか、設定が再読み込みされたか、上位により広いルールがないかを確認してください。LAN内アドレスへのアクセスに問題がある場合は、システムプロキシの除外リストも確認しましょう。リクエストがコアに届いていない可能性があります。デスクトップのプロセス単位のルールはプラットフォームやトラフィック制御機能に依存します。Androidのアプリごとのプロキシを、汎用的なrouting項目と考えないでください。
dns:名前解決とルーティングの連携
システムの名前解決と内蔵DNSを区別する
DNSはドメイン名をアドレスに変換しますが、1回のアクセスで複数の場所が名前解決を行うことがあります。アプリがシステムのリゾルバーを使う場合もあれば、独自の方式を使う場合もあります。コアもルーティング判定やアウトバウンド接続時に、内蔵DNSを呼び出すことがあります。トップレベルのdnsは、主にコアの名前解決機能を設定します。このオブジェクトを記述しただけで、端末全体のDNSリクエストを引き継ぐわけではありません。システムが従来のリゾルバーを使っているように見えても、コアのdnsが読み込まれていないとは限りません。どのプロセスが、どの処理段階で行った問い合わせかを確認してください。
ドメイン名を指定してSOCKSに接続した場合、その後の名前解決はコアまたはリモートサーバーが行うことがあります。アプリが先に名前解決してアドレスを渡した場合、コアが受け取るのはアドレスだけかもしれません。この違いによって、ドメインルールから見える情報やエラーが発生する場所も変わります。「ドメイン名では開けないが、アドレスなら接続できる」場合は、まずどちら側で名前解決しているかを特定し、その後で結果を確認してください。すべてのDNSサーバーを次々に変更すると、元の問題を覆い隠すだけで、アプリとブラウザーの挙動が異なる理由は解決できないことがあります。
項目を理解するためのDNS設定例
以下はローカルのリゾルバーを使い、システムの現在の名前解決経路を維持しながら、内蔵DNSの問い合わせでIPv4の結果を優先する例です。hosts内のexample.testは説明用のアドレスに割り当てられており、実際のWebサイトを提供するものではありません。この設定をトップレベルのdnsに統合しても、内蔵リゾルバーを呼び出す機能があって初めて使われます。問い合わせポリシーやサーバーオプションの対応状況はコアごとに異なります。起動時に項目エラーが出た場合は、現在のコアの設定仕様に戻って確認してください。
{
"dns": {
"hosts": {
"example.test": "192.0.2.10"
},
"servers": [
"localhost"
],
"queryStrategy": "UseIPv4"
}
}
hostsは、少数の明確で変わりにくいローカルマッピングに適しています。動的なサイトの名前解決を長期間代替する用途には向きません。多くのサービスは複数のアドレス、地域別の振り分け、障害時の切り替えを使っているため、古いアドレスを固定すると断続的な障害につながることがあります。静的マッピングを使う場合も、TLS証明書はドメイン名に対して検証されます。接続先アドレスを変更しても、任意のサーバーがそのドメインの正当な接続先になるわけではありません。テスト用マッピングを削除した後は、アプリやシステムのキャッシュも考慮してください。次回アクセスで古い結果が使われ、設定が反映されていないように見える場合があります。
名前解決のポリシーとアウトバウンドのポリシーは別
dns.queryStrategyとrouting.domainStrategyは似た名前ですが、役割が異なります。前者は主に内蔵DNS問い合わせのアドレスファミリーを制御し、後者はルーティングの照合でドメインをアドレスに解決するかを制御します。アウトバウンドやソケットにも独自のドメイン処理項目がある場合があり、これらも混同できません。内蔵DNSの問い合わせをIPv4に変更しても、すべてのアプリ、システムの名前解決、リモートプロキシがIPv4だけを使うとは限りません。アドレスファミリーの問題を調べるときは、ローカルでの名前解決、実際の接続先、最終的な出口を分けて確認してください。
| 設定場所 | 主な役割 | ここからは判断できないこと |
|---|---|---|
dns.servers | 内蔵DNSで使うサーバーの選択 | すべてのアプリがこれらのサーバーを使う |
dns.queryStrategy | 内蔵DNS問い合わせのアドレスファミリー設定 | 端末全体で別のアドレスファミリーを無効にする |
routing.domainStrategy | ルーティング照合時にドメインをアドレスへ解決するか | DNSサーバーが指定されている |
dns.hosts | 内蔵DNSの静的マッピング | OSのhostsファイルが書き換えられる |
暗号化DNSサービスを指定する場合は、そのサービス自体へ到達できる方法も必要です。問い合わせ先をドメイン名で指定していて、そのサービスへの接続にも同じ、まだ動作していない名前解決経路が必要な場合、循環依存が起きることがあります。プロキシサーバーのドメイン名も、プロキシ経由でしか使えないDNS経路に依存していると、起動時に行き詰まる可能性があります。サーバー名の初期アドレスをどう取得するか、DNS問い合わせの接続がどの出口を使うか、失敗時に分かりやすい代替経路があるかを明確にしてください。設定が複雑だからといって、信頼性が高まるとは限りません。
トラブル対処は3段階に分けられます。まずドメイン名の解決結果を取得できるか、次に結果が利用可能なアドレスか、最後に接続が想定した出口を通っているかを確認します。名前解決に成功して接続がタイムアウトするなら、引き続きネットワーク経路を調べてください。すべてのタイムアウトをDNSエラーと呼ぶのは適切ではありません。名前解決の失敗を証明書検証の無効化で解決しようとするのも避けましょう。結果を比較するときは、時刻とアドレスファミリーを記録してください。動的な振り分けにより結果が変わることがあります。変更と障害の関係を再現できた場合に限り、その設定を残す根拠になります。
ルーティングで使うgeositeデータはドメインの集合、geoipデータはアドレスの集合を表します。DNSキャッシュではなく、ドメイン名を正しいアドレスに自動変換する機能でもありません。ルールセットを読み込めるか、ドメイン名を解決できるか、出口から接続できるかは、それぞれ独立した確認項目です。透過的なトラフィック制御、仮想アドレス、DNS振り分けを使うと状態がさらに増えるため、まず通常のローカルプロキシで基本動作を確認してから、機能を段階的に追加してください。ルーターや中継ゲートウェイの設定については、Xrayゲートウェイの構築概要を参照してください。デスクトップ向けの待ち受け設定をそのまま流用しないようにしましょう。
policy:ポリシー、ログ、統計
ユーザー単位のポリシーを関連付ける
policyは接続動作や統計に関するポリシーを定義します。別のルーティングテーブルではなく、アプリに帯域幅を自動で割り当てる速度制限機能でもありません。levelsオブジェクトはユーザーレベルごとに項目を整理します。JSONではキー名を文字列で記述し、プロトコルのユーザー項目にあるlevelから該当レベルを参照します。この仕組みは、使用するプロトコルと設定経路が対応している場合に限り有効です。任意のインバウンドタグをレベル名として使うことはできません。明確な要件がなければコアの既定ポリシーを使い、意味を理解していない項目を汎用的な最適化として追加しないでください。
以下はレベル0の接続時間項目の例です。値の単位は秒で、構造を説明するものであり、すべてのネットワークに推奨する値ではありません。handshakeは該当する接続ハンドシェイク段階の時間を制限し、connIdleは接続のアイドル時間を扱います。uplinkOnlyとdownlinkOnlyは、接続が一方向の状態になった後の待機動作に影響します。それぞれの項目が対象とするプロトコルや段階は、現在のコアの実装を確認してください。サーバーの稼働状況を確認する機能の代わりにはならず、値を大きくするだけで到達不能なリモートアドレスが復旧するわけでもありません。
{
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5
}
}
}
}
時間設定を変える際の注意点
アイドルタイムアウトを短くしすぎると、データが一時的に流れない接続が早く終了することがあります。長く設定すると、切断済みの接続がより長くリソースを占有する可能性があります。長時間接続を使うアプリへの影響は、アプリ独自のハートビート、サーバー側のタイムアウト、ネットワーク機器の状態にも左右されます。切断を調べるときは、最後に有効なデータが流れてから切断するまでの時間を記録し、同じ間隔が繰り返されるかを確認しましょう。一度切断しただけで、すべてのタイムアウトを延ばしても原因は分からず、実際に失敗した接続の解放が遅くなるおそれがあります。
ハンドシェイクタイムアウトも、どの段階で起きたかを考慮する必要があります。ネットワークの混雑、サーバーの応答遅延、認証情報の不一致はいずれも、ハンドシェイクが時間内に完了しない原因になりますが、対処方法は異なります。待機時間を延ばしても許容範囲が広がるだけで、誤ったユーザー情報やトランスポートの不一致は直りません。まず実行ログで失敗した段階を確認し、そのうえで小幅な調整を検討してください。変更後に「すぐ失敗」から「長く待って失敗」に変わっただけなら元の値に戻し、アドレス、プロトコル、セキュリティ層を調べましょう。
まず適切なログレベルを選ぶ
logはトップレベルに置き、loglevelには現在のコアが対応するレベルを指定します。普段はwarningまたはerrorを確認し、問題の調査中は一時的にinfoへ上げ、より詳しい情報が必要な場合だけ短時間debugを使うのが一般的です。詳細なログにしても接続速度が上がるわけではなく、アクセス先、ローカルパス、ユーザー識別情報が記録される可能性があります。トラブル対処の内容を共有する前に、サブスクリプションURL、認証情報、個人を特定できる情報を削除してください。最後の「失敗」という一文だけを切り取るより、エラーの原文と発生順を残すほうが役立ちます。
{
"log": {
"loglevel": "info"
}
}
accessとerrorのファイルパスを明示する場合は、実行ユーザーに書き込み権限があるか、ディレクトリが存在するか、ディスク容量が十分かを確認してください。デスクトップクライアントがログ出力を管理している場合、手動でパスを設定してもクライアントのログ画面に表示されないことがあります。相対パスはプロセスの作業ディレクトリを基準にします。エディターのあるフォルダーを基準に考えないでください。調査が終わったら通常のログレベルに戻し、アクセス記録を含むファイルは、設定した保管期間に従って削除してください。
統計の有効化と監視画面は別
stats、policy内の統計設定、apiの統計取得機能は連携して動作します。スイッチを1つ有効にするだけでデスクトップにグラフが表示されるわけではありません。インバウンド、アウトバウンド、ユーザーの統計では対象範囲が異なります。ユーザー統計には、プロトコル内のユーザー識別項目が必要な場合もあります。クライアントに通信量の統計機能があるなら、まずその画面を使いましょう。数値を表示するためだけに管理インターフェースを公開するのは避けてください。統計は特定の計測位置の値であり、通信事業者の課金量やアプリが扱ったファイルのサイズと一致するとは限りません。
「最適化」の効果を比較する際は、同じアプリ、同じサーバー、同じテスト先を使い、まず変更前の状態を記録してからポリシーを1つだけ変更してください。スループットはノードの負荷、回線、プロトコル、アプリの並列処理、端末性能などに左右されます。policy内の時間設定だけで経路全体の速度が決まるわけではありません。接続は安定しているのにダウンロードが遅い場合は、通信速度が遅い場合の段階的な確認方法を参考に、ノード、回線、ローカル設定を切り分けてください。タイムアウトを繰り返し短くしたり、統計項目をすべて有効にしたりする方法は避けましょう。
設定の検証、移行、復元
再現可能な変更記録を残す
設定を変更する前に、現在正常に動作している状態を保存し、解決したい問題を具体的に書き留めてください。たとえば「特定のアプリがプロキシを通らない」「あるドメインが誤った出口に振り分けられる」「ネットワーク切り替え後に名前解決できない」といった内容です。これらはそれぞれ入口、ルーティング、名前解決に関わる問題であり、サブスクリプション全体の再インポートで一律に対処するものではありません。クライアント、実際に使うコア、トラフィック制御方式、変更した項目を記録すれば十分です。認証情報を書き写す必要はありません。保存したコピーに非公開のサーバー情報が含まれる場合があるため、公開場所へのアップロードは避けてください。
手動JSONの検証は、少なくとも構文解析、コアが受け付けるか、実際の動作の3段階で行います。構文では括弧、引用符、カンマ、データ型を確認します。コアの段階では項目の対応状況、タグ参照、リソースの読み込みを確認します。動作では実際のアプリが想定した入口に入り、正しい出口を使うかを確認します。最初の2段階に問題がなくても、3段階目が成功するとは限りません。逆にWebページを一度開けただけで、設定全体が正しいとも言えません。直接接続されていたり、キャッシュが使われていたりする可能性があります。実際の経路を確認して判断してください。
決まった順序で起動してテストする
まず、ローカルポートの競合を避けるため、重複して起動しているクライアントやテストプロセスを終了します。設定を読み込んだら起動ログを確認し、構文エラー、未知の項目、ルールデータの不足、待ち受け失敗がないことを確かめてから、アプリで宛先を明示したリクエストを送ります。起動に失敗した場合は、ルーティング方式を次々に切り替えないでください。正常に起動してもアクセス記録がない場合は、まずアプリの入口を確認します。記録があるのにタグが違う場合は、ルールの順序を確認しましょう。この順序で調べると、「リクエストが届いていない」状態と「届いた後の処理が誤っている」状態を明確に区別できます。
- 元の設定を残し、コピー上で1つの項目グループだけを変更して、予想される変化を記録します。
- コピーを読み込み、解析結果、タグ参照、ルールデータ、ポートの待ち受けを確認します。
- 宛先を固定してリクエストを送り、ログに記録された宛先情報とアウトバウンドのタグを確認します。
- 影響を受けないはずの宛先もテストし、例外ルールの適用範囲が広がっていないことを確認します。
- 普段使うアプリと元のログレベルに戻し、クライアントの再起動後も変更が残るか確認します。
テスト先は実際の用途に合わせますが、すべてのサイトを一度に試す必要はありません。少なくとも、直接接続する想定の宛先と、リモートのアウトバウンドを経由する想定の宛先を1つずつ選びます。LANを使う場合は、内部サービスも追加します。ページが開くかどうかだけを指標にしないでください。ブラウザーのキャッシュ、既存の接続、アプリ独自のプロキシが結果に影響することがあります。ルーティングやDNSを変更した後は、該当アプリを終了して再起動し、新しいリクエストが新しい設定を通るようにしましょう。キャッシュを消去する場合は、比較条件が不明確にならないよう対象範囲も記録してください。
復旧可能なエラーと互換性の問題を切り分ける
unknown fieldのようなメッセージが出た場合は、まず設定形式が現在のコアに合っているかを確認し、その後で項目名と階層を調べます。address already in useが出た場合は、サーバーを変更するのではなく、重複プロセスとポートを確認してください。証明書エラーでは時刻、サーバー名、証明書チェーンを調べます。ルールデータの読み込みエラーでは、クライアントがファイルを正しく管理しているかを確認します。エラーメッセージはコアによって異なりますが、「失敗した段階を特定してから、該当する項目を変更する」という手順は変わりません。
| 症状 | まず確認する項目 | 後回しにする項目 |
|---|---|---|
| コアが起動しない | JSON、項目の互換性、待ち受けポート | Webサイトのドメインルール |
| アプリのアクセス記録がない | システムプロキシ、アプリの入口、制御範囲 | リモート側の認証ユーザー |
| 想定と異なる出口になる | ルールの順序、宛先の形式、tag参照 | TLS証明書の検証 |
| 再起動後に変更が消える | 生成設定と保存設定の違い | ネットワーク経路 |
v2rayNからv2rayNGに移行する場合は、まず対応するサーバー情報を移行し、モバイル端末側でアプリごとのプロキシやルーティングを再設定してください。デスクトップのシステムプロキシ、ファイルパス、ウィンドウ設定は、コアの設定としてそのまま移行できません。v2flyNGへ移行する場合は、V2Flyコアが元のサーバーに必要なプロトコルとトランスポートに対応しているかも確認してください。サブスクリプションを読み込めても、インポート形式を認識できたことを示すだけで、すべての項目が移行先のコアで動作する保証にはなりません。移行後は同じ手順で改めて検証してください。
クライアントから共有リンク、完全な設定、バックアップをエクスポートできる場合は、まず用途を確認してください。共有リンクは通常、単一サーバーの情報を中心とするため、ルーティング、DNS、システム設定をすべて保存するものではありません。バックアップにはより多くのアプリデータが含まれ、復元時の影響範囲も広くなることがあります。エクスポートファイルをトラブル対処のために他者へ渡す前に、サーバー認証情報やサブスクリプションの内容を削除してください。ルールの問題を説明するだけなら、routing、関連するタグ定義、情報を隠したログだけを個別に共有しましょう。バックアップ全体を複数の場所へ転送するのは避けてください。
復元は古い設定を貼り戻すだけではありません。システムプロキシ、元のコア選択、ログレベル、アプリの入口も元に戻してください。LAN向けの待ち受けや管理インターフェースを追加した場合は、それらも無効にします。復元後に再起動し、元の宛先で動作を確認して、基本状態が戻ったことを確かめてから次の変更を試してください。日常の操作は入門ガイドに戻って手順を確認できます。別のプラットフォーム向けクライアントが必要な場合は、クライアントのダウンロードページを利用してください。出所が不明な設定例を多数集めるより、確実に動作する基本設定を1つ保つほうが長期的な管理に役立ちます。