Configuration Reference mihomo Core

Advanced Clash Configuration Guide

How proxy groups, rule sets, and network routing fit together.

This page is organized by topic for users who have already imported a subscription and want to adjust routing or network behavior. If you’re new to Clash, first follow the quick-start guide to import a subscription, choose a mode, and verify the connection, then return to the relevant section here. The two pages serve different purposes: the guide covers the steps to follow; this page explains how configuration fields work together, when changes take effect, and where to start troubleshooting.

YAML configuration examples Rules match from top to bottom The effective configuration is authoritative

Proxy Selection / proxy-groups

Proxy group types and actual egress

Proxy groups determine where traffic goes after matching a rule. Proxy in a rule is just a name; it is not a built-in proxy outlet in the core. It must refer to a node or another proxy group. A connection might match an application-specific rule, enter a manually selectable group, then end up on a node in an automatic test group. Understanding this chain of references matters more than creating lots of groups. Before making changes, list the node names provided by your subscription, existing group names, and rule references to avoid duplicate names or unresolved references that prevent the configuration from loading.

Manual selection, automatic testing, and failover

select provides manual control over the egress and is useful when you want to choose it yourself. url-test selects a candidate based on probes to a specified test URL, making it suitable for everyday automatic selection; it measures a particular network path, not the speed of every website. fallback uses available candidates in the configured order. Its purpose is to preserve priority and switch on failure, not to pick the lowest-latency option. These types can be nested, but keep the hierarchy simple and never make two groups reference each other.

load-balance distributes separate connections across candidate nodes; it cannot combine their bandwidth for a single download connection. Services sensitive to account sessions, egress region, or server-side risk controls usually work better with a fixed egress. How traffic is distributed also depends on strategy. For example, consistent-hashing aims to keep a destination mapped to a similar egress, but changing the candidates can still change the result. This does not guarantee a stable identity or public IP address over time.

config.yaml · Proxy group snippet referencing an existing provider
proxy-groups:
  - name: Proxy
    type: select
    proxies:
      - Automatic selection
      - Failover
      - DIRECT

  - name: Automatic selection
    type: url-test
    use:
      - Subscription source
    url: https://www.gstatic.com/generate_204
    interval: 300
    tolerance: 50

  - name: Failover
    type: fallback
    use:
      - Subscription source
    url: https://www.gstatic.com/generate_204
    interval: 300

Node sources, probing, and selection status

The example above requires an existing proxy-providers entry named “Subscription source.” use imports nodes from a provider, while proxies references specific node names, proxy group names, or built-in policies. Providers reduce the need to maintain nodes individually as a subscription changes, but you still need to confirm that the provider file loads successfully. If your client imports a subscription with complete proxy groups, don’t paste in another top-level proxy-groups field with the same name. Merge the lists through an override or by editing the effective configuration.

interval is the probe interval, in seconds. tolerance is the allowed latency difference for automatic selection, in milliseconds, and can reduce frequent switching caused by minor fluctuations. Choose a stable, reachable test URL that reflects the network path you actually use. A successful probe only shows that the probe request completed; it does not prove that a specific website, UDP, or services in every region are working. When troubleshooting, inspect probe connections separately from real traffic.

Provider health checks and proxy group tests are configured in different places. The former tracks node availability; the latter drives selection within a group. To make changes easier to diagnose, don’t change the test URL, interval, filter, and group type all at once. Keep one known-good candidate egress, then verify that the automatic group can reference it. If the candidate list is empty, check the provider and filter expression first rather than repeatedly switching global modes.

TypePrimary useKeep in mind
selectManual selectionSelecting DIRECT sends traffic directly
url-testAutomatic selection based on probe resultsThe test URL affects the result
fallbackFailover in configured orderPriority follows candidate order
load-balanceDistributes separate connectionsDoes not combine bandwidth for one connection

Check how rules connect to proxy groups

After making a change, check the matched rule and proxy chain in the connection details. If a rule matches the intended group but the connection ends up on DIRECT, check the group’s options rather than changing the domain rule. If the node changed but the page behaves the same, close existing connections and try again; an established TCP session won’t migrate to a different egress just because you selected another group. Browser connection pools, background app connections, and caches can all delay visible results, so test with a new connection.

In practice, keep one main entry group and add only a few subgroups for services that genuinely need different routing. Groups are useful when a service needs a fixed region, different transport capabilities, or an independent failover policy. For guidance on choosing nodes and understanding the difference between probe results and region, see how to choose proxy nodes. If the client UI doesn’t match the core’s behavior, check common questions for the difference between proxy mode and the system proxy.

Rule Management / rule-providers

Managing rule sets with providers and setting match order

The rules list answers one question: which policy should handle this connection? In Rule mode, the core typically checks rules from top to bottom. The first matching rule determines the policy; it won’t keep searching for a more specific match. Order is therefore part of the configuration’s meaning: put personal exceptions before broader rules and the final catch-all at the end. A neatly sorted list isn’t necessarily logically correct. What matters is the priority among exceptions, service categories, and the catch-all.

Separate rule sources from local policy

rule-providers defines reusable rule sets, and RULE-SET references them in the main rules list. A rule set describes what to match; the referencing rule determines which policy handles the match. This lets different devices route the same domain list through different egresses without editing the upstream rule file. For large lists that need regular updates, this is also easier to review and roll back than copying everything into a subscription.

Starting with a local file makes it easier to verify the whole setup before switching to a remote source. The local rule set below is ready to use: place both the main configuration and rule file relative to mihomo’s working directory. The actual working directory depends on how mihomo is launched and managed by the client; it isn’t necessarily your Downloads folder. If the path is wrong, the core can’t load the rule set, even when the file contents are correct.

config.yaml · Local classical rule set
mode: rule
rule-providers:
  development:
    type: file
    behavior: classical
    format: yaml
    path: ./rules/development.yaml

rules:
  - DOMAIN-SUFFIX,example.com,DIRECT
  - RULE-SET,development,Proxy
  - GEOIP,CN,DIRECT
  - MATCH,Proxy
rules/development.yaml
payload:
  - DOMAIN-SUFFIX,github.com
  - DOMAIN-SUFFIX,githubusercontent.com

Make sure behavior and format match the contents

behavior: classical accepts entries with rule types, such as DOMAIN-SUFFIX in the example. Don’t include Proxy in the entries; the policy is specified in the RULE-SET reference. domain is for domain lists, while ipcidr is for IP range lists. Their syntax can’t be mixed with classical rules. format describes the payload format, such as YAML or plain text; a file extension alone isn’t a valid format declaration.

To use an HTTP source, set type to http, add a reachable url and an interval in seconds, then assign a separate cache path. Give each provider its own file path to prevent cached content from overwriting another provider’s file. An error page, access check, or login page isn’t a rule file. Being able to open a URL in a browser doesn’t mean the core receives the expected payload.

Before deploying remote rules, make sure the file can be fetched on a cold start. A startup dependency can occur if the rule needed to reach a domain is itself hosted on that domain. A safer approach is to confirm the download path works and keep a verified local cache. Rule provider download failures and unavailable proxy nodes are separate problems; check update logs and connection logs separately rather than guessing based only on a website failing to load.

Test routing with a small, targeted request

To verify a new rule, choose a domain that definitely belongs to the target set, start a new connection, and check the matched rule, rule payload, and proxy chain in the connection details. If an earlier DIRECT rule matched, adjust the order. If the expected rule set doesn’t appear, check the provider name, load status, and file contents. IP-based rules also depend on resolution or destination address information, so don’t assume they can always replace domain matching.

For LAN devices, printers, and local services, maintain explicit direct-connection ranges and make sure broader proxy rules don’t capture them first. Before adding a REJECT rule, consider whether the domain is shared by multiple services; blocking a content delivery domain can break sign-in, images, or updates. During troubleshooting, temporarily route suspicious traffic through an observable policy and note the results. Avoid deleting the entire rule set and losing useful clues.

Rule set updates are changes to external inputs and should be managed separately from subscription node updates. If only one category of website breaks after an update, roll back that rule file or pause its RULE-SET first instead of resetting DNS and TUN at the same time. Keep personal exceptions in the local override layer and comment on why they’re needed and which targets they apply to, so they survive upstream updates. For differences between mihomo and older rule support in the original core, see mihomo vs. the original Clash core.

Resolution Path / dns

DNS configuration and resolution paths

Start by answering three questions when configuring DNS: who makes the query, which egress carries it to the resolver, and which connection uses the result? System DNS, browser secure DNS, app-specific resolvers, and mihomo DNS can all coexist. Changing nameserver alone won’t ensure every app sends queries through the core. And a website loading doesn’t prove that resolution followed the expected path. Map the actual query path before changing fields; this is more useful than adding multiple resolvers at once.

Separate bootstrap DNS from regular lookups

default-nameserver resolves the hostnames of DNS servers themselves, solving the bootstrap problem of needing a server’s address before sending it a query. nameserver is the upstream for regular domain lookups. proxy-server-nameserver resolves proxy node hostnames, helping separate the bootstrap lookups needed to establish a proxy connection from queries for regular traffic. These fields serve different stages; they aren’t simply the first, second, and third fallback servers.

The example below shows a basic setup that doesn’t depend on proxy egress. It can help verify the listen address, upstream resolver, and domain policy, but it doesn’t guarantee privacy or reachability on every network. Choose resolver addresses for your network and maintenance needs. A public resolver that works on one network may not be reachable on another.

config.yaml · Basic DNS configuration
dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  default-nameserver:
    - 223.5.5.5
  proxy-server-nameserver:
    - https://dns.alidns.com/dns-query
  nameserver:
    - https://dns.alidns.com/dns-query
  nameserver-policy:
    '+.example.com':
      - https://dns.alidns.com/dns-query

Choose upstream resolvers by domain and egress by rule

nameserver-policy selects an upstream resolver based on the queried domain. In the example, +.example.com matches the domain and its subdomains. This determines which resolver to ask; it does not determine how the website connection is routed. Proxy mode, rules, and proxy groups still control the connection policy. Internal company domains usually require the organization’s DNS; public resolvers may not have those records at all. First verify that the internal resolver is reachable on your current network.

Use respect-rules if DNS upstream connections need to follow routing rules. Before enabling it, make sure proxy node hostnames can be resolved. Otherwise, DNS may need the proxy to reach the resolver, while the proxy itself needs DNS to resolve its node—a circular dependency. Don’t assume a copied “leak protection” switch combination completes the setup. Verify node resolution, upstream connections, and regular domain queries separately, especially on first launch with an empty cache.

fallback and fallback-filter have their own response-filtering semantics; they aren’t simply “ask the second server only if the first fails.” More upstreams don’t necessarily mean greater reliability: they may return different addresses, leading to differences in CDN routing and inconsistent failures. If you don’t need specific filtering, start with a small number of easy-to-understand upstreams, record the query path, and add complexity only when needed.

Listen address, cache, and IPv6 limits

The example listens on port 1053 at the loopback address. The system won’t use it automatically just because that port is open. System DNS settings generally can’t specify a custom port, so you’ll need TUN-based DNS interception, a system resolver that forwards queries, or a test tool that supports custom ports. Use dig to test the listener directly, but remember that the result only represents this query sent explicitly to the core—not that every app is using it.

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA

dns.ipv6 controls how the core’s DNS handles AAAA queries, while the top-level ipv6 field concerns IPv6 support in the core. They operate at different levels. Disabling either one doesn’t mean the OS or browser has stopped using IPv6 altogether. If some apps bypass the expected path, check system IPv6 routes, app-level secure DNS, how the proxy is connected, and existing connections instead of repeatedly toggling one DNS field.

After changing DNS policy, an old cache may still show the previous result. Consider the core, system, and browser caches separately; close existing connections and query again if needed. Seeing a Fake-IP address doesn’t tell you the real server’s region; it’s a mapped address assigned by the core. For help troubleshooting DNS contamination, interception scope, and encrypted DNS paths, see how to test for and fix DNS leaks. Check each layer in turn: test, change, and retest.

Traffic Interception / tun

How TUN mode and Fake-IP work together

TUN receives IP traffic routed by the system through a virtual network interface, making it useful for apps that don’t follow the system HTTP proxy. Fake-IP is a DNS mode that returns mapped addresses for domains. They’re often configured together, but solve different problems: TUN determines how traffic enters the core; Fake-IP helps the core associate a domain with a connection. Enabling TUN doesn’t automatically fix every DNS path, and Fake-IP doesn’t mean TUN is required in every scenario.

Check permissions and system routes first

Desktop clients may create a virtual interface and routes through a service mode or elevated privileges. Mobile clients often connect through the system VPN interface, which the UI may call VPN mode; desktop network interface settings won’t necessarily apply. Linux permissions, route management, and resolver services also depend on the deployment. When enabling TUN for the first time, confirm the client reports that interception succeeded, then check routes and DNS. A switch showing “on” doesn’t prove the network stack is working correctly.

The snippet below shows how auto-routing and DNS hijacking work together; it requires the DNS configuration from the previous section. Choose stack based on your system and core support; mixed isn’t guaranteed to be faster on every machine. If you already use another VPN, container network, or corporate tunnel, auto-routing may conflict. Test each change on a local machine you can recover.

config.yaml · TUN and DNS integration
tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53

dns:
  enable: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - '*.lan'
    - '*.local'

DNS hijacking doesn’t intercept every DNS protocol

dns-hijack with any:53 targets ordinary DNS traffic that enters the interception path. When an app uses HTTPS or another encrypted protocol to reach a resolver, that traffic won’t automatically become a port 53 query just because it carries DNS. Browser secure DNS and app-specific resolvers need to be identified separately. If you want a consistent resolution path, first have apps use the system resolver, then confirm those system queries actually reach the core.

auto-detect-interface helps select the actual outbound network interface, but multiple adapters, hotspot sharing, network changes, and existing tunnels can make the automatic choice unsuitable. A typical symptom is that every connection times out with TUN enabled and works again as soon as it’s disabled. First confirm the actual default route and check for a routing loop, then inspect the core’s connection logs; switching nodes usually won’t fix the wrong egress interface. When remotely managing a server, always keep a separate recovery path.

Some systems support strict-route to enforce routing more strictly, but it can affect LAN access or conflict with other network components. Don’t enable it blindly before identifying the problem. Start with a minimal working configuration, record how direct traffic, proxied traffic, and local network access behave, then add restrictions for a specific reason. Firewall and routing implementations vary by platform, so the same snippet won’t always have the same effect.

Fake-IP exceptions and local services

Some device discovery, LAN services, and apps that require real addresses don’t work well with Fake-IP mappings. Use fake-ip-filter to add exceptions. The example uses domain suffixes that commonly need local resolution, but base your exceptions on the apps you actually use. An exception means the domain returns a real DNS result under the applicable mode; it doesn’t guarantee that its traffic will go direct. Subsequent rules may still send connections to the real address through a proxy.

After switching Fake-IP mode or changing its mapping range, apps may still hold old addresses. If those mappings no longer match the core’s current state, DNS can appear to succeed while connections fail. Close the affected app connections, clear the relevant DNS caches, and try again. Don’t add the entire reserved address range as a remote service to ordinary proxy rules; these addresses are used for local mapping, and the core restores the actual destination from its mapping information.

Use a consistent troubleshooting order: check the virtual interface and permissions first, then confirm ordinary DNS is intercepted, check whether connections enter the core, and finally verify rules and proxy groups. If only UDP apps fail, check whether the node protocol, server, and network path support the required UDP rather than simply changing the TUN stack. If your goal is to share a proxy with LAN devices, you’ll also need to understand the listen address, firewall, and access scope; see mixed-port and allow-lan setup. Enabling TUN alone doesn’t configure proxies for other devices.

Domain Association / sniffer

What domain sniffing does—and where it stops

Domain sniffing attempts to recover a domain from protocol handshakes or request data when a connection exposes only its destination IP and has no reliable domain association. The result can help with rule matching. Unlike DNS, which resolves names, sniffing inspects connections that have already entered the core. It isn’t a decryption proxy and can’t read every HTTPS request just because it’s enabled. First confirm that traffic reaches the core; connections that aren’t intercepted are outside its scope.

Start with specific protocols and ports

mihomo can sniff protocols such as HTTP, TLS, and QUIC. HTTP may expose a Host header, TLS can often provide a server name from the handshake, and QUIC has its own handling path. However, protocol changes, encrypted handshakes, client implementations, and traffic patterns all affect results; not every connection will reveal a domain. Apps that connect directly to an IP or use unsupported protocols may still need IP-based rules and a catch-all policy.

When starting out, limit sniffing to ports that you actually need. Check whether rule matching improves before expanding the scope. A port is only a filter; it doesn’t prove that traffic uses the corresponding protocol. Including every port won’t make the results easier to understand. The example below enables domain extraction without overriding the actual connection destination, so you can test what gets identified separately from whether the destination is rewritten.

config.yaml · A conservative sniffing setup
sniffer:
  enable: true
  force-dns-mapping: true
  parse-pure-ip: true
  override-destination: false
  sniff:
    HTTP:
      ports:
        - 80
        - 8080-8880
    TLS:
      ports:
        - 443
    QUIC:
      ports:
        - 443
  skip-domain:
    - '+.example.com'

Separate domain detection from destination overrides

parse-pure-ip allows sniffing attempts on connections to IP addresses that have no domain information. force-dns-mapping relates to DNS mapping and expands handling for relevant connections. Neither guarantees success or means you can ignore DNS configuration. override-destination controls whether a sniffed domain replaces the connection destination. This has a bigger impact than detection alone, so evaluate it only after considering how the target service works.

For example, an app may first select a service IP using its own routing logic, then include a domain in the TLS handshake. If the destination is overridden and the connection is re-established by domain, the chosen address may change and affect the app’s routing or reachability. If some sites break after sniffing is enabled, first determine whether the domain rule changed or the destination was overridden. Keep connection logs and compare the same request with destination overriding disabled and with sniffing disabled; this is more useful than resetting everything at once.

skip-domain lets you exclude specific domains from sniffing. example.com in the example demonstrates the syntax; it isn’t a universally necessary exception. Keep only targets you actually need in a real setup. An exception that’s too broad may prevent sniffing-based routing for domains that depend on it, while one that’s too narrow may miss related subdomains. After adding an exception, start a new connection and confirm the detected name matches expectations.

Test sniffing as part of a verifiable routing chain

For testing, choose a target you can reproduce and record its destination address, rule, and policy before enabling sniffing. Then enable it and start a new connection. If the matched rule changes from an IP-based rule to DOMAIN-SUFFIX, domain information is contributing to the match. If nothing changes, don’t assume the feature is broken: the connection may already have a DNS mapping, or sniffing may not have found a usable name. When a page loads resources from several domains, inspect the specific failing connection rather than only the main page domain.

The name sniffed from a connection may not match the address bar exactly. Redirects, CDNs, resource hosts, and backend services can all use different names. If a service needs a stable region or fixed egress, maintain a list of the actual connection domains rather than inferring every resource from one primary domain. Proxy groups still select the node after a rule matches; sniffing won’t fix an unreachable node, an expired account, or server-side restrictions.

In production, keep the scope as small as possible; don’t use sniffing to patch a broken configuration. First make sure system resolution, Fake-IP mapping, and TUN interception each work correctly, then use sniffing to supplement connections without domain information. If only one type of app has problems, add a specific exception and document why; decide on a long-term fix once you’ve identified the cause. For related concepts, see the glossary. If you’re simply unable to connect after importing a subscription, follow the main quick-start guide to verify proxy setup and nodes rather than immediately widening the sniffing scope.

Configuration Lifecycle / merge

Local overrides and merging multiple subscriptions

A subscription file is external input, a local override is the user’s configuration layer, and the effective configuration is the result after the client processes both. They aren’t interchangeable. Direct edits to a downloaded subscription may be overwritten on the next update. Editing an override template without applying it to the active configuration won’t change the core’s behavior either. Before making changes, confirm which configuration is active, where the override applies, and which file is ultimately generated to avoid repeatedly editing the wrong object.

Define ownership for each configuration layer

Override interfaces and merge behavior vary across clients; there is no universal top-level YAML override field that works across all graphical clients. Use the override, merge, or script entry point provided by your client, and check how it handles mappings, lists, and null values. The downloads page lists options such as Clash Plus, Clash Verge Rev, and FlClash for different platforms, but their configuration editors don’t necessarily work the same way.

A practical division is to let the subscription provide node information and the local layer manage proxy groups, rules, DNS, and control interfaces. If the subscription already includes a complete routing setup, decide whether to keep its structure or extract only the nodes for local management. Running both structures can cause duplicate group names, repeated MATCH rules, and unexpected overrides. Long-term maintainability comes from deciding which source owns each kind of field—not from making the file bigger.

Use providers to keep multiple node sources separate

The snippet below demonstrates the structure with two local node providers and no remote subscription URLs. Each provider file needs a valid proxies list with real, working nodes; the main configuration imports them with use. First validate with provider files exported by your client, then try HTTP sources. This makes it easier to distinguish source download failures from node configuration problems.

config.yaml · Combining two sources
proxy-providers:
  source-a:
    type: file
    path: ./providers/source-a.yaml
  source-b:
    type: file
    path: ./providers/source-b.yaml

proxy-groups:
  - name: Proxy
    type: select
    proxies:
      - Source A
      - Source B
      - DIRECT
  - name: Source A
    type: select
    use:
      - source-a
  - name: Source B
    type: select
    use:
      - source-b

rules:
  - GEOIP,CN,DIRECT
  - MATCH,Proxy

A complete subscription and a node provider file have different structures. A full configuration containing rules, proxy-groups, and other top-level fields isn’t a valid node provider payload just because its download URL works. If your client can convert or extract subscriptions, confirm the output format. For private subscription links, use a controlled local process where possible; don’t share access credentials with an untrusted conversion service.

Handle mappings, lists, and naming conflicts

YAML mappings can be merged by key, but lists have no single built-in merge behavior. A client may replace, prepend to, or append to the entire rules list, so inspect the generated result. Local exceptions appended after an upstream MATCH won’t take effect, even if they appear in the file. Replacing all proxy-groups may also break references to old group names in upstream rules. Passing a configuration check only means its structure and references are broadly acceptable; it doesn’t prove the routing logic is what you intended.

Don’t repeat dns or rules in the same YAML mapping expecting the parser to concatenate them. Duplicate keys may be rejected or overwritten by the later value; the result depends on the parser. Keep the complete content under one clearly defined key and preserve the indentation hierarchy. Tabs aren’t suitable for YAML indentation. Keep the space after colons, the dash before list items, and string quoting correct; quote complex domain patterns and values containing special characters explicitly.

Nodes from different sources may share the same name. Merging them into a flat list can make references ambiguous or cause the client to rename entries. Separate source groups help distinguish them, but you still need to check node IDs and display names in the effective configuration. Seeing two sources in the UI doesn’t mean they’re fully isolated; verify health checks, cache files, and persisted selections separately too.

Apply, validate, and roll back

Save a known-working configuration before making changes, and keep a separate copy of local overrides. In an environment with the mihomo command line, you can use the syntax check below; it requires a real configuration file and any referenced resources to be available and parseable. If a graphical client manages the core, use the client’s validation and apply controls first. Don’t launch a second core on the same port.

mihomo -t -f ./config.yaml

Change one category at a time—in this order: DNS, proxy groups, rules, then TUN. After applying each change, check the effective configuration and a new connection. If something fails, roll back the most recent change; there’s no need to delete every subscription and reinstall the client. After updating a subscription, check that personal exceptions remain, sources have refreshed, and the catch-all rule is still last. Before sharing a configuration, remove subscription URLs, node credentials, and control passwords. Troubleshooting usually requires only the field structure and redacted logs, not your complete private configuration.

Runtime Status / external-controller

External dashboards and runtime verification

An external dashboard uses mihomo’s control API to inspect status, switch policies, and perform related management tasks. It isn’t a proxy protocol or an entry point for application traffic. external-controller defines the management API; mixed-port defines a mixed HTTP and SOCKS proxy listener. They serve different purposes. Pointing a browser proxy at the control port won’t establish a working proxy connection, and pointing a dashboard at the mixed port won’t show runtime status.

Start with the loopback address

For local use, listen on 127.0.0.1 to avoid exposing management access to your LAN or the public internet. The password below is an explicitly fictional example; set a real one through a controlled local configuration for deployment. external-ui points to a local directory containing a prepared static dashboard. The core can serve its pages only if the path exists and the files are complete. Without dashboard files, the API may still work; don’t mistake a missing page for a control API that failed to start.

config.yaml · Local management API
mixed-port: 7890
allow-lan: false
external-controller: 127.0.0.1:9090
secret: "your-password"
external-ui: ./dashboard

A local dashboard is usually available at http://127.0.0.1:9090/ui/. Enter the control endpoint and password in its connection settings. Field names vary by dashboard, so use the options it actually provides. A graphical client may also manage the control interface itself and override file settings. If the port doesn’t change after manual edits, check the effective configuration and startup logs; don’t start another core that competes for the same port.

Use the API to distinguish connection, authentication, and UI problems

The request below only demonstrates how to query proxy information; its authentication value matches the fictional password above. Never put a real password in a public screenshot, shared command, or support ticket. Run the request on the device hosting the core: 127.0.0.1 on another computer refers to that computer, not the proxy host.

curl --noproxy '*' \
  -H 'Authorization: Bearer your-password' \
  http://127.0.0.1:9090/proxies

For a connection refusal, check the listen address, port conflicts, and whether the core is running. For an authentication failure, check the password and request headers. If the API works but the page doesn’t, check the dashboard files, browser console, and frontend connection settings. This sequence separates network, authentication, and UI issues without changing proxy rules prematurely. If the browser reports a cross-origin restriction, verify how the dashboard and API origins relate instead of allowing every site to access the control port.

Remote management requires additional planning for authentication, transport encryption, and access scope. A minimal approach is to keep the service bound to localhost and connect through a controlled secure channel, rather than binding to every interface and opening a public port. If you need a reverse proxy, also evaluate WebSocket support, cross-origin policy, and server-side access controls. The control API can change runtime state; it shouldn’t be treated like an ordinary read-only webpage.

Dashboard state isn’t the same as persisted configuration

Changing a proxy group in the dashboard primarily changes runtime state. Whether it persists after a restart depends on the core’s persistence settings and how the client manages it. Fields changed temporarily through the API may also revert when a subscription or override is reapplied. Store long-term rules and network settings in the managed local configuration layer. Use the dashboard to observe and verify, not as your only configuration record. After a change, reload and check that the expected behavior can be reproduced.

When inspecting a connection, correlate its domain, destination address, matched rule, proxy chain, and error logs. If no relevant connection reaches the core, start by checking the system proxy, TUN, or the app’s own connection method. If it reaches the core but matches the wrong rule, review the rule order. If the rule is correct but the egress is wrong, check the proxy group’s selection. If the egress is correct but the connection still fails, check node capabilities, DNS results, and the target service. This avoids guessing across every field at once.

Observed resultCheck firstNext verification
No connection to the targetTraffic interception and system routingConfirm which network path the app is actually using
Unexpected rule matchRule order, rule sets, and domain informationStart a new connection and inspect its rule details
Proxy chain ends in a direct connectionGroup selection and nested referencesPin a verified candidate egress
Control API works, but the page failsDashboard files and connection settingsInspect page requests and authentication responses

Complete a repeatable configuration check

Finish by establishing a fixed set of tests: one target that should connect directly, one that should use a proxy, one LAN service, and any UDP apps you actually need. After each change, compare new connections against this test set and record the effective configuration and logs. Consider the adjustment complete only after the results remain consistent across restarts, subscription refreshes, and network changes. For general connectivity issues, see common questions and Troubleshooting. To review the import process, return to the quick-start guide. A configuration you can explain is easier to maintain than one with more unverified switches.