Where the DNS Module Fits in Clash
Clash's routing rules fall into two categories: domain-based matching (DOMAIN, DOMAIN-SUFFIX, DOMAIN-KEYWORD) and IP-based matching (IP-CIDR, GEOIP). IP-based rules can't decide anything until a domain has been resolved to an address, so Clash ships a full DNS resolution module instead of handing resolution back to the OS. Domain rules can match as soon as a connection comes in, while IP rules depend on what the DNS module resolves — together they decide which policy group a connection ends up in.
The system's default DNS is usually a plaintext UDP port 53 service handed out by your ISP, where every query is visible in transit and can be rewritten by anything in between. Once Clash takes over DNS, you get to pin down exactly which path a query takes, which protocol it uses, and whose answer gets trusted — that's the whole premise behind fields like nameserver, fallback, and enhanced-mode.
The master switch for the dns block is enable; listen sets the address and port Clash answers queries on, commonly 0.0.0.0:53. When a desktop client turns on system proxy or TUN mode, it usually points the system's DNS at this listen address automatically, and other devices on the LAN can also be pointed here manually so every query funnels through one place.
nameserver: The Primary Upstream and Its Formats
nameserver is Clash's primary resolution chain. Each entry in the list can take one of three forms:
- A plain IP, such as
223.5.5.5, using traditional plaintext UDP on port 53 — the lowest latency option; tls://1.1.1.1:853, DNS over TLS, where queries run over the encrypted port 853;https://doh.pub/dns-query, DNS over HTTPS, where queries are wrapped inside an HTTPS request.
The list works as a race, not a primary/backup pair: Clash fires queries at every upstream in the list simultaneously and takes whichever answer comes back first. That means 2-3 low-latency upstreams in nameserver is plenty — piling on more entries won't improve reliability, it just multiplies outbound traffic.
Paired with nameserver is default-nameserver, the bootstrap resolver for the whole chain. DoH and DoT upstreams are themselves given as domain names, and you can't rely on those same upstreams to resolve their own hostnames — that would create a circular dependency. default-nameserver must be a plain IP reachable directly over UDP, such as 223.5.5.5 or 119.29.29.29. It's only used at startup and isn't touched by everyday queries.
default-nameserver Takes Plain IPs Only
Don't put https:// or tls:// entries into default-nameserver. It's the starting point of the whole DNS chain, whose job is to resolve the hostnames of your DoH and DoT servers — so it can't itself depend on any encrypted upstream.
fallback and fallback-filter: How the Backup Result Gets Decided
The most common misreading of fallback is "it kicks in only when the primary upstream is down." What actually happens: once fallback is configured, Clash queries both the nameserver group and the fallback group for the same domain at the same time, then uses fallback-filter's rules to decide which answer to trust. fallback is a result-filtering mechanism, not a failover mechanism.
The default filter condition is geoip: true plus geoip-code: CN: if the IP returned by nameserver geolocates to mainland China, that result is used; otherwise the fallback result is used instead. The intent is straightforward — domestic domains trust the fast local upstream, while domains resolving outside mainland China are only trusted when the answer came through an encrypted, outbound upstream.
fallback-filter also supports two extra conditions: ipcidr lists untrusted ranges — if the returned IP falls into one of them (say, a reserved block like 240.0.0.0/4), the result is treated as tampered and fallback is forced; domain lists domains that should always use the fallback result, useful for specific targets you've confirmed get poisoned.
One prerequisite can't be skipped: every fallback upstream must use DoH or DoT. If a fallback entry is a plaintext UDP address, queries for domains outside mainland China still leave the network in the clear, the same hijacking and poisoning issues persist, and fallback ends up doing nothing.
enhanced-mode: The Fork Between fake-ip and redir-host
enhanced-mode decides how Clash answers the DNS requests apps make, and its two values correspond to two different approaches.
redir-host is the classic mode: when Clash receives a connection to a hostname, it resolves the real address first, then forwards based on that IP. It's intuitive and the most compatible option, but the tradeoff is that real DNS queries do get made locally, and those queries are exposed to hijacking or logging while in transit.
fake-ip is the recommended default: for domains that need resolving, Clash hands back a fake address from the fake-ip-range block (198.18.0.1/16 by default). When the app connects to that fake address, Clash looks up the real domain behind it and routes by domain rule, pushing the actual resolution to the proxy exit side. Almost no real domain query leaves your machine, so there's nothing left in plaintext for a hijacker to rewrite, and you save a round trip of latency too.
fake-ip-filter lists domains that should never get a fake address. LAN hostnames (*.lan, *.local), NTP time sync, and STUN-based hole punching all need real IPs to work — handing them a fake one breaks them outright, so these entries need to stay on the filter list. fake-ip can also clash with shared LAN proxies and some P2P/multiplayer setups; if something breaks, switching back to redir-host is an easy way to compare the two modes.
dns Block Field Reference
| Field | Purpose | Common Values |
|---|---|---|
enable | Master switch for the DNS module | true |
listen | Listen address and port for answering queries | 0.0.0.0:53 |
ipv6 | Whether to return AAAA records | false |
enhanced-mode | Response mode | fake-ip / redir-host |
fake-ip-range | Fake address allocation range | 198.18.0.1/16 |
fake-ip-filter | Domains excluded from fake addresses | *.lan, *.local, etc. |
default-nameserver | Bootstrap resolver for upstream hostnames | 223.5.5.5 |
nameserver | Primary upstreams, raced concurrently | DoH / DoT / plain IP |
fallback | Backup upstreams, trusted per filter rules | DoH / DoT |
fallback-filter | Conditions for trusting a result | geoip、ipcidr、domain |
How DNS Hijacking Works, and How to Configure Around It
The typical hijacking mechanism: when a plaintext UDP port 53 query passes through an ISP gateway, the gateway races to return a forged answer before the real upstream replies, pointing the domain at the wrong IP. Symptoms include a normal site landing on an unrelated page, or the same domain resolving to wildly different results depending on the network. Hijacking targets two specific traits — plaintext and port 53 — and the countermeasures are built around exactly those two points.
All four of the following need to hold true for the anti-hijacking setup to actually close the loop:
- nameserver and fallback both use DoH or DoT exclusively, so query content is encrypted and nothing in between can read or rewrite it.
- enhanced-mode is set to fake-ip, so no real resolution is made locally for domains routed through the proxy, further shrinking the attack surface.
- System DNS points at Clash's listen address, or TUN mode is enabled to capture all traffic, so every query funnels through Clash internally.
- fallback-filter keeps its geoip check, so results for domains outside mainland China only ever come from an encrypted upstream, while domestic results come from a fast local one.
Verifying the Configuration Works
Bump the client's log level to debug and watch the dns-related output; then run dig @127.0.0.1 domain against both a domestic and a non-domestic domain and check whether the returned IPs match what you expect for that routing — domestic domains should return results close to your ISP, while proxied domains should return an address in the 198.18 range under fake-ip.
A Complete, Ready-to-Use Example
The dns block below strings the fields covered above into one usable template, matching line-for-line with the explanations above — just swap in your preferred upstream addresses:
dns:
enable: true
listen: 0.0.0.0:53
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "*.local"
- "localhost.ptlogin2.qq.com"
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://doh.pub/dns-query
- https://dns.alidns.com/dns-query
fallback:
- https://dns.google/dns-query
- tls://1.1.1.1:853
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
domain:
- "+.example.com"
Key points recap: the two plain IPs in default-nameserver handle bootstrapping; the two domestic DoH entries in nameserver race concurrently; the two encrypted entries in fallback handle domains outside mainland China; fallback-filter uses geoip-code CN as the trust boundary, ipcidr blocks poisoned results in reserved ranges, and the domain list can be trimmed or extended for specific cases. Entries in fake-ip-filter should be filled in based on your actual LAN setup — if a particular service starts acting up, check there first for a missing filter entry.
What's Improved in mihomo (Clash Meta)
The mihomo core is fully compatible with all the fields above, so an existing dns config can be carried over as-is. On top of that, it adds a few more granular fields worth migrating to gradually:
nameserver-policy: assigns upstreams by domain suffix rule, which is far more granular than fallback's binary check — you can pin a specific group of domains to a dedicated DoH upstream and run multiple resolution chains side by side;proxy-server-nameserver: dedicated to resolving the hostnames of your proxy nodes, so poisoning of a node's hostname can't take down the whole group;direct-nameserver: assigns a separate resolution chain for direct traffic, decoupled from proxied domains;respect-rules: makes DNS queries themselves follow routing rules for their outbound path, so DoH requests to upstreams outside mainland China go out through the proxy too, further cutting the odds of interference.
Migration tip: for new mihomo configs, express your routing intent with nameserver-policy first and keep fallback as the safety net; existing configs don't need an urgent rewrite — confirm fallback-filter is behaving as expected first, then migrate field by field.
Download the Client and Set Up DNS
The dns block syntax is shared across Clash clients. Grab a client for your platform from the download hub first, then adjust nameserver, fallback, and enhanced-mode following this guide.