Why policy routing is the backbone of Clash

Modern Clash engines still describe traffic as a prioritized decision tree. Every outbound TCP or UDP flow presents a hostname or IP tuple, DNS metadata, ports, inbound interface tags, optional process metadata depending on extensions, then the core walks your rules array until something matches or you fall through to a FINAL catch-all. Understand that sequencing is not stylistic fluff: it is semantics. Slip an overly broad GEOIP snippet above a surgical DOMAIN whitelist and you silently shadow the exemptions you meticulously composed.

Good operators reason in layers. Picture three horizontal bands inside the YAML: absolute bypass rails for multicast, captive portals, and RFC1918; targeted DOMAIN or IP matchers for flaky SaaS dashboards; GEOIP wedges for regional bulk traffic; lastly RULE-SET imports that track third-party trackers or streaming domains refreshed from remote manifests. Thinking in strata keeps merges from upstream subscriptions predictable when you splice them into your handcrafted header.

Scope note: Syntax here targets broadly adopted Mihomo-family cores bundled with GUIs such as Verge Rev, Stash-compatible forks, FlClash, and other maintained distributions. Older frozen cores omit some matchers; align feature flags with whatever release pins your package.

DOMAIN, DOMAIN-SUFFIX, and DOMAIN-KEYWORD distilled

Host-based matchers are the precision scalpels of any ruleset.

DOMAIN

DOMAIN asserts equality on the fully-qualified host segment after normalization. Reach for this when certificates, HTTP virtual hosts, or API gateways expect an exact hostname and you refuse accidental hits on cousin subdomains.

rules:
  - DOMAIN,stun.l.google.com,DIRECT

DOMAIN-SUFFIX

DOMAIN-SUFFIX aligns with suffix trees. It matches both the apex and arbitrarily deep subdomains, which mimics DNS zone delegation intuition. Abuse it carefully: suffixing co.uk would be disastrous, while suffixing corp.internal for a split-horizon zone is ergonomic.

rules:
  - DOMAIN-SUFFIX,githubcopilot.com,PROXY

DOMAIN-KEYWORD

DOMAIN-KEYWORD hunts substrings anywhere in the host label sequence. Powerful for messy CDNs emitting disposable host prefixes, risky when the substring appears inside benign SaaS multitenant namespaces. Prefer longer tokens, combine with supplemental IP checks, or graduate to RULE-SET curators.

rules:
  - DOMAIN-KEYWORD,analytics,REJECT

Anchor these near the top when they encode allow/deny absolutes, but never before link-local or private IP-CIDR bypass lines that protect discovery protocols and printer queues from accidental tunneling.

GEOIP: country buckets and database reality

GEOIP maps the destination IP to an ISO-3166 alpha-2 country using the embedded MMDB snapshot your distribution ships. That means your results only stay honest if the database update cadence of the GUI or core matches what you expect geopolitically. Cloud edge nodes shift countries when anycast routing changes, so do not treat GEOIP as moral truth—treat it as a statistical hint.

Two patterns dominate production configs. First, send everything tagged CN (or whichever domestic code you choose) to DIRECT while sending the complement through a proxy policy group. Second, invert with GEOIP,XX plus negation patterns if your provider ships specialized syntax for “not this region.” Always pair domestic splits with a reliable DNS policy; fake IP or encrypted DNS strategies change how early tuple resolution occurs.

rules:
  - GEOIP,LAN,DIRECT
  - GEOIP,CN,DIRECT
  - MATCH,PROXY

When DNS returns only domestic resolvers but the actual asset lives abroad, you may loop extra lookups. Watch log traces: if you see repeated resolution attempts before policy evaluation, consider moving pure IP-CIDR lines earlier or toggling no-resolve on sensitive GEOIP rows as recommended in later sections.

RULE-SET and rule-providers: scaling without YAML soup

Inline lists beyond a few hundred lines become merge-conflict magnets. RULE-SET references an indirection: you declare reusable bundles under rule-providers, assign an internal name, point to HTTP(S) or file resources, optionally choose binary snapshots, interval refresh windows, or behavior hints that clarify whether payloads describe classical rules or domain artifacts.

rule-providers:
  privacy:
    type: http
    behavior: classical
    url: https://ruleset.example.dev/privacy.yaml
    path: ./providers/privacy.yaml
    interval: 86400

rules:
  - RULE-SET,privacy,REJECT
  - DOMAIN-SUFFIX,meet.example,DIRECT

Selective adoption beats blind imports. Mirrors vanish without notice; prefer sources you can checksum or pin by hash when your threat model cares. Keep intervals staggered relative to subscription refresh so you avoid synchronized thundering herds when hotel Wi-Fi is already fragile.

Compose multiple RULE-SET entries with explicit ordering: granular DOMAIN exceptions before RULE-SET blocklists, lest a blocklist overshadow your corporate allowlist intended for conferencing infrastructure.

A grounded ordering recipe anyone can crib

Sequences matter more than novelty. Borrow this skeleton mentally: start with unconditional DIRECT for invalid or multicast targets; follow with LAN and private-CIDR bypass; carve custom DOMAIN/IP pairs for brittle finance portals; funnel ads or telemetry via RULE-SET REJECT directives; escalate streaming DOMAIN-SUFFIX entries if your provider forbids accidental datacenter egress; widen with GEOIP for domestic acceleration; funnel MATCH or FINAL defaults into a measured policy group—not raw single nodes.

Stage Typical matchers Outcome
Survival rails IP-CIDR link-local ranges, GEOIP LAN Protect discovery, captive portals
Fine exemptions DOMAIN, PROCESS-NAME* Warp stubborn enterprise apps (*if supported)
Hygiene bundles RULE-SET adware/tracking Drop noise early
Regional shaping GEOIP buckets Prefer domestic egress
Default posture MATCH/FINAL proxies Collapse remainder into policy groups

PROCESS-NAME support varies across distributions; validate before relying on desktop-only matchers in mobile forks.

no-resolve hints, fake-ip interactions, metadata traps

DNS resolution interleaves with rule evaluation modes. Fake IP modes short-circuit some hostname visibility until connection establishment, reshaping whether DOMAIN matchers fire when you expect them. Annotate IP-only rules so they behave deterministically when host information is ephemeral.

rules:
  - IP-CIDR,203.0.113.0/24,DIRECT,no-resolve
  - DOMAIN-SUFFIX,research.cdn,DIRECT

Use logging deliberately. Mihomo-derived cores expose verbosity toggles inside GUIs—raise them briefly when debugging unexpected DIRECT paths, then return to quieter defaults because verbose tracing on rotating logs fills disks on laptops.

Common pitfalls practitioners still trip over

Newcomers routinely duplicate FINAL rows or rely on mythical “automatic deduplication” that never arrives. Maintain exactly one terminating MATCH stanza referencing a policy group engineered for resilience, otherwise your editor might silently append provider fragments that drag duplicate catch-alls midway through evaluation. Likewise, chaining multiple GEOIP clauses without inspecting surrounding DNS settings creates apparent flakiness: the tuple might already be domestic while the HTTPS SNI hints something else entirely; log both tuple and sniffed hostname when diagnosing.

Another repeatable mistake is cramming contradictory DOMAIN-KEYWORD entries without negative lookahead safeguards. Telemetry vendors rotate subdomains aggressively; trimming noise with iterative RULE-SET updates beats bloated keyword ladders that snag innocent hosts inside university research networks.

How to iterate without outages

  1. Snapshot working config.yaml before rewriting entire rule headers.
  2. Introduce RULE-SET sources one at a time; validate fetch failures do not cripple reload.
  3. Exercise representative domains via curl (curl -I https://provider.test) through mixed ports or TUN to confirm path.
  4. Compare latency deltas when shifting GEOIP order; reorder if domestic traffic accidentally hairpins offshore.
  5. Document intent in brief English comments—which your engine preserves—because future merges from airport profiles will bury implicit rationale.

Frequently asked questions

Can RULE-SET fully replace handwritten DOMAIN rows?
Often yes for volatile lists curated upstream, yet keep surgical DOMAIN exemptions local so you react faster than provider refresh loops when a CDN breaks.
Why do two seemingly identical setups diverge?
MMDB vintages differ, RULE-SET download failures silently skip rows until retry, latency-based groups auto-switch nodes mid-flow, DNS modes diverge—all worth diffing systematically.
Should FINAL always be MATCH?
Semantics depend on wording in your distro; historically MATCH is the terminal wildcard. Prefer pointing it toward a resilient policy group combining url-test selectors rather than pinning to a brittle single server entry.

Why expressive rules still favor Clash-class cores

Many legacy VPN wrappers still reduce routing to coarse kill switches baked into proprietary XML. Operators waste hours toggling globally off just to unblock a stubborn accounting portal trapped behind regional fraud checks. Transparent SOCKS injectors lacking structured YAML force brittle shell scripts glued to iptables arcs nobody wants to babysit overnight.

Clash’s ordered rule vocabulary—DOMAIN matchers for precision, GEOIP for regional scaffolding, RULE-SET for maintainable communal lists—gives you a single readable document that survives Git merges, survives provider churn, and maps cleanly onto strategy groups you already understand. If you are hunting a maintained distribution that keeps Mihomo protocol breadth while exposing these primitives through a modern GUI, Clash from this project keeps downloads verified and documentation aligned with the behaviors above so you spend time tuning policy, not decoding mystery binaries.

The workflow stays grounded: download the client you trust, import the subscription you already pay for, then paste or sync the rule layers that reflect how you actually use the internet—not how a one-size vendor imagines it.

Download Clash for your platform and apply these routing patterns →