V2Rayの設定ファイルを解説|config.jsonのinbounds・outbounds・routingの読み方

config.jsonを使い、inboundsの待ち受け、outboundsのtag、routingルールの判定順と、tagによる連携をわかりやすく解説します。

この記事の概要

ノードのインポートはできるものの、各設定項目の役割がわからない方に向けた解説です。ローカル待ち受け、直接接続、ブロックだけを含む設定例で通信の流れを確認し、ポート、tag、ルールの順序を解説します。最後に実際のプロキシ出力の追加方法と、v2rayNが一時生成したファイルを編集して上書きされるのを避ける方法も紹介します。

1. config.jsonで通信が流れる仕組み

config.jsonはV2Rayコアが読み込む設定ファイルです。サブスクリプションURLやクライアントの設定ファイルとは異なります。サブスクリプションには通常ノード情報が含まれ、クライアントはノード、ルーティング、ローカルの待ち受け設定をもとにコア用の設定を生成します。この関係を理解すると、ノード編集、ルーティング設定、カスタム設定のどこを変更すべきか判断しやすくなります。

アプリからのリクエスト inboundで受信 ルーティング判定 outboundで接続 接続先サービス

inboundsは「リクエストの入口」、outboundsは「リクエストの出口」、routingは「どの出口を使うか」を決めます。ルーティングが処理するには、まずブラウザーからローカルのプロキシポートへリクエストを送る必要があります。ルーティングだけ変更しても、すべてのアプリが自動的にプロキシを使うわけではありません。

この記事では、V2Rayで一般的なJSON設定の構造を扱います。V2FlyとXrayには共通のフィールドがありますが、対応プロトコルや設定項目、コマンドライン引数は実際に使うコアごとに確認してください。v2rayNGはXrayコア、v2flyNGはV2Flyコアを使用します。デスクトップ版v2rayNでは、クライアント名だけで判断せず、現在の設定がどのコアを呼び出しているか確認してください。

2. 設定例:2つのinbound、直接接続、ブロック

以下は設定全体の構成を示す例です。SOCKSは127.0.0.1:10808、HTTPは127.0.0.1:10809で待ち受けます。例示用ドメインexample.orgとそのサブドメインへのアクセスはブロックし、それ以外は既定で直接接続します。リモートプロキシノードは含まれていないため、リモートプロキシとして使えるノード設定ではありません。

{
  "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": "blocked",
      "protocol": "blackhole",
      "settings": {}
    }
  ],
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "domain": [
          "domain:example.org"
        ],
        "outboundTag": "blocked"
      },
      {
        "type": "field",
        "ip": [
          "10.0.0.0/8",
          "172.16.0.0/12",
          "192.168.0.0/16",
          "127.0.0.0/8",
          "::1/128"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "inboundTag": [
          "http-in"
        ],
        "outboundTag": "direct"
      }
    ]
  }
}

これは厳密なJSONです。キー名と文字列は二重引用符で囲み、コメントや末尾の余分なカンマはありません。配列には複数のオブジェクトを含められますが、各オブジェクトは対応するプロトコルのフィールド定義に従う必要があります。画面に表示される「ノード名」をそのままコアの設定キーとして使ったり、トップレベルにsubscriptionフィールドを追加したりしないでください。サブスクリプションの管理はクライアントの機能です。

3. inbounds:待ち受けアドレス、ポート、inbound tag

listenはローカルでバインドするアドレスで、リモートノードのアドレスではありません。portはアプリが接続するローカルポートで、サーバー側のポートではありません。待ち受けアドレスを127.0.0.1にすると、ローカルのIPv4ループバック接続だけを受け付けます。すべてのネットワークインターフェースで待ち受けるとアクセス可能な範囲が広がり、LAN内のアクセス制御にも関わるため、接続できない場合の一般的な解決策として使わないでください。

SOCKS inbound

protocol
socks
listen
127.0.0.1
port
10808
tag
socks-in

アプリ側でSOCKSを使う必要があります。UDP通信にはアプリと後続のoutboundも対応している必要があります。

HTTP inbound

protocol
http
listen
127.0.0.1
port
10809
tag
http-in

HTTPSの接続先には通常CONNECTトンネルでアクセスするため、inboundプロトコルをhttpsに変更する必要はありません。

tagは設定内で使う識別子です。inboundのsocks-inはルーティングルールからinboundTagで参照できます。tagはプロトコルを決めるものでも、同名のoutboundを自動生成するものでもありません。inboundとoutboundにはそれぞれ一意で変更しにくいtagを付け、名前を変更した場合はすべての参照先も確認してください。

例にあるudp: trueは、SOCKS inboundでUDPを許可する設定です。アプリがSOCKS UDP ASSOCIATEに対応し、outboundもその通信を運べる必要があります。この項目を有効にしても、システム上のすべてのUDP通信がコアを経由するわけではありません。また、一般的なHTTPシステムプロキシでゲームの通信を取り込めるわけでもありません。

4. outbounds:プロトコルと既定の出口

例ではfreedomが直接接続、blackholeがブロックを表します。directとblockedは任意に付けたtagです。directをoffice-directに変更しても動作は変わりませんが、これを参照するすべてのoutboundTagも変更する必要があります。

項目または場所設定例実際の動作
protocolfreedom直接接続に使うoutboundの実装を選択
tagdirectルーティングルールから参照する識別子
settings{}outboundプロトコルの設定オブジェクト
配列の先頭要素directどのルールにも一致しない場合に使う既定のoutbound

通常のルーティングルールに一致しない場合、コアはoutbounds配列の先頭要素を使います。この例では直接接続を先頭に置いているため、ブロックルールにも特定のinboundルールにも一致しない通信は直接接続します。ブロック用outboundを先頭に移すと、一致しない通信の多くがブロックされます。これは「ノードが突然使えなくなった」のではなく、既定の出口が変わったためです。

確認の順序:まず既定の出口、次に例外ルール

設定を確認するときは、まずoutbounds[0].tagを確認し、次にrouting.rulesを上から順に見てください。どのルールにも一致しない通信の行き先を先に把握できるため、特定のドメインルールだけを見て全体の動作を見落とすのを防げます。

5. routing:ルールの判定順、条件の組み合わせ、ドメイン解決

routing.rulesは配列の上から順に評価され、最初に一致したルールで出口が決まります。後続の「より詳細な」ルールを探し続けることはありません。一般に、具体的な例外を先に、対象範囲の広いルールを後に置きます。最初のルールがすべてのTCP・UDP通信に一致する場合、後続のドメインルールは適用されません。

  1. まず接続先ドメインを確認します。リクエストの宛先がexample.orgまたはそのサブドメインなら、最初のルールでblockedが選ばれます。domain:は指定したドメインとそのサブドメインに一致します。ドメイン名全体だけに一致させる場合はfull:を使います。
  2. 次に接続先IPアドレスを確認します。例にあるプライベートアドレスとループバックアドレスはdirectで接続します。これはIPアドレス範囲に対するルールであり、ドメインが最終的にプライベートIPへ解決されるだけで必ず適用されるわけではありません。
  3. 次に送信元inboundを確認します。3つ目のルールはhttp-inからのリクエストに一致し、直接接続を選択します。ただし、先にドメインのブロックルールに一致したリクエストには適用されません。
  4. 最後に既定のoutboundを使います。socks-inからのリクエストが前の2つのルールに一致しない場合、配列の先頭にあるdirectが使われます。

同じルール内の異なる条件フィールドは、通常すべて満たす必要があります。たとえばinboundTagとdomainを両方指定すると、特定のinboundからの特定ドメイン宛ての通信に一致します。一方、同じドメイン配列内の複数の項目は候補条件です。「または」の条件を、複数の条件フィールドを含む1つのルールで表そうとするのは、ルーティングが機能しないよくある原因です。

domainStrategyはrouting内に置き、ルーティング判定でドメインをどのように扱うかを設定します。AsIsはIPルールとの照合を目的としたドメインの名前解決を行いません。IPIfNonMatchはドメインルールに一致しない場合に名前解決を試み、その後IPルールと照合します。IPOnDemandはIP情報が必要なルールの判定時に名前解決を行います。「すべてのDNS通信をプロキシ経由にする」設定ではありません。

6. プロキシoutboundの追加:接続先を確認してから参照を変更

リモートプロキシを使うには、実際のサーバー設定が必要です。VMessやVLESSなどのoutboundでは、アドレス、ポート、認証情報、トランスポートとセキュリティの設定をサーバーと一致させる必要があります。protocolの名前だけを変更しても、プロトコルを切り替えたことにはなりません。既存のノードは、異なるコアの設定項目を手作業で組み合わせるのを避け、クライアントからインポートして生成された設定を確認してください。

「outboundを追加して参照する」手順だけを説明するため、ここではローカルのSOCKS上流を使います。別のサービスが実際に127.0.0.1:10810で待ち受け、認証を要求しないことが前提です。このオブジェクトはoutbounds配列に追加します。設定の一部分であり、単独で使える完全なファイルではありません。

{
  "tag": "proxy",
  "protocol": "socks",
  "settings": {
    "servers": [
      {
        "address": "127.0.0.1",
        "port": 10810
      }
    ]
  }
}

7. 設定の検証とv2rayNでの保存場所

検証は、JSONとして解析できるか、コアが設定項目を受け付けるか、実際のリクエストがルールどおりに処理されるかの3段階に分かれます。それぞれは別の確認です。書式が正しくても参照先のtagが存在するとは限らず、コアが起動してもシステムプロキシが正しいポートを指しているとは限りません。

  1. 元のファイルをバックアップします。正常に起動するコピーを残し、ポートだけ、またはルーティングだけというように、一度に1種類の項目を変更すると、問題発生時に戻しやすくなります。
  2. 実行するコアに合わせて確認します。まず同梱されたコアのヘルプコマンドを実行し、そのバージョンで設定をテストする方法を確認してください。テストツールは実際に使うコアと同じものを使います。別の種類のコアによる検査結果で代用しないでください。
  3. 起動ログを確認します。待ち受けに失敗したというログがあれば、まずアドレスやポートを確認します。設定の読み込みに失敗した場合は、フィールドの型やプロトコル設定を確認してください。問題の切り分け中はloglevelを一時的にinfoへ変更し、確認後に元へ戻せます。
  4. 目的を絞った2種類のリクエストを送ります。まず直接接続を確認し、次にブロックルールを検証します。テストではポートを明示し、他のアプリのプロキシ設定が影響しないようにしてください。
curl --proxy socks5h://127.0.0.1:10808 --connect-timeout 5 https://example.com/
curl --proxy socks5h://127.0.0.1:10808 --connect-timeout 5 https://example.org/
curl --proxy http://127.0.0.1:10809 --connect-timeout 5 https://example.com/

socks5hは接続先のホスト名をプロキシ側で処理するため、この例のドメインルールを確認するのに適しています。インターネットから到達可能な場合、1つ目と3つ目のリクエストは直接接続でアクセスを試み、2つ目はブロックされます。エラーメッセージはコアとcurlのバージョンによって異なります。エラーコードだけで一致したルールを判断せず、ログも確認してください。Windowsでコマンドがターミナルのエイリアスに置き換えられる場合は、curl.exeを明示して実行します。

v2rayNでは、まず「設定」→「パラメーター設定」でローカルの待ち受けポートを確認し、続いて「設定」→「ルーティング設定」で有効なルーティング設定を確認します。バージョンによってグループ名や項目名が多少異なる場合があるため、現在の画面を確認してください。通常、ノードの実行時に使われる設定はクライアントが再生成します。ノードの切り替え、サブスクリプションの更新、コアの再起動後には、生成されたファイルへの直接の変更が上書きされることがあります。

保存場所:よく使うルールはクライアント設定に保存

ポートやルーティングルールを継続して使うには、クライアント側の該当設定を変更してください。JSON全体を細かく制御する場合は、クライアントのカスタム設定機能を使い、その設定がどのコアを呼び出すか確認します。画面上のルールと一時ファイルを別々に管理し、自動的に統合されると考えないでください。

8. よくある設定の疑問

ノードを選択したのに、なぜ例では直接接続になるのですか?

この例では最初のoutboundがfreedomで、リモートプロキシの設定はありません。クライアントでノードを選択しても、単独で実行するJSONが自動的に書き換わるわけではありません。実際に読み込まれているファイルを確認し、outbounds[0]と、一致したルールのoutboundTagを調べてください。

tagを変更したら、ルールが機能しなくなったのはなぜですか?

ファイル内で古いtagを検索し、outboundTagとinboundTagを1つずつ確認してください。参照先は対応するオブジェクトのtagと大文字・小文字も含めて完全に一致させる必要があります。変更後に再テストし、コアを再起動してください。テキストを保存しただけで、古いプロセスを使い続けないようにします。

システムプロキシを有効にしたのに、一部のアプリが10809を使わないのはなぜですか?

システムプロキシが適用されるのは、その設定に従うアプリだけです。まず上記のHTTPテストコマンドで待ち受けを確認し、アプリに個別のプロキシ設定があるか調べてください。アプリがプロキシを使っていない問題を解決するために待ち受けアドレスの範囲を広げないでください。この2つは別の問題です。

サブスクリプションの内容をそのままconfig.jsonに貼り付けられますか?

サブスクリプションのテキストをそのままコア用JSONとして使うことはできません。まずv2rayNのサブスクリプション管理からインポートして更新し、ノードのプロトコルが選択したコアに対応しているか確認してください。構造を調べる場合は、クライアントが生成した設定を確認し、共有する前にアドレスや認証情報を隠してください。

各項目の定義を確認するには、JSON設定ガイドで待ち受け、outbound、ルーティングの構造を参照できます。実際のトラブルシューティングも同じ順序で確認してください。アプリが接続しているか、inboundが待ち受けているか、ルールに一致するか、outboundが接続できるかを順に調べます。DNS、ポート、プロトコルを同時に変更するより、一度に1段階ずつ確認するほうが原因を特定しやすくなります。

v2rayNのダウンロード