1. 症状のパターン(タイムアウト・接続拒否・401)
まずはブラウザの挙動を言葉に落とすと、切り分けが速くなります。
- 接続は試みられるが最後まで待てない:多くの場合は、コアは起動しているが、指定した IP:ポート に HTTP サーバが生えていない、あるいは ファイアウォールで到達できないパターンです。別のポートに本当は生えている、というミスが典型です。
- 接続を拒否された(すぐ失敗):
127.0.0.1以外の機器から、127.0.0.1だけに束縛したプロセスへアクセスしようとしている、あるいは プロセスが落ちた直後に叩いている、などです。 - HTTP 401 や、パネルが「認証が必要」として止まる:secret(または同等の トークン)が空なのにクライアントが送っている、逆に YAML 側に長い secret があるのに、パネルに打ち込んでもいない、といった不整合が多いです。REST クライアントでは
Authorization: Bearer形式が要求される実装もあり、パネルごとに要確認です。
以降では、external-controller という 1 本の「管理用 HTTP エンドポイント」の聞いている相手(bind-address)と鍵(secret)を、設定ファイル上で揃える手順に集中します。プロキシ本丸(mixed-port や port、socks-port 等)の乱数ミスと取り違えないでください。前者は トラフィック、後者は API/パネル です(名称と役割の対応表は、当サイト ドキュメントの用語解説と併読しやすいです)。
2. external-controller(Clash 外部コントローラ)の意味
Clash 外部コントローラは、コア(clash プロセス)が HTTP で REST 風の API を出す受け口の総称で、実体の設定名はコアの世代やフォーク(Clash Premium、Clash Meta、Mihomo 等)でやや違います。いずれの場合も、ここにWeb ダッシュボード(yacd、metacubexd 等)のフロントが、ブラウザから /proxies や /version へ話しかける相手先になります。GUI 付きクライアント(Clash Verge 等)は、内部 API 呼び出しのために、裏で同じ external-controller を使うか、別途 抽象化するかは実装次第ですが、YAML を直接編集する運用であれば、まず external-controller の行にどの URL 相当の待受が出ているかを目で追うのが近道です。
用語の整理として、「Clash 外部コントローラ=external-controller キーで指定する、管理用の ip:port あるいは host:port 相当」として読み進めてください。一部ドキュメントでは bind-address を分離して説明し、ポート だけ external-controller に書かせる、という書式も流行しています。いずれにせよ、最終的に「どのローカル/グローバル IP のどの ポートが開くか」が一貫していればよい、という点は共通です。
3. YAML に書く external-controller とポート番号
最も分かりやすい表記のひとつは、ip:port または host:port 形式の1 行に、待受 アドレスと番号をまとめて書く形です。例(あくまで学習用の骨格。実装・バージョンで読み違いが出るなら、公式例に合わせてください)。
# Example skeleton — match your Clash / Mihomo version docs
external-controller: 127.0.0.1:9090
secret: "choose-a-long-random-string"
# If split style is used in your build:
# bind-address: "*"
# external-controller: :9090
ここで ポート は 9090 である例によく出ますが、常に 9090 であるわけではありません。他プロセス(別の プロキシ や、開発サーバ、システム予約等)と衝突して GUI が黙って別の番号へ逃がしている、という事故も少なくないです。実際の設定を開いて最終行を確認し、クライアント起動直後のログ(「listening on ...」風の行)に出ている数値を正にしてください。Linux で systemd 常駐のときも、同一ホスト上で 2 つのユニットが同じ external-controller を奪い合うと、片方は起動失敗するので注意です。
IPv6 や :: の取り扱い
環境によっては [::]:9090 のように IPv6 側にだけ生える、0.0.0.0 だけだと 二重で片方失敗、といった挙動があります。ブラウザが localhost を IPv6 優先で解釈し、リッスンは 127.0.0.1 だけ、という取り違いもゼロではありません。迷ったら http://127.0.0.1:(ポート)/ を数字の IPv4 で直打ちし、http://[::1]:(ポート)/ も比較すると切り分けしやすいです。
4. bind-address:127.0.0.1 だけ? LAN に開く?
bind-address(あるいは external-controller 行に焼き込まれた IP 部分)が、127.0.0.1 または localhost 相当に限られているとき、そのマシン上のブラウザなら到達しやすい一方、同じ LAN 内のスマートフォンや、リモートのノート PC から 192.168.x.x:9090 のようには届きません。これは仕様上の安全設計として妥当で、意図せず外に API を晒す事故を減らす効果があります。
同じ家の別端末から Web パネルを見たいなら、0.0.0.0 や * といった ワイルドな待受(実装表記差あり)+OS ファイアウォール上で当該ポートだけ信頼する相手(同一サブネット等)に制限する、という二段が現実的です。Windows の場合は、LAN とファイアウォールの解説に沿った整理が、到達性の話と併用しやすいでしょう。public IP から 平文の 9090 を直接開く、secret だけ信じる、は極力避けるのが本稿の立場です(SSH トンネル、VPN 内だけ開く、HTTPS 前方に正規の終端、など上の層を検討してください)。
Windows と WSL、Docker の罠
ホスト上の Clash の 127.0.0.1:9090 を、WSL2 内のブラウザから叩こうとすると、127.0.0.1 の指し先が Linux 側のループバックに向いて疎通しない、という定番の誤解があります。WSL2 とホストの記事の通り、resolv.conf や Windows の実 IP、host.docker.internal 等、到達先のモデルを図にしたうえで、bind-address を合わせてください。コンテナ上でコアを動かす場合も、ポート公開(-p 等)の層が1 段挟まる点を落としやすいです。
5. secret 設定と 401 認証エラー
secret キーは、external-controller の HTTP インターフェースに対する、簡易的な 共有鍵として機能します。実装の詳細(ヘッダ名、Bearer か、クエリの secret= か)はクライアントとフロント(パネル)のバージョン差でブレるため、ここでは原則として「YAML に書かれた文字列を、パネルの設定画面に 同一に入力する」ことだけを必須に挙げます。空欄 "" か未設定(実装差あり)のとき、パネルが古いトークンをローカル保存していて、毎回 401 になる、というパターンは、ストレージを消して再入力すると直る、が典型です。
| 画面・ログ上の挙動 | 想定原因 | 先に試すこと |
|---|---|---|
| 常に 401 または Unauthorized | secret 不一致、パネル側の古い保存値 | YAML の値をコピーし、パネルを再設定・キャッシュ消去 |
| パネルは開くが操作だけ失敗 | GET は通るが PUT が拒否、など メソッド制限 | 同じ API ベース URL を他ツールで比較 |
| 一時的に開いてすぐ 401 | 二重起動で片方のコアに当たる | プロセス一覧と、待受ポートの重複を確認 |
また、Clash 外部コントローラ向け Web UI をhttps:// で配信する中継(reverse proxy)の裏に同じ API を乗せる構成では、パスのプレフィックス(/clash 等)の取り扱いをミスると、正しい host:port に見えても、実際の fetch 先は別物、という罠が出ます。そういう層の話は、本稿の YAML 直確認より先に、中継の設定者と握るのが得策です。
6. GUI・プロファイル・上書きの食い違い
多くの GUI は、起動時に「作業中の YAML」を一時的に生成し、コアに流し込みます。手で config.yaml を直した直後、GUI が古い内容で保存し、external-controller 行が元に戻る、secret だけ GUI 側の常連値に戻る、はよくある戸惑いの種です。対策の基本は、一時的に GUI の「設定を書き戻す」手順を止める、どちらを正の編集面にするかを決め、一方に寄せ切ることです。CLI のみ、Linux の systemd 記事のように1 箇所のファイルに責任を集約する、という運用の方が、行間の secret ズレは出にくいです。
7. ファイアウォールと到達性(本機と LAN 以外)
OS 標準の ファイアウォール、サードパーティの セキュリティスイート、企業 MDM のプロファイル、はいずれも「着信の TCP 9090(例)」を黙殺する局面があります。症状は、127.0.0.1 では curl が通るのに、LAN 内の別 PC からだけタイムアウト、など非対称に現れます。ここは bind-address を LAN から到達可能にした「上で」ファイアウォールルールが不足、という 二重条件が満たされているか、を確認します。macOS では、Clash Verge 周辺の拡張の話と、到達性の話は層が違います。混同すると、「プロキシは動くのに API だけ 詰まる」の説明が辻褄合わないまま悩みが延びるので、レイヤを分けて考えてください。
8. Web パネル(ダッシュボード)の「API ベース URL」
ブラウザで使う Web パネル(静的フロント)は、どの http://…:port を「Clash 外部コントローラの根」として使うかを、初回の設定で聞かれることが多いです。ここに https:// や、存在しない パスを多く入れると、UI はロードしてもバックエンドに fetch できず、真っ白のまま、Console だけ CORS 風、など誤解を招きます。まずは、http://127.0.0.1:(YAMLの数字)/ が素の HTTP 200 を返すか、同一マシン上の curl で触ってください。
多くの公式・準公式 UI は、/ui や専用のサブパスを足した URL を ブックマークにしますが、API 本体の host:port とは役割が違います。混ぜると、画面の出どころ(静的ファイル)と、API(external-controller)の対応が分断されたまま、ずっと読み込み中に見える、という罠に落ちがちです。
9. セルフチェックリスト
- 実際に有効な YAML 断片(GUI の「実行中の設定」等)に、external-controller と意図した ポートが1 回で目視できるか。
127.0.0.1から、curl等で/version等の軽い GET が期待通り(401 の意味も一貫)か。- 別端末から叩くなら、bind が LAN から到達可で、ファイアウォール 着信が同ポートに許可か。
- secret があるなら、401 時のヘッダ挙動と、パネルの再入力・キャッシュ掃除をしたか。
- WSL/Docker なら、
127.0.0.1の意味がどの OS かを図にしたか。
10. まとめ
Clash 外部コントローラ(external-controller+secret)の不整合は、プロキシが一見動いていても、Web パネルと自動化だけが壊れている、という形で出やすいです。YAML 上の ポート、bind-address(127.0.0.1 か ワイルド待受か)、401 時の secret、OS のファイアウォール、WSL/コンテナのループバック、GUI の上書き、の六方向を順に揃えれば、タイムアウト・接続拒否・401 の大半は、再現性のある 一段ずつの作業に還元できます。コアのソースや Issue トラッカーは GitHub 上の公式情報で追えますが、クライアントの配布物は、手元の OS に合わせて当サイト ダウンロードページから揃う導線に任せるのが、初動の取り違えを減らしやすいです。
多機能 GUI より、まず API 直叩きで疎通を一発で可視化できる、というのが Clash 系の扱いやすい点でもあり、本トラブルに直面したときの切り分けにも直結します。