V2Rayのカスタムルーティングルール: domain・IP・geositeのマッチング優先順位を詳しく解説

routingルールにおけるdomain・ip・geositeの記法と書式、上から順に適用される仕組みや競合例を解説し、そのまま使える振り分け構成も紹介します。

この記事の概要

この記事は、ノードをインポートでき、直結・プロキシ・ブロックの範囲をさらに細かく制御したい方に適しています。ドメインとIP条件の実際のマッチ方法、geositeとgeoipデータセットの役割、ルール競合時の適用順、既存の出力タグに合わせて調整できるrouting設定を解説します。

まずroutingのマッチング処理を理解する

V2Rayのルーティングは、VMessやVLESSなどのノードプロトコル自体を変更しません。コアがリクエストを受け取った後、どのoutboundに渡すかを処理し、接続をプロキシ、直結、ブロック、その他の定義済み出口のどれに振り分けるかを決めます。結果はリクエストの宛先、ルールの順序、出力タグに左右されるため、ノードに接続できても振り分けルールが正しいとは限りません。

リクエストは通常、ローカルのSOCKS、HTTP、または透過プロキシの入口で受け付けられ、routing.rulesへ進みます。コアは配列の先頭ルールから確認し、条件を満たす最初のルールで判定を止め、そのルールのoutboundTagまたはbalancerTagを使用します。後ろにある、より具体的なルールも、先行ルールにマッチした後は上書きできません。

アプリがリクエストを開始入口が接続を受信宛先情報を読み取りルールを順番に照合対応するoutboundを選択

1つのルール内にある複数のフィールドは、通常「すべて満たす」関係です。たとえば network: "tcp"port: "443" を同時に指定した場合、TCP 443の接続だけにマッチします。一方、フィールド内の配列は「いずれか1つにマッチすればよい」条件です。domain配列に3つのドメイン条件があれば、そのうち1つに該当するだけでフィールドの条件を満たします。

domain・full・regexp・geositeの記述方法

domainフィールドは文字列配列を受け取りますが、配列内の文字列には複数のマッチ構文を使用できます。通常の文字列はドメインの部分一致に使い、domain: は指定ドメインとそのサブドメイン、full: は完全一致、regexp: は正規表現、geosite: は外部のドメイン分類データを参照します。日常的な振り分けではdomain、full、geositeを優先し、既存の構文で範囲を表現できない場合に限ってregexpを検討します。

完全一致とサフィックス一致

完全なドメイン名
full:api.example.com
ドメインとサブドメイン
domain:example.com
通常の文字列
example
正規表現
regexp:^.+\.example\.com$

固定のホスト名が分かっている場合はfull、サイト全体とサブドメインを対象にする場合はdomainを優先します。

分類データによるマッチング

中国本土でよく使われるドメイン
geosite:cn
広告カテゴリ
geosite:category-ads-all
中国本土以外のカテゴリ
geosite:geolocation-!cn
データソース
コアが読み込むデータファイル

利用できるカテゴリ名は、現在のコアが実際に読み込んでいるデータファイルとそのバージョンによって決まります。

domain:example.comexample.comwww.example.com を対象にでき、サイト全体のポリシーに適しています。一方、full:example.com はサブドメインを自動的に対象にせず、1つの固定ホスト名だけを処理する場合に向いています。通常の文字列は範囲が広く、同じ文字列を含む別サイトまで意図せずマッチする可能性があるため、短すぎる単語をルールに使うことはおすすめしません。

{
  "type": "field",
  "domain": [
    "full:api.example.com",
    "domain:static.example.com",
    "geosite:cn"
  ],
  "outboundTag": "direct"
}

geositeは、リアルタイムでインターネット検索を行うサービスではなく、コアが読み込むローカルのドメイン分類データです。クライアントやコアを更新すると、分類内容がデータファイルによって変わる場合があります。ログにgeositeカテゴリが見つからないと表示された場合は、まずカテゴリ名の存在を確認し、次にクライアントがV2RayとXrayのどちらのコアを使用しているかを確認してください。ルール順を何度も変更して、データ不足を隠そうとしてはいけません。

ip・CIDR・geoipのマッチ条件

ipフィールドは接続先のIPアドレスを判定し、単一のアドレス、CIDRネットワーク、または geoip: カテゴリを指定できます。よく使われる記法には 127.0.0.0/8192.168.0.0/16geoip:privategeoip:cn があります。CIDRのサフィックスはネットワークプレフィックス長を示し、1桁間違えるだけでマッチ範囲が広がったり狭くなったりします。

10808
一般的なローカルSOCKSポート
10809
一般的なローカルHTTPポート
53
従来型DNSサービスのポート
5グループ
推奨される基本ルール階層

アプリがIPアドレスへ直接リクエストする場合、コアはipルールですぐに判定できます。ドメイン名でリクエストする場合、ルーティングのマッチングで名前解決を行うかどうかはrouting.domainStrategyによって決まります。AsIs は主に元のドメイン名を使って判定し、IPIfNonMatch はドメインルールで結果が出なかった場合に名前解決してIPマッチングを続行します。IPOnDemand は、マッチング中にIP条件が必要になったときに名前解決を行う場合があります。

記法 マッチ範囲 主な用途
127.0.0.0/8 ローカルループバックアドレス帯 ローカルサービスをリモートプロキシへ送らない
192.168.0.0/16 一般的なLANアドレス帯 ルーター、ストレージ、社内ネットワークサービスへのアクセス
geoip:private データファイルで定義されたプライベートアドレス 複数のプライベートネットワークをまとめて処理
geoip:cn データファイルで中国本土向けに分類されたアドレス ドメイン振り分けを補う条件として使用

結論:ドメインルールを主軸に、IPルールで補完する

まずfull、domain、geositeで対象範囲を明確にし、geoip:private、geoip:cn、または明示的なCIDRでIPアドレスへ直接アクセスする接続を処理します。不要なDNS名前解決を減らせるうえ、ログからリクエストが特定のoutboundにマッチした理由も確認しやすくなります。

IPIfNonMatch を使う場合は、名前解決の経路にも注意が必要です。ルーティング判定で得たIPと、実際のリモート接続で使われる名前解決結果は、できるだけ一致させてください。内蔵DNS、システムDNS、リモートDNSで異なる結果が返ると、同じドメインでも時間によって別のアドレス分類に入る可能性があります。振り分けが不定期に変わる場合は、dns設定、domainStrategy、コアログに記録された宛先アドレスを併せて確認します。

ルールの優先順位とよくある競合

V2Rayは、どのルールが「より具体的か」を自動判定しません。配列の前にあるルールほど優先されるため、「例外を先に、広い範囲を後に、最後にフォールバック」という順で構成します。たとえば、あるドメインをプロキシ経由にしたいのに geosite:cn にも含まれる場合は、そのドメインのプロキシルールを先に書き、その後にgeositeの直結ルールを置く必要があります。

  1. まず、必ずブロックする、または個別に処理する必要がある正確なルールを置きます。たとえば full: ドメインです。
  2. 次に、LANとプライベートアドレスの直結ルールを置き、ローカル機器へのリクエストがプロキシへ送られないようにします。
  3. 続いて、用途別のドメイングループ、geositeカテゴリ、指定ネットワークを配置します。
  4. 最後に、対象範囲の広いプロキシまたは直結のフォールバックルールを置きます。
  5. 変更後はコアログでドメイン、IP、TCP、UDPのリクエストを1つずつ確認します。
{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:service.example.com"
        ],
        "outboundTag": "proxy"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "geosite:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

上の1つ目のルールは、geositeの直結範囲に対する例外なので先頭に置いています。2つ目はLANアクセスを保護し、3つ目と4つ目はそれぞれ中国本土向けのドメインとアドレスを処理します。最後のルールは、残りのTCP・UDPリクエストをproxyへ渡します。実際に使用する前に、outboundsに proxydirect の2つのタグが存在することを必ず確認してください。存在しないoutboundを参照すると、コアの起動に失敗します。

v2rayNでルーティングを設定・検証する

v2rayNのメニュー名はバージョンによって変わる場合があります。一般的な入口は「設定」→「ルーティング設定」です。カスタムルールセットを作成したら、現在のルールセットが選択されていることを確認してから設定を保存し、使用中のコアを再起動します。完全なカスタム設定ファイルを使う場合は、ノード切り替えやサブスクリプション更新時にクライアントが設定を再生成するか確認し、手動編集が上書きされないようにしてください。

確認項目 具体的な操作 期待される結果
ローカル入口 「設定」→「パラメータ設定」でSOCKS 10808、HTTP 10809を確認 ブラウザまたはテストプログラムが実際に有効なポートへ接続する
outboundタグ ルール内のproxy、directが既存のoutbound tagに対応しているか確認 コアの起動ログに不明なoutboundタグが表示されない
ルールの順序 正確なドメイン、geositeドメイン、直接IP、LANアドレスを個別にテスト 4種類のリクエストが想定したoutboundにマッチする
UDPリクエスト フォールバックルールにudpが含まれていることを確認し、ノードと入口の関連設定を確認 DNSなどのUDPトラフィックが取りこぼされない

検証では、ウェブページが開くかどうかだけを見ないでください。コアログを有効にし、少なくとも6つの対象を用意します。正確なプロキシ対象ドメイン、geositeの直結対象ドメイン、中国本土向けIP、LANのIP、ブロック対象ドメイン、そして前のルールに該当しないドメインです。1つずつリクエストして、マッチしたoutboundTagを記録します。ルール番号を確認できる場合は、それも併せて記録してください。

結論:毎回変更する条件は1グループだけにする

まずdomainStrategyとoutboundタグを固定し、そのうえで1つのルールを移動するか、1つのマッチ項目だけを変更します。DNS、geositeカテゴリ、ルール順を同時に変更すると、ログ結果を単一の原因と結び付けられず、かえって調査に時間がかかります。

よくある問題と調査の順番

ルーティングの問題は、特定のサイトが誤った出口を使う、LAN機器にアクセスできない、保存しても変化しない、コアが起動に失敗するといった形で現れます。調査ではまず設定が実際に読み込まれているか確認し、次にタグと順序、最後にDNSの名前解決と分類データを確認します。この順番なら、設定が反映されていないといった基本的な問題を先に切り分けられます。

domainルールを書いたのに、なぜ前のgeositeにマッチするのですか?

正確なdomainまたはfullルールをgeositeルールの前へ移動し、保存してからコアを再起動します。ルールは具体性の順に自動整列されないため、先にマッチしたgeositeで今回の判定はすでに終了しています。

IPでは振り分けられるのに、ドメイン名ではgeoipにマッチしないのはなぜですか?

routing.domainStrategyを確認します。AsIsでは、すべてのIPルールのためにドメインリクエストを一律で名前解決することはありません。ドメインルールにマッチしなかった後でIP判定を試したい場合は、IPIfNonMatchの利用を検討できます。

geositeを追加したらコアの起動エラーが出た場合はどうすればよいですか?

まず追加したカテゴリを削除して起動できる状態に戻し、カテゴリ名と現在のコアが読み込むデータファイルを確認します。カテゴリが存在しない、またはデータファイルを読み込めない場合、ルール順を変えてもエラーは解決しません。

LANアドレスがプロキシへ送られるのはなぜですか?

広範なプロキシルールの前にgeoip:privateを追加するか、10.0.0.0/8、172.16.0.0/12、192.168.0.0/16を明示的に追加します。その後、ルーターやLANサービスのアドレスがdirectにマッチするかテストします。

ルールは正しそうなのに、保存しても変化がありません。

現在有効になっているのが編集したばかりのルーティング設定か確認し、その後コアを再起動して生成された設定を確認します。ノード切り替え後にルールが消える場合は、クライアントがroutingセクションを再生成していないか確認してください。

保守しやすい振り分け設定では、大量の重複ルールを積み重ねる必要はありません。正確な例外、プライベートアドレス、主要なgeositeまたはgeoipカテゴリ、最後のフォールバックを残し、ログを見ながら本当に必要な項目だけを追加します。新しいルールには用途、対象outbound、検証結果を記録しておくと、データファイルの更新やコアの変更時にも、どのルールがまだ必要かすぐ判断できます。