Clash APIで自動切替を始める前の前提

Clash APIを使うと、GUIを開かなくても現在のプロキシグループ、選択中のノード、接続状態を確認し、必要に応じてグループのメンバーを切り替えられます。ノード障害や急激な速度低下を検知したときにスクリプトから操作できるため、常時稼働する小型サーバー、開発用PC、ホームゲートウェイのような環境と相性が良い方法です。ただし、APIは単なる便利なリモコンではありません。管理ポートをネットワークへ公開したままにすると、第三者がプロキシ設定を変更したり、接続先を悪用したりする可能性があります。まずはループバックアドレスだけで待ち受けること、認証キーを設定すること、そしてスクリプト以外からアクセスできないファイアウォール構成にすることを優先してください。

Clash Verge、Clash Verge Rev、Mihomo系クライアントでは、設定画面に「外部コントローラー」「External Controller」「API」などの名前で管理ポートが表示されます。実際の項目名や既定ポートはビルドによって異なるため、画面に表示されている値を正とします。代表的な設定は次のような形ですが、購読プロファイルを直接編集すると更新時に消えることがあるため、自分のローカルオーバーライドや永続設定へ記述してください。

external-controller: 127.0.0.1:9090
secret: "change-this-to-a-long-random-token"

接続確認には、まず現在のプロキシグループを取得します。APIのパスはコアの実装によって多少の差があるものの、MihomoやClash互換コアでは /proxies が基本的な入口になります。認証が有効な場合は、リクエストヘッダーに Authorization: Bearer を付けます。レスポンスが返らないときは、ノードの問題を疑う前に、管理ポートのアドレス、ポート番号、secret、ローカルファイアウォールを順番に確認してください。

curl -s \
  -H "Authorization: Bearer change-this-to-a-long-random-token" \
  http://127.0.0.1:9090/proxies
ℹ 安全な境界:APIポートを 0.0.0.0 で公開する構成は、LAN内だけのつもりでもゲスト端末やポート転送経由で露出しやすくなります。遠隔管理が必要な場合は、まずVPNやSSHトンネルで管理経路を作り、API自体はローカル待ち受けのままにする方が安全です。

プロキシグループを読み取り、切替対象を決める

自動切替で最初に迷うのは、ノード名を直接指定するのか、それとも select、url-test、fallback のようなプロキシグループを操作するのかという点です。スクリプトからは、原則として実際にルールから参照されている親グループを切り替えます。たとえばルールが PROXY というグループを使っているなら、APIでも PROXY を対象にします。個別ノード名だけを変更しても、通信が別の親グループへ流れていれば見た目だけが変わり、実際の経路は変わりません。

/proxies のレスポンスには、グループごとの種類、現在の選択値、候補となるメンバーが含まれます。スクリプトは人間が読む表示名に頼りすぎず、対象グループの type と all または proxies の配列を確認してから処理します。購読更新でノード名に地域名や番号が追加されることがあるため、「東京」という完全一致だけで判断すると、名前変更後に候補がゼロになることがあります。必要なら正規表現、遅延値、除外語、ノード数を組み合わせて候補を作ります。

切替対象を選ぶときは、単発の ping だけでなく、実際に利用するサービスへ近い測定を考えます。Clashの遅延テストは指定URLへ軽量なリクエストを送るだけなので、動画、Git、API、社内サービスなど、目的によって結果の意味が変わります。また、測定URLが落ちていると全ノードが悪く見えるため、固定の一つだけではなく、必要に応じて複数の観測先を用意し、DNS失敗、TLS失敗、HTTPステータス、応答時間を別々に記録すると判断を誤りにくくなります。

curl -s -X PUT \
  -H "Authorization: Bearer $CLASH_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"name":"Node-A"}' \
  http://127.0.0.1:9090/proxies/PROXY

APIで切替を実行した直後は、書き込み成功だけで完了と判断しません。もう一度対象グループを取得し、選択値が期待するノードになったかを確認します。そのうえで短い疎通テストを行い、切替後も失敗する場合は別ノードへ進めます。これにより、APIのHTTPステータスは成功したものの、コアの再接続や上流のTLS確立がまだ終わっていない状態を、正常復旧と誤認せずに済みます。

Pythonスクリプトで遅延判定とフォールバックを組み立てる

自動切替の基本構造は、候補を取得する → 各候補を測定する → 条件を満たすノードを選ぶ → APIで切り替える → 結果を再確認するという五段階です。下の例は考え方を示す最小構成であり、URL、グループ名、閾値、ノード名の判定は自分の環境に合わせて変更します。実運用では、スクリプト自身がプロキシ経由になると測定結果が意図せず現在のClash経路へ依存するため、API操作のHTTPクライアントと外向きの測定経路を分けて考えてください。

#!/usr/bin/env python3
import os
import time
import requests

BASE = "http://127.0.0.1:9090"
GROUP = "PROXY"
SECRET = os.environ["CLASH_SECRET"]
HEADERS = {"Authorization": f"Bearer {SECRET}"}
TARGET = "https://www.gstatic.com/generate_204"

def get_group():
    data = requests.get(f"{BASE}/proxies/{GROUP}",
                         headers=HEADERS, timeout=5)
    data.raise_for_status()
    return data.json()

def switch_node(name):
    response = requests.put(
        f"{BASE}/proxies/{GROUP}",
        headers={**HEADERS, "Content-Type": "application/json"},
        json={"name": name},
        timeout=5
    )
    response.raise_for_status()

group = get_group()
candidates = group.get("all", [])
for node in candidates:
    if "故障" in node or "Expired" in node:
        continue
    try:
        switch_node(node)
        time.sleep(3)
        probe = requests.get(TARGET, timeout=8)
        if probe.status_code in (200, 204):
            print(f"selected: {node}")
            break
    except requests.RequestException:
        continue
else:
    print("no healthy node found")
    raise SystemExit(2)

この例をそのまま短い間隔で実行すると、同じノードを何度も切り替えたり、サービス側のセッションを頻繁に変えたりする危険があります。そこで、成功したノードと時刻を状態ファイルへ保存し、一定時間は再評価しないクールダウンを設けます。また、一回の失敗で即切替するのではなく、連続二回または三回の失敗を障害とみなし、短時間のネットワーク揺らぎを無視します。切替後の待機時間も固定値だけにせず、接続ログが落ち着くまで少し余裕を持たせると、切替ループが起きにくくなります。

さらに安全性を高めるには、ノードを「正常」「一時失敗」「隔離中」の三つの状態で管理します。最初の失敗では一時失敗にとどめ、一定時間内に再度失敗した場合だけ隔離中へ移します。隔離期間が過ぎたら候補へ戻し、復旧したかを再測定します。この方式なら、混雑する時間帯に一時的に遅くなったノードを永久に捨てずに済みます。ログには secret や購読URLを絶対に書かず、ノード名も必要に応じて一部をマスクしてください。

定期実行、監視、障害時の復旧手順

定期実行には Linux の systemd timer や cron、macOS の launchd、Windows のタスクスケジューラを使えます。最初は一分ごとのような短周期ではなく、五分から十五分程度の間隔で始め、切替頻度とログ量を観察します。速度を常時計測したい場合でも、測定URLへ大量のリクエストを送る設計は避けてください。プロバイダや接続先から自動化通信として扱われる可能性があり、ネットワークにも不要な負荷を与えます。

環境変数にsecretを渡す場合は、シェルの履歴、プロセス一覧、CIのログ、バックアップへ漏れないようにします。systemdなら専用の環境ファイルの権限を絞り、Windowsなら資格情報や保護されたタスク設定を利用します。スクリプトの終了コードも運用上重要です。切替成功はゼロ、候補なしやAPI認証失敗は非ゼロにして、監視側が「何も起きなかった」のか「自動復旧に失敗した」のかを区別できるようにしてください。

トラブルシューティングでは、最初に三つのログを同じ時刻で照合します。第一はスクリプトの実行ログ、第二はClashの接続ログ、第三はOSまたはジョブ実行基盤のログです。401 ならsecretやAuthorizationヘッダー、404 ならAPIパスやグループ名、409 や類似の応答ならコアが切替処理中でないかを確認します。API自体が応答しても外向き通信が失敗する場合は、ルール順、DNSモード、TUNとシステムプロキシの二重適用、別VPNの常駐を切り分けます。

⚠ 切替ループに注意:測定URLが現在のノードを経由している構成で、失敗するたびに別ノードへ移ると、どの候補も安定する前に切替が続くことがあります。連続失敗回数、最低保持時間、最大切替回数を設定し、上限を超えたら自動操作を停止して最後の状態を保持してください。

運用開始後は、月に一度でもスクリプトを手動で実行し、Clashのアップデートや購読更新でAPIパス、グループ名、ノード表示名が変わっていないか確認します。特に購読サービスがグループ構成を置き換えるタイプでは、手動で追加したグループが消えることがあります。構成のバックアップ、変更前後の差分、最後に成功したノードを残しておけば、全候補が失敗した場合でも元の設定へ戻しやすくなります。自動化は「放置する仕組み」ではなく、異常を検知して人間が判断しやすい状態へ整える仕組みとして設計するのが現実的です。

GUIだけでノードを選ぶ運用は簡単ですが、障害発生時の判断履歴や再試行条件を残しにくく、単純な自動選択グループだけでは特定サービスの失敗やAPI認証の異常まで扱えません。Clash V.COREなら、APIによるグループ操作、Mihomo系コアとの互換性、ログを見ながらのルール調整を一つの運用にまとめやすく、今回のような自動切替スクリプトを段階的に試せます。まずは安全なローカルAPIと少数の候補で検証し、環境に合うことを確認したうえでダウンロードページから導入してください。