ノードに接続でき、これからルーティングルールを変更したい方向けの記事です。ドメインとIPの条件の違いから始め、5つのルール例でマッチ順、outboundタグ、DNS名前解決の方針を解説し、v2rayNでの設定変更と検証方法を紹介します。ページが開くかどうかだけで設定の成否を判断せず、接続がどのルールにマッチしたかを確認することがポイントです。
接続がコアに届いてからルーティングルールが適用される
システムプロキシ、TUNによる通信の取り込み、Xrayのルーティングは、それぞれ異なる段階で機能します。システムプロキシは、対応アプリの接続をローカルの入口へ送るかどうかを決めます。ルーティングルールは、コアに届いた接続を直結・プロキシ・ブロックのいずれにするか選択します。ブラウザーがシステムプロキシを迂回している場合、ルールが正しくても該当するルーティング結果は得られません。
この記事ではXray標準のJSONフィールドを使用します。v2rayNとv2rayNGは、画面での設定をコア用の設定に変換します。v2flyNGはV2Flyコアを使用するため、すべてのXrayフィールドをそのまま使えるとは限りません。編集前に現在使用中のコアを確認し、既存のルーティング設定をバックアップしてください。
domainはルールのフィールドです。配列にはdomain:、full:、regexp:、geosite:などのマッチ式を指定できます。ipは別のルールフィールドで、IPアドレス、CIDRネットワーク、geoip:のデータセットを指定します。ドメイン配列内のip:プレフィックスと混同しないでください。outboundTagはアウトバウンドを参照する値で、任意のメモではありません。最終設定に存在するアウトバウンドのtagと一致させる必要があります。
domain・full・regexp:マッチ範囲を指定する
誤った振り分けの多くは、マッチ範囲が広すぎることが原因です。文字列だけを指定すると、Xrayは部分文字列として照合します。「このドメインとそのサブドメイン」を対象にする場合は、domain:を明示してください。ルールにはホスト名を指定し、プロトコルやパス、クエリ文字列を含むURL全体は貼り付けないでください。
| 記法 | マッチする範囲 | マッチ例・対象外の例 |
|---|---|---|
example.com | ドメイン内の部分文字列にマッチ | notexample.comにもマッチする可能性があります |
domain:example.com | 指定したドメインとすべてのサブドメイン | example.com、img.example.comにマッチし、notexample.comにはマッチしません |
full:example.com | 完全なドメイン名に完全一致 | www.example.comは対象外です |
regexp:^img[0-9]+\.example\.com$ | 正規表現でマッチ | img12.example.comにマッチし、img.example.comにはマッチしません |
geosite:cn | ドメインデータファイル内のcnセットを参照 | 結果は使用中のデータファイルによって異なり、中国本土のすべてのサーバーを指すわけではありません |
正規表現にはJSON用のエスケープも必要です。ルーティングの編集欄では、元の式に\.を含められます。JSON文字列に記述する場合は、バックスラッシュを\\と書きます。以下は解析可能なJSONルールオブジェクトの例で、コアを単独で起動できる完全な設定ではありません。
{
"type": "field",
"domain": [
"full:example.com",
"domain:example.net",
"regexp:^img[0-9]+\\.example\\.com$"
],
"outboundTag": "direct"
}
ip・geoip・geosite:参照するデータが異なる
geositeはドメインのセット、geoipはIPアドレスのセットにマッチします。ウェブサイトが複数のコンテンツ配信先を使う場合、ドメインの分類と実際の接続先IPの地域分類が異なることがあります。特定のサイトを常にプロキシ経由にしたい場合は、IPの地域情報だけに頼らず、ドメインの例外ルールを優先してください。
{
"type": "field",
"ip": [
"192.168.0.0/16",
"10.0.0.0/8",
"geoip:private",
"geoip:cn"
],
"outboundTag": "direct"
}
上の例の最初の2項目はCIDRの記述例で、geoip:privateと対象範囲が一部重複します。実際の設定では重複する項目を削除できます。IPv4のプライベートネットワークだけではIPv6のローカルアドレスは自動的に対象になりません。デュアルスタック環境では、使用するプライベートアドレスセットの範囲を確認してください。
- セットの有無:
geosite:cnまたはgeoip:cnを指定する前に、コアが対応するデータファイルを読み込めることと、そのファイルに対象のセットが含まれていることを確認してください。 - 分類データの更新:クライアント設定の更新とgeoデータの更新は別の作業です。サブスクリプションの更新に成功しても、ドメイン分類が更新されたとは限りません。
- 拡張セットの記法:
geosite:セット名@属性が有効なのは、データファイルにその属性が定義されている場合だけです。任意のセットに属性を付ければ使えるわけではありません。 - 不具合の症状:データファイルが見つからない場合やセットが存在しない場合、設定の読み込みに失敗することがあります。ノードに接続できないと決めつけず、まず起動ログを確認してください。
ルールの優先順位:上から評価し、最初の一致で終了
1回のルーティング処理では、Xrayはrules配列の順に各ルールを確認し、すべての条件を満たす最初のルールを適用します。後ろのルールのドメインがより具体的でも、自動的にそちらが選ばれることはありません。対象を限定した例外ルールは広範な分類より前に、フォールバックルールは末尾に置いてください。
同じフィールドの配列内は、通常「OR」条件です。ドメイン配列なら、いずれかの式にマッチすれば対象になります。一方、1つのルール内の異なるフィルターフィールドは、通常「AND」条件です。domain、port、networkを指定すると、すべての条件を満たす必要があります。ドメイン条件とIP条件を同じルールに書いても、「どちらかに一致すれば直結」にはなりません。
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": ["geosite:category-ads-all"],
"outboundTag": "block"
},
{
"type": "field",
"domain": ["full:example.com"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:private", "geoip:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
これはルールの順序を説明するためのrouting設定例です。direct、proxy、blockの3つのアウトバウンドがすでに定義され、データファイルに例で使用するセットが含まれているものとします。タグ名はコアで予約されたアクション名ではありません。一般的な直結アウトバウンドにはfreedom、ブロックにはblackholeを使い、プロキシには実際のノードのプロトコルを指定します。
例外ルールをブロックルールより優先するか確認
あるドメインを必ず直結させたい場合、広告セットにも含まれているなら、そのドメインに完全一致する直結ルールを広告ルールより前に移動してください。cnセットより前に置くだけでは不十分です。
domainStrategy:ドメインをIPルールの照合に使うタイミング
ドメイン宛ての接続にIPルールを適用できるかは、ルーティングのdomainStrategyによって異なります。このフィールドはルーティング時に照合用の名前解決を行うかを制御するもので、クライアント全体のDNS設定や、直結アウトバウンドが最終的に宛先を名前解決する方法とは別です。
AsIs:宛先の種類を維持
- フィールド
routing.domainStrategy- 動作
AsIs- ドメイン宛て
- ルーティング照合のためにIPへ積極的に名前解決しない
- IPアドレス宛て
- IPルールに直接マッチできる
まずドメインルールを検証したい場合に適しています。初回の切り分けでDNSの解決結果が影響するのを避けられます。
IPIfNonMatch:マッチしなければ名前解決
- フィールド
routing.domainStrategy- 動作
IPIfNonMatch- 実行条件
- ドメイン宛ての接続が1回目の照合でどのルールにもマッチしない
- その後の処理
- 名前解決後、IPルールを含めて再度照合
末尾にすべての接続にマッチするフォールバックルールがあると、1回目の照合で結果が確定するため、その後のIPによる再判定は行われません。
そのため、前のセクションの5つのルールにIPIfNonMatchを指定していても、ドメイン宛ての接続が最後のTCP/UDPフォールバックに到達すると、1回目の照合でマッチ済みとなり、先にあるgeoip:cnのための名前解決は行われません。もともとIPアドレス宛ての接続なら、4番目のルールにマッチできます。「geoipを設定したのにドメイン宛ての通信がプロキシ経由になる」よくある原因です。
- IPによる再判定が必要な場合:すべての接続にマッチするフォールバックルールを削除し、ルールにマッチしなかった場合の最初のアウトバウンドが、想定するデフォルトのアウトバウンドであることを確認してください。
- IPルールの照合時に名前解決したい場合:
IPOnDemandを検討できます。IP情報を必要とするルールの照合時に名前解決を試みますが、DNSがルーティングに影響する機会も増えます。 - 特定のサイトだけ出口を固定したい場合:先頭に
full:またはdomain:ルールを追加する方法なら、名前解決の方針全体を変更するより検証しやすいのが一般的です。
また、インバウンドが宛先IPしか受け取っていない場合、ドメインルールが元のホスト名を自動的に把握することはできません。対応する通信ではスニッフィングによってドメイン情報を補えることがありますが、あらゆるプロトコルでホスト名を復元できるわけではありません。切り分け時は、インバウンドの宛先、スニッフィング設定、最終的なアウトバウンドをあわせて確認してください。
v2rayNでルール順を変更して結果を確認する
v2rayNで「設定」→「ルーティング設定」を開き、使用するルーティング設定を選んでルール編集画面に進みます。編集や上へ・下へ移動するボタンの位置は、画面のバージョンによって異なる場合があります。確認すべきなのは設定名やルールのメモではなく、最終的に生成されたrouting.rulesの順序です。
- 設定を複製:元の設定を戻せるように残し、複製した設定にテスト用ドメインの
full:ルールを1つ追加します。最初はDNS、スニッフィング、コアを同時に変更しないでください。 - 条件を分けて入力:
full:example.comはドメイン条件に、geoip:cnはIP条件に指定します。1行ずつ入力する画面では、各行にマッチ項目を1つ入力し、JSONオブジェクト全体を貼り付けないでください。 - アウトバウンドを確認:アウトバウンドの選択欄で使用する出口を選びます。標準設定を使う場合は、
outboundTagとアウトバウンドのtagが大文字・小文字も含めて完全に一致していることを確認してください。 - ルール順を変更:テストルールを先にマッチする可能性のあるルールより上に移動します。保存後、対象のルーティング設定が選択されていることを確認し、画面の案内に従ってコアを再読み込みまたは再起動してください。
- 新しい接続でテスト:既存のウェブ接続を閉じてから、もう一度アクセスします。長時間維持される接続は、ルールを変更しても自動で出口が切り替わらないことがあります。必要に応じてブラウザーを終了してからテストしてください。
- ログを記録:コアが正常に起動したことを確認し、テスト先へのアクセス記録とアウトバウンドタグを確認します。必要な場合はログ設定で一時的に詳細度を上げ、テスト後に元へ戻してください。接続情報が大量に記録され続けるのを防げます。
「HTTPSだけを直結する」ルールを検証する場合は、テストルールにドメイン条件とport: "443"、network: "tcp"を設定します。UDPを使うHTTP/3はTCP条件を満たしません。同じサイトがブラウザーで開けたというだけで、ルールが機能していないとは判断できません。テスト条件に合うプロトコルとポートを使用してください。
fullを指定したのにwwwのドメインがプロキシ経由になるのはなぜ?
full:example.comはwww.example.comを含みません。まずログで実際の宛先を確認してください。サブドメインも対象にする場合はdomain:example.comに変更します。この2つのホスト名だけが必要なら、fullのマッチ条件を2つ追加してください。
ルールを最後に置いても効かないのはなぜ?
上にnetwork: "tcp,udp"、対象ドメインを含むセット、または範囲の広いドメイン条件がないか確認してください。テストルールをそれらより前に移動し、設定を再読み込みして新しい接続でテストします。
geoデータを更新したら、コアが起動しなくなった?
起動ログに記載されたファイル名とセット名を確認します。データファイルを読み取れることと、対象のセットが実際に存在することを確認してください。まずエラーの原因となったセットの指定を削除して起動できるか検証し、その後データの取得元を修正します。設定ミスを隠すためにノードを何度も変更しないでください。
ウェブページが開けば、directにマッチしたと判断できる?
いいえ。直結でもプロキシ経由でも、ページが正常に開く場合があります。コアのアクセスログで宛先とアウトバウンドタグを確認してください。現在のログにルール番号が表示されない場合は、変更前後のアウトバウンドを比較し、一度に変更するルールは1つにしてください。