ClashのDNSリーク検出と対策:名前解決の経路と漏えい防止設定

ブラウザテストとシステム照会でDNSの出口を特定し、fake-ip、DNSハイジャック、フォールバックDNSを設定してリークのリスクを抑えます。

DNSリークとClashの名前解決経路

Webサイトにアクセスすると、通常はまずドメイン名をDNSリゾルバーに渡し、返されたIPアドレスへ接続します。プロキシルールによって、その後の接続を直接接続にするかプロキシ経由にするかは決められますが、DNSクエリまで自動的に同じ経路を通るとは限りません。Webトラフィックがプロキシを経由していても、ドメイン名の問い合わせがローカルルーター、通信事業者のDNS、または想定外のサーバーへ送信されれば、一般にDNSリークと呼ばれる状態になります。

ここでいう「リーク」は、想定する構成と照らし合わせて判断する必要があります。中国本土向けの直結ドメインをローカルDNSで解決すること自体は、必ずしも問題ではありません。重要なのは、本来プロキシ側で解決すべきドメインがローカルネットワークに公開されていないか、応答が不正に書き換えられていないか、そして各アプリがClashのDNSモジュールを迂回していないかです。検出サイトで特定の固定アドレスだけを表示させることが目的ではなく、名前解決の経路がルール設計と一致していることが本来の目標です。

一般的な名前解決の経路は4層に分けられます。アプリがクエリを発行し、OSがDNSサーバーを選択し、Clashまたはmihomoがクエリを受け取って処理し、上流リゾルバーが結果を返します。システムプロキシを有効にしても、通常はHTTPまたはSOCKSプロキシ設定に従う接続だけが対象で、OSがUDP 53番ポートへ送るDNSリクエストまで引き受けることはありません。TUNを有効にすると、クライアントはシステムのネットワークトラフィックをさらに捕捉できますが、通常のUDP/TCP DNSクエリを内蔵リゾルバーへ取り込むには、DNSハイジャックの設定も必要です。

ブラウザではDNS over HTTPS、つまりDoHが有効になっている場合もあります。DNSをHTTPS接続にカプセル化し、ブラウザが指定したサービスへ送信する仕組みです。この通信は443番ポートを使うため、通常の53番ポートのハイジャックでは識別できず、独立した名前解決経路になります。トラブル解決ではClash、OS、ブラウザをすべて確認し、クライアント画面のDNSスイッチだけを見て判断しないでください。

DNSの出口を段階的に検出:ブラウザ、システム、ログ

検出前に、システムプロキシの有効・無効、TUNの状態、Clash DNSの有効・無効、ブラウザのセキュアDNSの状態を記録します。次に、Clashを完全に終了した状態、システムプロキシだけを有効にした状態、TUNを有効にした状態の3パターンでそれぞれテストします。キャッシュ、ネットワークの切り替え、パブリックDNSの振り分けによって結果は変わるため、1回のスクリーンショットより比較結果のほうが有用です。

ステップ1:ブラウザで実際のアクセス環境を確認

  1. 古い接続やメモリキャッシュの影響を避けるため、ブラウザのウィンドウをすべて閉じてから再起動します。
  2. 信頼できるDNS検出サイトにアクセスし、基本テストと拡張テストを実行して、リゾルバーのIP、ネットワーク事業者、地域を記録します。
  3. ClashのシステムプロキシまたはTUNの状態を切り替え、もう一度テストしてリゾルバーが変化したか比較します。
  4. ブラウザ設定にあるセキュアDNS、安全なDNSの使用、DNS over HTTPSの項目を確認し、独立したプロバイダーが指定されていないか確認します。

検出サイトでは通常、ランダムなサブドメインを生成し、どのリゾルバーが権威DNSへ問い合わせたかを確認します。これはそのサイトがクエリを発生させた際の出口を示すもので、すべてのアプリが同じ名前解決経路を使うことを意味しません。ブラウザ拡張機能、企業ポリシー、システムキャッシュ、ネットワーク上の透過プロキシでも結果は変わるため、システムコマンドとClashのログも併用して確認してください。

ステップ2:OSが使用中のDNSを確認

WindowsではPowerShellでネットワークアダプターのDNSを確認し、未キャッシュのドメインを明示的に問い合わせます。

Get-DnsClientServerAddress
Resolve-DnsName example.com

macOSでは、現在のリゾルバー一覧とシステムの名前解決結果を確認できます。

scutil --dns
dscacheutil -q host -a name example.com

systemd-resolvedを使用するLinuxディストリビューションでは、次のコマンドを実行できます。

resolvectl status
resolvectl query example.com

コマンド出力に表示されるDNSサーバーは、ローカルループバックアドレス、LANゲートウェイ、またはTUNが割り当てた仮想アドレスの場合があります。ローカルアドレスが表示されたからといって、クエリがローカルで止まっているとは限りません。Clashが最終的にどの上流を選択したかも確認してください。逆に、システムがルーターへ直接クエリを送っているのにClashのログに対応する記録がなければ、そのリクエストはClash DNSモジュールに入っていない可能性が高いです。

ステップ3:ログと組み合わせて名前解決経路を特定

クライアントのログレベルを一時的に、DNSの動作を確認できるレベルへ変更し、これまでアクセスしていないドメインを問い合わせます。ログにドメイン解決、ルールのマッチ、上流への接続、失敗時の再試行が記録されているか確認します。テスト後は通常使うログレベルに戻し、大量のデバッグ情報が長期間ストレージを圧迫しないようにしてください。

ログにクエリの記録がまったくない場合は、まずシステムDNS、TUNのDNSハイジャック、ブラウザのDoHを確認します。クエリは記録されているものの、上流接続が想定外のDIRECTまたはプロキシポリシーになっている場合は、リゾルバーのアドレス自体がどのようにルールへマッチしているかを確認します。初回アクセスだけ異常で、その後は正常に戻るなら、システム、ブラウザ、ClashそれぞれのDNSキャッシュも確認してください。

Clash Meta(mihomo)のDNS設定とfake-ip

mihomoのDNSモジュールはクエリを一元的に受け取り、設定に応じて上流リゾルバーを選択できます。以下は各フィールドの関係を理解するための例です。実際に使う際は既存の設定へ統合し、ネットワーク環境、カーネルのバージョン、購読ルールに合わせて調整してください。変更前に元の設定を保存し、YAMLのインデントやフィールドの互換性によって設定を読み込めなくなる事態を避けます。

dns:
  enable: true
  listen: 0.0.0.0:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "*.lan"
    - "localhost"
    - "+.local"
  default-nameserver:
    - 223.5.5.5
    - 1.1.1.1
  nameserver:
    - https://dns.alidns.com/dns-query
    - https://doh.pub/dns-query
  proxy-server-nameserver:
    - https://dns.alidns.com/dns-query
  fallback:
    - tls://1.1.1.1
    - https://1.1.1.1/dns-query
  fallback-filter:
    geoip: true
    geoip-code: CN
    ipcidr:
      - 240.0.0.0/4

nameserverとdefault-nameserverの役割

nameserverは通常のドメイン問い合わせに使う主要な上流です。通常のDNS、DoT、DoHのアドレスを指定できます。暗号化DNSによって、ローカル経路でクエリの内容を直接読み取られたり改ざんされたりする可能性は下がりますが、上流サービス自体はクエリを処理できます。利用可能で、自分の信頼できる範囲に合ったサービスを選んでください。

default-nameserverは主にブートストラップ用の名前解決を担います。たとえばDoHの上流をドメイン名で指定した場合、暗号化接続を確立する前に、そのDoHドメインのIPアドレスを取得する必要があります。このフィールドには通常、直接アクセスできるIPアドレスを指定し、「DNSサービス自体を解決するために同じDNSサービスを先に使う」という循環を避けます。ブートストラップの問い合わせは通常のDNSとして行われる場合があるため、安定していて現在のネットワーク環境に適したアドレスを選択してください。

proxy-server-nameserverはプロキシサーバーのドメイン名を解決するために使います。プロキシノードをドメイン名で指定している場合、プロキシ接続を確立する前にノードのIPを取得しなければなりません。この問い合わせを分けて設定すると、ノードの名前解決と通常のルールが相互に循環する可能性を抑えられます。respect-rulesなど新しいフィールドを使う場合は、現在のmihomoカーネルのバージョンとクライアントの実装を確認してください。古いカーネルではフィールドが無視されたり、設定エラーが報告されたりすることがあります。

fake-ipがルールマッチに参加する仕組み

fake-ipモードでは、Clashが予約アドレス範囲内の一時的なマッピングアドレスをアプリへ返し、ドメイン名と偽IPの対応関係を保存します。アプリがそのアドレスへ接続すると、カーネルは元のドメイン名を復元してドメインルールのマッチングを続行できます。これによりリクエストを早い段階で引き受けやすくなり、アプリが自前の解決結果を使って直接接続するケースも減らせます。

198.18.0.0/15はベンチマークに使われることが多い予約ネットワークで、例にある198.18.0.1/16もこの範囲に含まれます。fake-ipのアドレスをWebサイトの実IPとみなさないでください。また、偽IPへのping結果でリモートサーバーの状態を判断することもできません。クライアントのマッピングは、現在のカーネルとキャッシュの有効期間内だけ有効です。

LANデバイスの検出、プリンター、画面ミラーリング、一部のゲーム、実IPに依存するプログラムは、fake-ipに適さない場合があります。その場合は必要なドメインをfake-ip-filterへ追加し、実際の名前解決結果を返すようにします。フィルター範囲を無制限に広げると、多数のドメインが再び実IPの解決へ戻り、一元的なトラフィック捕捉とドメインルールのマッチング効果が弱まります。

TUNモードとDNSハイジャックの設定

mihomoのDNSサービスを有効にしただけでは、システムが自動的にクエリをそこへ渡すとは限りません。クライアントはシステムDNSをローカルの待ち受けポートへ変更するか、TUN上で従来のDNSトラフィックをハイジャックできます。デスクトップ版でよく使われる設定は次のとおりです。

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

dns-hijackは、TUNを通過する53番ポートのクエリをmihomo DNSモジュールへ転送し、アプリが通常のDNSサーバーを自分で指定する一般的なケースにも対応します。通常はUDP 53とTCP 53を処理できますが、443番ポートへ送られるDoHを自動的に識別することはできません。また、独自のネットワークスタック、特殊な仮想NIC、カーネルレベルのバイパスを使うすべてのプログラムがTUNに入るとは限りません。

WindowsでTUNを有効にするには、管理者権限と利用可能な仮想NICコンポーネントが必要になることがあります。macOSでは、システムネットワーク拡張機能またはVPN設定でトンネルを構築します。Linuxでは、TUNデバイスの権限に加えて、ルーティングテーブルとファイアウォールルールの設定が必要です。AndroidとiOSのクライアントは通常、システムVPNインターフェースを使ってトラフィックを引き受けますが、同時に有効にできる主要なVPN設定は一般に1つだけです。

TUNを有効にした後、ドメインがまったく解決できなくなった場合は、まずTUNルートが構築されているか確認し、次にmihomoのDNS待ち受けポートが他のプロセスに使用されていないか確認します。さらに、ファイアウォールがカーネルから上流DNSへのアクセスを遮断していないか、プロキシノードのドメイン名がproxy-server-nameserverで解決できるかも確認してください。ノードの名前解決に失敗するとプロキシトンネルを確立できません。しかも上流DoHへのアクセスをプロキシ経由にしている場合、起動時に循環が発生します。

企業VPN、ゲームブースター、仮想マシンのネットワーク、コンテナネットワーク、その他のプロキシツールを同時に実行すると、複数のプログラムがデフォルトルートやDNS設定を奪い合うことがあります。トラブル解決では競合するツールを1つずつ停止し、Clashだけを動かしたときの結果を確認してから、ルートの優先順位を決めてください。ネットワークを頻繁に切り替えた後にDNS設定が残っている場合は、まずクライアントを終了し、システムDNSを自動取得へ戻してからTUNを再度有効にします。

ブラウザのDoHとアプリ内蔵リゾルバー

Chrome、Edge、Firefoxなどのブラウザでは、暗号化DNSを個別に有効にできます。ブラウザによってはシステムDNSを対応サービスのDoHへ自動的に切り替えようとし、手動でリゾルバーを指定できるものもあります。指定したサービスがClashの設定と異なる場合、ブラウザテストに別のDNS出口が表示されます。これは必ずしもTUNの失敗を意味せず、ブラウザが独立したHTTPS接続を自ら確立して問い合わせている可能性があります。

ブラウザでClash DNSを一元的に使うには、ブラウザのカスタムセキュアDNSを無効にして、問い合わせをOSへ戻し、システムDNSまたはTUNのハイジャックを通じてmihomoへ渡します。別の方法としてブラウザのDoHを維持し、ClashのルールでDoHサービスへの接続をプロキシ経由にするか直接接続にするか制御することもできます。ただしこの場合、ドメインの問い合わせはリモートのDoHサービスで行われるため、mihomoが各クエリの内容を直接取得することはできません。ドメインベースの振り分けも、ブラウザが後続接続に付加するドメイン情報に依存する場合があります。

アプリによっては固定DNS、DoH、DoTを内蔵しており、セキュリティソフトやペアレンタルコントロールもローカルのフィルタリングリゾルバーを配置することがあります。特定のアプリだけ結果が異常な場合は、Clashの上流を何度も変更するのではなく、そのアプリのネットワーク設定、起動パラメーター、システムポリシーを確認してください。Androidの「プライベートDNS」は通常DoTを使用します。VPNクライアントとの併用で問題が起きる場合は、一時的に自動または無効にして比較テストを行います。テスト後、実際の用途に合わせて最終設定を決めてください。

よくあるDNSリークと名前解決障害のトラブル解決手順

検出結果にローカル通信事業者のDNSが表示される

まずブラウザのセキュアDNSが無効になっているか確認し、次にシステムDNSがクライアントの引き受け用アドレスを指しているか確認します。システムプロキシだけを有効にしてTUNを有効にしていない場合、システムレベルのUDP DNSがルーターへ送られ続けるのは一般的な動作です。一元的に引き受けるには、互換性のあるTUNとDNSハイジャックを有効にし、クエリがクライアントログに記録されることを確認してください。

fake-ipを有効にするとLANデバイスへアクセスできない

LAN用のドメインサフィックスをfake-ip-filterへ追加し、LANセグメントのルールがデフォルトのプロキシルールより前にあることを確認します。NAS、ルーター、プリンターへアクセスする際は、まずLANアドレスで基本的な接続性を確認してください。IPアドレスではアクセスできるのにドメイン名ではできない場合は、ルーターDNS、mDNS、内部DNSのどれがローカルドメインを提供しているかを重点的に確認します。

DoHの上流接続がタイムアウトする

まずdefault-nameserverでDoHドメインのブートストラップ解決ができるか確認し、次にそのIPが誤った経路へ振り分けられていないか確認します。ネットワークによっては特定のパブリックDNSサービスが制限されるため、到達できない上流をむやみに追加すると再試行時間が延びるだけです。検証済みの上流を少数に絞り、直接接続とプロキシ経路に応じて設定を分けるほうが、多数のアドレスを重ねるより問題を特定しやすくなります。

プロキシノードは利用可能なのに、Webサイトでドメインを解決できないと表示される

ノードの接続性テストは、既存のIPアドレスやキャッシュ結果を使うことがあり、DNS経路が正常だと証明するものではありません。ノードアドレスがIPかドメイン名かを確認し、ドメイン名の場合はproxy-server-nameserverが利用できるか確認します。その後、通常のドメインを問い合わせてログを観察し、「ノードのドメインを解決できない」「上流DNSへ接続できない」「応答結果がルールで拒否された」という3種類の問題を切り分けます。

テスト結果に複数のリゾルバーが表示される

複数のリゾルバーは、上流サービスのクラスタ、ブラウザによる並列問い合わせ、フォールバック解決、またはシステムとブラウザの2経路が同時に動作していることが原因かもしれません。まず数だけで異常と判断しないでください。ランダムなドメインで再テストし、ブラウザのDoH、fallback、その他のネットワークツールを個別に無効化して、どの設定が追加の出口を生んだか確認します。すべてのリゾルバーが想定した上流に属し、ローカルネットワークのリゾルバーがプロキシ用ドメインを処理していなければ、設計どおりの結果である可能性があります。

設定を更新すると問題が再発する

購読の更新によってクライアントのDNSセクションが上書きされたり、ルールグループ名が変わって既存のnameserver-policyや上流の振り分けが機能しなくなったりすることがあります。クライアントが使用しているのが購読元の設定、上書き設定、結合後の設定のどれかを確認してください。長期的に保持したいDNS設定は、クライアントが対応する上書き機構へ配置し、更新のたびに最終的に有効な設定を確認します。購読元ファイルだけを確認して終わらせないでください。

完全なトラブル解決では、一連の確認を閉じたサイクルにします。まず、どのドメインをローカルで解決し、どの問い合わせをプロキシ側で処理するかを明確にします。次にブラウザテストで現象を確認し、システムコマンドでDNSの向きを確認し、ログでクエリがmihomoへ入ったか検証します。最後にfake-ip、上流リゾルバー、TUNハイジャック、ブラウザのDoHを調整します。一度に変更する変数を1つだけにして再テストすれば、どの設定が改善につながったか判断できます。

インストールと設定を続ける

ダウンロードページで現在のプラットフォームに合ったClashクライアントを選ぶか、クイックスタートガイドに沿って購読のインポート、プロキシの有効化、接続確認を完了してください。

ダウンロードページへ ガイドを見る