Clash Configuration Deep Dive Guide

Proxy groups, rule providers, and networking—organized by the layer where the issue occurs.

Get connected first, then fine-tune your configuration. The quick start guide covers installation, importing a subscription, system proxy setup, and your first connection test. This page explains how configuration fields work together, how to maintain them over time, and how to verify changes. Haven’t picked a client yet? Choose one for your platform on the client downloads page, where Clash Plus is the top pick for each supported platform. If you already have a working configuration, jump to the relevant section.

This guide focuses on mihomo configuration semantics. Client interfaces may transform, override, or restrict fields, so desktop YAML cannot be applied unchanged to every mobile app. Each code block is a topic-specific configuration snippet; merge it into the matching field in your complete configuration. Example domains illustrate matching behavior and do not represent proxy services. No proxy node details are provided, and a single test result should not be treated as proof that the entire connection path works.

Configuration Layers and Clash Port Settings

Before making changes, find the configuration that’s actually in use. The file downloaded from a subscription, the configuration saved by the client, and the merged runtime configuration are often different. Subscriptions provide proxies and baseline policies; client preferences may take over ports, mode, DNS, or TUN; local overrides can add rules. A field in an editor doesn’t necessarily mean the core is using it. Check the runtime configuration, client settings, and startup logs to confirm the effective value. If there’s no way to view the runtime configuration, at least note whether the client manages that setting.

YAML Indentation and Field Structure

YAML uses spaces to define hierarchy. Fields at the same level must line up, and list items start with a hyphen. Don’t mix tabs and spaces or define two dns or rules keys at the same level. Duplicate keys may cause an error or leave only the later value in effect. Quote names containing special characters, especially colons or spaces. Preserve the file’s existing structure and change only the field you need. Compressing an entire subscription into one line makes indentation mistakes and unintended overrides much harder to find.

Back up the file locally, then run a configuration check. If you’re using the command-line core, run the command below. ./config.yaml refers to the configuration file in the current directory; adjust the path if the file is elsewhere. A successful check only confirms that the syntax and basic references can be loaded. It doesn’t confirm server reachability, sufficient system permissions, or a correct DNS path. If your client has a configuration validation button, validate before applying changes to avoid interrupting a working session.

mihomo -t -f ./config.yaml

Mixed Port and Listen Address

mixed-port lets HTTP and SOCKS proxies share one listening port. It’s the local entry point for applications connecting to the core—not a remote proxy server’s port or the dashboard port. The configuration below listens only on the loopback address, which is suitable for a single device. Browsers typically connect through the system proxy; command-line tools may need proxy environment variables set separately. The client controls whether the system proxy is configured automatically; adding mixed-port alone won’t do that.

mixed-port: 7897
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: info
ipv6: false
FieldPurposeWhat to check after changing it
mixed-portHTTP and SOCKS entry pointSystem proxy and application proxy ports
allow-lanWhether LAN access is allowedListen address, firewall, and access scope
modeRule, global, or direct modeThe policy actually used in connection details
log-levelLog verbosityWhether to restore the normal level after troubleshooting

If a port error occurs, first determine whether another proxy app or a leftover core process is using the port. Don’t terminate an unfamiliar system process. Quit duplicate clients, make sure their processes have stopped, then restart. If you need a different port, update the system proxy, browser extensions, and terminal environment variables as well. Changing only the YAML while leaving the system proxy pointed at the old port often means the core runs normally but the browser gets a connection refused error. See the port conflict troubleshooting guide for specific commands.

Use a Change Process You Can Roll Back

Change one type of behavior at a time—for example, adjust the listen port first, then DNS, and enable TUN last. After applying each change, verify it with a new connection; an existing browser connection may stay open and mask the result. Record the fields changed, affected apps, and log timestamps so you know what to revert. If you need help, share only the smallest relevant configuration snippet. Remove subscription URLs, credentials, and personal network details, but keep the field structure and error context.

To confirm a configuration is working, check whether a new connection reaches the core, which rule it matches, and which outbound it selects. An enabled toggle, a saved file, and a successful configuration check each confirm a different stage. Check these stages separately to avoid mistaking a port issue for a subscription problem—or rewriting the entire configuration to fix a misleading UI status.

Proxy Group Types and Traffic Routing

Rules determine where traffic goes; proxy groups determine which outbound to use. Give services stable group names, then change the nodes within those groups so subscription updates don’t require repeated rule edits. Group names must match rule targets exactly, including capitalization, spaces, and punctuation. Groups can reference other groups, but circular references are invalid. For example, a manual group can include an automatic group; if the automatic group also includes the manual group, the resulting dependency can’t be resolved properly.

Manual and Automatic Selection

Use select when you need to choose a fixed outbound in the client. url-test periodically compares the test latency of candidate outbounds and is useful when you want automatic selection. fallback selects the first available member in list order, making it suitable for a clear primary-and-backup setup. load-balance distributes separate connections among members; it doesn’t combine their bandwidth for a single download. Choose the behavior that fits your needs before tuning the test interval. Don’t put every app into an automatic group just because it seems convenient.

Here’s a minimal snippet to illustrate how group references work. Its only member is the built-in DIRECT, so it provides no proxy outbound. After importing a real subscription, you can add proxies or other groups that already exist in it. The goal is to show a clear structure, not to invent a fake server that looks connectable. In practice, keep group names stable and let the subscription or local configuration manage the members.

proxy-groups:
  - name: Outbound Selection
    type: select
    proxies:
      - DIRECT

rules:
  - DOMAIN-SUFFIX,example.com,Outbound Selection
  - MATCH,DIRECT

Test Settings Aren’t Experience Metrics

Automatic tests usually need parameters such as url and interval. tolerance can help prevent frequent switching due to small latency changes. Choose a lightweight test resource that all candidate outbounds can reach reliably. The example domain only shows where the field goes; it isn’t a reliable test service. Pick an address that works on your network. Testing too often adds requests and drains mobile batteries; testing too infrequently delays updates when an outbound fails. Find a balance for your environment.

A successful test means an outbound completed a specific request—not that it can reach every site. An outbound may have a fast handshake but limited bandwidth during peak hours, or work well for browsing but poorly for jitter-sensitive voice calls. When comparing automatic groups, use the same target at roughly the same time and verify with new connections. For more on what latency tests measure and where their limits lie, see node latency tests vs. real-world speed. Don’t choose a long-term outbound based on milliseconds alone.

TypeSelection methodKey limitation
selectManually select a memberUsually requires user action when it fails
url-testSelect based on test resultsLow latency doesn’t guarantee high bandwidth
fallbackSelect the first available member in orderMember order determines primary and backup priority
load-balanceDistribute connections according to policyDifferent connections may use different outbounds

Keep service groups separate from node sources

A maintainable configuration can use two layers: lower-level groups collect nodes and handle automatic testing or failover; upper-level groups handle services such as browsing and work tools. Rules reference only the upper-level groups, so changes to node names affect only the lower layer. With proxy-providers, a group can use use to reference a declared provider. Provider names aren’t node names, and the provider must be declared in the complete configuration first. If the client generates groups automatically, check whether it preserves custom groups so an update doesn’t overwrite a group with the same name.

For services that rely on stable sign-in sessions, prefer a manual group or an explicit primary-and-backup group. Frequent outbound changes can trigger extra verification and affect access decisions based on source IP. Existing connections usually keep their current route after you change a group member; new connections use the new selection. If needed, close the relevant sessions in the connection list instead of assuming the change wasn’t saved. Before enabling load balancing, confirm that the service allows separate requests to come from different outbounds.

After configuring a group, test its service with a specific domain rule, then check the fallback rule. Global mode may bypass normal rule routing, while direct mode won’t use service groups as expected. Before troubleshooting group behavior, confirm that rule mode is active. Seeing a group in the client doesn’t prove any traffic uses it; the rule and route shown in connection details are the final evidence.

Manage Rules with Rule Providers

Rule providers manage where rules come from and how they’re updated; they don’t provide proxy nodes. rule-providers declares rule data, while rules determines when to use it and which policy to apply. Don’t confuse the two: downloading a rule file without adding a RULE-SET reference won’t make it participate in matching. A reference with an unloaded provider may cause the configuration to fail. Get a small local rule set working first, then add remotely maintained collections. That makes formatting and network issues easier to tell apart.

Behavior Types and File Formats

behavior describes the kind of rules in a collection. Use domain for domain lists, ipcidr for IP ranges, and classical for entries that include rule types, such as DOMAIN-SUFFIX,example.com. The outer RULE-SET specifies the rule target; don’t put proxy group names in classical entries. format describes how the file is encoded. YAML, plain text, and binary formats aren’t interchangeable just by changing the file extension, and the behavior type must be supported by the chosen format.

The example uses a local YAML file, which is useful for validating the structure first. Relative paths are generally resolved from the core’s working directory, but GUI clients may use their own configuration directory or restrict file access. Don’t assume the path points to the editor’s current directory. Create a rules folder in the appropriate directory, save the rule file, and merge the provider declaration into the complete configuration. Put service-specific rules before the fallback. This example routes directly and doesn’t depend on an external proxy group.

rule-providers:
  local-domains:
    type: file
    behavior: classical
    format: yaml
    path: ./rules/local-domains.yaml

rules:
  - RULE-SET,local-domains,DIRECT
  - MATCH,DIRECT

The rule file contains only matching criteria—not proxy servers, group definitions or global DNS settings. For domain behavior, use the domain-list syntax; changing a classical file’s type field alone does not convert its contents. If loading fails, check the provider’s behavior and format first, then the file contents, and finally whether the rules match your intent.

payload:
  - DOMAIN-SUFFIX,example.com
  - DOMAIN,example.net

Switch from a Local File to a Remote Source

For a remotely maintained list, change the source type to http, set the actual rule file URL, and keep a separate cache path and a reasonable update interval. interval is measured in seconds, not minutes. Give each provider its own path so one update can’t overwrite another collection. Use a direct URL to the rule file, not a web preview page. A successful download that returns an HTML sign-in or access page can’t be loaded as rule data.

Choose a source based on its maintenance scope, entry types, and update schedule—not its size. A very broad collection can change how traffic is routed, especially for work networks, intranet domains, or app sign-ins. When adding one for the first time, put personal exceptions before the collection, test a few targets, then expand coverage. Keep the last known-good local configuration. Cache behavior depends on the core and client, so don’t assume an empty cache will work offline.

Rule Order and Resolution Side Effects

Rules are evaluated from top to bottom, and matching stops at the first hit. Put exact domain exceptions first, broader domain suffixes and rule sets later, and MATCH last as the fallback. IP-based rules may need to resolve a domain first, adding a DNS lookup delay. For rules that support it, no-resolve prevents the rule from initiating a lookup just to make a match; it isn’t a universal setting for every rule. When routing by domain, domain rules generally belong before rules that require an IP address.

If a destination is routed incorrectly, check the actual matched rule in its connection details. A broad collection matched earlier in the list will prevent a later personal exception from running. If only the fallback matches, check whether domain information is available, the rule file loaded, and the target uses a different related domain. If logs show a rule download failure, investigate source access and cache directory permissions. Don’t replace every rule set over one mismatch; that only broadens the scope of the troubleshooting.

For long-term maintenance, record each source’s purpose and intended target policy. Before removing a provider, search for all RULE-SET references. When renaming a group, update its references too. Keep personal exceptions in a small local collection and general categories in remote collections to limit update risk to clear boundaries. For help with routing terminology, check the quick reference, then verify the result in connection history.

DNS Paths and Resolution Tuning

First identify what’s doing the resolving, then choose a DNS server. Apps may use system DNS, built-in encrypted DNS in the browser, or their own resolver. The core may also make separate queries for proxy server addresses and rule matching. These requests don’t automatically follow the same path. Changing only nameserver won’t affect the result if apps still resolve outside the core. Start by confirming that the target query reaches the core, then see which upstream it selects.

Default Resolvers, Upstreams, and Proxy Hostnames

default-nameserver is mainly used to bootstrap DNS upstreams specified by hostname; it’s typically set to IP addresses that are directly reachable. nameserver lists regular upstream resolvers. proxy-server-nameserver can resolve proxy server hostnames, avoiding a dependency loop where resolving the proxy requires a proxy path that isn’t available yet. Resolver reachability varies by network. Public DNS addresses are just examples; verify that you can reach them and that they return the expected results before using them.

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: redir-host
  default-nameserver:
    - 1.1.1.1
  nameserver:
    - https://1.1.1.1/dns-query
  proxy-server-nameserver:
    - https://1.1.1.1/dns-query

This local listen port provides DNS only; it isn’t an HTTP proxy port. Setting it to 1053 won’t automatically make system DNS use it. Operating systems typically send DNS on the standard port, so using another port requires client integration, forwarding, or TUN interception. First check how the client handles system queries, then decide on a listen address. Don’t bind to all addresses just to let another device connect; DNS access should also be restricted.

Route DNS by Domain

Use nameserver-policy for intranet domains, specialized services, or domains that must be answered by a particular resolver. A company’s internal domains may be known only to its DNS server; sending them to a public resolver may return a non-existent result. Public services may instead need a consistent encrypted DNS path. The field uses its own supported domain-matching syntax, so don’t paste in a full rules entry. Start with a policy for a specific domain suffix, verify the response, then expand its scope.

With respect-rules enabled, DNS upstream requests follow the rules, so you also need a reliable way to resolve proxy server hostnames. Otherwise, a loop can occur: the proxy needs a DNS lookup to connect, while reaching the resolver requires the proxy to be available. To check for a loop, route proxy server resolution through an upstream that’s directly reachable, then see whether DNS recovers. A longer resolver list isn’t necessarily more reliable; multiple upstreams can produce inconsistent results and make troubleshooting harder.

FieldPrimary purposeCommon misunderstanding
default-nameserverBootstrap resolution for upstream hostnamesDoesn’t handle all application system DNS queries
nameserverRegular DNS upstreamsA configured resolver doesn’t mean application queries are routed to it
proxy-server-nameserverResolve proxy server hostnamesAvoid resolution loops that depend on the proxy
nameserver-policyRoute DNS upstreams by domainUses different syntax from regular traffic rules

Caching, IPv6, and Troubleshooting

After a DNS change, the browser, operating system, and core may all retain old cache entries. To verify the new settings, close existing connections, clear caches using the method supported by your client, and make a fresh query. Don’t judge the new configuration by refreshing an old page once. Results from an operating system query tool reflect only that tool’s DNS path; a browser using its own secure DNS may behave differently. If needed, temporarily use one consistent resolution path for testing, then restore your usual settings.

IPv6 behavior depends on several things: whether DNS returns IPv6 addresses, whether the system has a working route, whether the proxy node supports the destination address, and whether TUN captures the relevant traffic. Disabling a single DNS field won’t prevent every app from making IPv6 requests. If some sites pause before loading, check whether they first try an unreachable address before falling back to another address family. Adjust settings based on what you find; not every delay is caused by proxy node latency.

If logs show a DNS timeout, first check whether the upstream is reachable and whether resolution is stuck in a loop. If an address is returned but the connection fails, check the routing rule and destination service. If only intranet names fail, focus on domain policies and internal DNS instead of switching the entire proxy group. Check the query entry point, upstream selection, address response, and service connection in that order. This is usually more effective than cycling through public resolvers. For more detail, see how to read runtime logs.

TUN Traffic Capture and Fake-IP

TUN is a traffic entry point; Fake-IP is a DNS mapping method. They’re not the same switch. TUN creates a virtual network interface and adjusts routes so that apps which ignore the system proxy can send traffic to the core. Fake-IP returns a mapped address for a domain; when the core receives the connection, it looks up the original domain. Together, they can preserve domain information, but that doesn’t make them suitable for every device or app. If your browser already works through the system proxy, enable TUN only if you have a specific need.

Requirements and a Minimal Capture Setup

Desktop platforms often require administrator privileges, service mode, or permission to change network settings. Mobile platforms rely on the system VPN interface. Missing permissions, a stopped service, or another VPN using the network interface can all prevent traffic capture. Check the client’s service status before enabling TUN. Don’t expect changing enable to true alone to configure the routes. The example shows common mihomo fields; first confirm whether the client lets YAML manage those settings.

tun:
  enable: true
  stack: system
  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"

auto-route configures capture routes automatically, while auto-detect-interface identifies the outbound interface. Multi-adapter systems, virtual machines, and corporate VPNs may still select the wrong interface. dns-hijack applies to ordinary DNS requests that can be intercepted; it doesn’t decrypt an app’s own DoH. The stack option selects a network stack implementation. Whether system, gvisor, or another supported option is available depends on the platform and core build, so the name alone doesn’t tell you which will be faster.

Fake-IP Mapping and Compatibility Exceptions

A Fake-IP address isn’t the destination server’s real address, so don’t use it for ordinary public IP reachability tests. Fake-IP relies on the core keeping a mapping between the domain and address, so the DNS query and later connection need to pass through the same handling system. An app may briefly fail to connect if it has cached an old mapping and the core’s mapping state has changed. After changing the address range or resolution mode, clear caches as needed and create new connections. This helps distinguish a mapping mismatch from a rule issue.

Some LAN services, device discovery, games, and apps that need the real address may need an entry in fake-ip-filter. The example includes common local domain suffixes, not every possible intranet domain. Add exceptions for domains that actually cause problems instead of filtering all domains. Filtered domains generally receive real DNS results. Whether traffic can still be routed by domain depends on the query path, cache association, and sniffing support. This is a compatibility adjustment, not a direct-connection rule.

PlatformCheck before enablingWhat to troubleshoot
Windows desktopClient service or administrator privilegesLeftover virtual interfaces, duplicate proxy processes
macOS desktopNetwork configuration permission and client serviceOther VPNs, routes, and interface selection
Linux desktopNetwork management permissions and TUN devicePolicy routing, firewall, and service permissions
Mobile devicesVPN permission and background operation requirementsApp exclusions and system battery restrictions

Check traffic, DNS, and routing separately

After enabling TUN, first check whether new connections appear in the core. If none do, check permissions, routes, and app exclusions. If connections appear but show only an address, check whether DNS is following the expected path. If the domain is identified but traffic uses the wrong outbound, check rule order and proxy group selection. If only some UDP apps fail, check whether the node protocol and server support that traffic. A working webpage doesn’t prove every protocol works.

If the internet still doesn’t work after disabling TUN, check whether the core has fully stopped, system routes have been restored, and DNS isn’t still pointing to a stopped service. Prefer stopping the service and resetting network settings through the client. Don’t start by deleting every virtual network adapter. For details on traffic capture and stack trade-offs, see how TUN virtual interfaces capture traffic, then confirm the right settings for your platform.

A reliable validation should cover ordinary browsing, an app that didn’t previously use the system proxy, LAN services, and recovery after sleep. Use a new connection for each test and inspect the actual rule and outbound. TUN expands the range of traffic handled—and the potential problem area. Capturing only the apps that need it and keeping sensible exceptions is easier to maintain than routing everything through TUN.

Sniffing and Rule-Matching Adjustments

Sniffing adds connection target information; it doesn’t read all encrypted content. If an app connects directly to an IP address, DNS queries bypass the core, or the domain association is lost, rules may see only an IP. Sniffing attempts to extract a hostname from protocol handshakes or request headers, such as HTTP Host, TLS SNI, and recognizable QUIC handshake information. Extraction depends on protocol implementations and privacy features, so a domain won’t be available for every connection.

First Confirm That Domain Information Is Missing

Prioritize sniffing only when connection records consistently show an address and the relevant domain rules don’t match. If the correct domain is already shown, the issue is more likely rule order, group selection, or destination reachability. Before enabling sniffing, make sure DNS and traffic entry are configured properly. Sniffing supplements connection information; it doesn’t replace DNS or fix traffic that never reaches the core. Treat it as an additional layer to keep troubleshooting straightforward.

sniffer:
  enable: true
  force-dns-mapping: true
  parse-pure-ip: true
  override-destination: false
  sniff:
    HTTP:
      ports:
        - 80
        - 8080-8880
    TLS:
      ports:
        - 443
        - 8443
    QUIC:
      ports:
        - 443

These ports specify where the core attempts to parse the corresponding protocols. They aren’t listening ports and don’t turn all traffic in that range into the specified protocol. parse-pure-ip allows sniffing attempts for destinations that are plain IP addresses. force-dns-mapping affects sniffing behavior when DNS mapping is involved. override-destination controls whether the sniffed domain replaces the connection target. Starting with false helps avoid changing both the target information and connection behavior at once; change it only after confirming you need to.

Overriding the Destination vs. Identifying a Domain

Overriding the destination may cause subsequent connections to be handled using the new domain, which can help with some routing setups. It can also change the address selected by the app. The same domain may resolve to different addresses with different resolvers, so the app’s chosen address and the address resolved again by the core may not match. When investigating a change in access, check the sniffed domain, original address, and final outbound. A rule changing from IP-based to domain-based alone doesn’t prove the fix is correct.

If an app hides the handshake hostname using a mechanism such as Encrypted Client Hello, or its protocol data doesn’t match a supported format, the core may not be able to identify a domain. Expanding the port range won’t necessarily help and may increase delays or false matches. A service addressed by a literal IP may not have a hostname to recover at all. Keep the necessary IP rules or adjust the traffic entry method for the app; don’t treat every failed sniff as a configuration error.

Skip Exceptions and How to Verify

For LAN devices, specialized TLS services, and apps sensitive to initial handshake timing, add sniffing exceptions for the affected domains. Reproduce the issue first, then use a narrowly scoped exception rather than skipping an entire category of public services. The exception affects sniffing only; it doesn’t create a direct-connection rule. Add the intended target explicitly in rules if the traffic needs to go direct. Some clients don’t expose every sniffing field, so check the final runtime configuration when using client settings.

To verify sniffing, first disable it and save a connection record for a new connection from the target app. Then enable sniffing for the same scope, reconnect, and compare the domain, rule, and result. If testing in a browser, don’t reuse an existing connection pool. Expand the scope only after new connections show the expected domain and behave consistently. If needed, temporarily increase log verbosity, then restore the normal level after testing to limit output and retained browsing metadata.

QUIC identification also depends on whether UDP traffic actually reaches the core. A system proxy usually can’t route every app’s UDP traffic; TUN or support built into the app may provide the right entry point. If TCP connections to a site can be identified but UDP connections don’t appear in the logs, check traffic capture first instead of repeatedly changing sniffing ports. For apps that fail only with certain protocols, recording the connection protocol is more useful than noting just the domain.

Keep a rule structure that still has a sensible fallback when sniffing information is unavailable. Use domain rules for primary classification, IP range rules for specific address ranges, and a final fallback for connections that can’t be identified. Sniffing can improve classification, but it shouldn’t be the configuration’s only source of identification. That way, behavior remains understandable when apps update, networks change, or protocols add stronger privacy protections.

Local Overrides and Merging Multiple Subscriptions

Keep personal rules in local overrides and let the subscription update its original content. Editing a downloaded subscription directly can mean losing your changes on the next refresh. Copying the subscription into a permanent local file prevents normal updates. A maintainable setup separates the source layer, client preferences, and override layer: proxy data changes with the subscription, while ports, service groups, and personal exceptions stay stable. Clients may call this feature overrides, extensions, merges, or scripts; the label alone doesn’t explain how merging works.

Objects, Lists, and Merge Order

Object fields may merge recursively or be replaced entirely. Lists may be appended, prepended, or overwritten. This matters especially for rules: personal exceptions appended after MATCH will never take effect. Test prepend behavior with one recognizable domain exception before adding a batch of rules. When modifying dns, check that existing upstreams and policies remain in place. Don’t assume an old setting survived just because the new field appears.

The snippet below shows the desired order in the final rules, not a universal client override file format. Put personal exceptions first, keep existing service rules in the middle, and leave one fallback at the end. If your client requires a specific prepend or append format, follow its documentation. A fragment from the final runtime configuration isn’t necessarily a valid extension format for every client. The runtime configuration is the common place to verify the merge result.

rules:
  - DOMAIN,printer.lan,DIRECT
  - DOMAIN-SUFFIX,example.com,DIRECT
  - MATCH,DIRECT

Resolve Naming Conflicts Before Merging Subscriptions

Different sources often use the same group and node names, making references ambiguous when combined directly. Choose a stable identifier for each source and check how duplicate names are handled before merging. If prefixes are added automatically, update manual member lists and filter expressions too. Changing display names without updating references can leave groups pointing to missing members. Don’t use temporary test names as long-term service targets; have service rules reference stable, locally defined upper-level groups.

Use proxy-providers to manage sources separately, then reference them in a group with use. Provider URLs contain sensitive subscription information; keep them in your personal configuration and out of public screenshots or support requests. The example uses a local proxy data source, so you’ll need to prepare a valid file first. It isn’t a complete subscription and includes no usable nodes. If the source has no proxy entries, fix the source rather than expecting the group to create an outbound.

proxy-providers:
  personal-source:
    type: file
    path: ./providers/personal.yaml

proxy-groups:
  - name: Subscription Outbounds
    type: select
    use:
      - personal-source

A remote proxy source must provide a proxy collection format supported by the core; a complete GUI configuration may not work directly as provider data. Subscription conversion and client import workflows may extract proxies, depending on their implementation. If a source loads successfully but has no members, check its data structure, filters, and renaming rules before changing DNS. A filter that’s too broad includes unwanted members; one that’s too narrow can leave the source empty.

The Limits of Override Scripts

Scripts can deduplicate entries, standardize names, and insert rules in bulk, but they should have clear input and output boundaries. Check that a field exists before changing an array. Check whether a rule is already present before inserting it to avoid adding duplicates on every update. If a source changes, the script should return useful diagnostic errors instead of an empty configuration. Script APIs vary by client, and a complex script isn’t necessary just to set a static port.

After merging, verify three cases: personal exceptions come before general rules, service groups include the expected sources, and overrides remain after a subscription refresh. Also test an empty source or a failed download to make sure the client doesn’t treat an unusable structure as a valid configuration. Multiple subscriptions mean more independent failure points. Keep one working single-source configuration so you can quickly narrow down problems.

When migrating from an older client, move the subscription URL and essential service rules first, then restore DNS, TUN, and scripts one at a time. UI-specific fields and extension syntax in old files may not be recognized by the new client; matching file extensions don’t make the configurations interchangeable. Clash for Windows and ClashX Meta are discontinued legacy options. For migration advice, see the configuration migration guide for discontinued clients, then return to the client comparison to choose a platform-appropriate client.

External Controllers and Runtime Diagnostics

An external controller exposes a core management API. A dashboard uses it to read status, switch proxy groups, and view connections. It isn’t a proxy entry point or DNS listener. Pointing your browser proxy at the controller port won’t create a working proxy connection; setting the dashboard address to the mixed port won’t manage the core. Identify what each port does before configuring the dashboard. Most desktop users can use the client’s built-in dashboard. Extra management access is mainly for servers or standalone core setups.

Local Listening and Access Authentication

For a typical single-device setup, listen on the loopback address. The secret shown below is an intentionally fake example: replace it with a strong random value and keep it in your personal configuration. The secret protects the controller API; it is not a substitute for LAN proxy authentication. Even when listening only on localhost, consider access by other local programs. For remote administration, use a controlled tunnel rather than exposing the management port.

external-controller: 127.0.0.1:9090
secret: "your-controller-secret"
log-level: info

A client may configure the controller address and authentication automatically, so hand-written fields may not take effect. Before connecting a dashboard, check the runtime configuration or the connection details provided by the client. The host, port, protocol, and credentials in the dashboard must all match the same core instance. If multiple clients are running, the dashboard may connect to an old instance, making policy changes appear ineffective. Confirm the active instance before troubleshooting the API.

Dashboard Files and Browser Access Restrictions

external-ui specifies the directory containing local dashboard assets. It should contain the complete page and its related static files. Don’t point it to a nonexistent folder or assume the client’s installation directory is the dashboard directory. On a server, manage permissions for dashboard assets, core configuration, and cache paths separately. After updating the dashboard, check that the resource path is still correct. If you only use the built-in dashboard, you usually don’t need to set this field.

If a browser reports a connection failure, the cause may be incorrect authentication, cross-origin restrictions, or mixed-content blocking. A browser may block an HTTPS page from accessing an HTTP controller, even when the port is reachable. A standalone dashboard hosted on another origin must also comply with the core’s cross-origin settings. Don’t allow all origins and expose the controller just for convenience. The simplest verification is to use the client’s local entry point or a same-origin dashboard. Get that working before expanding remote access.

SymptomCheck firstNext step
Connection refusedWhether the core is running, plus the listen address and portConfirm the port’s purpose and the active core instance
Authentication failedWhether dashboard credentials match the runtime configurationUpdate the dashboard’s local connection settings
Page loads, but no data appearsAPI requests, cross-origin settings, and browser restrictionsVerify requests through a same-origin entry point
App still uses the old outbound after a switchPersistent connections and service group referencesReconnect and inspect the route

Use runtime records to complete the troubleshooting loop

Start with the connection list. The target domain or address, matched rule, proxy group chain, and outbound are key to understanding the configuration’s behavior. Then check logs from the same time to distinguish DNS timeouts, dial failures, connection refusals, and rule mismatches. Temporarily increase the log level from info to debug, reproduce the issue once, collect the necessary context, and restore the normal level. Keeping detailed logs enabled increases storage use and retains more connection metadata.

For a complete reproduction, record the time, app, destination, current mode, traffic entry method, and expected policy. If a webpage won’t load and there’s no connection record, check the app’s traffic path and system proxy first. If a record exists but the domain is missing, check DNS and sniffing. If the rule is correct but dialing fails, check the node and remote destination. If traffic still uses the old outbound after a switch, check for a persistent connection. Follow this sequence to avoid switching nodes repeatedly for a DNS problem or changing routes over and over for a node issue.

When sharing diagnostic material, include only the relevant connections and a short window of logs. Hide subscription URLs, credentials, and personal browsing history. Rule and group names can usually remain to show the route structure; handle proxy server details according to your privacy needs. Don’t upload the entire runtime directory, which may contain caches, subscriptions, and client settings. A minimal reproduction both reduces exposure and makes the issue easier to understand.

When you’re done, return to a known-good baseline: confirm rule mode, normal log verbosity, the intended listen scope, and a backup configuration. Restart the client once to make sure the configuration works beyond the current session, then check that personal rules survive a subscription refresh. For first-time setup questions, return to the system proxy quick start. For field definitions, use the quick reference. The goal of advanced configuration is behavior you can explain, changes you can verify, and problems you can roll back—not as many switches as possible.