V2RayのDNS振り分け設定|中国本土のドメインは直接解決、海外ドメインはDoHで保護

DNSの仕組みから、ドメインごとにDNSサーバーを使い分ける設定方法を解説。FakeDNSやキャッシュ、ルーティング連携でつまずきやすい点も紹介します。

この記事の概要

この記事では、プロキシのアウトバウンドが利用可能で、DNSポリシーを調整したい方を対象に、まずDNSサーバーの選択とクエリの通信経路を区別します。次に、中国本土向けルール、リモートDoH、直接接続のアウトバウンドを組み合わせ、最後に独立したテスト用エンドポイントで名前解決の経路を確認します。例にはV2Ray形式のJSONを使用します。サブスクリプションのサーバー設定を置き換えるものではなく、すべてのクライアントが同じコアを使うことを前提としていません。

1. DNSの振り分けでは、DNSサーバーの選択とクエリのルーティングを分けて考える

DNSの振り分けは、サーバーアドレスを2つリストに登録するだけでは完了しません。まず、ドメインごとにどのDNSサーバーへ問い合わせるかを決め、次に、そのDNSサーバーへの接続を直接接続とプロキシのどちらに通すかを決めます。この2段階を明確にして初めて、海外ドメインのクエリが意図した経路を通っているか判断できます。暗号化DNSはクエリの通信を保護しますが、DNSサーバーの応答が常に正しいことを保証するものではありません。

ドメインがコアに渡る DNSサーバーを選択 クエリのルートを判定 名前解決の結果を取得 接続先へ接続

コアのDNSは、OSのDNSと同じものではありません。アプリがドメイン名をSOCKS経由で渡す場合、プロキシプロトコルを通じてサーバー側で名前解決されることがあります。アプリが先にシステムのDNSでIPアドレスを取得した場合、コアに渡るのはIPアドレスだけかもしれません。設定のdnsオブジェクトを変更しても、PCやスマートフォン上のすべてのアプリのDNS問い合わせが自動的に切り替わるわけではありません。

2. 設定前にコア、ルールファイル、アウトバウンドのタグを確認

v2rayNはデスクトップ向けの設定管理クライアントで、実際の動作は選択中のコアによって異なります。Android向けのv2rayNGはXrayコア、v2flyNGはV2Flyコアを使用します。多くの設定項目は共通していますが、DNSオプション、FakeDNSの動作、初期値がすべて同じとは限りません。まずコア名とバージョンを確認し、対応する設定ドキュメントで各項目のサポート状況を調べてください。

  1. v2rayNの「設定」→「パラメーター設定」で、使用中のコアに関する項目を確認します。DNS設定の編集場所はクライアントのバージョンによって異なるため、実際の画面で確認してください。
  2. 現在の設定をバックアップし、生成された設定のoutboundsを確認して、プロキシと直接接続の各アウトバウンドで実際に使われているtagを控えます。
  3. 実行ディレクトリにあるgeosite.datを読み込めることと、cnカテゴリが含まれていることを確認します。IPカテゴリを使う場合に限り、対応するgeoip.datルールも必要です。
  4. DNSを調整する前に、プロキシ接続が使えることを確認します。プロキシのアウトバウンド自体に接続できない場合、リモートDNSの失敗をDNSサーバーの問題と決めつけることはできません。
53
直接接続DNSの例で使うUDPポート
443
リモートDoHの例で使うHTTPSポート
1053
後述のループバックテスト用ポート

これらの数字は設定例のポート番号であり、性能測定の結果ではありません。以下では、既存のプロキシアウトバウンドをproxy、直接接続のアウトバウンドをdirectと呼びます。実際のタグが異なる場合は、参照箇所もすべて合わせて変更してください。ルール内の名前だけをコピーしても動作しません。

3. 中国本土のドメインは直接接続DNS、それ以外はリモートDoHを使用

以下の設定例を、既存設定のトップレベルにあるdnsフィールドへ統合します。中国本土のカテゴリに該当するクエリは223.5.5.5を優先し、該当しないクエリにはhttps://1.1.1.1/dns-queryを使います。これらは具体的な設定例であり、あらゆるネットワーク環境で接続できることや、この2つのパブリックDNSを必ず使うべきことを意味するものではありません。

{
  "dns": {
    "queryStrategy": "UseIPv4",
    "servers": [
      {
        "address": "223.5.5.5",
        "port": 53,
        "domains": [
          "geosite:cn"
        ],
        "skipFallback": true
      },
      {
        "address": "https://1.1.1.1/dns-query"
      }
    ]
  }
}

リモートDNSのアドレスにIPアドレスを直接指定すると、「DoHに接続するために、先にDoHのドメインを名前解決する」という依存を減らせます。ただし、TLS証明書の検証は引き続き必要です。接続エラーを解消するために証明書検証を無効にしないでください。DNSサーバーをドメイン名で指定する場合は、そのドメイン名の初期名前解決も用意し、まだ確立していない同じDNS経路に再び依存しないようにします。

4. DNSクエリのアウトバウンドを指定し、既定のルートによる経路変更を防ぐ

以下のルール例ではAsIsを使い、まず2つのDNSエンドポイント、次に中国本土のドメインを処理し、最後に残りのTCP・UDP接続をプロキシへ送ります。通常のhttps://形式のDoHと、直接接続の意味を持つhttps+local://は同じものとして扱えません。この例ではDNSクエリの接続をコアのルーティングに通す必要があるため、前者を使います。

{
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "ip": ["223.5.5.5"],
        "port": "53",
        "network": "udp",
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": ["1.1.1.1"],
        "port": "443",
        "network": "tcp",
        "outboundTag": "proxy"
      },
      {
        "type": "field",
        "domain": ["geosite:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

これは通信経路を確認しやすくするための基本ポリシーで、LAN、企業内ネットワーク、広告カテゴリなどのルールは含みません。既存設定に統合する際は必要なルールを残し、順序を確認してください。通常、ルールは上から順に照合されるため、末尾に置くフォールバックがDNSエンドポイントのルールより先に処理されないようにします。また、上記のIPアドレスとポートのルールは、同じエンドポイントに接続するほかの通信にも適用されます。DNSモジュールが生成した通信だけを判別するものではありません。

直接接続のアウトバウンドでは、Freedomのドメイン処理ポリシーも確認してください。以下は既存の直接接続アウトバウンドに必要な構成例です。同じタグを持つアウトバウンドを追加するのではなく、該当する項目を編集してください。UseIPを指定すると、このアウトバウンドは内蔵DNSで接続先のIPアドレスを取得します。指定しない場合、既定の動作では引き続きシステムDNSに依存することがあります。

{
  "tag": "direct",
  "protocol": "freedom",
  "settings": {
    "domainStrategy": "UseIP"
  }
}

まとめ:名前解決先と接続経路をそれぞれ検証する

まず、中国本土向けの直接接続アウトバウンドが内蔵DNSを実際に呼び出していることを確認し、次にリモートDoHへの接続がプロキシに振り分けられていることを確認します。Webページが開けるだけではDNSの振り分けが有効になった証拠にはなりません。プロキシリクエストにドメイン名が含まれる場合、接続先の名前解決はサーバー側で行われることがあります。

5. 独立したDNSエンドポイントで検証し、ブラウザーのキャッシュを結果と混同しない

内蔵DNSモジュールを直接テストするには、既存のinboundsとoutbounds配列に以下のオブジェクトをそれぞれ追加します。インバウンドは127.0.0.1のみにバインドし、外部から接続できるアドレスに変更しないでください。このエンドポイントはローカルでのトラブルシューティング用です。システムDNSを自動変更したり、ブラウザーのクエリを自動的に処理したりするものではありません。

{
  "tag": "dns-in",
  "listen": "127.0.0.1",
  "port": 1053,
  "protocol": "dokodemo-door",
  "settings": {
    "address": "1.1.1.1",
    "port": 53,
    "network": "tcp,udp"
  }
}
{
  "tag": "dns-out",
  "protocol": "dns",
  "settings": {}
}

続いて、以下のルールを先ほどのrouting.rulesの先頭に置きます。テスト用リクエストをDNSアウトバウンドへ送り、末尾のプロキシ用フォールバックルールに拾われないようにします。DNSアウトバウンドはAレコードとAAAAレコードの問い合わせに内蔵DNSモジュールを呼び出します。その他のレコードタイプの処理や転送動作は個別に確認してください。この例のアドレスレコードのテストを、TXTレコードの問い合わせ1回で代用しないでください。

{
  "type": "field",
  "inboundTag": ["dns-in"],
  "outboundTag": "dns-out"
}
  1. コアを再起動し、まず設定読み込みログを確認します。ポートの競合、未対応フィールド、ルールファイルの読み込みエラーがないことを確認してください。
  2. digがインストールされた環境で以下のコマンドを実行し、中国本土向けカテゴリとリモートDNSの経路をそれぞれテストします。
  3. DNSのデバッグログとアウトバウンドのアクセスログを照合し、2つのDNSエンドポイントで実際に使われたタグを確認します。トラブルシューティング中は一時的にログレベルを上げ、完了後に元へ戻してください。
  4. 一度に変更する設定は1つだけにします。繰り返し問い合わせるとキャッシュが使われることがあります。必要に応じてコアを再起動し、アプリやシステムのキャッシュを消去してから結果を比較してください。
dig @127.0.0.1 -p 1053 www.baidu.com A
dig @127.0.0.1 -p 1053 www.example.com A

テスト用ドメインがカテゴリに該当するかどうかは、現在のルールファイルで確認してください。名前解決の結果が異なっても、必ずしもDNS汚染を意味するわけではありません。CDNの振り分け、DNSサーバーの場所、キャッシュの状態によって応答は変わります。IPアドレスを2回比較するだけでなく、問い合わせ先が想定どおりか、タイムアウトが発生していないか、最終的な接続が成功するかを確認してください。

6. FakeDNS、キャッシュ、ルーティングの名前解決方式を正しく理解する

FakeDNSが返すのは、コア内でマッピングするための合成アドレスであり、接続先サイトの実際のアドレスではありません。主に、通信がプロキシに入った後もドメイン情報を保持または復元できるようにする仕組みです。実際のDNSサーバーの代わりにはならず、接続できないプロキシサーバーを直すものでもありません。有効にする前に、使用中のコア、通信の取り込み方法、ドメイン名の復元経路が設定に対応していることを確認してください。

設定・仕組み実際の役割よくある誤解
DNS queryStrategy内蔵DNSモジュールが問い合わせる、または使用するアドレスファミリーを制御します。IPv4に設定すれば、すべてのアプリがIPv6通信を行わなくなると思い込む。
routing.domainStrategyルーティングの照合時に、ドメイン名からIPアドレスを取得するかどうかを制御します。AsIsを、コア全体でドメイン名を一切解決しない設定だと思い込む。
Freedom domainStrategy直接接続のアウトバウンドが接続を確立する際、ドメイン名をどう処理するかを制御します。DNSサーバーのリストだけを変更し、直接接続のアウトバウンドはシステムDNSに依存したままにする。
FakeDNSドメイン名と合成アドレスの対応を保持します。後続の通信が、対応関係を復元できるコアに戻る必要があります。合成応答だけを有効にし、対応する接続も取り込まれるようにしていない。
DNSキャッシュ以前取得した名前解決の結果を再利用し、重複した問い合わせを減らします。設定変更後に古い結果が表示されたため、新しい設定が読み込まれていないと判断する。

IPIfNonMatchは、ドメインルールが一致しない場合に名前解決を試み、その後IPルールの照合を続けます。IPOnDemandは、IPアドレスを必要とするルールを照合するときに名前解決を行います。どちらもローカルでのDNS問い合わせが増える可能性があります。設定に必ず一致するフォールバックルールがある場合、すべてのドメインがIPによる名前解決まで進むとは限らない点に注意してください。

7. DNS振り分けでよくある質問とトラブルシューティング

リモートDNSを設定したのに、ブラウザーがローカルDNSサーバーへ問い合わせるのはなぜ?

まず、クエリがコアに入っているかを確認します。前述の1053番ポートのテスト用エンドポイントで個別に検証し、その後ブラウザーのセキュアDNSとシステムプロキシの動作を確認してください。通常のシステムプロキシは主にアプリの接続を処理するもので、OSのUDP 53番ポートの問い合わせを取り込む設定ではありません。

中国本土のサイトは開けるのに、海外ドメインの名前解決がタイムアウトする場合は?

1.1.1.1:443がproxyに振り分けられているかを確認し、そのタグが実際に存在することと、プロキシ接続が正常であることを確かめます。続いてTLSエラーとシステム時刻を確認してください。プロキシサーバーのアドレス自体がドメイン名の場合は、その初期名前解決がリモートDoHに依存してループしていないかも確認します。

サブスクリプションを更新したら、追加したDNS設定が消えたのはなぜ?

変更をクライアントが一時的に生成した実行用設定ファイルに書き込んでいないか確認してください。ノードの切り替えや再起動で、生成ファイルが上書きされることがあります。使用中のバージョンに用意されたDNS設定またはカスタム設定の入力欄に保存してから、生成された設定を再確認し、該当フィールドとタグが保持されているか確かめてください。

FakeDNSを有効にしたら一部のアプリがまったく接続できない場合、まず何を戻す?

まず通常の名前解決に戻してコアを再起動し、関連アプリのキャッシュを消去します。接続が復旧したら、合成アドレスへの接続が同じコアに戻っているか、インバウンドのドメイン名復元設定が使用中のコアの要件に合っているかを確認してください。合成アドレスを取得したアプリが、通信の取り込みを迂回して直接接続する状態にしないでください。

最終確認では、現在のコアと設定の取得元、2つのDNSエンドポイントに対応するアウトバウンドタグ、独立したテスト用エンドポイントの問い合わせログの3点を記録してください。これにより、DNSサーバーの選択、クエリの通信経路、接続先への接続のどの段階に問題があるか切り分けられます。パブリックDNSのアドレスを何度も変更する必要はありません。

クライアントをダウンロード