V2Rayのカスタムルーティングルール: domain・ip・geositeの構文とマッチング優先順位

domain・ip・geositeの3種類のルール構文とワイルドカード範囲を詳しく解説。ルールの評価順を整理し、そのまま使える振り分け例も紹介します。

この記事の概要

ノードのインポートを終え、直結・プロキシ・ブロックの振り分けを細かく制御したい方に適しています。完全なドメイン名、ルートドメイン、キーワード、CIDR、geositeカテゴリの違いと、上から順に最初に一致するルールの仕組みを理解し、フォールバック付きの設定を検証できます。

ルーティングルールが処理する対象

V2RayまたはXrayのルーティングモジュールは、ノードのプロトコルを変更したり、ノード自体の帯域を向上させたりするものではありません。接続先の情報を受け取り、その接続をどのアウトバウンドへ渡すかを決定します。代表的なアウトバウンドタグは proxydirectblock で、それぞれプロキシノードへ転送、直接接続、接続拒否を表します。タグ名は変更できますが、ルール内の outboundTag は、大小文字を含めてアウトバウンド設定の tag と完全に一致させる必要があります。

1つのリクエストで利用できるマッチング情報はドメイン名だけではありません。接続先にはIPアドレス、ポート、ネットワーク種別が含まれる場合があり、クライアントによってはプロセス名やインバウンドタグも利用できます。この記事では、特に混同しやすい domainipgeosite の3条件を扱います。geositeは実際には domain 配列内に記述し、独立したルールフィールドではなく、あらかじめ整理されたドメインカテゴリを参照します。

アプリがリクエストを開始インバウンドが接続を受信接続先情報を読み取りルールを順番に照合対応するアウトバウンドを選択

ルーティング判断の基本は「上から順に、最初に一致したルール」です。コアはルールリストを順番に読み取り、あるルールの条件がすべて成立すると、そのルールで指定されたアウトバウンドを使用し、後続のルールは確認しません。そのため、同じドメインが広告カテゴリと地域カテゴリの両方に属する場合、前に置いたブロックルールが後ろの直結ルールより先に適用されます。

ルール条件 参照する情報 代表的な用途 主な制約
domain 接続先ドメイン 特定サイトを直結またはプロキシ経由にする 接続先が最初からIPアドレスの場合は一致しない
geosite: ドメインカテゴリデータ 地域や用途ごとに一括振り分け ローカルのカテゴリデータファイルに依存する
ip 接続先IPまたは名前解決結果 プライベートネットワーク、地域IP、サブネットの振り分け ドメインリクエストを解決するかどうかはポリシーに左右される
port 接続先ポート 53、80、443などのポートを限定する 同じルール内の他フィールドとは「かつ」で評価される

domainとgeositeの記述方法の違い

domain 配列では複数のプレフィックスを利用できます。すべてのアドレスを通常の文字列で書くのではなく、完全なホスト名、ルートドメイン全体、名前に特定の文字列を含むサイトのどれを対象にするかを先に決めるのが確実です。範囲を広くしすぎると無関係なドメインまで同じアウトバウンドに送られ、狭すぎると静的リソースやAPI、ログイン用サブドメインを取りこぼすことがあります。

完全なドメイン名に一致

記述例
full:api.example.com
一致する対象
api.example.com
一致しない対象
www.example.com
適用範囲
単一のホスト名

1つのAPIドメインだけを変更し、同じサイトの他のサブドメインには影響させたくない場合に適しています。

ルートドメインに一致

記述例
domain:example.com
一致する対象
example.com
同時に一致
cdn.example.com
適用範囲
ルートドメインとサブドメイン

サイト全体を同じアウトバウンド経由にする場合に適しており、手書きルールで最もよく使われる形式です。

キーワードに一致

記述例
example
方式
文字列を含む
適用範囲
その文字列を含むすべてのドメイン
リスク
一致範囲が広がりやすい

あいまいな一致が必要な場合だけ使用し、短い語では誤一致がないか先に確認してください。

カテゴリリストに一致

記述例
geosite:cn
参照元
ローカルのドメインカテゴリデータ
方式
複数の項目を一括照合
管理方法
データファイルの更新に合わせて更新

広範囲の振り分けに適していますが、カスタムドメインはカテゴリルールより前に置く必要があります。

regexp: では正規表現を使用できます。たとえば regexp:^([a-z0-9-]+\.)*example\.com$ のように記述します。複雑なホスト名構造を表現できますが、domain: より保守の負担が大きくなります。ルートドメインとすべてのサブドメインを対象にするだけなら、domain:example.com と直接書く方が明確で、エスケープミスによるルール不成立も起こりにくくなります。

geosite:cn はcnという名前のドメインカテゴリを参照し、geosite:category-ads-all は広告関連ドメインのマッチングによく使われます。カテゴリの内容はクライアントが利用するデータファイルに由来し、ルール自体にはカテゴリ名だけを記述します。コアのアップグレード後にカテゴリが存在しないというログが出た場合は、geositeデータが完全か、カテゴリ名が現在のデータバージョンでサポートされているかを確認してください。

{
  "type": "field",
  "domain": [
    "full:api.example.com",
    "domain:static.example.com",
    "geosite:category-ads-all"
  ],
  "outboundTag": "block"
}

ip、CIDR、domainStrategyの組み合わせ方

ip フィールドには、単一のアドレス、CIDRサブネット、geoipカテゴリを記述できます。CIDRのスラッシュ後の数字はネットワークプレフィックス長を示します。たとえば 192.168.0.0/16192.168.0.0 から 192.168.255.255 までを対象にし、10.0.0.0/8 は10で始まるプライベートネットワーク全体を対象にします。家庭用ルーター、ストレージ機器、LANサービスを扱う場合は、サブネットを1つずつ列挙するより geoip:private を使う方が手軽です。

ドメインリクエストをIPルールの対象にできるかどうかは、ルーティングの domainStrategy によって決まります。AsIs では元の接続先を基準に判定し、IPマッチングのためにドメインを自動解決しません。IPIfNonMatch ではドメインルールに一致しなかった後でIPを解決し、IPルールも試します。IPOnDemand では、マッチング中に接続先IPが必要なルールに到達すると、名前解決が実行されることがあります。

  1. ドメインだけで振り分ける: AsIs を選び、ルーティング段階で余分な名前解決が発生しないようにします。
  2. ドメインを優先し、IPで補完する: IPIfNonMatch を選び、手書きのドメインルールとgeositeカテゴリで先に振り分けます。
  3. 前段のルールがIPに依存する: IPOnDemand を検討し、DNS設定から利用可能な結果が返ることを確認します。
  4. LANは必ず直結する: geoip:private ルールを地域IPルールと最終プロキシフォールバックより前に置きます。
{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "ip": [
          "geoip:private",
          "192.168.0.0/16",
          "10.0.0.0/8"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:cn"
        ],
        "outboundTag": "direct"
      }
    ]
  }
}

よくある誤りは、同じルールに domain:example.comgeoip:cn を同時に書くことです。「ドメインまたは地域IPのどちらかに一致したら直結」のつもりでも、実際には「ドメインがexample.comに属し、かつ解決結果がそのIPカテゴリに属する場合だけ直結」になります。「または」を表すには2つのルールに分け、同じ outboundTag を指定してください。

結論: ドメインルールを先に置き、IPルールで取りこぼしを補う

まずfull、domain、geositeで明確な意図を表し、geoipとCIDRは後ろに置きます。IPIfNonMatchを採用すると、ドメインルールに一致しなかったリクエストだけがIP判定へ進むため、ルールの順序を予測しやすくなります。

マッチング優先順位とそのまま使えるルール順序

ルールの優先順位は domainipgeosite の種類では決まりません。「完全一致ルールがカテゴリルールより自動的に優先される」という仕組みもありません。信頼できる唯一の優先順位は配列の順番です。カスタム例外は一括カテゴリより前に置き、ブロックルールはそれを覆う可能性のある直結・プロキシカテゴリより前に置き、最後にTCPとUDPを対象にするフォールバックルールを追加します。

以下の例では、「カスタム直結、広告ブロック、プライベートアドレス直結、地域ドメイン直結、地域IP直結、その他はプロキシ」の順に並べています。実際に使う前に、アウトバウンドタグが本当に directblockproxy であることを確認してください。サブスクリプションのテンプレートで別のタグが使われている場合は、タグの値だけを置き換え、条件の順序はむやみに変更しないでください。

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:portal.example.com",
          "domain:intranet.example"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "geosite:category-ads-all"
        ],
        "outboundTag": "block"
      },
      {
        "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 手書きの例外 後続カテゴリの既定判断を上書きする
2 明示的なブロック 地域直結カテゴリに先取りされるのを防ぐ
3 プライベートアドレス ルーターやLAN機器への直接アクセスを保証する
4 地域ドメイン まずドメインカテゴリで判定し、名前解決への依存を減らす
5 地域IP ドメインがない、またはカテゴリ未登録の接続先を処理する
6 最終フォールバック 一致しなかった接続の出口を確定する

フォールバックルールは、すべてのコア設定で必ず手書きする必要はありません。一致しない接続がデフォルトのアウトバウンドへ進む場合もあるためです。ただし明示的なフォールバックを置くと、設定の確認や移行が容易になります。別の設定へ移行するときも、最後のルールを見れば未分類トラフィックの行き先を判断でき、アウトバウンド配列の先頭項目を推測する必要がありません。

結論: 例外は必ずカテゴリより前に書く

特定サイトを強制的にプロキシ経由にする場合は、そのfullまたはdomainルールをgeosite:cnより前に置きます。後ろに置くと、前のカテゴリに一致した時点でコアはこの例外を確認しません。

v2rayNでルールを登録して検証する

v2rayN 7.12.xのデスクトップ画面を例にすると、まず「設定」→「ルーティング設定」を開き、現在使用中のルールセットをコピーしてから複製した方を編集します。直接上書きせずコピーを使えば、構文エラーが起きてもすぐ元のルールへ戻せます。マイナーバージョンによってボタンの位置は変わることがありますが、確認すべき項目はルール順序、ドメインリスト、IPリスト、接続先ポート、アウトバウンドタグです。

入力が終わったら新しいルールセットを選択し、コアを再起動します。続いて「設定」→「パラメータ設定」を開き、ローカル待受ポートを確認します。一般的なローカルポートは 10808 ですが、現在の画面に表示されている値を優先してください。ポートを変更した場合は、テストコマンドも同じ値に置き換えます。システムプロキシが有効なら、カスタム直結ドメイン、プロキシ対象ドメイン、LANアドレスをそれぞれ1つずつ開き、3種類の接続が想定したアウトバウンドへ進むか確認します。

curl --proxy socks5h://127.0.0.1:10808 https://example.com
curl --proxy socks5h://127.0.0.1:10808 https://www.example.org

socks5hh は、プロキシ側でドメイン解決を行うことを示します。これによりコアが元のドメイン名を認識し、domainやgeositeルールを適用しやすくなります。ローカルで先に名前解決し、そのIPをプロキシへ渡すテスト方法に変えると、ログには接続先IPしか表示されないことがあり、その場合domainルールには当然一致しません。

よくある問題と切り分け方

ルールが正しそうなのに結果が合わない場合、原因は構文ではなく、現在の設定でルールが有効になっていない、想定と異なる接続先情報になっている、または前方のルールがすでに一致していることが多いです。調査では全ルールを何度も入れ替えず、まず対象ドメインを1つに絞り、ログでコアが実際に受け取ったのがドメインかIPかを確認してください。

domainルールを書いたのに一致しないのはなぜ?

まずログの接続先がすでにIPアドレスへ変わっていないか確認します。テストツールがローカルで名前解決している場合は、ドメイン名をプロキシへ渡せる方法に変更してください。同時に、ルールがgeositeカテゴリと最終フォールバックより前にあることも確認します。

geositeカテゴリが見つからない場合は?

現在のコアが読み込んでいるデータディレクトリとgeositeデータファイルを確認し、カテゴリ名のスペルも確認します。コアを更新した場合は対応するデータも更新し、その後コアを再起動して再読み込みしてください。

LANサイトがプロキシへ送られる場合は?

プロキシのフォールバックより前に geoip:private の直結ルールを追加します。カスタムサブネットを使う場合は、172.16.0.0/12 のような実際のCIDRも追加し、前方により広い強制プロキシルールがないか確認してください。

同じルールにdomainとipを書くと、より正確になりますか?

2つの条件を同時に満たす必要がある場合だけ、そのように記述します。ドメインまたはIPのどちらかに一致させたい場合は、隣接する2つのルールに分け、両方に同じアウトバウンドタグを指定してください。

ルール保存後もWebページが古い出口を使うのはなぜ?

まず新しいルールセットが選択されていることを確認し、コアを再起動して新しい接続を確立します。ブラウザーが接続を再利用すると古い出口が維持されるため、関連ページを閉じて開き直し、ログを確認してください。

最後に順序を確認します。手書きの例外はカテゴリより前にあるか、ブロックルールは広範囲の直結より前にあるか、privateはプロキシのフォールバックより前にあるか、domainStrategyはドメイン優先の設計に合っているかを確認してください。この4点を設定から直接読み取れるようにしておけば、後からルールを追加しても既存の振り分けを壊しにくくなります。

  1. まず単一の接続先に対する full: ルールを書き、アウトバウンドタグが有効か確認します。
  2. 次に domain: へ範囲を広げ、ルートドメインと2つのサブドメインで検証します。
  3. geositeカテゴリを追加し、カスタム例外はカテゴリより前に残します。
  4. 最後にgeoip、CIDR、TCP/UDPのフォールバックを有効にし、ログを段階的に確認します。
V2Rayクライアントをダウンロード