1. DNSモードと通信の取り込みは別々の設定

dns.enhanced-modeは、DNSクエリへの応答方法を決めます。システムプロキシとTUNは、アプリの通信をどのようにコアへ取り込むかを決めます。この2つは互いに代用できません。Fake-IPを有効にしても、システム上のすべてのDNSリクエストが取り込まれるわけではありません。TUNを有効にしても、ブラウザー内蔵の暗号化DNSが必ずコアで解決されるとは限りません。

この記事では、mihomoコアを使用するClashクライアントを対象に説明します。旧バージョンのClashや異なる派生コア、クライアント側の設定上書き機能では、動作が異なる場合があります。操作前に現在の設定をバックアップし、コアのバージョンを記録したうえで、サブスクリプションの元ファイルだけでなく、実行時設定のdns項目も確認してください。

  • システムプロキシ:アプリがドメイン名を指定してHTTPプロキシへ接続する場合、コアは接続先の名前を直接取得できます。そのため、ローカルDNSのFake-IPマッピングに依存しないことがあります。
  • TUN:アプリが送信するIPパケットを受け取ります。元のドメイン名を復元するには、DNSの取り込みとマッピングテーブルが特に重要です。
  • DNSリスナー:たとえば127.0.0.1:1053は、コアがDNSクエリを受け付ける待ち受け先にすぎません。適切な転送やリダイレクト経路を通じて、システムからクエリを送る必要があります。

設定が有効か確認するには、「DNSクエリがどこへ送られるか」と「その後の接続がどこへ向かうか」を個別に調べます。クライアントのメインスイッチを見るだけでは、2つの経路が一致しているか判断できません。

2. Fake-IPのアドレス割り当てとドメイン復元の仕組み

Fake-IPの基本は、「ドメイン名と合成IPアドレス」の対応付けです。アプリからドメインのIPv4アドレスを問い合わせられると、コアはfake-ip-rangeで指定されたアドレスプールからアドレスを割り当てて返せます。実際のAレコードが返るのを待つ必要はありません。よく使われるアドレスプールは198.18.0.1/16で、ベンチマーク用に予約されたアドレス空間です。WebサイトのグローバルIPアドレスではありません。

  1. アプリがexample.comを問い合わせ、クエリがmihomoのDNSに届きます。
  2. コアはプール内の合成アドレスを返し、そのアドレスとexample.comの対応関係を保存します。割り当てられる値は実行時の状態によって変わるため、固定値として扱わないでください。
  3. アプリが合成アドレスへ接続し、その通信がTUNなどの取り込み経路を通って、同じコアのインスタンスに届きます。
  4. コアはマッピングテーブルからドメイン名を復元し、ルールに応じてDIRECTまたはプロキシ経由で接続します。
  5. DIRECT接続では通常、実際の接続先アドレスを解決する必要があります。ドメイン名を転送できるプロキシ接続では、ドメイン名の処理をリモート側に任せられます。実際の動作はルール、ノードのプロトコル、関連するDNS設定にも左右されます。

待ち時間を短縮できる場合がある理由

ドメイン名で接続先を振り分け、ドメイン名をプロキシへ渡せる場合、ローカルで接続先の実IPアドレスを先に調べる必要はありません。そのため、ローカルDNSの解決が遅い場合や妨害されている場合でも、最初の接続が必ずしも待たされるとは限りません。ただし、Fake-IPでノードとのハンドシェイク、リモート側の名前解決、サーバーの応答時間が短縮されるわけではなく、すべてのサイトが速くなる保証もありません。

マッピングが失われると通信できなくなる理由

合成アドレスが意味を持つのは、そのマッピングを保持しているコアの中だけです。アプリに古いアドレスがキャッシュされている状態でコアを再起動し、マッピングが引き継がれなければ、その後の接続でドメイン名を復元できないことがあります。クライアントの切り替え、DNSモードの変更、通信を別のゲートウェイへ通す場合にも、同様の問題が起こりえます。解決するにはDNSクエリをやり直してください。合成アドレスに通常のDIRECTルールを追加しても解決しません。

3. redir-hostの名前解決タイミングとルール判定の違い

redir-hostでは通常、まず上流DNSへ問い合わせ、実際のアドレスをアプリに返します。コアは、自身を経由したDNSクエリの結果を使ってドメイン名とIPアドレスの対応を記録し、後続の接続でドメイン名を復元します。アプリから見えるのが実際のアドレスである点が互換性上のメリットですが、実IPアドレスとドメイン名が常に一対一で対応するとは限りません。

比較項目Fake-IPredir-host
アプリに返すAレコード通常はアドレスプール内の合成アドレス通常は上流DNSが返す実アドレス
初回問い合わせの待ち時間合成アドレスの割り当てでは、通常、接続先の実アドレス解決を待つ必要がない通常は上流DNSの解決完了を待つ必要がある
ドメイン名の復元に使う情報合成アドレスに対応するマッピングDNSクエリの記録と実IPアドレスの対応関係
IPアドレス共有の影響ドメインごとに個別のマッピングを作成できる複数のドメインでIPアドレスを共有すると、対応付けが曖昧になることがある
アプリが独自に暗号化DNSを使用する場合合成アドレスの割り当てを迂回する可能性があるコアのDNS対応記録を迂回する可能性がある
LANサービスとの互換性内部ドメインにはフィルター設定が必要なことが多い実際のプライベートIPアドレスを返すほうが通常は扱いやすい

ルールによっても名前解決のタイミングは変わります。Fake-IPが有効でも、接続先の実IPアドレスを必要とするルールを評価する際に、コアが名前解決を行うことがあります。IP-CIDRなどのルールに指定するno-resolveは、そのルールのためにドメイン名を積極的に解決するのを避ける設定です。「接続全体の名前解決を禁止する」スイッチではありません。ルールの順序、実IPアドレスがすでに判明しているか、ほかのルールの動作もあわせて確認してください。

プログラムがIPアドレスへ直接接続し、事前にコアへドメイン名を問い合わせていない場合、どちらのDNSモードでも元の名前を確実に知ることはできません。通信のスニッフィングで一部のプロトコルのハンドシェイクからドメイン名を取得できることはありますが、DNSマッピングの代わりにはならず、すべての暗号化プロトコルに対応するわけでもありません。

4. Fake-IPとDNS漏れの関係

DNS漏れとは通常、本来想定していた経路を通らずにクエリが送信される状態を指します。たとえば、指定したリゾルバーへ送るはずのクエリが、接続中のネットワークから提供されたDNSへ送られるケースです。Fake-IPは、プロキシ対象ドメインの一部についてローカルで実IPアドレスを解決する必要を減らせますが、DNS漏れを防ぐ万能スイッチではありません。redir-hostでも必ず漏れるわけではありません。漏れの有無は、クエリを取り込む範囲、上流DNSのプロトコル、接続に使う出先によって決まります。

  • ブラウザーのセキュアDNS:ブラウザーがHTTPS経由で外部リゾルバーへ直接問い合わせると、システムDNSを迂回することがあります。切り分けの際は一時的にこの機能を無効にし、結果を比較してください。
  • 通常のUDP/TCP DNS:ポートは通常53です。TUNのDNSリダイレクトで条件に合うクエリを取り込めますが、HTTPSの443番やTLSの853番を使う暗号化DNSは、ポート53のルールだけでは単純に処理できません。
  • IPv6:Aレコードの確認だけでは不十分です。AAAAクエリ、IPv6ルート、アプリの接続先も確認してください。IPv4用Fake-IPアドレスプールが機能していても、IPv6の経路が取り込まれているとは限りません。
  • ブートストラップとノードの名前解決:暗号化DNSサービスのドメイン名やプロキシノードのサーバー名には、別の解決経路が使われる場合があります。default-nameserverやproxy-server-nameserverなどの項目を確認してください。

DoHを使うとリゾルバーまでのクエリを暗号化できますが、その接続がプロキシ経由になるとは限らず、リゾルバーからドメイン名が見えなくなるわけでもありません。DNSチェックサイトに表示される事業者は、そのサイトが観測したDNSの出口を示すにすぎません。コアのログやパケットキャプチャも確認し、問い合わせ先のリゾルバーと実際の出先を照合してください。

5. fake-ip-filterの設定とLANでの例外

fake-ip-filterでは、通常のFake-IP方式で応答しないドメインを指定します。以下の例では、mihomoのblacklistフィルターモードを明示しています。リストに一致したドメインには実際の名前解決結果を返し、それ以外のドメインには引き続き合成アドレスを割り当てます。古いコアがfake-ip-filter-modeに対応していない場合は、該当バージョンのドキュメントを確認してから設定してください。項目をそのまま流用しないでください。

dns:
  enable: true
  listen: 127.0.0.1:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter-mode: blacklist
  fake-ip-filter:
    - "*.lan"
    - "*.home.arpa"
    - "router.home.arpa"
  nameserver:
    - 223.5.5.5
  nameserver-policy:
    "+.lan": 192.168.1.1
    "+.home.arpa": 192.168.1.1

これは設定項目の関係を示す例であり、全設定を置き換えられるサブスクリプションファイルではありません。192.168.1.1は内部ドメインの名前解決を実際に担うルーターを想定しています。使用前に、現在のネットワークで使っている内部DNSのアドレスに置き換えてください。パブリックDNSには通常のDNSを使用しており、処理の流れを確認するための例です。暗号化DNSやプロキシ経由の名前解決を推奨するものではありません。listenを設定しても、システムDNSは自動で変更されません。

フィルター、名前解決ポリシー、出先ルールはそれぞれ別の役割

  • fake-ip-filter:一致したドメインに合成アドレスを返さないようにします。DIRECT接続を指定するものではありません。
  • nameserver-policy:内部ドメインを解決できるDNSを選びます。通常、パブリックDNSには企業や家庭ネットワーク内のプライベートなレコードは登録されていません。
  • rules:接続に使う出先を決めます。内部サービスに実IPアドレスが返されても、適切なDIRECTルールと到達可能なルートが必要です。

たとえば、広範囲に適用されるプロキシルールより前に、次の2つのルールを置けます。これらは出先の選択だけを制御し、DNSポリシーの代わりにはなりません。例に合わせるために既存のルールを削除しないでください。

rules:
  - DOMAIN-SUFFIX,home.arpa,DIRECT
  - DOMAIN-SUFFIX,lan,DIRECT

LANサービスに問題が起きやすい理由

NAS、プリンター、画面ミラーリング、一部のゲームのデバイス検出では、接続先がローカルネットワーク内にあるか確認したり、名前解決の結果をほかのデバイスへ渡したりすることがあります。198.18.0.0/16の範囲内のアドレスが返されると、アプリが接続を拒否する場合があります。同じマッピングを持たない別のデバイスも、そのアドレスを利用できません。まず実際に使う内部ドメインだけをフィルターに追加し、最初からすべてのドメインを対象外にしないでください。

.localはmDNSで使われることが多く、通常のユニキャストDNSだけでなくマルチキャストによる検出も関係します。*.localをフィルターに追加しても、mDNSが自動的に復旧するわけではありません。画面ミラーリング機器が見つからない場合は、LANへのアクセス許可、マルチキャスト転送、TUNルート、ファイアウォールも確認してください。ルーターからほかのデバイスへDNSを配布する場合は、それらのデバイスから合成アドレスへの通信も、マッピングを保持するゲートウェイを経由する必要があります。

6. DNS応答と通信の取り込みを確認する

まず待ち受け先を明示してコアのDNSを確認し、次にシステムの標準クエリ経路を調べます。以下のコマンドは、対応するツールがインストールされたシステムで使用できます。問い合わせ先ポート1053は、実行中の設定と一致させてください。

# Windows:コアのDNSへ直接問い合わせ
nslookup -port=1053 example.com 127.0.0.1

# macOS / Linux:コアのDNSへ直接問い合わせ
dig @127.0.0.1 -p 1053 example.com A

# 内部ドメインに実際のプライベートIPアドレスが返るか確認
dig @127.0.0.1 -p 1053 router.home.arpa A
  1. 応答を確認:フィルター対象外のドメインには、Fake-IPモードの設定に応じてプール内のアドレスが返るはずです。フィルター対象の内部ドメインには、内部DNSが返す実際のアドレスが返るはずです。タイムアウトする場合は、まず待ち受け先とコアの起動状態を確認してください。
  2. システム側の経路を確認:続いて、サーバーを指定せずにnslookup example.comを実行するか、通常のアプリからアクセスします。コアへの直接問い合わせが成功しても、システムのクエリがコアへ届いているとは限りません。
  3. 接続記録を確認:クライアントの接続画面やログで、ドメイン名、適用ルール、出先を確認します。名前解決できても接続できない場合は、通信が同じコアに届いているか、ルールで誤ったノードが選ばれていないか調べてください。
  4. IPv6を個別に確認:AAAAレコードを問い合わせ、アプリが実際に使用するアドレスファミリーを確認します。Aレコードが正常だからといって、DNS経路全体も正常だとは判断できません。

切り分け中はlog-levelを一時的にdebugへ変更し、完了後に通常のレベルへ戻してください。ドメイン名が大量に記録される状態を長時間続けないようにします。ログを共有する前に、サブスクリプションURL、トークン、ノードの認証情報、内部ホスト名を削除してください。

7. モード切り替えとトラブル対処の手順

TUNでドメイン名ルールによる振り分けを主に使い、DNSと接続の両方が同じコアに届くなら、Fake-IPを優先して検討できます。実IPアドレスを必要とするアプリが多い、内部サービスが複雑、または制約のある環境で合成アドレスを確実に取り込めない場合は、redir-hostとの互換性を比較してください。判断基準はモード名ではなく、通信経路です。

症状まず確認する項目対処方法
合成アドレスが返った後、接続がタイムアウトするTUNルートとコアのマッピングが一致しているか通信の取り込み経路を修正し、DNSを再問い合わせする
インターネットは正常だが、NASのドメイン名に接続できないフィルターリスト、内部DNS、DIRECTルール対象の内部ドメインに例外を設定する
再起動後、一部のアプリが切断されるアプリに古い合成アドレスがキャッシュされていないか既存の接続を閉じ、キャッシュを消去して再試行する
サブスクリプション更新後にモードが元に戻るクライアントによるDNS設定の上書きとサブスクリプション更新の仕組み実際に適用されている設定レイヤーを変更する
ブラウザーだけ結果が異なるブラウザーの暗号化DNSと独自キャッシュテスト経路を統一してからモードを比較する

一度に変更するのは1つの項目だけ

  1. 設定をバックアップし、現在のenhanced-mode、DNS上流、TUNの状態を記録します。
  2. DNSモードだけを切り替え、同じノード、同じルール、同じテスト用ドメインを使います。
  3. 設定を適用したら古い接続を閉じ、システムとアプリのDNSキャッシュを消去します。Windowsではipconfig /flushdnsを実行できます。ブラウザーなどのアプリは個別に再起動が必要な場合があります。
  4. パブリックドメイン、内部ドメイン、実際の業務アプリの順にテストし、問い合わせ、ルール判定、接続開始のどの段階で失敗するかを記録します。

IPv6を恒久的に無効にする、すべてのドメインを一括でフィルターする、ノードを切り替えるといった変更を、一度に修正策として適用しないでください。条件を複数同時に変更すると、原因を特定する手がかりが失われます。各項目の意味は設定項目リファレンスで、通信の取り込み経路は入門ガイドで確認できます。

最終的な設定では、3つの条件を満たす必要があります。クエリが想定したリゾルバーへ送られること、接続が想定したコアに届くこと、ルールが想定した出先を選ぶことです。Fake-IPとredir-hostは、この経路におけるDNS処理方式にすぎません。3点を個別に検証すれば、名前解決、ルーティング、プロキシノードのどこに問題があるか切り分けられます。