Mihomo Configuration Reference

Clash Advanced Configuration Guide

A systematic reference for proxy groups, rule providers, DNS, TUN, Fake-IP, domain sniffing, local overrides, subscription merging, and external controllers.

Core: Mihomo Configuration format: YAML Updated: 2026-08-19
How this page fits with the quick tutorial

For first-time installation, subscription import, and your first connection, start with the quick-start tutorial. This page assumes the client already launches and explains how configuration options relate, how to combine them, and how to troubleshoot. If the client is not installed yet, choose your platform on the download page; for desktop and mobile, Clash Plus is the recommended option.

01 / POLICY

Proxy group types and practical combinations

Start by separating nodes, proxy groups, and final policies

In a Clash configuration, a proxy node contains the parameters for a specific connection, a proxy group organizes nodes or other groups, and the last item on a rule line is the final policy name. All three names may appear in the interface, but they serve different roles. For example, when a subscription provides multiple nodes, place them in a select group called “Node Selection,” then have business groups such as “Developer Services” and “Streaming” reference “Node Selection.” Rules only need to target the business group, not bind each line to an individual node. This lets you change nodes without editing rules and avoids reorganizing routing logic after every subscription update.

Proxy group names must exactly match their rule targets, including spaces and capitalization. A configuration that parses successfully does not guarantee that the referenced policy exists: some clients report a missing policy during loading, while others expose the problem only when a rule is matched. After renaming a group, reload the configuration, then verify the target group in connection details or logs. Do not judge only by whether a webpage opens—browser caches, reused connections, and the system DNS cache can temporarily preserve old results.

Roles of four commonly used groups

Type Selection logic Best used for Keep in mind
select Selected manually by the user Main entry points and business groups Does not switch automatically; results are easiest to control
url-test Test periodically and choose the candidate with a suitable response time Automatic selection among similar nodes The test result reflects only the test address, not every site's experience
fallback Selects the first currently available candidate in order Primary/backup failover Order expresses priority; lowest latency is not the only goal
load-balance Distributes different connections across multiple candidates according to policy Using multiple exits in parallel Different exits for the same service may trigger login or fraud controls

url-test works well for interchangeable nodes. Common parameters include the test address url, the test interval interval, and the acceptable difference tolerance. Very short intervals create extra connections and battery use, especially on mobile; a tolerance that is too small can make selections change constantly. The test address should return a stable, very small response. A successful test proves only that the path from the current network through the candidate node to the test address works—it does not guarantee the target service's handshake, region detection, or account status.

fallback prioritizes order. It suits scenarios where the primary route should be used until it becomes unavailable, then replaced by a backup. By contrast, load-balance distributes concurrent connections across different nodes. Logins, payments, real-time messaging, and long-lived connections that need a stable source address should not be placed directly in a load-balancing group. Even with consistent hashing, domain changes, connection rebuilds, and rule changes can still alter the exit.

A maintainable layered structure

proxy-groups:
  - name: Node Selection
    type: select
    proxies:
      - Automatic Selection
      - Failover
      - DIRECT

  - name: Automatic Selection
    type: url-test
    use:
      - airport-main
    url: https://www.gstatic.com/generate_204
    interval: 600
    tolerance: 80

  - name: Failover
    type: fallback
    use:
      - airport-main
    url: https://www.gstatic.com/generate_204
    interval: 600

  - name: Developer Services
    type: select
    proxies:
      - Node Selection
      - Automatic Selection
      - DIRECT

  - name: Final Match
    type: select
    proxies:
      - Node Selection
      - DIRECT

This structure separates “how nodes are selected” from “where a service is routed.” use references a proxy-providers name, while proxies references specific node or other proxy group names. They are not interchangeable. When a subscription contains many nodes, use a provider with filter conditions to maintain candidates instead of manually editing proxies after every update. If the client's override system can append entries to a group, keep the same separation: providers manage node sources, while local proxy groups manage business semantics.

Groups must not form circular references. For example, if “Node Selection” contains “Automatic Selection” and “Automatic Selection” also includes “Node Selection” in proxies, the final exit cannot be determined. When editing, trace backward from the end of a rule: the rule targets a business group, the business group targets the main entry point, and the entry point ultimately targets a node or DIRECT. Every chain should terminate. Built-in policies such as REJECT and DIRECT do not need same-named nodes.

When validating a proxy group, first explicitly select the expected option in the client, then close existing connections in the target application and issue a new request. Check the connection record for the rule type, rule content, proxy group, and final node. If the interface still shows the old group name, the active configuration probably has not been reloaded. If new nodes are missing, check whether the provider updated successfully and whether the filter expression excluded every node. For a fuller explanation of rule priority, continue with Custom rule syntax and matching priority.

02 / RULE PROVIDERS

Managing rules as subscriptions

Separate rule content from the main configuration

As the rule count grows, keeping everything in the main configuration's rules creates three problems: updates can overwrite local edits, duplicate domains become difficult to track, and loading failures are hard to attribute to a specific batch. rule-providers declares the source, behavior type, file path, and refresh interval for external rule sets. The main rule section only uses RULE-SET to determine their position in matching order and the proxy group used when they match.

Rule providers do not bypass top-to-bottom matching. Whether RULE-SET,developer,Developer Services appears before or after mainland-China direct rules directly changes the result for overlapping domains. Plan business priority first, then order rule sets; do not sort them by downloaded filename or size. Put high-confidence custom domains first, followed by LAN and required direct rules, broader regional collections later, and finish with MATCH for everything else.

Provider fields explained

rule-providers:
  developer:
    type: http
    behavior: domain
    format: yaml
    path: ./ruleset/developer.yaml
    url: https://example.com/rules/developer.yaml
    interval: 86400

  private-network:
    type: file
    behavior: ipcidr
    format: text
    path: ./ruleset/private-network.txt

rules:
  - RULE-SET,developer,Developer Services
  - RULE-SET,private-network,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,Final Match

type: http tells the core to fetch and cache the payload from url; type: file reads only a local file. The example domain illustrates the structure and should be replaced with a rule source you have verified as reachable. path specifies the cache or local rule-file location. Providers in the same configuration should not share a path, or later writes may overwrite earlier files. The base directory for relative paths depends on the working directory assigned to the core; desktop clients usually map it to their own configuration directory rather than the terminal's current directory.

behavior determines how the rule payload is interpreted. domain suits domain collections, ipcidr suits IPv4 and IPv6 networks, and classical allows each line to carry a complete rule type. With the wrong choice, a file may download successfully but fail to match as intended. For example, declaring content containing DOMAIN-SUFFIX,example.com as domain data gives it the wrong parsing model. Check the source's actual format first; do not infer behavior from the file extension.

format describes the payload encoding, commonly yaml, text, or a binary rule format supported by the core. Each format has a different structure. A YAML domain provider commonly uses a top-level payload array, while text format usually stores one entry per line. If the source explicitly provides Mihomo format, follow its instructions. Do not treat an ordinary hosts file, ad-blocking syntax, or browser-extension rules as a Clash rule set.

interval is measured in seconds and controls the update-check period; it does not mean the first fetch must wait that long after configuration loading. Avoid intervals that are too short: rule sources usually change less often than node status, and frequent fetching only adds startup and network overhead. If the client offers an “Update rule providers” action, trigger it once after changing the source, then use the logs to verify the HTTP status, parsing result, and cache path.

Domain sets, IP sets, and no-resolve

Domain rules are most direct while the request still retains its domain information. IP-CIDR rules target the destination IP. When an IP rule ends with no-resolve, it means the core should not actively resolve the domain to obtain an IP while evaluating that rule. It does not disable DNS or prevent an application from resolving the name itself. For a connection made directly to an IP, the core can still match that IP. Whether to add the parameter depends on whether the preceding DNS and sniffing flow already provides enough information and whether the rule is worth the extra lookup.

Rule-set contents behavior Typical payload Common uses
Domains and domain suffixes domain example.com+.example.org Website and service grouping
IPv4/IPv6 networks ipcidr 192.0.2.0/24 Regional networks and private networks
Complete rule lines classical DOMAIN-SUFFIX,example.com Combining multiple rule types

Troubleshooting order when updates fail

First distinguish a fetch failure from a parsing failure. Fetch failures usually appear in the logs as connection, certificate, timeout, or HTTP-status errors. A parsing failure usually means the file was retrieved but its fields, indentation, behavior type, or format is invalid. Next, check whether the URL is reachable through the current network path. Routing for rule-provider downloads depends on the core's startup stage and configuration; during the first load, relying on a policy that has not been created yet can create an ordering problem.

Then check that the cache directory is writable. When a desktop client manages the configuration through its GUI, avoid pointing path to a system-protected directory. Filenames must be unique, and directory paths should not depend on absolute locations that have not been created. Finally, confirm that the corresponding RULE-SET exists in the main rules and that its name matches the provider key. A provider that downloads successfully but is never referenced in rules only occupies cache space; it does not route traffic.

When a rule source is unreliable, keep a minimal working configuration with basic direct access, essential proxying, and final rules that do not all depend on remote files. If a provider cannot refresh temporarily, cached data or local baseline rules can still let the configuration start. For a complete mainland-China direct / outside-China proxy arrangement, see Routing ideas for mainland-China and outside-China traffic, then split stable large collections into providers using the method in this chapter.

03 / DNS

DNS optimization and leak troubleshooting

Understand DNS's place in the routing chain

DNS configuration is more than switching resolvers. After Mihomo DNS is enabled, the core must decide which upstream to query, which network path carries the query, whether to return real addresses or Fake-IP addresses, and how results participate in rule matching. An application may send requests to system DNS or use its own encrypted DNS; browsers may also enable Secure DNS. First confirm that requests actually enter the core—only then do nameserver changes become meaningful.

A common flow is: the application requests a domain, the system or TUN hands the DNS request to the core, the core selects an upstream according to domain rules, obtains a result or assigns a Fake-IP, then restores the domain and routes the connection when it is established. If an application bypasses system resolution and contacts its own DNS server, TUN routing, DNS hijacking, or application settings must bring that traffic into the same path. Changing the system DNS address to a public service does not automatically ensure that every query follows Clash policy.

A troubleshooting-friendly baseline configuration

dns:
  enable: true
  listen: 0.0.0.0:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter-mode: blacklist
  fake-ip-filter:
    - "*.lan"
    - "localhost.ptlogin2.qq.com"
    - "+.stun.*.*"
  default-nameserver:
    - 223.5.5.5
    - 1.1.1.1
  nameserver:
    - https://dns.alidns.com/dns-query
    - https://cloudflare-dns.com/dns-query
  proxy-server-nameserver:
    - https://dns.alidns.com/dns-query
  direct-nameserver:
    - https://dns.alidns.com/dns-query
  respect-rules: true

default-nameserver is mainly used to resolve the hostnames of encrypted DNS upstreams, so it is usually filled with directly reachable IP addresses. This avoids a loop in which the DNS server's hostname must be resolved before connecting to that same server. It is not the default final answer source for every business domain. nameserver is the main upstream for ordinary queries and can use traditional DNS IPs or encrypted DNS addresses supported by the core.

proxy-server-nameserver resolves the proxy server's own hostname. If a node address is a domain, the core must obtain its real IP before establishing the proxy connection; this step cannot depend on a proxy chain that does not yet exist. The upstream should be reliably reachable through the current direct network. If node addresses are already IPs, this setting matters less, but keeping a clear bootstrap-resolution path still helps when switching subscription sources.

direct-nameserver can specify a resolution path for domains expected to connect directly. When combined with respect-rules, pay close attention to dependencies between rules and DNS. An overly complex setup can require the query to know the rule while the rule depends on the query result. During troubleshooting, start with a few known-reachable upstreams, verify ordinary queries and proxy-node resolution, then add domain-based nameserver-policy rules.

Using nameserver-policy precisely

dns:
  nameserver-policy:
    "geosite:cn":
      - https://dns.alidns.com/dns-query
    "+.example.internal":
      - 192.168.1.1
    "rule-set:developer":
      - https://cloudflare-dns.com/dns-query

nameserver-policy selects a DNS upstream by domain, making it useful for internal domains, specific services, or regional resolution requirements. It determines “where to ask,” not the proxy policy for the connection. A domain resolved by local DNS is not necessarily connected directly; rules still decides that. Conversely, obtaining an address through remote encrypted DNS does not mean the business connection must use a proxy. Separating resolution paths from connection paths prevents many apparently contradictory results.

When a router or corporate DNS must answer internal domains, assign a LAN DNS server to the specific suffixes. Do not send broad wildcards to the internal server, or leaving that network will cause widespread timeouts. If a laptop frequently changes networks, put office-only rules in a separate override and enable them when needed rather than permanently adding them to the main configuration.

IPv6, caching, and fallback behavior

ipv6: false usually means the DNS module will not return AAAA records; it does not disable IPv6 at the operating-system level. If an application obtains an IPv6 address through another resolution path or connects to IPv6 directly, it may still bypass the intended route. When the network lacks stable IPv6, proxy nodes do not support IPv6, or rule sets cover only IPv4, disabling AAAA responses can reduce connection delays. If IPv6 is required, also check TUN routing, rule sets, and exit capabilities.

DNS caching can delay the visible effect of a change. After reloading the configuration, clear the client's internal cache; if needed, also clear the operating-system and browser caches and establish a new connection. Do not judge rules by repeatedly refreshing the same open browser tab: HTTP/2, HTTP/3, and connection pools may continue reusing an old connection. The reliable method is to close the target application's connections, clear caches, reload the configuration, and retest alongside DNS logs and connection records.

Symptom Check first Common cause
Node hostname cannot be resolved default-nameserverproxy-server-nameserver Bootstrap-resolution loop or unreachable direct upstream
Internal domain will not open nameserver-policy, Fake-IP exclusions Internal queries are sent to a public upstream
Old route remains after changing rules DNS cache, existing connections Old resolutions and connection pools are still being reused
Some applications do not appear in the logs Application Secure DNS, TUN routing The application bypasses system DNS or proxy settings

To determine whether DNS is working as expected, record four facts: the domain requested by the application, how the request entered the core, the upstream actually used, and the rule ultimately matched by the connection. A test site showing only “a DNS server” cannot distinguish browser Secure DNS, system caching, upstream forwarding, or core configuration. For complex failures, continue in the Help Center, checking DNS, system proxy settings, and connection logs in that order.

04 / TUN & FAKE-IP

Coordinating TUN mode and Fake-IP

System proxy and TUN coverage

A system proxy affects only applications that follow the operating system's proxy settings. Browsers and most desktop software usually do, but command-line tools, games, virtual machines, some store apps, and software with its own network stack may ignore them. TUN mode creates a virtual network interface and uses system routes to pass more TCP and UDP traffic to the core, so its coverage is broader. The trade-off is that it also affects routing, DNS, and interface selection; configuration errors therefore have more visible consequences than ordinary system proxy settings.

Before enabling TUN, confirm that nodes, rules, and DNS work in ordinary proxy mode. Otherwise, once TUN is active, node failures, DNS loops, and routing conflicts can overlap and obscure the root cause. Recommended order: verify node connectivity, verify rule matches, enable TUN, then enable DNS hijacking and Fake-IP. Change only one group of variables at a time and keep a configuration copy you can restore.

TUN fundamentals

tun:
  enable: true
  stack: mixed
  dns-hijack:
    - any:53
    - tcp://any:53
  auto-route: true
  auto-detect-interface: true
  strict-route: true
  mtu: 1500

dns:
  enable: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16

stack determines which network stack handles TUN traffic. Common Mihomo options include system, gvisor, and mixed. The system stack usually follows the direct performance path; the gVisor userspace stack has different compatibility characteristics on some platforms, while mixed combines processing modes. There is no universal best choice. If the default is stable, do not switch merely to make the configuration more elaborate. For UDP, LAN access, or game-specific issues, test the network stack as an isolated variable.

auto-route lets the core add required routes automatically, while auto-detect-interface identifies the current default exit interface. Automatic detection is convenient on laptops switching among Ethernet, Wi-Fi, hotspots, and VPNs; servers, multi-homed hosts, and policy-routing environments may need an explicit interface. If logs show traffic repeatedly entering TUN, or the proxy-node connection itself being sent back into TUN, check the exit interface, route exclusions, and any existing VPN for a loop.

strict-route applies tighter constraints to traffic passing through TUN, with platform-specific effects and permission requirements. It can reduce some bypasses but may also expose routing conflicts that the system previously handled automatically. If LAN printers, shared folders, or virtual-machine networks become unreachable, check private-network rules and route exclusions first rather than sending every LAN address through the proxy.

dns-hijack hands DNS traffic on specified ports to the core. any:53 covers common UDP queries; adding TCP handling covers retries after truncated responses. It cannot automatically intercept every application using DNS over HTTPS or DNS over TLS; such traffic looks like an ordinary encrypted connection and must be handled through application settings, domain rules, or the complete routing path. Whether hijacking is needed depends on whether the application follows system DNS.

How Fake-IP works

When Fake-IP mode receives a domain query, it does not immediately return the real destination address to the application. Instead, it assigns a mapped address from a reserved pool. When the application connects to that address, the core uses the mapping to restore the original domain, then applies domain rules and proxy routing. Even if the application carries only an IP afterward, the core retains the domain context, making domain-based routing more reliable and reducing dependence on obtaining a real address locally before choosing a policy.

198.18.0.0/15 is a reserved range intended for benchmark testing and is commonly used by Fake-IP. The configured pool must not conflict with existing LANs, container networks, lab networks, or corporate routes. If the current network uses the same range, the system may treat Fake-IP addresses as real routing targets. Choose a non-conflicting reserved range, then restart related connections and clear the DNS cache so old mappings are no longer used.

Some protocols require real addresses or validate DNS behavior and are unsuitable for Fake-IP responses. Common examples include LAN hostnames, STUN, connectivity checks, specific game-discovery protocols, and certain device-control services. Put them in fake-ip-filter. Keep exclusions as precise as possible: confirm the domain in the logs first, then add a suffix or wildcard pattern. Excluding broad domain ranges removes much of Fake-IP's domain-preservation advantage.

MTU, UDP, and LAN access

When the MTU is too large, some tunnels, mobile networks, or stacked VPNs can suffer fragmentation and packet loss, appearing as stalled webpage resources, TLS handshake timeouts, or unstable UDP. An MTU that is too small increases packet count and processing overhead. Do not lower it blindly because one website is slow. First confirm that the issue occurs only under TUN, compare different networks and protocols, and look for retransmissions or handshake failures in the logs. Make recorded, incremental changes and test after restarting TUN.

LAN access requires checking both rules and routing. Rules can send RFC1918 private ranges, link-local addresses, and actual LAN domains to DIRECT, but DIRECT only means the connection avoids proxy nodes; it does not guarantee that the operating system routes it through the correct interface. If TUN automatic routing takes over the LAN path, also check route exclusions and strict-route settings. Sharing a proxy with devices on the same network additionally requires a listen address, allow-lan, and firewall configuration; see Mixed ports and LAN proxy sharing.

Scope of the issue Comparison test Next step
Only the system proxy works Recovers when TUN is disabled Check routing, interface detection, and permissions
Domain rules do not work Check Fake-IP mappings and sniffing results Check whether DNS actually enters the core
LAN devices are unreachable Inspect the target subnet and exit interface Add direct rules and route exclusions
UDP application behaves abnormally Change the network stack and test separately Check node UDP support and MTU

05 / SNIFFER

Domain sniffing and connection restoration

What sniffing solves

The rule system is best at classifying traffic by domain, but some applications expose only the destination IP when establishing a connection. Domain sniffing identifies the HTTP Host, the SNI in a TLS ClientHello, or a destination domain in a supported protocol from early connection data, then uses the recovered domain for rule matching. It does not decrypt HTTPS bodies or read page content; the visible information comes from domain fields already carried during the protocol handshake.

Sniffing and Fake-IP both preserve domain context, but through different paths. Fake-IP creates a domain-to-mapped-address relationship during DNS resolution; sniffing restores the domain from protocol data as the connection is established. They can be enabled together: Fake-IP handles connections using the core's DNS, while sniffing covers cases that bypass that resolution path or use a destination IP directly. If DNS already provides stable mappings, do not blame every failure on sniffing.

Limit scope by protocol and port

sniffer:
  enable: true
  force-dns-mapping: true
  parse-pure-ip: true
  override-destination: false
  sniff:
    HTTP:
      ports:
        - 80
        - 8080-8880
      override-destination: true
    TLS:
      ports:
        - 443
        - 8443
    QUIC:
      ports:
        - 443
  skip-domain:
    - "Mijia Cloud"
    - "+.push.apple.com"
  skip-src-address:
    - 192.168.0.0/16
  skip-dst-address:
    - 192.168.0.0/16

parse-pure-ip allows sniffing attempts on connections that initially appear to target a bare IP, which is useful when supplementing domain-based routing. force-dns-mapping works with DNS mappings and uses relationships that already exist. Client-provided core templates may adjust the defaults, so inspect the actual runtime configuration before editing rather than relying only on the subscription source.

override-destination determines whether, after a domain is identified, the sniffed result replaces the original destination for the subsequent connection. Enabling it can improve domain routing in some cases, but misidentification has more direct effects. Start by enabling it for clearly defined protocol sections such as HTTP instead of applying it globally. Afterward, check the original destination, sniffed domain, and final rule in connection details to confirm the change is expected.

A wider port range does not guarantee better detection. The sniffer parses the beginning of a connection by protocol; forcing attempts on ports that are clearly not HTTP, TLS, or QUIC only increases false positives and processing cost. Add nonstandard service ports according to the actual application. For example, if an internal HTTPS service runs on 9443, add that port to the TLS range; do not hand every port to TLS sniffing just to cover it.

QUIC, ECH, and visibility limits

QUIC usually runs over UDP, and detection depends on the core, network stack, and available handshake information. A browser may fall back to TCP/TLS after a network change, so connection records for the same site can show different protocols. During troubleshooting, observe TCP and UDP separately rather than judging from one visit. If the node or network has unreliable UDP support, temporarily disable QUIC in the application for comparison, but use that only as a diagnostic step—not as a substitute for checking the real UDP path.

Encrypted client greetings and similar mechanisms reduce the domain information visible to intermediaries. When a handshake contains no readable domain, sniffing cannot recover the service name from nothing. Rely instead on core DNS, Fake-IP mappings, application-process rules, or destination-IP rules. The goal is to make several reliable information sources complement one another, not to make sniffing cover every connection.

Shared CDN IPs are another reason sniffing is valuable. An IP-only rule may treat multiple unrelated domains on the same address identically, and broad network-based routing can affect other services. When a domain is available, prefer domain rules. Fall back to IP-CIDR, GEOIP, or the final rule only when the connection truly has no domain context.

Skip lists and false-positive handling

skip-domain skips domains known to be unsuitable for sniffing or destination overrides; skip-src-address and skip-dst-address exclude specific source or destination ranges. When smart-home devices, casting, LAN discovery, or vendor push services behave abnormally, use logs to identify the exact connection first, then add the narrowest exclusion. Skipping the entire private network is simple but may deprive local containers or development environments of the domain information they need for routing.

If the identified domain does not match the application's expected target, first check whether the destination passes through a CDN, redirect, or third-party static resource. A page commonly connects to its main domain, login domain, image domain, and analytics endpoints, so multiple names in the connection list are normal. A genuine false positive usually appears when a previously working connection fails after destination override is enabled; disabling override-destination for that protocol restores it, while the logged sniffed domain clearly disagrees with the certificate or service target.

Log symptom Meaning Recommended action
Only an IP appears for the destination No usable mapping or protocol information Check the DNS path, port range, and protocol support
A domain is identified but an IP rule still matches Rule order or override settings did not use the domain Check the domain-rule position and override setting
The application recovers when sniffing is disabled Possible false positive or incompatible destination override Narrow the port range and add precise exclusions
TCP works, UDP fails The QUIC and TLS paths differ Check TUN, node UDP support, and QUIC separately

Process rules can supplement domain rules, but the ability to obtain process information, required permissions, and accuracy vary by platform. Mobile app sandboxes, system services, and containers require particular care. Prefer stable domain rules when available; use process rules only when no domain exists and process data is reliable; use IP ranges and the final rule only when neither is available. This fallback order is easier to maintain across platforms than binding all traffic to application names.

06 / OVERRIDES

Local overrides and subscription merging

Treat remote subscriptions as inputs, not finished configurations

Remote subscriptions primarily provide nodes, though they may also contain proxy groups, rules, and DNS settings. Editing the YAML generated by a subscription directly usually means losing those changes at the next update. A safer structure treats the subscription as an updatable input and keeps long-lived rules, policy names, DNS, and TUN parameters in a local override layer. The client reapplies the override after each subscription update, keeping the runtime configuration consistent.

Clients differ in both terminology and override capabilities; the feature may appear as a script, extension configuration, merged configuration, or preprocessing step. With clients such as Clash Plus, use the configuration entry points actually provided by the interface. Whatever the method, distinguish three artifacts: the raw remote subscription, the local override source, and the final runtime configuration. The last one matters most during troubleshooting, because a successful save in the interface does not guarantee the merge result is correct.

How mappings and arrays merge differently

A YAML mapping consists of key-value pairs, such as enable under dns; an array is an ordered list, such as rules and proxy-groups. Mappings can usually be overridden by key, while arrays require a choice among replacement, prepending, appending, and deduplication. If a merge tool replaces arrays wholesale, adding one local rule may delete every rule from the subscription. If it appends, placing a critical custom rule at the end may mean it never matches.

First determine the client's merge semantics, then design the override. Rule arrays usually need prepending so precise local rules appear before broad ones; proxy-group arrays often need replacement or appending by name; DNS mappings are well suited to key-based overrides. Do not assume every feature called Merge behaves the same way. After updating a client or moving platforms, export the final configuration and compare it again.

# Logical example for local maintenance; use the client's actual merge entry point
prepend-rules:
  - DOMAIN-SUFFIX,example.internal,DIRECT
  - DOMAIN-SUFFIX,github.com,Developer Services

override:
  mode: rule
  log-level: info
  dns:
    enable: true
    enhanced-mode: fake-ip

append-proxy-groups:
  - name: Local Services
    type: select
    proxies:
      - DIRECT
      - Node Selection

The prepend-rules, override, and append-proxy-groups above illustrate merge intent; they are not universal top-level keys in a Mihomo main configuration. A client may instead use a GUI form, a JavaScript processing script, or its own extension syntax. Do not paste this block directly into the core configuration. The result handed to the core should still contain standard fields such as rules, proxy-groups, and dns.

Combine multiple node sources with providers

proxy-providers:
  provider-a:
    type: http
    url: https://example.com/subscription/a
    path: ./providers/a.yaml
    interval: 21600
    health-check:
      enable: true
      url: https://www.gstatic.com/generate_204
      interval: 600

  provider-b:
    type: http
    url: https://example.com/subscription/b
    path: ./providers/b.yaml
    interval: 21600
    filter: "(?i)香港|HK|Hong Kong"
    health-check:
      enable: true
      url: https://www.gstatic.com/generate_204
      interval: 600

proxy-groups:
  - name: All Nodes
    type: select
    use:
      - provider-a
      - provider-b

  - name: Hong Kong Auto
    type: url-test
    use:
      - provider-a
      - provider-b
    filter: "(?i)香港|HK|Hong Kong"
    url: https://www.gstatic.com/generate_204
    interval: 600

proxy-providers lets multiple subscriptions update and cache independently, then lets proxy groups reference them through use. It is easier to troubleshoot than concatenating subscription text: if one source fails, the other providers can still load. Every provider must use a different path. Subscription URLs are sensitive configuration and should not appear in log screenshots, public rule repositories, or shared configurations; the address in the example is structural only.

filter usually selects nodes by name, so the regular expression should reflect the subscription's actual naming. An empty group after filtering is a common multi-subscription failure. First inspect the node names actually loaded by the provider, then test the expression; do not write it based only on a Chinese region name. (?i) can ignore Latin-letter case where supported, but Chinese aliases, flag symbols, and abbreviations still need to match the source.

When two sources contain nodes with the same name, interface identification and policy references can become ambiguous. The safest approach is to add a source prefix during preprocessing or have the subscription provider maintain unique names. If the client supports provider-level prefixes, add short markers such as “A-” and “B-” consistently at the merge layer. Do not distinguish nodes by their position, because subscription updates can reorder them.

Isolating failures during multi-subscription updates

When an update fails, inspect providers one at a time instead of deleting every cache. Check request success first, then YAML parsing, then whether nodes remain after filtering, and finally whether proxy groups reference them correctly. One failed provider should not remove DIRECT or local fallback groups from the baseline configuration. The main entry point can include groups generated by several independent providers, allowing manual switching when one source has a problem.

Also check port conflicts, duplicate policy names, and missing rule targets in the merged configuration. Merging several complete subscriptions often duplicates mixed-port, external-controller, the DNS listen address, and a group named “Node Selection.” Node sources can be multiple, but control ports and core policy structure should each have one authoritative definition. Keep these global fields in the local layer and let remote inputs provide nodes only; this minimizes maintenance.

Content Recommended owner Reason
Node parameters Remote provider Must update with the subscription
Business proxy groups Local override Names must remain stable for local rules
DNS and TUN Local override Depends on the device and current network
Large public rule sets rule provider Update independently and keep the main configuration smaller
A small number of precise rules Front of the local rule list Makes priority easy to control and corrections quick

When moving between clients, do not export only the subscription URL. Also record local proxy group names, rule-set sources, override order, Fake-IP exclusions, and provider paths. Extension merge syntax varies between clients, but standard Mihomo configuration can be reused. Build a minimal configuration in the new client first, then migrate providers, policies, rules, and TUN layer by layer. This avoids importing a large set of extensions at once and ending up with a configuration that will not start.

07 / CONTROLLER

External controllers and the security boundary

What the controller can do

Mihomo's external controller lets desktop clients or web panels read runtime status, switch policies, view connections and logs, and reload configuration. It is not an ordinary proxy port and has significantly higher privileges. A desktop client's built-in interface usually manages the core through a local controller; manually expanding the listen scope is needed only for an independent web panel, remote administration, or another tool.

The controller API and the panel's static files are separate. external-controller defines the API listen address, while external-ui points to the local panel directory. After the panel opens in a browser, it still needs to connect to the API to display policies and connections. If the page loads but shows no data, the usual causes are the controller address, authentication, CORS permissions, or a protocol mismatch—not damaged panel files.

Minimal configuration for local use

external-controller: 127.0.0.1:9090
secret: "your-password"
external-ui: ./ui
external-ui-name: metacubexd

external-controller-cors:
  allow-origins:
    - http://127.0.0.1
    - http://localhost
  allow-private-network: true

For local-only administration, listen on 127.0.0.1. This keeps the control port off LAN interfaces. secret authenticates API requests; replace the example with your own strong random string and keep it in the local configuration. When the panel asks for a key, enter this value. Restart or reload the core after changing it, and update the panel's connection settings as well.

external-ui is the directory containing the panel's static resources. Some clients download and manage the panel themselves, so no manual setting is needed. For a self-hosted panel, confirm that the directory exists and that the core process can read it. Whether external-ui-name takes effect depends on the current core and download mechanism. If the interface still shows old content, check the actual directory, browser cache, and whether the client has overridden the field.

CORS permissions determine which webpage origins may call the controller API from a browser. List exact combinations of scheme, host, and port rather than opening access broadly. When the panel is served by a local static server, the browser origin may be http://127.0.0.1:port; opening it directly through the file protocol has different restrictions. Check the rejected Origin in browser developer tools, then add a precise entry.

Additional constraints for LAN administration

external-controller: 0.0.0.0:9090
secret: "your-password"

external-controller-cors:
  allow-origins:
    - http://192.168.1.20:8080
  allow-private-network: true

Listening on 0.0.0.0 binds the controller to every available network interface and should be used only when LAN administration is genuinely required. Also restrict sources in the system firewall to a trusted subnet or specified management devices; do not rely solely on the panel's login form. The key entered in the panel authenticates API calls, but the network layer should still prevent untrusted devices from reaching the port.

If the device connects to public Wi-Fi, listening on every interface for an extended period carries greater risk. Use the operating system firewall to distinguish private and public networks, or restore loopback-only listening when remote access is unnecessary. Do not expose the controller port directly to the internet. A safer approach is to establish a controlled private network tunnel first, then connect as though accessing a LAN service while retaining API authentication.

The proxy port’s allow-lan setting is separate from the control API’s listening scope. Allowing LAN devices to use mixed-port does not require exposing the control API to the LAN; conversely, binding the control API to all addresses does not make the proxy port available automatically. Check proxy listening, control listening, the system firewall, and authentication separately so that fixing one does not unnecessarily widen another’s access.

Troubleshooting path for panel connections

First confirm that the core is listening on the expected address and port. If another program occupies the port, the core logs usually show a bind failure; the client may also switch to its own controller port, so use the runtime configuration and logs as the source of truth. Next, test API reachability on the same device, then test the panel. If the API itself is unreachable, fix listening and firewall settings before repeatedly clearing browser caches.

Third, check authentication. An unauthorized response usually means the key is missing, incorrect, or was not sent by the panel. Do not copy extra spaces, and do not treat the YAML wrapper quotes as part of the key. Fourth, check CORS. A cross-origin rejection in the browser console may mean the API responded but the browser blocked the panel from reading it; add the panel's exact origin rather than disabling all origin restrictions.

Fifth, check the protocol and address. When an HTTPS page calls an HTTP controller, the browser may block the request as mixed content. In the panel, localhost refers to the device running the browser; if the panel is opened on a phone, localhost is the phone, not the computer running Mihomo. For LAN access, enter the computer's address on that LAN and confirm that the firewall allows the phone's connection.

Symptom Likely layer Check
Panel page will not open Static files or web service Check the external-ui directory and access address
Page opens but shows no data API address, authentication, or CORS Inspect browser network requests and the console
Works locally but not from a phone Listen address or firewall Check whether it is bound only to 127.0.0.1
Unauthorized response secret values do not match Re-enter the key and check for spaces
Policy switch takes effect immediately Configuration reload or client management Check whether the client reapplied the subscription configuration

Logs, connection details, and minimal exposure

A control panel can display visited domains, destination addresses, process information, and policy choices—all of which reveal network usage on the device. Before sharing troubleshooting screenshots, redact subscription names, node addresses, controller keys, internal addresses, and unrelated browsing records. Keep the log level only as detailed as troubleshooting requires; leaving verbose logging enabled increases storage use and information exposure.

Before using a third-party panel, understand that it is an API client, not a replacement for core configuration. A policy switch is usually a runtime operation, and whether it survives a configuration reload depends on the client and group type. To make a policy persistent, set it in the local configuration or the client's persistence mechanism rather than clicking it once in a web panel. When subscription updates regenerate proxy groups, changed names can also prevent the previous selection from being restored.

After finishing the configuration, perform an end-to-end check: restart the client and confirm that the controller port is listening; open the panel from an allowed device and authenticate with the key; switch a select group and observe a new connection; reload the configuration and confirm the expected state; finally, test from an untrusted interface that the port is unreachable. This verifies not just that the panel opens, but also authentication, access boundaries, and configuration persistence.

If the client will not start after changing the controller, restore the loopback address first and temporarily remove external-UI extension fields so the core configuration can load. Then add settings back one at a time. Common causes include a port conflict, invalid YAML indentation, a field already managed by the client, or an invalid panel directory. For other startup and configuration-loading issues, search the error logs in the Help Center; if you need to reinstall, choose the current-platform client on the download page.