1. JSONの構造と設定の範囲
クライアントとカーネルを区別する
v2rayN、v2rayNG、v2flyNGは、サブスクリプションやノード、システムプロキシ、起動処理を管理するGUIクライアントです。設定に従って実際に通信を処理するのはカーネルです。Project Vは関連技術エコシステムの基盤を提供し、V2FlyはV2Rayのコミュニティ開発を引き継ぎ、Xrayは独立して発展する別のカーネルです。共通する概念は多いものの、対応する項目は完全には一致しません。動作するJSONを見つけたら、まず対象のカーネルを確認し、現在のクライアントがどのプログラムを起動しているかを調べましょう。
このページでは、従来のJSON設定構造を中心に解説し、リモート接続の例にはXrayでよく使われる記述を採用しています。v2rayNGは通常Xrayを使い、v2flyNGはV2Flyカーネルを採用したAndroid向けの選択肢です。v2rayNでは複数のカーネルを管理できますが、利用できる機能は選択したカーネルとクライアントの設定によって異なります。メニューに「カスタム設定」があるからといって、ある系統向けの新しい項目を別の系統へそのまま移せるとは限りません。未知の項目や未対応プロトコルに遭遇したら、サブスクリプションを何度も切り替える前にカーネルを確認してください。
トップレベルのオブジェクトがリクエストをつなぐ仕組み
設定の最上位はオブジェクトです。inboundsはリクエストの入口、outboundsは出口、routingは両者の対応関係を決めます。dnsは組み込みリゾルバーを設定し、policyは一部の接続や統計に関する動作を管理し、logは実行状況の確認に使います。これらは記述順に実行されるスクリプトではありません。ファイルの先頭に書かれた項目が、後のモジュールより先に通信を処理するわけではありません。
以下は、ローカルでのテストに絞った簡易設定です。ローカルのSOCKSポートだけを待ち受け、受け取ったリクエストを宛先へ直接接続します。JSONの構文、ポート、アプリのプロキシ設定を確認するためのもので、リモートプロキシには接続しません。ポートが他のプログラムで使われている場合は、設定とテストに使うアプリの両方を変更してください。最初の設定がシンプルなほど、後からリモートoutboundsやルーティング、DNSを追加したときに、問題の原因を特定しやすくなります。
{
"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のオブジェクトキーと文字列には半角の二重引用符を使い、配列は角括弧で囲みます。真偽値は引用符で囲まず、trueまたはfalseと記述します。オブジェクトの最後の項目の後にはカンマを付けません。読み込み側がコメントを許容する場合でも、クライアント間で確認しやすいよう、厳密なJSONとして保存するのがおすすめです。同じオブジェクト内でキーを重複させないでください。解析器によっては前の値が上書きされたり、読み込みが拒否されたりするため、実際の設定内容が分かりにくくなります。
構文を確認した後は、各項目が正しい階層にあるかをチェックします。たとえば、portはinboundオブジェクトに属し、リモートサーバーのポートは該当プロトコルのサーバー設定に記述します。streamSettingsは通常、outboundのsettingsと同じ階層に置き、サーバーアドレスのオブジェクトには入れません。階層が誤っていてもファイル自体は読み込める場合があり、その場合は設定項目が無視されることがあります。例を読むときは、まず外側の括弧を確認してから項目をコピーすると、単語だけを見比べるより間違いを防げます。
動作する基準設定を別途保存し、変更ごとに「LAN内宛ての通信だけに直結ルールを追加」など目的を記録しておくのがおすすめです。ノードの認証情報やサブスクリプションURL、ログに記録されたアクセス先には個人情報が含まれる場合があります。設定を共有する前に置き換えてください。リモートアドレスを含む例では、説明用のドメインと識別子を使っており、接続可能なサービスではなく構造を示しています。ポートが空いていれば、上記のローカル直結設定だけをそのままテストに使えます。
2. inbounds:ローカルリクエストの入口
待ち受けアドレス・ポート・プロトコル
inboundでは、どのアドレスで接続を待ち受けるか、どのポートを使うか、どのプロトコルを受け付けるかを指定します。listenに127.0.0.1を設定すると、このIPv4アドレスへの接続は同じ端末からしかできません。0.0.0.0ではすべてのIPv4インターフェースで待ち受けるため、LAN内の端末から接続できる可能性があります。後者は単に「互換性を高める」ための設定ではありません。ファイアウォールやネットワーク環境、アクセス制御も考慮してください。端末上のブラウザーだけで使う場合は、ループバックアドレスで待ち受けるほうが管理しやすくなります。
portはローカルサービスのポートであり、リモートノードのポートではありません。両者に同じ番号を設定しても特別な意味はありません。SOCKSとHTTPは異なるinboundプロトコルなので、アプリ側でも正しい種類を選ぶ必要があります。アドレスとポートが正しいだけでは十分ではありません。システムプロキシ、ブラウザー拡張、端末の環境変数がそれぞれ別の入口を参照している場合もあります。ブラウザーでページを開けたからといって、すべてのアプリが同じinboundを経由しているとは限りません。
HTTPの入口を追加する
以下は2つのinboundを組み合わせた例です。1章の設定にあるinbounds配列と置き換えて使えます。SOCKSは対応アプリ向け、HTTPは一般的なHTTPプロキシやCONNECTに対応するクライアント向けです。2つのポートはそれぞれ空いている必要があります。HTTP inboundは汎用のUDP入口ではありません。また、SOCKSでUDPを許可しても、すべてのアプリがSOCKS 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": {}
}
]
tagは設定内で使う名前で、後続のルーティングからinboundTagを使って指定できます。用途が分かる短い名前を付け、重複しないようにしましょう。タグを設定してもシステムプロキシが自動で作られるわけではなく、「global」という名前にしてもすべての通信を取り込むわけではありません。入口ごとに異なる出口を使う場合は、入口に別々の名前を付け、ルーティングルールで対応関係を明確にしてください。クライアントの表示名から推測する設定は避けましょう。
スニッフィングで補えるのは宛先情報
アプリによっては、カーネルに宛先IPアドレスだけを渡すため、ドメインルールを適用するための情報が不足することがあります。スニッフィングでは、対応するプロトコルの初期データからHTTPのホスト名やTLSのサーバー名情報を検出できます。一般的にはinboundオブジェクトのsniffingに設定し、enabledで有効化したうえで、destOverrideに検出対象の種類を指定します。これは復号ツールではなく、すべての接続でドメインを取得できるわけでもありません。暗号化されたハンドシェイク情報や対象外のプロトコルでは、補完できない場合があります。
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"],
"routeOnly": true
}
これはXrayでよく使われるinboundの追加設定です。routeOnlyは、スニッフィングで得た情報をルーティングの判定に使い、実際の接続先は書き換えない設定です。対応状況はカーネルごとに確認してください。トラブル対処では、「ドメインを検出できた」「ルールに一致した」「宛先へ接続できた」の3段階を区別しましょう。スニッフィングで情報が得られても確認できるのは最初の段階だけで、DNSやリモート接続、宛先サービスが正常とは限りません。
AndroidのVPNによる通信制御は通常のプロキシと異なる
v2rayNGでは、システムVPNの許可と通信の取り込みをクライアントと連携して行います。SOCKS inboundを1つコピーしただけで、端末全体の通信を同じように取り込めるわけではありません。アプリごとのプロキシ設定、除外するアプリ、バックグラウンド動作の制限もJSONの範囲外です。カスタム設定を読み込んだ後は、クライアントがどのように設定を利用するか、どのローカルポートを確保するかを確認し、自動生成される待ち受け設定と重複しないようにしてください。
デスクトップでも、システムプロキシとTUNを区別する必要があります。システムプロキシが影響するのは該当設定に従うプログラムだけです。TUNには仮想インターフェースや権限、ルーティング処理も関わるため、inboundの設定1つだけでは説明できません。「一部のアプリだけ使える」場合は、まずそのアプリの通信がカーネルに届いているかを確認し、次にoutboundを調べましょう。ブラウザーと端末の違いについては、システムプロキシを個別に確認する手順も参照してください。最初からリモートプロトコルの設定を変更するのは避けましょう。
3. outbounds:接続先とプロトコル設定
デフォルトの出口とタグの参照
outboundは、カーネルが宛先へ接続する方法を決めます。リモートプロキシ、直接接続、通信を遮断する出口を同時に設定できますが、それだけで自動的に振り分けられるわけではありません。従来の設定では、ルーティングに一致しないリクエストは通常、outboundリストの先頭をデフォルトの出口として使用します。そのため、配列の順序を変えると、ルールに一致しない通信の動作も変わる可能性があります。まずデフォルトの方針を決めてから例外を追加すると、タグを並べ替えて動作を試すより分かりやすくなります。
ルーティングでは、outboundTagからoutboundのtagを参照します。両者は完全に一致している必要があります。GUIに表示されるノード名が、実行設定内のタグと同じとは限りません。よくある問題は、ルールをコピーした後に古い名前が残り、カーネルが該当する出口を見つけられなくなることです。また、デフォルトの出口をdirectに設定しているのに、ルールに一致しない通信がすべてプロキシ経由になると思い込むケースもあります。設定を読むときは、outbounds配列の先頭から確認し、各ルールの参照先を追ってください。
直結と遮断の基本設定
freedomは宛先へ直接接続し、blackholeは通信を遮断します。以下は既存のoutbounds配列に追加し、個別に参照できる2つの出口オブジェクトです。直結は端末自身のネットワークを使うため、宛先へ必ず到達できるとは限りません。遮断はアクセス可能な予備ノードではありません。トラブル対処では、特定のテスト用ドメインを一時的に直結へ振り分け、プロキシ経由とローカル経由の違いを確認できます。変更内容を記録し、テスト後は元に戻してください。
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
VLESSの例で各項目が属する場所
以下はXrayのVLESS outboundの構造例です。サンプルのドメインとユーザー識別子は説明用で、接続するにはサーバーから提供された実際の値に置き換える必要があります。addressはリモート接続に使うアドレス、portはサーバーの待ち受けポート、usersはプロトコルのユーザー設定です。idはユーザー識別子で、encryptionの記述はプロトコルによって定義されます。ここでのnoneは、トランスポート層にもセキュリティ保護がないという意味ではありません。
{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "edge.example.org",
"port": 443,
"users": [
{
"id": "00000000-0000-4000-8000-000000000001",
"encryption": "none",
"level": 0
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "edge.example.org"
},
"wsSettings": {
"path": "/tunnel"
}
}
}
この例では、プロトコル設定とトランスポート設定は別の階層です。VLESSのユーザー識別子が正しくても、WebSocketのパスが違えば接続できません。TLSのハンドシェイクに成功しても、ユーザー認証が通ったとは限りません。サーバーが要求するフロー制御、トランスポートの種類、その他の項目を1つずつ照合してください。プロトコル名が同じでも、ノードの設定が同じとは限りません。この例にすべての任意項目が含まれているわけではありません。記載のない項目を推測で追加しないでください。
異なるプロトコルの設定構造を混同しない
VMessでもvnext構造がよく使われますが、ユーザー項目の意味はVLESSと異なります。Trojanでは通常、servers配列とパスワード項目を使います。TrojanのパスワードをVLESSのidに入れたり、別プロトコルのユーザーオブジェクトをそのまま流用したりしないでください。ノードの共有リンクを読み込んだ後は、長い設定ファイルを手作業で組み立てるより、クライアント画面でプロトコルと主要項目を確認するほうが抜けを防げます。
outboundには、ドメイン解決、インターフェースのバインド、チェーン接続などの高度な設定を含めることもできます。これらはカーネルによる違いが大きいため、必要性が明確な場合にだけ追加してください。「予備の出口」を設定しても、自動でフェイルオーバーするとは限りません。outboundを追加しただけでは、カーネルが自動で速度を測定し、最速のものを選ぶことはありません。自動選択には通常、選択機構や監視ロジック、クライアント機能が必要です。利用中のカーネルのドキュメントに従って設定してください。
読み込み後に特定のoutboundだけが失敗する場合は、ほかの動作している設定を保ったまま、その項目のアドレス、認証情報、トランスポート設定だけを変更して比較します。出口の順序とルーティングを同時に変更するのは避けてください。接続が復旧しても、ノードが直ったのか、実際には別の出口を通るようになったのかが分からなくなります。
4. トランスポートとセキュリティ:項目を分けて確認
プロトコル・トランスポート・暗号化は別のもの
ノードの設定は、3つの層に分けて考えると分かりやすくなります。アプリケーションプロキシのプロトコルは認証と転送の仕組みを定め、トランスポートは接続の運び方を定め、セキュリティ層は対応するハンドシェイクと保護を担います。たとえばVLESS、WebSocket、TLSはそれぞれ異なる層に属します。プロトコル名が合っているのは出発点にすぎません。サーバーがWebSocketを待ち受けているのに、クライアントが通常のストリーム接続を使えば、ポートが同じでも接続できません。
streamSettings.networkでトランスポートを選び、streamSettings.securityでその層のセキュリティ方式を選択します。詳細はそれぞれのオブジェクトに記述します。トランスポート名や新旧の項目に対する対応状況はカーネルによって異なるため、新しいカーネル向けの例をあらゆるバージョンで使えるテンプレートとして扱わないでください。まず読み込み時の設定を保存し、明確なエラーに沿って変更しましょう。特に、似て見えるネットワーク名をまとめて置き換えるのは避けてください。
WebSocketとTLSの項目を照合する
以下はトランスポート部分の設定例です。単独で実行できる完全な設定ではなく、該当するoutboundオブジェクトに追加します。パスはサーバーまたは手前のリバースプロキシに合わせ、先頭のスラッシュも含めて指定してください。実際のパスにクエリパラメーターが含まれる場合は、その意味も維持します。serverNameはTLSのサーバー名に関する処理で使い、WebSocketのHostはHTTPリクエスト層の項目です。値が同じことは多いものの、同じ項目ではありません。
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "edge.example.org",
"allowInsecure": false
},
"wsSettings": {
"path": "/tunnel",
"headers": {
"Host": "edge.example.org"
}
}
}
実際の接続先にはドメイン名を使う場合と、サービス提供元が指定したアドレスを使う場合があります。証明書の名前、TLSのサーバー名、HTTPのホスト名は、それぞれ異なる段階で使われます。アドレスに接続できても証明書名が一致しない場合は、サービスから指定されたドメイン名と端末の時刻を確認してください。allowInsecureを安易にtrueへ変更しないでください。検証を無効にすると、証明書や接続先の誤りが隠れるため、常用できる解決策ではありません。
| 項目 | 主な役割 | よくある確認点 |
|---|---|---|
address | リモート接続先 | ドメイン解決とアドレスへの到達性 |
serverName | TLSのサーバー名に関する処理 | 証明書名とサーバー側の要件 |
headers.Host | WebSocketのHTTPホスト名 | 前段サーバーの仮想ホスト判定 |
path | WebSocketのリクエストパス | 大文字・小文字、スラッシュ、パス全体 |
REALITYと他のトランスポートの違い
REALITYのクライアント設定は通常のTLS設定と異なります。securityの名前を変えるだけでは移行できません。サーバー名、鍵に関する項目、short IDなどをサーバー側の設定に合わせる必要があり、項目への対応はカーネルごとに異なります。共有リンクから読み込んだ場合も、クライアントがすべての設定を認識しているか確認してください。GUIに該当項目がない場合は、まず対応状況を調べましょう。似た名前のオブジェクトに設定を無理に追加しないでください。
同様に、gRPCのサービス名はWebSocketのパスとは異なり、HTTP系トランスポートのリクエストヘッダーも別の種類にそのまま流用できません。トランスポートを変更する場合は、通常サーバー側の設定も変更が必要です。クライアントだけ切り替えても、サーバーが自動で対応するわけではありません。2つのノードを比べるときは、まず同じサービス設定を使っているか確認してから、動作の違いを調べましょう。そうでなければ、測定結果は同一条件下のトランスポート性能ではなく、異なる接続経路の比較になります。
失敗した段階からログを読む
接続がタイムアウトする場合は、まずアドレス、ポート、パスへの到達性を確認します。証明書エラーが出る場合は、名前、証明書チェーン、システム時刻を重点的に調べます。HTTPステータスが返ってアップグレードに失敗する場合は、パス、ホスト名、前段サーバーの設定がよくある確認ポイントです。認証エラーなら、プロキシプロトコル層に戻ってユーザー識別子やパスワードを確認してください。エラーが発生した層から次に調べる場所を絞り、すべての失敗をDNSの問題と決めつけないようにしましょう。
トラブル対処では、ノードとアプリを1つずつに絞り、テスト先も固定して、リクエストを書き換えるプロキシ拡張機能は一時的に無効にします。トランスポート、証明書設定、ルーティング方式を同時に切り替えないでください。変更するのは一度に1項目だけにし、失敗する段階が前後したかを記録します。「接続できない」状態から「認証エラー」に変わった場合、まだ成功ではありませんが、ネットワークとハンドシェイクの段階は進んでいます。
5. routing:ルールの順序と宛先の一致
上から順に確認し、最初に一致した出口を選ぶ
ルーティングでは、一致したルールをすべて集めてから優先度を計算するわけではありません。一般的な条件ルールは配列の順に確認され、有効なルールに最初に一致すると、指定された出口が選ばれます。そのため、細かい例外は広い条件のルールより前に置きます。早い位置にある「すべての通信をプロキシへ」ルールが、後続のLAN内直結ルールを妨げることもあります。設定を確認するときは、目的のルールが存在するかだけでなく、その前にリクエストを拾ってしまうルールがないかも見てください。
ルールに異なる条件項目を指定した場合、通常はすべての条件を満たす必要があります。同じ項目の配列に複数の値がある場合は、いずれかが候補になります。たとえば、1つのルールにinboundTagとdomainを指定すると、指定した入口から来て、かつ宛先ドメインが一致するリクエストが対象です。どちらか片方の条件だけで一致するわけではありません。「ドメインが特定の集合に属する、または宛先IPが特定のネットワークに属する」という条件を表す場合は、ルールを分けるほうが分かりやすく、ログからどの条件が適用されたかも確認しやすくなります。
読みやすいルール設定例
以下の例では、説明用の特定ドメインを先に遮断し、次にプライベートアドレスを直結し、その後に指定ドメインとサブドメインをプロキシへ転送します。既存のoutboundタグblock、direct、proxyを使います。geoip:privateには利用可能なGeoIPデータファイルが必要です。データが用意されていない環境では、まず明示的なネットワーク範囲を使ってテストしてください。集合名だけで全アドレスが含まれると思い込まないようにしましょう。
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": ["full:blocked.example.org"],
"outboundTag": "block"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["domain:example.org"],
"outboundTag": "proxy"
}
]
}
full:は完全一致、domain:はドメインとそのサブドメインへの一致、regexp:は正規表現、geosite:はドメイン集合の参照に使います。接頭辞のない一般的な文字列は、より広い範囲に一致する場合があり、特定のドメインだけを指定する用途には向きません。1つのホストだけに一致させたい場合は、意味が明確な接頭辞を使い、名前に同じ文字列を含む別のドメインまでルールに含めないようにしてください。
ドメインの解決方針が一致判定に影響する
AsIsでは、できるだけリクエストに含まれる宛先情報を使ってルーティングし、IPルールのためにすべてのドメインを積極的に解決することはありません。そのため、ドメイン名で始まったリクエストが実際にはプライベートアドレスへ解決されても、上記のプライベートIPルールに必ず一致するわけではありません。IPIfNonMatchはドメインに一致しなかった場合に解決を試み、関連するルールでもう一度判定します。IPOnDemandは、判定にIP情報が必要な場合に解決を試みます。どちらも追加の名前解決が必要になります。
これらの設定は主にルーティング判定に影響するもので、「すべての通信をローカルで強制的に解決する」「DNSは必ずプロキシを通る」と単純に解釈できません。最終的に名前解決をローカルで行うか、リモートへ任せるかは、選択したoutboundやプロトコルの動作にも左右されます。設定変更後にページの初回表示が遅くなった場合は、名前解決の待ち時間が増えていないか確認してください。IP集合による判定が明確に必要な場合だけ該当設定を有効にし、早く解決すればルールが正確になると思い込まないようにしましょう。
データファイルとGUIのルール設定
geosite.datとgeoip.datは、それぞれドメインとIPの集合データを提供するファイルです。カーネル設定内の通常のコメントではありません。指定する集合名が現在のデータファイルに存在する必要があります。ファイルの読み込みに失敗したり、名前を間違えたりすると、起動に失敗する場合があります。更新によって分類内容が変わることもあるため、トラブル対処ではデータの取得元と変更内容を記録してください。更新先やルールの順序については、GeoIPとGeoSiteの使い方を参照してください。
v2rayNのルーティングプリセットやv2rayNGのカスタムルールは、実行用設定を生成するときにGUIの選択項目と組み合わされる場合があります。ファイルを編集しても古いルールが反映されているように見える場合は、現在選択されている設定とモードを確認し、クライアントがファイルを再生成していないか調べてください。検証には、特定のドメイン1つと既知のプライベートアドレス1つを使い、それぞれ出口タグを確認します。ページが1つ開けただけでは、すべてのルーティングルールが意図どおり動作しているとは判断できません。
6. dns:名前解決の経路と接続元
組み込みDNSとシステムDNSは別
設定内のdnsは、カーネルに組み込まれたリゾルバーの動作を定義しますが、端末上のすべてのアプリのDNS設定を自動で変更するわけではありません。ブラウザーが独自の暗号化DNSを使う場合や、アプリがシステムリゾルバーを呼び出す場合があります。AndroidでVPNを使う場合は、DNS通信の処理をクライアントが管理することもあります。トラブル対処を始める前に、どのアプリの名前解決が失敗しているのか、リクエストがどこから送られ、どのリゾルバーが応答しているのか確認しましょう。カーネルのDNS設定を変えても、ブラウザー独自の経路をテストし続けていると、期待した変化は見えません。
ルーティングモジュールや直結outbound、その他の機能が組み込みリゾルバーを使うかどうかは、具体的な設定によって異なります。アプリがIPアドレスを渡している場合、カーネルが元のドメインを再解決する必要はないかもしれません。アプリがドメインをプロキシに渡す場合は、ルール判定やリモート側での処理に使えるドメイン情報が残る可能性があります。そのため、ログにDNSクエリがないからといって、必ずしもDNSモジュールが故障しているとは限りません。リクエストにすでにアドレスが含まれている、または処理上ローカルで名前解決する必要がない場合もあります。
シンプルな名前解決設定を基準にする
以下の設定では、一般的なDNSサーバーを2つ指定し、カーネルで名前解決する際はIPv4の結果を優先して取得します。DNSサーバーの一覧と問い合わせ方針を理解するための基本例です。どのネットワークからもこのアドレスに到達できることや、問い合わせが自動的にプロキシ経由になることを示すものではありません。実際の環境では、利用可能で信頼できるDNSサービスを選び、カーネルの動作に合わせて問い合わせ経路を設定してください。
"dns": {
"servers": [
"1.1.1.1",
"8.8.8.8"
],
"queryStrategy": "UseIPv4"
}
UseIPv4は組み込みリゾルバーが取得する結果のアドレス種別を指定するもので、OSのIPv6を無効にしたり、アプリが直接開始したIPv6接続を書き換えたりする設定ではありません。一部のアドレスファミリーに関する問題を切り分ける用途には使えますが、あらゆる接続失敗への決まった解決策ではありません。端末とノードの両方でIPv6が安定して使える場合は、実際の宛先をテストしてから方針を決めましょう。一時的な回避策によって、もともと使える接続経路を長期的に失わないようにしてください。
静的マッピングとドメイン別の名前解決
hostsを使うと、組み込みリゾルバーで特定の名前に静的なアドレスを割り当てられます。以下の例では、説明用のテストドメインをループバックアドレスに対応させています。ローカルサービスの名前解決をテストする用途に使えます。これはシステムのhostsファイルを変更する設定ではなく、そのドメインを含むすべてのoutboundが自動的に書き換わることを保証するものでもありません。この名前解決処理を利用する機能だけに適用されます。テスト後は削除し、リモートへ接続すべきリクエストがローカルへ戻らないようにしてください。
"dns": {
"hosts": {
"lab.example.org": "127.0.0.1"
},
"servers": [
"1.1.1.1"
],
"queryStrategy": "UseIPv4"
}
より複雑なDNS設定では、特定ドメインに使用するDNSサーバーや、期待するIP範囲、フォールバック動作を指定できます。ただし、設定の組み合わせにはカーネルごとの差があり、サーバーのオブジェクトを追加しただけで、完全なDNS振り分けが実現するとは限りません。特に、指定したサーバーから受け入れ可能な応答が返らない場合の動作や、フォールバックを許可するか、どのサーバーへ切り替えるかを明確にする必要があります。分岐を整理してから項目を追加するほうが、複数のリゾルバーを重ねるより管理しやすくなります。
名前解決の依存関係が循環しないようにする
暗号化DNSを使う場合、DNSサーバー自身のドメインを解決する必要が生じることがあります。その名前解決が、まだ接続できていないプロキシに依存していると、起動時に依存関係が循環します。同様に、プロキシサーバーのアドレスがドメイン名で、その解決にプロキシ経由が必須になっている場合も、接続を開始できない可能性があります。トラブル対処では、まず確実に到達できる基本の名前解決経路を残し、暗号化DNSやルーティングの条件を段階的に追加してください。未検証の出口にすべての問い合わせを最初から結び付けないようにしましょう。
DNSクエリの送信方法は、サーバーアドレスの形式にも左右されます。通常のUDP問い合わせ、暗号化された問い合わせ、一部のローカル処理では、ルーティングの動作が完全には同じではありません。DNSにタグを1つ付けただけで、あらゆる種類の問い合わせがそのタグに従ってルーティングされると考えないでください。該当するサーバー形式について、現在のカーネルの仕様を確認し、ログと実際の通信状況で検証しましょう。名前解決の成功はアドレスを取得できたことを示すだけです。最終的な出口からそのアドレスへ接続できるかも確認してください。
「ノードは接続済みなのにページが開かない」場合は、同じ宛先の名前解決結果と接続エラーを比較し、システム時刻、アドレスファミリー、アプリごとのプロキシ設定を確認してからDNSを調整するか判断しましょう。確認手順の全体像は、接続済みでもアクセスできない場合の確認リストをご覧ください。DNSサーバーは一度に1つだけ変更し、接続を再試行します。アプリのキャッシュによって古い結果が使われ続ける場合もあります。
7. policy:接続方針と統計の設定
policyのレベルはシステム権限のレベルではない
policyでは、一部の接続動作をポリシーオブジェクトにまとめて設定します。levelsのキーはユーザーレベルの識別子です。たとえば文字列キー"0"はレベル0を表し、プロトコルのユーザーオブジェクトから対応するlevel項目で参照できます。このレベルは管理者権限でもノードの品質スコアでもありません。明確なレベル分けが必要なければ、複数のレベルを追加する前にデフォルトのポリシーを理解するほうが管理しやすくなります。
すべてのinboundとoutboundがユーザーレベルを同じように使うわけではありません。JSONに項目を記述できても、現在のプロトコルに対応するユーザー情報があるとは限りません。ポリシーが適用されているかを判断するには、プロトコルの対応状況、レベルの参照先、接続の種類を確認してください。特に、levelsにオブジェクトを追加しただけですべての通信に自動適用されるわけではありません。対応する場所で関連付けを明示する必要があります。
タイムアウト項目は段階ごとに理解する
handshakeは対象となる接続のハンドシェイク待ち時間を指定し、connIdleは有効なデータ通信がないアイドル状態を扱います。uplinkOnlyとdownlinkOnlyは、接続の片方向だけで通信が続いている段階に対応します。これらは互いに置き換えられる4種類の「接続タイムアウト」ではなく、短く設定するほど動作が良くなるわけでもありません。モバイルネットワークの切り替え、長時間接続を使う通知、時間のかかるハンドシェイクでは必要な待ち時間が異なるため、実際の症状に合わせて調整してください。
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5
}
},
"system": {
"statsInboundUplink": false,
"statsInboundDownlink": false,
"statsOutboundUplink": false,
"statsOutboundDownlink": false
}
}
上記の時間項目は秒単位で、設定階層全体を示す例です。すべての端末向けの推奨値ではありません。ハンドシェイクが完了する前に接続が終了する場合は、まず通信経路とサーバーの応答を確認し、待ち時間が本当に短すぎるか判断してください。長時間のアイドル後に接続が再確立される場合は、アプリの再接続機能、OSのバックグラウンド制限、ネットワークの変化も考慮します。「切断」という表示だけで、すべてのタイムアウトを長くしないでください。
統計にはモジュールとスイッチの両方が必要
policy.systemの統計スイッチは、対応する方向の通信量を集計します。通常はカーネル側でトップレベルのstatsモジュールも有効にする必要があります。クライアントからデータを参照する場合は、対応する問い合わせインターフェースやクライアント独自の連携機能も必要です。スイッチを有効にしただけで、画面に統計パネルが自動表示されるわけではありません。統計の対象も区別してください。inboundの統計は入口、outboundの統計は出口、ユーザー統計は識別可能なユーザーと関連設定に基づきます。
"stats": {},
"policy": {
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true,
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
}
これはトップレベルの設定例です。既存のpolicyオブジェクトに統合し、同じ階層に同名キーを2つ書かないでください。統計値は通常、カーネルが処理した通信量を示すもので、通信事業者の課金量と同じとは限りません。接続のヘッダーや再送、システム内のその他の通信が同じ集計基準に含まれない場合があります。クライアントに表示される累計値は再起動後にリセットされることもあります。異なる画面の数字を単純に差し引く前に、集計範囲と期間を確認しましょう。
速度の問題をpolicyの項目追加で解決しようとしない
通信速度が遅くなる原因は、接続先のサービス、リモートノードの負荷、ネットワーク経路、ローカルでの通信制御など、複数の層に分かれます。policyの待ち時間設定は接続のライフサイクルを管理するもので、利用可能な帯域を増やすものではありません。一部のカーネルでは接続バッファーを調整できますが、バッファーを大きくしても通信速度が上がるとは限らず、メモリー負荷が増えることもあります。再現性のあるテスト結果を得てから、問題と関係する項目を判断してください。
Android端末では、バッテリー制限やバックグラウンド動作の条件も確認してください。デスクトップでは、システムプロキシ、TUN、ほかのネットワークツールが干渉していないか調べます。これらはすべてpolicyの設定ではありません。アプリがバックグラウンドに移った後で通信できなくなる場合は、まずクライアントが動作を続けているか確認し、アイドル時間を極端に延ばすのは避けましょう。特定の時間帯だけ遅い場合は、複数のノードと直結の結果を比較してください。具体的な手順は速度低下の段階別診断をご覧ください。
8. 設定の統合・ログ確認・復元
部分設定をまとめて有効なファイルにする
このページの例は部分的な設定であり、単純に連結して使うものではありません。トップレベルのオブジェクトは1つにし、inboundオブジェクトは1つのinbounds配列に、outboundオブジェクトは1つのoutbounds配列にまとめます。ルーティングルールは既存のrulesに追加し、順序を確認してください。トップレベルのdns、policy、logはそれぞれ1つのオブジェクトだけを残し、重複キーによって前の設定が上書きされないようにしましょう。
構文を確認した後は、リクエストの流れを1つ追ってみましょう。アプリは正しいinboundに接続しているか、入口のタグは何か、リクエストにはドメイン名とIPのどちらが含まれているか、最初に一致したルールは何か、選択されたoutboundタグは存在するか、リモート接続の設定はそろっているかを確認します。この手順で、「設定は起動できるがアクセスの挙動が違う」といった問題を多く見つけられます。テストが意図しない直結で成功していないか、デフォルトの出口も必ず確認してください。
クライアントで読み込み結果を確認する
v2rayNでは、まず現在選択されている設定、カーネルの種類、ルーティングモードを確認してからログ画面を見ます。v2rayNGでは、選択中の設定、VPNの許可、サービスの状態を確認してください。メニュー名はクライアントの更新で変わる場合があるため、実際の画面を基準にします。カスタム設定と通常のノード編集では管理方法が異なることがあります。変更後は該当サービスを再起動し、ログで読み込まれているのが編集した設定か、別の設定項目ではないかを確認してください。
一時的にログレベルをinfoへ上げると、接続先や出口を確認しやすくなります。トラブル対処が終わったらwarningに戻し、長期間記録される内容を減らしましょう。設定ファイルの解析に失敗した場合、ファイル内のログ設定は反映されないことがあります。その場合はクライアントに表示される起動ログを確認してください。ログファイルが作成されないからといって、カーネルの起動が試みられていないとは限りません。
"log": {
"loglevel": "info"
}
宛先を固定してローカルの入口を確認する
デスクトップで利用可能なコマンドラインのリクエストツールがあれば、ローカルプロキシを明示的に指定し、システムプロキシ設定の影響を切り分けられます。以下の2つのコマンドは、それぞれSOCKSとHTTPの入口をテストするもので、2章のポートに対応しています。SOCKSのコマンドはドメイン名をプロキシ側の処理に渡し、HTTPのコマンドは同じ説明用サイトへローカルHTTPプロキシ経由でアクセスします。通信が指定した入口を通るか確認するためのもので、速度測定には使えません。
curl --proxy socks5h://127.0.0.1:10808 https://example.org/
curl --proxy http://127.0.0.1:10809 https://example.org/
コマンドでローカル接続が拒否された場合は、まず待ち受けポートとサービスの状態を確認します。カーネルまでリクエストが届いてリモート側でタイムアウトする場合は、出口とネットワークを調べてください。コマンドは成功するのにブラウザーでは失敗する場合は、ブラウザー拡張、独自のプロキシ設定、DNSの動作を確認します。Androidではブラウザーと宛先を固定して再現テストを行い、v2rayNGのログとアプリごとの設定を確認してください。デスクトップのコマンドをそのまま使うために、追加ツールをインストールする必要はありません。
エラーの種類から原因を絞り込む
| 症状 | まず確認する項目 | 次に行うこと |
|---|---|---|
| JSONを読み込めない | 引用符、カンマ、括弧、階層 | 直近で変更したオブジェクトを確認する |
| 待ち受けに失敗する | ポートの競合とアドレスの権限 | 競合するプログラムを終了するか、ポートを変更する |
| 集合データが見つからない | データファイルと集合名 | 読み込み先のパスとルール名の綴りを確認する |
| ハンドシェイクまたは認証に失敗する | トランスポート、セキュリティ、ユーザー設定 | 失敗した段階に沿って項目を照合する |
| 一部のアプリだけ失敗する | プロキシの入口と通信の取り込み範囲 | 明示的なプロキシ設定とシステム設定を比較する |
ログの最後の行は、それ以前の失敗による結果にすぎない場合があります。たとえば接続終了の原因が、その前に発生した名前解決や認証のエラーであることもあります。同じ試行の前後関係を残し、末尾だけでなく最初に明確なエラーが出た箇所から読み進めてください。共有する際は、ユーザー識別子、パスワード、サブスクリプションURL、アクセス先を置き換え、項目名、エラーの種類、必要な構造だけを残します。起動エラーの詳しい分析はv2rayNGのカーネルログの読み方をご覧ください。
変更ごとに復元用の状態を残す
安全に進めるには、まず基準設定の起動を確認し、リモートoutboundを追加して単一の接続を検証してから、ルーティング、DNS、policyを追加します。各段階で設定のコピーを保存し、変更の目的も記録してください。問題が起きたら直近の動作する設定に戻し、端末とネットワークが正常であることを確認してから、失敗した変更だけを再適用します。これにより、環境の変化と設定の問題を切り分けやすくなり、すでに崩れた設定へ修正を重ねる事態も避けられます。
日常的に管理する設定は、できるだけクライアントから編集できる場所に戻し、サブスクリプション更新後に何が保持され、何が再生成されるか確認してください。このガイドは設定同士の関係を理解するためのもので、毎回JSONをすべて手書きする必要はありません。読み込みと接続の手順を確認したい場合はクイックスタートガイドへ戻り、OSに合ったプログラムを選ぶ場合はクライアント一覧をご利用ください。