DNSリークと判断できる範囲

DNSリークとは、ドメイン名の問い合わせが想定した経路を通らない状態です。たとえば、ブラウザーの通信はプロキシ経由なのに、名前解決の問い合わせだけが接続中のネットワーク事業者の再帰DNSサーバーに送られるケースがあります。Webページが開けることや、出口IPアドレスが変わったことだけでは、DNSクエリもプロキシを経由しているとは判断できません。

調査では、アプリが問い合わせをどこに送るか、Clashのコアがどの上流DNSを選ぶか、上流への接続がどの経路を通るかを分けて確認します。fake-ipは主にコアがアプリへ返すアドレスを変えます。nameserver-policyはDNSサーバーを選び、respect-rulesはDNSサーバーへの接続にルーティングルールを適用するかを決めます。それぞれ解決する問題は異なります。

確認できた現象そこから分かることそれだけでは判断できないこと
Webアクセス時の出口IPがプロキシサーバーのもの今回のWeb接続がプロキシを経由したシステムDNSや他のアプリもすべてプロキシを経由している
問い合わせ結果が198.18.0.0/16のアドレスその問い合わせでFake-IPによるマッピングが使われた可能性がある上流DNSへの接続が必ずプロキシを経由している
テストページに特定のパブリックDNS事業者が表示されるテスト用ドメインの問い合わせがその事業者のDNS基盤で処理された端末からDNSサーバーまでの通信が必ず暗号化されている、または必ずプロキシを経由している
ログでDNSサーバーへの接続がプロキシ用ルールに一致しているその上流接続が指定したルールに従ってルーティングされたブラウザー内蔵のDoHもコアのDNSモジュールを経由している

確認手順:システム、コア、ブラウザーのDNSを調べる

手順1:現在の状態を記録する

まず、現在のネットワーク、クライアントのモード、システムプロキシの有効・無効、TUNの有効・無効、ブラウザーのセキュアDNS設定を記録します。テスト中は同じプロキシノードを固定し、自動選択の切り替えは一時的に避けてください。切り替わると、比較した結果が別々の出口からのものになる可能性があります。会社のVPNやほかのプロキシクライアントも、テスト中は同時に使わないでください。

  • Windows:PowerShellでGet-DnsClientServerAddressを実行し、使用中のネットワークアダプターとDNSアドレスを記録します。
  • macOS:scutil --dnsを実行して、デフォルトおよびドメイン別のリゾルバーを確認します。複数のリゾルバーが同時に設定されている場合があります。
  • systemd-resolvedを使うLinux:resolvectl statusを実行し、/etc/resolv.confだけでなく、各リンクに設定されたDNSを確認します。

ネットワークアダプターにルーターのアドレスが表示されても、必ずしもDNSリークとは限りません。TUNが有効なら、そのアドレスの53番ポート宛ての問い合わせをコアが処理している場合があります。逆に、パブリックDNSのアドレスが表示されても、問い合わせが暗号化されているとは限りません。実際の接続経路を確認してください。

手順2:コアの待ち受けポートに直接問い合わせる

以下の例では、コアのDNSを127.0.0.1:1053で待ち受けるように設定します。設定を適用したら、次のコマンドを実行してください。1つ目はnslookupが使える環境向け、2つ目はdigをインストール済みの環境向けです。

nslookup -port=1053 example.com 127.0.0.1
dig @127.0.0.1 -p 1053 example.com A

Fake-IPの除外ルールに該当しない場合、Aレコードの問い合わせには、設定したアドレスプール内のマッピングアドレスが返る想定です。これは結果の読み方を示すもので、この記事で実測済みという意味ではありません。タイムアウトする場合は、DNSモジュールが有効か、設定が読み込まれているか、1053番ポートが使用中でないかを先に確認してください。すべてのルールを一度に変更するのは避けましょう。

次にnslookup example.comを実行し、システムのデフォルトDNSへの問い合わせと、コアへの直接問い合わせの結果を比べます。システムプロキシだけを有効にしている場合、両者の結果が異なるのは珍しくありません。通常、コマンドラインの名前解決はHTTPのシステムプロキシを使わないためです。TUNを有効にしてから再度テストすると、システムの問い合わせがコアに取り込まれているかを確認できます。

手順3:ブラウザー独自の名前解決を確認する

Chromeでは「設定」→「プライバシーとセキュリティ」→「セキュリティ」→「セキュアDNSを使用する」でDoHの設定を確認できます。メニュー名はバージョンによって多少異なる場合があります。最初の調査では一時的にこの機能をオフにし、ブラウザーにシステムの名前解決を使わせます。基準となるテストが終わったら設定を戻し、ブラウザーのDoH接続がどの経路を通るかを別途確認してください。

DNSリークテストページは通常、ランダムなサブドメインへの問い合わせを使って再帰DNSサーバーを調べます。プロキシの有効・無効で表示されるDNS事業者を比較し、コアの接続ログと照らし合わせてください。DNSサーバーの所在地とプロキシの出口は一致するとは限りません。パブリックDNSでは、Anycastの接続先と再帰DNSの出口が異なる場所にある場合もあります。国や都市の表示だけで判断すると誤判定につながります。

Fake-IPと上流DNSの設定例

以下はmihomoの設定に統合できるdnsセクションです。既存のプロキシノード、プロバイダー、ポリシーグループはそのまま残してください。ファイルにトップレベルのdns:がすでにある場合は、フィールドを置き換えるか統合し、同じ名前のセクションを追加しないでください。設定を読み込む前に、後述する上流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"
    - "*.local"
    - "localhost"
  respect-rules: true
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  proxy-server-nameserver:
    - https://dns.alidns.com/dns-query
  nameserver:
    - https://cloudflare-dns.com/dns-query
  nameserver-policy:
    "+.qq.com":
      - https://dns.alidns.com/dns-query#DIRECT
    "+.weixin.qq.com":
      - https://dns.alidns.com/dns-query#DIRECT

各フィールドの役割と注意点

  • listenはローカルのループバックアドレスだけにバインドします。ここでの1053は待ち受けポートの例です。OSのDNS設定が自動的にこのポートへ変更されるわけではなく、LAN内の端末にそのまま公開する用途にも適しません。
  • enhanced-mode: fake-ipはドメイン名にマッピング用のアドレスを割り当てます。これにより、後続の接続でドメイン名を保持してルールに一致させやすくなります。上流への問い合わせを暗号化する機能ではありません。
  • fake-ip-filterに登録したドメインには、通常のFake-IPマッピング方式とは異なる結果が返ります。除外項目は直通ルールではないため、rulesの代わりには使えません。
  • ipv6: falseは今回のDNS調査対象を絞るための設定です。OSのIPv6を無効にするものではなく、アプリが既存のIPv6アドレスへアクセスするのを防ぐものでもありません。
  • proxy-server-nameserverはプロキシノードのホスト名を専用に名前解決します。ノードのアドレスを解決する際に、そのノード自身を使って接続を確立する事態を避けられます。ノードの名前解決は、独立した経路として確認が必要です。

初回の読み込み時に問題を切り分けやすいよう、ここではブートストラップ用の経路を明示しています。利用中のネットワークから指定したDNSサービスへ接続できない場合は、実際に到達できる上流へ変更し、ルーティングも再確認してください。DoHが保護するのは、端末とDNSサービスの間を流れるDNS問い合わせの内容です。DoHへ直接接続する場合でも、ネットワークには接続先DNSサーバーのアドレスが見えます。

nameserver-policyとrespect-rulesの使い分け

DNSサーバーの選択と接続経路を分けて考える

nameserver-policyは問い合わせ先のドメインに応じて上流DNSを選ぶ設定で、Webサイトへの接続に使うノードを決めるものではありません。この例では、qq.comとそのサブドメインを指定した中国本土のDNSサーバーに割り当て、#DIRECTでDNSサーバーへの接続を直接接続に指定しています。weixin.qq.comの項目は、この設定では重複して上書きする例です。細かいドメイン指定の書き方を示すために残していますが、別途使い分ける必要がなければ削除できます。

それ以外の問い合わせはcloudflare-dns.comに送ります。respect-rulesを有効にすると、上流DNSへの接続にもルーティングルールが適用されます。ただし「ルールに従う」ことは「自動的にプロキシを使う」ことではありません。対象ドメインが最終的にDIRECTに一致すれば、DoH接続も直接接続になります。

既存の設定に「プロキシ」という名前のポリシーグループがあり、そのグループで使用可能なプロキシノードを選択しているとします。次の2つのルールは、より広い範囲に適用されるDIRECTルールと最後のMATCHより前に配置してください。設定内のグループ名は実際の名前と一致させる必要があります。既存のグループ名が「ノード選択」の場合は、参照先も同じ名前に変更してください。

rules:
  - DOMAIN,dns.alidns.com,DIRECT
  - DOMAIN,cloudflare-dns.com,プロキシ
  # この後に既存のルーティングルールと最後の MATCH ルールを残す

ここでは統合する位置だけを示しています。既存のrulesをすべて置き換える設定ではありません。この2つのルールを追加するために、サブスクリプションに含まれるほかのルールを削除しないでください。プロキシグループでDIRECTを選べる場合は、現在選択されている項目も確認しましょう。ルール名が正しくても、実際には直接接続になっていることがあります。

名前解決の依存関係が循環しないようにする

よくある循環依存は、DoHサービスのホスト名を引くにはプロキシが必要なのに、プロキシサーバーのホスト名を引くには、まだ確立していない同じDoH接続が必要になる状態です。起動後に大量の名前解決がタイムアウトし、ノードにも接続できないことがあります。この例では、ノードのホスト名をproxy-server-nameserverで解決し、その上流接続を直接接続にして、2つの依存経路を分けています。

  • ノードにホスト名が指定されている場合は、独立した名前解決経路でアドレスを取得できることを先に確認します。
  • ノードにIPアドレスが指定されている場合、ノードのホスト名を引く必要はありません。ただし、DoHサービスのブートストラップDNSは別途必要な場合があります。
  • 利用できないプロキシ経路をすべてのブートストラップDNSにも強制し、自動復旧を期待するのは避けてください。
  • 依存関係は一度に1つだけ変更します。保存後に設定の読み込み結果を確認し、その後で接続ログを調べてください。

TUNでシステムDNSを取り込む

システムプロキシが影響するのは、主にシステムプロキシ設定に従うアプリです。OSが送信するUDPのDNSクエリまで自動的に取り込むわけではありません。より多くのアプリの通常のDNS問い合わせをコアに通すには、クライアントのTUN機能を有効にします。デスクトップOSでは適切な権限、サービス、仮想ネットワークアダプターが必要な場合があります。画面上の設定と設定ファイルが互いに上書きしないよう、まずはクライアントに用意されたスイッチを使ってください。

以下はmihomoのTUN設定を統合する例です。クライアントがすでにtunセクションを生成している場合は、実際に適用される最終設定を確認してから変更してください。

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

any:53は、TUNに入るUDPの53番ポート宛ての問い合わせを取り込みます。2つ目の項目はTCPの53番ポートを対象にします。重要な制約は「TUNに入る通信」に限られることです。ルーティングの除外設定、別のVPN、仮想マシンのネットワーク、プラットフォーム側の制限などにより、一部の通信がこの経路を迂回する場合があります。LAN内のDNSアドレスを使う場合は、実際に問い合わせて取り込み状況を確認してください。

DoHは通常HTTPSの443番ポート、DoTは通常853番ポートを使います。53番ポートのDNSリダイレクトを設定しても、自動的にコアのDNSモジュールへ取り込まれるわけではありません。TUNでこれらのネットワーク接続をルーティングすることはできますが、53番ポートの設定だけで接続内のDNS問い合わせを置き換えることはできません。Androidの「プライベートDNS」とブラウザーのセキュアDNSも、それぞれ確認してください。

変更後の確認と問題発生時の切り戻し

条件をそろえて再テストする

  1. 設定が正常に読み込まれたことを確認します。不明なフィールドや存在しないポリシーグループのエラーが出た場合は、先に設定を修正してください。ブラウザーのテストには進まないでください。
  2. ノードを固定し、127.0.0.1:1053へ直接問い合わせてDNSモジュールの応答を確認します。
  3. TUNを有効にした後、システムのデフォルトDNSへ問い合わせながら、コアのDNSログと接続記録を確認します。
  4. 新しいドメインにアクセスし、Web接続だけでなく、cloudflare-dns.comへの上流接続が想定したプロキシグループを通っているか確認します。
  5. ブラウザーのDNSテストを再実行します。最後にセキュアDNSなどの元の設定を戻してもう一度テストし、結果の違いを記録してください。

Windowsではipconfig /flushdnsでシステムのDNSキャッシュを消去できます。systemd-resolvedを使うLinuxではresolvectl flush-cachesを実行します。ブラウザーやコアにも独自のキャッシュがある場合があります。必要に応じてブラウザーを再起動し、設定を読み込み直してください。Fake-IPのマッピングは保持されることがあるため、以前のアドレスが表示されても、それだけで設定が反映されていないとは判断できません。

症状まず確認する項目対応する順番
コアへのDNS問い合わせがタイムアウトする1053番ポートの待ち受け、設定の読み込み、ポート競合まず端末からDNS応答を得られる状態に戻し、その後に上流を確認する
Fake-IPは正常だがWebページが開かないプロキシノード、マッピング後の接続がコアに戻るか、TUNのルーティング接続が取り込まれていることを確認してから、プロキシへの接続可否を調べる
テストページにローカルのDNSサーバーが表示されるブラウザーのDoH、システムからの別経路の問い合わせ、ほかのネットワークアダプター問い合わせ元のアプリを特定してから、該当する経路を確認する
respect-rulesを有効にするとノードがすべてタイムアウトするノードのホスト名解決とDoHのルーティング依存関係ノード用の独立した名前解決を復旧し、ルールを1つずつ有効にする
LAN内の端末名が解決できないローカルドメインのサフィックス、mDNS、LAN内のDNSサーバー実際に使うローカルドメインに合わせて名前解決ルールを設定し、すべてのドメインを一律に直接接続にしない

切り戻す際は、保存しておいたDNS設定とルールを先に復元し、次に今回追加したTUN設定を無効にします。最後に、OSのプロキシ設定とネットワークアダプターのDNSがテスト時の値のままになっていないか確認してください。クライアントのデータフォルダーを丸ごと削除するのは避けましょう。サブスクリプション、自作ルール、ログも失われ、問題の切り分けに使える情報が減ってしまいます。

よくある質問

Fake-IPを有効にしたのに、テストページにネットワーク事業者のDNSが表示されるのはなぜですか?

ブラウザーが独自のDNSサーバーを使っている可能性があります。または、コアから上流への問い合わせがDIRECTルールで送信されている場合もあります。Fake-IPが示すのは、特定の名前解決にアドレスのマッピング機能が使われたことだけで、すべてのDNS通信がプロキシを通る証拠ではありません。ブラウザーの設定、上流への接続、ブートストラップDNSをそれぞれ確認してください。

nameserverをすべてDoHに変えれば十分ですか?

十分ではありません。DoHはDNS問い合わせの通信を暗号化しますが、プロキシの出口はルーティングによって決まります。また、OSやアプリがコアを迂回することもあります。問い合わせがコアに取り込まれているか、上流DNSの選択、ルーティングルール、ノードの名前解決に関する依存関係をあわせて確認してください。

中国本土のドメインを直接接続で名前解決する設定は、必ずDNSリークになりますか?

事前に決めた要件に照らして判断してください。指定したDNSサーバーへの直接問い合わせをポリシーで許可しているなら、意図した振り分けです。すべての問い合わせをプロキシ経由にすることが要件なら、その設定は要件を満たしません。許可する例外を明確にしたうえでログを確認するほうが、テストページに1つのアドレスだけを表示させることを目指すより確実です。

サブスクリプション更新後に設定が消えました。どこを変更すればよいですか?

リモートサブスクリプションによって上書きされる元ファイルを、継続的に直接編集するのは避けてください。クライアントがサポートするローカル上書き、設定のマージ、スクリプト機能を利用します。具体的な操作場所はクライアントのバージョンによって異なります。サブスクリプションを更新した後は、上書き用ファイルが保存されているかだけでなく、実際に適用されたDNS、TUN、ルールの順序を確認してください。