Why rule-based split routing still matters
Modern Mihomo-based clients can tunnel everything through TUN and capture UDP alongside TCP, yet where each flow exits remains a policy question. Sending every packet to a distant relay burns latency for domestic video, file sync, and campus intranet tools that were never meant to hairpin through another country. The opposite failure—keeping a naive global DIRECT path—breaks access to services that only resolve cleanly when you exit from an overseas IP. Rule routing is how Clash-style engines reconcile those needs on one machine without running two VPN products.
Think of rules as a prioritized decision list evaluated for every connection attempt after DNS has produced a candidate destination. The engine walks from top to bottom, stops at the first match, and hands the flow to a policy group name or a built-in outbound like DIRECT or REJECT. Nothing in your subscription URL magically encodes that ordering; providers ship nodes, while you (or a template author) supply the routing grammar in YAML. That separation is why two people with identical node lists can see wildly different speeds: one profile might send mainland CDN traffic straight to the ISP, the other might accidentally steer it through a congested overseas hop.
If you are still wiring up your first profile, finish the subscription import walkthrough so proxies and proxy-groups exist before you tune rules. Rules operate on names that must already be defined.
The first-match model (and why order is not cosmetic)
Clash rules are not a weighted graph where multiple paths compete. They behave like a firewall ACL: earlier rows win. That means a broad catch-all placed too high—say, a MATCH to a proxy group at line three—makes every subsequent domestic exception dead code. Conversely, placing thousands of niche domain lines before basic LAN and DNS safeguards can slow evaluation and complicate debugging. Experienced users keep a short block of local safety rules near the top: loopback, RFC1918 space, captive portal probes, and perhaps multicast, each mapped to DIRECT or REJECT as appropriate.
After local exceptions, a typical China-oriented stack introduces GEOIP or curated domain lists for domestic properties, then foreign or "proxy" lists, then a final MATCH. The exact labels differ by template, but the invariant holds: specific before general. When you import a community bundle wholesale, read the comments: many upstream files assume a particular group name such as 🎯 Direct or PROXY. Rename consistently across proxy-groups and rules or the parser will link to a missing group and fail to load.
rules: is an ordered array of strings. Each string combines a rule type, payload (when required), and an outbound or policy. The Mihomo documentation lists supported types and edge cases; this article focuses on patterns, not every keyword variant.
Rule types you will actually use
DOMAIN matches a single hostname exactly. Use it for one-off exceptions where you know the FQDN, such as a telemetry endpoint you want forced DIRECT. DOMAIN-SUFFIX matches a registrable suffix, which is the workhorse for grouping entire sites that share a base domain. DOMAIN-KEYWORD is powerful but blunt: a short keyword can collide with unrelated hosts, so reserve it for controlled lists or temporary experiments.
IP-CIDR and IP-CIDR6 operate after resolution when the engine already has an IP, or when the connection was literal-IP from the start. They are essential for pushing RFC1918, link-local, and carrier-grade NAT ranges to DIRECT without relying on DNS. GEOIP consults the bundled MaxMind-style database (exact provider depends on your build) and tags traffic by country code. A line such as GEOIP,CN,DIRECT is the classic backbone of "domestic direct" setups—when the database and DNS agree on what "China" means for that IP.
PROCESS-NAME and similar OS-specific matchers appear in advanced profiles to steer particular binaries. They are invaluable for split-tunneling stubborn apps but add platform maintenance cost; test on each OS separately. Finally, MATCH matches everything left over. It should almost always be last. Its target is your default policy—often an auto url-test group for overseas exit, occasionally DIRECT if you intentionally run a deny-by-default posture (rarer).
Policy groups: naming reality so rules stay readable
Rules rarely point at raw proxy server entries. They point at proxy-groups: logical handles like Proxy, Auto, or emoji-prefixed labels from third-party templates. A minimal overseas-oriented configuration defines at least one select or url-test group containing remote nodes, plus explicit DIRECT for domestic routing. Some users add a relay or fallback chain for resilience; that is orthogonal to country split as long as the group name referenced in rules: matches.
url-test and fallback groups automate picking a working node—useful when providers rotate addresses often. select keeps you in manual control for streaming or latency experiments. From a routing perspective, the critical discipline is: do not create circular references where group A lists group B while B lists A. The parser rejects obvious cycles, but indirect loops through several layers can still confuse newcomers.
When you label groups, prefer neutral machine-friendly names in your own hand-written YAML, even if the UI displays localized strings. That habit pays off when you diff configs across machines or merge snippets from documentation. If you need inspiration for structuring outbound selection after routing is stable, skim our TUN mode guide—it complements rule tuning when you want full-device enforcement.
Domestic DIRECT: what "China traffic" should include
Domestic-direct policies aim to keep latency-sensitive and billing-sensitive traffic on your ISP path: streaming that geo-locks to mainland catalogs, university VPNs, bank portals, and large-object downloads from in-country CDNs. The GEOIP-based approach is simple when IPs are stable and correctly mapped. Real-world friction appears when a global SaaS fronts China users from an anycast POP still tagged as non-CN, or when corporate split-DNS returns different answers inside the office. In those cases, augment GEOIP with explicit DOMAIN-SUFFIX lines for the handful of services you care about.
Private address space deserves unconditional attention. Traffic to 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 should not wander toward a commercial proxy unless you truly intend remote penetration testing. The same applies to link-local and carrier-specific walled-garden hosts used for captive portals. Many templates already encode these as early IP-CIDR rules; if yours omits them, add them manually before GEOIP lines.
DNS leaks can make domestic routing look "broken" even when IP rules are perfect. If queries go to a public resolver overseas while GEOIP expects CN answers, you may classify traffic inconsistently between TCP and UDP paths. The next section ties DNS to rule outcomes; for now, treat consistent resolver choice as part of domestic performance, not an afterthought.
Overseas proxy: precision beats "send everything abroad"
The other side of the split is selecting which destinations warrant a relay. Community-maintained domain lists—often grouped under labels reminiscent of ACL or "GFW" lists—attempt to enumerate foreign properties that users in mainland China commonly need through a proxy. They are helpful starting points and horrible contracts: the web changes daily, CDNs merge, and a domain-based rule that was correct last month may today resolve to a domestic edge node. Treat remote lists as living dependencies: enable scheduled refresh in rule-providers, pin URLs you trust, and diff updates when something regresses.
When lists disagree with reality, prefer adding a narrow DOMAIN or IP-CIDR override near the top of your custom section rather than editing upstream files in place. That preserves mergeability the next time you pull template updates. For services with aggressive anycast—large public clouds, global APIs—expect occasional flip-flop unless you also stabilize DNS routing for those hostnames.
Bandwidth ethics matter on metered nodes. Split routing exists partly so that multi-terabyte software updates and LAN backups do not count against a provider fair-use policy. If every client on your network defaulted to a single overseas hop, you would also concentrate failure there. A balanced MATCH to an auto-testing group keeps resilience without asking humans to micromanage per tab.
Rule-providers: scaling lists without pasting ten thousand lines
Inline rules: arrays are fine for dozens of lines. They do not scale to large community sets. rule-providers let Mihomo fetch, cache, and periodically refresh rule files from HTTP(S) URLs or local paths, then reference them as a single logical block inside rules: with RULE-SET syntax (exact keyword depends on core version; always verify against your installed release notes). Providers carry metadata: format (yaml or text), behavior (classical versus newer optimized modes), and update intervals.
Operational tips: use sane interval values—minutes for volatile lists, hours or days for slow-moving GEOIP databases if you mirror them locally. Log fetch failures; a stale cached file is usually better than an empty rule file that causes immediate mass MATCH to proxy. When you self-host lists for privacy, serve them over HTTPS with valid certificates because embedded clients validate TLS in most default builds.
Finally, separate concerns: proxy-providers supply nodes; rule-providers supply matchers. Confusing the two in YAML placement is a frequent copy-paste error that produces obscure parse errors on startup.
Aligning DNS with routing decisions
Routing rules run in conversation with the dns: section. In fake-ip mode, Clash may synthesize short-lived answers locally so domain rules can trigger before a real resolver round trip completes. That is fast, but it interacts with fake-ip-filter: hosts that must resolve to genuine LAN or intranet addresses should be listed there to avoid mysterious breakage. In redir-host or conventional modes, upstream resolvers matter more visibly; inconsistent answers between encrypted DNS and ISP DNS manifest as "sometimes proxied, sometimes not" for the same site.
Use nameserver-policy or equivalent split when you want domestic domains queried through domestic resolvers and the rest through neutral or encrypted paths. Keep loopback DNS (127.0.0.1) in mind if another local forwarder sits in front of Clash—double NAT-style DNS chains are a common source of timeout bugs. Our documentation hub collects additional YAML snippets for DNS once your rule skeleton is stable.
Practical ordering template (conceptual)
Although your file will differ, a readable baseline often follows this narrative: (1) reject or direct obvious bad actors if you maintain blocklists; (2) direct LAN and private IP ranges; (3) direct intranet or campus domains you trust; (4) apply GEOIP CN to DIRECT when you want a broad domestic fast path; (5) apply curated foreign domain rule-sets to your proxy group; (6) MATCH to proxy or auto. Insert explicit exceptions above GEOIP when you know a domain resolves contrary to country expectation. Insert testing hooks sparingly—verbose per-domain logging belongs in diagnostics builds, not daily driver configs.
rules:
- IP-CIDR,192.168.0.0/16,DIRECT
- IP-CIDR,10.0.0.0/8,DIRECT
- GEOIP,CN,DIRECT
- GEOSITE,gfw,Proxy
- MATCH,Proxy
Replace GEOSITE/gfw with the providers your build actually supports; many templates use RULE-SET instead of inline keywords.
When domestic sites still ride the proxy
Symptom: domestic streaming or app stores feel sluggish while the status panel shows an overseas node. First confirm which rule matched—Mihomo logs include matcher types when debug logging is enabled. If a foreign DOMAIN-SUFFIX line is too greedy, narrow it. If GEOIP misclassified an IP, add a temporary IP-CIDR override and report upstream database lag if it persists across updates.
Symptom: overseas sites fail despite proxy availability. Check that your proxy group still contains healthy nodes (url-test latency) and that DNS is not returning poisoned or domestic answers for those hosts. Toggle a manual select node to isolate provider issues from routing issues.
Symptom: intermittent failures only in fake-ip mode. Review fake-ip-filter and any hosts overrides. Remember that some applications cache DNS aggressively; flush caches during testing or you will chase ghosts.
Closing: split routing rewards clarity
Rule routing is less about memorizing every keyword and more about maintaining a coherent story: local safety first, broad regional shortcuts second, curated exceptions third, sane default last. Templates accelerate setup, but blind copying without understanding rules: order turns performance tuning into superstition. When you treat GEOIP, domain lists, and DNS as three lenses on the same traffic—not three independent features—profiles become easier to reason about and safer to update.
Compared with one-size-fits-all global proxy toggles, a disciplined split keeps domestic CDNs responsive, reduces unnecessary load on shared nodes, and makes logs intelligible when something misfires. Modern Mihomo clients and graphical editors make iteration faster than ever—especially when paired with a well-tested subscription and occasional rule-provider refreshes.
When you are ready to standardize on a maintained client build and apply these patterns on your own hardware, download Clash for free from our official page and experience the difference.