YAML Structure and Load Order
The top-level mapping tells the core what to load
A Clash configuration file is essentially a YAML document. Its outermost level usually contains key-value pairs: ports and runtime options use scalars, dns uses a nested mapping, and proxies, proxy-groups, and rules use lists. At startup, the core parses the YAML syntax, validates field types and references, then creates the listening ports, DNS module, proxy outbounds, proxy groups, and rule tree. A file that parses successfully is not necessarily runnable. For example, a proxy group that references a nonexistent node may not fail until configuration validation.
YAML expresses nesting through indentation rather than braces. Use two spaces consistently and never mix tabs into the same file. Put a space after each colon; list items begin with a hyphen and a space. Quote names containing colons, hash signs, asterisks, brackets, or leading or trailing spaces so the parser does not treat them as syntax. Node names may contain non-Latin text, but proxy group names and rule targets are referenced repeatedly, so shorter names are easier to inspect.
mixed-port: 7890
mode: rule
log-level: info
ipv6: false
dns:
enable: true
listen: 0.0.0.0:1053
enhanced-mode: fake-ip
proxies:
- name: "Example-Node-A"
type: ss
server: 192.0.2.10
port: 443
cipher: aes-128-gcm
password: "your-password"
proxy-groups:
- name: "Node Selection"
type: select
proxies:
- "Example-Node-A"
- DIRECT
rules:
- DOMAIN-SUFFIX,example.com,Node Selection
- MATCH,DIRECT
The example forms a minimal working loop: inbound traffic enters through mixed-port, DNS queries go to the DNS module, rules route requests to “Node Selection,” and the proxy group chooses a specific node or DIRECT. If proxy-groups is removed, rule targets must name a node directly or use a built-in action. If rules is removed, rule mode generally cannot provide complete routing behavior. Real subscriptions contain more nodes, but the relationships remain the same.
Scalars, lists, and mappings are not interchangeable
mode: rule is a scalar, not a list; rules is an ordered list and cannot be changed into a mapping keyed by rule type; dns is a mapping whose child fields each have their own type. Write Boolean values as lowercase true or false; do not replace them with “yes,” “no,” or quoted strings. Ports should be integers. Although "7890" may be accepted by some clients, it increases compatibility differences.
Anchors and aliases are built into YAML. For example, use &common to define shared parameters, then merge them with <<: *common. This reduces repetition but is not ideal for subscription configurations synchronized across multiple clients, because some override tools expand or discard anchors during serialization. For long-term maintenance, write critical fields explicitly and use anchors only when the entire import chain is known to preserve YAML semantics.
Load Paths, Subscription Files, and Runtime Configuration
Graphical clients usually download a remote subscription into a local configuration directory, then pass the selected configuration to the mihomo core. The configuration name, subscription URL, and update time shown in the interface belong to the client management layer and may not appear in the YAML. The core processes only the final generated file. Some clients also apply scripts, global overrides, or local patches before loading, so an exported file may differ from the original response returned by the subscription server.
When troubleshooting a parse failure, first distinguish the download stage from the parsing stage. Opening a subscription URL in a browser only proves that the server responded; it does not prove that the response is YAML. If the server returns a login page, rate-limit notice, or JSON error object, the client may still save it and then report a syntax error at the first line. Follow the subscription parsing failure checklist to verify the response status, content type, indentation, and cache. When editing manually, keep a copy of the original, make small batches of changes, adjust one structural section at a time, and validate again.
| Top-Level Field | Data Type | Primary Purpose | Common Error |
|---|---|---|---|
mixed-port |
Integer | Accepts both HTTP and SOCKS proxy connections | Port already in use by another process |
dns |
Mapping | Defines the listening address, upstreams, and enhanced mode | Child fields indented to the top level |
proxies |
List | Declares static proxy nodes | Required protocol field missing |
proxy-groups |
List | Organizes nodes and selection logic | Reference name does not match |
rules |
Ordered list | Determines request routing by declaration order | Fallback rule appears too early |
General Fields: Ports, Modes, and Control Interfaces
Inbound Ports and LAN Access
port provides HTTP proxy access only, socks-port provides SOCKS5 proxy access only, and mixed-port supports both on one port. Desktop clients commonly use mixed-port so the system proxy, browser, and SOCKS-capable tools can share one listener. You do not need to enable all three. If you configure more than one, they must use different ports or the core cannot bind the listening addresses. Port numbers do not accelerate the network; they only need to be unused and match the system proxy settings.
allow-lan controls whether devices on the local network may connect. With false, access is normally limited to the local machine; with true, also check bind-address, the operating system firewall, and router isolation settings. Opening a LAN listener expands the reachable surface, so configure authentication or restrict firewall sources as well. Never expose a proxy port directly to the public Internet. When a mobile device uses a computer’s proxy, enter the computer’s LAN address and Clash inbound port, not the remote proxy server address.
mixed-port: 7890
allow-lan: false
bind-address: "*"
authentication:
- "local-user:your-password"
mode: rule
log-level: info
ipv6: false
unified-delay: true
tcp-concurrent: true
Enable allow-lan only when LAN sharing is actually needed. Some clients override the YAML value with an interface toggle, so return to the runtime status page after editing and confirm the effective listening address. If the system proxy is enabled but the browser cannot connect, first check the client log for “address already in use,” then verify that the system proxy still points to the correct port. Windows app containers may also be affected by UWP loopback restrictions; that is a system network permission issue, not a rule-field problem.
mode determines whether rules participate in routing
Common mode values are rule, global, and direct. In rule mode, requests are matched against rules in order; in global mode, traffic generally goes to the global proxy group; in direct mode, connections are established directly without ordinary rule routing. Keep rule mode during configuration debugging because it most closely reflects normal long-term use. Temporarily switching to global mode can show whether a fault is caused by rules, but it does not prove that DNS, nodes, or the system proxy are all working.
The mode switch in a graphical client is often runtime state. After a subscription refresh, the client may retain the previous selection or reapply the YAML mode. For predictable behavior, check both the configuration file and the client’s global override settings. In rule mode, “a website uses the wrong policy” should be investigated through rule-match logs. In global mode, every request enters the same policy, so changing domain rules has no effect—one of the most common troubleshooting context gaps.
Logs, IPv6, and Concurrent Connections
log-level controls log detail. Common values include silent, error, warning, info, and debug. Keep info for everyday use; switch temporarily to debug when tracing parsing, handshakes, or rule matches, then switch back to avoid burying key details in noise. Domains, node names, and destination addresses in logs may reveal browsing activity, so remove sensitive data before sharing troubleshooting screenshots.
ipv6 determines whether the core handles IPv6-related resolution and connections. Disabling it does not completely disable IPv6 in the operating system; it only makes Clash’s corresponding module use restricted behavior. Enable it when the network, proxy nodes, and upstream DNS all have reliable IPv6 support. If some sites return AAAA records first but cannot connect, compare the DNS results with the node’s capabilities instead of repeatedly changing rules. tcp-concurrent enables concurrent connection attempts to resolved addresses, which may reduce wait times for multi-address destinations but increases the number of short-lived connections.
unified-delay makes latency tests use a more consistent calculation method. It changes how proxy-group test results should be interpreted; it does not make an unavailable node usable. A latency test describes connectivity to the test address only. Real access also depends on the destination, protocol handshake, egress quality, and rule path, so nodes should not be ranked by a single number. See Latency, Multipliers, Regions, and Protocols for node-selection guidance.
External Controller and Management UI
external-controller exposes the core’s control API, which graphical clients use to read connections, switch policies, and reload configuration. It commonly listens on a local address and port. If bound to a non-local address, configure secret and restrict sources with a firewall. external-ui points to a directory containing static management UI files; it does not download the UI automatically. Ordinary graphical clients already include a management layer, so separate configuration is unnecessary.
external-controller: 127.0.0.1:9090
secret: "your-controller-secret"
external-ui: dashboard
profile:
store-selected: true
store-fake-ip: true
profile.store-selected saves the selected proxy-group member so it can be restored after a restart; profile.store-fake-ip saves Fake-IP mappings to reduce changes after restarting. The actual persistence location depends on the client’s working directory. The configuration file declares intent only: if the client clears its cache directory at every startup, these fields cannot preserve state. For multi-device synchronization, do not copy the entire runtime directory. Sync subscriptions, overrides, and the specific configuration files you need, leaving lock files, caches, and platform-specific paths behind.
DNS Fields, Fake-IP, and Resolution Paths
The DNS module runs before connection decisions
Domain requests usually go through DNS resolution before rules and outbounds establish a connection. Clash’s DNS module does more than turn names into addresses: it affects whether domain information remains available to rules, how Fake-IP mappings are created, how different upstreams are routed, and which resolver handles proxy node server names. Many cases where “the proxy is connected but the page will not open” are actually caused by an unreachable DNS upstream, polluted results, incomplete Fake-IP filtering, or system requests bypassing the core.
dns.enable turns on the built-in DNS service, while listen defines its listening address. A desktop client may send queries into this module through system DNS interception, TUN, or a local port. Enabling DNS in YAML alone does not guarantee that the operating system uses it; the client must also configure system DNS correctly or enable the appropriate takeover method. Conversely, if another DNS service already occupies the port, the core may fail to start or skip listening.
dns:
enable: true
listen: 0.0.0.0:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
use-hosts: true
respect-rules: true
default-nameserver:
- 223.5.5.5
- 1.1.1.1
nameserver:
- https://dns.example/dns-query
- tls://dns.example:853
proxy-server-nameserver:
- 223.5.5.5
nameserver-policy:
"geosite:cn":
- 223.5.5.5
default-nameserver primarily resolves the hostnames of encrypted DNS upstreams, so it is usually filled with directly reachable IP addresses. If you put hostnames here, you can create a loop: resolving the upstream hostname requires the upstream, while using the upstream requires resolving its hostname. nameserver lists the main query upstreams and may use UDP, TCP, DoT, or DoH. dns.example in the example is fictitious; replace it with a real service.
proxy-server-nameserver resolves proxy node server hostnames specifically. If a node’s server is a hostname, the core must resolve it before establishing the proxy connection. Sending that lookup through a proxy chain that has not been established yet creates a dependency loop. Assigning a directly reachable resolver here separates node-hostname resolution from ordinary website lookups. Nodes written as IP addresses bypass this step but lose the ability to follow backend address changes behind a hostname.
How Fake-IP Preserves Domain Information
With enhanced-mode: fake-ip, the core first returns a mapped address from a reserved range to the application. When the application connects to that address, the core restores the original domain from its mapping table and applies the rules. This allows domain-based rules to work even when an application opens an IP connection. fake-ip-range should use a reserved test range and must not overlap with real LANs, corporate VPNs, or container networks.
Fake-IP is not a remote server address and is never sent to the public Internet. It is a temporary mapping maintained by the local core. Seeing a system connection to 198.18.x.x does not mean DNS is broken; the key question is whether Clash has taken over that connection. If an application bypasses the system proxy and TUN is not intercepting traffic, it will try to connect to the reserved address directly and time out. Check the takeover path rather than adding every domain to the filter list.
fake-ip-filter makes selected domains return real addresses. LAN services, network probes, time synchronization, some games, and services that rely on local discovery may not work well with mapped addresses. Keep the filter as precise as possible; broad wildcards remove domain visibility from many hosts and defeat the benefit of Fake-IP. After changing it, clear old DNS caches or restart affected applications, otherwise they may continue using previous results.
dns:
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "*.local"
- "localhost.ptlogin2.qq.com"
- "+.stun.*.*"
- "time.*.com"
- "time.*.gov"
Choosing Between redir-host and Fake-IP
redir-host returns real resolved addresses and has a more direct flow, often offering better compatibility for applications that require real IPs. In transparent proxy scenarios, however, the core may see only the destination IP and need sniffing or resolution mapping to recover the domain; domain-rule stability then depends on the interception chain. fake-ip is better suited to TUN setups that need to preserve domain information, but some programs do not accept reserved addresses. Choose based on the system takeover method and application compatibility, not as a node-speed switch.
respect-rules makes DNS queries follow the existing rules, but it requires the resolver and proxy policy to be free of circular dependencies. If the main DoH upstream requires a proxy while the proxy node’s hostname depends on that same DoH service, the initial connection may never complete. Provide a separate directly reachable resolver for node hostnames, or ensure that at least one basic upstream works without a proxy. When logs show repeated DNS timeouts, trace the dependency chain from its lowest layer.
The routing boundary of nameserver-policy
nameserver-policy selects DNS upstreams based on domains or geosite collections. It determines “where to ask DNS,” not whether the subsequent connection uses DIRECT or a proxy. Connection policy remains controlled by rules. If different upstreams return different addresses for the same domain, DNS routing indirectly affects the connection target. Keep DNS routing and rule routing aligned geographically to avoid resolving mainland domains through distant upstreams or receiving unsuitable results for proxy domains from local resolvers.
Troubleshoot DNS in three steps: confirm that system queries enter Clash; confirm that Clash can reach the specified upstream; then confirm that the returned addresses and rule matches are expected. Testing only a browser page cannot distinguish cache, HTTP/3, and system-proxy effects. Temporarily disable the browser’s secure DNS, clear application caches, and watch domain queries and connection records in the core log. For a fuller sequence, see the system proxy, DNS, and rule-mode checklist.
Proxy Node Fields and Protocol Parameters
Every node needs a unique name that can be referenced
Each item under proxies represents a static outbound node. Common fields include name, type, server, and port; the remaining fields depend on the protocol. name is the identifier referenced by proxy groups and rules and should be unique within the configuration. With duplicate names, a client may overwrite the earlier item or show two identical options, making it impossible to tell which one a rule actually uses. Subscription generators should preserve region or purpose in node names without stuffing them with lengthy announcements.
server may be an IP address or hostname, but must not include a protocol prefix or path. port is the remote service port, not the local mixed-port. When a connection fails, distinguish local inbound traffic from remote outbound traffic: the system proxy connects to the local port, then the core connects to the server specified by the node. Confusing these two ports is a common manual-configuration mistake.
proxies:
- name: "SS-Example"
type: ss
server: 192.0.2.20
port: 443
cipher: aes-128-gcm
password: "your-password"
udp: true
- name: "Trojan-Example"
type: trojan
server: proxy.example.com
port: 443
password: "your-password"
sni: gateway.example.com
skip-cert-verify: false
udp: true
- name: "VMess-Example"
type: vmess
server: 192.0.2.30
port: 443
uuid: "00000000-0000-4000-8000-000000000000"
alterId: 0
cipher: auto
tls: true
servername: edge.example.com
network: ws
ws-opts:
path: /proxy
headers:
Host: edge.example.com
The addresses and credentials in the example only demonstrate field relationships. Shadowsocks cipher must match the server; Trojan commonly connects over TLS, with sni sending the server name; VMess uuid, transport, TLS, and WebSocket parameters must match as a set. Changing one field in isolation rarely fixes a handshake failure and may instead make the client and server configurations inconsistent.
TLS, SNI, and Certificate Verification
Protocols using TLS usually distinguish the connection address, SNI, and HTTP Host. server determines where to connect; sni or servername determines which hostname TLS announces during the handshake; WebSocket Host belongs to the HTTP request headers. These values may be identical or may differ according to the server deployment. When certificate names do not match, verify the domain covered by the server certificate and the SNI instead of immediately enabling skip-cert-verify.
skip-cert-verify: true bypasses certificate validation and should be limited to temporary tests when you understand the server certificate. Long-term configurations should keep false and fix the system clock, certificate chain, SNI, or server deployment. An incorrect system clock can make both not-yet-valid and expired certificates appear wrong. Such errors usually show up as TLS verification failures and are unrelated to rules or proxy groups.
Transport options must be nested at the correct level
WebSocket parameters belong under ws-opts, gRPC parameters under grpc-opts, and HTTP parameters under the relevant transport options. They cannot simply be placed beside server under arbitrary renamed keys. An indentation error may move headers outside ws-opts; the YAML can remain readable, but the core will ignore the misplaced field or reject the file. Compare each level with the protocol documentation rather than checking values alone.
- name: "VLESS-gRPC-Example"
type: vless
server: 192.0.2.40
port: 443
uuid: "00000000-0000-4000-8000-000000000001"
network: grpc
tls: true
servername: grpc.example.com
udp: true
grpc-opts:
grpc-service-name: example-service
udp indicates whether a node can carry UDP. Enabling it also requires UDP support from the protocol, server, and network path. When a game or voice app fails, do not look only for udp: true; also verify TUN interception, proxy-group selection, server forwarding, and the application protocol. UDP failures can coexist with normal TCP web access.
Protocol Differences and Selection Principles
| Protocol | Key Identity Fields | Common Transport Fields | What to Check |
|---|---|---|---|
| Shadowsocks | cipher、password |
udp |
Encryption must match the server |
| Trojan | password |
sni、TLS |
Certificate name and system time |
| VMess | uuid、alterId |
WS、gRPC、TLS | Transport parameters must match as a set |
| VLESS | uuid |
WS, gRPC, Reality, and others | Flow control must match the server deployment |
| HTTP/SOCKS | Optional username and password | TLS or plain TCP | Proxy type and authentication method |
Node fields should come from the actual server or subscription, not from guesswork. Compatibility differences between clients commonly appear in new protocol features, transport parameter names, or core capabilities. When you see “unsupported proxy type” or “unknown field,” first identify the core used by the client, then verify that the subscription generated the appropriate format. If you need another client, the download page provides platform-specific entries for Clash Plus, Clash Verge Rev, FlClash, Clash Nyanpasu, Clash Meta for Android, ClashX Meta, Surfboard, and others.
Static nodes suit small manual configurations. For larger node sets or remote updates, use proxy-providers. Both can coexist, and a proxy group can reference static nodes and providers at the same time. Regardless of the source, every name entering a proxy group must be resolvable by the core, and a successful remote download must still contain a valid node structure.
Proxy Group Types, Nesting, and Health Checks
Proxy groups form the control layer between rules and nodes
proxy-groups organizes multiple nodes, other proxy groups, and built-in actions into referenceable targets. Rules usually point to “Node Selection,” “Auto Select,” “Streaming,” or another proxy group rather than to a specific node. When nodes change, you can update the group without editing large numbers of rules. Proxy group names are also case-sensitive and must not contain unexpected spaces compared with the names referenced elsewhere.
select is a manual selection group whose member the user chooses in the client; url-test periodically tests members and selects the one with the best measured performance; fallback checks members in order until it finds one that works; load-balance distributes connections across members according to its strategy. Each type solves a different problem. Use a manual group for a stable fixed exit rather than relying on an automatic group that switches frequently. When you want priority-based failover, fallback better expresses the intent than simply choosing the lowest latency.
proxy-groups:
- name: "Node Selection"
type: select
proxies:
- "Auto Select"
- "Failover"
- "SS-Example"
- "Trojan-Example"
- DIRECT
- name: "Auto Select"
type: url-test
proxies:
- "SS-Example"
- "Trojan-Example"
- "VMess-Example"
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 50
lazy: true
- name: "Failover"
type: fallback
proxies:
- "Trojan-Example"
- "SS-Example"
url: https://www.gstatic.com/generate_204
interval: 300
lazy: true
url is the health-check target. Choose a stable, lightweight URL that all candidate nodes can reach. A successful test proves only that a node can reach that target; it does not guarantee that every website works. interval sets the test interval: too short creates unnecessary connections, while too long delays detection after a node fails. With lazy enabled, a group can reduce active tests while unused. tolerance prevents frequent switching when results are close; it is not a fixed speed difference.
Nested groups must use one-way references
A proxy group can reference another group—for example, “Node Selection” can contain “Auto Select,” while “Streaming” contains “Node Selection.” This nesting helps separate default and purpose-specific policies, but it must not form a cycle. If A contains B and B contains A, the core cannot resolve a final outbound. Design the relationship as a one-way tree from service groups to base groups to nodes. Every path should ultimately reach a concrete node, DIRECT, or REJECT.
Too many nesting levels also increase troubleshooting costs. A request that matches “Streaming” may enter “Region Selection,” then “Auto Select,” and only then reach a node. When the interface shows only the outermost choice, it is easy to misidentify the actual exit. Keep the base configuration to three levels or fewer: the rule target group, a selection or testing group, and concrete nodes. To pin different services to different regions, reference regional groups directly from service groups instead of duplicating node lists.
Use filter and use to manage provider nodes
A proxy group references proxy-providers with use and filters members by node name with filter. The expression is generally treated as a regular expression, so characters must be escaped correctly. Node names are controlled by the subscription provider and may change after an update. Use stable region markers without matching too broadly. For example, a lone “US” may also match announcement text; combining common region codes with clear names is safer.
proxy-groups:
- name: "US Nodes"
type: url-test
use:
- remote-nodes
filter: "(?i)美国|US|United States"
exclude-filter: "测试|过期|到期"
url: https://www.gstatic.com/generate_204
interval: 600
- name: "Service Routing"
type: select
proxies:
- "US Nodes"
- "Node Selection"
- DIRECT
If filtering returns no results, the proxy group may become unusable. When a group suddenly has no nodes after a subscription refresh, first check whether the provider updated successfully, then whether node naming changed, and finally whether YAML quoting or backslashes altered the regular expression. Double-quoted strings process escape sequences; for complex expressions, consider single quotes to reduce escaping layers.
DIRECT, REJECT, and PASS
DIRECT connects to the destination without a proxy node; REJECT denies the connection; PASS is commonly used with certain rule combinations or sub-rule sets to pass matching on to the next stage. These are built-in actions and do not need to be declared under proxies. Adding DIRECT to a manual group lets users switch to a direct connection temporarily. Using REJECT for advertising or malicious domains requires consideration of how false positives affect page resources.
Whether to include DIRECT in a proxy group depends on the group’s purpose. Including it in a default proxy group helps diagnosis, but an accidental selection can send sensitive traffic directly. A purpose-specific group with an explicit proxy requirement may omit direct access. Names should describe behavior: “Node Selection” allows manual adjustment, “Auto Select” is test-driven, and “Direct Mainland” describes a rule target rather than a node’s region.
| Group Type | Selection Method | Typical Use | Main Risk |
|---|---|---|---|
select |
Manual selection | Fixed exit, main entry point | A failed node stays selected instead of switching automatically |
url-test |
Test results | Everyday automatic selection | The test target does not represent every use case |
fallback |
List order | Primary and backup routes | The order may not reflect actual priorities |
load-balance |
Distribute connections | Multiple exits in parallel | Login sessions may encounter changing exits |
Automatic groups are not a case of “more nodes is always better.” Too many candidates increase test traffic, while large quality differences can make results unstable. Filter by region, purpose, and protocol first, then test a limited candidate set for more consistent behavior. For identical policy structures across devices, see multi-device configuration synchronization and keep subscriptions, overrides, and device-specific settings in separate layers.
Rule Syntax, Priority, and Fallback Order
Rules match for the first time in declaration order
rules is an ordered list. The core checks it from top to bottom and normally stops after the first match, so specific rules belong first, broad rules later, and MATCH at the end. There is no universal rule that domain rules always outrank IP rules; priority comes from file order. Placing MATCH in the middle prevents every later rule from being considered.
The common format is “rule type, match value, policy target,” with some rule types accepting extra parameters. Commas separate fields. If the match value needs to express something complex, use the appropriate rule type or rule provider instead of adding commas arbitrarily. The policy target must be an existing proxy group, node, or built-in action. Rules do not create proxy groups.
rules:
- DOMAIN,api.example.com,Node Selection
- DOMAIN-SUFFIX,example.com,Node Selection
- DOMAIN-KEYWORD,example,Node Selection
- GEOSITE,cn,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- GEOIP,CN,DIRECT
- MATCH,Node Selection
DOMAIN matches only the complete domain; DOMAIN-SUFFIX matches the specified domain and its subdomains; DOMAIN-KEYWORD may match any hostname containing the keyword, making it the broadest and most error-prone. Use a full domain whenever possible. When using a suffix, confirm whether the root domain should also match. For example, DOMAIN-SUFFIX,example.com covers both example.com and www.example.com, making it suitable when an entire site should use one policy.
IP Rules and no-resolve
IP-CIDR matches IPv4 ranges and IP-CIDR6 matches IPv6 ranges. A request with a destination IP can be matched directly; when the request is still represented by a hostname, the core may need to resolve it before deciding whether it falls in the range. Adding no-resolve tells the core not to trigger resolution for that rule, which is useful for private ranges and connections already known to use an IP.
GEOIP determines a region from an address database, so results depend on the local database and its update status. It works well as a broad fallback but not for precise single-service routing. Cloud and CDN addresses change, and the same hostname may return addresses from different regions depending on the network. For service-specific rules, prefer domains or maintained rule sets. After enabling IPv6, also confirm that the rules cover the corresponding address family.
Process, Port, and Network-Type Rules
Desktop platforms may support process rules such as PROCESS-NAME and PROCESS-PATH, but availability depends on system permissions, how the core runs, and platform capabilities. Process-name rules are useful for pinning an app to a proxy group; path rules are more precise but can break when the installation directory changes. Mobile platforms generally cannot read process paths like desktop systems, so cross-platform configurations should not rely entirely on process rules.
Port rules such as DST-PORT and SRC-PORT can handle specific protocols or local services, but a port does not identify an application. Many modern services share port 443, so DST-PORT,443 as a broad proxy rule covers almost all HTTPS traffic. Port rules are better for known service ports, LAN administration ports, or debugging, and should be placed where they do not mask more specific rules.
rules:
- PROCESS-NAME,example-client.exe,Service Routing
- DST-PORT,22,DIRECT
- NETWORK,udp,Node Selection
- DOMAIN-SUFFIX,internal.example,DIRECT
- MATCH,Node Selection
NETWORK,udp matches a broad range of UDP traffic. Whether it is appropriate depends on node UDP support, whether DNS is handled by a separate module, and the application’s purpose. Sending all UDP through a policy that lacks UDP support can break voice, gaming, or QUIC connections. If only one application should use a proxy, prefer a combination of domain, process, and port rules over a rule that covers every UDP flow.
Design the intent before writing the rule syntax
Before maintaining rules, organize the requirement into layers: direct access for private networks; domains that must be rejected; services that require a particular region; commonly used mainland services that should connect directly; and all remaining traffic sent to the default policy. Translate each layer into rules and order them from exceptions to general cases. This is easier to review for conflicts than stitching together fragments from multiple network configurations.
Suppose an entire domain should connect directly but one API subdomain must use a proxy. Put the complete API domain rule first, followed by the suffix rule for direct access. If the order is reversed, the suffix rule matches first and the exception never runs. During troubleshooting, inspect the actual matched rule type and target policy in the connection log rather than merely searching the file for a rule.
rules:
- DOMAIN,api.example.com,Node Selection
- DOMAIN-SUFFIX,example.com,DIRECT
- GEOSITE,private,DIRECT
- GEOIP,LAN,DIRECT,no-resolve
- GEOSITE,cn,DIRECT
- GEOIP,CN,DIRECT
- MATCH,Node Selection
As rule counts grow, duplicates and conflicts become difficult to spot by eye. Move stable shared rules into rule-providers and keep local rules for a small number of high-priority exceptions and the final fallback. Check the behavior type and policy target of remote rule sets as well; a trusted source does not make its coverage harmless. If routing changes after an update, compare match results before and after instead of immediately switching nodes.
| Rule Type | Match Target | Precision | Recommended Use |
|---|---|---|---|
DOMAIN |
Complete domain | High | Single endpoint or special subdomain |
DOMAIN-SUFFIX |
Root domain and subdomains | Medium | One policy for an entire site |
DOMAIN-KEYWORD |
Domain fragment | Low | Clear naming pattern where some false matches are acceptable |
IP-CIDR |
IPv4 range | Depends on the subnet | Private networks and fixed address ranges |
GEOSITE |
Domain collection | Collection-level | Regional or service categories |
MATCH |
Remaining requests | Fallback | Last item in the rule list |
Proxy Providers and Rule Providers
proxy-providers manage remote node collections
proxy-providers moves a node list out of the main configuration. Each provider typically includes a type, download URL, local cache path, update interval, and health check. A proxy group references providers with use instead of listing every node name under proxies. This structure suits subscription updates and makes it easier to apply separate filters and checks to multiple sources.
type: http fetches content from a remote address, path specifies the local cache location, and interval controls the update interval. The remote file must use a proxy-provider format supported by the core; a complete Clash configuration cannot simply be treated as a list of nodes. If a subscription returns a full configuration, import it through the client’s subscription manager or generate a provider file through a trusted conversion process.
proxy-providers:
remote-nodes:
type: http
url: "https://subscription.example/nodes.yaml?token=xxxx"
path: ./providers/remote-nodes.yaml
interval: 21600
health-check:
enable: true
lazy: true
url: https://www.gstatic.com/generate_204
interval: 600
proxy-groups:
- name: "Provider Selection"
type: select
use:
- remote-nodes
proxies:
- DIRECT
The example subscription URL uses an obviously fictitious value. Real subscriptions often contain access credentials and should never be placed in public repositories, screenshots, or shared documents. When a provider download fails, the core may continue using its local cache, so the interface can still show old nodes. Check both whether the latest update succeeded and whether the cache remains readable; the presence of a node list alone does not prove that the subscription is healthy.
path must point to a configuration directory the client can write to. Absolute paths reduce portability, and Windows, macOS, Linux, and Android use different directory layouts. Prefer a relative path under the client’s working directory and give each provider a different filename. If multiple providers write to the same path, they overwrite one another, making one source’s refresh appear to change another source’s nodes.
Health checks observe provider-level availability
A provider’s health-check tests whether nodes can reach a target URL. It is related to, but serves a different purpose from, a proxy group’s url-test: the former maintains provider-node availability, while the latter selects among group members. Setting very short intervals in both places creates duplicate test traffic. A practical setup can check providers less often and let groups that need automatic selection test at a reasonable interval.
The test URL should be stable and lightweight. A node failing to reach it may be broken, or the destination may be restricted by the egress network. If all nodes fail at once, test DNS and the target itself first; if only certain protocols fail, inspect handshake logs. A health check is not a bandwidth test and does not verify video playback, login, or region-specific content.
Use rule-providers to split large rule sets
rule-providers loads remote or local rule collections. Common behavior values include domain, ipcidr, and classical. A domain collection contains domain entries, ipcidr contains address ranges, and classical can contain classic typed rules. The behavior must match the file contents or parsing may fail and rules may not take effect.
rule-providers:
private-domain:
type: http
behavior: domain
format: yaml
url: "https://rules.example/private-domain.yaml"
path: ./rules/private-domain.yaml
interval: 86400
service-rules:
type: http
behavior: classical
format: yaml
url: "https://rules.example/service-rules.yaml"
path: ./rules/service-rules.yaml
interval: 86400
rules:
- RULE-SET,private-domain,DIRECT
- RULE-SET,service-rules,Service Routing
- MATCH,Node Selection
A rule provider supplies a match collection only. To use it, the main configuration must specify a policy target with RULE-SET under rules. The same rule set can map to different proxy groups in different configurations. Because remote updates can change the match range, record each source’s purpose and avoid placing an unknown large collection at the highest priority.
format must match the remote content. YAML rule files commonly organize entries in a payload list; binary formats depend on core support and the relevant extension. Changing a file extension does not convert its contents. If the downloaded file is actually an HTML error page, the parser will usually fail near the beginning. When a provider update fails, check the HTTP status and response body first, then verify behavior, format, and local path permissions.
Update Boundaries Between Providers and the Main Configuration
The main configuration controls ports, DNS, proxy-group structure, and final rule order; providers supply changing node or rule collections. Keeping stable structure in the main file and frequently changing data in providers reduces the chance that a refresh overwrites local settings. If a remote subscription generates everything, add local preferences through an override layer rather than editing the cache after every refresh.
Separate providers can be created for multiple node sources and then combined through proxy groups. Watch for duplicate node names: different sources may contain the same display name, making group filtering and log identification difficult. Add a source prefix during subscription conversion or overriding instead of relying on duplicate names in rules. Rule providers should also avoid overlapping responsibilities. If two broad domain collections point to different policies, their order under rules still determines the actual behavior.
| Project | proxy-providers | rule-providers |
|---|---|---|
| Content Carried | Proxy node objects | Domains, address ranges, or classical rules |
| Reference Location | Proxy group use |
Rule list RULE-SET |
| Local Cache | Node provider file | Rule-set file |
| Key Validation | Node format and protocol fields | behavior and content format |
Overrides, Merging, Validation, and Fault Isolation
The override layer should modify stable structure, not subscription caches
A subscription refresh usually downloads and replaces its cache file, so direct edits to subscription content are easily lost at the next update. A safer approach is to keep the remote subscription as the data source and use the client’s global overrides, extension scripts, or local merge files to change ports, DNS, proxy groups, and rules. Override formats vary by client, and the names and execution order shown in Clash Plus, Clash Verge Rev, and FlClash may differ. First determine whether the override runs before or after subscription parsing.
Overrides can replace scalars, merge mappings, append lists, prepend lists, or delete fields. A scalar such as mode is normally replaced directly; for dns, only selected child fields may need changing; rules is ordered, so simply appending to the end may place a rule after MATCH where it has no effect. Local high-priority rules should be inserted at the front. If proxy-group lists are merged by name, verify that the client recognizes objects by key; otherwise it may create two groups with the same name.
# base.yaml
mode: rule
dns:
enable: true
enhanced-mode: fake-ip
rules:
- GEOSITE,cn,DIRECT
- MATCH,Node Selection
# Target semantics for override.yaml
dns:
ipv6: false
fake-ip-filter:
- "*.lan"
- "*.local"
# Local rules to prepend before MATCH
rules-prepend:
- DOMAIN,api.example.com,Service Routing
- DOMAIN-SUFFIX,internal.example,DIRECT
rules-prepend is an example of a semantic used by some override tools, not a top-level field recognized directly by every core. The final file passed to mihomo must still expand to a standard rules list. Keep client-specific extension fields in the client’s override file and do not copy them into a configuration intended for direct core loading. To determine whether a field belongs to the client or the core, inspect the exported final configuration and startup log.
List merging requires explicit ordering and deduplication rules
Order is the most important property when merging rule lists. Put locally enforced rules before remote rules, supplemental rules before regional rules, and keep the final fallback as the only last item. After merging, check for multiple MATCH entries, private-network rules placed after the proxy fallback, and domains covered earlier by broader rules. Duplicate rule text may not prevent startup, but it increases matching and maintenance costs.
Deduplicating proxy groups and node lists cannot rely on comparing complete lines. Node objects may share a name while using different servers, or share a server while using different names. For ordinary manual maintenance, make unique names the first constraint, then verify protocol, server, and port. Duplicate proxy-group names are usually more dangerous than duplicate node names because rules reference groups by name, and duplicate-definition behavior can vary by parser or client.
When merging DNS mappings, pay particular attention to whether list fields are replaced or appended. If an override tool completely replaces nameserver, backup upstreams from the base configuration disappear; if it appends to fake-ip-filter, that usually matches the intent of adding exclusions. Do not judge from the override fragment alone; inspect the merged final YAML. If the graphical client offers “view runtime configuration” or “export current configuration,” use that output for validation.
Validate the configuration at four levels
Level one is YAML syntax: indentation, colons, quotes, lists, and data types must be correct. Level two is field validation: the core must recognize the fields and all required protocol parameters must be present. Level three is reference integrity: rule targets, proxy-group members, provider names, and local paths must exist. Level four is runtime behavior: ports must listen, DNS must reach its upstreams, nodes must complete handshakes, and rules must select the expected policies. Check the levels in order; network testing is meaningless until the earlier level passes.
# When using the client’s built-in validator, use the actual core and configuration paths
mihomo -t -f config.yaml
# If validation passes, the output will typically indicate that configuration testing is complete
# If it fails, record the error line, field name, and reference name
The executable name and arguments in a command line depend on how the software was installed, and graphical clients usually provide a configuration-check entry point. Test with the same mihomo core used by the client; one core may accept a field that another does not. The reported line is where the parser detected the problem, not necessarily where the root cause occurred. For example, a missing quote on the previous line may not surface until the next line.
After editing, do not rewrite several sections at once. Use a binary-isolation approach: restore a runnable version, then add DNS, nodes, proxy groups, and rules one block at a time. When a block triggers an error, narrow it down to the specific field. Temporarily replace a remote provider with one or two static example nodes to determine whether the problem lies in the download path or policy structure. Restore the full source after troubleshooting.
Common Error Investigation Paths
| Symptom | Check First | Next Branch |
|---|---|---|
| Configuration cannot be imported | Response body, first YAML line, indentation | Field types and client compatibility |
| Core cannot start | Port conflicts, unknown fields, path permissions | Proxy-group and provider references |
| All nodes time out | Basic network, DNS for node hostnames | Server port and protocol parameters |
| Only some websites fail | Rule matches, DNS responses, policy selection | Destination protocol and node egress |
| Settings disappear after a subscription refresh | Whether the subscription cache was edited directly | Override order and merge behavior |
| LAN devices cannot connect | allow-lan, listening address |
Firewall, device proxy address, and port |
If the configuration starts but the Internet is unreachable, first verify that the basic network works without Clash, then verify the local inbound port, followed by DNS, proxy groups, node handshakes, and rule matches. Do not begin by deleting every rule or disabling all security settings; that destroys the evidence. Keep the timestamp of the first failure in the log and compare it with the selected mode and proxy group. This is usually more effective than repeated restarts.
If only the browser is affected, check whether it has its own secure DNS, proxy extension, or QUIC enabled. If every application is affected, check the system proxy or TUN. If LAN devices fail while the local machine works, check the listening scope and firewall. If one proxy group fails while others work, inspect its members and health checks. Different scopes point to different configuration layers, so defining the scope first prevents unrelated changes.
Final Checklist for a Maintainable Configuration
After completing the configuration, confirm that each top-level field has only one effective definition; ports do not conflict; DNS upstreams have a base resolution path; every node name is unique; proxy-group references form one-way relationships; every rule target exists; MATCH appears only once at the end; provider cache paths do not overlap; local overrides contain no public copy of subscription credentials; and the final runtime configuration passes validation with the current core. Then test a direct domain, a proxied domain, an IP destination, and a UDP application to ensure success is not limited to one lucky webpage.
Back up the configuration separately from the subscription source, override files, and runtime state. For reuse across devices, remove platform-specific paths and controller ports first, then keep system takeover settings separate for each device. The remote subscription handles node changes, local overrides handle stable preferences, and the client runtime directory handles caches and selection state. Keeping these layers distinct prevents subscription updates, client upgrades, and device migrations from overwriting one another.
For problems that do not fit a category, visit the Help Center and continue with fundamentals, installation and configuration, usage tips, or Troubleshooting. If you need to rebuild a working baseline from installation through the first connection, return to Getting Started and follow the steps. If you need to choose a different client or core package, visit the download page and browse by platform. During troubleshooting, always save the current configuration before making small, reversible changes.