セキュリティとプライバシー · Clash 技術ブログ

Clash Dashboard へ安全にリモートアクセスする方法

Dashboard が実際に接続するのは、ノードの切り替え、設定の変更、接続の終了が可能な制御インターフェースです。リモートから使う場合は、まずリッスンアドレスを制限して secret を設定し、その後 LAN またはトンネル経由でアクセスしてください。

  • セキュリティ
  • Dashboard
  • secret
目次

リモートのパネルは通信量を見るだけではなく、設定の変更や接続の終了ができる制御インターフェースにつながっています。ページが開いても、そのインターフェースに安全に接続できているとは限りません。待ち受け範囲、認証の設定、ウェブページのオリジンを個別に確認し、オリジンの制限で認証を代用しないようにします。認証情報がないリクエストと誤った認証情報のリクエストがどちらも拒否されることを確かめてから、一時的なトンネルか継続的なリモートアクセス方法を選びましょう。

構成を変更できる Dashboard のアクセス制限

external-controller の設定で、9090 などの実際の待ち受けポートと、アクセスできる範囲を確認します。Clash Dashboard はこの REST API で接続、通信量、プロキシグループ、ルールを読み取り、ノードの切り替え、設定の再読み込み、一部の動作設定の変更、接続の終了も行えます。インターネットに直接公開するリスクは、読み取り専用の状態ページよりはるかに高くなります。

アクセス場面と推奨する入口

状況リッスン方法アクセス制限
ローカルクライアントに同梱されたパネル127.0.0.1:9090強力な secret を設定し、任意のウェブページからローカルインターフェースを呼び出せないようにする
家庭内 LAN からの管理明示した LAN アドレスまたは制限付きのリッスンファイアウォールで管理デバイスまたはプライベートサブネットだけを許可
別の場所から一時的に保守引き続きローカルホストだけでリッスンSSH のローカルポート転送を利用し、必要なら Tailscale 経由で接続する
公開インターネット向けサービス直接公開は推奨しない少なくとも独立したリバースプロキシ、TLS、認証、接続元制限が必要

ローカル待ち受けと secret 認証の設定・テスト

最終的に有効となる Mihomo 設定で、external-controller を 127.0.0.1 にバインドします。GUI クライアントでは、「設定 → 外部コントローラー」またはオーバーライドファイルからこのフィールドを生成する場合があるため、元のサブスクリプションを編集しても反映されるとは限りません。再読み込み後に、最終設定と実際のリッスン状態を確認してください。

REPLACE_WITH_RANDOM_SECRET は仮の値です。パスワードマネージャーで長いランダム値を生成し、Mihomo の設定と Dashboard の接続設定の両方に入れて再読み込みします。例の仮の値をパスワードにしないでください。

ローカルの Dashboard 専用の開始設定
external-controller: 127.0.0.1:9090
secret: "REPLACE_WITH_RANDOM_SECRET"
9090 で待ち受けているプロセスを確認する
# Windows PowerShell
Get-NetTCPConnection -LocalPort 9090 -State Listen

# Linux / OpenWrt
ss -lntp | grep ':9090'

secret はこの記事で扱う TCP 制御インターフェースの Bearer Token です。空の値ではこの認証がなく、短いパスワードは推測されやすくなります。複数機器で使い回すと漏えいの影響も広がります。完全な token をスクリーンショット、フロントエンドのリポジトリ、公開の障害ログに載せないでください。

認証情報なし、誤った認証情報、正しい認証情報を個別にテストする
# 无 Authorization,应返回未授权,而不是接口数据
curl -i http://127.0.0.1:9090/version

# 错误 token 也必须被拒绝
curl -i -H "Authorization: Bearer WRONG_TOKEN" http://127.0.0.1:9090/version

# 只在自己的终端中替换 REAL_TOKEN
curl -i -H "Authorization: Bearer REAL_TOKEN" http://127.0.0.1:9090/version

認証が機能していることを示す結果

  • Authorization なしのリクエストでバージョン JSON ではなく 401 が返る
  • 正しい secret で /version を読み取れる
  • 誤った secret も拒否される
  • Dashboard を更新すると接続とプロキシグループが正常に表示される
  • ログとブラウザのアドレスバーに secret が露出していない

Dashboard を開けない場合も、CORS を任意のオリジンへいきなり許可しない

リモートでホストされた Dashboard は、ブラウザから external-controller へリクエストを送るウェブオリジンです。CORS はインターフェースを呼び出せるウェブオリジンを制限するだけで、ユーザー認証の代わりにはなりません。

allow-origins を * に設定し、さらにプライベートネットワークへのリクエストを許可すると、任意のウェブページからローカルまたは同一ネットワーク内のコントローラーポートへのアクセスを試みやすくなります。secret を設定していても、漏えいした場合の影響範囲は広がります。

まず Dashboard の実際の origin(例: https://dashboard.example.com)を確認し、その完全な origin だけを許可します。ドメイン、プロトコル、ポートのいずれかが変われば、別の origin になります。設定内の UI 静的ファイルのパスと API のリッスンアドレスも別物です。ページが開くからといって、コントロール API が安全に接続されているとは限りません。

サンプルドメインを実際の Dashboard origin に置き換える
external-controller-cors:
  allow-origins:
    - "https://dashboard.example.com"
  allow-private-network: false

一時的なリモート保守には SSH トンネルを使い、9090 をローカルへ転送する

Mihomo を自宅サーバーで動かす場合は、external-controller を 127.0.0.1:9090 のままにし、SSH ローカルポートフォワーディングでリモート側のループバックポートを現在のコンピューターへ転送できます。ブラウザは引き続き自身の 127.0.0.1 にアクセスし、公開インターネットから 9090 は見えません。

例: リモートコントローラーをローカルの 19090 に転送する
ssh -N -L 19090:127.0.0.1:9090 [email protected]

# Dashboard 后端填写
http://127.0.0.1:19090

Tailscale 経由でサーバーに接続しても、ループバックだけで待ち受けるコントローラーには上記の SSH 転送を使ってアクセスします。tailnet に参加しただけでは、このポートは公開されません。tailnet policy でホストと転送に必要なポートへ接続できるユーザーや端末を制限し、secret も残してください。

家庭用ルーターで LAN アドレスの待ち受けが必要な場合は、管理用パソコンだけをファイアウォールで許可し、Guest Wi-Fi や WAN zone 全体は許可しないでください。

リモート管理パネルへ安全にアクセスする経路
  1. 使用中のブラウザ信頼できるデバイスからのみアクセスする
  2. SSH 転送(VPN 経由でも接続可能)コントローラーポートを直接公開しない
  3. 127.0.0.1:9090external-controller はローカルホストだけでリッスン
  4. Mihomosecret でコントロールリクエストを検証

LAN アドレスでのリッスンが避けられない場合も、ファイアウォールで接続元を制限し、十分に長い secret を設定してください。

継続的なリモートアクセスに必要なリバースプロキシの保護

固定ドメインと長期的なリモートアクセスが必要な場合に限り、リバースプロキシの導入を検討します。Mihomo の external-controller は引き続き 127.0.0.1:9090 でリッスンし、同じホスト上の Nginx、Caddy、または別のゲートウェイが外部向けに HTTPS を提供します。公開インターネットにはリバースプロキシのポートだけを開放し、9090 は開放しません。

リバースプロキシには、少なくとも信頼できる TLS、独立したログインまたはクライアント認証、接続元の制限、アクセスログを用意し、Dashboard が使用する WebSocket も正しく転送する必要があります。Mihomo の secret も残してください。secret とリバースプロキシのログインは独立した二層の保護であり、互いの代わりにはなりません。secret は公開 URL に付加せず、Dashboard の接続設定に保存します。

Dashboard のウェブページと API が異なるドメインを使用する場合は、実際のページの origin を CORS に正確に追加します。設定後は、公開インターネットからのポートスキャンまたは別のデバイスでテストしてください。HTTPS ドメインではログインでき、サーバーの公開 IP:9090 へ直接アクセスすると接続に失敗する状態が正解です。

コントローラーの認証と、許可されていないネットワークからのアクセス結果を確認する

総合検証

  1. ローカルでリッスン状態を確認

    ポートが想定したアドレスにバインドされ、プロセスが古いインスタンスではなく現在の Mihomo であることを確認します。

  2. 未認証アクセス

    curl で /version をリクエストし、token がない場合も誤っている場合も 401 が返ることを確認します。

  3. 認証済みアクセス

    Dashboard を開いてテスト用のポリシーグループを切り替え、Mihomo 側にも同じ結果が反映されることを確認します。

  4. 権限のないネットワークからテスト

    アクセス権を持たないはずの LAN、Guest Wi-Fi、または公開アドレスからテストし、接続がタイムアウトするか拒否されることを確認します。

  5. 再起動して再テスト

    Mihomo を再起動した後、リッスンアドレス、secret、ファイアウォールルールがクライアントによって上書きされていないことを確認します。

コントローラーが公開されていた可能性がある場合は、まずリッスン範囲とファイアウォールを絞り、その後 secret をローテーションします。続いて、ポートマッピング、クラウドのセキュリティグループ、リバースプロキシのアクセスログ、設定リポジトリの履歴を確認してください。Dashboard のパスワードだけを変更しても、漏えいした Bearer Token は無効になりません。

参考資料