DNSリークと判断する基準

DNSリークとは、ドメイン名の問い合わせが想定した経路から外れて処理されることです。たとえば、ブラウザーの通信はプロキシ経由でも、ドメイン名の問い合わせだけが契約中のインターネットサービスプロバイダー(ISP)のDNSで処理される場合があります。Webページが開けることや、外部から見えるIPアドレスが変わったことだけでは、DNSも想定どおりの経路を通っているとは判断できません。アプリの通信、DNSの上流サーバー、DNS接続の実際の出口を分けて確認しましょう。

この記事の設定例は、mihomoカーネルを使うクライアントを対象としています。旧Clashカーネルやクライアントによって、対応する設定項目は異なります。変更前にクライアントの「バージョン情報」またはカーネル情報の画面で、カーネル名、バージョン、現在の設定元を確認してください。メニュー名はクライアントごとに異なるため、特定のクライアントの画面操作ではなく、設定項目を使って説明します。

検出手順:基準値を記録してプロキシ利用時と比較

1. プロキシを使わない状態で結果を記録

  1. プロキシの適用を一時停止し、現在のグローバルIPアドレス、システムに設定されたDNSアドレス、ブラウザーのセキュアDNS設定を記録します。
  2. https://www.dnsleaktest.com/にアクセスし、Standard testとExtended testをそれぞれ実行して、リゾルバーのIPアドレス、組織名、検出時刻を記録します。
  3. 現在使っているシステムプロキシまたはTUNを有効にし、キャッシュを消去してから、同じブラウザーで2種類のテストを再実行します。
  4. プロキシノード、ブラウザー、ネットワークはそのままにし、DNS設定を一度に一項目だけ変更して再検査します。ノード、リゾルバー、通信の取り込み方式を同時に変更しないでください。

オンライン検査では通常、ランダムなサブドメインを使って再帰リゾルバーの接続元を確認します。結果に表示されるアドレスはリゾルバーの再帰問い合わせ元であることが多く、端末の出口IPとは異なります。また、1.1.1.1など設定上の接続先アドレスと同じとは限りません。パブリックDNSのAnycastによる振り分けや位置情報データベースの誤差で、表示地域が変わることもあります。そのため、「リゾルバーの国とノードの国が違う」という結果だけでリークと判断せず、手がかりとして扱ってください。

2. キャッシュを消去し、検査条件をそろえる

Windowsではターミナルで以下のコマンドを実行します。macOSの2つ目のコマンドには管理者権限が必要です。キャッシュを消去したらブラウザーを終了して再起動し、必要に応じてプロキシにも再接続してください。以前の接続が古いDNS経路を再利用するのを防げます。

# Windows
ipconfig /flushdns

# macOS
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

# systemd-resolvedを使用するLinux
resolvectl flush-caches

すべてのLinuxディストリビューションでsystemd-resolvedが使われているわけではありません。コマンドが見つからない場合は、現在使われている名前解決サービスを確認してください。検査記録には、時刻、通信の取り込み方式、ブラウザーのセキュアDNSの状態、リゾルバーの組織名、実際の接続出口の5項目を含めるとよいでしょう。根拠のない実測割合は示しません。対策が有効かどうかは、使用中の端末で検査を繰り返して判断してください。

3. アドレスの数だけでなく、根拠をもとに判断

検出された現象考えられる原因次に確認すること
契約中のISPのリゾルバーが表示されるシステムDNSが取り込まれていない、またはルールで明示的に直接接続しているTUN、ポート53宛ての通信、DNSルールを確認する
パブリックDNSだけが表示されるカーネルまたはブラウザーがパブリックDNSを使用している接続の出口を引き続き確認する。表示だけではプロキシ経由とは判断できない
複数のパブリックDNSが表示される並列問い合わせ、fallback、またはリゾルバーのクラスタリング設定した上流サーバーと一つずつ照合する
ブラウザーとコマンドラインで結果が異なるブラウザー独自のDoH、キャッシュ、またはアプリごとのプロキシ設定の違いDNSの入口を統一して再検査する

fake-ipとnameserver:検証可能なDNSの入口を用意する

enhanced-mode: fake-ipを使うと、カーネルは対象ドメインに仮想IPアドレスを返し、その対応関係に基づいて接続を処理します。これにより、接続開始前に実IPアドレスを解決する必要がある場面を一部減らせますが、すべての上流問い合わせがなくなるわけではありません。直接接続する通信、IPアドレスに基づくルール判定、一部のアプリでは引き続き実IPアドレスの解決が必要です。

以下はDNS経路を確認するための設定例であり、サブスクリプション設定全体ではありません。同名の項目を既存設定に統合し、ノード、グループ、ルールはそのまま残してください。同じ階層にdns:を重複して記述しないでください。例の7890は混合プロキシポート、1053はローカルDNS待ち受けポートです。互いに置き換えて使うことはできません。

mixed-port: 7890
mode: rule

dns:
  enable: true
  listen: 127.0.0.1:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "localhost"
    - "*.lan"
  nameserver:
    - https://1.1.1.1/dns-query
    - https://8.8.8.8/dns-query
  • enableはカーネルのDNS機能を有効にします。この項目だけを有効にしても、すべてのアプリが自動的にその待ち受けアドレスへ問い合わせるわけではありません。
  • listenはループバックアドレスにバインドし、ローカル端末からのテストに使います。調査のために全ネットワークインターフェースで待ち受けると、LANにDNSサービスを公開するおそれがあるため避けてください。
  • fake-ip-filterに登録したドメインは実IPアドレスで解決されます。互換性上必要なドメインだけを追加し、特定のアプリの問題を直すためにすべてのドメインを除外しないでください。
  • nameserverで上流DNSを指定します。複数の上流を指定しても、厳密な優先・待機順になるとは限りません。2つ目のアドレスが1つ目の完全な障害時だけ使われると決めつけないでください。

以下のコマンドで、カーネルのUDP DNS待ち受けを直接確認できます。フィルター対象外のドメインでは、198.18.0.0/16の範囲にある仮想IPアドレスが返るのが想定される結果です。これは今回の問い合わせがカーネルに届いたことを示すだけで、ブラウザーも同じ入口を使っている証明にはなりません。

# Windows
nslookup -port=1053 example.com 127.0.0.1

# digをインストール済みのmacOS / Linux
dig @127.0.0.1 -p 1053 example.com A

DoHの接続出口:暗号化通信でもプロキシ経由とは限らない

例のDoHは通常、TCP 443でHTTPS接続を確立するため、問い合わせ内容が通常のUDP 53として送信されることはありません。ただし、その接続が直接接続なら、リゾルバーから見えるのはローカルネットワークのグローバルIPアドレスです。ローカルネットワークからは、リゾルバーへの接続先アドレスが見える可能性もあります。リゾルバーにプロキシノードの出口を認識させたい場合は、カーネルが開始するDNS接続のルーティングも確認してください。

respect-rulesを使う前にノードのドメイン名解決を設定する

この項目に対応するmihomoでは、dns.respect-rules: trueを設定するとDNS接続にもルーティングルールが適用されます。ただし、「すべてのDNSを強制的にプロキシ経由にする」機能ではありません。リゾルバーのIPアドレスがDIRECTに一致すれば、接続は直接行われます。実際のルールで、選択したリゾルバーの宛先を既存のプロキシポリシーに割り当ててください。また、それより前にある直接接続ルールが先に適用されないよう確認しましょう。

有効にする場合は、プロキシノードのサーバードメイン名を起動時に解決するため、proxy-server-nameserverも設定してください。設定しないと、プロキシ接続にはノードのドメイン名解決が必要なのに、その名前解決にはプロキシ接続が必要という循環依存が起きることがあります。この起動時リゾルバーがネットワーク環境に合っていることも確認してください。起動時の名前解決を直接接続で行う場合、ノードのドメイン名がそのリゾルバーに伝わる点を理解したうえで選択する必要があります。

ドメイン形式のDoHアドレスを使う場合は、リゾルバー自身のドメイン名を起動時に解決する必要があります。default-nameserverはこの基礎的な名前解決に使うもので、通常の問い合わせに適用するデフォルトの振り分けルールではありません。上の例では切り分けを簡単にするため、IPアドレス形式のDoHを使っています。それでも上流に到達できること、TLS検証が正常なこと、実際の接続出口を確認してください。

fallbackとnameserver-policy:意図しない名前解決経路を減らす

fallbackでは並列問い合わせが行われる場合がある

fallbackは単純に「メインDNSがタイムアウトした後にだけ起動する」機能ではありません。設定すると、カーネルがメインと予備のリゾルバーに並行して問い合わせ、fallback-filterに従って採用する結果を決める場合があります。そのため、検査ページに予備DNSサービスが表示されても、メインDNSの障害を意味するとは限らず、問い合わせがプロキシを迂回したとも限りません。

調査の初期段階では経路を単純にするため、fallbackを省略することをおすすめします。基本経路を確認した後、特定の異常な応答を除外する必要があれば、以下の項目を同じdnsブロックに統合してください。この例ではGeoIP判定を無効にし、明示したアドレス範囲に一致した場合に予備DNSの結果を使う方法だけを示しています。すべての汚染された応答を検出できる設定ではありません。

  fallback:
    - https://9.9.9.9/dns-query
  fallback-filter:
    geoip: false
    ipcidr:
      - 0.0.0.0/32
      - 240.0.0.0/4

fallback-filter.geoipを有効にしてgeoip-code: CNを設定すると、メインDNSの応答が指定地域に属するかどうかによって採用する結果が変わります。これは応答のフィルタリングであり、DNS接続の出口を制御する機能ではありません。データベースの古さ、CDNアドレスの帰属変更、地域をまたぐ配信構成などで判定が変わるため、GeoIP判定を汎用的なDNSリーク対策として扱わないでください。

nameserver-policyで「どのDNSに解決させるか」を指定

nameserver-policyでは、ドメインごとに使用するリゾルバーを選べます。たとえば、以下の設定例ではexample.comとそのサブドメインに指定したDoHを使用します。このドメインは構文の説明用です。実際には専用のDNSが必要なドメインを設定し、統合後に動作を確認してください。

  nameserver-policy:
    "+.example.com":
      - https://1.1.1.1/dns-query

ドメインの名前解決ポリシーと、接続の振り分けルールは別々の仕組みです。リゾルバーを指定しても、そのWebサイトの通信がプロキシ経由になるわけではありません。同様に、Webサイトのルールをプロキシに設定しても、リゾルバーへの接続が必ずプロキシ経由になるとは限りません。社内ネットワークや家庭内機器のドメインにはローカルDNSが必要な場合があります。こうしたドメインだけを直接接続で解決するなら、意図的に残した例外として記録し、パブリックドメインの検査と混同しないようにしてください。

TUN DNS横取り:システムのポート53宛て問い合わせを取り込む

システムプロキシの影響を受けるのは主にプロキシ設定に従うアプリで、システムのDNS経路が自動的に切り替わるわけではありません。TUNはより多くのIP通信をカーネルに渡し、DNS横取りを組み合わせることで通常のDNS問い合わせを受け取ります。以下も既存設定に統合するための例です。TUNに対応したmihomoクライアントを使い、プラットフォームの要件に従って仮想ネットワークアダプターの作成とルーティング変更を許可してください。

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53
  • auto-routeはルートを自動設定する項目です。有効にした後は、スイッチがオンになっているだけでなく、クライアント上でTUNが実際に動作していることを確認してください。
  • any:53とtcp://any:53はそれぞれ、取り込み対象の経路に入る通常のUDP DNS問い合わせとTCP DNS問い合わせを対象にします。
  • auto-detect-interfaceは出口インターフェースの特定に役立ちます。複数のVPN、仮想ネットワークアダプター、特殊なルーティングがある場合は、実際に選択されたインターフェースを確認してください。

DNS横取りで、暗号化された名前解決がすべて取り込まれるわけではありません。アプリ内蔵のDoHはHTTPS、DoTは通常TCP 853を使うため、ポート53を指定してもカーネルDNSに切り替わりません。別のVPNがすでに通信を取り込んでいる場合、除外ルートを通る場合、特殊なシステム名前解決経路で処理される場合も、これらの横取りルールに入らないことがあります。

ブラウザーのセキュアDNSとIPv6は別々に確認する

検査中は、まずブラウザー独自のセキュアDNSを無効にして、ブラウザーとシステムが同じDNS経路を使う状態にすると切り分けやすくなります。Chromeでは「設定」→「プライバシーとセキュリティ」→「セキュリティ」から「セキュア DNS を使用する」を確認できます。表記はバージョンによって異なる場合があります。ブラウザーのDoHを使い続ける場合は、独立した経路として、リゾルバー、接続出口、失敗時のフォールバック動作を確認してください。

IPv6も確認してください。DNSからAAAAレコードが返ることと、IPv6通信が正しく取り込まれることは別の問題です。dns.ipv6: falseはカーネルのAAAA応答処理に影響しますが、システムのIPv6ルーティング制御の代わりにはなりません。アプリ独自の名前解決でIPv6アドレスが得られることもあります。IPv4の出口だけを確認して検査を終えないでください。

修正後の確認とよくあるトラブル

3つの観点から結果を確認する

  1. 入口の確認:ローカルの1053ポートへの問い合わせが正常に処理され、fake-ipの対応関係も想定どおりであることを確認します。TUN有効時には、システムの通常のDNS問い合わせがカーネルに届くことも確認してください。
  2. ルーティングの確認:クライアントの接続一覧またはデバッグログで、リゾルバーのアドレス、適用されたポリシー、接続出口を確認します。デバッグログを有効にした後は、確認が済み次第、通常のログレベルに戻してください。共有する前にドメイン名、ノード、サブスクリプションの情報を削除します。
  3. 外部からの確認:標準テストと拡張テストを再実行し、表示されたリゾルバーをすべて現在の設定で説明できるか確認します。ブラウザー、コマンドライン、保護対象のほかのアプリでも検証してください。

実際の出口インターフェースでパケットをキャプチャし、Wiresharkの表示フィルターudp.port == 53 || tcp.port == 53 || tcp.port == 853で通常のDNSと一般的なDoT接続を調べる方法もあります。キャプチャ対象のインターフェースを正しく選んでください。仮想ネットワークアダプター上の平文リクエストは、その後カーネルに取り込まれることがあり、物理インターフェースからの漏えいとそのまま判断できません。DoHはHTTPSに含まれるため、このフィルターだけでは問い合わせ内容を確認できません。

fake-ipを有効にしても検査結果にISPのDNSが表示される場合、まず何を確認すればよいですか?

まずローカルの1053ポートで、DNS設定が読み込まれていることを確認します。次に、システムの問い合わせがTUNに入っているかを確認してください。その後、ブラウザー独自の名前解決、ほかのVPN、ポリシーで指定したローカルDNS、サブスクリプションの更新によって変更が上書きされていないかを調べます。fake-ipだけでは、システムが使用するDNSの入口は切り替わりません。

DoHを設定したらどのWebサイトも開けなくなりました。どうすれば戻せますか?

変更前の設定に戻し、まずノードと基本ネットワークが使えることを確認してください。その後、到達可能と確認できたDoHを一つだけ有効にして、タイムアウト、TLSエラー、ノードのドメイン名解決の循環がないか調べます。この段階ではfallback、ポリシーによるDNS振り分け、ルール連動を同時に追加しないでください。

サブスクリプション更新後に対策が無効になりました。設定を維持するには?

ダウンロードしたサブスクリプションファイルを一度だけ直接編集するのではなく、クライアントが対応するオーバーライド、設定のマージ、設定拡張機能を使ってください。保存後に最終的な有効設定を確認し、dnsとtunの項目が後続のマージで上書きされていないことを確かめます。機能名は使用するクライアントによって異なります。

検査の目標は、結果ページに一つのアドレスだけを表示させることではありません。すべての名前解決経路について、接続元と出口を説明できる状態にすることです。完了後はブラウザーのセキュアDNS、LAN内名前解決の例外、ほかのネットワークツールを一つずつ元に戻し、その都度再検査してください。新たに加わった経路を特定でき、次に異常が起きたときに一から原因を推測せずに済みます。