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.
- 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.
- 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. - Check the outbound name. This guide uses
Proxyfor an existing proxy group. Names are case-sensitive. The group must be defined in the current configuration’sproxy-groupsand have a valid node selected. - 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 type | Applies to | Key distinction |
|---|---|---|
DOMAIN | A single fully qualified domain name | Exact match; does not automatically include other subdomains |
DOMAIN-SUFFIX | A domain and its subdomains | github.com also matches api.github.com |
GEOSITE | A set of domains in a database | Requires the local database to include the relevant category |
GEOIP | The region associated with the destination IP | Does not identify the region of a website, account, or service operator |
RULE-SET | Entries in a rule provider | The set is defined under rule-providers |
MATCH | Connections not matched by earlier rules | A 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
rulesand one top-levelrule-providersin the configuration, and merge new entries into them. - Behavior and content: A
classicalfile contains complete rule conditions such asDOMAIN-SUFFIX,github.com; don’t mix in a plain list of domains. Thedomainandipcidrbehaviors each have their own content format. - Local updates:
type: filedoes 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: 86400means 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.
- Validate syntax before loading. If you manage mihomo directly, run
mihomo -t -f ./config.yamlfrom the same working directory. Use the actual configuration filename and path. For a GUI client, use its built-in configuration validation feature as well. - Test a direct-routing example. Open
www.bilibili.comin a new connection and check that it matcheslocal-directand ultimately usesDIRECT. Other resources on the page may match different rules, so check their logs individually. - Test a proxy example. Open
github.comin a new connection and check that it matcheslocal-proxy. Expand the outbound chain and confirm thatProxycurrently selects a proxy node, notDIRECTwithin the group. - 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.
- 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
| Symptom | Check first | What to do |
|---|---|---|
| A site in mainland China still uses a proxy | Whether it matched MATCH; whether only domain metadata is available | Add domain rules and check the GEOSITE category and the effect of no-resolve |
| Proxy is shown, but traffic uses a local connection | The proxy group’s current selection and the full outbound chain | Confirm that the group has a valid proxy node selected, not DIRECT |
| No change after editing | The effective configuration, current mode, and existing connections | Reload the correct configuration and retest with new connections |
| Rule provider fails to load | File path, payload, behavior, and indentation | Fix the local file first, then investigate remote download issues |
| Some images or sign-ins fail | Other domains used by the failed requests and their outbounds | Set a consistent outbound for the related domains that need it |
| Only one app ignores the rules | Whether the app’s connections appear in the core | Check 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.