この記事は、ノードへの接続ができ、通信の振り分けルールを調整したい方向けです。まずカーネルがドメインとIPのどちらを受け取っているか確認し、マッチ方法とルールの順序を決めて、ログで出口を検証します。掲載しているJSONはカーネル設定の一部であり、サブスクリプションの内容ではありません。違いを理解すれば、「ルールを追加したのに反映されない」「プライベートネットワーク宛ての通信が誤ってプロキシ経由になる」「分類ルールの読み込みに失敗する」といった問題を切り分けやすくなります。
1. ルーティングで通信の出口が決まる仕組み
v2rayNはクライアントの画面を提供し、実際のマッチングと転送はV2RayまたはXrayのカーネルが行います。VMessやVLESSはノードへの接続に使うプロトコルであり、特定のサイトの出口を決めるものではありません。ルーティングでは接続処理中に、宛先ドメインや宛先IP、ポート、インバウンドのタグなどをもとに、設定済みのアウトバウンドを選択します。
routing.rulesは上から順に評価され、最初に条件を満たしたルールで出口が決まります。「より細かい」ルールを探して評価を続けることはありません。どのルールにも一致しない場合、通常はoutbounds配列の先頭が使われるため、ルールの末尾だけでなくデフォルトの出口も確認してください。
- 同じ項目に複数の値を指定した場合、通常は「または」条件です:
domain配列のいずれかに一致すれば、ドメイン条件を満たします。 - 1つのルールに異なる条件を指定した場合、通常は「かつ」条件です:
domainとportを両方指定すると、ドメインとポートの両方が一致する必要があります。 - ルールは上から順に評価されます:個別の例外は広い範囲を対象とする分類ルールより前に、フォールバックルールは最後に配置します。
- アウトバウンドのタグは実在する必要があります:
outboundTagには、対応するアウトバウンドのtagを指定します。自由に書ける説明文ではありません。
2. domain・full・regexpのマッチ範囲
domainはルールのフィールド名であると同時に、フィールドの値に付けるプレフィックスでもありますが、両者は別のものです。フィールドはドメイン条件を入れる欄、プレフィックスはマッチ方法を指定するものです。ルートドメインとすべてのサブドメインを対象にするならdomain:、完全一致するホスト名だけを対象にするならfull:を使います。
| 記述方法 | マッチの動作 | マッチ範囲の例 |
|---|---|---|
example.com | プレフィックスなしの場合は部分一致 | notexample.comにもマッチする場合があります |
domain:example.com | ルートドメインとそのサブドメインにマッチ | img.example.comにはマッチし、notexample.comにはマッチしません |
full:api.example.com | ドメイン全体に完全一致 | img.api.example.comにはマッチしません |
regexp:^api[0-9]+\\.example\\.com$ | 正規表現(ここではJSON文字列内の記述例) | api12.example.comにはマッチし、api.example.comにはマッチしません |
ドメインルールでは、WebページのURLパスは判定できません。たとえばhttps://api.example.com/v1/statusの場合、宛先ドメインはapi.example.comです。プロトコル、パス、クエリパラメーターをドメイン欄に含めないでください。HTTPSのパスも、通常のルーティングルールで直接判定できる条件ではありません。
{
"type": "field",
"domain": [
"full:api.example.com",
"domain:static.example.net",
"regexp:^edge[0-9]+\\.example\\.org$"
],
"port": "443",
"outboundTag": "proxy"
}
このルールでは、3つのドメイン条件のいずれかに一致し、かつ宛先ポートが443の場合にproxyを使います。正規表現のドットはエスケープが必要です。JSON文字列ではバックスラッシュもエスケープするため、\\.と記述します。クライアントのプレーンテキストのドメイン欄に入力する場合、通常は\.だけで十分です。入力方法を混同しないようにしてください。
3. ip・CIDR・geoipの使い分け
ipフィールドでは、宛先IPを対象に、単一のアドレス、CIDR形式のネットワーク、またはgeoip:分類を指定できます。判定するのは今回の通信の宛先アドレスであり、PCのネットワークインターフェースのIPやノードサーバーのIPではありません。アプリがIPアドレスへ直接アクセスする場合、ドメインを解決しなくてもIPルールにマッチします。
IPアドレスを直接指定するルール
- 単一アドレス
192.168.1.10- IPv4ネットワーク
192.168.0.0/16- IPv6ネットワーク
fc00::/7- データへの依存
- 地理分類ファイルに依存しない
範囲が明確なLANや固定サービス用ネットワークに適しています。
geoip分類ルール
- プライベートアドレスの分類
geoip:private- 地域別アドレスの分類
geoip:cn- 主なデータファイル
geoip.dat- 確認・管理のポイント
- 分類が存在し、データを読み込めること
分類の範囲は使用するデータセットによって異なり、リアルタイムのネットワーク上の所在地を示すものではありません。
{
"type": "field",
"ip": [
"127.0.0.0/8",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"::1/128",
"fc00::/7"
],
"outboundTag": "direct"
}
上の例は、特定のネットワークを明示的に直接接続する設定であり、特殊用途アドレスの完全な一覧ではありません。geoip:privateを使う場合は、現在のデータセットに含まれる範囲を確認してください。社内ネットワークでは、「プライベートアドレスの分類に含まれるはず」と推測せず、実際に使っているネットワークを個別に指定するのがおすすめです。
4. geositeの参照方法とデータファイル
geosite:はdomain配列に記述し、ドメインの集合を参照します。一方、geoip:はip配列に記述します。互いに置き換えられるプレフィックスではありません。geosite:cnは、データセット内のcnという集合を参照する指定であり、単に末尾が.cnのドメインすべてを意味するわけではありません。
{
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
}
- まず、集合が存在するか確認します:同じ名前のデータファイルでも、提供元によって分類名や内容、属性が異なる場合があります。
- 2種類の読み込みエラーを区別します:
geosite.datが見つからない場合は、ファイルまたはリソースのパスに問題があります。指定した分類が見つからない場合は、集合名またはデータのバージョンを確認してください。 - 更新後にもう一度検証します:集合の内容が変わればマッチ結果も変わる可能性があります。更新が成功しても、従来と同じ振り分けになるとは限りません。
- 必要に応じて属性で絞り込みます:たとえば
geosite:google@cnが意図したとおりに機能するのは、使用中のデータセットに該当項目の属性が用意されている場合に限られます。名前だけから判断しないでください。
設定の読み込み時にカーネルがすぐ終了する場合は、ノードを何度も切り替えるのではなく、まずログでリソースの読み込みエラーを確認します。分類ルールが正しく読み込まれていない状態では、接続速度のテストをしてもルーティング設定の正しさは確認できません。問題のある分類参照を一時的に外し、明示的なドメインルールを1つ残すと、設定の誤りとネットワーク障害を切り分けやすくなります。
5. domainStrategyがIPルールに与える影響
routing.domainStrategyは、ルーティングの判定時にドメイン宛てのIPアドレスを解決するかどうかを制御します。最終的なアウトバウンドで使うDNSの設定とは別のものです。また、アプリがすでに失ったドメイン情報を復元する機能でもありません。アプリからIPアドレスだけが渡される場合にドメインルールを使うには、インバウンドでのスニッフィングなども検討する必要があります。ただし、スニッフィングはすべての通信に有効とは限りません。
| ポリシー | ドメイン宛て通信の処理 | よくある影響 |
|---|---|---|
AsIs | ルーティング判定のためにドメインをIPへ積極的に解決しない | ドメイン宛て通信は通常、IPルールだけでは振り分けられません。もともとIPアドレス宛ての通信はマッチできます。 |
IPIfNonMatch | まず受け取った情報で照合し、マッチしなかった場合にドメインを解決して再照合 | 最初の評価でフォールバックルールにマッチすると、再評価のための名前解決は行われません。 |
IPOnDemand | 評価中に宛先IPが必要な条件に達した時点で、ドメインを解決 | 前方にあるIPルールが先にマッチし、後続のドメイン例外に影響する場合があります。 |
よくある誤りは、IPIfNonMatchを設定したうえで、ルールの最後にすべてのTCP・UDP通信にマッチするプロキシルールを置くことです。このフォールバックは最初の評価で必ずマッチするため、ドメイン宛て通信は「マッチしなかった後にIPを解決する」段階に進みません。その結果、前方にあるgeoip:cnが、解決後のIPを判定できないことがあります。
ポイント:フォールバックを決めてから、名前解決のポリシーを選ぶ
マッチしなかったドメインをIP分類で振り分ける場合、IPIfNonMatchでは、最初の評価で必ずマッチするルールを末尾に追加せず、先頭のアウトバウンドをフォールバックとして利用できます。IPOnDemandを使う場合は、残しておきたいドメイン例外を範囲の広いIP分類より前に配置してください。
ここでのDNSの結果は、IP分類の判定に直接影響します。「同じドメインなのに、今日は直接接続で明日はプロキシ経由」という場合、ルール順序の問題と決めつけず、名前解決の結果と分類データの両方を確認してください。DNSとルーティングの各項目については、設定リファレンスも参照してください。
6. 優先順位を付けたルーティング設定例
ここではIPOnDemandを使い、「指定ドメインの例外、プライベートネットワークへの直接接続、ドメイン分類、IP分類、最後にプロキシ」の順で設定しています。既存の設定に組み込めるroutingオブジェクトのみの例です。設定内にproxyとdirectの2つのアウトバウンドタグがあり、必要な分類データが利用できることが前提です。
{
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"domain": [
"full:api.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"
}
]
}
}
例のapi.example.comはルールの説明用に予約されたドメインであり、接続テスト用のサービスではありません。最初のルールに置いているため、後続のIP分類にマッチする可能性があっても、優先してプロキシが選ばれます。実際に使うときは、このルールを出口を固定したい業務用ドメインに置き換えるか、削除してください。
- 現在の設定を保存します:クライアントから既存の設定をエクスポートし、現在有効なルーティング方式を記録しておきます。変更に失敗しても元に戻せるようにしてください。
- 実際のタグを確認します:生成された設定の
outboundsにあるtagを確認し、例のタグと一致しているか確かめます。クライアントによってタグ名は異なる場合があります。 - routingオブジェクトだけを統合します:この内容で設定全体を上書きすると、インバウンド、ノードのアウトバウンド、DNSなどの必要な設定が失われます。
- 画面から保存して有効にします:v2rayNのメニュー名はバージョンによって異なります。一般的には「設定」→「ルーティング設定」から開きます。ルールを追加したら、対象のルーティング方式が有効になっていることも確認してください。
- 接続を新しくしてテストします:保存後、クライアントの案内に従ってカーネルを再読み込みするか再起動し、既存のWeb接続を閉じてからテストします。確立済みの接続では、ルーティングが再評価されない場合があります。
7. ルールが実際にマッチしたか確認する方法
Webページが開けても、接続に成功したことしか分からず、出口が正しいとは限りません。振り分けを検証する際は、宛先、プロトコル、選択された出口、テスト時刻を記録してください。まず単一の完全一致ドメインで最小限のテストを行い、その後で分類ルールを少しずつ追加すると、十数件を一度に変更するより原因を特定しやすくなります。
- 通信がカーネルに届いていることを確認します:ブラウザーがシステムプロキシを使用しているか確認してください。コマンドラインからは
curl --proxy socks5h://127.0.0.1:10808 https://example.com/ -Iを実行できます。10808はクライアントで実際に使用しているSOCKSインバウンドのポートに置き換えてください。 - 宛先のドメインを維持します:上記のコマンドは
socks5hを使い、ドメインの処理をプロキシ側に任せます。アプリがローカルで名前解決してからIPを送る場合、ドメインルールをテストする前提が変わります。 - カーネルのログを確認します:宛先アドレスとアウトバウンドタグを確認します。ログの形式はカーネルのバージョンによって異なります。アクセスログが無効な場合は、使用中のバージョンに合わせて一時的に有効にしてください。「記録がない」ことを「通信がない」と判断しないようにしましょう。
- 3種類の通信を比較します:明示的なドメイン例外、到達可能なプライベートネットワークのアドレス、一般的なインターネット上のドメインをそれぞれテストし、想定した出口と実際の出口を記録します。イントラネットのポートには、環境に応じて
80または443を使えます。 - テスト条件を元に戻します:既存の接続を閉じてから再試行し、必要であればテストに使ったアプリを再起動します。テスト後は通常のログレベルに戻し、詳細なアクセス記録が長期間蓄積されないようにしてください。
fullルールを追加したのに、サブドメインがプロキシ経由にならないのはなぜですか?
full:example.comが対象にするのは、完全一致するこのホスト名だけです。www.example.comも対象にするにはdomain:example.comに変更し、広い範囲を直接接続するルールより前に移動してから、接続をやり直してください。
domainとipを両方指定したら、なぜマッチしにくくなるのですか?
同じルールに指定した2つのフィールドは、どちらか一方が一致すればよいという意味ではありません。「このドメイン群またはこのIP群を直接接続したい」場合は、ルールを2つに分け、どちらにも同じoutboundTagを指定してください。
geositeの分類をコピーした後、カーネルが起動しなくなった場合はどうすればよいですか?
最初に出ている読み込みエラーを確認し、geosite.datのリソースパスと分類名を調べてください。まずその分類を外し、full:ルールでカーネルが正常に動作することを確認してから、利用可能なデータファイルと分類を戻します。
Android版にデスクトップ版の設定全体をそのまま流用できますか?
v2rayNGはXrayカーネル、v2flyNGはv2flyカーネルを使用します。基本的なマッチ構文は似ていますが、アウトバウンドタグ、リソースファイルの場所、インポート方法はクライアントによって異なります。選択したカーネルが対応する項目を確認してからルーティング設定の一部を移行し、実行設定全体をそのまま上書きしないでください。
問題を切り分ける際は、「宛先情報、ルールの順序、名前解決ポリシー、データファイル、実際の出口」の順に確認してください。まず正確なルールが1つ動作することを確かめてから、ドメイン集合やIP分類を追加すると、ルール全体を何度も入れ替えるより確実です。