Rule Structure and Prerequisites

Mihomo's rules is an ordered list of rules. The common format is rule type,match criteria,target policy; the final catch-all rule is written as MATCH,target policy. Targets can be built-ins such as DIRECT and REJECT, or the name of a proxy or proxy group defined in the configuration.

Rules determine where a connection is routed; they don't automatically capture all system traffic. Whether the core can see a request depends on how it enters Mihomo: the browser may use the system proxy, an app may have a proxy configured manually, or the client may capture connections through TUN. If the connection list doesn't show traffic from the app, check how it's connected before changing rules.

Check These Three Things First

  • The current mode is rule. Global mode doesn't route traffic through this standard rule list one rule at a time; Direct mode sends traffic directly.
  • You're editing the active configuration, and it has been saved and reloaded. The text in the client's editor may not match what the core actually loaded.
  • Every target policy exists. For example, if a rule uses PROXY, the configuration must define a proxy or proxy group with exactly that name, including capitalization and spacing.
mode: rule

rules:
  - DOMAIN,example.com,DIRECT
  - DOMAIN-SUFFIX,example.org,DIRECT
  - MATCH,PROXY

These snippets are meant to be merged into an existing configuration, not used as a complete setup with proxies, DNS, and listening ports. The examples assume an existing policy group named PROXY; if your group is actually named "Proxy Select," change the target accordingly. example.com and example.org are documentation domains—replace them with the services you want to route.

DOMAIN Rules: Exact Match, Suffix, and Keyword

Domain rules work well for websites and APIs addressed by domain name. Choose a rule type based on the scope you need; don't turn every domain into a keyword match. Broad keywords can route unrelated services whose names happen to contain the same text.

Type Example What It Matches
DOMAIN DOMAIN,api.example.com,DIRECT Exact match for api.example.com only
DOMAIN-SUFFIX DOMAIN-SUFFIX,example.com,DIRECT example.com and its subdomains
DOMAIN-KEYWORD DOMAIN-KEYWORD,example,DIRECT Targets with example anywhere in the domain name

Don't include the protocol or page path in a rule

The match value for DOMAIN must be a domain name, not a full URL. Adding https://api.example.com/v1 to a DOMAIN rule won't match a webpage path. Standard domain rules also can't distinguish between two pages on the same domain.

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

These rules send api.example.com through PROXY first, then send other example.com subdomains directly. This depends on rule order; DOMAIN doesn't automatically get higher priority. Swap the first two lines and the suffix rule will match first, leaving the exact-match rule no chance to run.

GEOSITE and Rule Sets: Categories Aren't Fixed Lists

GEOSITE uses domain category data. For example, GEOSITE,cn,DIRECT matches domains in the category named cn in the current geosite data. It doesn't check where a website's servers are located, nor does it identify every Chinese-language webpage. The actual matches depend on the data source and how recently it was updated.

rules:
  - DOMAIN,api.example.com,PROXY
  - GEOSITE,cn,DIRECT
  - GEOIP,CN,DIRECT,no-resolve
  - MATCH,PROXY
  • GEOSITE matches domain categories, while GEOIP matches categories based on the destination IP. They aren't interchangeable.
  • Make sure the required data is available before using these rules. A missing data file, failed download, or nonexistent category name can cause a load error.
  • Put custom exceptions before category rules. For example, if a domain needs to use a proxy, don't place it after a direct-routing category that already matches it.

Define a Provider Before Using RULE-SET

RULE-SET references a name defined under rule-providers. This example uses a local file to keep remote download issues separate from rule-matching issues. The path is relative to the core's working directory, and the client may restrict which locations it can access.

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

rules:
  - RULE-SET,local-direct,DIRECT
  - MATCH,PROXY

The corresponding local-direct.yaml file contains:

payload:
  - 'example.com'
  - '+.example.org'

With behavior: domain, the payload should contain domain match entries; +.example.org covers that domain and its subdomains. With behavior: classical, the payload should contain rule expressions such as DOMAIN-SUFFIX,example.org, while the outer RULE-SET specifies the target. Don't mix the two formats, and don't infer the rule-set type from the file extension alone.

IP-CIDR and no-resolve: Matching Destination Addresses

IP-CIDR matches IPv4 ranges, and IP-CIDR6 matches IPv6 ranges. The number after the slash is the prefix length: /32 represents a single IPv4 address, while /24 represents a network with 256 addresses. These rules check the destination address, not the source address of the device making the request.

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
  - MATCH,PROXY

no-resolve Doesn't Disable DNS

no-resolve means this IP rule won't actively trigger a domain lookup. If the connection already has a usable destination IP, it can still match. If it only has a domain name and no usable IP yet, the rule may be skipped and evaluation will continue. This isn't a global DNS switch, and it doesn't guarantee the domain won't be resolved at another stage.

Adding no-resolve to an IP rule doesn't guarantee that a domain will be routed based on its eventual resolved address. For internal domains that must connect directly, you should usually add a matching domain rule too, and check that the core can resolve the name using the correct internal DNS server.

PROCESS-NAME: Process Detection and Its Limits

PROCESS-NAME matches by process name and is useful when an entire app should use the same route. It relies on the core getting process information from the operating system; it doesn't infer an app's identity from its domain names. Availability depends on the OS, client implementation, permissions, and how traffic enters the core.

find-process-mode: strict

rules:
  - PROCESS-NAME,curl,DIRECT
  - PROCESS-NAME,curl.exe,DIRECT
  - DOMAIN-SUFFIX,example.com,PROXY
  - MATCH,PROXY

strict looks up process information on demand. For troubleshooting, temporarily switch to always and check whether process details become available, then choose the mode that fits your needs. Use the process name shown in connection details or the actual executable name—not the app's desktop shortcut name.

  • On Windows, process names commonly end in .exe; executable names may differ on other desktop platforms.
  • Browsers, launchers, and download tools may use child processes. The name of the main window may not match the process that actually opens the connection.
  • If requests are forwarded through another local proxy, the core may identify only the forwarding process and not the app that originally made the request.
  • TUN can capture traffic from more apps, but it doesn't guarantee that every platform provides complete process information. If the process field is empty, check permissions and platform support first.

Putting a process rule before domain rules means that connections from that process are handled by the process policy first. To route some websites opened in a browser directly while proxying others, put those domain exceptions before the browser's process rule.

Rule Order: First Match and the MATCH Catch-All

For the standard rules covered here, think of evaluation as: check from top to bottom and select the target when the first rule matches. The core won't skip a matching rule to look for a longer domain suffix, and it won't automatically move process rules ahead of domain rules.

Common Pitfall: A Broad Rule Masks a Narrow One

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

A request to api.example.com matches the first line here. To fix it, move the exact-match exception above the suffix rule instead of adding a duplicate. Likewise, an earlier GEOSITE, RULE-SET, or process rule can match before a later custom entry gets a chance.

Suggested Rule Order

  1. Specific exceptions: individual domains, processes, or special addresses.
  2. LAN and internal services: arrange domain and IP range rules to fit your network.
  3. Service rule sets and regional categories: these cover broader ranges, so check for overlap.
  4. MATCH: the final catch-all for connections that didn't match any earlier rule.

This order is a maintenance recommendation, not a requirement imposed by the core. If LAN traffic must bypass a process proxy rule, put the LAN rule above it. MATCH has no match-value field, so write it as MATCH,PROXY. If it's placed in the middle of the list, later standard rules won't get a chance to match.

Matching a policy group doesn't determine the final node. For example, a rule can route traffic to PROXY while that group is set to DIRECT, so the connection still goes directly. Check separately which rule matched and which route the policy group ultimately selected.

Rules Not Taking Effect: Check the Connection Evidence

Don't change DNS, TUN, and the entire ruleset all at once. Start with a reproducible test destination. Note its domain, request time, matched rule, policy chain, and any log errors, then change one variable at a time. Client menus vary, so look for the equivalent connection details, runtime logs, and active configuration view.

  1. Confirm the connection reaches the core. Make a new request, then search the connection list for the domain or process. If there's no entry, check the system proxy, the app's proxy settings, or the scope of TUN capture.
  2. Check the listening port. If the configuration has mixed-port: 7890, your test tool should connect to 127.0.0.1:7890. Don't assume another client's port is the same.
  3. Check the current mode and loaded configuration. Make sure the mode is Rule, and check for YAML, unknown-policy, or rule-set load errors when reloading.
  4. Check what's actually being matched. See whether the request redirects to another domain or uses multiple domains for static assets and APIs. Routing the page's main domain doesn't mean every resource follows the same route.
  5. Check earlier rules before the match. Look for an earlier DOMAIN-SUFFIX, GEOSITE, RULE-SET, process rule, or MATCH that may be catching the connection first.
  6. Check the route and use a new connection. Verify the policy group's current selection, then close existing connections or restart the test app. Don't use a long-lived connection established before the reload to test new rules.

Test a Fixed Entry Point with curl

These commands are for a local configuration with mixed-port: 7890 enabled. --noproxy "" clears the bypass list for this request to reduce interference from environment variables; -I sends a HEAD request, mainly to observe connection setup and rule matching. In Windows PowerShell, use curl.exe to call the executable explicitly.

curl --noproxy "" -I --proxy http://127.0.0.1:7890 https://example.com
curl --noproxy "" -I --proxy socks5h://127.0.0.1:7890 https://example.com

socks5h sends the destination domain to the proxy for resolution, which helps avoid differences caused by resolving it locally first. These commands test the explicit proxy path; they don't verify the TUN path. To test TUN, make sure the app isn't using an explicit proxy, then check the client's connection records to confirm traffic actually entered the virtual interface.

Symptom Check First What to Do
Configuration won't reload after saving Indentation, policy names, category data, rule-set format Fix the line indicated in the logs and use spaces for indentation
Always matches MATCH Whether the domain matches and process information is available Check the actual connection fields, not just the address bar
Matches PROXY but still connects directly Whether the policy group is set to DIRECT or a nested group that routes directly Expand the full policy chain and check the final route
Custom rules disappear after a subscription update Whether you're editing a file generated from the subscription Use the persistent override mechanism supported by the client

Subscription Updates and Rule Maintenance

A subscription may provide a complete configuration or just proxy nodes. Direct edits to a file generated from a full subscription may be overwritten on the next update. If your client supports overrides, merging, or script-based processing, first check how it handles rules: does it replace the list, prepend entries, or append them at the end?

Appending rules is especially likely to leave them present but ineffective. If the original subscription ends with MATCH, any new rules must appear before MATCH in the final active configuration. Don't check only the override editor; verify the merged rule order and test with a new connection.

Keep a Record of Changes You Can Roll Back

  • Add one clearly scoped set of rules at a time, and record the target domains, expected route, and reason for each change.
  • Back up local rule sets along with the main configuration so you don't lose external files when restoring only the YAML.
  • After updating the client or core, recheck process detection, rule-set loading, and critical exceptions. Don't rely on results from old connections.
  • Before sharing logs, redact subscription URLs, proxy credentials, and controller API secrets. For troubleshooting, share the relevant rule snippet and match details instead.

Good rule maintenance comes down to making scope and order easy to understand: put specific exceptions ahead of broad rules that would catch them, keep the catch-all last, and use connection details to confirm what actually matched. Verify the traffic entry point first, then the match fields, and finally the policy chain. This is usually more effective than repeatedly switching modes.