上級設定 読了時間:約12分

MihomoのDNS設定ガイド:nameserver・fallback・DNSハイジャックの書き方

MihomoのDNS設定を解説。nameserver、fallback、fallback-filter、dns-hijackの役割や、fake-ipとredir-hostの選び方をYAML例付きで紹介します。

DNS設定の3つの段階:入口・名前解決・接続

Clash Meta(mihomo)のDNSトラブルを調べるときは、まず3つの処理を切り分けます。アプリの問い合わせ先、コアが問い合わせる上流DNS、結果を受け取った後に接続が適用されるルールです。サイトが開けない原因は、いずれの段階にもあり得ます。nameserverを変更しただけでは、システムからDNS問い合わせがコアに届いていない問題は解決しません。

  • 入口:dns.listenでコアのDNS待ち受けポートを開きます。TUNではdns-hijackが条件に合うDNS通信を横取りします。
  • 名前解決:nameserver、fallback、nameserver-policyで問い合わせ先の上流DNSと応答の選択方法を決めます。
  • 接続:アプリがIPアドレスを受け取って接続を開始すると、コアがプロキシモード、ルール、プロキシグループに従って通信を処理します。

システムプロキシを設定しても、すべてのアプリのDNS通信が自動的に取り込まれるわけではありません。ブラウザー独自のセキュアDNS、AndroidのプライベートDNS、アプリ内蔵のDoHも別経路を使う場合があります。そのため、「システムプロキシが有効」と「すべての名前解決がMihomo経由」は同じ意味ではありません。

nameserverとdefault-nameserver:上流DNSと名前解決の起点

nameserverは通常のドメイン問い合わせに使う上流DNSのリストです。IPアドレスを直接指定すると通常のDNSを表し、https://はDoH、tls://はDoTを表します。通常のDNSはポート53、DoTは既定で853、DoHは一般にHTTPSのポート443を使います。

上流DNSにhttps://dns.alidns.com/dns-queryを指定した場合、コアはまずdns.alidns.comのIPアドレスを知る必要があります。default-nameserverはDNSサーバー自身のホスト名を解決するための設定で、「すべての問い合わせで最初に使う既定のDNSサーバー」ではありません。ここにIPアドレスを指定すると、解決前のホスト名に依存せず、名前解決を始められます。

項目役割よくある誤解
listenローカルのDNS待ち受けアドレスとポートを指定する設定すればシステムが自動的に使う
default-nameserver上流DNSのホスト名を解決するすべてのドメインで最優先されるDNSサーバー
nameserver通常のDNS問い合わせを処理する複数のアドレスは必ずリスト順に試される
proxy-server-nameserverプロキシノードのホスト名を専用に解決するプロキシ経由でアクセスするすべてのサイトを担当する
nameserver-policy該当するドメインに使う上流DNSを指定するサイトへの接続先ノードを直接決める

プロキシノード自体がホスト名で指定されている場合、その名前解決も必要です。proxy-server-nameserverで到達可能な上流DNSを別途指定すれば、「プロキシに接続しないとプロキシのアドレスを解決できない」という循環を避けやすくなります。これはサイトへの接続ルールによる振り分けとは別の設定で、相互に代用できません。

fallbackとfallback-filter:並行問い合わせ後の応答選択

fallbackは、従来の「メインDNSがタイムアウトしたら起動する予備DNS」とは限りません。fallbackを使った応答選択が行われる通常の名前解決では、コアが関連する上流DNSへ並行して問い合わせ、フィルター条件に基づいてfallback側の応答を採用するか判断します。そのため、fallbackを追加すると、1回のドメイン問い合わせが2系統のDNSサービスに届くことがあります。

よく使う3つのフィルター条件

  • geoip:IPアドレスの地域判定を有効にします。geoip-codeで地域コードを指定します。たとえばCNを指定すると、通常の応答がその地域の条件に合わない場合にfallback側の応答が選ばれます。この判定にはGeoIPデータが必要です。
  • ipcidr:通常の応答が指定したIPアドレス範囲に含まれる場合、fallback側の応答に切り替えます。対象はIPアドレスの範囲であり、ドメインの照合ルールではありません。
  • domain:一致したドメインにはfallback側の応答を直接使います。例の+.github.comは、ルートドメインとそのサブドメインを表します。

以下のDNS設定例ではgeoip: falseを明示し、初期設定時にGeoIPデータの更新問題が混ざらないよう、IP範囲とドメインの条件だけを示します。0.0.0.0/8と240.0.0.0/4は異常な応答を除外する例であり、汚染されたIPアドレスの完全な一覧ではありません。また、あらゆる誤った名前解決を検出できるものでもありません。

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-mode: blacklist
  fake-ip-filter:
    - localhost
    - "+.lan"
    - "+.local"

  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29

  proxy-server-nameserver:
    - https://dns.alidns.com/dns-query

  nameserver:
    - https://dns.alidns.com/dns-query

  fallback:
    - https://cloudflare-dns.com/dns-query

  fallback-filter:
    geoip: false
    ipcidr:
      - 0.0.0.0/8
      - 240.0.0.0/4
    domain:
      - "+.github.com"

この例では、指定した上流DNSに現在のネットワークとルーティング条件から到達できる必要があります。DoHは暗号化通信を使いますが、暗号化されているからといって自動的にプロキシ経由になるわけではありません。上流DNSへの接続経路は関連する設定によって決まります。接続できない上流DNSがある場合は、到達できると確認済みのサービスに変更し、未確認のアドレスを一度にいくつも追加しないでください。

fake-ipとredir-host:アプリに返すアドレスの違い

enhanced-mode: fake-ipは、対象となるDNS問い合わせにマッピング用アドレスを返します。アプリがそのアドレスに接続すると、コアがマッピングからドメインを特定し、ルールに従って処理します。例の198.18.0.1/16はベンチマーク用のアドレス範囲です。この範囲の応答があっても、すぐにDNS汚染と判断しないでください。

redir-hostは、名前解決で得られた実際のIPアドレスをアプリに返し、ドメインとIPアドレスの関連付けを使って接続を処理します。従来のDNSに近い動作ですが、共有IP、複数ドメインが同じアドレスを指す場合、アプリがキャッシュを使う場合などは、ドメインとの関連付けがfake-ipほど明確でないことがあります。

項目fake-ipredir-host
アプリに返されるアドレス通常はマッピング用アドレス(フィルター対象を除く)上流DNSが返す実際のアドレス
まず動作確認したいケースTUNでの通信取り込み、ドメインベースのルール振り分けアプリが実際のIPアドレスを必要とする互換性の問題
重点的に確認する点接続もマッピングを保持するコアに戻っているかDNS応答と接続を関連付けられているか

フィルターリストで変わるのは返すアドレスの形式だけ

例のfake-ip-filter-mode: blacklistは、リストに一致した項目にはfake-ipを返さない設定です。LANのドメインサフィックスをフィルターに追加すると、その名前にマッピング用アドレスを返さずに済みますが、名前解決が成功する保証はありません。.localは通常mDNSを使います。また、LAN機器の名前がルーターのDNSにしか登録されていない場合、パブリックDNSでは解決できません。

NASのホスト名を引き続き解決できない場合は、まずmDNSとルーターのDNSのどちらに依存しているかを確認し、そのうえでLAN向けの名前解決ルールが必要か判断してください。問題を回避するためにすべてのドメインをフィルターへ追加するのは避けましょう。モードを切り替えた後は、古いDNSキャッシュを消去して接続を作り直し、アプリが以前のアドレスを使い続けないようにしてください。

TUNのdns-hijack:ポート53のDNS問い合わせを取り込む

dns-hijackはトップレベルのtunセクションに記述し、dnsセクションには入れません。以下は、該当するTUN設定に対応したデスクトップクライアント向けの例です。TUNの作成には権限が必要です。クライアントによっては、サービスモードや権限補助プログラムを使って設定を管理します。

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53
  • any:53は、TUNに入り、条件に一致するUDPポート53のDNS問い合わせを取り込みます。
  • tcp://any:53を追加すると、TCPポート53も対象になり、TCPを使う通常のDNS問い合わせを処理できます。
  • auto-routeは関連するルートを自動設定しますが、特定のアプリの通信まで対象になるかは、システムのルーティングやクライアントの実装にも左右されます。
  • auto-detect-interfaceは外向きインターフェースを自動検出します。複数のネットワークアダプターがある環境や特殊なルーティングでは、実際の出口を別途確認してください。

ここでの「any」は、ネットワーク上のあらゆるDNS通信を傍受できるという意味ではありません。取り込み対象の経路に入った通信だけが処理されます。また、ブラウザーがHTTPSのポート443で送信するDoHを通常のDNSに自動変換することもありません。DoTのポート853も、上記2つの指定には含まれません。

この例ではDNSの待ち受け先を127.0.0.1:1053にしており、ローカルでのテストに適しています。一般的なシステムDNSの設定画面はアドレスのみを受け付け、ポートを指定できないことが多いため、127.0.0.1だけを入力すると1053ではなくポート53へ問い合わせます。TUN内部のDNSハイジャックと、システムDNSの手動設定は別の入口です。混同しないでください。

待ち受け・上流・取り込み・ルールの順に確認

ステップ1:最終設定と待ち受けポートを確認

設定を再読み込みしたら、まずクライアントのログでYAMLの解析エラー、未対応の項目、ポートのバインド失敗がないか確認します。最終設定のdns.enable、listen、enhanced-modeを重点的に確認してください。クライアントによってメニュー名は異なるため、サブスクリプションの元データだけでなく、実際の実行設定や設定プレビューを確認します。

macOSやLinux、またはdigをインストールした環境では、1053番ポートへ直接問い合わせられます。1つ目はUDP、2つ目はTCPのテストです。これは確認用のコマンドであり、実測結果を示すものではありません。

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

fake-ipモードでは、フィルター対象でないAレコード問い合わせに対し、通常はマッピング範囲のアドレスが返されます。これは現在のDNS入口から応答があったことを示すだけで、接続先のウェブサイトにアクセスできる証明にはなりません。対象の接続が同じコアに届いているか、ノードへの接続が確立できるかも確認してください。

ステップ2:上流DNSに届かない場合と入口で取り込めていない場合を切り分ける

  1. 1053番ポートへ直接問い合わせてもタイムアウトする:まず待ち受けが成功しているか確認し、次に上流DNSへの接続エラーを調べます。必要であれば、到達できると確認済みのnameserverを一時的に1つだけ残し、原因を絞り込みます。
  2. 1053番ポートへの問い合わせには応答するが、アプリが別のDNSを使っている:TUNが有効か、ルートが適用されているか、ブラウザーのセキュアDNSが別経路を使っていないかを確認します。
  3. 名前解決できるのにウェブサイトが開かない:接続ログでルールの一致、プロキシグループの選択、ノードのエラーを確認してください。原因を確かめずにDNSを次々と変更しないでください。
  4. LAN内のホスト名だけ解決できない:ルーターのDNSまたはmDNSの名前解決経路を確認し、LAN向けの専用ルールが必要か調べます。

ステップ3:キャッシュを消去して再テスト

Windowsではターミナルでipconfig /flushdnsを実行します。macOSでは以下の2つのコマンドを順に実行してください。2つ目のコマンドには管理者権限が必要です。ブラウザーやアプリにも独自のキャッシュがある場合があります。システムのキャッシュを更新したら、既存の接続を閉じてからアクセスし直してください。

sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

想定外のサーバーへDNS問い合わせが送られていないか調べるには、システム、ブラウザー、コアの実際の動作をあわせて確認する必要があります。DoHのアドレスを見ただけ、あるいはDNS確認サイトに一度アクセスしただけでは、すべてのプロセスの名前解決経路は判断できません。fallbackによる並行問い合わせ、ブラウザー独自のDoH、システムのバックグラウンド通信は、それぞれ分けて確認してください。

設定の統合と追加調整

同じYAMLファイルにトップレベルのdns:やtun:を重複して記述しないでください。重複したキーはパーサーでエラーになる場合や、片方の設定がもう片方を上書きする場合があります。例の項目は既存のセクションに統合し、クライアントのオーバーライド適用順を確認してください。サブスクリプションを更新した後も、実行設定に変更が残っているか再確認します。

  • まず動作する基本設定を作る:単一の上流DNSに到達できることと、ローカルの1053番ポートに問い合わせられることを確認してから、fallbackとTUNでの取り込みを追加します。
  • 次に特定のドメインを調整する:ドメインごとに名前解決先を指定する場合はnameserver-policyを使います。接続先を振り分ける場合はrulesを変更し、それぞれ個別に動作を確認してください。
  • 最後にIPv6を調整する:例のdns.ipv6: falseは、DNSのAAAA応答を無効にする設定です。OS全体のIPv6を無効にするものではなく、アプリが既に取得したIPv6アドレスを使うことも妨げません。
  • 元に戻す手順を用意する:インターネットに接続できなくなった場合は、設定を重ね続けるのではなく、まずTUNを無効にし、元のシステムDNSとプロキシ設定に戻してからバックアップを読み込みます。

ルールとTUNの設定関係をさらに確認するには、DNS設定ガイドとTUN設定ガイドをご覧ください。トラブルシューティングでは、一度に変更するレイヤーを1つに絞ることが重要です。まず問い合わせがコアに届くか、次に上流DNSが応答するか、最後に接続ルールを確認します。これにより、変更がどの問題を解決したのか判断しやすくなります。

Clashをダウンロード