mihomoのDNS設定ガイド:nameserver・fallback・DNS hijackの設定方法

mihomoのdns設定を項目ごとに解説。enhanced-mode、nameserver、fallback、fallback-filter、dns-hijackの設定例を用途別に紹介します。

まずDNSリクエストの経路を確認する

まず「名前解決」と「接続の転送」を区別しましょう。DNSはドメイン名をIPアドレスに変換する仕組みです。プロキシルールは接続を直接接続するか、プロキシ経由にするかを決めます。名前解決に成功しても、通信がプロキシ経由になるとは限りません。また、システムプロキシを有効にしても、システムのすべてのDNSクエリがmihomoに届くわけではありません。

次に、クライアントで使用しているコアを確認します。mihomoはClash Metaの名称変更後も開発が続くコアです。GUIクライアントは設定の生成、コアの起動、システムネットワークの管理を担います。この記事はmihomoの設定項目に基づいており、すべての例が旧版のClashで使えるわけではありません。クライアントのコア情報画面でバージョンを確認するか、以下のコマンドを実行してバージョンと設定チェックの結果を記録してください。

mihomo -v
mihomo -t -f config.yaml

以下の順に確認しましょう。問題が起きている箇所だけを変更すれば、DNS、ノード、ルールを一度に入れ替えるより原因を特定しやすくなります。

  1. アプリからクエリを送信:ブラウザーは独自のセキュアDNSを使う場合があります。ターミナルのプログラムは通常、システムのリゾルバーを呼び出します。
  2. リゾルバーにリクエストが届く:ルーター、システムDNS、またはmihomoのDNS待ち受けポートに届く可能性があります。
  3. コアが上流DNSを選択:mihomoは名前解決の方針に基づいてDNSサーバーを選び、設定に従って応答をフィルタリングします。
  4. アプリが接続を確立:その後、コアがプロキシルールに従って接続先への経路を選びます。

dnsセクションの基本:待ち受け・モード・上流DNSを分けて設定

まず、それぞれの項目の役割を確認します。表中のポート番号はこの記事の例であり、各クライアントの既定値とは限りません。実際に稼働している設定を確認してください。

項目役割確認ポイント
enableコアのDNS機能を有効化trueにしても、リクエストがコアに届くようにする必要があります
listenDNSクエリの待ち受けアドレスを設定127.0.0.1:1053はローカルマシンからのみアクセス可能
enhanced-mode拡張名前解決モードを選択一般的にはfake-ipまたはredir-hostを使用
default-nameserver上流DNSサーバーのドメイン名を解決名前解決経路の起動に使う設定で、すべての通常ドメインの既定上流を意味するわけではありません
nameserver通常の名前解決に使う上流DNSを設定リストの順序は、単純な順次フェイルオーバーを意味しません
fallback予備の応答候補となる上流DNSを指定主な上流DNSがタイムアウトしたときだけ使う予備アドレスではありません
fallback-filter予備の名前解決結果を使う条件を設定ドメイン名、GeoIP、IPアドレスの範囲を組み合わせて判定できます

fake-ipとredir-hostの選び方

まず互換性の要件に合わせてモードを選びます。fake-ipは条件に合うクエリに仮想アドレスを割り当て、コア内にドメインとの対応関係を保存します。アプリがそのアドレスに接続すると、コアはドメイン名を特定して接続を処理できます。例の198.18.0.1/16は仮想アドレスプールの設定であり、パブリックDNSサーバーとして設定するアドレスではありません。

実アドレスでの名前解決が必要なプログラムがある場合は、ドメインごとにfake-ip-filterを追加するか、比較のためにredir-hostを試してください。後者は実際に解決したアドレスを返します。モードを切り替えた後は、システムとアプリのDNSキャッシュを消去し、既存の接続を再起動してください。切り替え前のアドレスを使い続けると、「設定が反映されない」と誤解することがあります。

ケース1:最小構成でnameserverを検証する

まずは上流DNSを1組だけ有効にし、基本の名前解決が正常になってからfallbackを追加します。以下は単独で使える診断用設定です。ローカルの混合プロキシポート7890とDNSポート1053を使用します。サブスクリプションのノードは含まず、末尾のルールはすべて直接接続にしています。DNSの経路をテストするための設定であり、完全なプロキシ設定ではありません。

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  nameserver:
    - https://dns.alidns.com/dns-query

rules:
  - MATCH,DIRECT

既存のサブスクリプションを使う場合は、ここにあるdnsセクションだけをマージし、例のrulesで既存の振り分けルールを上書きしないでください。同じ階層にdns:を2つ書かず、インデントにはスペースを使います。設定チェックに通ったら、クライアントでコアの設定を再読み込みしてください。

DoHと起動時の名前解決を理解する

上流DNSのアドレス形式からプロトコルを見分けます。https://dns.alidns.com/dns-queryはDoHで、HTTPS経由でDNSクエリを送信します。通常のIPアドレス形式の上流は、一般に従来型のDNSを使用します。DoHが暗号化するのはクライアントとDNSサービス間のクエリ通信です。その後のすべてのウェブサイト接続がプロキシ経由になるわけではありません。

まず上流サーバーのドメイン名を解決できるようにしてから、通常のドメインの名前解決を設定します。この例では、default-nameserverのIPアドレスを使ってDoHサーバーのドメイン名を起動時に解決します。「DoHに接続しないとDoHのアドレスが分からない」という循環を避けるためです。パブリックDNSサービスに接続できるかどうかはネットワーク環境によって異なるため、特定のアドレスがどの環境でも使えるとは限りません。

ケース2:fallbackとfallback-filterを設定する

サーバーを追加する前に、予備の応答が選択される仕組みを理解しましょう。fallbackは、一般的なネットワーク機器の「第2DNS」と同じものではありません。通常の上流DNSと予備の上流DNSが並行して名前解決に使われる場合があります。予備の応答を採用するかどうかは、フィルター条件や名前解決の状態などによって決まり、最初のアドレスがタイムアウトするまで単純に待つわけではありません。

以下の設定例は、前の設定のdnsセクション全体と置き換えてください。GeoIPを使って通常の上流DNSの応答を判定し、240.0.0.0/4に該当する場合は予備の応答を使う条件を示しています。

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  nameserver:
    - https://dns.alidns.com/dns-query
  fallback:
    - https://cloudflare-dns.com/dns-query
  fallback-filter:
    geoip: true
    geoip-code: CN
    ipcidr:
      - 240.0.0.0/4

フィルター条件を項目ごとに確認する

  • 地域判定を確認:geoip: trueでIPアドレスの地域判定を有効にします。geoip-code: CNは、通常の応答がこの地域条件に合わない場合、予備の応答を優先する設定です。「中国のドメインはすべて直接接続する」というプロキシルールではありません。
  • アドレス範囲を確認:ipcidrはIPアドレスの範囲を指定するリストです。通常の上流DNSが返したアドレスがフィルター対象の範囲に該当すると、予備の応答が選択されます。社内ネットワークの範囲をむやみに追加すると、内部サービスの名前解決に支障が出るおそれがあります。
  • データの依存関係を確認:GeoIPによる判定には、利用可能な地理情報データが必要です。データが見つからない、または古い場合は、まずコアのログに記録された読み込みエラーを解決してください。DNSサーバーを何度も変更して問題を覆い隠さないようにしましょう。
  • 2つの経路を確認:予備のDoHサーバーにも接続できる必要があります。メインの上流DNSから応答があっても、予備の上流DNSへの接続が正常とは限りません。

特定のドメインで使う上流DNSを固定する場合は、予備フィルターの対象範囲をむやみに広げるのではなく、ドメインごとにリゾルバーを指定するnameserver-policyの利用を検討してください。特に社内ドメインは企業のDNSに問い合わせる必要があります。パブリックDNSでは内部のレコードを解決できない場合があります。

DNS上流への接続経路と、ウェブサイトへの接続経路は別々に確認してください。DNS上流への接続にもルーティングルールを適用する場合は、respect-rulesを設定できます。また、プロキシサーバーのドメイン名を解決するために、現在のコアの要件に従ってproxy-server-nameserverを設定してください。プロキシ接続とDNS解決が互いの完了を待つ状態を避けられます。この記事の最小構成では、これらの応用設定は有効にしていません。

ケース3:TUNのdns-hijackで53番ポートを取り込む

まず設定項目を正しい階層に置きます。dns-hijackはトップレベルのtunセクションに記述し、dnsセクションには記述しません。TUNは仮想ネットワークインターフェースです。コアはTUNにルーティングされたIP通信を処理します。ここでいうDNS hijackは、条件に合うDNSクエリをコアのDNSモジュールにリダイレクトすることです。

既存の設定では、前述のdnsセクションを残したまま、以下のtunセクションをマージします。有効にする前に、クライアントに必要な管理者権限またはサービス権限があることを確認してください。また、別のVPNが同時にデフォルトルートを取り込まないようにします。

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

2つのハイジャックルールを区別しましょう。any:53はTUNに取り込まれたUDP 53番ポートのクエリに一致し、tcp://any:53はTCP 53番ポートのクエリを補います。これらは捕捉対象を表すもので、DNSの待ち受けアドレスをany:53に変更する指定ではありません。実際に捕捉できるかどうかは、システムのルーティング、インターフェース、プラットフォームの制約にも左右されます。

取り込み対象を確認する

  • ブラウザーのセキュアDNSを確認:ブラウザー独自のDoHは通常、HTTPSの443番ポートを使います。53番ポートをハイジャックしても、自動的にコアのDNSクエリに切り替わるわけではありません。
  • 暗号化DNSを確認:DoTはTLS経由でDNSを送信し、通常は853番ポートを使用します。これも上記2つのルールの対象外です。
  • LAN宛ての通信を確認:ルーター宛てのDNS通信がTUNに入るかどうかはルーティング設定によります。LAN内のリクエストがすべて捕捉されるとは限りません。
  • 待ち受けアドレスの公開範囲を確認:個人用PCでのテストでは、ループバックアドレスでの待ち受けを優先してください。TUNを機能させるために、DNSをすべてのネットワークインターフェースに無条件で公開しないでください。

名前解決・取り込み・ルールの順に検証する

まずコアの待ち受けをテストし、その後に通常のアクセスを確認します。これにより、「DNSモジュール自体が応答しない」のか、「システムのクエリが届いていない」のかを切り分けられます。以下のコマンドは確認方法を示すもので、特定のパブリックDNSが現在のネットワークで実測した速度を示すものではありません。

手順1:1053番ポートに直接問い合わせる

digをインストールしたLinuxまたはmacOS環境で、以下の2つのコマンドを実行し、UDPとTCPをそれぞれテストします。Windowsでは、後述のnslookupコマンドでポートを指定できます。

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

まずタイムアウトの有無を確認し、次に応答の種類を見ます。fake-ipを有効にしている場合、条件に合うAレコードのクエリに対して仮想アドレスプール内のアドレスが返るのは正常です。それだけで上流DNSが誤ったIPアドレスを返したとは判断できません。実際の名前解決結果と比較するには、一時的にredir-hostに切り替えて設定を再読み込みし、キャッシュを消去してから同じクエリを実行してください。

手順2:システムの通常の経路で問い合わせる

nslookup example.com

DNSサーバーを明示した問い合わせと、既定の問い合わせを比較します。1053番ポートへの問い合わせは成功するのに通常の問い合わせがタイムアウトする場合は、すぐにnameserverを変更せず、まずシステムDNS、TUNのルーティング、セキュリティソフトを確認してください。ハイジャックを有効にしても、コマンドに表示されるDNSサーバー名は元の宛先のままの場合があります。リクエストを実際に処理したものを、コアのログと照らし合わせて確認しましょう。

手順3:キャッシュを消去し、接続経路を確認する

Windowsではipconfig /flushdnsを実行します。systemd-resolvedを使うLinuxではresolvectl flush-cachesを実行してください。その後、ブラウザーを再起動するか既存の接続を閉じ、クライアントの接続パネルでドメイン名、適用されたルール、接続経路を確認します。ブラウザー独自のキャッシュや接続の再利用は、システムのキャッシュを消去しても解消されないことがあります。

詳しい手掛かりが必要な場合は、一時的にlog-levelをdebugに変更し、問題を1回再現した後でinfoに戻します。ログを共有する前に、サブスクリプションURL、認証情報、機密性の高いドメイン名を削除してください。ログから上流DNSのタイムアウト、待ち受けの失敗、ルーティングの問題を特定できますが、実行設定全体を公開するのは避けてください。

よくあるトラブル:症状から変更箇所を絞り込む

症状まず確認する項目次に行うこと
ローカルの1053番ポートへの問い合わせがタイムアウトするDNSが有効か、ポートが競合していないか、設定が再読み込みされているか起動ログを確認し、設定の構文チェックを実行する
1053番ポートは正常だが、通常の問い合わせに失敗するシステムDNSの経路とTUNのルーティング予備の上流DNSを変更する前に、リクエストがコアに届いているか確認する
ブラウザーとターミナルで結果が異なるブラウザーのセキュアDNS、それぞれのキャッシュ、プロキシ拡張機能一時的に名前解決の経路を統一し、同じドメインに問い合わせる
社内サイトにアクセスできないパブリックDNSに内部レコードがない、または仮想アドレスとの互換性に問題がある内部ドメインに企業のDNSを指定し、必要に応じてfake-ip-filterを追加する
fallbackを有効にすると名前解決が遅くなる予備の上流DNSへの接続と、フィルター条件に一致する範囲上流DNSを1つだけ使う基本設定に戻し、フィルター条件を1つずつ復元する
サブスクリプション更新後に設定が元に戻るクライアントが生成した設定で手動変更が上書きされている変更を対応済みの上書き設定に移し、最終的な設定を確認する

最後に、次の3点を確認しましょう。リクエストがコアに届いているか、上流DNSが正しい応答を返しているか、その後の接続に想定したルールが適用されているか。条件を一度に1つだけ変更し、変更前後の設定と問い合わせ結果を保存してください。そうすれば、nameserver、fallback、dns-hijackのトラブルを調べる際に、どの設定が問題を解決したのかを特定できます。

Clashをダウンロードクライアントのプラットフォームを選択