DNS設定を構成する4つの要素
ClashのDNSを調べるときは、クエリの取り込み、名前解決モード、上流DNSの選択、接続の振り分けを分けて考えます。アプリのDNSクエリがどのサーバーに送られるかは、OSやブラウザー、通信の取り込み方法によって異なります。Clashがクエリを受け取った後に、dnsの設定に従って処理します。最終的な接続先はプロキシモードとrulesで決まり、DNSサーバーの指定だけで特定のノードを経由するわけではありません。
| 要素 | 主な設定項目 | 確認すること |
|---|---|---|
| クエリの取り込み | listen、tun.dns-hijack | アプリのクエリがコアに届いているか |
| 名前解決モード | enhanced-mode | 実IPアドレスとマッピングアドレスのどちらを返すか |
| 上流DNSの選択 | nameserver、fallback-filter | どのグループの応答を採用するか |
| 接続の振り分け | rules、proxy-groups | 実際の接続がどの出口を使うか |
サブスクリプションの原文、クライアントの編集画面、実際に適用される設定は、それぞれ別のファイルである場合があります。更新時にサブスクリプションの内容が上書きされる場合は、クライアントの上書き機能やマージ設定を使って変更を保持してください。マージ後は最終的な設定を確認し、同じYAMLマッピング内にdns:やtun:を重複して記述しないようにします。
nameserver・fallback・名前解決の仕組み
nameserver:通常の上流DNS。プロキシノードではない
nameserverはDNSの上流サーバー一覧です。通常のDNSアドレスのほか、コアが対応していればDoHやDoTのアドレスも指定できます。223.5.5.5のようなアドレスは通常UDPの53番ポートを使い、https://1.1.1.1/dns-queryはDoHを表し、通常HTTPSの443番ポートで接続します。上流サーバーには現在のネットワークから到達できる必要があり、プロトコル名だけで通信の成功が保証されるわけではありません。
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: redir-host
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- 223.5.5.5
- 119.29.29.29
fallback:
- https://1.1.1.1/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
これは設定項目の関係を説明するための例であり、ノード設定を含む完全な構成ではありません。127.0.0.1:1053はローカルでのみ待ち受けるため、明示的なクエリテストに使えます。このポートで待ち受けても、OSがすべてのDNSクエリを自動的に転送するわけではありません。ipv6: falseはこのDNSモジュールのAAAA応答を制御する項目で、OSのIPv6を無効にしたり、すべてのIPv6接続を遮断したりする設定ではありません。
default-nameserver:上流DNSのホスト名を名前解決
上流サーバーをhttps://dns.example.com/dns-queryのようにホスト名で指定した場合、接続前にIPアドレスを取得する必要があります。このような名前解決にはdefault-nameserverを使います。名前解決のループを避けるため、例ではIPアドレスを直接指定しています。これは、すべての通信先ドメインを最初に問い合わせるためのデフォルトサーバーでも、プロキシノード専用の名前解決サーバーでもありません。
mihomoには、プロキシノードのホスト名を解決するproxy-server-nameserverもあります。ノードのアドレスがホスト名で、名前解決の経路が循環する場合は、この設定も個別に確認してください。「Webサイトのドメインを解決できない」問題と「ノードのホスト名を解決できない」問題を混同しないようにしましょう。
fallback:予備の応答。順番に試す仕組みではない
fallbackを設定すると、一般的な処理ではメインと予備のグループに並行して問い合わせ、フィルター条件に基づいて採用する応答を決めます。「nameserverがタイムアウトするまで待ってから、fallbackを順番に試す」という動作ではありません。複数アドレスからの応答の競合、キャッシュ、失敗時の処理はコアの実装によって異なります。リストの順番を厳密な優先順位と見なすこともできません。
DoHが示すのは、DNSサービスとの通信にHTTPSを使うことだけです。プロキシ経由の通信が自動的に有効になるわけではなく、ブラウザー独自のセキュアDNSを防ぐこともできません。DNSクエリがルールに従うかどうかは、コアの設定項目、最終設定、ログをあわせて確認してください。
fallback-filter:予備の応答に切り替える条件
fallback-filterはIPアドレスの地域情報を書き換える設定ではなく、予備の応答を選ぶための条件です。上の設定では、geoip: trueとgeoip-code: CNを組み合わせ、メインのグループが返したアドレスが指定地域の条件に合わない場合に、予備グループの応答を採用しやすくします。GeoIPデータを参照するため、データの古さ、CDNの振り分け変更、アドレスの地域判定の誤りによって選択結果が変わることがあります。
geoip: false:この地域判定を無効にします。ほかのフィルター条件まで無効になるわけではありません。ipcidr:メイングループの応答が指定したアドレス範囲に含まれる場合、予備の応答を使います。240.0.0.0/4は、予約済みアドレス範囲を除外する一般的な例です。domain:指定したドメインに一致した場合、メイングループのアドレスが地域条件を満たすかどうかにかかわらず、予備グループの応答を使います。
fallback-filter:
geoip: false
ipcidr:
- 240.0.0.0/4
domain:
- '+.example.com'
この設定例は既存のdnsの下に置き、前の例のfallback-filterと置き換えてください。example.comは文書用に予約されたドメインであり、実際の運用で使うドメイン一覧ではありません。ここでは地域判定を無効にし、アドレス範囲とドメインの条件だけを残して問題を切り分けます。検証せずにすべてのプライベートネットワークを除外しないでください。社内ドメイン、ルーターの管理画面、家庭内NASは、プライベートアドレスに解決される必要がある場合があります。
もう一つよくある誤解は、fallback-filter.domainをプロキシルールだと思うことです。この設定が制御するのはDNS応答の選択元だけで、DOMAIN-SUFFIXルールを作成するわけではありません。Webサイトの名前解決に予備の応答が使われても、接続がDIRECTルールに振り分けられることがあります。
fake-ipとredir-hostの違い
fake-ip:ドメインとマッピングアドレスを対応付ける
enhanced-mode: fake-ipを使うと、対象となるクエリにマッピングアドレスを返します。アプリがそのアドレスに接続すると、コアは元のドメインを特定してからルール判定と接続処理を行います。そのため、コマンドラインに198.18.x.xが表示されても、DNS汚染とは限りません。ローカル設定によるマッピング結果の可能性があります。
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:
- '*.lan'
- '*.local'
default-nameserver:
- 223.5.5.5
nameserver:
- https://1.1.1.1/dns-query
198.18.0.1/16はベンチマーク専用のアドレス空間です。使用前にローカルのルーティングを確認し、実験用ネットワークと競合しないようにしてください。マッピングアドレスが返された後、関連する接続が再びコアに届く必要があります。DNSクエリがClashを経由しても、データ接続が取り込み対象から外れていると、アプリがこれらのアドレスに接続できない場合があります。
fake-ip-filterは、指定したドメインに実際の名前解決結果を返すための設定です。上の例では一般的なブラックリスト方式を使い、別のフィルターモードは併用していません。社内サービスは実際のドメインに合わせてリストに追加できます。ただし、.localは通常mDNSで処理されます。フィルターに追加しても、Clashがすべてのマルチキャスト検出リクエストをプロキシするわけではありません。
redir-host:実際のIPアドレスを返す
redir-hostは実際の名前解決結果を返し、DNSの記録を使ってドメインと接続を対応付けます。実IPが必要な互換性の問題には適していますが、複数のドメインが同じIPを共有する場合、アプリが独自に名前解決する場合、キャッシュが長時間残る場合は、ドメインとの対応付けが不完全になることがあります。どちらのモードもスニッフィングとは異なります。mihomoのsnifferは、後続の接続情報からドメインを特定する別の仕組みです。
TUNのdns-hijack:DNSクエリをコアに取り込む
dns-hijackはtunの設定であり、dnsの子項目ではありません。mihomoでは、次のように記述するのが一般的です。前のセクションのDNS設定と統合する場合、2つのトップレベル項目を同じ階層に置いてください。
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番ポートを追加します。取り込まれたクエリはコアのDNSモジュールで処理されるため、システムのDNSサーバーに127.0.0.1:1053を明示する必要はありません。ただし、パケットが実際にTUN経由で送信され、使用中のプラットフォームが該当するルーティングと取り込み機能に対応している必要があります。
- TUNを有効にするには、通常、管理者権限またはシステムの許可が必要です。仮想ネットワークアダプターを作成できたら、ルートが有効になっているかも確認してください。
- ブラウザーのDoHはHTTPSを使用し、AndroidのプライベートDNSはDoTを使用することがよくあります。どちらも通常の53番ポートを使うクエリではないため、上記の2行だけでは書き換えられません。
- システムのHTTPプロキシを有効にしても、アプリのDNSクエリがコアに届くとは限りません。アプリによっては、システムのDNSで名前解決してからプロキシ接続を開始します。
- 複数のVPN、仮想ネットワークアダプター、ローカルDNSサービスを同時に使う場合は、まず取り込み経路を一つに絞って検証し、ルートの競合を避けてください。
取り込みのためだけにdns.listenを0.0.0.0:53へ変更しないでください。待ち受け範囲が変わり、システムの名前解決サービスとポートが競合するおそれがあります。LAN内の端末にDNSを提供する必要がある場合に限って外部向けに待ち受け、ファイアウォールで接続元とアクセス可能なネットワークを制限してください。
よくある構成と選び方
| 利用条件 | おすすめの開始構成 | 重点的に確認すること |
|---|---|---|
| まず上流DNSを調べたい | redir-host + ローカルの1053番ポートで待ち受け | 明示的なクエリで実IPアドレスを取得できるか |
| ドメイン単位で安定して振り分けたい | fake-ip + TUNで取り込み | マッピングアドレス宛ての接続がコアに届くか |
| 社内ネットワークや家庭内サービスが多い | ドメインごとにDNSを指定し、フィルターの例外を設定 | 内部ドメインのクエリがパブリックDNSに送られていないか |
| 2つのグループの名前解決結果を比較したい | nameserver + fallback + 明確なフィルター条件 | 選択された応答が想定した条件を満たすか |
mihomoではnameserver-policyを使って、特定のドメインに上流DNSを指定できます。たとえば、社内DNSが192.168.50.1にあり、社内ドメインに文書用のサフィックスcorp.exampleを使う場合は、既存のdnsの下に次の設定を追加できます。
nameserver-policy:
'+.corp.example':
- 192.168.50.1
実際に使う際は、実在する社内ドメインのサフィックスと到達可能なDNSアドレスに置き換え、該当ドメインをfake-ip-filterにも追加する必要があるか確認してください。ドメインごとのDNS指定、予備応答のフィルター、接続ルールは別々の設定レイヤーです。問題を調べるときは、重複する設定をいったん外し、基本の名前解決を確認してから一つずつ戻してください。
DNS接続にも振り分けルールを適用したい場合、mihomoのrespect-rulesはproxy-server-nameserverなどとあわせて設計し、「ノードに接続するための名前解決に、先にそのノードへの接続が必要」という循環を避けてください。基本設定を検証する前に、このスイッチと複数のドメイン別DNS設定をまとめて追加することはおすすめしません。
検証の手順とトラブルの切り分け
手順1:設定と待ち受けを確認
使用中のmihomo実行ファイルで設定の構文を確認し、その後クライアントから再読み込みします。以下では、現在のディレクトリに実際の設定ファイルconfig.yamlがあり、digがインストール済みであることを前提とします。
mihomo -t -f config.yaml
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
構文チェックに成功しても、すべての上流DNSに到達できるとは限りません。UDPクエリは成功するのにTCPクエリが失敗する場合は、待ち受け設定とローカルのファイアウォールを確認してください。どちらもタイムアウトする場合は、dns.enable、ポートの競合、実際に適用されている設定を確認します。fake-ipモードでマッピングアドレスが返ることから分かるのは、ローカルのマッピング経路が機能していることだけです。それだけで実際の上流DNSが正常だとは判断できません。
手順2:システムの経路を確認
127.0.0.1とポートを明示して問い合わせると、コアの待ち受けをテストできます。続けてnslookup example.comを実行し、システムのデフォルト経路で名前解決をテストします。結果が異なっても、必ずしも問題とは限りません。すべてのクエリがコアを経由する想定なら、システムDNS、TUNのルート、ブラウザーのセキュアDNS設定を確認してください。
手順3:接続と通信の出口を確認
- キャッシュを消去し、以前のタブやアプリの接続を終了してから、もう一度アクセスします。
- クライアントの接続一覧で、対象ドメイン、適用されたルール、最終的なプロキシグループを確認します。
- 名前解決は成功しても接続がタイムアウトする場合は、ノードへの到達性、プロキシプロトコル、接続先ポートを確認してください。すぐにDNSを変更する必要はありません。
- 内部サービスだけ接続できない場合は、社内DNSとパブリックDNSにそれぞれ問い合わせ、ドメイン別の上流DNS設定が不足していないか確認します。
- DNSの迂回が疑われる場合は、パケットキャプチャで物理ネットワークアダプターから送信されるUDP/TCP 53番・853番ポートの通信と、既知のDoH接続を確認してください。公開テストページに表示されるDNSリゾルバーの所在地だけでは、ローカルのクエリ経路を証明できません。
一度に変更するのは一つの要素だけにしてください。まずコアで名前解決できることを確認し、次にアプリのクエリがコアに届くこと、最後に接続ルールを確認します。こうすれば、上流DNSへの到達不可、フィルター条件の誤り、fake-ip接続の迂回、TUNによる取り込み不足を区別できます。各設定項目の全体像は設定リファレンスを、初回インストールと設定のインポート手順は使い方ガイドを参照してください。