Security & Privacy · Clash Technical Blog

How to Access the Clash Dashboard Remotely and Safely

Dashboard connects to a control interface that can switch nodes, change configuration, and close connections. For remote use, restrict the listen address, set a secret, and access it only through a private network or tunnel.

  • Security
  • Dashboard
  • secret
On this page

A remote panel does more than display traffic: it connects to a control interface that can change configurations and close connections. An open page does not establish a secure connection to that interface. Check the listening scope, authentication, and web origins separately; origin restrictions do not replace authentication. Verify that requests with no credentials or incorrect credentials are rejected before choosing a temporary tunnel or a lasting remote-access method.

Dashboard Can Change Configuration: How to Restrict Access

Check the actual listening port, such as 9090, and who can reach it in the external-controller settings. Clash Dashboard uses this REST API to read connections, traffic, proxy groups, and rules. It can also switch nodes, reload configurations, change some runtime settings, and close connections. Exposing it directly to the internet is far riskier than exposing a read-only status page.

Access scenarios and recommended entry points

ScenarioListening methodAccess restrictions
Panel bundled with a local client127.0.0.1:9090A strong secret, preventing arbitrary web pages from calling the local interface
Administration from the home LANAn explicit LAN address or restricted listenerThe firewall allows only management devices or private subnets
Temporary maintenance from another locationContinue listening only on the local machineSSH local forwarding, optionally established over Tailscale
Public internet serviceDirect exposure is not recommendedAt minimum, use a separate reverse proxy, TLS, authentication, and source restrictions

Configure and Test Local Listening and secret Authentication

In the final active Mihomo configuration, bind external-controller to 127.0.0.1. A graphical client may generate this field through “Settings → External Controller” or an override file, so editing the raw subscription may have no effect. After reloading, inspect both the final configuration and the actual listener.

REPLACE_WITH_RANDOM_SECRET is a placeholder. Generate a long random value with a password manager, replace it in the Mihomo configuration and Dashboard connection settings, then reload. Do not use the example placeholder as a password.

A starting point for a local-only Dashboard
external-controller: 127.0.0.1:9090
secret: "REPLACE_WITH_RANDOM_SECRET"
Confirm what is listening on 9090
# Windows PowerShell
Get-NetTCPConnection -LocalPort 9090 -State Listen

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

secret is the Bearer Token for the TCP controller discussed here. An empty value provides no authentication at this layer, short passwords are easier to guess, and reuse across devices increases the impact of a leak. Keep the full token out of screenshots, frontend repositories, and public troubleshooting logs.

Test no credentials, incorrect credentials, and correct credentials separately
# 无 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

Results that prove authentication works

  • A request without Authorization returns 401 rather than version JSON
  • The correct secret can read /version
  • An incorrect secret is also rejected
  • Dashboard shows connections and proxy groups correctly after a refresh
  • Neither the logs nor the browser address bar exposes the secret

If Dashboard will not open, do not immediately allow every CORS origin

A remotely hosted Dashboard is a web origin that sends requests to external-controller from the browser. CORS restricts which web origins can call the interface; it does not replace user authentication.

Setting allow-origins to * and also allowing private network requests makes it easier for any website to attempt access to local or LAN controller ports. Even with a secret configured, the blast radius is larger if it leaks.

First confirm the Dashboard's actual origin, such as https://dashboard.example.com, and allow only that complete origin. A change in the domain, scheme, or port creates a different origin. The UI static-file path in the configuration and the API listening address are also separate: a page that opens does not mean the control API is connected securely.

Replace the example domain with the actual Dashboard origin
external-controller-cors:
  allow-origins:
    - "https://dashboard.example.com"
  allow-private-network: false

For temporary remote maintenance, use an SSH tunnel to bring 9090 to the local machine

If Mihomo runs on a home server, keep external-controller on 127.0.0.1:9090 and use SSH local forwarding to map the remote loopback port to the current computer. The browser still connects to its own 127.0.0.1, while 9090 remains invisible to the public internet.

Example: map the remote controller to local port 19090
ssh -N -L 19090:127.0.0.1:9090 [email protected]

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

After connecting to the server over Tailscale, still use the SSH forwarding above to reach a controller that listens only on loopback. Joining the tailnet does not automatically expose that port. Use tailnet policy to restrict which users or devices can reach the host and the port needed for forwarding, and keep the secret.

If a home router must listen on a LAN address, allow only the management computer through the firewall, not Guest Wi-Fi or the entire WAN zone.

Secure access path for a remote administration panel
  1. Your browserInitiate access only from a trusted device
  2. SSH forwarding (optionally over a VPN)Do not expose the controller port directly
  3. 127.0.0.1:9090external-controller listens only on the local machine
  4. MihomoValidate control requests with a secret

If listening on a LAN address is unavoidable, also restrict firewall sources and keep a sufficiently long secret.

What Reverse-Proxy Protection Does Long-Term Remote Access Need?

Deploy a reverse proxy only when you need a stable domain and long-term remote access. Mihomo's external-controller should still listen on 127.0.0.1:9090, while Nginx, Caddy, or another gateway on the same host serves HTTPS externally. Expose only the reverse-proxy port to the public internet, not 9090.

The reverse proxy should have at least valid TLS, a separate sign-in or client authentication, source restrictions, access logs, and correct forwarding for the WebSocket used by Dashboard. Keep Mihomo's secret as well; it and reverse-proxy authentication are two independent layers and cannot replace each other. Store the secret in Dashboard connection settings instead of appending it to a public URL.

If the Dashboard page and API use different domains, add the page's exact origin to CORS. After configuring it, test with an external port scan or from another device: the HTTPS domain should present a sign-in, while direct access to the server's public IP:9090 should fail to connect.

Check Controller Authentication and Access from Unauthorized Networks

Complete acceptance checks

  1. Inspect the listener locally

    Confirm that the port is bound to the intended address and that the process is the current Mihomo instance rather than an old one.

  2. Unauthenticated access

    Use curl to request /version and confirm that a missing or incorrect token returns 401.

  3. Authenticated access

    Open Dashboard, switch one test policy group, and confirm that Mihomo shows the same result.

  4. Test from a network without permission

    Test from a LAN, Guest Wi-Fi, or public address that should not have access; the connection should time out or be refused.

  5. Restart and retest

    After restarting Mihomo, confirm that the client did not overwrite the listening address, secret, or firewall rules.

If the controller may have been exposed, first tighten the listener and firewall, then rotate the secret. Next, inspect port mappings, cloud security groups, reverse-proxy access logs, and configuration-repository history. Changing only the Dashboard password cannot invalidate a leaked Bearer Token.

References