Clash Custom Rules: DOMAIN-SUFFIX, IP-CIDR, GEOIP & Rule Order

Learn Clash rule syntax, first-match-wins ordering, and where to place rule-providers and the MATCH fallback.

Rule syntax: type, match value, and outbound policy

Clash custom rules go in the rules: list of your YAML configuration. In Rule mode, the core uses this list to decide how each connection is routed. This guide covers standard Clash rule syntax; for rule-set loading, use configuration supported by mihomo. The desktop client provides the editing interface, but the active core evaluates the rules.

mode: rule
rules:
  - DOMAIN,example.com,DIRECT
  - DOMAIN-SUFFIX,example.org,Proxy
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - MATCH,Proxy

This snippet must be merged into an existing configuration; it is not a complete subscription. Proxy must match the name of a policy group already defined under proxy-groups, or you can replace it with the name of an existing proxy node. Names must match exactly, including spaces and capitalization. A policy that doesn't exist can cause the configuration to fail to load.

  • DOMAIN: the rule type, which determines how the second field is interpreted.
  • example.com: the match value, in this case a fully qualified domain name without a scheme, path, or port.
  • DIRECT: a built-in policy that connects to the destination directly through your local network.
  • REJECT: a built-in policy that blocks matching connections.
  • no-resolve: an optional parameter supported by some IP rules; it is not an outbound policy name.

DOMAIN-SUFFIX: exact domains vs. domain suffixes

Use DOMAIN to match a single hostname. Use DOMAIN-SUFFIX to match a domain and all its subdomains. Suffix matching respects domain-label boundaries; it doesn't search for an arbitrary string anywhere in the hostname.

Rule examplesMatchesDoes not match
DOMAIN,example.com,DIRECTexample.comwww.example.com
DOMAIN-SUFFIX,example.com,DIRECTexample.com、api.example.comnotexample.com
DOMAIN-KEYWORD,example,DIRECTA hostname containing exampleA domain that doesn't contain this string

Put exceptions before suffix rules

Suppose you want all of example.com to go direct, except api.example.com, which should use a proxy. Put the exact-domain rule first, followed by the broader suffix rule:

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

If you swap the first two lines, the API hostname matches the suffix rule first and goes direct. The core won't reconsider the connection just because a more specific rule appears later. DOMAIN-KEYWORD has a broader scope and can catch unrelated domains. When an exact-domain or suffix rule will do, prefer the more clearly scoped match.

Domain rules don't match URL paths

Don't put https://example.com/video in a DOMAIN rule. These rules match hostnames, not full URLs, so they can't distinguish /video from /docs on the same domain. For HTTPS, the core also can't read encrypted URL paths using these rules alone.

IP-CIDR and GEOIP: address ranges, databases, and no-resolve

IP-CIDR matches IPv4 destination ranges; use IP-CIDR6 for IPv6. The number after the slash is the prefix length, not a port. A single IPv4 address can use /32, and a single IPv6 address can use /128.

rules:
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
  - IP-CIDR6,fc00::/7,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,Proxy

The first three rules cover common IPv4 private address ranges; the fourth covers IPv6 unique-local addresses. These rules route traffic inside the core, but they don't guarantee that all local network connections will pass through it. System proxy bypass lists and TUN route exclusions can still let traffic bypass the client.

GEOIP doesn't identify the country a website belongs to

GEOIP,CN,DIRECT matches destination addresses using the IP geolocation data available to the core. It doesn't check the domain suffix, company registration, or the user's account region. CDN address changes, different DNS responses, and geolocation database versions can all affect the match. To control a specific service reliably, put an explicit domain rule before GEOIP.

no-resolve only prevents DNS resolution for the current rule

When a connection has a domain name but no usable destination IP yet, an IP rule may trigger DNS resolution to check the address. Adding no-resolve prevents that rule from resolving the domain just to evaluate the match. If a usable IP is already available, the address can still be matched.

  • Adding no-resolve to private-range rules can reduce DNS lookups performed solely to check for private addresses.
  • With this parameter on a GEOIP rule, a connection that has only a domain name and no usable IP may skip the rule and continue to the next one.
  • If an earlier rule has already triggered resolution, a later no-resolve won't undo the result.

Rule order: top to bottom, stop at the first match

The rule list isn't automatically sorted by specificity, nor does the core move DOMAIN rules ahead of GEOIP rules based on type. It checks rules in order: if one doesn't match, it checks the next. Once a rule matches, the connection is sent to that policy and no further rules are evaluated.

  1. Put explicit exceptions first. For example, a specific API that must use a proxy or a test domain that must be blocked.
  2. Next, add domain and service rule sets. Define policies for known services before matching by IP location.
  3. Then add private-range and regional IP rules. Their order depends on whether domain policies should override address-based policies.
  4. Put MATCH last. It provides an explicit outbound for every connection that hasn't matched an earlier rule.

This is a common way to organize rules, not a requirement imposed by the core. If every private-network destination must go direct, move those rules ahead of any service rules that could match them first. To choose the right order, decide which policy takes priority for your use case.

rules:
  - DOMAIN,blocked.example.com,REJECT
  - DOMAIN,api.example.com,Proxy
  - DOMAIN-SUFFIX,example.com,DIRECT
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,Proxy

With this list, blocked.example.com is rejected, api.example.com is sent to Proxy, and www.example.com goes direct. Even if the API resolves to an address covered by the GEOIP rule below, that rule isn't checked because the domain rule already matched.

Regular rules after MATCH won't run

MATCH,Proxy has no match-value field, so it applies to every connection that reaches it. If you put it in the middle of the list, all subsequent regular rules are effectively disabled. Don't write MATCH,*,Proxy; the outbound is the second field.

A connection failure after a rule matches usually won't make the core go back and try the next rule. For failover between nodes, configure the appropriate selection behavior in a policy group instead of repeating the same domain in rules with different outbounds.

rule-providers: define a rule set, then reference it with RULE-SET

Use rule-providers to declare a rule-set source and RULE-SET to add that set to the matching list. A declaration by itself doesn't affect routing. This example uses a local rule set in mihomo, with the file in the classic rule format:

rule-providers:
  office-services:
    type: file
    behavior: classical
    format: yaml
    path: ./rules/office-services.yaml

rules:
  - DOMAIN,api.example.com,Proxy
  - RULE-SET,office-services,DIRECT
  - GEOIP,CN,DIRECT
  - MATCH,Proxy

Save the following content as rules/office-services.yaml in the core's working directory. The working directory used to resolve relative paths depends on how the client starts the core; it isn't necessarily the download directory. The file must also be somewhere the client allows the core to access.

payload:
  - DOMAIN-SUFFIX,example.org
  - DOMAIN,intranet.example.com
  - IP-CIDR,10.20.0.0/16

The payload entries here don't include DIRECT or a policy group name. The referencing rule, RULE-SET,office-services,DIRECT, specifies the outbound for the whole set. A regular configuration's rules list and a rule-set file's payload use different structures and aren't interchangeable.

behaviorFormatWhen to use
classicalTyped entries such as DOMAIN-SUFFIX,example.orgSuitable for a mix of domain and IP conditions
domainDomain-only match entriesDon't paste classic entries with a DOMAIN-SUFFIX, prefix
ipcidrAddress ranges such as 10.20.0.0/16Don't include domains or outbound policies

A RULE-SET takes priority from its position in rules. It won't run if placed after MATCH, and it may catch connections meant for a specific exception if placed before that exception. The position of the top-level rule-providers section relative to rules doesn't affect match priority.

For a remote HTTP rule set, interval: 86400 sets the provider's update interval to 86,400 seconds, or 24 hours. This is separate from the subscription update schedule and the proxy-node list update schedule. This guide uses a local file, so it doesn't configure HTTP update options.

In the client: overrides, reloads, and connection checks

If you edit a subscription file directly, the next subscription update may restore its original contents. To keep custom rules, use the client's override, configuration merge, or scripting feature where possible, and verify the final order in rules. Clients may replace the entire array or insert entries at the beginning or end. The contents of an editor alone don't tell you what the final configuration will be.

Check the active configuration, not just the editor

  1. Note the client and core versions. In the client's Settings or About page, check whether it runs mihomo or another core so you don't use newer syntax with an older core.
  2. On the Configuration page, select the active subscription, then open its editor or override settings. Menu names vary between client versions. After saving, reload or apply the configuration.
  3. Check that the active configuration has only one top-level rules: list, and that your new exceptions come before the subscription-generated MATCH.
  4. Switch to Rule mode, then open the target connection under Connections to check the matched rule, rule content, and policy chain.

Test the rule with a new connection

Existing TCP connections usually keep using the outbound they had when established. After changing rules, close the relevant connections or restart the application before making a new request. This avoids false results caused by browser connection reuse. The command below applies only if the active configuration actually listens on mixed-port: 7890 and accepts connections from your local machine:

curl.exe -I --proxy http://127.0.0.1:7890 https://example.com/

On Windows, use curl.exe to call the curl program explicitly. This command specifies an HTTP proxy rather than relying on whether the browser uses the system proxy. Port 7890 is just an example for testing, not a standard default across clients. After running it, find example.com on the Connections page and check the matched rule and policy chain; whether the page opens doesn't prove that routing is correct.

Common errors and how to fix them

  • Configuration parse error: Check that indentation uses spaces, list items start with - , and commas are standard ASCII commas. Don't add a duplicate top-level key.
  • Policy not found: Compare the rule's third field character-for-character with the actual policy group name. In particular, check whether a subscription update renamed the group.
  • Rule set failed to load: Check the provider name, file path, behavior, and file contents. Make sure payload is indented correctly.
  • MATCH is always hit: Check whether the connection details show a domain, whether the destination has changed to another hostname, and whether the rule made it into the active configuration.
  • No entries on the Connections page: First check whether the application is using the proxy or is routed through TUN. Rules can't fix traffic that never reaches the core.

For configuration field details, see the Protocol Reference. If you're unsure how policy groups, system proxy, and TUN differ, start with the Glossary. Keep exceptions clear, outbounds valid, and MATCH in the fallback position.

Download ClashChoose an installer for your OS