1. Before You Configure: Core, Mode, and Proxy Groups

“Direct in mainland China, proxy abroad” isn’t a switch that can automatically determine where every website belongs. A typical setup combines explicit domain rules, domain or IP classification databases, and a final catch-all rule. The goal is to send frequently used services in mainland China direct, route selected overseas services through a proxy group, and provide a predictable route for anything not classified.

This guide uses mihomo, the name of the core used by later versions of Clash Meta. The legacy Clash core, different forks, and configuration converters built into clients do not support exactly the same fields. In particular, support for GEOSITE and geodata settings cannot be inferred from the client’s name alone.

  1. Check which core is running. Find the core name and version in the client’s About or core information page. If configuration validation reports an unsupported rule type, check the core’s capabilities before adding more rules of the same type.
  2. Choose rule mode. Split routing requires mode: rule. Global mode typically sends connections through the global proxy policy, while Direct mode does not select proxies using the rules in this guide.
  3. Check the outbound name. This guide uses Proxy for an existing proxy group. Names are case-sensitive. The group must be defined in the current configuration’s proxy-groups and have a valid node selected.
  4. Back up your current configuration. A subscription update may overwrite generated configuration. Prefer the client’s persistent override, configuration merge, or rule editing features, and check the final effective configuration.

2. Rule Order: First Match Wins

In rule mode, the core checks rules in order. In typical routing scenarios, once a rule matches, the connection uses its specified outbound; the core does not keep looking for a “more specific” match. Order matters more than rule count: put manual exceptions first, bulk categories next, and MATCH last.

Rule typeApplies toKey distinction
DOMAINA single fully qualified domain nameExact match; does not automatically include other subdomains
DOMAIN-SUFFIXA domain and its subdomainsgithub.com also matches api.github.com
GEOSITEA set of domains in a databaseRequires the local database to include the relevant category
GEOIPThe region associated with the destination IPDoes not identify the region of a website, account, or service operator
RULE-SETEntries in a rule providerThe set is defined under rule-providers
MATCHConnections not matched by earlier rulesA final fallback, not a way to identify “overseas” traffic

Test rule order with two domain rules

rules:
  - DOMAIN,api.github.com,Proxy
  - DOMAIN-SUFFIX,github.com,DIRECT
  - MATCH,Proxy

This snippet illustrates rule priority: api.github.com matches the first rule and uses Proxy, while github.com and other subdomains may match the second rule and go direct. If you swap the first two rules, the suffix rule catches api.github.com first, making the exact-domain rule ineffective. In a real setup, route all GitHub traffic consistently as needed; this contrast is just an example.

Don’t put MATCH,DIRECT at the beginning of your rules, and don’t assume the most specific rule for a domain will be selected automatically. The same principle applies to exceptions for ad blocking, corporate networks, and download sites: put the more specific requirement first.

3. Basic Routing: Domains First, GEOIP Next, Proxy Fallback

Start with a small set of domain rules to establish a baseline you can verify, without adding external rule files. This example sends private IPv4 addresses directly, routes Bilibili-related domains directly, sends common GitHub domains through a proxy, routes destination IPs in mainland China directly, and sends everything else to Proxy.

mode: rule

rules:
  - 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
  - DOMAIN-SUFFIX,bilibili.com,DIRECT
  - DOMAIN-SUFFIX,bilivideo.com,DIRECT
  - DOMAIN-SUFFIX,github.com,Proxy
  - DOMAIN-SUFFIX,githubusercontent.com,Proxy
  - GEOIP,CN,DIRECT,no-resolve
  - MATCH,Proxy

no-resolve Does Not “Disable DNS”

no-resolve means the core won’t actively resolve a domain solely to match this IP rule. If the connection metadata already contains a real destination IP that can be used for matching, the core can still check whether it falls within the specified range or region. If only a domain is available and no usable IP is present, the rule may be skipped and matching continues with the next rule.

So GEOIP,CN,DIRECT,no-resolve does not guarantee that every domain in mainland China will connect directly. A domain not covered by a domain rule may end up using Proxy if no IP is available when the rule is checked. Adding a domain category for mainland China is usually more controllable than relying on IP classification alone. If you allow IP rules to trigger DNS resolution, also consider the resolution path, latency, and whether the returned addresses are what you expect.

  • Private network rules only determine the outbound for connections that have already entered the core. They do not create LAN routes or grant applications permission to access your local network.
  • This example lists only common private IPv4 ranges. If you use IPv6 on your local network, add the relevant rules for your setup.
  • With fake-IP DNS, pay attention to the domain restored by the core and the actual resolved address. Don’t simply add the fake-IP range as an ordinary direct-routing range.
  • A service may use multiple domains. If the main site works but images, sign-in, or downloads fail, check connection logs for missing domains instead of switching all traffic to Direct.

4. Add GEOSITE: Use Domain Categories for Direct Routing in Mainland China

GEOSITE matches domain sets; it does not infer a domain’s region from the server IP. Place it before GEOIP so domains classified as local can use DIRECT. Category names and coverage depend on the specific database and are not consistent across all data sources.

In mihomo, you can use the following configuration fragment. When merging it, keep the local network ranges and manual exceptions confirmed in the previous section. Don’t mistake this shorter rules list for a complete replacement for your existing list.

geodata-mode: true

rules:
  - DOMAIN-SUFFIX,github.com,Proxy
  - DOMAIN-SUFFIX,githubusercontent.com,Proxy
  - GEOSITE,cn,DIRECT
  - GEOIP,CN,DIRECT,no-resolve
  - MATCH,Proxy

geodata-mode: true enables DAT data mode for GEOIP. This setup requires a usable geoip.dat; GEOSITE also depends on geosite.dat. Check the core’s working directory, database loading logs, and whether the data source actually includes the cn category. If that category is missing, changing capitalization or repeatedly restarting won’t fix it.

If the logs show a database load failure or a missing category, return to the basic rules in the previous section and fix the data file first. Don’t change DNS, databases, and proxy nodes all at once, or it will be difficult to tell which change affected the behavior.

5. Using rule-providers: Move Manual Rules into Maintainable Files

As your rules grow, splitting direct-routing and forced-proxy entries into separate files reduces repeated edits to the main configuration. This example uses local file providers so you don’t have to add rule URLs from unknown sources. Paths are relative to the configuration directory actually used by the core. If you import the configuration through a client, check whether it copies or rewrites that directory.

Step 1: Create Two Rule Files

Create a rules folder in the core’s configuration directory, then save the following content as rules/direct.yaml and rules/proxy.yaml. These use the classical behavior, so each entry includes a rule type but not a trailing outbound name.

# rules/direct.yaml
payload:
  - DOMAIN-SUFFIX,bilibili.com
  - DOMAIN-SUFFIX,bilivideo.com
  - DOMAIN-SUFFIX,qq.com
  - DOMAIN-SUFFIX,jd.com
# rules/proxy.yaml
payload:
  - DOMAIN-SUFFIX,github.com
  - DOMAIN-SUFFIX,githubusercontent.com
  - DOMAIN-SUFFIX,wikipedia.org

Step 2: Define the Providers and Add Them to the Rules

This snippet combines local IPv4 ranges, two rule sets, a domain category for mainland China, and IP classification. Your existing configuration must already define a valid Proxy group, and the databases mentioned in the previous section must be loadable.

mode: rule
geodata-mode: true

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

rules:
  - 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
  - RULE-SET,local-proxy,Proxy
  - RULE-SET,local-direct,DIRECT
  - GEOSITE,cn,DIRECT
  - GEOIP,CN,DIRECT,no-resolve
  - MATCH,Proxy

If a domain appears in both sets, the order of the RULE-SET entries in the main configuration still determines which one matches. This example puts the forced-proxy set before the direct-routing set so it can override exceptions. Provider names are identifiers; they don’t determine priority automatically.

Step 3: Check the Format and Update Behavior

  • YAML structure: Use spaces for indentation, not tabs. Keep only one top-level rules and one top-level rule-providers in the configuration, and merge new entries into them.
  • Behavior and content: A classical file contains complete rule conditions such as DOMAIN-SUFFIX,github.com; don’t mix in a plain list of domains. The domain and ipcidr behaviors each have their own content format.
  • Local updates: type: file does not periodically fetch content over the network. After editing a file, apply the changes using the client’s reload or rule-set update feature, then check the logs.
  • Remote updates: If you switch to type: http, provide a trusted, valid URL, a cache path, and an update interval. For example, interval: 86400 means 86,400 seconds, or 24 hours—not 86,400 milliseconds.

Subscription updates and rule-provider updates are separate operations. The former may rebuild the entire configuration; the latter typically updates just one rule set. If your rules disappear after every subscription update, check the client’s override and merge order instead of repeatedly editing a temporary generated file.

6. Verify Routing: Check Rules, Proxy Chains, and New Connections

A page loading successfully only shows that one access path works; it doesn’t prove that the expected rule matched. Set the log level to info, then check the target domain, destination IP, matched rule, and outbound chain on the connections page. Page labels differ between clients, so use the fields your client actually displays.

  1. Validate syntax before loading. If you manage mihomo directly, run mihomo -t -f ./config.yaml from the same working directory. Use the actual configuration filename and path. For a GUI client, use its built-in configuration validation feature as well.
  2. Test a direct-routing example. Open www.bilibili.com in a new connection and check that it matches local-direct and ultimately uses DIRECT. Other resources on the page may match different rules, so check their logs individually.
  3. Test a proxy example. Open github.com in a new connection and check that it matches local-proxy. Expand the outbound chain and confirm that Proxy currently selects a proxy node, not DIRECT within the group.
  4. Test the fallback. Choose a domain that isn’t in your manual sets and see whether it matches GEOSITE, GEOIP, or MATCH. Don’t assume that every domain not listed manually will use a proxy.
  5. Close existing connections before retesting. Reloading rules usually doesn’t migrate established connections. Browser connection reuse, HTTP/2, and QUIC can keep the old route active. Close the relevant connections or exit the app, then make a new request.

Use an Explicit Proxy to Tell “Traffic Didn’t Reach the Core” from “No Rule Matched”

If your mixed-port is set to 7890, run these two requests in a terminal. Replace the port with your actual value if it’s different. In Windows PowerShell, use curl.exe to avoid confusion with command aliases. Port 7890 is just an example; it isn’t the default for every client.

curl -I --proxy http://127.0.0.1:7890 https://www.bilibili.com
curl -I --proxy http://127.0.0.1:7890 https://github.com

A server may redirect or reject HEAD requests; that doesn’t prevent you from checking whether the connection reached the core. Watch the connection log at the same time. If explicit proxy requests appear in the log but browser or game traffic doesn’t, first check the system proxy, the app’s own proxy settings, or the scope of TUN capture. Don’t expand the rule list yet.

TUN mode captures network traffic that meets its routing conditions; it doesn’t force all traffic through a proxy. Once traffic reaches the core, the mode and rules still determine the outbound. Not every app follows the system proxy, either. Both features address how traffic enters the core, not how rules match.

7. Common Issues and Troubleshooting Order

SymptomCheck firstWhat to do
A site in mainland China still uses a proxyWhether it matched MATCH; whether only domain metadata is availableAdd domain rules and check the GEOSITE category and the effect of no-resolve
Proxy is shown, but traffic uses a local connectionThe proxy group’s current selection and the full outbound chainConfirm that the group has a valid proxy node selected, not DIRECT
No change after editingThe effective configuration, current mode, and existing connectionsReload the correct configuration and retest with new connections
Rule provider fails to loadFile path, payload, behavior, and indentationFix the local file first, then investigate remote download issues
Some images or sign-ins failOther domains used by the failed requests and their outboundsSet a consistent outbound for the related domains that need it
Only one app ignores the rulesWhether the app’s connections appear in the coreCheck the app’s proxy settings or TUN route capture before changing the classification database

Troubleshoot in this order: traffic capture path → rule mode → effective configuration → matched rule → proxy group selection → node connectivity. Rules select an outbound; they can’t fix a failed node or guarantee that the direct connection itself is available. If the expected rule matched, investigate the selected outbound instead of repeatedly adding the same domain.

For more on rule mode, listening ports, and proxy groups, see the proxy modes guide, ports guide, and proxy groups guide. For issues caused by subscription updates, continue with subscription troubleshooting.