V2Ray config.jsonの設定項目を解説|inbounds・outbounds・routingの読み方

V2Rayの設定ファイルをlog、inbounds、outbounds、routing、dnsの順に解説。各項目の役割と、outboundTagでルールと出口を結び付ける仕組みがわかります。

この記事の概要

クライアントが生成した設定を読み解き、ポートやルーティングの問題を調べたい方向けの記事です。まず、ローカルのinbound、直結・ブロック用outboundを含む設定例で各項目の対応関係を確認し、その後、リモートプロキシやルールの順序、DNSの扱いを解説します。設定例は構造の検証用で、接続可能なリモートプロキシノードは含みません。読み終えると、リクエストの入口、適用されるルール、最終的な出口を判断できるようになります。

1. config.jsonのトップレベル構造とリクエストの流れ

config.jsonは一般的な設定ファイル名であり、固定された名称ではありません。実際に読み込むファイルは、カーネルの起動引数で決まります。この記事では、V2Rayで従来から使われているJSON設定形式を扱います。V2RayとXrayには共通する項目もありますが、拡張機能やバージョンごとの対応状況は異なります。一方のカーネルで使える新しい項目を、もう一方にそのままコピーしないでください。

アプリからのリクエスト ローカルinbound ルール判定 outbound処理 接続先

inboundsはアプリからの通信を受け取り、outboundsは接続方法を定義します。routingは使用するoutboundを決定します。logは実行状況を記録し、dnsは内蔵リゾルバーを設定します。JSONオブジェクト内でこれらのトップレベルキーを記述する順番は、通常、実行結果に影響しません。一方、ルール配列の順序は判定結果を左右します。

トップレベル項目データ型まず確認すること
logオブジェクト起動エラーやアクセス記録を確認できるか
inbounds配列アプリ接続のプロトコル、アドレス、ポートが一致しているか
outbounds配列outboundのプロトコルとパラメーターがそろっているか
routingオブジェクトルールの順序とoutboundタグが対応しているか
dnsオブジェクトどの処理で内蔵リゾルバーが実際に使われるか

以下の設定は、単独で動かすカーネルの構造テストに使えます。ローカルの2つのポートで待ち受け、example.orgとそのサブドメインへの通信をブロックし、それ以外のリクエストはデフォルトで直結します。リモートのプロキシサーバーへ通信を転送する設定や、システムプロキシを自動で有効にする設定は含まれていません。

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": false
      }
    },
    {
      "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": ["domain:example.org"],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      }
    ]
  },
  "dns": {
    "servers": ["1.1.1.1"]
  }
}

2. log:設定エラーを特定しやすくする

loglevelには、debug、info、warning、error、noneなどを指定できます。例では、通常時のログを抑えられるwarningを使用しています。起動や接続の問題を調べるときは、一時的にinfoへ変更してください。より詳細な内部ログが必要な場合は、debugを使います。

{
  "log": {
    "access": "access.log",
    "error": "error.log",
    "loglevel": "info"
  }
}

これはトップレベルの設定例です。完全な設定のlogを置き換えてください。同じキーを重複して追加するものではありません。相対パスで指定したログの保存先は、プロセスの作業ディレクトリを基準に解釈されるため、設定ファイルと同じ場所になるとは限りません。クライアントからカーネルを起動する場合、作業ディレクトリや書き込み権限、ログの表示方法はクライアントによって異なることがあります。まずはクライアントの実行ログを確認してください。

3. inbounds:待受アドレス、ポート、プロキシプロトコル

inboundsは配列で、複数の入口を同時に設定できます。各inboundのprotocolは、アプリから届くデータの解釈方法を決めます。SOCKSとHTTPプロキシは別のプロトコルです。どちらもローカルで待ち受けていても、アプリ側で種類を間違えると接続に失敗することがあります。

10808
この記事のSOCKS inboundポート
10809
この記事のHTTP inboundポート
2
この記事で設定するローカルinbound数

ここで指定しているポートは、この記事の例で明示した値です。すべてのバージョンやクライアントのデフォルト値ではありません。アプリにHTTPプロキシを設定する場合は、アドレスに127.0.0.1、ポートに10809を指定します。SOCKS5プロキシの場合は、127.0.0.1:10808を指定してください。

SOCKSのローカル入口

タグ
socks-in
待受
127.0.0.1:10808
プロトコル
socks
認証
noauth
UDP
false

ここではローカルマシンからのTCPリクエストのみを扱い、SOCKSのUDP転送は有効にしていません。

HTTPのローカル入口

タグ
http-in
待受
127.0.0.1:10809
プロトコル
http
設定
{}

HTTPプロキシに対応したアプリで使用します。HTTPSリクエストは通常、CONNECTでトンネルを確立します。

listenにループバックアドレスを指定すると、接続できるのは同じマシン上からのみです。0.0.0.0に変更すると、すべてのIPv4インターフェースで待ち受けるため、LAN内のほかの端末から接続できる可能性があります。共有する場合は、待受アドレスを変えるだけでなく、認証、ファイアウォール、アクセス範囲も適切に設定してください。

4. outbounds:プロトコルとタグの対応関係

outboundsは、カーネルから外部へ通信する方法を定義します。例のfreedomは直結用、blackholeはブロック用のoutboundです。directとblockは任意に付けたタグにすぎません。タグ自体に機能はなく、実際の動作はprotocolと関連設定によって決まります。

outboundタグプロトコルこの記事での動作
directfreedom接続先へ直接接続。ルールに一致しない通信のデフォルトoutboundとしても使用
blockblackhole一致したリクエストをブロックし、リモートプロキシには接続しない
proxy実際に使用するノードによって決まるこの記事では未定義。完全なプロキシoutboundを追加してから参照する

この形式の設定では、ルーティングルールに一致しないリクエストは、outbounds配列の先頭にあるoutboundを使用します。この記事ではdirectを先頭に置いているため、デフォルトでは直結します。先頭を実際のプロキシoutboundに変更すると、ルールに一致しない通信の経路も変わります。

VMessまたはVLESSのoutboundには、実際のサーバーアドレス、ポート、ユーザーIDに加え、サーバー側と一致する通信方式やセキュリティ設定が必要です。WebSocketのパスやTLSのサーバー名などは、プロトコル名だけから判断できません。Xray独自の拡張機能を使う場合は、カーネルの対応状況も確認してください。すべてのVLESS設定が汎用的なV2Ray設定として使えるわけではありません。

まずタグを確認してから、ノードのパラメーターを調整

各ルールのoutboundTagとoutboundのtagを一字ずつ照合し、先頭のoutboundがデフォルトの通信方針に合っていることを確認してください。この2点を確認してから、サーバーや通信設定を調べます。

5. routing:ルールの順序とoutboundTag

routing.rulesは配列の先頭から順に評価され、一致したルールで指定されたoutboundが使われます。対象範囲の広いルールを先に置くと、後続の細かいルールが評価されないことがあります。同じルール内に複数の条件項目がある場合は通常すべての条件を満たす必要がありますが、同じ項目の配列に複数の候補がある場合は、通常いずれかに一致すれば対象になります。

{
  "type": "field",
  "inboundTag": ["http-in"],
  "domain": ["domain:example.org"],
  "outboundTag": "block"
}

上の例では、複数の条件を組み合わせています。リクエストの送信元がhttp-inで、接続先のドメインがexample.orgまたはそのサブドメインに一致する場合に限り、blockへ送られます。ドメインを完全一致で指定する場合は、サブドメインにも一致する指定ではなくfull:example.orgを使います。

  1. まず、この記事のdirectやblockのように、実際に設定されているoutboundタグを一覧にします。
  2. 優先して処理したい対象が明確なルールを先に置き、その後に広い範囲を対象とするルールを追加します。
  3. 各ルールのoutboundTagを照合します。スペル、大文字・小文字、ハイフンまでoutboundタグと一致させてください。
  4. inboundが受け取った接続先情報がドメイン名かIPアドレスか確認します。接続先情報によって、一致するルールが異なる場合があります。
  5. ルールに一致しない通信は先頭のoutboundへ送られます。「一致しない」からといって自動的にブロックされるわけではありません。
domainStrategyルーティングの処理方法使用時の注意点
AsIs現在の接続先情報を使い、ルーティング判定のためにドメイン名を積極的に名前解決しない接続先がもともとIPアドレスなら、IPルールに一致する場合がある
IPIfNonMatchドメイン名がルールに一致しない場合は、名前解決してからIPルールとの一致を試みる追加の名前解決が発生する場合があり、結果はDNSが返すアドレスに左右される
IPOnDemandIPアドレスによる判定が必要なルールに達したときに名前解決する名前解決されるタイミングはルールの順序と合わせて確認する

この記事ではAsIsを使っています。そのため、アプリがプライベートIPアドレスを送信した場合はgeoip:privateに一致します。一方、最終的にプライベートIPアドレスへ解決されるドメイン名をアプリが送信した場合、このIPルールには一致しないことがあります。ルーティング時に積極的な名前解決をしない設定でも、実際の接続時に名前解決が不要とは限りません。

6. dns:内蔵リゾルバーとシステムDNSの違い

dns.serversでは、カーネルの内蔵リゾルバーが使用するDNSサーバーを指定します。例にある1.1.1.1は従来型DNSのアドレスであり、暗号化DNSを有効にするものではありません。また、現在のネットワークから到達できるとは限りません。実際のネットワーク環境に合った名前解決方法を選び、問い合わせ先のDNSサーバーまでリクエストが届くことを確認してください。

たとえば、直結outboundから内蔵DNSを使ってIPv4アドレスを取得するには、カーネルが対応していることを確認したうえで、次のようにoutboundの設定を変更します。これはoutboundの設定であり、ルーティングの設定ではありません。どちらにもdomainStrategyがありますが、適用範囲は異なります。

{
  "tag": "direct",
  "protocol": "freedom",
  "settings": {
    "domainStrategy": "UseIPv4"
  }
}

7. 設定の検証とクライアント利用時の注意

まず構文を確認し、次に待受を開始して、最後にリクエストの経路を検証します。通常のJSONではコメントや末尾のカンマは使えません。設定例をコピーする際は対応するオブジェクトを置き換え、同じトップレベルキーが重複しないようにしてください。特定のローダーで拡張構文を使えても、ほかのカーネルやクライアントでも使えるとは限りません。

  1. 元の設定をバックアップし、編集しているファイルが実際に読み込まれているものか確認します。
  2. 使用中のカーネルに付属する設定テストコマンドを使い、まず項目エラーやリソースファイルのエラーを解消します。
  3. 10808と10809を使用しているプロセスを停止してから、テスト用カーネルを起動します。
  4. システムプロキシが有効かどうかに頼らず、プロキシのポートを明示してリクエストを送信します。
  5. ブロック対象のドメインと通常の接続先への結果を確認し、問題がなければ実際のプロキシoutboundや複雑なルールを一つずつ追加します。

V2Ray 5系では、従来のJSON設定を次のコマンドでテストできます。実行ファイルの場所は配布パッケージによって異なる場合があります。まずv2ray helpを実行して、利用できるサブコマンドを確認してください。旧バージョンの-test -config形式と、新しいサブコマンドを混同しないようにしましょう。

v2ray test -c config.json
v2ray run -c config.json

カーネルが正常に起動したら、プロキシ経由のリクエストに対応したツールで通信経路を確認できます。次の2つのコマンドは、どちらもこの記事でブロック対象にしたドメインへリクエストを送信します。失敗するか接続が切断されれば、ルールが適用されたと判断できます。これはルールの動作確認であり、接続成功を確かめるテストではありません。2つ目のコマンドで使うsocks5hは、ドメイン名をプロキシ側へ渡すため、ドメイン名によるルール判定に役立ちます。

curl --max-time 10 --proxy http://127.0.0.1:10809 http://example.org/
curl --max-time 10 --proxy socks5h://127.0.0.1:10808 http://example.org/

v2rayNは、ノード、ルーティング、設定に応じてカーネルの実行設定を生成するデスクトップクライアントです。生成されたファイルは、ノードの切り替えや再起動時に上書きされることがあります。v2rayNGはXrayカーネル、v2flyNGはV2Flyカーネルを使用します。実行設定を読むと共通する項目の理解に役立ちますが、カスタムJSONを読み込めるか、画面上の設定と併用できるかは、各クライアントのバージョンによって異なります。

config.jsonを編集しても、クライアントの通信経路が変わらないのはなぜですか?

まず、過去にエクスポートしたファイルではなく、現在のプロセスが実際に読み込んでいるファイルを編集したか確認します。次に、クライアントが設定を再生成していないか、カーネルが再起動されたか、アプリの通信が対象のinboundを経由しているかを確認してください。サブスクリプション内のノード設定、クライアントのルーティングプリセット、カーネル全体の設定はそれぞれ別のレイヤーです。一つを変更しても、ほかのレイヤーが変わるとは限りません。

設定テストに通れば、プロキシノードも必ず使えますか?

設定テストで確認できるのは、主に設定を読み込めるかどうかです。リモートサーバーが稼働中か、ユーザーID、通信経路、TLS設定がサーバー側と一致しているかまでは確認できません。この記事の例にはリモートプロキシoutboundがありません。ノードの動作を検証するには、必要な設定を含むoutboundを追加し、実際にリクエストを送って接続結果を確認してください。

ドメインによるルーティングだけが機能しない場合、何から確認すればよいですか?

まず、アプリからinboundへ渡された接続先がドメイン名か、名前解決済みのIPアドレスか確認します。次に、domain:とfull:の一致範囲、ルールの順序、domainStrategyを確認してください。接続先情報を確認しないまま、DNS、スニッフィング、すべてのoutbound設定を同時に変更しないようにしましょう。

v2rayNをダウンロード