Clash Custom Rules: Rule Types, Matching Order, and the MATCH Catch-All
Learn the syntax for DOMAIN, DOMAIN-SUFFIX, IP-CIDR, GEOIP, and more. See how first-match rule ordering works and how to prioritize overrides.
1. Rule Syntax: Match Conditions and Policies
Clash custom rules determine which outbound policy handles a connection. The client provides the editing interface, while the core performs the actual matching. Rule support differs between the original Clash and Clash Meta (now called mihomo). This guide covers common basic syntax for both, with compatibility notes for rule providers where relevant.
Common rules go in the top-level YAML rules: list. Each line typically contains a rule type, a match value, and a policy; some rule types also accept additional parameters. MATCH has no match value, so you only need to specify the outbound policy.
rules:
- DOMAIN,example.com,DIRECT
- DOMAIN-SUFFIX,example.org,REJECT
- IP-CIDR,192.168.50.0/24,DIRECT,no-resolve
- MATCH,DIRECT
This is a rule snippet, not a complete subscription configuration. DIRECT sends traffic directly, while REJECT blocks the connection. If you use Proxy Out as the policy, that name must already exist as a proxy node or policy group in the current configuration. Policy names are exact references; their meaning does not automatically create an outbound route.
2. DOMAIN and DOMAIN-SUFFIX: Exact Matches and Domain Suffixes
| Type | Example | What it matches |
|---|---|---|
| DOMAIN | DOMAIN,api.example.com,DIRECT | Matches only api.example.com, not its subdomains. |
| DOMAIN-SUFFIX | DOMAIN-SUFFIX,example.com,DIRECT | Matches example.com and its subdomains, such as api.example.com. |
| DOMAIN-KEYWORD | DOMAIN-KEYWORD,example,REJECT | Matches connections to domains containing example. This is broader than a suffix rule. |
Domain rules do not include URL paths
To handle https://api.example.com/v1/status, enter the domain api.example.com. Do not include https://, /v1/status, or a port. Standard domain rules cannot route traffic based on HTTPS page paths, so two paths on the same domain will not use different outbounds.
- For an exception that applies to a single endpoint, use
DOMAIN. - To apply the same policy to a base domain and all its subdomains, use
DOMAIN-SUFFIX. - Keyword rules can match unrelated domains. Check the connection log to confirm their scope before leaving them enabled.
Domain matching also depends on whether the core can obtain the destination domain. If an app connects directly to an IP, DNS does not pass through the core as expected, or the connection metadata does not include a domain, do not assume a DOMAIN rule will match. mihomo’s domain sniffing can provide additional information in some cases, but it is not a universal fix for every protocol.
3. Rule Order: Top to Bottom, First Match Wins
Clash does not gather every matching rule and then choose the one that “looks most specific.” It checks the standard rule list in order, and the first rule whose conditions are met determines the outbound for that connection. Later rules are not considered. That is why specific exceptions usually go first and broader categories follow.
rules:
- DOMAIN,api.example.com,DIRECT
- DOMAIN-SUFFIX,example.com,REJECT
- MATCH,DIRECT
In this example, connections to api.example.com go direct, while connections to www.example.com are rejected. If you swap the first two lines, api.example.com matches the domain suffix rule first, and the exact-match direct rule never gets a chance to apply. DOMAIN has not lost priority—the match process has already stopped.
A Practical Order That’s Easy to Maintain
- Explicit exceptions for individual sites: Domains that need a dedicated allow, block, or outbound policy.
- LAN and internal services: Address ranges and internal domains confirmed to belong to your local network.
- Service categories and rule sets: Broad routing rules organized by purpose.
- Broad geographic matches: For example, IP rules that rely on a geolocation database.
- MATCH: Handles connections not matched by any rule above.
This is a maintenance approach, not a template you have to follow. If security requirements say a type of connection must be blocked first, put the block rule before the corresponding allow rule and check for conflicts. The key principle is that every rule near the top should be allowed to override the rules below it.
4. IP-CIDR and GEOIP: Destination Addresses, Resolution, and no-resolve
IP-CIDR matches destination IPv4 address ranges; IP-CIDR6 is for IPv6. For example, 192.168.50.0/24 covers addresses in that subnet and is useful for routing a home NAS, printer, or internal service directly. It does not filter by the source device’s address.
rules:
- IP-CIDR,192.168.50.0/24,DIRECT,no-resolve
- IP-CIDR6,fd00::/8,DIRECT,no-resolve
- GEOIP,CN,DIRECT
- MATCH,DIRECT
GEOIP,CN,DIRECT checks whether the destination IP is classified as CN by the current IP geolocation database. It is not a complete list of “Chinese websites.” A site may use a CDN in multiple regions, and a single domain can resolve to different addresses. The database, its update date, and DNS results all affect the match, so verify the matching GEOIP rule using the resolved destination IP and its database classification.
What no-resolve Does—and Does Not Do
If a connection has a domain but no usable destination IP, an IP rule may trigger a DNS lookup. Adding no-resolve means the rule will not actively resolve the domain just to check for a match. If the connection metadata already contains a usable IP, address matching can still happen. This does not disable DNS or make every domain request bypass IP-based checks.
- LAN IP direct rules often include
no-resolveto avoid resolving other domains just to check whether they fall within a private network range. - If you want GEOIP to evaluate domains that have not yet been resolved, do not add
no-resolveby default. - To route traffic based on the address of the device that initiated the connection, use a source-address rule supported by the core instead of putting the source IP in IP-CIDR.
The fd00::/8 range above is only an example of an IPv6 local address range; it does not cover every local network setup. Choose a subnet based on your address plan, and check that traffic still follows the intended policy when DNS returns an IPv6 address.
5. MATCH Catch-All: Choosing the Final Outbound
MATCH matches unconditionally. If it appears in the middle of the list, the standard matching process can no longer reach the ordinary rules below it. Usually, keep just one MATCH rule and place it at the end. Appending custom rules after MATCH is a common reason a configuration loads successfully but the rules have no effect.
rules:
- DOMAIN,api.example.com,DIRECT
- DOMAIN-SUFFIX,example.org,REJECT
- IP-CIDR,192.168.50.0/24,DIRECT,no-resolve
- MATCH,Proxy Out
This example assumes the configuration already has a policy group named Proxy Out. Connections not matched by the first three rules go to that group, but the actual outbound still depends on the group’s current selection. If DIRECT is selected, the connection still goes direct. Matching a policy group and using a specific proxy node are two separate outcomes.
6. Subscription Overrides: Prepending, Appending, and Replacing Rules
Subscriptions are usually updated periodically, so edits made directly to a downloaded configuration may be overwritten on the next update. A safer option is to use the client’s local override, configuration merge, or rule editor feature. The interface, fields, and merge behavior vary by client and version; one client’s override syntax is not universal Clash YAML.
Inspect the Final Configuration Before Assuming the Save Worked
- Back up the working configuration and note the existing policy group names and final catch-all rule.
- In the local override linked to the current subscription, choose the option to prepend custom rules. If the interface only supports appending, make sure the rules are not inserted after MATCH.
- Inspect the merged, active configuration. Search for the test domain and confirm it appears in
rulesbefore broader rules. - Reload the configuration, start a new connection, and check which rule matched. Do not rely only on the original snippet in the editor.
Replacing rules removes the existing rule list, potentially including rule set references from the subscription, LAN exceptions, and the catch-all policy. If you only need to change one domain, prefer prepending a single specific rule over copying and maintaining the entire subscription.
RULE-SET Placement Matters Too
Cores that support rule-providers can reference rule sets with RULE-SET. Check the core and version for specific support; do not assume every original Clash build supports it. The snippet below assumes a provider named work-domains and a policy group named Proxy Out are already defined:
rules:
- DOMAIN,status.example.com,DIRECT
- RULE-SET,work-domains,Proxy Out
- MATCH,DIRECT
Even if the rule set contains status.example.com, the DOMAIN exception above it matches first. A rule set has no special priority outside its position in the rules list. Also check the provider’s behavior and the file format: payloads for domain, ipcidr, and classical cannot be used interchangeably.
7. Custom Rules Not Working? Troubleshoot with Connection Logs
For easier testing, change one thing at a time. Add a temporary REJECT rule for a domain you control at the top of the list, reload, and make a new request. Check the connection log to confirm the rule matched, then change it to the intended outbound. Remove the temporary block rule after testing so it does not affect later use.
| Symptom | Check First | Next Step |
|---|---|---|
| New rule does not appear at all | Active subscription, override association, and effective configuration | Confirm that you are editing the configuration loaded by the core. |
| A different rule matches | Earlier DOMAIN-SUFFIX, RULE-SET, or MATCH entries | Move the specific exception above the relevant broader rule. |
| Policy group matches, but traffic uses the wrong outbound | The group’s current selection and any nested policy groups | Follow the policy chain to the final node or DIRECT. |
| Only some requests behave as expected | Redirected domains, resource domains, IPv6, and existing connections | Check each new connection instead of relying only on the browser’s address bar. |
| Reload fails with an error | YAML indentation, rule syntax, policy names, and provider names | Run a configuration check, then reload. |
Validate the Configuration with the Core
When using the mihomo command line directly, run the following check from the directory containing the configuration file. The executable must be on your command search path, and referenced resources must be available:
mihomo -t -f config.yaml
A successful check means the configuration meets the core’s loading requirements; it does not confirm that traffic is routed as intended. Open the client’s connection log or logs and check the destination domain, destination IP, matched rule, and policy chain. In a GUI client, also verify which generated configuration it actually loaded—checking a backup file on its own is not enough.
Finally, changing rules usually does not move existing long-lived connections to a new outbound immediately. Browser HTTP/2 sessions, downloads, and messaging connections may continue using their original channels. After saving and reloading, establish a new test connection. If necessary, close the old connection before testing again so connection reuse is not mistaken for a rule failure.
Keep custom rules focused on a few clear exceptions, and note why each one appears where it does. When troubleshooting, check in order whether traffic reaches the core, Rule mode is enabled, the active rule order is correct, the expected policy matches, and the final outbound is right. This usually pinpoints the issue faster than repeatedly switching nodes.