Clash Rule-Based Routing: Split Rules for Mainland China vs. Overseas Traffic

A practical guide to routing rules for mainland China vs. overseas traffic: rule types, match order, and proxy groups, plus a ready-to-use config and verification steps.

The Goal: Direct for Mainland China, Proxy for Everything Else

Clash's core mechanism is rule-based forwarding: every connection that enters Clash carries a destination address, which gets checked against the rule list in order. Whichever rule matches first decides the outbound. Splitting mainland China traffic from overseas traffic essentially means translating "which traffic goes direct, which goes through the proxy" into a correctly ordered rule list.

There are only three kinds of rule outbounds: DIRECT means a direct connection, with the destination reached straight from the local network; REJECT means the connection is blocked outright, often used for filtering; and the third type is the name of a proxy node or proxy group, meaning the connection is handed off to the proxy tunnel.

What you're aiming for is concrete: sites inside mainland China connect directly, keeping latency low and node bandwidth free; sites outside China go through the proxy outbound; anything you explicitly don't want to allow gets rejected. Getting this right takes three things — a rule set that covers domestic and overseas addresses, a proxy group pointing to your nodes, and the correct ordering. Let's break each part down.

Rule Types: What Each Rule Actually Matches

A rule is written as "type,parameter,outbound", separated by commas. The type determines what the rule checks the request against. Common types are listed below.

Rule TypeMatchesExampleNotes
DOMAINExact domainDOMAIN,example.com,PROXYOnly matches the exact domain, not subdomains
DOMAIN-SUFFIXDomain suffixDOMAIN-SUFFIX,example.com,PROXYMatches the root domain and all subdomains; the most common domain rule
DOMAIN-KEYWORDKeyword in domainDOMAIN-KEYWORD,example,PROXYMatches if the domain contains this string; wide blast radius, use with caution
GEOSITEDomain category setGEOSITE,cn,DIRECTOne rule covers an entire domain category; requires mihomo core
IP-CIDRDestination IP rangeIP-CIDR,192.168.0.0/16,DIRECT,no-resolveMatches by subnet; good for LANs and fixed address ranges
GEOIPDestination IP's countryGEOIP,CN,DIRECTLooks up the IP's country via a geo database; good as a fallback
DST-PORTDestination portDST-PORT,853,DIRECTRoutes by port; good for single-port services
PROCESS-NAMEOriginating processPROCESS-NAME,chrome.exe,PROXYRoutes by process; works on desktop platforms
MATCHEverything elseMATCH,PROXYThe catch-all outbound at the end of the list; must be placed last

The rule of thumb is simple: use a domain suffix instead of a keyword whenever possible; use a GEOSITE category instead of stacking hundreds of DOMAIN-SUFFIX entries; keep IP-based rules after domain rules as a fallback based on IP location. DOMAIN-KEYWORD is the easiest to misfire — a short keyword can accidentally match a subdomain of a mainland site — so unless the target is very specific, keep it out of your main routing list.

Core differences

GEOSITE is a Clash Meta / mihomo core capability and depends on the corresponding geodata files; on the original Clash core, use DOMAIN-SUFFIX, rule providers, or GEOIP instead. Check the core name on the client's About page before deciding how to write your rules.

Match Order: First Match Wins

Clash checks the rules list from top to bottom and stops at the first match — rules after that point are never evaluated. So ordering isn't a formatting habit; it *is* the routing outcome. A stable order for splitting mainland China and overseas traffic is: local machine and LAN direct → explicit blocks → mainland domains direct → mainland IPs direct → everything else through the proxy.

  1. Allow local, LAN, and reserved address ranges first, so traffic to routers, NAS devices, or printers doesn't get routed into the proxy.
  2. Then place precise block rules — for example, known tracking domains or services you don't want to allow; the earlier a block rule sits, the fewer downstream lookups it triggers.
  3. Next, place the mainland domain set — GEOSITE,cn covers a huge number of domains in one line; without GEOSITE, use a maintained domain rule set instead.
  4. Then add GEOIP,CN,DIRECT, which catches destinations the domain set missed but that resolve to a Chinese IP.
  5. Finally, leave a single MATCH,PROXY at the end. Every request that didn't match a mainland rule falls through to the proxy group.

no-resolve only affects IP-based rules: adding it tells Clash not to resolve a domain to an IP just to check this rule. LAN ranges usually always carry no-resolve; whether GEOIP,CN should carry it depends on how well your domain rules already cover things. When your domain set is comprehensive, GEOIP,CN,DIRECT,no-resolve cuts down on extra lookups; when it's a bit outdated, keeping resolution enabled is safer, but make sure your DNS setup doesn't let resolution itself bypass the proxy tunnel.

Ordering mistakes

Placing MATCH,PROXY partway through the list disables every direct-connect rule after it; placing GEOIP,CN before GEOSITE,cn forces a lot of requests that could've matched by domain to go through an IP lookup first. Both produce the same symptom: mainland sites get routed through a node, driving up latency and node bandwidth at the same time.

Proxy Groups: Expose Only One Name to the Rules

Rather than hardcoding a node name into a rule, write a proxy group name instead. That way, switching nodes, running speed tests, or adding a backup outbound never requires touching the rule list. At minimum, splitting mainland/overseas traffic needs two groups: a manually selectable PROXY group, and an auto-testing AUTO group.

Group TypeBehaviorBest used for
selectManually pick an outbound in the clientThe main outbound group, ideal as the final decision point
url-testPeriodically tests latency and switches to the fastest nodeNested inside a select group as an auto option
fallbackTries nodes in order, switching to the next available one on failurePrioritizes availability over lowest latency
load-balanceDistributes connections across multiple nodesMulti-link load spreading; not ideal as a default troubleshooting entry point

A recommended structure: make PROXY a select group with AUTO, several nodes, and DIRECT as options; make AUTO a url-test group containing only nodes that are actually working. Point all rules at PROXY, so switching between auto mode and a manual node only changes the selection inside the group, never the rules.

A Ready-to-Use Configuration Example

Below is a minimal working skeleton — focus on how proxy-groups and rules relate to each other. The node shown is an obvious placeholder used only to illustrate field positions; if you use a subscription, hand node and group management over to a subscription converter or override mechanism, since manual edits to the converted result get overwritten on the next update.

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false

proxies:
  - name: "example-node-do-not-use"
    type: ss
    server: node1.example.invalid
    port: 443
    cipher: aes-128-gcm
    password: "demo-pass-000"

proxy-groups:
  - name: PROXY
    type: select
    proxies:
      - AUTO
      - example-node-do-not-use
      - DIRECT

  - name: AUTO
    type: url-test
    proxies:
      - example-node-do-not-use
    url: http://example.invalid/generate_204
    interval: 300
    tolerance: 50

rules:
  - DOMAIN-SUFFIX,localhost,DIRECT
  - DOMAIN-SUFFIX,local,DIRECT
  - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR,169.254.0.0/16,DIRECT,no-resolve
  - GEOSITE,cn,DIRECT
  - GEOIP,CN,DIRECT
  - MATCH,PROXY

If your client runs from a subscription, look for an "override / Mixin / config patch" entry point first, and apply the ordering logic above before or after the subscription-generated rules — don't directly edit the finished config, since the client rebuilds it on every update. If you need to add blocks, insert a standalone REJECT rule or rule set before GEOSITE,cn, keeping the mainland-direct rules contiguous.

What success looks like

The signal that this configuration is working isn't just "the internet works" — it's that in the connections panel, mainland targets match GEOSITE,cn or GEOIP,CN with a DIRECT outbound, while overseas targets only match MATCH and route through whichever node is currently selected inside the PROXY group.

How to Verify the Split Is Working

Verify in three layers, in this order. First, check the mode: the client should be in rule mode with system proxy or TUN taking over traffic; browser extension proxies or in-app proxies bypass Clash entirely, so rule those out first. Second, check the actual matches: open the client's connections or logs page, make one request to a mainland site and one to an overseas site, and check the rule chain and outbound shown next to each connection — don't guess based on page load speed. Third, check from the command line: send a request through the explicit proxy port to confirm traffic is actually entering Clash.

curl -x http://127.0.0.1:7890 -I https://your-target-domain/

The command line only proves the request entered Clash; where it ends up still needs to be checked in the connections panel via the rule and chains fields. Mainland requests should show a direct chain, overseas requests should show a node chain. If an overseas request shows DIRECT, it's usually being caught by an earlier DOMAIN-SUFFIX or keyword rule. If a mainland request ends up on a node, check first whether MATCH is positioned too early, whether GEOSITE data is missing, or whether the client is actually running the original core.

With TUN or enhanced DNS mode enabled, also confirm that system traffic is genuinely entering Clash's virtual network adapter — otherwise the rules can be perfectly correct and still only apply to apps with a manually configured proxy. When troubleshooting, turn off TUN first and verify the rules via the system proxy, then turn TUN back on — this separates "a rule problem" from "a traffic takeover problem."

Common Mistakes

  • Rules out of order: putting the catch-all rule too early disables every fine-grained rule after it; checking the first and last screens of your rules list before saving catches most of these.
  • Overly broad keywords: DOMAIN-KEYWORD matching too widely pulls mainland sites into the proxy; switch to DOMAIN-SUFFIX or a GEOSITE category instead.
  • Hardcoded node names in rules: when a subscription renames a node, the rule silently stops working; rules should only reference proxy group names.
  • Relying on GEOIP alone: using only GEOIP,CN misses CDNs and overseas mirrors; domain sets and IP location checks need to work together.
  • Manually editing subscription output: gets overwritten on the next update, which looks like the config "reverting on its own"; use the override entry point to maintain custom sections instead.
  • Ignoring IPv6: if the local machine has working IPv6 but the config disables or omits it, some requests fall back to the system network directly; either enable IPv6 consistently at both the core and system level and add IP-CIDR6 rules, or disable it explicitly.

Treat rules as waypoints to maintain: each one marks a single destination, ordered from most specific to catch-all. Once mainland-direct, overseas-proxy, and blocked-when-needed each have their place, swapping nodes, changing clients, or adding rule sets later only means replacing a local piece — never rewriting the whole config.

Download the Clash Client

Rule-based routing needs a client to take over traffic first. Head to the download hub, pick a client for your platform, then come back to this guide to finish setting up system proxy or TUN takeover.

Download Clash