mihomo 設定ファイルリファレンス
YAML構造、ポート、DNS、ノード、振り分けルールを解説。まず項目の階層を確認し、参照関係と実行結果をチェックしましょう。
このページは、クライアントを起動できており、設定の動作を理解したい方向けです。初回インストール、サブスクリプションの追加、接続確認については、まず入門ガイドをご覧ください。個別の設定項目、上書きの優先順位、サービスの実行環境による違いを調べる場合は、このページの該当章を参照してください。例はLinux上でmihomoを直接実行する構成を基準にしています。GUIクライアントでは、ポート、権限、上書き設定などが追加されることがあります。
YAML構造と設定ディレクトリ
マップ、リスト、インデント
config.yamlは階層構造を持つ設定ファイルであり、上から順に実行するスクリプトではありません。トップレベルのdnsやtunはマップで、その下に項目を記述します。proxies、proxy-groups、rulesは通常リストで、ハイフンを使って項目を並べます。インデントで所属先が決まるため、半角スペース2つに統一し、タブは使わないでください。項目名が正しくても、誤った親項目の下にインデントされていると、解析に失敗したり、設定が反映されなかったりすることがあります。
コロンの後には半角スペースを1つ入れます。真偽値はtrueまたはfalse、ポートや間隔は数値で記述します。パスワード、記号を含む名前、日付のように見える文字列は、引用符で囲むのがおすすめです。通常のスカラー値では、#がコメントの開始と解釈されることがあるため、#を含むパスワードは文字列として記述してください。ダブルクォート内ではバックスラッシュがエスケープとして処理されます。バックスラッシュをそのまま残したい場合はシングルクォートが適しています。すべてを機械的にダブルクォートで囲み、パス内のバックスラッシュが意図せずエスケープされないよう注意してください。
同じマップ内で同じキーを重複して定義しないでください。ファイルの上部にdnsを書き、下部にもう一つ書いても、自動的に統合されるわけではありません。パーサーによっては重複キーを拒否したり、片方だけを保持したりするため、この動作に依存しないでください。ルールを追加するときは、既存のrulesリストに追記し、同名のリストを新たに作らないようにします。YAMLアンカーは記述の重複を減らせますが、クライアントの上書き機能とは別のものです。最終的な設定の確認も必要です。
まず検証可能な最小構成を作る
次の例は直結のみを行う最小構成です。サブスクリプションやプロキシサーバーを使わずに、ファイルのパス、パーサー、待受ポートを確認できます。TUNは無効にし、コントロールインターフェースと混合ポートをループバックアドレスに明示的にバインドしています。テストに成功しても、確認できるのはローカルの接続口までで、プロキシ経由の通信が確立したことを意味しません。ノードを追加した後も、この最小構成をトラブルシューティングの基準として残しておきましょう。複雑な設定で起動できない場合、バイナリ、システム環境、設定内容のどこに問題があるか切り分けやすくなります。
mixed-port: 7890
bind-address: 127.0.0.1
allow-lan: false
mode: rule
log-level: info
external-controller: 127.0.0.1:9090
tun:
enable: false
rules:
- MATCH,DIRECT
カーネルを直接実行する場合は、作業ディレクトリと設定ファイルを明示してください。起動するターミナルによって参照するファイルが変わるのを防げます。次のコマンドでは、-dがデータディレクトリ、-fが設定ファイルのパス、-tが設定テストを指定します。ディレクトリにはキャッシュ、Providerのダウンロードデータ、地理情報データなども含まれる場合があり、すべてを設定本文とみなすことはできません。相対パスは通常、ターミナルの現在のディレクトリではなく、カーネルの作業ディレクトリを基準に解決されます。サービスを移行するときは、この点を改めて確認してください。
mkdir -p "$HOME/.config/mihomo"
mihomo -t -d "$HOME/.config/mihomo" \
-f "$HOME/.config/mihomo/config.yaml"
mihomo -d "$HOME/.config/mihomo" \
-f "$HOME/.config/mihomo/config.yaml"
元ファイルと実行ファイルを区別する
GUIクライアントは、サブスクリプションの原文、ユーザー設定の上書き、生成後の実行ファイルをそれぞれ管理していることがあります。キャッシュディレクトリ内の生成ファイルを編集しても、次回の設定切り替えやサブスクリプション更新で再生成される場合があります。まずクライアントのログで、カーネルが実際に読み込んだパスを確認してから、変更するファイルを決めてください。GUIクライアント内蔵のカーネルと独立サービスを同時に起動し、同じポートを待ち受けさせないでください。同名のファイルを読み込んでいても、プログラムごとにディレクトリ、作業場所、実行ユーザー、環境変数が異なる場合があります。
設定エラーが出たら、最後の行から推測するのではなく、最初のエラーとその前後の行番号を確認してください。直前のリスト項目のインデント不足が原因で、後続の正しい項目でパーサーが停止することがあります。ウェブページの例をコピーした場合は、全角コロン、スマートクォート、不可視の空白が混入していないか確認しましょう。変更は機能単位で一つずつ追加し、その都度テストして、元に戻せるコピーを残すのがおすすめです。ファイルの自然な順序に沿って復習する場合は、config.yamlを項目ごとに解説も参考にしてください。最終的には、使用中のカーネルによる解析結果を確認してください。
待受ポート、接続範囲、動作モード
ポートはアプリからカーネルへの接続口
portはHTTPプロキシ、socks-portはSOCKSプロキシの接続口です。mixed-portでは、1つのポートで両方のプロトコルを受け付けます。一般的なデスクトップ環境では混合ポートだけで十分で、項目をそろえるために3種類すべてを有効にする必要はありません。アプリから接続する際は、正しいプロトコルとアドレスを指定してください。HTTPプロキシの設定にコントロールインターフェースのポートを入力したり、無効にしたSOCKSポートを指定したりしても、カーネルが正常に動作しているだけでは接続できません。
allow-lanはLANからの接続を許可するかどうか、bind-addressは待受アドレスを指定します。ローカル専用なら、ループバックへのバインドを維持するのが安全です。他のデバイスから使う場合に限り、実際のネットワークインターフェースのアドレス、ファイアウォール、アクセス制御を確認して接続口を開放してください。バインドアドレスがすべてのポートに共通するセキュリティ設定とは限りません。特に、コントロールインターフェースやDNSの待受アドレスも連動して変わるとは考えないでください。設定変更後は、画面上のスイッチだけでなく、システムツールで実際の待受状態を確認するのが確実です。
| 項目 | 用途 | ローカル向け設定例 |
|---|---|---|
mixed-port | HTTPとSOCKSの共通ポート | 7890 |
allow-lan | LANからの接続を許可するか | false |
bind-address | プロキシ接続口のバインドアドレス | 127.0.0.1 |
external-controller | 管理インターフェースの待受アドレス | 127.0.0.1:9090 |
log-level | ログの詳細度 | info |
ルール・全体・直結モードの違い
mode: ruleはルールに応じて接続先を選ぶモードで、長期運用時にも動作を把握しやすい設定です。globalは通常の通信をグローバルポリシーに送り、directは主に直結確認に使用します。モードが制御するのは、カーネルに入った通信の処理方法です。ブラウザー、コマンドラインツール、バックグラウンドプロセスを自動的にカーネルへ接続する機能ではありません。そのため、グローバルモードにしてもシステムプロキシを使用しないアプリは直結することがあります。その場合はルールを入れ替える前に、通信がカーネルに取り込まれているかを確認してください。
GUIクライアントのモード切り替えは、管理インターフェースを通じて実行中の状態を即時変更しても、サブスクリプション元のファイルには反映されないことがあります。再起動後に古いモードへ戻る場合は、複数のファイルにmodeを重複して追加するのではなく、クライアントの永続化設定と設定生成の仕組みを確認してください。また、プロキシグループの現在の選択状態はキャッシュから復元される場合があり、リストの先頭項目とは限りません。調査時は、ファイルの値、画面上の値、実際の接続記録をそれぞれ記録し、混同しないようにしましょう。
mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: info
external-controller: 127.0.0.1:9090
secret: "your-controller-secret"
管理インターフェースは状態の取得、プロキシ選択、設定の読み込みに使うもので、ブラウザー用のプロキシではありません。管理機能を使う場合はアクセスキーを設定し、実際の値はローカルに保管してください。管理インターフェースをインターネットに直接公開したり、キーをスクリーンショット、公開設定ファイル、問い合わせ内容に含めたりしないでください。リモート管理が必要なら、管理された接続経路を用意し、インターフェースのバインド、認証、ファイアウォールを個別に確認します。推測されにくいポート番号に変えるだけでは、アクセス制御の代わりになりません。
明示的なテストで環境の違いを切り分ける
まず待受状態を確認し、次に単一のコマンドからプロキシを明示的に指定してテストします。HTTP接続口とSOCKS接続口はそれぞれ別に検証してください。後者でsocks5hを使うと、接続先ドメインの名前解決をプロキシ側に任せられるため、ローカルの名前解決経路と区別しやすくなります。テスト先、ネットワーク、出口によって結果は異なるため、「接続拒否」「ハンドシェイク失敗」「名前解決失敗」など、エラーの原文を記録しましょう。「開けない」とだけ記録すると、接続口の手前と出口の先のどちらに問題があるのか判断しにくくなります。
ss -lntp | grep -E ':(7890|9090)\b'
curl --proxy http://127.0.0.1:7890 \
--connect-timeout 10 --head https://example.com
curl --proxy socks5h://127.0.0.1:7890 \
--connect-timeout 10 --head https://example.com
env | grep -iE '^(http|https|all|no)_proxy='
環境変数は、それを引き継いだプロセスにだけ適用されます。デスクトップ環境の設定がすべてのコマンドラインツールに反映されるとは限りません。大文字・小文字の変数やNO_PROXYが結果に影響する場合もあります。切り分けテストでは、システム全体を恒久的に変更するのではなく、実行するコマンドの環境変数を消すか、明示的なオプションを使ってください。詳細ログを一時的に有効にした場合は、出力に接続先情報が過剰に含まれないよう、テスト後に元に戻します。ポートが待ち受けていても失敗する場合は、トラブル対処でプロキシ接続口、DNS、ルール、ノードの順に確認してください。
DNS上流、fake-ip、名前解決の経路
クエリがカーネルに届いているか確認する
dns.enableは内蔵DNSリゾルバーを有効にしますが、システムのDNS参照先を自動的に変更するものではありません。デスクトップの名前解決サービス、ルーターから配布されたDNSアドレス、ブラウザーの暗号化DNSが引き続きクエリを処理することがあります。システムがカーネルの待受アドレスを明示的に使うか、TUNなどの仕組みでクエリがカーネルに取り込まれて初めて、該当するDNS設定が機能します。上流DNSの選定を始める前に、アプリ、システムのリゾルバー、カーネル、上流DNSの間でクエリがどのように流れるかを整理してください。この段階を飛ばすと、実際には使われていない項目を何度も変更することになります。
listenはDNSサービスの待受アドレスを指定するもので、混合プロキシポートとは別です。例では、切り分けテストがしやすいよう、ループバックアドレスと高いポート番号を使っています。システム標準のDNSポートを直接置き換える設定ではありません。通常、システムのネットワーク設定にはDNSサーバーのアドレスを指定しますが、任意のポート番号は入力できません。そのため、この例をデスクトップのDNS欄にそのまま入力することはできません。実際にDNSを転送する場合は、ローカル転送、TUNによる横取り、その他の明確な方法を選び、システムの名前解決サービスが対象ポートをすでに使用していないか確認してください。
dns:
enable: true
listen: 127.0.0.1:1053
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://dns.alidns.com/dns-query
proxy-server-nameserver:
- 223.5.5.5
3種類の名前解決を区別する
nameserverは通常の接続先ドメインを解決します。default-nameserverは主にDNS上流サーバー自身のドメインを解決し、暗号化DNSサービスが最初に接続先アドレスを取得できるようにします。proxy-server-nameserverはプロキシサーバーのドメイン名を解決します。役割を分けて考えることで、プロキシ接続にDNSが必要なのに、DNSはまだ確立していないプロキシに依存するという循環を防げます。例にあるパブリックDNSは設定をテストするための選択肢です。実際の運用では、利用するネットワークから到達できるか、採用する名前解決方針に適しているかも検討してください。
fake-ipは、ドメインに対応付けるための合成アドレスを返し、接続がカーネルに入った後にドメイン名を復元して振り分けます。このアドレスは接続先ウェブサイトの実サーバーのものではなく、表示されただけでDNS汚染を意味するわけではありません。割り当てに使うネットワーク範囲が、ローカルネットワークの設計と重複しないことも確認してください。アプリが合成アドレスを取得しても、カーネルを経由せずに接続すると到達できない場合があります。fake-ipを正しく使うには、DNSの経路と接続の経路が一致している必要があります。クエリが一度成功しただけで、通信経路全体が正常だと判断しないでください。
fake-ip-filterに指定したドメインは、実際の名前解決結果を返します。LAN内のデバイス検出や、アドレスの扱いに敏感なアプリでよく使われます。この設定は通信を直結させるものでも、ルールリストの代わりでもありません。フィルター対象のドメインへの接続も、引き続き振り分けルールに従います。LAN内のデバイスで問題が起きたら、ドメイン名の解決、実際のアドレス、LANの経路、ルールを併せて確認してください。失敗するドメインをすべてフィルターに追加するのは避けましょう。例外の範囲が広がりすぎると、設定の動作を把握しにくくなります。
DNSポリシーとキャッシュの範囲
特定のドメインに指定した上流DNSを使わせる場合は、nameserver-policyを検討できます。上流DNSへの接続にも振り分けルールを適用する場合は、respect-rulesを確認してください。後者はDNS接続自体のルーティング依存関係を変えるため、プロキシサーバーのドメインをどう解決するかも決め、循環依存を避ける必要があります。fallbackを「メインのDNSサーバーに障害が起きたときだけ使う予備サーバー」と単純に捉えないでください。フィルタリングの判定と組み合わせて結果が決まります。初回構築では、まず明快で検証しやすい単一経路を使い、複雑なポリシーは一つずつ追加してください。
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA
resolvectl status
resolvectl query example.com
カーネルへの直接クエリと、システムのリゾルバーへのクエリは別々のテストです。前者が正常で後者が異常なら、システムの参照先や転送設定を優先して確認します。両方が正常でもブラウザーだけ失敗する場合は、ブラウザー独自の暗号化DNS、キャッシュ、プロキシ設定も調べてください。設定変更後もアプリ、システム、カーネルの各キャッシュに古い結果が残ることがあります。どの層のキャッシュを消去したかを明確にしてください。既存の長時間接続が以前のアドレスを使い続ける場合もあり、ページを開き直しただけで新しい接続になるとは限りません。
dns.ipv6とトップレベルのipv6は適用範囲が異なり、片方だけを変更しても、すべてのアプリがIPv6を使わなくなるとは限りません。デュアルスタック環境でのみ発生する問題は、Aレコード、AAAAレコードの結果と実際の接続先アドレスを個別に確認し、出口がそれぞれに対応しているか調べてください。項目ごとの検証方法は、接続済みなのにウェブサイトを開けない場合のチェックリストもご覧ください。DNSを変更する際は目的を明確にし、上流、動作モード、ルーティングを一度に変えて、ページが開くかどうかだけで原因を判断しないようにしましょう。
プロキシノードの項目とサブスクリプションProvider
ノードには出口への接続情報を設定する
proxiesには個々のノードを定義します。各項目には、参照に使うnameとプロトコル種別のtypeが最低限必要です。その他の項目はプロトコルに応じて設定してください。ノード名は画面表示だけでなく、プロキシグループやルールからも参照されるため、重複を避け、安定した識別しやすい名前にします。名前が似ていても同じノードとは限りません。実際の接続先を決めるのは、サーバーアドレス、ポート、認証情報です。名前を変更したら、そのノード名を使うすべてのリストも確認してください。ノードの項目が解析に通っただけでは不十分です。
以下ではShadowsocksを使って基本的な項目の関係を説明します。サーバーには例示用に予約されたドメインを、パスワードには説明用の文字列を使用しています。接続するには、サービス提供者から指定された実際の情報に置き換えてください。cipherはサーバーと同じものにする必要があります。新しいアルゴリズムに見えるという理由だけで変更しないでください。udpは関連機能の有効・無効を表しますが、UDPに対応していないサーバーやネットワークで機能を使えるようにするものではありません。アプリのプロトコル、カーネルの実装、サーバー、通信経路上のネットワークがすべて対応している必要があります。
proxies:
- name: SS-Example
type: ss
server: proxy.example.com
port: 443
cipher: aes-128-gcm
password: "your-password"
udp: true
プロトコルによって、パスワード、UUID、TLS名、伝送パス、公開鍵など、必要な項目は異なります。あるプロトコルの設定をそのまま別のプロトコルに流用しないでください。接続先アドレスとTLSの検証名が異なる場合もあり、IPアドレスを入力したからといって証明書名を省略できるわけではありません。証明書エラーが出たら、検証を無効にする前に、システム時刻、サーバー証明書、名前の一致を確認してください。公開の場で相談する場合は、認証情報やサブスクリプションURL内の機密情報を削除し、必要なプロトコル設定とエラー情報だけを共有してください。
Providerでノード更新をメイン設定から分離する
proxy-providersを使うと、メイン設定にはプロキシグループやルールを残し、変わりやすいノードリストを外部ファイルやサブスクリプションで更新できます。Provider名とノード名は別の階層です。プロキシグループではuseでProviderを参照し、proxiesで個別のノードや別のプロキシグループを参照します。Providerを定義しただけでは、すべてのルールが自動的にそのProviderを使うわけではありません。プロキシグループを作り、そこに通信を振り分ける必要があります。設定の分離は更新に便利ですが、参照関係の確認も欠かせません。
proxy-providers:
local-nodes:
type: file
path: ./providers/local-nodes.yaml
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 600
proxy-groups:
- name: PROXY
type: select
use:
- local-nodes
ローカルProviderファイルは、ファイルのトップレベルにproxiesリストを置くなど、ノード一覧の形式にする必要があります。メイン設定で指定する相対パスは作業ディレクトリを基準に解決されるため、対象ディレクトリの存在と、サービス実行ユーザーの読み取り権限を確認してください。ポート、DNS、ルールを含むクライアント設定全体を、ノードファイルとして安易に使わないでください。一部の入力形式が互換処理されても、動作未確認の変換に依存するのは避けましょう。リストが空の場合は、まず実際のファイルを開き、ログで読み込みパス、形式エラー、ノードのフィルター条件を確認してください。
リモート更新、ヘルスチェック、エラーの切り分け
HTTP形式のProviderには、url、キャッシュ用のpath、更新間隔のintervalも必要です。更新間隔とヘルスチェックの間隔は別の処理です。前者はノード情報を再取得し、後者は登録済みノードからテスト先へ接続できるかを調べます。一方の間隔を短くしても、もう一方が速くなるわけではありません。テスト先自体に接続できないと、ヘルスチェックで失敗が続くことがありますが、すべてのノードで認証情報が無効になったとは限りません。一つの検査結果だけを見てノードを一括削除せず、実際の利用先にも接続して確認してください。
サブスクリプションの更新タイムアウト、HTTPステータスの異常、取得内容がYAMLではない、保存先への書き込み権限がないなど、原因ごとに対処は異なります。まずリクエストに応答があったかを確認し、次に返された内容と保存後のファイルを調べてください。サブスクリプションURLにはアカウントへのアクセス権が含まれる場合があります。バックアップやログはアクセス制限のある場所に保存し、公開リポジトリにアップロードしないでください。更新に既存のプロキシが必要なら、起動時に利用できる経路を用意します。ノードがないために初回のノード取得もできない事態を防いでください。ローカルキャッシュは復旧に役立ちますが、安定した取得方法の代わりにはなりません。
更新に成功しても、ノード名、地域ラベル、対応プロトコルが変わり、プロキシグループのフィルターや手動選択に影響することがあります。保守時はノード一覧の変更を比較し、ファイルのダウンロード成功だけでルールから出口までの経路が正常だと判断しないでください。サブスクリプション提供元と当サイトのクライアント設定ガイドは役割が異なり、クライアントが接続可能なサービスを自動生成するわけではありません。クライアントが必要な場合は、クライアント一覧ページでプラットフォームを選んでください。Windows、macOS、Android、iOSではClash Plus、LinuxのGUI環境ではClash Verge Revを確認できます。更新エラーの詳しい対処は、サブスクリプションの更新失敗と自動更新の設定をご覧ください。
プロキシグループの種類、参照、選択状態
プロキシグループでルールと実際の出口をつなぐ
proxy-groupsでは通信の出口を決めます。ルールからグループを指定し、そのグループでノード、別のグループ、組み込みの接続先を選択できます。これにより、サブスクリプションでノード名が変わるたびに、ルールを一つずつ修正せずに済みます。プロキシグループは単なるノードのフォルダーではなく、種類によって選択方法が異なります。すべてのノードを一つのグループに入れても、カーネルが同時にすべてを使うわけではありません。構成を考える前に、手動選択、接続テストに基づく選択、順番に従ったフェイルオーバー、接続の振り分けのどれが必要かを決めてください。
selectは、ユーザーまたは管理インターフェースから選択項目を指定し、出口を明示的に制御する場合に適しています。url-testはテスト結果を基に候補を選び、fallbackは主に候補の順番に沿って利用可能な出口を探し、load-balanceは設定した方式に従って接続を振り分けます。自動選択の基準は指定したテスト先であり、すべてのサービスに対する総合的な品質ではありません。テストで速かったノードでも、接続先のサービスにアクセスできないことがあります。自動テストの結果を読む際は、テスト先とテスト方法、実際の用途を分けて考えてください。
proxy-groups:
- name: AUTO
type: url-test
use:
- local-nodes
url: https://www.gstatic.com/generate_204
interval: 600
tolerance: 50
- name: PROXY
type: select
proxies:
- AUTO
- DIRECT
use:
- local-nodes
上の設定は、前章で定義したlocal-nodes Providerを使います。AUTOはProviderから候補を取得します。PROXYでは自動選択グループのほか、個別のノードや直結も選択できます。グループにDIRECTを残すのは、手動で選べるようにするためであり、プロキシノードの障害時に必ず直結するという意味ではありません。接続失敗時に出口を切り替えず通信を停止したい場合は、要件に合わない候補を外し、フェイルオーバーグループの経路全体を確認してください。名前に「安全」や「固定」とあるだけで、実際の動作を判断することはできません。
名前の参照関係は有向グラフを構成する
proxiesに記載した名前は実在している必要があり、大文字・小文字や空白も一致させてください。グループから別のグループを参照できますが、入口グループが自動選択グループを参照し、自動選択グループが入口グループを参照するような循環は作れません。循環があると実際のノードまで到達できず、テスト時に拒否されたり、実行時に異常が発生したりする場合があります。ルールからグループ、さらにノードへ向かう矢印図を描くと整理しやすくなります。すべての経路が、最終的に具体的なノードか明示的な組み込み出口に到達することを確認してください。
グループ名とノード名は別の名前にし、組み込みポリシーと同じ名前を業務用グループに付けるのも避けてください。文字列の境界を明確にするために複雑な名前を引用符で囲めますが、名前の不一致は直りません。Providerの更新でノードが消えると、手動選択が無効になったり、ほかの候補に切り替わったりすることがあります。クライアント上で現在の選択項目を確認してください。選択状態のキャッシュは再起動後の復元に役立つ一方、リストの順序を変えても出口が切り替わらない原因になることがあります。リストの先頭項目と実行時の選択項目は別のものです。
| 種類 | 選択基準 | 注意点 |
|---|---|---|
select | 手動または管理インターフェースで指定 | 現在保存されている選択項目を確認 |
url-test | 候補からテスト先への接続結果 | テスト結果はすべての通信を保証しない |
fallback | 候補の順序と利用可否 | 順序によって出口の優先順位が変わる |
load-balance | 設定した接続の振り分け方式 | 単一接続の帯域は合算されない |
自動切り替えの影響範囲を把握する
intervalは定期テストの間隔を指定します。toleranceを使うと、小さな差による頻繁な切り替えを抑えられますが、接続品質を保証するものではありません。テスト間隔を短くしすぎると、特にノード数が多い場合にネットワークへのリクエストが増加します。グループの選択が変わっても、既存の長時間接続が別の出口へシームレスに移るとは限りません。切り替えをテストするときは新しい接続を確立し、アプリが既存のセッションを再利用していないことを確認してください。ログイン状態、地域判定、長時間の処理に関わる場合は、出口が変わっても問題ないかを先に検討しましょう。
ロードバランシングは通常、接続または接続先に応じて振り分けを行います。単一のダウンロード接続を複数のノードに分割し、帯域を合算するものではありません。接続ごとに異なる出口を使うと、接続先サービスのセッション制限にかかる場合があります。用途ごとにグループを分け、すべての通信を一つのランダムな出口プールに集約しないようにしましょう。出口を固定したいサービスには専用の選択グループを用意し、ルールで先にマッチさせます。一般的なウェブ閲覧には自動選択グループを利用できます。グループが少ないほど保守しやすくなりますが、まとめすぎると、関係のない通信まで一度の切り替えの影響を受けます。
グループが空の場合は、Providerの読み込み、候補をすべて除外するフィルター式、参照先Providerの誤り、プロトコルのサポート条件による除外を順に確認してください。候補があるのに通信できない場合は、ノードを手動で一つ選んで新しい接続を確立し、ルールの最終的な振り分け先と出口のエラーを確認します。グループの種類、テスト先、ノードのフィルター条件を一度に変更すると、原因を特定できなくなります。運用しやすいプロキシグループには、明確な用途、説明可能な選択基準、失敗時の処理方針が必要です。
ルールの順序、マッチ構文、ルールセット
上から順に判定し、最初にマッチしたルールを適用
rulesは順序を持つリストで、通常は上から順に評価され、マッチしたルールに指定されたポリシーが適用されます。ルールの記述位置によって結果が変わるため、キーワードを並べるだけで最適なルールが自動選択されるわけではありません。一般には、明確な例外を上部に置き、用途別ドメインやルールセットを中段に配置し、広範囲のアドレス判定を下部に置いて、最後にMATCHで振り分けます。フォールバックルールが先にあると、通常は後続のルールまで評価されません。
DOMAINはドメイン名を完全一致で照合し、DOMAIN-SUFFIXはドメイン名とそのサブドメインを照合します。DOMAIN-KEYWORDは文字列のキーワードで照合します。キーワードルールは想定以上の範囲にマッチしやすいため、短い語を用途の判定基準にするのは避け、慎重に使ってください。通常のドメインルールではウェブページのパスを区別できません。同じドメイン上の異なるディレクトリを分けて扱うこともできません。暗号化された通信で取得できる接続先情報は、アプリの動作、DNS経路、スニッフィング設定にも左右されます。すべての接続で完全なURLが取得できるとは限りません。
rules:
- DOMAIN,example.com,DIRECT
- DOMAIN-SUFFIX,example.org,PROXY
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- IP-CIDR6,::1/128,DIRECT,no-resolve
- IP-CIDR6,fc00::/7,DIRECT,no-resolve
- MATCH,PROXY
この例では、すでに定義されているPROXYグループを使用します。対象ドメインはマッチ範囲を示すためのものです。プライベートアドレスを直結させるルールは一般的なローカルネットワークに適していますが、トンネル、コンテナ、企業内ネットワークを対象に含めるかは、実際のルーティングに応じて判断してください。no-resolveは、このアドレスルールのために接続先ドメインを積極的に名前解決しない指定であり、DNSモジュール全体を無効にするものではありません。接続先IPアドレスがすでに分かっている場合は、アドレスでマッチできます。この指定を削除すると名前解決への依存が増えることがあるため、目的を理解してから変更してください。
ルールセットの形式を実際の内容と一致させる
rule-providersを使うと、大量のルールを個別に管理し、メインルールからRULE-SETで参照できます。Providerのbehaviorは、項目がドメイン、アドレス、従来形式のルールのどれに該当するかを示します。formatはファイル形式を指定します。別の項目なので混同しないでください。ドメインリストとして宣言して完全なルール行を入れたり、テキスト形式として宣言してトップレベルのマップを含むYAMLを渡したりすると、読み込みに失敗したり、意図どおりにマッチしなかったりすることがあります。宣言内容と実際に取得したファイルの両方を確認してください。
rule-providers:
business-domains:
type: file
behavior: classical
format: yaml
path: ./rules/business.yaml
rules:
- RULE-SET,business-domains,PROXY
- MATCH,DIRECT
対応するbusiness.yamlファイルは次のとおりです。ルールセットの各項目は照合条件だけを定義し、使用する出口はメインファイルのRULE-SET行で指定します。これにより、同じ条件のセットを使いながら、環境ごとに異なるポリシーを適用でき、ルールファイル自体を変更する必要がありません。ローカルファイルとリモートファイルには別々のパスを割り当て、更新処理で手書きの内容が上書きされないようにしてください。ファイルが存在するのにマッチしない場合は、メインルール内の位置を確認し、先行する範囲の広いルールに先に処理されていないか調べましょう。
payload:
- DOMAIN-SUFFIX,example.org
- DOMAIN,api.example.net
まずマッチするかを確かめ、その後にルールセットを調整する
リモートルールセットの更新に失敗しても、現在の動作がすぐ変わるとは限りません。カーネルが既存のキャッシュを使い続ける場合があります。一方、初回起動時にキャッシュがないと、セットの取得失敗が設定の読み込みやマッチ結果に影響することがあります。Providerの読み込み状態とエラーログを確認し、ローカルファイルの更新日時だけで判断しないでください。地理情報データを使うルールでは、データファイルが利用可能か、形式が対応しているか、更新方法が明確かも確認します。ルール構文が正しくても、外部データの準備が整っているとは限りません。
Linuxのプロセスルールでは、プロセス検出機能と必要な権限が求められることがあります。コンテナ、転送通信、別のユーザーで実行されるプログラムでは、同じプロセス情報を取得できない場合もあります。プロセスルールにマッチしないときは、プロセス名の綴りを何度も変える前に、カーネルから対象プロセスが見えているか確認してください。送信元アドレスのルールでは、ローカルアプリの通信か、LANから転送された通信かを区別します。ルールは実際に取得できる情報に基づいて判定されるため、ルーティングやNATで送信元が変わると、以前のルールの前提が成り立たなくなることがあります。
意図しない振り分けを調べるときは、対象ドメイン、接続先アドレス、マッチしたルール、最終的なプロキシグループ、実際の出口を記録してください。範囲を明確にした一時ルールをリストの上部に追加して検証し、確認後に正しい位置へ戻します。「ネットワークを直す」ためにルールを大量削除しないでください。ルールを更新した後は新しい接続で再テストし、必要に応じて関連キャッシュを消去します。一つのサイトが複数のドメインを使う場合は、接続記録を一つずつ確認してください。トップページのドメインだけを処理し、API、静的ファイル、認証用ドメインを見落とさないようにしましょう。
TUNによる通信の取り込み、Linuxの権限、常駐サービス
透過的な通信の取り込みにはカーネル以外の条件も必要
tun.enableは仮想ネットワークデバイスによる通信の取り込みを有効にし、auto-routeは関連するルートの設定を要求します。auto-detect-interfaceは出口のネットワークインターフェースを検出します。これらは通信をカーネルに入れるための設定であり、ノード、DNS、ルールの設定を代替するものではありません。まず明示的なプロキシ接続が使えることを確認してからTUNを有効にしてください。入口、ルート、出口を同時に変更すると、障害の切り分けが難しくなります。デスクトップで別のVPNや透過プロキシが動作している場合は、デフォルトルートとDNSをどのプログラムが管理するかを先に決めてください。
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
stackはTUNが使用するプロトコルスタックを指定します。対応状況はプラットフォーム、ビルド、カーネルの実装によって異なります。例ではmixedを使っていますが、すべての環境で最適とは限りません。dns-hijackの一般的な設定は通常のDNSクエリを対象とし、ブラウザーやアプリのHTTPS DNSを自動的に復号するものではありません。有効にした後もクエリの経路を確認してください。特に、システムのローカル名前解決サービス、コンテナ、アプリ独自の上流DNSは、画面上のTUNスイッチだけでは判断できません。
権限が足りないと、デバイスの作成やルートの追加に失敗することがあります。まずシステムに/dev/net/tunが存在するかを確認し、次に実行ユーザーと権限設定を調べてください。コンテナでは、デバイスの割り当て、ネットワーク名前空間、ホスト側の許可設定にも左右されます。コンテナ内で管理者権限を使っていても、ホストから必要なネットワーク機能が許可されているとは限りません。リモートサーバーでルートを変更すると管理接続が切れる可能性があります。コンソールや復旧用の経路を用意し、管理用ネットワークと既存VPNのルートが誤って取り込まれないことを確認してください。
実際に使うバイナリに権限を付与する
カーネルを直接導入する場合は、権限の影響範囲を確認したうえで、必要なネットワーク機能を付与できます。以下はユーザーディレクトリ内の固定バイナリを例にしています。実際に起動するファイルのパスを先に確認してください。機能はファイルに対して設定されるため、バイナリを交換したり再インストールしたりすると、再設定が必要になることがあります。出所が不明なプログラムに権限を与えないでください。ネットワーク機能を付与しても、すべての安全対策が完了したことにはなりません。別のプロセスが許可済みプログラムを置き換えられないよう、ディレクトリの書き込み権限も確認してください。
test -c /dev/net/tun
install -d "$HOME/.local/bin"
sudo setcap cap_net_admin,cap_net_bind_service=+ep \
"$HOME/.local/bin/mihomo"
getcap "$HOME/.local/bin/mihomo"
cap_net_adminはネットワーク管理に関わり、cap_net_bind_serviceは1024未満のポートへのバインドに使います。後者が必要かどうかは、実際の待受ポートによります。ファイルシステムやサービス側のセキュリティ制限により、ファイルに設定した機能が期待どおりに働かない場合があります。権限の表示を確認するだけでなく、起動ログも調べてください。GUIクライアントでは独自のサービスコンポーネントが権限を処理することがあるため、別の方法を重ねて適用しないでください。明示的なHTTPプロキシだけを使うなら、権限やルートの変更を抑えるためにTUNを無効のままにできます。
ユーザーサービスで実行パスとログを追跡する
次のユーザーサービスは、固定の作業ディレクトリと絶対パスの設定ファイルを使い、起動前に設定テストを実行します。前述のとおり、カーネルをユーザーディレクトリにインストールした環境向けです。systemdはExecStartを対話型シェルとして実行しないため、ターミナルのエイリアス、一時的な環境変数、チルダ展開には依存できません。例の%hはsystemdによってユーザーのホームディレクトリに展開されます。システムサービスとして導入する場合は、実行ユーザー、ディレクトリ権限、権限境界を別途設計してください。ファイルをシステムディレクトリに移動するだけでは不十分です。
# ~/.config/systemd/user/mihomo.service として保存
[Unit]
Description=mihomo user proxy service
[Service]
Type=simple
WorkingDirectory=%h/.config/mihomo
ExecStartPre=%h/.local/bin/mihomo -t -d %h/.config/mihomo -f %h/.config/mihomo/config.yaml
ExecStart=%h/.local/bin/mihomo -d %h/.config/mihomo -f %h/.config/mihomo/config.yaml
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target
まずサービス用ディレクトリを作成し、ファイルを保存してから、ユニットを再読み込みします。サービスの起動後は、ログで実際のパス、権限エラー、ルーティングエラーを確認してください。プロセスが存在するかどうかだけでは判断できません。ユーザーサービスは通常、ユーザーマネージャーのライフサイクルに従います。ログアウト後も動作させる必要がある場合に限り、ユーザーサービスの残留を有効にするか検討してください。バックグラウンドタスクのライフサイクルが変わるため、すべてのデスクトップ環境で既定の手順にするのではなく、マシンの用途に応じて判断しましょう。
mkdir -p "$HOME/.config/systemd/user"
systemctl --user daemon-reload
systemctl --user enable --now mihomo.service
systemctl --user status mihomo.service
journalctl --user -u mihomo.service -n 80 --no-pager
ip route
ip rule
TUNを有効にした後にLANや別のVPNへ接続できなくなった場合は、まずサービスを停止し、ルートが元に戻るか確認します。そのうえで、有効にする前後のルーティングテーブルとポリシールーティングを比較してください。出所が分からないルートをまとめて削除すると、システムのネットワーク管理状態を壊すおそれがあります。サービス停止後も異常が続く場合は、別のカーネルプロセス、残存するDNS設定、クライアントのバックグラウンドサービスがないか確認しましょう。ルーターへの導入には、転送、ファイアウォール、ゲートウェイの設定も必要です。OpenWrtでバイパスルーターを構成する方法を参考にしてください。ローカルPC用のTUN例を、そのままバイパスルーターの完全な設定として使わないでください。
設定の上書き・統合、変更テスト、ロールバック
YAML構文とクライアントの生成処理を区別する
設定の上書きとは、クライアントや外部ツールが設定を加工する処理です。すべてのYAMLファイルに備わっている機能ではありません。サブスクリプションの原文、ローカルの上書き設定、画面上の設定が異なる順序で統合され、実行用ファイルが生成されることがあります。クライアントによって統合ルールも異なります。「後から書いた項目が必ず優先される」と決めつけたり、特定クライアントの拡張キーを独立したカーネルに渡したりしないでください。まず、設定を処理しているのは何か、入力ファイルは何か、最終出力先はどこかを確認してから、項目が上書きされた理由を調べましょう。
スカラー、マップ、リストはそれぞれ別に確認する必要があります。ポート番号のような値は置き換えやすい一方、DNSのマップは再帰的に統合される場合も、全体が置き換わる場合もあります。ルールやプロキシグループのリストは、追記、先頭への追加、全体の再生成など、処理方法が異なります。ツールが上書き設定のrulesをメイン設定全体に置き換えると、LAN向けのルール1つだけで既存のプロキシルールがすべて消えることがあります。反対に、フォールバックルールの後ろに単純に追加すると、新しい項目が一度もマッチしない可能性があります。統合処理が成功しても、目的どおりの順序になったとは限りません。
サブスクリプション設定を管理する場合は、ノードはサブスクリプションに、安定したポート、安全性、用途別のポリシーはローカル設定に任せるのがおすすめです。Providerで分離できる場合は、ノードの更新を独立させ、ファイル全体を更新するたびに発生する競合を減らしてください。ただし、すべてのクライアントで共通する操作手順ではありません。GUIによっては対象の設定部分を再生成することがあります。クライアントが用意する上書きや拡張用の仕組みで設定し、エディターの保存成功表示だけで判断せず、最終的な実行ファイルを確認してください。
一度に一つの動作だけを変更してテストする
変更前に元へ戻せるコピーを保管し、現在のモード、プロキシグループの選択、通信の取り込み方法を記録してください。YAMLだけをバックアップしても、クライアントのキャッシュ、Providerファイル、システムプロキシ設定が影響するため、実行状態まで復元できないことがあります。DNSやTUNを変更する場合は、変更前のDNS参照先とルーティング情報も記録しておきましょう。バックアップにサブスクリプションや認証情報が含まれる場合は、アクセス制限のあるディレクトリに保存してください。ウェブサイト、共有同期フォルダー、公開の問い合わせ添付には置かず、差分を共有する前に機密情報を削除してください。
cd "$HOME/.config/mihomo"
cp -p config.yaml config.yaml.before-change
cp -p config.yaml config.candidate.yaml
# 候補ファイルを編集したら、まず候補ファイル自体を確認します。
mihomo -t -d "$HOME/.config/mihomo" \
-f "$HOME/.config/mihomo/config.candidate.yaml"
diff -u config.yaml.before-change config.candidate.yaml
候補ファイルは、相対パスを同じ条件で使えるよう、同じ作業ディレクトリに置いてテストしてください。ただし、設定テスト中にProviderへアクセスしたりキャッシュを生成したりする場合があり、完全に隔離されたサンドボックスではありません。設定テストで主に検出できるのは構文、項目、参照の問題です。リモートノードの利用可否、DNSの循環依存、ルートの競合までは保証できません。テスト後は差分も確認し、プロキシグループが意図せず削除されていないか、待受範囲が広がっていないか、管理インターフェースが外部アドレスに変更されていないかを調べてから、実際の切り替えを行いましょう。
候補ファイルを確認してから正式なファイルに置き換え、現在の導入方法に応じて再読み込みしてください。このページのユーザーサービスを使う場合は、サービスを再起動すると起動前の設定テストが再実行されます。クライアントのホットリロードを使う場合は、別のサブスクリプションではなく、目的の設定が読み込まれることを確認してください。再読み込みが成功したら、新しい接続を確立して検証します。既存の接続では、以前の出口やDNS結果が使われ続ける場合があります。接続を明示的に切断する際は、進行中のダウンロード、リモートセッション、ほかのユーザーの作業を確認してください。テストのために不要な中断を起こさないようにしましょう。
cd "$HOME/.config/mihomo"
cp -p config.candidate.yaml config.yaml
systemctl --user restart mihomo.service
journalctl --user -u mihomo.service -n 80 --no-pager
curl --proxy http://127.0.0.1:7890 \
--connect-timeout 10 --head https://example.com
# 元に戻す場合に実行:
cp -p config.yaml.before-change config.yaml
systemctl --user restart mihomo.service
原因を特定できる段階に分けて検証する
第1段階では設定の解析とプロセスの起動、第2段階ではプロキシ、DNS、管理インターフェースの実際の待受状態、第3段階ではノードのハンドシェイクと接続先へのアクセス、第4段階ではルールのマッチと透過的な通信の取り込みを確認します。前の段階の結果が明確になってから次へ進むと、テスト結果を判断しやすくなります。明示的なプロキシ接続は成功してTUNだけ失敗する場合は、通信の取り込みと権限を優先して確認します。ノードのドメイン名を解決できない場合は、まず名前解決の経路を調べてください。アクセスできても出口が違う場合は、クライアントを再インストールするのではなく、ルールの順序とグループの選択を確認します。
ロールバック後も、復旧した状態を検証してください。ファイルを戻した後、サービスが実際に再読み込みされたか、Providerの内容が更新後のままではないか、クライアントがポートやDNSを再び上書きしていないかを確認します。サブスクリプションの更新後にだけ問題が発生した場合は、機密情報を削除した構造上の差分を保存し、ノード名、プロトコル項目、グループのフィルター条件を調べてください。更新機能を恒久的に無効にするのは避けましょう。変更箇所を特定できたら、保守記録には変更の目的、対象項目、テスト結果、復元方法を記載すれば十分です。アカウント情報を含むログ全体を保存する必要はありません。
長期運用では、実際の用途に必要な設定だけを残しましょう。使わない接続口は無効にし、業務上の例外は範囲を明確にし、リモートルールセットは取得元を追跡できるようにします。起動サービスの管理主体も一つにしてください。項目を追加する前に、現在のカーネルが対応しているか、クライアントの設定生成時に削除されないかを確認しましょう。動作を判断できない場合は、入門ガイドにある最短の検証手順に戻るか、トラブル対処に沿ってエラー情報を整理してください。このガイドでは項目と依存関係を説明していますが、最終的な判断の根拠となるのは、ローカルで実際に読み込まれたファイル、ログ、新しく確立した接続の結果です。