この記事は、v2rayNでドメイン例外を追加し、直結とプロキシの順序を調整したい方向けです。ドメイン・IP・データセットの各マッチ対象を整理し、routing設定の例を使って、最初に一致したルール、DNSによる追加解決、フォールバック出力の関係を説明します。例ではV2RayやXrayで一般的な従来型のJSONルーティング構造を使用します。クライアント画面で設定するルールは、使用中のコアが認識できる形式に変換する必要があります。
1. ルーティングルールの基本構造とマッチ対象
システムプロキシはアプリの接続を受け入れ、ルーティングは通信がコアに入った後の出力先を決めます。ブラウザーがシステムプロキシを使っていない場合、ルールが正しくても判定を通らず、迂回されることがあります。そのため、カスタムルールを調べる前に、アプリがクライアント経由で接続していることを確認しましょう。サイトに表示される出口IPだけを確認しても、原因の特定にはつながりません。
従来型の設定では、routing.rules配列にルールを記述します。各ルールのtypeは通常fieldで、domain、ip、port、networkなどを条件にできます。出力先はoutboundTagで指定します。タグは設定内で参照する名前であり、コアに固定されたアクション名ではありません。
{
"type": "field",
"domain": [
"full:api.example.com",
"domain:example.net"
],
"port": "443",
"network": "tcp",
"outboundTag": "proxy"
}
このルールは、宛先ドメインが配列内のいずれかに一致し、宛先ポートが443、通信ネットワークがTCPであることを条件とします。ドメイン配列内の条件は「または」、異なる条件フィールド間は「かつ」です。同じドメインへのUDP 443接続やTCP 80接続には適用されません。以下の3つの数値は設定例であり、速度測定の結果ではありません。
2. domain・full・regexpと通常の文字列の書き方
domainはルール内のフィールド名であり、フィールド配列に書くdomain:はマッチ方式を示すプレフィックスです。両者を混同しないでください。配列にはドメイン名または対応する式だけを指定し、URLのスキーム・パス・クエリパラメーターは含めません。同じサイト内のURLパスごとに振り分けることは、通常のドメインルールではできません。
| 書式 | マッチ範囲 | 判定例 |
|---|---|---|
full:example.com | ホスト名の完全一致 | example.comには一致し、www.example.comには一致しない |
domain:example.com | 指定したドメインとそのサブドメイン | example.comとa.example.comには一致し、notexample.comには一致しない |
example.com | 通常の文字列による部分一致 | notexample.comにも一致する可能性があり、想定より広い範囲を対象にしやすい |
regexp:^api[0-9]+\\.example\\.com$ | 正規表現によるマッチ | api1.example.comには一致し、api.example.comには一致しない |
表の正規表現はJSON文字列として示しています。正規表現ではピリオドを文字として扱うために\.と書きますが、JSONではバックスラッシュもエスケープするため、設定ファイルでは\\.と記述します。クライアントの通常のテキスト入力欄に式を入力する場合は、一般にバックスラッシュは1つです。JSON用のエスケープをすべての画面にそのまま貼り付けないでください。
{
"type": "field",
"domain": [
"full:example.com",
"domain:example.net",
"regexp:^api[0-9]+\\.example\\.com$"
],
"outboundTag": "proxy"
}
まとめ:ドメイン例外にはまずfullまたはdomainを使う
ホスト名を1つだけ指定する場合はfull:、ドメイン全体とそのサブドメインを対象にする場合はdomain:を使います。正規表現はホスト名に明確な規則性がある場合に限り、先頭と末尾のアンカーを付けて、無関係なドメインまで含めないようにします。
3. ip・geoip・geositeの違い
ipフィールドは宛先アドレスのマッチに使い、単一IP、CIDRネットワーク、またはgeoip:データセットを指定できます。一方、geosite:はdomain配列に記述し、ドメインの集合でマッチします。2つのデータセットは収録対象が異なるため、同じ名前のgeositeに一致すればgeoipにも必ず一致する、という保証はありません。
{
"type": "field",
"ip": [
"192.168.0.0/16",
"10.0.0.0/8",
"geoip:private"
],
"outboundTag": "direct"
}
上の例では、まずCIDRの具体的な書き方を示し、続けてプライベートアドレスの集合を示しています。対象範囲が重なるため、実際の設定では要件に合うどちらか一方を選ぶのが一般的です。IPv6の単一アドレスには/128を指定できます。IPv4だけを対象にして、すべてのLAN接続をカバーしたと判断しないでください。デュアルスタック環境ではIPv6の宛先も確認が必要です。
geosite:cn:データファイル内のcnというドメイン集合を参照します。.cnで終わるドメインだけに一致するわけではありません。geoip:cn:アドレスデータベースを使って宛先IPの割り当て範囲を判定します。サイトの表示言語やアクセスした人の所在地を示すものではありません。geoip:private:プライベートアドレスなど、ローカル用途のアドレス集合を参照します。対象範囲は実際のデータファイルで確認してください。- データファイルへの依存:従来型のデータセット指定では、通常、コアが読み込める
geosite.datとgeoip.datが必要です。集合名が実際に存在することを確認し、名前を推測して指定しないでください。
同じドメインでも、複数の地域のCDNアドレスが使われることがあります。DNSの応答が変われば、IPルールの判定結果も変わる可能性があります。特定のサービスを常に指定した出力先へ接続したい場合は、一度の名前解決で得たCDNのIPアドレスを固定するのではなく、明示的なドメイン例外を優先してください。
4. 適用順序:上から評価し、最初に一致したルールを適用
ルールの評価では、コアはrules配列を上から順に確認し、一致した時点でそのルールの出力先を選びます。後ろにあるfull:のほうが精密でも、先にあるgeosite:を自動で上書きすることはありません。ネットワーク範囲の長さに応じて並べ替えられることもありません。「例外を優先」するには、設定する側が例外を上の位置に移動します。
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["full:api.example.com"],
"outboundTag": "proxy"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:cn"],
"outboundTag": "direct"
}
]
}
}
ここでは、単一ドメインの例外をドメイン集合より前に置いています。同じ接続が2つ目のルールに一致した場合、3つ目以降のルールは判定されません。ただし、最初のプライベートIPルールが初回の評価で一致するかは、宛先がすでにIPアドレスか、現在のドメイン戦略で名前解決が行われるかによって変わります。ルールが一番上にあるからといって、DNSが必ず先に実行されるとは限りません。
- 宛先が
api.example.comで、受信側にドメイン名が保持されていれば、2つ目のルールでproxyを直接選択できます。 - ほかのドメインが
geosite:cnに一致すると、3つ目のルールでdirectが選択され、IPによる追加判定を待つ必要はありません。 - ドメインによる判定で何も一致しなかった場合に限り、
IPIfNonMatchは名前解決を試み、取得したIPアドレスを使ってルールを再評価します。 - それでも一致しない場合、従来型の設定では
outbounds配列の先頭にある出力先が使われます。その名前がproxyとは限りません。
5. domainStrategyがDNSとルーティング結果に与える影響
routing.domainStrategyは、ルーティングの判定で宛先ドメインをIPアドレスに名前解決するかどうかを制御します。システムのDNS設定や、直結出力に設定する同名の戦略とは別のものです。名前が似ていても、設定階層が異なれば適用される段階も異なります。
AsIs
ルーティング段階では、ドメインをIPアドレスにするための追加の名前解決は行いません。宛先がもともとIPアドレスであれば、IPルールには一致します。接続時に最終的な名前解決が必要かどうかは、その後の出力先などによって決まります。
向いている構成:ドメインルールが中心で、ルーティングの判定に余分なDNS問い合わせを加えたくない場合。
IPIfNonMatch
おすすめすでにある宛先情報で先に判定し、どのルールにも一致しない場合にドメインを名前解決して、以降の判定にIPルールを使います。早い段階で一致する全体向けフォールバックルールは避けてください。
向いている構成:この記事のように、ドメイン例外を優先し、IPの割り当て情報を補助的に使うルーティング。
IPOnDemand
判定中にIP情報を必要とするルールに達すると、必要に応じて名前解決します。前方にあるIPルールが一致すると、後方のドメイン例外より先に出力先が決まる場合があります。
向いている構成:IPルールを早い段階から適用する必要があり、DNSの応答とルール順を管理できる場合。
たとえば、1つ目のルールがgeoip:privateで、2つ目が特定ドメインのプロキシ例外だとします。そのドメインがプライベートアドレスに解決されると、IPOnDemandでは1つ目が先に一致する可能性があります。一方、IPIfNonMatchでは2つ目に一致すれば、追加の名前解決を待つ必要はありません。戦略を変更した後は、サイトが開くかどうかだけでなく、実際に選択された出力先も確認してください。
- DNSの応答に複数のアドレスが含まれる場合、IPルールの判定はコアが名前解決結果をどう処理するかに基づいて考える必要があります。コマンドラインに表示された先頭のアドレスだけで判断しないでください。
- アプリがIPアドレスを直接指定して接続する場合、ドメインルールには通常、マッチする情報がありません。一部のプロトコルではスニッフィングによってドメイン名を復元できることもありますが、すべての接続で機能するとは限りません。
- 「UDP 53をすべて遮断」するルールを追加しても、すべてのDNSを遮断できるわけではありません。暗号化DNSは別のポートや通信方式を使うことがあります。
6. v2rayNでカスタムルールを追加して確認する
ここではv2rayN 7.xデスクトップ版で一般的な画面を例にします。マイナーバージョンによってボタンの位置は変わることがあるため、ルールの項目は現在の画面で確認してください。画面から設定するルールと、完全なJSON設定は入力形式が異なります。routingオブジェクト全体を「ドメイン」入力欄に貼り付けないでください。
-
コアを確認する
「設定」→「パラメーター設定」を開き、Coreタイプに関する設定と現在の構成で使うコアを確認します。起動後はログに記録されたコア名も確認してください。この記事の構文はV2RayとXrayの従来型ルーティング設定を対象としています。ほかの形式では変換が必要です。
-
ルーティング設定を開く
「設定」→「ルーティング設定」を開き、まず現在のプロファイルをバックアップしてから、使用するルールセットを編集します。編集対象がメイン画面で選択中のルーティング設定であり、未使用の複製ではないことを確認してください。
-
例外を追加する
ルール編集画面で出力先を選び、ドメイン欄に
full:api.example.comまたは対象のドメインを入力します。最初はポートやネットワークの条件を追加せず、動作を確認してから少しずつ条件を絞り込みます。 -
ルールの順序を調整する
例外ルールを、それに一致する可能性のあるドメイン集合ルールより前に移動し、保存してそのルーティング設定を選択します。クライアントが関連設定を再読み込みするのが一般的です。ログに変更が反映されない場合は、サービスを再起動してからテストしてください。
-
接続を再確認する
既存のテスト用タブを閉じて新しい接続を開始し、接続ログで宛先と出力先タグを確認します。詳細なログが必要な場合は、「設定」→「パラメーター設定」で一時的にログレベルを上げ、確認後に通常のレベルへ戻してください。
ルーティングの変更は通常、新しい接続から適用されます。ブラウザーの接続再利用や長時間接続では、以前の出力先が引き続き使われることがあります。ページを一度更新しただけでは、新しいルールが適用されていないとは判断できません。メインドメイン・サブドメイン・直接指定したIPアドレスの3種類を試し、トップページだけでなく、ページ内のリソースが別ドメイン経由になっていないかも確認してください。
| テスト項目 | 確認する内容 | 想定どおりでない場合の確認点 |
|---|---|---|
| 完全一致するドメイン | 完全なホスト名に対して指定したタグが選択されるか | 前方にあるルール、実際に有効なルーティング設定 |
| サブドメイン | fullとdomainの対象範囲の違い | 通常の文字列を誤って使っていないか、サブドメインを指定し忘れていないか |
| IPアドレスを直接指定 | IPルールが独立して適用されるか | CIDRの書き方、IPv4・IPv6のアドレス種別 |
| どのルールにも一致しない宛先 | 想定したデフォルト出力先が使われるか | 出力先配列の先頭、全体向けフォールバックルール、名前解決の戦略 |
7. カスタムルーティングでよくある質問
fullルールを最後に置いたのに、なぜ直結される?
より精密なルールが優先されるわけではありません。「設定」→「ルーティング設定」を開き、対象ルールを一致する可能性のあるgeositeや通常のドメインルールより前に移動します。保存して新しい接続を開始し、出力先タグを確認してください。
geoip:cnを設定したのに、ドメイン接続が地域別に振り分けられないのはなぜ?
まずrouting.domainStrategyを確認してください。AsIsでは、IPルール用にドメインを自動で名前解決しません。IPIfNonMatchの場合は、前方にドメインルールの一致がないか、末尾に判定を早く終了させる全体向けルールがないかを確認してください。
geositeを追加した後、コアの起動時にエラーが出る場合は?
まず追加した項目を取り消して接続を復旧し、起動ログを確認します。データファイルをコアが読み込めるか、指定した分類名が存在するかを重点的に確認してください。集合名を手当たり次第に変更して試さないでください。まずは単一のdomain:ルールでルーティングの流れを確認できます。
トップページはルールどおりなのに、ログインや画像で出口が異なるのはなぜ?
対象リクエストで実際に使われているホスト名を確認してください。ログインAPI、静的リソース、ダウンロードサービスは別のドメインを使うことがよくあります。full:でメインドメインを指定しても、それらは対象になりません。同じ管理対象ドメインに属する場合はdomain:に変更し、独立したドメインは個別に追加してください。あいまいなキーワードで対象を広げないようにしましょう。
コアを切り替えた後も、以前のルールをそのまま使える?
まず、切り替え先のコアが受け付ける設定形式・データセット・出力先タグを確認し、ルールを1つずつ検証してください。V2RayとXrayには共通する従来型のフィールドがありますが、クライアントが設定を生成する方法や拡張機能は異なる場合があります。インポートできても、すべての接続が以前と同じ経路で出力されるとは限りません。