設定ファイルは、まず通信の流れを追ってから個々の項目を確認しましょう。この記事ではローカル直結の例を使い、inbounds、outbounds、routing、ログの関係を解説します。ノードを読み込み済みで、ポートの競合やルーティングの不具合を調べたい方に向けた内容です。例にはリモートプロキシノードを含みません。クライアントが保存するノード情報と、コアが実行する設定の違いを把握し、順番に変更内容を検証できます。
1. V2Rayの設定構造:クライアントとコアを区別する
まず結論です。inboundsはリクエストの受け口、outboundsは接続先への接続方法、routingはリクエストをどのoutboundに渡すかを決めます。それぞれ独立した設定ではなく、一連の処理を構成する3つの要素です。
v2rayNはデスクトップ向けクライアントで、ノードの保存、サブスクリプションの管理、実行設定の生成、選択したコアの起動を行います。Android版のv2rayNGはXrayコア、v2flyNGはV2Flyコアを使用します。クライアント名が似ていても、対応する設定項目が完全に同じとは限りません。問題を調べる前に、ログやバージョン情報画面で実際に動作しているコアとバージョンを確認してください。
この記事では、一般的な従来形式のJSON設定を扱います。V2RayとXrayはこの形式の一部を共有していますが、各機能の対応状況はそれぞれのバージョンによって異なります。たとえばREALITYやxtls-rprx-visionは、Xrayの設定例にあるからといって、そのままV2Flyの設定に使えるわけではありません。共有リンクやサブスクリプションの内容も、実行用設定一式とは限りません。アドレスをJSONファイルに貼り付けただけでは、コアで実行できません。
2. inbounds:アドレス・ポート・プロトコルの役割
inboundはコアが通信を受け付ける入口で、リモートサーバーではありません。ブラウザーがローカルのSOCKSポートに接続すると、リクエストはいったんinboundに届き、その後コアがoutboundを選択します。ここではSOCKSの待ち受けポートを10808、HTTPの待ち受けポートを10809に設定します。これは説明用の値で、すべてのクライアントのデフォルト値ではありません。
SOCKS inbound
- listen
127.0.0.1- port
10808- protocol
socks- tag
socks-in
アプリではSOCKS5を選び、同じアドレスとポートを指定します。
HTTP inbound
- listen
127.0.0.1- port
10809- protocol
http- tag
http-in
HTTPプロキシはCONNECTでHTTPS接続を中継できます。HTTPサイトだけに使えるわけではありません。
listenは待ち受けアドレスです。127.0.0.1は同じ端末からの接続のみを受け付けます。0.0.0.0に変更すると、すべてのIPv4ネットワークインターフェースで待ち受けるため、同じネットワーク上の他の端末からプロキシの入口に接続できる可能性があります。ローカル端末だけで使う場合、問題の切り分けを目的に待ち受け範囲を広げないでください。
- ポートの競合:
address already in useやバインド失敗が発生した場合は、まず別のコアプロセスが同じアドレスとポートを使用していないか確認します。 - プロトコルの不一致:HTTPプロキシのリクエストをSOCKSの入口に送ると、ポートに接続できてもハンドシェイクで失敗することがあります。
- タグの役割:
tagは設定内で参照する名前です。パスワードではありませんが、後続のルーティング設定で参照するときは一字一句同じにする必要があります。 - UDPの範囲:SOCKSでUDPを許可しても、システム内のすべてのアプリのUDP通信が自動的にinboundへ送られるわけではありません。
3. outbounds:ノードの設定とデフォルトの出口
outboundは、コアが外部へ接続する方法を定義します。リモートプロキシでは通常、サーバーアドレス、ポート、ユーザー認証情報、通信方式やセキュリティの設定が必要です。directのoutboundは接続先へ直接接続します。この記事で扱う従来形式では、ルールに一致しないリクエストにはoutbounds配列の先頭要素が使われます。そのため、配列の順番も実際の通信経路に影響します。
| 項目またはプロトコル | 役割 | 確認ポイント |
|---|---|---|
tag | ルーティングルールからこのoutboundを参照する | outboundTagと完全に一致させる |
freedom | 接続先アドレスへ直接接続する | directを意味し、リモートプロキシではない |
blackhole | 渡された通信を破棄する | 意図しないルールに一致していないか確認する |
settings | プロトコルに対応するパラメーターを設定する | 設定の構造はoutboundのプロトコルによって異なる |
streamSettings | 通信方式と通信のセキュリティを設定する | サーバー側の設定と一致させる |
VMess、VLESS、Trojan、Shadowsocksでは、同じsettingsを共用できません。同じ「ポート」という項目でも、ローカルの待ち受けポートとリモートサーバーのポートを区別してください。前者はアプリからローカル端末へ接続するためのもの、後者はコアからサーバーへ接続するためのものです。一方を変更しても、もう一方の問題は解決しません。
VMessを例にすると、ユーザー情報はプロトコルで定められたユーザー配列に記述します。TLSは通信のセキュリティ設定に属します。WebSocketのパス、TLSのサーバー名、接続先アドレスは、それぞれ異なる場合があります。サブスクリプションを読み込んでも接続できない場合は、項目名をすべてサーバーアドレスに置き換えるのではなく、サービス提供元の案内と一つずつ照合してください。
ポイント:デフォルトのoutboundを確認してからルールを調べる
どのルールにも一致しないリクエストが直接接続される場合は、配列の先頭がfreedomになっていないか確認してください。ルールのプロキシ用タグだけを変更して、デフォルトの出口がdirectのままになっている状態を見落とさないようにしましょう。
4. routing:ルールの順序とドメイン解決のタイミング
ルーティングは「より細かく見える」ルールを自動で選ぶのではなく、設定順に照合し、最初に一致したルールの出口を使います。範囲の広いルールを先に置くと、後続の詳細なルールが適用されないことがあります。同じルールにinbound、ドメイン、ポートなど複数の条件を指定した場合、通常はすべての条件を満たす必要があります。
{
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": ["full:example.invalid"],
"outboundTag": "block"
},
{
"type": "field",
"inboundTag": ["socks-in", "http-in"],
"outboundTag": "direct"
}
]
}
このルールはまず、example.invalidという完全一致のドメインをblockへ送り、続いて2つのローカル入口から来たその他のリクエストをdirectへ送ります。このドメインはマッチング構文の説明用で、利用可能なリモートサービスのアドレスではありません。full:はドメイン全体との完全一致を表します。domain:は指定したドメインとそのサブドメインに一致するため、両者を混同しないでください。
- AsIs:ルーティング時に宛先の形式を維持し、IPルールのためのドメイン解決は行いません。接続時にはdirectのoutboundがドメインを解決する場合があります。
- IPIfNonMatch:ドメインルールに一致しなかった場合、ドメインを解決してIPルールとの照合を続けます。
- IPOnDemand:照合にIP条件の確認が必要な場合、ドメイン解決を行います。
ドメインルールが機能するかどうかは、inboundがどの情報を受け取るかにも左右されます。アプリが宛先をIPアドレスに解決してからプロキシへ渡すと、コアが元のドメインを把握できないことがあります。スニッフィングで一部のプロトコル通信からドメインの手がかりを取得できますが、あらゆるリクエストに有効な対策ではなく、DNSルーティングを設定したことにもなりません。
5. JSON設定の全体例:2つのinbound、direct、block
以下は従来形式の設定全体の例で、構造のみを示しており、リモートプロキシ機能はありません。ローカルの2つのポートで待ち受け、デフォルトでは直接接続し、例示用のドメインを1つブロックします。すでにクライアントがこれらのポートを使っている場合は、設定の構文エラーとポート競合を混同しないよう、該当プロセスを停止するか未使用のポートに変更してください。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"tag": "http-in",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": ["full:example.invalid"],
"outboundTag": "block"
},
{
"type": "field",
"inboundTag": ["socks-in", "http-in"],
"outboundTag": "direct"
}
]
}
}
項目の参照先を逆にたどると、設定を読み解きやすくなります。outboundTag: "block"を見つけたら、outbounds配列からtag: "block"を探します。inboundTagを見つけたら、inbounds配列に戻って名前を確認してください。タグを設定内の接続線と考えると、項目を一つずつ暗記するより問題を見つけやすくなります。
- プレーンテキストに対応したエディターで
config.jsonとして保存し、リッチテキスト形式で保存されていないことを確認してください。 - オブジェクトのキー名と文字列には半角のダブルクォートを使い、数値のポートを単位付きの文字列にしないでください。
- 配列やオブジェクトの最後の要素の後にカンマは付けません。この例は標準JSON形式で記述しており、コメントも含みません。
- まずコアで設定をテストし、その後に待ち受けを開始してください。構文テストに通っても、リモートサービスへの接続が保証されるわけではありません。
6. ログとクライアント画面:症状から設定箇所を特定する
logはログ出力を制御します。一般的なloglevelにはdebug、info、warning、error、noneがあります。通常はwarningのままにし、問題の切り分け時だけ一時的にinfoまたはdebugへ上げてください。調査後は元に戻し、アクセスの詳細が記録され続けないようにします。
| 設定箇所 | 画面で確認する場所 | 確認する内容 |
|---|---|---|
inbounds | v2rayNの「設定」→「パラメーター設定」にあるローカル待ち受け関連の項目 | ポート、待ち受け範囲、inboundのプロトコル |
outbounds | ノード一覧で現在のノードを編集 | リモートアドレス、ポート、ユーザー情報、通信方式とセキュリティの設定 |
routing | 現在のルーティング設定とルールの編集画面 | ルールの順序、宛先outbound、設定の有効・無効 |
log | ログレベルの設定と実行ログの画面 | 起動失敗のメッセージと発生時刻 |
クライアントのバージョンによってメニュー名が変わることがあります。この表は項目の対応関係を示すもので、すべてのバージョンで同じ階層にあるとは限りません。Androidでは、VPNによる通信の取り込みとローカルプロキシの待ち受けを区別してください。v2rayNGとv2flyNGはシステムのVPN機能で通信を受け取れるため、デスクトップのシステムプロキシと同じ考え方をそのまま当てはめることはできません。
デスクトップでシステムプロキシを有効にすると、システムプロキシ設定に従うアプリに指定の入口を使うよう通知されますが、すべてのアプリの通信がコアを通るとは限りません。ログにアプリの接続記録がまったくない場合は、リモートノードを変更する前に、通信がinboundへ届いているか確認してください。通信の取り込み方法は使い方ガイドを、接続の問題は接続トラブルの解説を参照してください。
- 起動直後に終了する
- まずJSONの解析エラー、未対応の項目、ポートのバインド失敗、データリソースの不足を確認してください。
- ローカルポートには接続できるが、通信できない
- ルーティング、リモート接続、認証、TLSハンドシェイク、DNS解決を確認してください。「ポートが開いている」ことと「プロキシが使える」ことは同じではありません。
- 一部のサイトだけで問題が起きる
- 該当するドメインと時刻を記録し、blockまたはdirectのルールに一致していないか確認してから、同じノードでの結果を比較してください。
7. 設定の検証手順:一度に変更するのは1項目だけ
コマンドラインでのテストは、コアが設定を受け付けるか確認するのに役立ちます。以下はV2Ray 5.xとXrayで一般的なコマンド形式です。実際に使っているコアに合う方だけを実行し、実行ファイルのパスと現在の作業ディレクトリを確認してください。バージョンが異なる場合は、まずプログラムのヘルプを確認します。
v2ray test -c config.json
xray run -test -config config.json
このテストでは実際のリクエストを検証できず、アカウント、サーバー、ネットワーク経路が正常であることも確認できません。テストに通ったら、「コアを起動する、待ち受けを確認する、リクエストを送る、出口を確認する」の順に進めてください。同じ宛先と接続方法を使ってテストすれば、どの変更が結果に影響したか判断しやすくなります。
- 実際に使われているファイルを確認:起動引数がどの設定ファイルを参照しているか確認します。バックアップを編集しただけで、別のファイルが実行されている事態を防げます。
- 構文と項目を確認:現在使用しているコアで設定をテストします。失敗した場合は、まず最初に表示された明確なエラーを修正してください。後続のメッセージは連鎖的に発生した可能性があります。
- 入口を確認:アプリのプロキシ種別とポートを確認し、リクエストが想定したinboundに届いていることを確かめます。
- ルールを確認:タグの参照先とルールの順序を確認します。必要なら一時的に出口を1つに絞り、結果を比較してください。
- リモート接続先を確認:実際のプロキシ設定に戻したうえで、サーバーアドレス、認証情報、通信のセキュリティ設定を確認します。
- 通常の設定に戻す:一時的に広げた待ち受け範囲とログレベルを元に戻し、再現可能な変更内容を記録して保存します。
ポイント:リクエストがinboundに届くことを確認してから、リモート接続を調べる
inboundの記録がない場合は、まずアプリの接続方法と待ち受け設定を修正します。inboundに届いているのに出口が違う場合は、ルーティングを確認してください。処理の流れに沿って段階的に調べると、ポート、プロトコル、ノードを一度に変更するより原因を特定しやすくなります。