DNSリークを判断する前に、想定する名前解決経路を確認

ClashのDNSリークとは、ドメイン名の問い合わせが想定した経路を通らない状態を指します。たとえば、通信自体はプロキシ経由でも、システムからルーターやプロバイダーのDNSサーバーへ問い合わせが送られるケースです。Webページが正常に表示され、接続元IPがプロキシのものでも、DNS問い合わせだけ別経路を通ることがあります。「Webにアクセスできること」と「DNSが設定どおり処理されていること」は分けて確認しましょう。

まず、従来のDNS問い合わせをすべてローカルのコアに取り込むのか、それとも上流DNSへの接続もプロキシ経由にするのか、目標を明確にします。前者では通信の取り込み、後者ではDNS上流への接続に適用するルーティング方針も確認が必要です。DoHやDoTを使っても、問い合わせが暗号化されていることを示すだけで、プロキシ経由で送信された証明にはなりません。

  • クライアント:設定、システムプロキシ、サービス権限、画面上のスイッチを管理します。
  • コア:DNS解決、Fake-IPのマッピング、ルール判定、接続の転送を実行します。
  • サブスクリプション:ノード、ルール、または設定一式を提供します。更新時にローカルの変更が上書きされることがあります。
  • アプリ:システムのリゾルバーを使う場合もあれば、DoHを内蔵してシステムのDNS設定を経由しない場合もあります。

確認手順:出口IP・リゾルバー・端末の通信を分けて調べる

手順1:プロキシを無効にした状態を基準として記録

直接インターネットに接続できるテスト環境で、システムプロキシとTUNを無効にし、グローバルIP、システムDNSのアドレス、DNSテストサイトに表示されるリゾルバーの情報を記録します。企業ネットワークや管理対象端末では、定められたネットワークポリシーを独断で無効にしないでください。この基準は比較用です。テストサイトに表示される国や都市だけでDNSリークと判断することはできません。

WindowsではPowerShellを使って、各ネットワークアダプターのDNSを確認できます。Wi-Fi、イーサネット、VPN、仮想アダプターが同時に存在する場合があるため、画面に表示された先頭の項目だけを確認しないでください。

Get-DnsClientServerAddress -AddressFamily IPv4
Get-DnsClientServerAddress -AddressFamily IPv6
ipconfig /all

手順2:設定を有効にして同じテストを再実行

  1. 想定しているシステムプロキシまたはTUNを有効にし、現在の設定と選択中のプロキシグループを確認します。
  2. 出口IPを再確認し、ブラウザーで「セキュアDNS」が有効かどうかも記録します。
  3. DNSテストを実行し、「成功」の表示だけでなく、リゾルバーのIPアドレス、事業者、テスト時刻を記録します。
  4. クライアントの接続履歴やデバッグログでDNS上流への接続を探し、宛先アドレスと実際に適用された出力ルールを確認します。
  5. キャッシュされていないドメイン名でもう一度問い合わせ、キャッシュヒットをDNSが動作していない状態と誤認しないようにします。

パブリックDNSでは、エニーキャストや分散型の出口が使われることがあります。テストサイトに表示されるリゾルバーの所在地が接続先の所在地と一致するとは限らず、プロキシノードの都市とも異なる場合があります。設定で一部のドメインにローカルリゾルバーを使う場合、ローカルの解決結果が返るのは想定どおりかもしれません。ドメインごとの設定と通信ログが一致するかを確認してください。

手順3:指定したローカルポートでコアを確認

コアが127.0.0.1:1053で待ち受けている場合、ポートを指定できるdigでDNSサービスを確認できます。ここで使う1053は説明用のポートで、すべてのクライアントの既定値ではありません。システムにdigがない場合、テストのために無理に別のツールへ切り替える必要はありません。

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA

ローカルの待ち受けポートへの問い合わせに成功しても、コアがDNSに応答できることが分かるだけです。システムDNS、TUNによるハイジャック、ブラウザーの名前解決が想定どおりか確認するには、実際のアプリからの問い合わせもテストしてください。Windowsのnslookupは既定で53番ポートを使います。1053番ポートで待ち受けるサービスに対して、既定ポートへの問い合わせが失敗しても、そのサービスが原因とは限りません。

Fake-IP:ドメイン名のマッピング機能であり、DNSを暗号化するものではない

enhanced-mode: fake-ipを設定すると、対象ドメインに仮想アドレスを返し、ドメイン名と仮想アドレスの対応をコアが保持します。アプリがそのアドレスに接続すると、コアはドメイン名を復元してルールを判定したり、ドメイン名をプロキシ経由で転送したりできます。実際のアドレスは後続の接続時に解決される場合も、プロトコルや出力方式によってはリモート側のプロキシサーバーで処理される場合もあります。

Fake-IPでよく使われるアドレス範囲は198.18.0.1/16です。これは仮想マッピング用であり、ノードのグローバルIPではありません。問い合わせ結果にこの範囲のアドレスが返るのは、モードが正常に動作している状態であることが多く、リモートサーバーのアドレスとして設定したり、システムのパブリックDNS一覧に手動で追加したりしないでください。

設定主な役割これだけでは保証できないこと
fake-ip仮想アドレスを返し、ドメイン名との対応を保存上流への問い合わせの暗号化、またはプロキシ経由の接続
redir-hostアプリに実際の解決アドレスを返すアプリのDNS問い合わせが必ずコアを通ること
fake-ip-filterフィルタールールに該当するドメインを処理し、実アドレスを返す用途などで使用プロキシのルーティングルールの代わり

LAN内のデバイス検出、一部の機器管理ページ、実アドレスを必要とするアプリでは例外設定が必要な場合があります。まず対象を特定のドメインに絞り、そのうえで範囲を広げるか検討してください。多くのパブリックドメインをFake-IPのフィルター一覧に追加すると、名前解決の挙動が変わり、問題の切り分けも難しくなります。フィルター一覧はDNSの応答方法を制御し、rulesは接続の出力先を制御します。互いに代用することはできません。

nameserverの設定:通常の名前解決と起動時の名前解決を分ける

以下は設定項目を理解するためのmihomo DNS設定例であり、サブスクリプション全体ではありません。既存のノード、プロキシグループ、ルールを残したまま、該当項目を実際に有効な設定へ統合してください。同じYAML階層にdnsキーを複数置かないでください。クライアントで設定の上書きやマージを行う場合は、編集画面のテキストだけでなく、マージ後の設定を確認します。

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"
    - "localhost"
  default-nameserver:
    - 223.5.5.5
  nameserver:
    - https://dns.alidns.com/dns-query
  proxy-server-nameserver:
    - https://dns.alidns.com/dns-query
  • listen:ループバックアドレスにバインドし、DNSサービスがLANに直接公開されないようにします。他の端末から使う必要がある場合は、アクセス範囲も別途設定してください。
  • default-nameserver:主にDNS上流のホスト名を解決し、起動時に「リゾルバーのアドレスを先に特定する」問題を解決します。
  • nameserver:通常のドメイン名解決に使う上流サーバーの一覧です。実際の処理はドメイン別ポリシーなどの設定にも左右されます。
  • proxy-server-nameserver:プロキシノードのドメイン名解決に使い、まだ確立していないプロキシ経路にノードの名前解決が依存する事態を避けます。
  • ipv6: false:このDNSモジュールが返すIPv6の解決結果を制限します。OSのIPv6を無効にしたり、すべてのIPv6接続を遮断したりする設定ではありません。

DoHを接続するために証明書検証を無効にしないでください。まずシステム時刻、上流アドレス、ネットワークへの接続性、起動時の名前解決を確認します。DNS上流への接続にもルーティングルールを適用する場合、mihomoではrespect-rulesなどを設定できますが、ノードのドメイン名解決とDNS上流への接続経路もあわせて考慮する必要があります。ルールを確認せずにrespect-rules: trueだけを追加すると、名前解決がループしたり、意図せずDIRECTルールに一致したりすることがあります。

fallbackとドメイン別ポリシー:fallbackは失敗時だけ使うとは限らない

fallbackは「最初のDNSがタイムアウトしたときだけ予備のDNSへ問い合わせる」と誤解されがちです。一般的なfallbackの処理では、コアが通常のリゾルバーとfallbackの両方へ同時に問い合わせ、fallback-filterに基づいて結果を選ぶことがあります。そのため、パブリックDNSをfallbackに指定しても、通常時に問い合わせを受け取らないとは限りません。

fallback-filterは、地理情報、IPアドレス範囲、ドメイン名などの条件に基づいて、採用する結果に影響します。地理データベースが古くなっている場合や、CDNが別地域のアドレスを返す場合もあるため、地域コードを一律の汚染判定基準として使わないでください。トラブルシューティングでは、まず検証可能な上流を設定し、必要に応じてfallbackを追加すると、複数のリゾルバーを一度に設定するより原因を特定しやすくなります。

特定ドメインの上流を指定する:nameserver-policy

LAN内のドメイン名には、通常、LAN内のDNSサーバーが必要です。次の例では+.home.arpaを192.168.1.1へ送ります。このアドレスが現在のネットワーク内のリゾルバーである場合に限り使用してください。これは明示的にローカルへ問い合わせる設定です。「すべての問い合わせをプロキシノード経由にする」ことを合格基準にしないでください。

dns:
  nameserver-policy:
    "+.home.arpa":
      - 192.168.1.1

この設定は項目の一部です。前の設定にあるdnsマッピングへ統合し、ファイル末尾に重複して追加しないでください。実際のLAN内アドレスが必要なドメインについては、Fake-IPのフィルター設定も確認します。ドメイン名の解決先をLAN内にしても、接続が自動的にLAN経由になるわけではありません。接続ルールで該当するLANアクセスを許可する必要があります。

TUNのDNSハイジャック:53番ポートの通信を取り込む設定であり、すべての名前解決を取り込むわけではない

システムプロキシが影響するのは、主にプロキシ設定に従うアプリです。システムDNSを一括で取り込む機能はありません。TUNは仮想ネットワークアダプターとルーティングで通信を取り込み、dns-hijackを併用すると、条件に一致する従来型DNSの問い合わせをコアへ転送できます。以下の設定を使うには、クライアントのサービス権限と対象プラットフォームの対応が必要です。既存のTUN設定に統合してください。

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53

any:53はUDP 53番ポートの問い合わせに一致し、tcp://any:53はTCP 53番ポートを対象にします。実際に取り込めるかどうかは、OSのルーティング、TUNスタック、除外ネットワーク、他のVPNにも左右されます。特にLAN内DNS宛ての問い合わせがTUNに入るかは、実際のパケットをキャプチャして確認してください。ネットワークアダプターを切り替えた後も再テストが必要です。起動時のひとつのネットワークで確認するだけでは不十分です。

個別に確認が必要な3種類の通信

  • ブラウザーのDoH:通常はHTTPS 443番ポートへの接続として通信するため、53番ポートのハイジャックルールでは自動的に切り替わりません。トラブルシューティングではブラウザーのセキュアDNSを一時的に無効にするか、明確な暗号化DNSの設計に組み込んでください。
  • DoTなどの暗号化DNS:DoTは通常TCP 853番ポートを使います。アプリ内蔵の暗号化DNSは、実際のプロトコルと接続の出力先を確認してください。
  • IPv6と複数のネットワークアダプター:IPv4の通信を取り込めていても、IPv6も同様に取り込めているとは限りません。IPv6のルート、DNSアドレス、クライアントの対応状況を確認し、dns.ipv6の設定だけに頼らないでください。

パケットキャプチャでは、udp.port == 53 || tcp.port == 53をWiresharkの表示フィルターとして使えます。物理ネットワークアダプターで、想定外のリゾルバー宛てに平文DNSが継続して送信されている場合は、追跡が必要です。ループバックや仮想アダプターに取り込み前の問い合わせが表示されても、外部へ漏れているとは限りません。このフィルターではDoHの問い合わせ内容は見えず、他のポートに名前解決の通信がないことも証明できません。

トラブルシューティングの順序と設定の確認項目

症状まず確認する項目確認方法
ローカルの1053番ポートが応答しないDNSの有効化、ポートの競合、設定の読み込みエラーコアの起動ログとポートの待ち受け状態を確認
ローカルからの問い合わせは正常だが、ブラウザーの結果が異なるブラウザーのセキュアDNS、キャッシュ、プロキシ拡張機能DNS設定をそろえ、新しいドメイン名で再テスト
TUNを有効にすると、すべてのドメインがタイムアウトする権限、上流への接続性、名前解決のループまずノードのドメイン名と上流の起動時解決を確認
パブリックなドメインは正常だが、LAN内の名前を解決できないドメイン別の上流設定、Fake-IPフィルター、LANルールLAN内DNSとコアのDNSをそれぞれ使って問い合わせる
サブスクリプション更新後に問題が再発する上書きの順序と有効な設定更新前後のDNS・TUN設定項目を比較

名前解決モードや上流を変更した後は、関連するキャッシュを消去してから再テストしてください。Windowsではipconfig /flushdnsを実行してシステムキャッシュを消去できます。ブラウザーとコアには独立したキャッシュが残っている場合があるため、それぞれの消去機能を使うか、再起動してください。既存の接続では再度名前解決されないことがあります。テストでは新しい接続を作成し、長時間維持されているページを更新するだけで済ませないようにします。

  1. 設定が有効:コアが設定を正常に読み込み、DNSの待ち受けアドレスとポートがテストコマンドと一致している。
  2. 通信の取り込みが有効:実際のアプリによる従来型DNSの問い合わせが想定どおりコアに入り、例外経路の用途も明確である。
  3. 上流が有効:通常の名前解決、起動時の名前解決、ノードのドメイン名解決で、それぞれどの上流を使うか説明できる。
  4. 出力経路が有効:プロキシ経由にするDNS上流への接続が正しいルールに一致している。DoHのアドレスだけを根拠に判断しない。
  5. 再起動後も有効:クライアントの再起動、サブスクリプションの更新、ネットワークの切り替え後にも確認を繰り返し、設定が保持されることを確認する。

DNSリーク防止は、ひとつのスイッチで実現するものではありません。アプリの名前解決方法、システムルート、コアの設定、上流への接続経路を組み合わせて確認します。Fake-IPはドメイン名のマッピング、nameserverは名前解決サービス、TUNのハイジャックは条件に合う問い合わせの取り込みを担います。それぞれを個別に検証すれば、どの層で問題が起きているか判断できます。詳しくはFake-IPプロトコルの解説をご覧ください。設定のインポートと上書きについては使い方ガイドをご確認ください。