まずカーネルを確認し、設定の参照関係を把握する

設定の基本は3層構造です。ノードが接続先を定義し、ポリシーグループが接続先をまとめ、ルールが接続をどこに振り分けるかを決めます。proxiesはルール一覧ではなく、proxy-groupsを設定しただけですべての接続が自動的にプロキシ経由になるわけでもありません。クライアントが接続を取り込み、該当するルールに一致して初めて、設定した振り分けが適用されます。

Clashは設定エコシステムの総称として広く使われていますが、対応フィールドはカーネルによって異なります。この記事の設定例はmihomo(旧Clash.Metaカーネル)向けです。インラインルールセットなどの記述が、すべての旧Clashカーネルで使えるとは限りません。クライアントの「バージョン情報」やカーネル情報画面でカーネル名を確認し、対応する設定ドキュメントを参照してください。

  • proxies:各ノードのプロトコル、サーバー、ポート、認証情報を設定します。
  • proxy-groups:ノード名やほかのグループ名を使って、接続先を選べるポリシーとしてまとめます。
  • rule-providers:ファイル、HTTP、インラインリストなどを使い、再利用できるルールセットを定義します。
  • rules:接続を上から順に照合し、DIRECT、REJECT、またはポリシーグループへ振り分けます。

読み込み可能なconfig.yamlの構成例

以下はmihomo向けの設定例です。リモートプロキシノードは含まず、既定の接続先はDIRECTです。設定の読み込み、ポリシーグループの選択、ルールの照合を確認するためのもので、プロキシ回線を新たに用意するものではありません。構成が読み込めることを確認してから、サービス提供元から入手した実際のノードを追加してください。

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false

dns:
  enable: true
  listen: 127.0.0.1:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - 223.5.5.5
    - 1.1.1.1

proxies: []

proxy-groups:
  - name: "手動選択"
    type: select
    proxies:
      - DIRECT
      - REJECT

rule-providers:
  local-demo:
    type: inline
    behavior: classical
    payload:
      - DOMAIN-SUFFIX,example.org

rules:
  - DOMAIN,example.com,DIRECT
  - RULE-SET,local-demo,DIRECT
  - 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
  - MATCH,手動選択

設定を読む順序と実際の適用順序は異なる

トップレベルの項目は「共通設定 → DNS → ノード → ポリシーグループ → ルールセット → ルール」の順に並べると読みやすくなりますが、この順序で記述する必要はありません。実際の振り分けに直接影響するのは、rulesリストの順序とポリシーグループの初期選択です。参照する名前は、空白、大文字・小文字、日本語も含めて完全に一致させてください。

YAMLのインデントには半角スペースを使い、タブは混ぜないでください。この記事では各階層を半角スペース2つで字下げし、リスト項目はハイフンと半角スペースで記述します。特殊文字を含む名前やパスワードは、引用符で囲むのがおすすめです。数字だけのパスワードも文字列として記述し、解析時に型が変わらないようにしてください。

共通設定:ポート、動作モード、通信の取り込み範囲

項目設定例の値動作
mixed-port78901つの待ち受けポートでHTTPとSOCKSのプロキシ接続を受け付けます。
allow-lanfalseLAN内のほかの端末には公開しません。ローカルでの学習に適した設定です。
moderulerulesに従って通信を振り分けます。グローバルモードでは、このルールに沿った個別の振り分けは行いません。
log-levelinfo通常の動作情報を記録します。問題の調査時は一時的にdebugへ切り替えられます。
ipv6falseこの設定例ではカーネルのIPv6対応を無効にします。システム全体のIPv6を無効にする設定ではありません。

mixed-port: 7890は、カーネルがこのポートでプロキシ接続を受け付けることを示すだけで、システムやすべてのアプリがプロキシを使うという意味ではありません。アプリによってはシステムプロキシの設定に従いますが、無視するものもあります。TUNは仮想ネットワークインターフェースを通じて、より多くの通信を取り込みます。利用できるかどうかは、システム権限、ルーティング、クライアントの実装にも左右されます。

この記事ではTUNを有効にしていません。まずテスト用アプリのHTTPプロキシに127.0.0.1:7890を設定すれば、プロキシの入口を確認できます。ポートがほかのプログラムに使用されていると、ログにaddress already in useと表示されることがあります。その場合は、使用中のプログラムを終了するか、設定とアプリのプロキシポートをそろえて変更してください。たとえば両方を7891にします。

dns:名前解決とルール照合の連携

dnsセクションでは、カーネルのDNS名前解決を設定します。この例ではfake-ipを有効にし、仮想アドレスプールに198.18.0.1/16を使います。これらはドメイン名と対応付けるためのアドレスで、Webサイトの実サーバーのアドレスではありません。カーネルが対応関係を保持するため、後続の接続でドメイン名を復元し、ドメインルールの照合に利用できます。

1053は待ち受けポートであり、上流DNSサーバーのアドレスではない

listen: 127.0.0.1:1053は、ローカルでDNSサービスを受け付けるアドレスです。上流の名前解決サーバーはnameserverに記述した2つのIPアドレスです。この例では構成を確認しやすいよう、通常のDNSを使用しています。上流DNSを選ぶ際は、現在のネットワークから到達できるか、プライバシー要件を満たすかも考慮してください。特定のパブリックDNSを、あらゆるネットワークで使える固定の選択肢と考えないようにしましょう。

  • dns.enableを有効にしただけでは、システム上のすべてのDNSリクエストが自動的にカーネルへ送られるわけではありません。
  • 通常、システムのDNS設定には127.0.0.1:1053のような独自ポート付きのアドレスを直接指定できません。DNS通信を取り込むには、クライアントやローカルフォワーダーとの連携が必要です。
  • TUNでのDNSハイジャックは別レイヤーの設定です。DNSを機能させるために、ほかのOS向けのTUN設定をそのままコピーしないでください。
  • アプリ内蔵の暗号化DNSによって、ドメイン名の解決経路が変わることがあります。ドメインルールに一致しない場合は、ブラウザーのセキュアDNS設定と実際の接続記録も確認してください。

この例ではfake-ip-filterを設定していません。LAN内のサービスやアプリが仮想アドレスに対応していない場合は、ログを確認して対象のドメインをフィルターリストに追加し、接続を作り直して検証してください。範囲の広すぎるワイルドカードを追加すると、多数の接続で名前解決の動作が変わるおそれがあります。

proxies:ノードのパラメーターをサーバー側と一致させる

proxies: []は、ノードのリストが空であることを示します。ノードを追加するには、これをリストに置き換えます。以下はShadowsocksの項目構成を示す例です。192.0.2.10はドキュメント用のアドレスで、パスワードもサンプル文字列のため、実際の接続には使えません。実際のパラメーターはサブスクリプションまたはサービス提供元の管理画面で確認してください。サーバーアドレスだけを置き換え、ほかの項目をそのまま使わないでください。

proxies:
  - name: "SS-サンプル"
    type: ss
    server: 192.0.2.10
    port: 8388
    cipher: aes-128-gcm
    password: "demo-only-not-a-real-password"
    udp: true

nameは後続のポリシーグループから参照する識別名です。serverとportには接続先のサーバーとポートを指定します。cipherとpasswordはサーバー側の設定と一致させてください。ここにある8388はサーバー側のポートで、ローカル側の7890とは別のものです。

udp: trueは、そのノードで対応するUDP通信を許可する設定です。通信経路全体でUDPが必ず使えることを保証するものではありません。結果はサーバー、プロトコル、通信の取り込み方法、接続先のネットワークによって変わります。ほかのプロトコルにはそれぞれ異なる項目があるため、VMess、VLESS、Trojanのパラメーターをtype: ssの下に設定しないでください。

ノード名の重複を避ける

地域と用途を組み合わせるなど、判別しやすく安定した名前を付け、重複しないようにしましょう。サブスクリプションの更新でノード名が変わると、手動で設定したポリシーグループから古い名前を参照できなくなることがあります。ノード数が多い場合は、proxy-providersでノードの取得元を管理する方法もあります。これはノードを管理する機能であり、照合条件を管理するrule-providersとは別のものです。

proxy-groups:ノードをまとめてルールから参照する

実際のノードをproxiesに追加したら、ポリシーグループにも登録します。以下のグループは、前のセクションで設定したノード名を参照しています。有効なノード情報に置き換えて初めて、選択した項目で接続できるようになります。

proxy-groups:
  - name: "手動選択"
    type: select
    proxies:
      - "SS-サンプル"
      - DIRECT

selectは手動選択型のグループです。通常、クライアントの「プロキシ」またはポリシーグループ画面に表示され、メンバーを選ぶと接続先が決まります。初回読み込み時に以前の選択がなければ、通常はリストの先頭が使われます。選択状態の永続化が有効な場合は、再読み込み後に先頭ではなく、前回の選択が復元されることがあります。

グループの種類選択基準使用時の注意
selectユーザーがメンバーを手動で選択まずノードを検証し、その後、接続先を固定したい場合に適しています。
url-test指定したテストURLへの接続確認結果テストで計測した遅延は、すべてのWebサイトでのダウンロード速度を示すものではありません。
fallbackメンバーの順に、利用可能なものを選択主回線と予備回線の切り替え向けで、常に最も遅延の小さいものを選ぶ方式ではありません。
load-balance設定したポリシーに従って接続を振り分け1つのダウンロード接続の帯域幅を単純に合算する機能ではありません。

ポリシーグループから別のポリシーグループを参照することもできますが、循環参照はできません。たとえば「日常用の接続先」から「手動選択」を参照するのは問題ありませんが、両者が互いを参照する設定は避けてください。proxy not foundのようなエラーが出たら、名前が一致しているか、参照先が実際に定義されているかをまず確認します。

rule-providersとrules:ルールセットの定義と照合順

設定例のlocal-demoはインラインルールセットです。behavior: classicalは、ルール種別を含む形式で記述することを示します。DOMAIN-SUFFIX,example.orgはexample.orgそのものと、そのサブドメインに一致します。ルールセットが保持するのは照合条件です。最終的な接続先は、rulesに記述するRULE-SET,local-demo,DIRECTで指定します。

3種類のルールセットのbehaviorは混同しない

  • classical:DOMAIN-SUFFIX,example.orgのように、ルール種別を含む形式で記述します。
  • domain:ドメイン名または対応するドメイン照合式を記述します。classical形式の行をそのまま使うことはできません。
  • ipcidr:192.168.0.0/16のようなIPアドレス範囲を記述します。

type: httpに変更する場合は、実際にアクセスできるurlに加え、使用する形式に応じたキャッシュパスや更新間隔などの項目も設定します。たとえばinterval: 86400は86400秒、つまり24時間を表します。取得するデータは、指定したbehaviorと形式に合っている必要があります。ダウンロードできたからといって、必ず解析できるとは限りません。

rulesは上から照合し、最初に一致した時点で終了する

例の1行目はexample.comに完全一致した接続を直接接続にします。2行目でルールセットを参照し、続いていくつかのローカルネットワークを処理した後、最後のMATCH,手動選択で残りを振り分けます。MATCHはほかのルールに一致しなかった接続をすべて受け取るため、必ず最後に置いてください。先頭に置くと、後続のルールが照合されません。

rules:
  - DOMAIN,example.com,DIRECT
  - DOMAIN-SUFFIX,example.org,手動選択
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - MATCH,手動選択

DOMAINはドメイン名への完全一致、DOMAIN-SUFFIXはドメインの後方一致です。混同しないでください。IPルールに付けるno-resolveは、そのルールの判定だけを目的にドメイン名を新たに解決しない指定です。接続に宛先IPアドレスがすでに含まれている場合は、そのIPで照合できます。DNS全体を無効にする設定でも、対象ネットワークを必ず直接接続にする追加指定でもありません。

また、ルールにGEOIPやGEOSITEを使うと、対応する地理情報データが必要になります。この記事の最小構成例では、初回読み込み時にデータファイルの不足や更新失敗に左右されないよう、これらのルールを使用していません。

保存・検証・読み込み:3ステップでエラーを切り分ける

ステップ1:カーネルで構文と参照先を確認する

mihomoを単体でインストール済みの場合は、設定ファイルのあるディレクトリで以下のコマンドを実行します。Windows PowerShellでは、カレントディレクトリにあるプログラムを通常.\mihomo.exeと指定します。実際の実行ファイル名は環境に合わせてください。

mihomo -t -f ./config.yaml

# Windows PowerShell
.\mihomo.exe -t -f .\config.yaml

検証に通ったことが示すのは、現在のカーネルが設定を受け付けるという点だけです。ノードの稼働状況、パスワードの正しさ、DNSへの到達性は保証されません。コマンドでの検証は成功してもクライアントで失敗する場合は、両者で同じカーネルと設定ファイルを使っているか、クライアント側で別の設定が追加されていないかを確認してください。

ステップ2:読み込み後に実際の設定値を確認する

  1. クライアントの「設定」画面でローカルのYAMLをインポートし、その設定を選択します。画面に「編集」がある場合は、変更を保存してから設定を再読み込みしてください。
  2. 「プロキシ」画面で「手動選択」グループを開き、メンバーがあることを確認します。実際のノードをまだ追加していない場合は、DIRECTのままにしてください。
  3. 動作モードを「ルール」に設定し、実際に使用するmixed-portが7890か確認してください。メニュー名はクライアントによって多少異なる場合があります。
  4. プロキシ経由になるよう明示したリクエストでテストし、「接続」画面と「ログ」画面を確認してください。ブラウザーでWebページが開けるかどうかだけでは判断できません。
curl -I --proxy http://127.0.0.1:7890 https://example.com

# Windowsではコマンド名の違いを避けるためcurl.exeを使用
curl.exe -I --proxy http://127.0.0.1:7890 https://example.com

このリクエストは、設定例ではDOMAIN,example.com,DIRECTに一致します。HTTPレスポンスを受信できるかどうかは、ローカルネットワークの状態にも左右されます。ルールが正しいかを判断するには、「接続」の詳細に表示されるルールと最終的な接続先を優先して確認してください。このコマンドで検証できるのはHTTPプロキシの入口であり、TUNやシステムDNSの取り込み状態ではありません。

ステップ3:エラーの種類に応じて確認し、一度に複数箇所を変更しない

症状まず確認する項目次に行うこと
YAMLの解析に失敗するインデント、タブ、コロン、引用符エラー行とその1つ前の行を見直し、設定の検証を再実行します。
ノードまたはポリシーが見つからないグループ名とノード名が完全に一致しているか定義から名前をコピーし、手入力による違いを避けます。
ポートの待ち受けに失敗する7890または1053が使用中か競合しているプログラムを終了するか、両方の設定をそろえて変更します。
ルールに一致しないルールモードか、接続がカーネルを経由しているか先行するルールを確認し、既存の接続を終了してから再試行します。
ルールは正しいのに接続がタイムアウトする選択中のノード、認証情報、接続先ネットワークノードを1つに固定してテストし、ルールの問題か回線の問題かを切り分けます。