前提知識と設定ファイルの構造
先に進む前に、2点を確認してください。クライアントが正常にネット接続できていること(チュートリアルページのメインの流れを終えていること)、そして現在使っている設定がどのサブスクリプションから来ているかを把握していることです。上級設定の変更はすべて「動作するベースライン」の上に成り立っており、ベースラインが不安定だと以降の調整を検証できません。
mihomo の設定ファイルは1つの YAML で、トップレベルのキーは役割ごとに5つのブロックに分けられます。本ガイドの章構成もこれに対応しています:
- インバウンド:
port、socks-port、mixed-port、tun——トラフィックがどこから入ってくるか; - アウトバウンド:
proxies、proxy-providers、proxy-groups——トラフィックがどこから出ていくか; - ルーティング:
rules、rule-providers——どの種類のトラフィックがどの出口を通るか; - 名前解決:
dns、sniffer——ドメイン名がどのようにアドレスへ変換され、アドレスがどのようにドメイン名へ復元されるか; - コントロール:
external-controller、external-ui、secret——実行状態をどのように外部へ公開するか。
最小構成の骨格
オプションをすべて取り除くと、起動できる設定は次のようになります。以降の各章のサンプルは、この骨格の対応する位置に追加されるものとして読んでください:
mixed-port: 7890
mode: rule
log-level: info
proxies: [] # 通常はサブスクから提供される
proxy-groups:
- name: ノード選択
type: select
proxies:
- DIRECT
rules:
- GEOIP,CN,DIRECT
- MATCH,ノード選択
YAML はインデントに非常に敏感です。スペース2つで統一し、タブは禁止。値にコロンやシャープ、特殊文字が含まれる場合は引用符で囲みます。起動時のクラッシュで最初に疑うべきは常にインデントです。切り分け方はブログ『Clash 起動クラッシュの対処法』を参照してください。
プラットフォームの違い:iOS とデスクトップ
iOS の Clash Plus は Network Extension 上で動作し、設定管理は「サブスクを基盤 + オーバーライドで差分適用」という方式です——通常サブスクの原文を直接編集せず、クライアント側で自分の変更を重ねます(詳細は第6章)。デスクトップの Clash Verge Rev や FlClash は設定全文を直接編集できます。どのクライアントを使うにせよ、本ガイドが扱うのはカーネル層の仕様なので、書き方はどれでも共通です。
最後に、身につけておきたい習慣があります。設定を変更したら毎回「設定を再読込 → ログを確認 → 動作を検証」の3ステップを踏むことです。ログの各レベルの読み方や頻出エラーの意味は、ブログ『Clash 実行ログの読み方』で1つずつ解説しており、本ガイドの以降の章でもこの検証方法を繰り返し使います。
ポリシーグループの種類と実践的な組み方
ポリシーグループ(proxy-groups)はルールとノードの間にある中間層です。ルールにマッチした後の宛先は、単一ノード、組み込みの出口(DIRECT / REJECT)、あるいはポリシーグループのいずれかになります。そしてポリシーグループのメンバーもまた、ノードか別のポリシーグループになり得ます。「グループはグループを入れ子にできる」という点を理解することが、複雑な振り分けを組む上での前提です。
mihomo は5種類のグループタイプを提供し、それぞれ選択ロジックが異なります:
| タイプ | 選択ロジック | 典型的な用途 |
|---|---|---|
select | 手動選択、ユーザーが切り替えるまで変わらない | メイン入口グループ、地域選択グループ |
url-test | 定期的に速度測定し、遅延が最も低いメンバーを自動選択 | 同地域ノードの自動最適化 |
fallback | リスト順で最初に使えるメンバーを採用し、失効したら次へ | メイン/バックアップの切り替え、保険用の出口 |
load-balance | ハッシュまたはラウンドロビンで接続を複数メンバーに分散 | 複数ノードで大容量トラフィックを分担 |
relay | メンバーを順番に直列接続してチェーン転送 | 特殊な経路要件向け、通常はあまり使わない |
自動測速グループの4つの重要パラメータ
url-test と fallback はヘルスチェックに依存し、動作は4つのパラメータで決まります。url は測定先で、204 を返す軽量なアドレスを使うのが一般的です。interval はチェック周期(秒)で、300 が無難な値です。低くしすぎるとノードの流量を無駄に消費します。tolerance は切り替えの許容差(ミリ秒)で、新旧ノードの遅延差がこの値未満なら切り替えません。遅延が近い2つのノードが行き来してばたつくのを防ぐためのものです。lazy: true はグループが使われていない間は測定を一時停止する設定で、モバイル端末では省電力・省通信量のために有効化を推奨します。
実践:3層構造
多くの場面では、明快な設定に必要なのは3層だけです。最上位に手動のメイン入口、中間に自動測速とフェイルオーバー、最下位にサブスクのノード。ルールはすべてメイン入口を指すようにし、日常の切り替えはこの1グループだけ触れば済みます:
proxy-groups:
- name: ノード選択
type: select
proxies:
- 自動測速
- フェイルオーバー
- DIRECT
- name: 自動測速
type: url-test
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 50
lazy: true
use:
- main-sub
- name: フェイルオーバー
type: fallback
url: https://www.gstatic.com/generate_204
interval: 300
use:
- main-sub
サンプル中の use フィールドが参照しているのはプロキシ集合(proxy-providers、第6章で詳述)で、グループのメンバーをサブスク更新に合わせて自動同期させ、ノード名を手書きする必要がなくなります。注意点は2つ:グループ名は rules で参照する際に一字一句正確でなければならず、スペースが1つ多いだけでも起動に失敗します。また、グループ同士が相互参照して循環を作ることはできず、内核は起動時にすぐエラーを出して読み込みを拒否します。
用途ごとに細分化したい場合(例えば動画配信サービスだけ別グループにする)は、同じパターンで select グループを1つ追加し、メンバーに「自動測速」「ノード選択」を入れるだけです——先に骨格を作ってから加えていく方が、最初から10数個のグループを積み上げるより保守しやすくなります。
ルールセットの外部化管理
数千行のルールを rules に直接書き込むと2つの代償があります。設定本体が肥大化して読みにくくなること、そしてルールが変わるたびにメイン設定を編集する必要があることです。rule-providers の発想は、ルールを独立したファイルに外出しし、内核が定期的に自動取得・更新し、メイン設定には参照行を1行だけ残すというものです。
rule-providers:
streaming:
type: http
behavior: domain
format: yaml
url: https://example.com/rules/streaming.yaml
path: ./rule-sets/streaming.yaml
interval: 86400
rules:
- RULE-SET,streaming,ノード選択
- GEOIP,CN,DIRECT
- MATCH,ノード選択
フィールドを1つずつ説明します。type は http(リモート取得)か file(ローカルファイル)を指定します。url と path はそれぞれリモートアドレスとローカルキャッシュのパスです。interval は自動更新周期(秒)で、ルールセットの内容は頻繁には変わらないため 86400(1日)で十分です。format は yaml、text、mrs に対応しており、mrs は mihomo 独自のバイナリ形式でサイズが小さく読み込みが速いため、ルール提供元が用意していれば優先的に選びましょう。
behavior:最も踏みやすい落とし穴
behavior はこのルールセットの内容形式を宣言するもので、ファイルの実際の内容と一致させる必要があります:
| behavior | 内容の形式 | サンプル行 |
|---|---|---|
domain | 純粋なドメイン名リスト(+. によるワイルドカードに対応) | +.example.com |
ipcidr | 純粋な IP 範囲のリスト | 203.0.113.0/24 |
classical | 完全なルール行(マッチタイプ付き) | DOMAIN-SUFFIX,example.com |
behavior と内容が一致しない場合、ルールセットはたいていサイレントに機能しなくなります——エラーは出ず、単に永久にマッチしないだけです。振り分けが「設定したはずなのに効かない」ときは、まずここを確認してください。また、ipcidr 系のルールセットは RULE-SET 行の末尾に no-resolve を付けることで、純粋な IP マッチのために余計なドメイン解決が発生するのを避けられます。
GeoSite / GeoIP との関係
GEOSITE と GEOIP ルールの背後にあるのは別種の「パッケージ化されたルールセット」です——2つのバイナリデータベースが、国やサイトごとにドメイン名と IP 範囲を分類収録しています。これらは rule-providers と競合しません。geo データベースは汎用的な大分類をカバーし、rule-providers は個別のエントリを補完します。データベースが古くなると振り分けの精度が直接落ちます。更新方法はブログ『GeoIP と GeoSite データベース更新ガイド』を参照してください。rules 内の各タイプの文法と上から下への優先順位については、ブログ『Clash カスタムルールの書き方』で詳しく解説しているため、ここでは繰り返しません。
DNS 設定の最適化
まず「なぜ内核が自分で DNS を管理する必要があるのか」に答えます。ルールによる振り分けは解決結果に大きく依存します。GEOIP,CN,DIRECT はドメイン名を IP に解決してからでなければ帰属を判定できません。解決をシステムに任せ、システムが汚染されたアドレスを受け取ると、GEOIP は本来プロキシを通すべきトラフィックを誤って直接接続と判定してしまい、「ルールは正しいのに開かない」という現象になります。内核が信頼できる暗号化 DNS を使って自分で解決することが、振り分けの精度を支える基盤です。
dns:
enable: true
listen: 0.0.0.0:1053
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
nameserver:
- https://doh.pub/dns-query
- https://dns.alidns.com/dns-query
proxy-server-nameserver:
- https://doh.pub/dns-query
nameserver-policy:
"geosite:cn":
- https://doh.pub/dns-query
3種の nameserver がそれぞれ担当する範囲
この一連のフィールドは混同しやすいので、「何を解決するか」で覚えます。default-nameserver は純粋な IP しか書けず、nameserver にある DoH アドレス自身のドメイン名を解決するための、いわば鶏と卵問題のブートストラップです。nameserver は主力の解決サーバーで、通常のクエリすべてを担当します。DoH(https:// 接頭辞)や DoT(tls:// 接頭辞)形式を推奨し、平文の 53 番ポートは一部のネットワーク環境で乗っ取られることがあります。proxy-server-nameserver はプロキシノード自身のサーバードメインの解決を単独で担当し、これを直接接続できる国内向け DoH に固定することで、「ノードのドメイン解決にプロキシが必要で、プロキシはノードに依存する」というデッドロックを避けられます。
nameserver-policy:ドメインごとに解決サーバーを振り分ける
nameserver-policy はドメインパターンごとに解決サーバーを指定できます。最も使われるのがサンプルにある geosite:cn で、国内サイトは国内向けの DoH で固定的に解決し、近いリージョンの CDN アドレスを得られます。それ以外のドメインは主力の nameserver に任せます。キーには通常のドメインパターン(例えば "+.internal.example.com" を社内 DNS に向ける)も書けるため、オフィスネットワークの場面にも向いています。
DNS 設定が有効かどうかを確認する最も直接的な方法は、ログの解決記録を見ることです。どのドメインを、どの解決サーバーが、どう返したか。dns resolve failed がまとまって出る場合は、まず default-nameserver に到達できるか確認してください。切り分け方はブログ『Clash 実行ログの読み方』を参照してください。
サンプルにある enhanced-mode: fake-ip は DNS と TUN の境界で最も重要なスイッチであり、章を1つ割く価値があります——続きをご覧ください。
TUN モードと Fake-IP
システムプロキシは「プロキシ設定を読みにいく」アプリしかカバーできず、コマンドラインツールや一部のゲーム、バックグラウンドサービスは直接迂回します。TUN モードのやり方はより徹底しています。仮想ネットワークインターフェースを1枚作成し、ルーティングテーブルと組み合わせてデバイスの全トラフィックを内核に引き込みます——アプリが送信するすべてのパケットがこのインターフェースを経由するため、迂回する余地がありません。
まずプラットフォームの違いをはっきりさせておきます。iOS の Clash Plus は Network Extension のトンネル機構上で動作し、動作としては自然に TUN と等価であり、追加のスイッチは不要かつ存在しません。以下の tun 設定ブロックは主にデスクトップとルーターの場面向けです(Windows は仮想ネットワークカードドライバを読み込むために管理者権限が必要、macOS はシステム設定でネットワーク拡張を承認する必要があります)。ルーターで内核を直接動かす全体的な考え方は、ブログ『ルーターで mihomo カーネルを直接動かす』を参照してください。
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
stack はプロトコルスタックの実装を決めます。system はシステムスタックで性能が良い一方、互換性はプラットフォーム依存です。gvisor はユーザー空間スタックで互換性が安定しています。mixed は両者の長所を取ったもので、通常はこれを選べば十分です。auto-route は自動でルーティングテーブルを書き込み、auto-detect-interface は物理的な出口ネットワークカードを自動検出してループを防ぎます。この2つは有効にしたままにします。dns-hijack: any:53 は 53 番ポート宛のすべての平文 DNS クエリを内核の解決へ横取りするもので——これは TUN モードで「解決は必ず内核を経由する」ことを保証する重要な部分です。
Fake-IP:待ち時間を1回省く解決モード
前章の enhanced-mode に戻ります。従来の redir-host モードでは、内核が DNS クエリを受け取るたびに実際に1回解決してから応答します。fake-ip モードでは、予約されたアドレス帯(デフォルトは 198.18.0.1/16)から偽アドレスを即座に割り当てて返し、同時に「この偽 IP はこのドメイン名に対応する」と記録します。アプリが偽 IP で接続を開始すると、内核はマッピングからドメイン名を復元してルールとマッチングします——プロキシを通るトラフィックはドメイン名をそのまま相手側に解決させ、ローカルでの実解決を完全に省けるため、接続確立が速く、ドメインマッチングもより正確になります。
| 比較項目 | fake-ip | redir-host |
|---|---|---|
| 応答速度 | 即座に偽アドレスを返す | 実際の解決完了を待つ |
| ルールマッチング | 常にドメイン名を得られ、ドメインルールが全面的に機能する | 一部の場面では IP マッチングに退化する |
| 互換性 | 実 IP に依存する一部の場面はフィルタが必要 | 偽アドレスによる副作用はない |
互換性の問題は fake-ip-filter で解決します。実 IP を必ず得る必要があるドメイン——LAN デバイス探索、NTP 時刻同期、一部のゲーム対戦プラットフォーム——をリストに入れて、実際の解決を通させます:
dns:
fake-ip-filter:
- "*.lan"
- "+.local"
- time.apple.com
- "+.stun.*.*"
fake-ip と redir-host を切り替えた後、システムやブラウザに古いモードの解決キャッシュが残ることがあり、しばらく一部のサイトが開けないという症状として現れます。切り替え後はクライアントのネットワーク接続を再起動し、必要ならデバイスを再起動してから検証してください。
ドメインスニッフィング:失われたドメイン名を取り戻す
前の2章では「ドメイン名をどう解決するか」を扱いましたが、内核の DNS を一切経由しないトラフィックも存在します。アプリが独自の暗号化 DNS を内蔵している(ブラウザ内蔵の DoH など)場合や、サーバー IP をコードに直接埋め込んでいる場合です。この種の接続が内核に届くと目的 IP しか持たず、設定で丁寧に整えたドメインルール(DOMAIN-SUFFIX、GEOSITE)はすべて無効になり、IP ルールでの兜底に頼るしかなくなり、振り分けの精度が大きく落ちます。
ドメインスニッフィング(sniffer)は、トラフィック自体からドメイン名を取り戻すやり方です。TLS ハンドシェイクの ClientHello には SNI が含まれ、HTTP リクエストヘッダには Host があり、QUIC の初期パケットからも目的のドメイン名を復元できます。内核は接続確立の初期段階でこれらのフィールドを読み取り、復元したドメイン名をルーティングエンジンに書き戻すことで、ドメインルールを再び機能させます。
sniffer:
enable: true
sniff:
HTTP:
ports: [80, 8080-8880]
override-destination: true
TLS:
ports: [443, 8443]
QUIC:
ports: [443, 8443]
force-domain:
- "+.v2ex.com"
skip-domain:
- "Mijia Cloud"
3つのプロトコルブロックはそれぞれ、どのポートで対応プロトコルのスニッフィングを試みるかを宣言しています。override-destination はスニッフィングで得たドメイン名で接続先アドレスを上書きするという設定で、通常は有効にしておきます。force-domain にリストしたドメインは、解決結果が正常でも強制的にスニッフィング結果で上書きされ、一部の CDN でドメインと IP が対応しないケースに対処します。skip-domain は逆に、スニッフィングによって問題が起きる対象を除外するものです——一部のスマートホームの独自プロトコルが誤認識される場合はここに追加します。
コストの面では、スニッフィングは各接続の最初のハンドシェイクデータだけを読み取るため、オーバーヘッドは無視できます。fake-ip との関係は代替ではなく補完です。fake-ip は内核の DNS を経由するトラフィックにドメイン名を持たせることを保証し、スニッフィングは内核の DNS を迂回する部分を補います。両方を同時に有効にすることで、ドメインルールのカバー範囲が完全になります。
ローカルオーバーライドと複数サブスクの統合
誰もが必ずぶつかる問題があります。サブスクファイルはサーバー側で生成されているため、そこに直接加えたルールや変更した DNS は、次回のサブスク更新でまとめて上書きされて消えてしまいます。正しいやり方は、サブスクをそのまま保ち、自分の変更をオーバーライドとして宣言することです——サブスク更新の都度、クライアントが自動的にオーバーライドを重ね直してくれます。
2種類のオーバーライド形式
主要なクライアントは2種類のオーバーライドを提供しています。宣言式(merge):YAML の断片を書き、どのトップレベルキーを置き換え、どのリストの先頭・末尾に追加するかを宣言する方式で、直感的でミスが少ないです。スクリプト式:完全な設定オブジェクトを受け取り、変更後の設定を返す関数を書く方式で、柔軟ですがデバッグのコストは自己負担です。Clash Plus と Clash Verge Rev はいずれもオーバーライドの入口を内蔵しており、日常的な用途では宣言式で十分です。よく使われる merge の書き方を例に見てみましょう:
# オーバーライド断片:dns をキー全体で置き換え、ルールの先頭に2件追加
dns:
enable: true
enhanced-mode: fake-ip
prepend-rules:
- DOMAIN-SUFFIX,internal.example.com,DIRECT
- PROCESS-NAME,Terminal,DIRECT
merge を理解するには1点だけ覚えれば十分です。通常のトップレベルキーは丸ごと置き換え、prepend / append の接頭辞が付くキーはリストへの追加です。ルールは上から下へマッチするので、カスタムルールを優先的に効かせたいなら先頭追加、兜底として使うだけなら末尾追加を使います。
複数サブスクの統合:proxy-providers
複数のサブスクを持っている場合、クライアント内で設定をいちいち切り替える必要はありません。proxy-providers は各サブスクを1つのノード集合として宣言し、ポリシーグループが use で集合を参照することで、すべてのサブスクのノードが1つの設定に集約されます:
proxy-providers:
main-sub:
type: http
url: https://example.com/sub?token=xxxx
path: ./providers/main.yaml
interval: 43200
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 600
backup-sub:
type: http
url: https://backup.example.com/sub?token=xxxx
path: ./providers/backup.yaml
interval: 43200
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 600
フィールド構成は第2章の rule-providers と同型です。interval はサブスクの自動更新周期を制御し、43200(半日)がほとんどのサブスクで十分です。health-check は集合内のノードに可用性の状態を持たせ、url-test / fallback グループが直接利用できるようにします。第1章のサンプルにある use: [main-sub] が参照しているのはまさにここです——グループのメンバーはサブスク更新に応じて自動的に増減し、設定本体は1行も変更する必要がありません。サブスク更新が失敗したときは、まずログの取得エラーを確認し、それから URL が期限切れになっていないか確認してください。
サブスク URL に含まれる token はアカウントの認証情報と同等です。スクリーンショットを取ったり、公開の問い合わせ内容に貼り付けたりしないでください。サンプル中の token=xxxx は仮の値です。
外部コントロールとパネル
内核が動作している間のすべての状態——ノードの遅延、アクティブな接続、リアルタイムログ、現在のモード——は1つの RESTful API を通じて外部に公開されます。これが外部コントロールインターフェースです。クライアント内の接続一覧、Web パネル、コマンドラインでの照会は、いずれも裏側では同じ API を使っています。
external-controller: 127.0.0.1:9090
secret: "your-secret"
external-ui: ./ui
external-controller はリッスンするアドレスとポートを宣言します。secret はアクセストークンで、すべてのリクエストがヘッダーに含める必要があります。external-ui は静的なパネルディレクトリを指し、内核は同じポートの /ui パスでそれを配信します。ブラウザで直接アクセスするだけです。主要な Web パネルはいずれも純粋なフロントエンドプロジェクトで、そのディレクトリに展開すれば使えます。
curl で内核と直接やり取りする
# すべてのポリシーグループとノードの状態を確認
curl -H "Authorization: Bearer your-secret" \
http://127.0.0.1:9090/proxies
# 「ノード選択」グループの現在の出口を切り替える
curl -X PUT -H "Authorization: Bearer your-secret" \
-d '{"name": "自動測速"}' \
http://127.0.0.1:9090/proxies/ノード選択
# リアルタイムログストリーム / アクティブな接続
curl -H "Authorization: Bearer your-secret" \
http://127.0.0.1:9090/logs
curl -H "Authorization: Bearer your-secret" \
http://127.0.0.1:9090/connections
よく使うエンドポイントは4つ覚えれば十分です。/proxies(グループとノード)、/connections(アクティブな接続、「このトラフィックがどの出口を通ったか」を調べるのに最も直接的)、/logs(リアルタイムログストリーム)、/configs(実行中設定の読み取りとホットリロード)。ネットワーク切り替え後に自動でグループを変更するといった自動化スクリプトも、これらのエンドポイントを中心に組み立てます。
安全上の最低ラインです。secret は必ず設定し、十分に複雑にすること。リッスンアドレスはデフォルトの 127.0.0.1 のままにし、本当にLAN管理の必要がある場合のみ LAN アドレスに変更してください——コントロールインターフェースを認証なしで 0.0.0.0 に公開することは、デバイス全体のトラフィック制御権を同一ネットワーク内の誰にでも渡してしまうのと同じです。
iOS の場面について補足します。Clash Plus の内蔵パネルはクライアント内部で同じインターフェースを利用しており、通常の使用では本節の内容を手動設定する必要はありません。実際に外部コントロールが必要になるのは、デスクトップでのデバッグとルーターのヘッドレス配置という2つの場面です。