Routing — mihomo
mihomo's routing engine is a list of compact one-line rule strings under the top-level rules: key. Each rule has the form:
<TYPE>,<payload>,<target>[,no-resolve][,src]Rules are evaluated in declaration order; the first matching rule wins. The target is either a proxy name, a proxy-group name, or one of the built-in DIRECT / REJECT / COMPATIBLE names.
Rule types
mihomo defines 30+ rule types. The most commonly used:
Destination matchers
| Type | Payload | Example |
|---|---|---|
DOMAIN | exact domain | DOMAIN,example.com,proxy |
DOMAIN-SUFFIX | suffix match (any subdomain) | DOMAIN-SUFFIX,example.com,proxy |
DOMAIN-KEYWORD | substring match in any label | DOMAIN-KEYWORD,google,proxy |
DOMAIN-REGEX | RE2 regex against the full domain | DOMAIN-REGEX,^([a-z]+)\.cdn\.example$,proxy |
DOMAIN-WILDCARD | glob with * (and + matches one label) | DOMAIN-WILDCARD,*.example.com,proxy |
GEOSITE | category from geosite.dat / MaxMind | GEOSITE,category-ads,REJECT |
GEOIP | category from geoip.dat / MaxMind | GEOIP,CN,DIRECT |
IP-CIDR | CIDR match | IP-CIDR,10.0.0.0/8,DIRECT,no-resolve |
IP-SUFFIX | match by trailing IP bits | IP-SUFFIX,::1/128,DIRECT |
IP-ASN | ASN from MaxMind | IP-ASN,13335,proxy |
Source matchers
| Type | Payload | Example |
|---|---|---|
SRC-IP-CIDR | source CIDR | SRC-IP-CIDR,192.168.1.0/24,DIRECT |
SRC-IP-SUFFIX | source IP-suffix | SRC-IP-SUFFIX,::1/128,DIRECT |
SRC-GEOIP | source GeoIP category | SRC-GEOIP,CN,DIRECT |
SRC-IP-ASN | source ASN | SRC-IP-ASN,4134,DIRECT |
SRC-PORT | source-port range | SRC-PORT,53,DNS |
IN-PORT | inbound listener port | IN-PORT,8388,DIRECT |
IN-USER | inbound auth user | IN-USER,alice,proxy |
IN-NAME | inbound listener name | IN-NAME,vless-in,proxy |
IN-TYPE | inbound listener type | IN-TYPE,SOCKS5,proxy |
Connection matchers
| Type | Payload | Example |
|---|---|---|
DST-PORT | destination port (single, range, list) | DST-PORT,443,proxy |
NETWORK | tcp or udp | NETWORK,udp,proxy-udp |
DSCP | DSCP value | DSCP,46,proxy-priority |
UID | local user ID (Linux/macOS) | UID,1000,proxy |
Process matchers
| Type | Payload | Example |
|---|---|---|
PROCESS-NAME | process basename | PROCESS-NAME,curl,proxy |
PROCESS-PATH | absolute path | PROCESS-PATH,/usr/bin/curl,proxy |
PROCESS-NAME-REGEX / PROCESS-PATH-REGEX | regex | PROCESS-NAME-REGEX,^chrome.*$,proxy |
PROCESS-NAME-WILDCARD / PROCESS-PATH-WILDCARD | glob | PROCESS-NAME-WILDCARD,fire*,proxy |
Set & combinator types
| Type | Payload | Example |
|---|---|---|
RULE-SET | rule-set name (declared in rule-providers) | RULE-SET,gfw,proxy |
SUB-RULE | named sub-rule (declared in sub-rules) | SUB-RULE,(NETWORK,udp),sub-udp |
AND / OR / NOT | boolean combinators | AND,((DOMAIN-SUFFIX,com),(IP-CIDR,1.0.0.0/8)),proxy |
MATCH | unconditional default | MATCH,proxy |
Modifiers
After the target, two optional comma-separated modifiers are allowed:
no-resolve— for IP/GEOIP rules, do not resolve a destination domain to IP for matching. Speeds up the rule but trades accuracy.src— for IP-suffix rules, match on the source IP instead of the destination IP.
rule-providers
Top-level rule-providers: declares named rule sources you reference from RULE-SET rules. Two transport types and three formats:
rule-providers:
geosite-cn:
type: http
behavior: domain # 'domain', 'ipcidr', or 'classical'
format: mrs # 'yaml', 'text', or 'mrs' (binary)
url: https://example.com/geosite-cn.mrs
interval: 86400 # refresh interval in seconds
path: ./rule-providers/geosite-cn.mrs
proxy: DIRECT # outbound used for the download
local-block:
type: file
behavior: classical
format: yaml
path: ./rule-providers/block.yamlBehaviors:
domain— payload is one domain per line. Fast.ipcidr— payload is one CIDR per line.classical— payload is full mihomo rule strings (everything except the target). Slower but most flexible.
sub-rules
Top-level sub-rules: declares named sub-rule lists you can call into with SUB-RULE. Useful for nesting rule logic without duplicating it.
sub-rules:
sub-udp:
- GEOIP,CN,DIRECT
- MATCH,udp-proxy
rules:
- SUB-RULE,(NETWORK,udp),sub-udp
- MATCH,proxyExamples
Classic CN-bypass routing:
rules:
- DOMAIN-SUFFIX,local,DIRECT
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,127.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
- GEOSITE,cn,DIRECT
- GEOIP,CN,DIRECT
- MATCH,proxyProcess-based split:
rules:
- PROCESS-NAME,curl,DIRECT
- PROCESS-NAME-WILDCARD,fire*,proxy
- MATCH,DIRECTBoolean combinators:
rules:
- AND,((NETWORK,udp),(DST-PORT,443)),quic-proxy
- OR,((DOMAIN-SUFFIX,onion),(GEOSITE,private)),tor
- NOT,((GEOIP,CN)),proxy
- MATCH,DIRECTUsing rule-providers with a RULE-SET rule:
rule-providers:
gfw:
type: http
behavior: domain
format: mrs
url: https://example.com/gfw.mrs
interval: 86400
path: ./providers/gfw.mrs
rules:
- RULE-SET,gfw,proxy
- MATCH,DIRECTNotes
- Rules are evaluated in order. Put
no-resolvemodifiers on IP rules early in the list to avoid one DNS lookup per connection for obvious-local traffic. - The
GEOSITE/GEOIPrule types read fromgeoip.dat/Country.mmdbandgeosite.dat. URL overrides live under the top-levelgeox-urlblock. - The combinator syntax (
AND,(<rule>,<rule>),target) uses parentheses around each nested rule. The nested rules omit the target — the target on the outer combinator applies. RULE-SETrules ignore theno-resolve/srcmodifiers on the outer rule; instead set those properties on the rule-provider declaration itself.- mihomo has no
finalfield. Use aMATCH,<target>at the end ofrules:for the catch-all behavior.
Cross-core notes
- Xray-core uses structured JSON rules with per-criterion fields and a polymorphic match shape. There is no compact-string form. See Routing — Xray-core.
- sing-box uses structured rules too, but with explicit
actionenums (route / direct / bypass / reject / hijack-dns / sniff / resolve) and a separaterule_setblock for named rule lists. See Routing — sing-box.
