プロキシへの接続は問題なくできていて、ドメイン名の名前解決品質を最適化したい方向け。読み終えると、中国国内・海外で分流するdnsセクションを自力で書けるようになり、expectIPsの検証の意味を理解したうえでv2rayNの設定項目に対応づけられるようになります。
DNS分流が解決する2つの問題
中国国内のネットワーク環境から海外ドメインを直接名前解決すると、応答が汚染されることがよくあります。返ってくるIPが目的のサイトのものではなく、接続がタイムアウトしたり、別のページに飛ばされたりします。暗号化されたリモート名前解決では問い合わせをTLSトンネルに包むため、汚染源が応答内容を改ざんできません。これが分流におけるDoHの中心的な役割です。
中国国内のドメインは逆です。リモート名前解決でも結果は得られますが、問い合わせ経路にプロキシが1ホップ余分に挟まり、さらに一部の中国国内CDNは名前解決の発生元によって異なるノードを返すため、リモート名前解決では遠方のノードを掴みやすくなります。中国国内ドメインはローカルDNSに任せて最寄りで名前解決すれば、CDNの振り分けも正確になります。
| 比較項目 | ローカルDNS | リモートDoH |
|---|---|---|
| 問い合わせ経路 | キャリアまたは公共DNSへ直接接続 | プロキシ経由の暗号化問い合わせ |
| 対象ドメイン | geosite:cn 中国国内ドメイン | geosite:geolocation-!cn 海外ドメイン |
| 汚染対策能力 | 弱い(平文で問い合わせ) | 強い(TLS内で改ざん不可) |
| 遅延の傾向 | 低い(最寄りで名前解決) | やや高い(プロキシが1ホップ挟まる) |
分流の目的は、問い合わせを機械的に分けることではなく、2種類のドメインをそれぞれの名前解決経路に流しつつ、routingルールとdnsセクションが同じドメイン集合を使うようにすることです。
dnsセクションの基本構造と分流の書き方
Xrayのdnsセクションはservers配列で、順番にマッチングされます。ドメインがエントリのdomainsリストに一致すればそのエントリが使われ、domainsを持たないエントリはすべてのドメインにマッチするため、最後にフォールバックとして置きます。次の記述を設定のルートノードに置くだけで動きます。
"dns": {
"servers": [
{
"address": "https://1.1.1.1/dns-query",
"domains": ["geosite:geolocation-!cn"],
"tag": "proxy"
},
{
"address": "223.5.5.5",
"domains": ["geosite:cn"],
"expectIPs": ["geoip:cn"]
},
"223.5.5.5"
]
}
1つ目は海外向けで、問い合わせはプロキシのアウトバウンド経由で送信されます。2つ目は中国国内向けで、expectIPsで応答の帰属を検証します。3つ目は素のアドレスによるフォールバックで、geositeデータに収録されていないドメインをカバーします。v2rayNが生成する設定では、プロキシのアウトバウンドタグはproxy、直結はdirectなので、参照時はこれに合わせてください。プロキシサーバーのアドレスはIPを直接書くのがおすすめです。名前解決の段階を減らせます。
ローカルDNS
- アドレス
- 223.5.5.5 または 119.29.29.29
- マッチ
- geosite:cn
- 検証
- expectIPs: geoip:cn
- アウトバウンド
- direct
中国国内ドメインは最寄りで名前解決され、CDNの振り分けが正確になります。
リモートDoH
- アドレス
- https://1.1.1.1/dns-query
- マッチ
- geosite:geolocation-!cn
- アウトバウンド
- tag: proxy
- 検証
- 任意で geoip:!cn
問い合わせはプロキシ経由で送信され、応答が汚染されることはありません。
固定の名前解決が必要なドメインはdns.hostsに書けます。これはservers配列より優先され、問い合わせは外部に送信されません。内部ネットワークのホスト名やセルフホストのサービスドメインに向いています。
routingルールとdomainStrategyの連携
dnsセクションはドメインを誰が名前解決するかを決め、routingは接続がどのアウトバウンドを通るかを決めます。dnsセクションだけを設定してroutingを設定しないと、トラフィックがすべてプロキシ経由になる可能性があります。逆にroutingだけを設定してdnsを設定しないと、中国国内ドメインもリモート名前解決で汚染されます。この2つは必ずセットで設定してください。
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:geolocation-!cn"],
"outboundTag": "proxy"
}
]
}
domainStrategy 3つの値の使いどころ
- AsIs:ドメイン名の文字列だけでルールにマッチさせ、自らは名前解決しません。ルールがすべてドメインで書かれていてIPルールに依存しない場合に向いています。
- IPIfNonMatch:ドメインルールに一致しなかった場合に名前解決してIPルールを試します。分流の場面でよく使われる値です。
- IPOnDemand:ルールにIP条件があれば名前解決するため、DNSリクエストが増えます。通常は必要ありません。
結論:dnsセクションとroutingで同じドメイン集合を使う
geosite:cnを両側に置き、海外側はgeosite:geolocation-!cnで補集合を取ります。間に空白を残さないようにしてください。残すと名前解決はDoH、接続は直結というズレが生じます。
expectIPsの汚染対策としての意味と検証方法
expectIPsはルーティングルールではなく、名前解決の結果を検証するだけのものです。結果が指定したgeoipリストに含まれていなければ破棄し、順番に次のサーバーを試します。中国国内エントリで最もよく使われる書き方はexpectIPs: ["geoip:cn"]で、ローカルDNSが中国国内IPだけを受け入れるようにします。
{
"address": "223.5.5.5",
"domains": ["geosite:cn"],
"expectIPs": ["geoip:cn", "geoip:private"]
}
expectIPsは否定も書けます。海外エントリにgeoip:!cnを追加すると、中国国内のCDNノードに解決された結果を拒否できます。検証に失敗したときにフォールバックせずエラーにしたい場合は、エントリにskipFallback: trueを付けます。geoip:privateは内部ネットワークのアドレス帯を許可するので、内部ドメインが誤って破棄されるのを防げます。
分流が機能しているか検証する
- 「設定」→「パラメータ設定」→「基本設定」でログレベルをdebugに変更し、ノードに再接続します。
- 海外サイトにアクセスし、ログでそのドメインが1つ目のDoHで名前解決され、問い合わせがプロキシ経由で送信されていることを確認します。
- 中国国内のサイトにアクセスし、問い合わせが223.5.5.5に届き、応答がgeoip:cnの検証を通過していることを確認します。
- コマンドラインで
nslookup www.qq.com 223.5.5.5を実行し、ローカルDNS自体が使えることを確認します。
結論:expectIPsは検証器であり、ルーターではない
expectIPsは不合格な名前解決結果を破棄するだけで、トラフィックの向きは変えません。どのアウトバウンドを通るかはroutingルールが決めるので、expectIPsに分流を任せようとしないでください。
よくある問題とトラブルシューティング
分流を設定して問題が起きたら、次の4つの手順で順に確認してください。
分流を有効にしたら中国国内サイトがかえって遅くなった?
まずログで問い合わせがどのサーバーに当たったか確認します。よくある原因はgeosite:cnのデータが古く、新しいドメインが収録されておらず、リモートDoHに流れていることです。geositeとgeoipのデータファイルを更新するか、そのドメインをdns.hostsに書いてローカル名前解決に固定してください。
リモートDoHがタイムアウトし続ける?
DoHエントリのtagがプロキシのアウトバウンドを指しているか確認し、v2rayNでは「リモートDNSはプロキシ経由」にチェックを入れます。1.1.1.1に直接接続できない場合は、アドレスをhttps://dns.google/dns-queryまたはhttps://8.8.8.8/dns-queryに変更してください。
海外ドメインの名前解決結果がまだ汚染されたIP?
そのドメインがgeosite:geolocation-!cnのカバー範囲外である可能性が高いです。dnsセクションの1つ目のdomainsとroutingの海外ルールが同じドメイン集合を使っているか確認し、ログレベルをdebugに上げて、問い合わせが実際にDoHエントリに当たっているか確かめてください。
config.jsonを手で編集したのに、ノードを選ぶと消えてしまう?
v2rayNはサーバーを切り替えるときに内蔵テンプレートで設定を再生成するため、手で編集したdnsセクションは上書きされます。分流の設定は「設定」→「パラメータ設定」→「DNS設定」で行い、生成された設定ファイルを直接編集しないでください。