まずDNSリクエストの経路を確認
mihomoのDNSを設定する前に、3つの流れを整理しましょう。アプリがどこへ問い合わせるのか、mihomoがどの上流DNSで名前解決するのか、最終的な接続がどのルールで転送されるのかです。nameserverを暗号化DNSに変更しても変わるのは中間の処理だけです。ブラウザーが独自のセキュアDNSを使っていれば、問い合わせがmihomoのDNSモジュールを通らない場合があります。
この記事では、Clash Metaの後継として開発されているmihomoコアを対象に解説します。クライアントによってはDNSやTUNの設定が画面上で上書きされるため、サブスクリプションの元ファイルだけでなく、実際に読み込まれている実行時設定を確認してください。旧Clashコアでは、ここで扱うすべての項目に対応しているとは限りません。
- 現在の設定をバックアップし、システムプロキシ、TUN、DNS上書きの各スイッチの状態を記録します。
- クライアントのコア情報を確認し、アプリ名だけで判断せず、mihomoが実際に起動していることを確かめます。
- まずはローカルの
127.0.0.1:1053で名前解決をテストし、その後にTUNでの接続制御を有効にするか判断します。 - 一度に変更するのは1つの項目グループだけにします。再読み込みのたびにログを確認し、同じドメインでテストしてください。
nameserverとdefault-nameserver:最小構成から始める
以下は既存の設定に追加するDNSの例であり、プロキシ設定全体ではありません。ノードやルールは含まれておらず、既存のproxies、proxy-groups、rulesを削除する必要もありません。トップレベルのdns:は1つだけにし、項目をそこへ統合してください。キーが重複すると、読み込み結果が不明確になることがあります。
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:
- "localhost"
- "*.lan"
- "*.local"
- "+.home.arpa"
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
| 項目 | 設定での役割 |
|---|---|
enable | mihomo内蔵のDNSモジュールを有効にします。 |
listen | ローカルループバックアドレスの1053番ポートでDNSクエリを受け付けます。LANには公開しません。 |
default-nameserver | 上流DNSサービスのドメイン名を名前解決します。DoHサーバーのアドレスが最初から分からない状態を防ぐための設定です。 |
nameserver | 通常の名前解決に使う上流DNSを設定します。この例ではHTTPS対応のDNSアドレスを2つ指定しています。 |
ipv6: false | DNSモジュールでAAAAクエリに空の応答を返し、IPv4経路を先に切り分けやすくします。OSのIPv6を無効にする設定ではありません。 |
上流DNSのリストを固定の優先順位と考えない
nameserverに2つ指定しても、「1つ目が失敗した場合だけ2つ目を使う」という意味ではありません。コアは並行して問い合わせ、応答を採用することがあります。リストの順番で厳密な主系・予備系を実現できるとは限りません。まずは現在のネットワークから到達できる上流DNSを選び、その後に遅延を比較しましょう。アドレスを十数個追加しても、切り分けが複雑になるだけです。
default-nameserverも、「すべてのサイトの名前解決に使う標準DNS」ではありません。主な役割は、DNSサービスのドメイン名自体をどう名前解決するかを指定することです。この例ではブートストラップ用にIPアドレスを使っていますが、後続の通信でDoHを使っても、初期の問い合わせが自動的に暗号化されるわけではありません。
fallbackとfallback-filter:タイムアウト時の予備ではなく、応答結果を選別
fallbackは別系統の上流DNSであり、プロキシのポリシーグループではありません。ノード選択用のグループが作られるわけでもありません。nameserverとfallbackを併用すると、コアは並行して名前解決を行い、fallback-filterの条件に基づいてfallbackの結果を採用することがあります。「メインDNSがタイムアウトしたときだけ起動する予備DNS」と考えると、DNS通信の挙動を誤解しやすくなります。
IPアドレスの地理的な位置で応答を選別する場合は、以下の項目を先ほどのdns:に追加します。まず、指定する上流DNSに現在のネットワークから接続できることを確認してください。到達できないDoHアドレスを設定しても、DNS汚染や接続の問題が自動で解決するわけではありません。
fallback:
- https://1.1.1.1/dns-query
- https://8.8.8.8/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
3つの条件から選別の仕組みを把握する
- 地理条件:
geoip: trueを有効にし、geoip-code: CNを指定すると、通常の名前解決結果が指定した地域に属さない場合、fallbackの結果が選ばれやすくなります。判定対象はドメインの末尾ではなく、解決されたIPアドレスです。 - アドレス範囲の条件:
ipcidrで通常の名前解決結果から除外するアドレス範囲を指定します。この例の240.0.0.0/4は明示的な選別条件であり、Webサイトへの通信に適用するプロキシルールではありません。 - データへの依存:GeoIP判定はコアが使用する地理情報データに依存します。データがない、古い、あるいはCDNのIPアドレスの割り当て先が変わると、選択結果に影響する場合があります。
この仕組みで「中国国内のドメインには中国国内のDNS、日本国外のドメインには海外DNS」という振り分けが保証されるわけではありません。ドメインのサーバーは複数の地域に設置でき、CDNの応答アドレスも変わります。社内ドメインや特定のサービスを確実に振り分ける場合は、地理判定に頼らずnameserver-policyを使う方法が分かりやすいでしょう。
nameserver-policy:ドメインごとに上流DNSを指定
オフィスのネットワーク、家庭内NAS、プリンターでは、内部DNSでしか解決できない名前を使うことがあります。こうしたドメインをパブリックDNSに問い合わせるのは適切ではありません。以下は家庭内ネットワークの例です。ルーターのアドレスが実際に192.168.1.1であり、home.arpaの内部レコードを解決できる場合に限って、この設定を使ってください。
nameserver-policy:
"+.home.arpa":
- 192.168.1.1
ここに示すのは、既存のdns:に統合する項目だけです。該当するドメインはこのポリシーで上流DNSを選ぶため、通常のnameserver/fallbackの選別手順がそのまま適用されるとは限りません。+.home.arpaは該当ドメインとそのサブドメインを照合します。会社の内部ドメインに置き換える前に、DNSサーバーとアクセス要件をネットワーク管理者に確認してください。
nameserver-policyとfake-ip-filterは別の問題を解決する設定です。前者はどのDNSに問い合わせるかを決め、後者はアプリに偽のIPアドレスを返すかどうかを決めます。内部ドメインのDNSポリシーを設定した後、デバイス検出や直接接続に実際のIPアドレスが必要なら、該当するドメインもfake-ipの除外リストに追加してください。
fake-ipとredir-host:偽のIPアドレスと実際のIPアドレス
enhanced-modeでDNSの拡張モードを指定します。fake-ipでは、アプリに予約済みアドレス範囲内のマッピング用IPアドレスを返します。そのアドレスへの接続が再びmihomoに届くと、コアが対応するドメインを復元し、ルールと出力先を適用します。このアドレスはWebサイトの実サーバーではないため、mihomoを経由しないデバイスから直接アクセスすることはできません。
| 比較項目 | fake-ip | redir-host |
|---|---|---|
| アプリに返されるAレコード | 通常は設定したアドレスプール内のマッピング用IPアドレス | 実際の名前解決で得られたIPアドレス |
| ドメインとの対応付け | 偽のIPアドレスとの対応関係を利用してドメイン情報を保持 | DNSキャッシュとの対応付けなどの仕組みでドメインを復元 |
| 接続時の要件 | 偽のIPアドレスへの接続は、必ず対応するmihomoのインスタンスに戻す必要があります | 実際のIPアドレスを取得できますが、接続は想定したプロキシまたはルーティング経路を通す必要があります |
| よくある互換性の問題 | LAN内のデバイス検出、実IPアドレスを確認するアプリ、接続制御を迂回する通信 | 共有IP、キャッシュとの対応付け、アプリ独自のDNSによるドメイン識別の制限 |
fake-ip-filterに追加するケース
LAN内のドメインや、実アドレスを必要とするデバイス検出サービスは、まず除外リストに追加できます。デフォルトのブラックリスト方式では、リストに該当するドメインにはfake-ipではなく、実際の名前解決結果を返します。すべてのドメインを追加するのは避けてください。設定上はfake-ipのままでも、実際の動作が大きく変わってしまいます。
特定のアプリだけに問題がある場合は、すぐに全体のモードを切り替えず、そのアプリが使うドメインだけを除外してください。redir-hostに切り替えた後は、クライアントのDNSキャッシュを消去して関連アプリを再起動します。必要に応じてシステムのDNSキャッシュも更新してください。古い198.18.x.xの記録は、YAMLを変更してもすべてのアプリからすぐに消えるわけではありません。
TUNでのDNS hijack:従来の53番ポートの問い合わせを取り込む
ここでいうDNS hijackは、TUNを通る指定DNS通信をmihomoのDNSモジュールに渡すことです。接続先WebサイトのDNSレコードを書き換える機能ではありません。システムプロキシを使わないアプリの通信をデスクトップで取り込むには、まずTUNのルーティングを正しく有効にし、そのうえでDNS hijackを設定します。
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
any:53はTUNを通過するUDP 53番ポートの問い合わせに適用し、tcp://any:53はTCP 53番ポートを補います。auto-routeはルートの自動設定に、auto-detect-interfaceは出力インターフェースの検出に使います。実際に取り込まれる範囲はOS、ルーティング、クライアントの実装にも左右されるため、このYAMLだけでDNS通信がすべて制御されているとは判断できません。
- 必要な権限:デスクトップクライアントで仮想ネットワークアダプターやルートを作成するには、通常、サービスモードまたは適切な管理者権限が必要です。DNS項目を変更する前に、権限に関するエラーがないか確認してください。
- ポートを区別する:
listen: 127.0.0.1:1053は明示的に問い合わせるための入口です。TUNによる53番ポートのDNS hijackはコアが処理するため、システムDNSのアドレスに1053を付けて設定する必要はありません。 - 暗号化DNSを確認する:DoHは通常443番ポート、DoTは通常853番ポートを使用します。53番ポートだけを対象にしても、これらの通信は強制的に取り込めません。切り分けの際は、ブラウザーの「セキュアDNS」を一時的に無効にして比較テストしてください。
- DNSを不用意に公開しない:LAN内のデバイスにDNSを提供する必要がある場合に限り、LANアドレスでの待ち受けを検討し、あわせてファイアウォールを設定してください。テストを簡単にするためにインターネットへ公開してはいけません。
Androidクライアントは通常、システムのVPNインターフェースを使って通信を取り込みます。デスクトップ向けの自動ルーティング項目がそのまま使えるとは限りません。iOSクライアントも、各アプリのネットワーク拡張機能の実装に左右されます。デスクトップのTUN設定をすべてのプラットフォームにコピーせず、クライアントが用意するVPN、DNS、バイパスの設定を優先してください。
動作確認とトラブル対処:名前解決・通信の取り込み・接続を分けて確認
ステップ1:ローカルDNSへ直接問い合わせる
設定を有効にした後、digがインストールされている環境で以下の2つのコマンドを実行します。1つ目はUDP、2つ目はTCPで問い合わせ、ローカルDNSの受付先が応答するか確認します。DNSサーバーを明示しているため、これだけではシステムDNSがTUNに取り込まれていることは確認できません。
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
Windowsでは、標準搭載のnslookupでテスト先のポートを指定できます。
nslookup -port=1053 example.com 127.0.0.1
fake-ipモードでは、フィルター対象外の通常のAクエリに対して、通常は198.18.0.1/16のアドレスプールからIPアドレスが返ります。これは問い合わせが偽アドレスのマッピングに該当したことを示すだけで、上流での実際の名前解決やプロキシ経由の接続が正常とは限りません。除外リストに該当するドメインは、実際の名前解決経路を確認してください。
ステップ2:接続が同じコアに戻っているか確認
- クライアントの接続パネルを開き、HTTPSサイトにアクセスして、該当するドメインが表示されるか確認します。
- 想定したルールが適用されていることを確認し、最終的な出力先がDIRECTか、プロキシポリシー内のノードかを確認します。
- fake-ipが返っているのに接続記録がない場合は、まずTUN、ルーティング、アプリのバイパス設定を確認してください。
- 接続がコアに届いているのにタイムアウトする場合は、ノード、ルール、上流への接続を確認してください。DNSモードを何度も切り替えるのは避けましょう。
ステップ3:症状から原因を絞り込む
| 症状 | まず確認する項目 | 次に行うこと |
|---|---|---|
| ローカルの1053番ポートへの問い合わせがタイムアウトする | DNSが有効か、設定が読み込まれているか、ポートが使用中でないか | 起動ログで待ち受けアドレスを確認し、もう一度問い合わせる |
| DoHのログにTLSエラーが表示される | システム時刻、証明書、上流DNSへの到達性、ブートストラップ名前解決 | 時刻を合わせ、上流DNSを1つずつテストする。問題を隠すために証明書検証を無効にしない |
| Webサイトは使えるがNASのドメインを解決できない | 内部DNSのポリシーとfake-ipの除外設定 | 内部ドメインにルーターのDNSを指定し、実際のIPアドレスが必要か確認する |
| 設定変更後も結果が変わらない | クライアントによる上書き、サブスクリプションの更新、アプリやシステムのキャッシュ | 実行時設定を確認し、再読み込みしてキャッシュを更新する |
| ブラウザーだけ挙動が異なる | ブラウザーのセキュアDNS、プロキシ拡張機能、独立したキャッシュ | 関連機能を一時的に無効にし、同じドメインで比較テストする |
Windowsではipconfig /flushdnsを実行してシステムの名前解決キャッシュを更新できます。ただし、ブラウザーやアプリに独自のキャッシュが残っている場合があります。診断ログを共有するときは、時刻、エラーの種類、関連する項目だけを残し、サブスクリプションURL、認証情報、機密性の高い内部ドメインは削除してください。
動作を確認できたDNS設定は、サブスクリプションの更新で消えないよう、クライアントが対応する上書きまたは設定のマージ機能に保存します。「最小構成」と「現在の設定」の2つを記録しておきましょう。問題が起きたら、まず設定を戻してからfallback、ドメイン別ポリシー、TUNの通信取り込みを1つずつ元に戻すと、すべてのスイッチを一度に変更するより原因を特定しやすくなります。設定ファイルとプロキシルールの全体像は設定ガイドをご覧ください。