DNSリークと判断する基準
Clashでプロキシ接続中なのに、DNSリークテストにローカルのインターネットサービスプロバイダー(ISP)が表示される。これは原因を調べる際によくある出発点です。ただし、「複数のDNSアドレスが検出された」だけで、ただちにリークとは限りません。まず、プロキシ対象のドメインだけをプロキシ経由で名前解決するのか、それともノード接続用の名前解決を除き、すべてのパブリックドメインの問い合わせを指定した出口から送信するのか、目的を明確にしましょう。目的によって正常とみなせる結果は異なります。
この記事では、DNSリークを「ドメインの問い合わせが意図したポリシーに従わず、システムやローカルネットワーク、許可していないDNSリゾルバーへ流れること」と定義します。テストページに表示されるのは通常、テスト用ドメインの問い合わせを受け取った再帰DNSリゾルバーです。PCに設定されたDNSアドレスやプロキシノードそのものではありません。そのため、DNSの所在地とWeb通信の出口の国が異なっていても、それだけではリークと断定できず、判断材料の一つにとどまります。
| 結果 | 考えられる原因 | 次に確認すること |
|---|---|---|
| ローカルISPのリゾルバーが表示される | システムのDNS問い合わせが制御されていない、またはルールで直接接続が許可されている | ポリシーとポート53の通信を確認する |
| パブリックDNSサービスが表示される | コアまたはブラウザーがそのサービスを使用している | 想定した上流DNSと通信出口か確認する |
| リゾルバーとノードの国が異なる | パブリックDNSのエニーキャスト、再帰問い合わせの出口、または位置情報データベースの違い | 接続ログからルーティングを確認する |
| 毎回複数のアドレスが表示される | 同じサービスが複数の再帰問い合わせ出口を使っている、または名前解決経路が複数ある | IPアドレスの数ではなく、運営事業者を比較する |
再現可能な手順でDNSリークをテストする
環境を記録し、変更する設定は一度に一つ
- クライアント名、コア名とバージョン、システムプロキシとTUNのどちらを使っているかを記録します。この記事の例はmihomo向けです。更新が終了した旧Clashコアにそのまま適用しないでください。
- ほかのVPN、通信高速化ツール、プロキシアプリを終了します。複数の仮想アダプターやDNS設定が互いに上書きしないよう、まずはクライアントを一つだけ起動した状態でテストしてください。
- ブラウザーで
dnsleaktest.comを開き、「Standard test」を実行してから「Extended test」も実行します。リゾルバーのIPアドレス、運営事業者、テスト時刻、Web通信の出口アドレスを記録し、国名だけを切り取らないようにしてください。 - プロキシを無効にして基準となるテストを行い、その後、目的の設定を有効にして再テストします。基準テストではローカルネットワーク経由で通信するため、厳格なネットワーク隔離が必要な環境では実行しないでください。
- 設定を変更したらコアを再読み込みし、システムのキャッシュを消去して、ブラウザーを完全に終了してから2回目のテストを行います。同じノード、同じネットワーク、同じテストページを使うと比較しやすくなります。
Windowsでは、ターミナルで ipconfig /flushdns を実行すると、システムのDNSキャッシュを消去できます。ただし、ブラウザー独自のDNSキャッシュやmihomoコアの実行状態すべてが消去されるわけではありません。結果が変わらない場合は、設定が反映されていないと判断する前に、ブラウザーとコアを再起動してください。
ブラウザーとシステムの結果を区別する
ブラウザーのセキュアDNSはHTTPS経由で直接問い合わせることがあり、システムのポート53を使った名前解決を迂回します。原因を特定するには、まずブラウザーの設定で「セキュアDNS」を検索し、一時的に無効にして比較します。コアによる制御が機能していることを確認したら、必要に応じて設定を戻し、DoH接続に明確なプロキシルールを設定してください。ブラウザーでのテストが正常でも、コマンドラインツールやゲーム、ほかのアプリが同じ経路を使っているとは限りません。
たとえば、比較結果を「システムプロキシ:ISPとパブリックDNSを検出、TUN:設定したパブリックDNSのみ検出」のように記録できます。これは記録方法の例であり、実測結果ではありません。実際の結果を保存し、コアの接続ログで変化の原因を確認してください。
fake-ipと明示的な上流DNSを設定する
編集前に、現在正常に使えている設定をバックアップしてください。サブスクリプション設定は定期更新で上書きされることがあるため、クライアントのオーバーライド機能またはマージ機能を使います。マージ方法がわからない場合は、設定を複製して独立したローカル設定として検証してください。最終的に有効な設定には、トップレベルの dns: を一つだけ置きます。ファイル末尾に同名のセクションを重複して貼り付けないでください。
以下はmihomoのDNS設定例です。既存のノード、プロキシグループ、ルールを含む設定全体に統合してください。この例では通常の問い合わせをCloudflare DoHに送り、qq.com とそのサブドメインには中国本土のDoHを使います。後者はドメインごとに分ける設定であり、「すべての問い合わせをプロキシ経由にする」ものではありません。
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "*.local"
respect-rules: true
default-nameserver:
- 223.5.5.5
proxy-server-nameserver:
- https://223.5.5.5/dns-query
nameserver:
- https://1.1.1.1/dns-query
nameserver-policy:
"+.qq.com":
- https://223.5.5.5/dns-query
listen: 127.0.0.1:1053はローカルホストだけで待ち受け、LANにはDNSサービスを公開しません。通常、システムのDNS設定には1053のような任意のポートを指定できないため、後述のTUNによる制御か、システムが対応するローカルフォワーダーを使って接続する必要があります。198.18.0.1/16は、この例で選んだ仮想アドレスプールです。アプリにこの範囲のアドレスが返されても正常です。ネットワーク内ですでに同じサブネットを使っている場合は、先に競合を解消してください。fake-ip-filterに登録したドメインには、実際のIPアドレスを返します。主にLAN内のデバイス検出などとの互換性を保つための設定です。これはルーティングルールではなく、該当する問い合わせが必ず直接接続になるという意味でもありません。proxy-server-nameserverはプロキシサーバーのホスト名専用の名前解決設定です。「ノードへの接続にDNSが必要で、そのDNSがノードへの接続を待つ」という循環依存を防ぎます。ノードをIPアドレスで指定している場合、この問い合わせは発生しないことがあります。default-nameserverはDNSサーバーのホスト名を解決するなど、接続開始時の名前解決に使います。実際に通常のDNS問い合わせが発生すれば、ローカルネットワークからそのドメインを観測できる場合があります。すべての通信の名前解決にこのアドレスが使われるわけではありません。
nameserver-policyとルールでDNSの出口を指定する
nameserver-policy は「各ドメインをどのリゾルバーに問い合わせるか」を決めます。respect-rules: true は、上流DNSへの接続にルーティングルールを適用します。役割はそれぞれ異なります。上流DNSを海外のパブリックDNSに変更しただけでは、問い合わせがプロキシ経由で送信されるとは限りません。
設定に プロキシ選択 という利用可能なプロキシグループがある場合、次の2行を既存の rules: リストに追加し、先に一致する可能性があるルールより前に配置します。この2行でルール全体を置き換えないでください。また、プロキシグループが存在しない状態で保存しないでください。
rules:
- IP-CIDR,1.1.1.1/32,プロキシ選択,no-resolve
- IP-CIDR,223.5.5.5/32,DIRECT,no-resolve
1行目は、例にある 1.1.1.1:443 へのDNS上流接続に指定のプロキシグループを使います。2行目は中国本土向けの上流DNSを直接接続にします。no-resolve を付けることで、このIPルールを判定するための余分なドメイン解決を防ぎます。ルールは上から順に評価されるため、前に広範囲な直接接続ルールがあると、追加したルールが適用されないことがあります。
すべてのDNSをプロキシ経由にする場合と中国本土向けの振り分けを分けて検証する
- 中国本土向けに振り分ける場合:例の
nameserver-policyを残し、指定したドメインを中国本土のDNSサービスに問い合わせます。テストページが生成するランダムなテストドメインは通常このポリシーに一致せず、一般向けの上流DNSが使われます。 - より厳格にプロキシ経由で名前解決する場合:このような中国本土向けの個別設定を削除し、ほかの上流DNS、予備のリゾルバー、直接接続の名前解決設定も確認してください。ノードの接続に必要な名前解決は別途設計が必要です。設定を1行削除しただけで、すべての経路を遮断できたとは言えません。
- 企業・学校のイントラネットを使う場合:イントラネットのドメインはローカルDNSでの解決が必要な場合があります。ネットワーク管理者に確認し、必要なドメイン別の設定を残してください。イントラネットのドメインをまとめてパブリックDNSに送らないでください。
検証時はクライアントの接続一覧で 1.1.1.1 を検索し、接続先ポートが 443 か、想定したプロキシグループが適用されているかを確認します。DNS内部接続の表示機能はクライアントごとに異なります。一覧に表示されない場合は、デバッグログやパケットキャプチャも確認してください。「見えない」ことを「リクエストがない」証拠とみなしてはいけません。
TUNでシステムDNSを制御し、ポート53を横取りする
システムプロキシの影響を受けるのは、主にプロキシ設定に従うアプリです。すべてのシステムDNS問い合わせが自動的に制御されるわけではありません。より多くのアプリを対象にするには、mihomoのTUNに対応したクライアントで仮想アダプターを有効にし、次の設定を既存設定に統合します。有効化には管理者権限や仮想アダプター用サービスのインストールが必要な場合があります。
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
ここでの any:53 と tcp://any:53 は、TUNを通る通常のUDP DNSとTCP DNSをそれぞれ制御します。任意のアプリが使うHTTPS経由の名前解決を自動的にコアのDNSへ書き換えるものではなく、仮想アダプターを通らない接続も制御できません。実際にどこまで対象にできるかは、システム、ルーティングテーブル、クライアントの権限によって変わります。
ローカル環境での確認手順
- クライアントでTUNが起動していることを確認し、権限不足、仮想アダプターの作成失敗、ルート追加失敗などのエラーがログにないか確認します。
nslookup example.com 127.0.0.1を実行する前に、ローカルのポート53でDNSが待ち受けていることを確認します。この記事では1053で待ち受けているため、このコマンドの失敗だけでDNS障害と判断することはできません。- システムに
digがインストールされている場合は、次のコマンドでコアのポート1053を直接テストします。fake-ipが適用されると、通常は198.18.0.0/16の範囲のアドレスが返されます。 - 次に
nslookup example.com 8.8.8.8を実行し、通常のシステムDNS問い合わせが制御されているか確認します。ログと照らし合わせて判断してください。コマンドに表示されるサーバー名だけでは、DNSが制御されている証拠になりません。 - 最後に、ブラウザーの拡張機能でもう一度テストし、普段使うアプリで実際に通信できるか確認します。
dig @127.0.0.1 -p 1053 example.com A
nslookup example.com 8.8.8.8
Windows 11では、「設定」→「ネットワークとインターネット」→「プロキシ」を開き、ほかのツールが設定した手動プロキシが残っていないか確認します。クライアントの設計によってはTUNとシステムプロキシを併用できますが、原因を調べる段階では、まず明確な制御経路を一つだけ使い、その後ほかの機能を一つずつ戻してください。
IPv6、ブラウザーのDoH、キャッシュに残るリスク
DNSのIPv6設定とシステムのIPv6設定は別
例の dns.ipv6: false は、AAAA問い合わせをコアが処理するかどうかを制御する設定です。OSのIPv6を無効にするものではなく、アプリが独自に解決したIPv6アドレスへの接続を自動的に防ぐものでもありません。キャッシュ、アプリ内蔵のDoH、固定アドレスが別経路を使う可能性もあります。IPv4とIPv6それぞれの通信出口を確認してください。現在のクライアントでIPv6を完全に制御できない場合は、原因を特定するための比較としてテスト用ネットワークアダプターのIPv6を一時的に無効にし、長期的な対処は結果を見て判断します。
ポート53以外の名前解決は個別に対処する
DoTは一般にTCP 853、DoHは通常HTTPSの443を使い、HTTP/3経由の場合はUDP 443を使うこともあります。dns-hijack のポート53ルールで、こうした暗号化接続を通常のDNSに変換することはできません。ブラウザーやアプリ内蔵のセキュアDNSには、システムDNSを使わせるか、DNSサービスへの接続に目的に合ったプロキシルールを設定してください。
パケットキャプチャで想定外の平文DNS問い合わせを確認する
パケットキャプチャツールが使える場合は、物理ネットワークアダプターで表示フィルター udp.port == 53 || tcp.port == 53 を指定し、テスト中の通信を確認します。問い合わせドメイン、宛先アドレス、時刻をログと照合してください。TUNアダプター上のDNSパケットは、制御される前の内部処理である場合があります。外部への漏えいを判断するには、物理ネットワークアダプターから想定外の外部DNSへ問い合わせが送信されているかを重点的に確認します。
ポート53の通信を捕捉できなくても、DoHやDoTは暗号化されているため、名前解決の通信がないとは限りません。反対に、ノード接続用の名前解決、LAN内デバイスの問い合わせ、ほかのプロセスの通信を、テスト中のWebページが原因だと決めつけることもできません。プロセス、ドメイン、時刻から発生元を区別してください。
設定の検証とトラブル時の切り戻し
信頼できる検証には、少なくとも3つの確認が必要です。リゾルバーが想定どおりであること、DNS上流への接続が正しい出口を通ること、利用するアプリが正常に通信できることです。テストページに「ローカルアドレスが表示されない」ことだけでは、イントラネットのドメイン解決失敗、ノード接続時の名前解決ループ、ほかのアプリによる迂回を確認できません。
- 設定を読み込めない:YAMLのインデント、トップレベル項目の重複、未対応のオプションを確認します。クライアントの見た目だけでコアのバージョンを判断せず、実際にmihomoが動作していることを確認してください。
- すべてのドメインがタイムアウトする:まずノードに接続できるか、プロキシサーバーのホスト名を専用の上流DNSで解決できるかを確認し、次に
1.1.1.1:443へのプロキシ経路を調べます。障害時にノード、DNS、ルールを一度に変更しないでください。 - テストは正常だがイントラネットに接続できない:イントラネットのドメインにローカルDNSが必要か確認し、
fake-ip-filterとドメイン別ポリシーを見直します。実際に使う上流DNSを確認せず、フィルター対象だけをむやみに増やさないでください。 - サブスクリプション更新後に問題が再発する:更新前後の実際に有効な設定を比較し、DNS、TUN、ルールのオーバーライドが維持されているか確認します。エディターに保存されたテキストだけを確認しても不十分です。
- クライアントを終了すると通信できない:システムDNS、手動プロキシ、ルートが元に戻っているか確認します。まずTUNを無効にしてクライアントを終了し、バックアップからネットワーク設定を復元してください。
fake-ipはドメインとアドレスの対応付け、nameserver-policyはリゾルバーの選択、ルーティングルールは上流接続の出口、TUNはシステム側の制御範囲を広げる役割を担います。この4つを分けて検証すれば、「DNSリーク対策」のスイッチを何度も切り替えるより、原因を見つけやすくなります。基本的なルール設定やサブスクリプションの使い方はClash設定ガイドを、各項目の詳細は詳細ドキュメントをご覧ください。