Advanced Setup 12 min read

Clash DNS Configuration: nameserver, fallback, and DNS Hijacking Explained

Learn how mihomo DNS settings work, including enhanced-mode, nameserver, fallback, fallback-filter, and dns-hijack, with YAML examples for filtering and split DNS.

Identify the core and DNS traffic entry point first

The key is to send DNS queries to Clash DNS before choosing which upstream resolver to use. Changing nameserver alone does not automatically route all DNS traffic from your system, browser, or local network devices through Clash. A website loading successfully does not prove that queries used these settings: system caches, browser Secure DNS, or an app's own resolver may bypass them.

A Clash client is the interface; the core is what parses the YAML. The original Clash, the legacy Premium core, and Clash Meta (now mihomo) do not support exactly the same fields. The examples in this article target the mihomo core. Do not apply proxy-server-nameserver or TUN settings directly to older cores. Check the core name and version in the client's About page or startup logs, then validate the configuration against that core.

  1. Back up the current configuration and note the existing dns, tun, and client-side DNS override settings.
  2. Under Profiles, confirm which configuration file is active. If the client supports subscription overrides, edit the persistent override rather than a temporary file that will be replaced at the next subscription update.
  3. Inspect the runtime configuration or export the merged configuration to make sure the client's DNS settings are not overriding the YAML.
  4. Change one set of settings at a time. Reload, check startup errors and DNS logs, then move on to the next change.

The dns section: choosing a listener address and resolution mode

FieldPurposeConfiguration notes
enableEnable the core DNS serviceSetting it to true still requires a way to route queries to it
listenAddress where the DNS service listensFor local testing, use 127.0.0.1:1053
enhanced-modeChoose an enhanced DNS modeCommon values: fake-ip and redir-host
fake-ip-rangeVirtual IPv4 address poolExample: 198.18.0.1/16
default-nameserverResolves hostnames used by DNS upstreamsUse resolver IP addresses to avoid bootstrap dependency loops
nameserverDefault set of DNS upstreamsNot a proxy-node list or a strict primary/backup queue

A fake IP is an expected response, not a DNS failure

fake-ip assigns a virtual address to each domain and stores the mapping between the domain and address. When an app connects to that address, the core can recover the domain and apply the matching rules. A response such as 198.18.x.x is usually expected. Do not compare it directly with a public DNS resolver's real IP, or assume the setup has failed because the address does not respond to ping.

With redir-host, DNS returns real addresses. This can improve compatibility with apps that rely on real IPs, but requires more attention to DNS poisoning and preserving domain information. Neither mode determines whether traffic uses the proxy; the DNS mode maps domains to addresses, while rules determine where connections go.

listen is not a system DNS setting

127.0.0.1:1053 provides a DNS service on a non-standard port on this device only. Most system DNS settings accept only an IP address and use port 53 by default, so they cannot be pointed directly at this address and port. First, use a DNS query tool to test port 1053, then configure TUN hijacking. Do not change the listener to 0.0.0.0:53 just to make it accessible from other devices. That exposes it on all interfaces and requires checking for port conflicts, firewall rules, and LAN access boundaries.

nameserver: start with a minimal upstream configuration

Here is an example mihomo dns section. It is not a complete proxy configuration and does not include subscriptions, proxy groups, or rules. When merging it into an existing configuration, keep a single top-level dns: key; do not append a second section with the same key at the end of the file.

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

Here, default-nameserver resolves hostnames for upstreams such as dns.alidns.com and doh.pub; routine DNS queries are handled by nameserver. DoH uses HTTPS, typically over port 443, but encryption does not guarantee that a service will always be reachable or that its answers will work with every proxy exit.

  • Do not assume the list means “try the second server only if the first fails.” The core may query servers concurrently or use its own selection strategy, so list order is not a reliable primary/backup priority.
  • Do not add a dozen upstreams at once. Start with one or two reachable services. If something fails, it will be easier to identify which endpoint is timing out.
  • Be aware of what IPv6 is disabled here: dns.ipv6: false makes DNS return an empty answer for AAAA queries. It does not disable IPv6 on the system or prevent apps from connecting to known IPv6 addresses.

If the proxy server itself is identified by a hostname, mihomo also supports dns.proxy-server-nameserver to resolve node server hostnames. It is not an upstream dedicated to resolving websites accessed through the proxy. If a node hostname fails to resolve, first check that this step works independently and avoid a circular dependency where you need the proxy to resolve the proxy server.

fallback and fallback-filter: not a timeout backup switch

The name fallback can be misleading. It works with fallback-filter to filter DNS answers; it does not simply wait for nameserver to time out before being used. With both upstream sets configured, queries may be sent to both. Which answers are accepted depends on the filter conditions and the core's implementation.

Add the following snippet to the existing dns section, at the same level as nameserver. GeoIP checks are disabled here to avoid relying on an unverified regional database. The example shows explicit domain matching and filtering for suspicious addresses.

  fallback:
    - https://cloudflare-dns.com/dns-query
  fallback-filter:
    geoip: false
    ipcidr:
      - 0.0.0.0/32
      - 127.0.0.0/8
    domain:
      - '+.google.com'
      - '+.github.com'

What each of the three filter types does

  • domain: use the fallback answer for specified domains. In this example, +.github.com matches the domain and its subdomains; it does not make the website use the proxy automatically.
  • ipcidr: use the fallback answer when a regular upstream returns an address in one of these ranges. This example treats unspecified and loopback addresses as suspicious. Do not copy this filter if an internal domain is supposed to resolve to a loopback address.
  • geoip and geoip-code: when GeoIP checks are enabled, use the expected region to decide whether to replace a regular upstream's answer. A common setup is geoip: true and geoip-code: CN, but this depends on a GeoIP database, and an overseas CDN address is not inherently evidence of DNS poisoning.

If you need certain domains to always use a specific DNS resolver, consider nameserver-policy first instead of stacking complex fallback filters. It selects the DNS upstream; connection rules still determine the proxy exit.

  nameserver-policy:
    '+.cn':
      - https://dns.alidns.com/dns-query
    '+.github.com':
      - https://cloudflare-dns.com/dns-query

This snippet also belongs inside dns. Queries matched by the policy use the specified upstream; do not assume the default fallback filtering logic applies to them. While setting things up, test either policy-based resolution or fallback filtering first. Combine them only after the logs and results are consistent.

dns-hijack: capture port 53 queries in TUN

In mihomo, dns-hijack belongs in the top-level tun section, not dns. It sends DNS traffic that enters TUN and matches the configured conditions to the core's DNS module. Use the example below with your existing TUN settings. If the client manages TUN through its interface, check the final runtime configuration to make sure the UI has not overwritten the YAML.

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53

any:53 matches UDP queries on port 53; tcp://any:53 adds TCP on port 53. Enabling TUN usually requires administrator privileges or the client's service mode. If your configuration already has a tun: section, edit its fields rather than declaring the section again.

Writing any:53 does not automatically capture these requests

  • Browser DoH: It usually uses HTTPS over port 443, so it does not match port 53. To troubleshoot, temporarily turn off the browser's Secure DNS setting. In Firefox, it is typically under Settings → Privacy & Security → DNS over HTTPS. Restore it after testing if needed.
  • Android Private DNS: Strict mode usually uses DoT on port 853. On some devices, find it under Settings → Network & internet → Private DNS. Menu names vary by manufacturer, and this traffic should not be treated as ordinary UDP on port 53.
  • Traffic that never enters TUN: Direct routes to the LAN, another VPN, special network interfaces, or system-level routing can all bypass TUN. Even if the system DNS points to your router, verify that this traffic is actually being captured.

A working listener, an active TUN, and effective DNS hijacking are three separate things. On phones, check VpnService permissions and conflicts with other VPNs. On desktop systems, check service permissions, routes, and firewall rules. Repeatedly switching resolvers will not fix a problem with the traffic entry point.

Troubleshooting sequence: validate the config, query the listener, then test system DNS

Step 1: Check the YAML and startup logs

If mihomo is available locally, run the following commands from the directory containing the configuration. Client users can also use the configuration checker in the app. A successful command only confirms that the configuration parses; it does not prove that an upstream is reachable.

mihomo -t -f config.yaml

If you see an unknown field, check that you are using the right core. For indentation or duplicate-key errors, fix the file first. If the logs show address already in use, find the process using port 1053 or choose another test port. Changing the upstream URL will not fix a listener port conflict.

Step 2: Query the local port 1053 directly

On macOS or Linux with dig installed, run these three commands. The first tests UDP, the second tests TCP, and the third checks AAAA query behavior.

dig @127.0.0.1 -p 1053 www.example.com A
dig @127.0.0.1 -p 1053 www.example.com A +tcp
dig @127.0.0.1 -p 1053 www.example.com AAAA

On Windows, use nslookup in interactive mode and set the test port. Enter exit when you are done.

nslookup
server 127.0.0.1
set port=1053
set type=A
www.example.com
exit

In fake-ip mode, it is normal for an A query to return a virtual address. To check the real upstream answer, back up your settings, temporarily switch to redir-host, reload the configuration, clear the relevant caches, and compare the query results. Restore your original settings afterward. Do not treat fake-ip response time as the network latency to the real upstream.

Step 3: Test the system's default DNS path

Once local queries succeed, enable TUN and query through the system's default resolver while watching the client logs. On Windows, run ipconfig /flushdns to clear the system DNS cache. On Linux with systemd-resolved, run resolvectl flush-caches. Browsers may also keep their own cache and connections, so restart the browser or clear its data separately.

SymptomCheck firstNext step
Local queries to port 1053 time outDNS listener, configuration loading, upstream reachabilityCheck startup logs and retry with a single upstream
Direct queries work, but the browser does notSecure DNS, cache, system DNS pathTemporarily disable browser DoH and compare with a default DNS query
The domain resolves, but the website still times outProxy group, connection rules, destination portCheck the domain, matched rule, and proxy exit in the connection log
Only node hostnames fail to resolveWhether node bootstrap resolution depends on the proxyCheck proxy-server-nameserver and routing dependencies
Settings disappear after a subscription updateConfiguration merging and override precedenceUse the client's persistent override and check the runtime configuration

Everyday DNS setup: keep the resolution path easy to follow

For everyday use, start with a single DNS entry point, a small number of reachable upstreams, and a clearly defined rules mode. Add nameserver-policy when specific domains need a fixed resolver; configure fallback-filter only when you need to filter incorrect answers. For every additional policy layer, be able to explain which domains it affects, how it connects to the upstream, and where to find the logs if it fails.

Encrypted DNS protects queries in transit to the resolver, but it does not hide all connection information. A DNS leak test showing a particular resolver does not reveal the path taken by all app traffic. To check whether traffic bypasses the expected entry point, compare packet captures, DNS logs, and connection records rather than relying on a single website test.

Keep these three roles distinct: nameserver determines where queries go, fallback-filter helps select which DNS answers are accepted, and tun.dns-hijack determines which traditional DNS requests are sent to the core. Testing these layers separately usually pinpoints problems faster than repeatedly replacing the entire configuration with a “one-size-fits-all DNS setup.” For other core fields, see the YAML guide. For connection and startup issues, see Troubleshooting.

Download the latest version of Clash