mihomo vs Classic Clash Core: Rule Syntax, DNS & TUN Differences
Compare mihomo (Clash Meta) and the classic Clash core: new protocol support, rule-set and GeoSite usage, DNS split strategies, TUN mode, and migration tips.
Compare mihomo (Clash Meta) and the classic Clash core: new protocol support, rule-set and GeoSite usage, DNS split strategies, TUN mode, and migration tips.
Clash's original core repository was maintained by the original author, with fairly conservative protocol support and rule syntax that stayed on a stable but limited version for a long time. The community forked it as Clash Meta, continuously adding new protocols, new rule types, and more complete DNS/TUN implementations. It was later renamed mihomo and became the de facto community mainline. Today most clients (including the majority of Windows, macOS, and Android versions listed on this site) already use mihomo as the default or optional core, while updates to the classic core have slowed noticeably.
Understanding the differences between the two helps a lot when figuring out "why doesn't this rule take effect," "why can't this protocol connect," or "why does the config throw errors after moving to a new client" — most of these root causes trace back to core differences, not to mistakes in the config file itself.
The classic core's supported protocol set is essentially fixed at early mainstream options like Shadowsocks, ShadowsocksR, VMess, Trojan, and Snell. mihomo adds the following on top of that:
If a subscription node contains fields like vless, hysteria2, or tuic, and the client reports the node type as unsupported, it's usually still running the classic core — switching to a mihomo-based client version resolves this without needing a new subscription or regenerated nodes.
The classic core's rule types are limited to DOMAIN, DOMAIN-SUFFIX, DOMAIN-KEYWORD, IP-CIDR, and the built-in GEOIP. Rule sets need to be written into the config as full lists or maintained as separate rule files, which raises maintenance costs. mihomo introduces finer-grained rule types and a more efficient rule-set mechanism:
rule-providers:
reject:
type: http
behavior: domain
url: "https://example-ruleset/reject.txt"
path: ./ruleset/reject.yaml
interval: 86400
rules:
- RULE-SET,reject,REJECT
- GEOSITE,category-ads-all,REJECT
- GEOSITE,cn,DIRECT
- GEOIP,CN,DIRECT
- MATCH,PROXY
rule-providers supports periodic remote fetching with local caching, and GEOSITE rules reference precompiled domain-category lists (such as category-ads-all, cn) directly, so there's no need to list domains by hand. This syntax isn't recognized by the classic core — if a config uses rule-providers or GEOSITE but runs on the classic core, it will throw a syntax error or simply not take effect, which is the first thing to check when troubleshooting rule failures.
The classic core's DNS module is fairly basic, usually allowing only one group of upstream servers, making fine-grained splitting by target domain difficult. This often leads to problems like "domestic domains routed through overseas DNS causing slower access" or "DNS leaking the real geographic origin." mihomo's DNS module supports policy-based grouping:
dns:
enable: true
enhanced-mode: fake-ip
nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver-policy:
"geosite:cn": [223.5.5.5, 119.29.29.29]
"geosite:geolocation-!cn": [https://1.1.1.1/dns-query]
fake-ip-filter:
- "*.lan"
- "+.local"
nameserver-policy can assign different resolvers by GeoSite category — domains inside mainland China use domestic DNS, while domains outside use encrypted DNS, cutting unnecessary detours at the source. enhanced-mode has also grown from the classic core's simpler implementation into a more stable fake-ip mode, which works better alongside TUN.
When migrating a config from the classic core to mihomo, old DNS fields (such as the simple dns.fallback list used by some earlier versions) should be rewritten in the new syntax rather than copied as-is, otherwise they may simply not error out while quietly doing nothing.
TUN mode lets Clash take over system-wide traffic through a virtual network adapter, without relying on application-layer system proxy settings — this matters a lot for programs that don't support proxy protocols (games, some command-line tools). The classic core's TUN implementation arrived late, with fewer config options and limited platform support; early on it mainly worked on Linux, with incomplete Windows/macOS support.
mihomo's TUN module rewrote the network stack handling logic, with a typical config like this:
tun:
enable: true
stack: system
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
stack can be set to different network stack implementations such as system or gvisor, balancing compatibility and performance; auto-route and auto-detect-interface automatically configure the routing table and detect the exit interface, cutting down manual route setup. TUN entry points (also called virtual adapter / VPN mode) in current Windows, macOS, and Android clients are almost all built on top of the mihomo core — a key reason to prefer mihomo when choosing a core version.
Migrating a classic-core config file to mihomo usually works out of the box, since mihomo maintains backward compatibility with the classic syntax. Still, a few points are worth checking:
MATCH or FINAL last as a catch-all, and this rule must stay last in mihomo too, otherwise later rules get ignored;type field gains new options in mihomo such as smart and load-balance — if these unrecognized new types are mistakenly written into a classic-core config, it will fail to start;Overall, mihomo is already the default choice for most clients today. New protocols, finer rule syntax, category-based DNS policies, and a more complete TUN implementation are gaps the classic core is unlikely to close anytime soon. Unless there's a specific compatibility need, everyday use is best served by a client version built on the mihomo core, adjusting configs to the new syntax gradually rather than forcing old conventions to stick.