Clash DNS Configuration: nameserver, fallback, and DNS Hijacking
Learn how Clash DNS settings work, including nameserver, fallback, fallback-filter, and dns-hijack. Compare fake-ip and redir-host, then troubleshoot common DNS issues.
First, distinguish DNS resolution, DNS interception, and proxy routing
Clash DNS configuration involves three separate questions: which resolver handles a domain, how an app's DNS requests reach the core, and which route a connection ultimately takes. nameserver selects upstream resolvers, tun.dns-hijack captures eligible DNS traffic, and rules determine the route for application connections. These layers are related, but they are not interchangeable.
This guide focuses on clients using the mihomo core. Older Clash versions, different forks, and client-side configuration generators may support different fields. A client's “DNS override” may also replace the entire dns section from your subscription. When troubleshooting, inspect the final configuration generated by the client and passed to the core—not just the subscription editor.
- Core DNS: The core provides DNS resolution using this section only when
dns.enableis enabled. - System DNS: The resolver currently used by the operating system. Enabling the system HTTP proxy alone does not mean all DNS requests go through the core.
- Proxy rules: The matching domain or IP rule determines whether traffic goes direct or through a proxy. Using a DNS resolver in a particular region does not select a proxy node in that region.
- App-level DNS: Browser Secure DNS and built-in app DoH can bypass the system's traditional DNS settings.
Here, “DNS hijacking” means redirecting specified DNS traffic to the local core. It does not mean an ISP tampered with DNS results. Verify that interception is working by checking queries and connection logs.
nameserver and default-nameserver: application lookups and bootstrap DNS
Start with a DNS listener you can test independently
The following DNS snippet is intended to be merged into an existing mihomo configuration; it is not a complete configuration with proxies and rules. The listener is restricted to localhost and uses port 1053 to avoid competing directly with the system's 53 port. The system will not use it automatically, so we'll test it with an explicit query first.
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
nameserver is the list of upstream resolvers for regular domain lookups. It can include traditional DNS addresses, DoH (DNS over HTTPS), or other protocols supported by the core. Listing two addresses does not establish a strict primary-and-backup order, so don't rely on list order for failover behavior.
default-nameserver is mainly used to resolve the hostnames of DNS upstreams. For example, before connecting to https://dns.alidns.com/dns-query, the core needs the IP address for dns.alidns.com. Specifying bootstrap resolvers as IP addresses avoids a circular dependency in which resolving a DNS server's hostname depends on that same server.
Check node hostname resolution and DNS egress separately
mihomo's proxy-server-nameserver can be used specifically to resolve proxy server hostnames. If a node's address cannot be resolved, normal DNS for application domains won't help establish a proxy connection. When respect-rules makes DNS upstream connections follow routing rules, configure node hostname resolution carefully to avoid a circular dependency where the resolver relies on the proxy and the proxy relies on that same resolver.
Don't add every advanced field at once while troubleshooting. First verify that the selected DoH endpoint can connect on your current network, then add settings such as rule-based routing. DoH typically uses TCP port 443, but using HTTPS does not automatically mean the connection goes through a proxy. The actual route depends on the core configuration and routing conditions.
fallback and fallback-filter: result selection, not a timeout backup
It's easy to mistake fallback for a backup list used only when the primary DNS times out. In practice, the core queries nameserver and fallback and uses fallback-filter to decide which results to accept. It is neither a backup proxy group nor a way to ensure a domain goes through a proxy.
The snippet below shows explicit filtering conditions. Merge it into the dns section above; do not add a second top-level section with the same name. The example disables GeoIP filtering and uses a documentation-only network range plus a specific domain to illustrate how the checks work. These ranges are not a complete list of unusual addresses.
fallback:
- https://cloudflare-dns.com/dns-query
fallback-filter:
geoip: false
ipcidr:
- 0.0.0.0/8
- 192.0.2.0/24
- 198.51.100.0/24
- 203.0.113.0/24
domain:
- '+.github.com'
| Field | What it checks | How it works |
|---|---|---|
geoip | IP geolocation of regular DNS results | Enables the GeoIP condition; requires usable geolocation data. |
geoip-code | GeoIP country or region code | When GeoIP is enabled, regular results that don't match the specified region trigger the use of fallback results. |
ipcidr | IP addresses returned by regular DNS | If a result falls within a listed range, use the fallback result. |
domain | Queried domain | Matching domains use the result from the fallback resolver directly. |
Using geoip: true with geoip-code: CN does not mean “send sites in mainland China direct.” It checks whether the resolved IP's geolocation makes the result eligible for use. CDN addresses, geolocation data updates, and your network egress can all affect the result; proxy egress is still determined by rules. To use a specific resolver for a particular domain, nameserver-policy is usually clearer than stacking geolocation filters.
Your fallback upstream must also be reachable. If it times out on your current network, forcing certain domains to use it will only widen the outage. Verify the upstream separately before enabling filters.
fake-ip and redir-host: virtual addresses or real IPs
fake-ip preserves domain information through address mappings
In fake-ip mode, the core can return a virtual IPv4 address from the 198.18.0.0/16 range and maintain a mapping between the domain and that address. When the app connects to the address, the traffic must pass through the same core so it can recover the domain, match rules, and establish a real connection. This range is reserved for network testing; it is not a public website address.
So, getting a 198.18.x.x address does not mean your DNS is poisoned. The issue to investigate is whether DNS reaches the core but the subsequent connection takes the normal network route, or whether the system still has an old virtual address cached after switching clients or clearing mappings. Capturing DNS without capturing the subsequent connection is a common reason fake-ip traffic fails.
redir-host returns real IPs, but connections still need to be intercepted correctly
In redir-host mode, the core typically returns the real IP from the upstream resolver, so apps don't need to connect to a virtual address. This can improve compatibility with programs that depend on real IPs, but the association between a domain and its connection can be affected by caching and shared IPs. The mode's name does not mean you must enable Linux REDIRECT firewall rules, nor does it automatically provide transparent proxying.
- When using TUN and preserving domain information for rule matching, try
fake-ipfirst. - If local network discovery, a specific device, or a game has compatibility issues, identify the domain involved before considering
fake-ip-filter. - With the default blacklist filter mode, domains added to
fake-ip-filterno longer receive virtual addresses. Check your current mihomo configuration for the meaning of other filter modes. - After switching enhanced modes, restart affected apps and clear DNS caches to avoid stale results from the previous mode.
dns.ipv6: false controls how core DNS handles AAAA queries; it does not disable all IPv6 connections on the system. A browser using its own DoH or an app with a cached IPv6 address may still connect over another path.
tun.dns-hijack: what intercepting port 53 does—and doesn't—cover
dns-hijack belongs inside the tun section, not the dns section. The following is a common mihomo TUN snippet; it changes routing, so prepare console access or another recovery method before applying it to a remote server. Desktop clients usually manage TUN permissions through service mode or a privileged helper. Don't start a second core unless you know where the required permissions come from.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
any:53 matches UDP DNS traffic on port 53 entering TUN, while tcp://any:53 covers TCP port 53. These are not switches for scanning or intercepting an entire network: traffic must pass through TUN before the core can handle it. Route exclusions, operating system behavior, and local loopback resolvers can all keep some requests off this path.
- DoH: Usually uses HTTPS on port
443; configuringany:53does not route it through core DNS. - DoT: Usually uses TLS on port
853, outside the scope of traditional port 53 interception. - Local DNS on Ubuntu:
127.0.0.53is commonly the local stub address for systemd-resolved. Seeing it does not by itself mean DNS interception failed. - LAN devices: Enabling TUN on this machine does not automatically intercept DNS from your router or other devices. Gateway setups require additional forwarding and firewall configuration.
Don't change the listener to 0.0.0.0:53 and expose it to the internet to fix a local DNS issue. If you need to serve your LAN, restrict access to permitted subnets and check both UDP and TCP firewall rules.
Ubuntu troubleshooting order: listener, query, interception, route
Step 1: Check the active configuration and listening process
For a command-line deployment, test the actual configuration directory. The path below uses /etc/mihomo/config.yaml as an example. With a desktop client, inspect its active runtime configuration instead of assuming this path is where it stores files.
mihomo -t -d /etc/mihomo -f /etc/mihomo/config.yaml
sudo ss -lntup 'sport = :1053'
resolvectl status
Configuration tests can catch syntax and configuration errors, but they don't prove that upstream servers are reachable. Use ss to confirm the correct process is listening on 1053. If the address is already in use, identify the other DNS service first; don't stop the system resolver blindly.
Step 2: Bypass the system resolver and test the core directly
On Ubuntu, dig is provided by the dnsutils package. Start with a query to an explicit address to distinguish a failure in core DNS from a system request that never reaches the core.
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
dig @127.0.0.1 -p 1053 example.com AAAA
Check the response status, answer records, and whether the query times out. In fake-ip mode, an A query may only confirm that the core can assign a virtual address; it does not prove the real upstream lookup succeeded. Verify with an actual connection and the logs as well. If dns.ipv6: false is set, an AAAA query returning no address is not necessarily a failure.
Step 3: Verify the system resolver and application connections
resolvectl query example.com
curl -I --connect-timeout 10 https://example.com
curl -I --connect-timeout 10 --proxy http://127.0.0.1:7890 https://example.com
The final command assumes the existing mixed-port is 7890 and establishes an HTTPS tunnel through an explicitly configured HTTP proxy; it cannot prove that system DNS is being intercepted. The second command may also be affected by proxy environment variables, so check your terminal environment before comparing results. If the explicit proxy works but regular apps don't, check which traffic the system proxy covers, TUN routes, and app-level DNS.
Step 4: Clear caches and roll back changes one at a time
sudo resolvectl flush-caches
After clearing the systemd-resolved cache, quit and reopen the browser; its DNS cache and existing connection pool may persist independently of the system cache. Temporarily increase the core's log level and look for DNS timeouts, node hostname resolution failures, and rule matches, then restore the original log level. Logs may contain visited domains; remove subscription URLs, credentials, and personal browsing records before sharing them.
Common symptoms and the minimal-change approach
| Symptom | Check first | Next step |
|---|---|---|
| Explicit query to port 1053 times out | Listener address, port conflicts, whether the core is running | Check ss and runtime logs first, then verify upstream connectivity. |
| A 198.18 address is returned, but connections fail | fake-ip traffic routing and address mappings | Check TUN routes, clear the cache, and reconnect. |
| Only a specific domain fails | fallback-filter, nameserver-policy, and domain rules | Temporarily remove the domain-specific policy and compare the logs. |
| Nodes are listed, but none can connect | Node hostname resolution and node reachability | Check proxy-server-nameserver and node connection errors. |
| Only the browser behaves differently | Secure DNS, proxy extensions, and browser cache | Temporarily use the same resolution path throughout, restart the browser, and test again. |
| Issue returns after subscription updates | Client overrides and generated configuration | Use the client's supported persistent override mechanism for changes. |
A reliable sequence is to make one DNS listener queryable, verify one upstream is reachable, confirm system requests and application connections reach the core, and only then add fallback, per-domain resolver policies, and TUN interception rules. Change one variable per round and record the query results before and after. This makes it possible to tell whether the problem is DNS resolution, routing, or a node issue—instead of attributing every failure to “DNS poisoning.”
For the bigger picture on ports, proxy groups, and rules, see the Getting Started Guide. To check configuration fields, refer to the Protocol Reference. Merge the DNS and TUN snippets in this guide into your existing configuration, keeping your current proxies and rules. Don't overwrite the entire subscription configuration.