DNSリークを防ぐには、リクエストの入口、リゾルバー、通信経路をあわせて確認する必要があります。ノードには接続できるものの、名前解決もプロキシ経由か判断できない方に向けて、まず直結時とプロキシ利用時を比較し、次にv2rayN・v2rayNGのDNSを設定します。最後にFakeDNS、ブラウザーのセキュアDNS、ルーティングの例外を確認します。検出結果は実際のルールと照らし合わせ、リゾルバーの所在地だけで判断しないでください。
1. DNSリークの判断:まずプロキシ経由にするクエリを決める
ドメインにアクセスすると、通常はIPアドレスを取得してから通信を開始します。Webページへの接続がプロキシ経由でも、その前のDNSクエリまでプロキシ経由とは限りません。システムプロキシが変えるのは、主にプロキシ対応アプリの通信経路です。通常、デバイス全体のUDP 53番ポートのクエリは制御しません。
この記事では、「プロキシ経由にするはずのドメインクエリが、ローカルネットワークから送信される」ケースを調べます。LAN内のドメインやローカルドメイン、指定サイトを直結にするルーティングポリシーの場合、そのクエリがローカルリゾルバーを使うのは設定どおりの動作です。すべてのパブリックドメインのクエリをプロキシ経由にするには、ローカルへのフォールバックやアプリによる迂回も制限する必要があります。
| 検出結果 | この結果だけでは判断できないこと | 次に確認すること |
|---|---|---|
| Webサイトの接続元IPが変わった | すべてのDNSクエリがプロキシ経由である | ブラウザー、システム、コアの各リゾルバー |
| パブリックDNSが表示された | クエリが必ずプロキシ経由である | DoH接続が直結とプロキシのどちらへルーティングされているか |
| 複数のリゾルバーが検出された | 必ずリークが発生している | 分割ルーティング、フォールバック、リゾルバーのクラスタリングが使われているか |
| ローカル回線事業者のリゾルバーが表示された | ノードの設定に問題がある | システムのクエリ、ブラウザーのフォールバック、直結対象のドメインがないか |
判断の基本:想定する経路を先に決めてから結果を確認
「パブリックドメインはプロキシ経由で名前解決し、LAN内の名前はローカルで解決する」想定なら、それぞれのクエリを個別にテストします。リゾルバーの名前や所在地は手がかりにすぎません。送信ログやパケットキャプチャの証拠とあわせて判断してください。
2. 直結時と比較:ブラウザーの検査と端末のパケットキャプチャ
まずプロキシを一時停止し、DNS検査ページに表示されるリゾルバー情報を記録します。次にプロキシを有効にし、同じブラウザーで再度テストします。検査ページは通常、ランダムなサブドメインへのクエリを発生させるため、キャッシュの影響を抑えられます。ただし、主に現在のブラウザーの名前解決経路を調べるもので、ほかのアプリも制御されている証明にはなりません。
-
基準値を記録する
現在のネットワーク、プロキシモード、ブラウザーのセキュアDNS、システムのプライベートDNSの状態を記録します。まず直結でテストし、その後プロキシを有効にします。2回のテストでは、ほかの設定を変えないでください。
-
キャッシュをクリアする
Windowsでは、以下のコマンドでシステムのDNSキャッシュをクリアできます。ブラウザーに独自のキャッシュがある場合もあるため、関連ページを閉じてから開き直してください。キャッシュをクリアしても、既存の接続が自動的に新しい経路へ切り替わるわけではありません。
-
ランダムなドメインで再テストする
DNS検査ページでテストを新たに実行します。前回の結果を更新するだけでは不十分です。リゾルバーのアドレスと事業者を記録し、直結時の結果と比較してください。ページに表示された地域だけで判断しないでください。
-
通信経路を確認する
実際に通信しているネットワークアダプターでUDP/TCP 53番ポートのトラフィックを確認します。テスト対象のドメインへのクエリが、ルーターや回線事業者のリゾルバーへ直接送信されていないか調べ、コアのログと照合してリモートDNSの送信経路を確認します。
ipconfig /flushdns
nslookup example.com
nslookup example.com はシステム側のクエリ動作を確認するコマンドで、HTTPプロキシやSOCKSプロキシのテストではありません。システムプロキシを有効にしただけでは、システムに指定されたDNSへクエリが送信される場合があります。TUNを有効にした場合にクエリが制御されるかは、そのモードのDNSリダイレクトとルーティング設定によります。
3. v2rayN:システムプロキシ、TUN、リモートDNSを個別に設定
v2rayNはデスクトップクライアントです。実際の名前解決とルーティングは、選択中のコアと生成される設定によって決まります。まずメイン画面で現在のノードが利用可能か確認し、「設定」→「DNS設定」を確認してください。ビルドによって項目の配置は異なります。該当する項目が画面にない場合は、実際に生成された設定を確認してください。別バージョンの画面を固定のメニュー構成とみなさないでください。
-
通信を制御する範囲を確認する
ブラウザーだけをテストする場合は、まずシステムプロキシを使います。システムプロキシに従わないアプリも対象にするには、メイン画面でTUNモードを有効にし、システムの許可が正常に得られたことを確認します。TUNを有効にしただけでDNSリダイレクトも機能するとは限りません。
-
リモートDNSを設定する
「設定」→「DNS設定」を開き、現在のコアに対応するリモートDNS欄に、サポートされているリゾルバーのアドレスを入力します。たとえば
https://1.1.1.1/dns-queryはDoHのアドレスです。通常のIPアドレスだけを受け付ける入力欄には設定できません。 -
DNSのルーティングを確認する
「設定」→「ルーティング設定」と、現在有効なルールセットを確認します。リモートDNSへの接続が先行する直結ルールに拾われていないことを確認してください。また、ノードサーバーのアドレスに必要なブートストラップ名前解決の経路は残します。
-
再起動して再テストする
設定を保存して現在のサービスを再起動し、キャッシュをクリアしてから同じ条件で比較テストします。TUNに切り替えた後はシステム側のクエリもテストしてください。ブラウザーで成功しただけで、デバイス全体のDNSが制御されたと判断しないでください。
システムプロキシモードでは、ローカルの待ち受けアドレスにも注意してください。アプリで使うHTTPまたはSOCKSポートは、クライアントに表示されている値と一致させます。DNSの53番ポートはSOCKSの接続先ではありません。リモートDNSのアドレスをアプリのプロキシサーバー欄に入力したり、DNSの問題を解決するためにLANへの待ち受けを安易に公開したりしないでください。
4. v2rayNG:ローカルDNS、リモートDNS、対象アプリを確認
v2rayNGはAndroidのVPNインターフェイスを使ってアプリの通信を受け持ち、コアにはXrayを使用します。ここでいう「ローカルDNS」は通常、名前解決ポリシーにおけるローカル側のサーバーを指し、必ずしもローカルのループバックアドレスだけで待ち受けるという意味ではありません。設定項目の説明と生成された設定をあわせて確認し、名称だけでデータが端末外へ出るか判断しないでください。
-
対象アプリを確認する
「設定」→「アプリごとのプロキシ」を開き、選択したアプリだけをプロキシ経由にする設定か、選択したアプリを除外する設定か確認します。テストに使うブラウザーがプロキシの対象外だと、そのアプリの直結動作が検出されます。
-
コアでの名前解決を有効にする
「設定」を開き、「ローカルDNSを有効にする」とDNS設定項目を探します。現在のビルドに該当するスイッチがある場合は有効にし、「リモートDNS」と「ローカルDNS」に設定されている値を確認します。メニューの表記はバージョンによって多少異なる場合があります。
-
リモートDNSを設定する
「リモートDNS」に、現在のコアがサポートするサーバーアドレスを入力します。たとえば
https://1.1.1.1/dns-queryを指定できます。まずリモートDNSを1つだけ設定してテストし、未検証のフォールバックサーバーを複数重ねないでください。 -
システム側の名前解決を確認する
Androidのシステム設定で「プライベートDNS」を検索します。現在の状態を記録してから、比較用に一時的に無効にしてください。テスト後は元の設定に戻し、暗号化された名前解決の接続が想定どおりにルーティングされるか確認します。
-
再接続してログを確認する
接続をいったん切り、再接続して、名前解決エラーやリクエストのタイムアウトがないか確認します。除外したアプリだけがローカルリゾルバーを使っている場合は、DNSアドレスを次々と変更するのではなく、まず対象アプリの設定を見直してください。
5. リモートDNSのルーティング:暗号化されていてもプロキシ経由とは限らない
DoHは通信中のクエリを暗号化しますが、プロキシを使うかどうかは接続のルーティングによって決まります。Xray内蔵DNSの通常のhttps://クエリはコアのルーティング対象にできます。一方、https+local://はローカルクエリモードです。コアのプロキシルーティングを経由させる必要がある場合は、両者を混在させないでください。
以下は仕組みを説明するためのXray設定例で、クライアントの完全な設定ではありません。内蔵DNSのクエリにdns-queryのタグを付け、そのタグの通信を既存のproxyアウトバウンドに送ります。使用前に、現在のコアが該当する項目に対応していることと、実際のプロキシアウトバウンドのタグがproxyであることを確認してください。
{
"dns": {
"tag": "dns-query",
"servers": [
"https://1.1.1.1/dns-query"
],
"queryStrategy": "UseIPv4"
},
"routing": {
"rules": [
{
"type": "field",
"inboundTag": ["dns-query"],
"outboundTag": "proxy"
}
]
}
}
- 既存設定に追加し、置き換えない:DNSルールは既存のルール一覧に適切な位置で追加します。通常は、そのルールに一致する可能性のある広範な直結ルールより前に配置します。クライアントが生成した
routing全体を置き換えないでください。 - 内部処理と外部通信を区別する:
dns.tagがタグ付けするのは内蔵DNSが送信するクエリです。すべてのアプリからUDP 53番ポートへ送られるパケットが、自動的に内蔵リゾルバーへ取り込まれるわけではありません。システム側のクエリには、引き続きDNSリダイレクトまたは専用のDNSインバウンド処理が必要です。 - ブートストラップ名前解決を確保する:ノードのアドレスがドメイン名で、リモートDNSへのアクセスにもそのノードが必要な場合、起動時に依存関係が発生します。ノードのドメイン名を解決できるブートストラップ経路を用意するか、アドレスが有効だと確認したうえで適切な固定マッピングを使ってください。
- IPv6の方針を明確にする:例の
UseIPv4は今回の名前解決条件を限定するもので、システムのIPv6を無効にする設定でも、一般的なDNSリーク対策でもありません。IPv6を使う場合は、AAAAレコードの解決とIPv6接続のルーティングもあわせて検証してください。
設定の要点:まず単一の経路を検証し、その後に分割ルーティングを追加
まず1つのリモートDNSがプロキシ経由で安定してクエリを処理できる状態にし、その後、本地域名のルール、予備のリゾルバー、IPv6を順番に追加します。項目を追加するたびに再テストすれば、どの例外が送信経路を変えたのか特定できます。
6. FakeDNS:仮想アドレスを返すだけでは不十分
FakeDNSは、接続先サイトの実IPアドレスをアプリに返す代わりに仮想アドレスを割り当て、ドメイン名と仮想アドレスの対応を保存します。アプリがそのアドレスに接続すると、コアは対応情報からドメイン名を復元し、ルーティングとアウトバウンド処理に渡します。特定の状況で実IPアドレスによる事前解決を減らせますが、暗号化されたリモートDNSの代わりにはなりません。
よく使われるIPv4仮想アドレスプールは198.18.0.0/15、範囲は198.18.0.0から198.19.255.255です。この範囲はWebサイトのパブリックIPアドレスではありません。FakeDNSでクエリを処理した後、接続が同じ経路で制御されないと、アプリは接続先に到達できない仮想アドレスへアクセスしようとします。
| 連携が必要な項目 | 確認する内容 | 設定が足りない場合の症状 |
|---|---|---|
| クエリの入口 | アプリのDNSクエリがFakeDNSに届いている | 実IPアドレスが返る、または設定がテスト対象アプリに適用されていない |
| 接続の制御 | 仮想アドレスへの通信が同じコアに戻る | 名前解決は成功するが、接続がタイムアウトし続ける |
| マッピングの復元 | インバウンドがFakeDNSのドメイン名復元に対応している | 元のドメイン名でルーティングできない |
| キャッシュの有効期間 | 再起動後に古い仮想アドレスを使い続けない | コアの再起動後、一部のアプリが一時的に開けなくなる |
v2rayNGでは、「設定」に「仮想DNSを有効にする」がある場合、まずそのビルドの要件に従ってローカルDNSを有効にし、その後で仮想DNSを有効にします。「スニッフィング」関連の設定がFakeDNSの復元に対応しているかも確認してください。v2rayNでは、TUNと現在のコアがFakeDNSにどう連携するか確認します。仮想アドレスプールを追加しただけで、DNSの制御とドメイン名の復元が完了したと判断しないでください。
7. ログの確認:名前解決エラーと接続エラーを切り分ける
エラーが発生した時刻と接続先アドレスを記録し、同じ時間帯のログと照合します。以下の文字列がログに表示されることがありますが、プレフィックスや詳細はコアのバージョンによって異なります。単独のタイムアウトだけでは、DNSリークもDNSサーバーの障害も証明できません。
エラー:failed to lookup ip for domain
原因:コアが対象ドメインの有効なアドレスを取得できませんでした。リモート名前解決の失敗、ブートストラップ名前解決の失敗、または利用可能なレコードを除外するクエリポリシーが原因として考えられます。
対処:ログに記録されたドメイン名を確認します。まずノードのドメイン名をブートストラップ解決できるか調べ、その後、リモートDNSのルーティングとIPv4・IPv6のクエリポリシーを確認してください。
エラー:context deadline exceeded
原因:処理が制限時間内に完了しませんでした。DoHリクエストに関連するエラーなら、リゾルバーへのHTTPS接続または上流からの応答がタイムアウトした可能性があります。
対処:同じプロキシ経路を通してリゾルバーのアドレスをテストします。リモートDNSは一度に1つだけ変更し、「名前解決にプロキシが必要で、プロキシにも名前解決が必要」という依存関係のループがないか確認してください。
エラー:network is unreachable
原因:現在のネットワークに対象アドレスへの有効な経路がありません。到達不能なIPv6アドレスへ接続しようとしている場合などが考えられます。
対処:エラーに表示された接続先のアドレスファミリーを確認し、一時的にIPv4を使う名前解決ポリシーで比較します。あわせてTUNのルーティング、物理ネットワーク、プロキシアウトバウンドのIPv6対応を確認してください。
8. よくある質問と最終確認
検査ページにローカルリゾルバーが表示されたら、必ずDNSリークですか?
まず、テストに使うブラウザーがプロキシの対象か確認し、次にローカルDNSの分割ルーティングルールを確認します。テスト対象のドメインがポリシー上プロキシ経由になるはずなのに、物理ネットワークアダプターで対応するクエリの直結が確認できた場合は、迂回を示す有力な証拠になります。
DoHアドレスを設定したのに、検査結果が変わらないのはなぜですか?
変更した設定が現在使用中のコアのDNS設定であることを確認し、サービスを再起動します。その後、ブラウザーのセキュアDNSを一時的に無効にして再テストしてください。ブラウザーが独自に名前解決している場合、変更したコアのDNSを使っていない可能性があります。
FakeDNSを有効にすると名前解決はできるのに、Webページが開かない場合は?
まず、仮想アドレスへの接続が同じ制御経路に入っているか、インバウンドで適切なドメイン名復元が有効か確認します。FakeDNSを無効にしてアプリのキャッシュをクリアし、再テストしてください。正常に戻る場合は、ノードを先に変更するのではなく、マッピングと通信の制御を確認します。
53番ポートをすべて禁止すれば解決しますか?
いいえ。正常なブートストラップ名前解決を妨げる可能性があり、443番ポートのDoHや853番ポートのDoTも遮断できません。まず管理されたDNS経路を確保し、その後必要に応じて迂回を制限しながら、必要なLANサービスは利用できるようにしてください。
最後に、プロキシの再接続、クライアントの再起動、ネットワークの切り替えを含めて再テストします。Wi-Fiとモバイルネットワークでは、通知されるリゾルバーやIPv6のルーティングが異なる場合があります。一方のネットワークだけで行った検査結果を、もう一方にも当てはめないでください。設定変更を記録し、問題が起きた場合は一つずつ元に戻します。
- ブラウザーの検査結果が想定どおりで、ブラウザー独自のセキュアDNS設定も確認した。
- 制御対象のシステムクエリが、物理ネットワークアダプターから想定外のリゾルバーへ直接送信されていない。
- リモートDNSへの接続がプロキシのアウトバウンドを通り、ノードアドレスの起動時に必要な名前解決もできる。
- LAN内のドメイン、直結サイト、プロキシ経由のサイトをそれぞれ検証した。
- FakeDNSを有効にしている場合は、コアの再起動後に古いキャッシュをクリアし、仮想アドレスへの接続を再テストした。