Start by separating DNS query entry, upstream servers, and response filtering

To troubleshoot Clash DNS, trace the query path: where the app sends the request, whether the core receives it, which upstream it selects, and what response it returns to the app. Changing nameserver alone does not ensure browser queries reach Clash. Enabling TUN does not guarantee that an app's built-in encrypted DNS will be intercepted by a port-based hijack.

This guide uses the mihomo core. Field support and override behavior vary between legacy Clash versions and clients. First check the core information in your client to confirm which core is running, then inspect the effective configuration. A toggle in the client UI is not a substitute for a YAML field.

FieldConfiguration levelWhat it controls
enable / listendnsWhether the built-in DNS is enabled, and the address and port where it accepts queries.
nameserverdnsThe primary upstream used for regular domain lookups.
fallbackdnsUpstreams used for fallback resolution and evaluated by the filtering logic.
fallback-filterdnsWhen to use the fallback result.
dns-hijacktunForward matching DNS traffic on the TUN path to the built-in DNS.

nameserver: the upstream resolvers used by the core

nameserver is the list of primary resolvers for built-in DNS. It can include standard DNS addresses and DoH or DoT endpoints supported by the core. These are resolver services, not proxy nodes; entering a node server address here usually won't produce a usable DNS response.

Start with a minimal, testable configuration

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: redir-host
  nameserver:
    - 223.5.5.5
    - 119.29.29.29

This is a DNS snippet to merge into an existing configuration, not a complete proxy config. 1053 is the test listening port for built-in DNS, separate from the commonly used mixed proxy port 7890. The loopback address is accessible only from the local machine, making it a good starting point for testing the resolution path. To serve DNS to devices on your LAN, also consider the listen address, firewall rules, and access scope.

  • redir-host makes it easier to inspect actual DNS results and works well for initial testing; it does not have to be your long-term mode.
  • ipv6: false simplifies AAAA-record troubleshooting in this example. It does not disable IPv6 in the operating system or block all IPv6 connections.
  • Listing multiple upstreams does not mean they are queried strictly one by one in order, nor does it reveal which one handled any given query.

DoH endpoints may need to be resolved first

If you switch the upstream to https://dns.alidns.com/dns-query, the core first needs to resolve dns.alidns.com. default-nameserver resolves the hostnames of DNS servers. It is used for bootstrap resolution, not as the default resolver list for regular websites. Using an IP address as the bootstrap server avoids depending on a hostname to resolve the server needed to resolve that hostname.

dns:
  enable: true
  listen: 127.0.0.1:1053
  enhanced-mode: redir-host
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  nameserver:
    - https://dns.alidns.com/dns-query

DoH encrypts DNS traffic between the client and that resolver; it does not automatically route every app connection through a proxy. Check upstream reachability, DNS query routing, and the rules applied to website connections separately.

fallback and fallback-filter: fallback is more than a simple failover

Don't think of fallback as a second DNS server that activates only after the first one times out. Once configured, the core can query the primary and fallback upstreams in parallel, then use fallback-filter conditions to choose which result to return. The number of actual queries also depends on caching, resolution strategy, and core implementation.

Filters can match domains or inspect the IP addresses returned by the primary resolver. A matching domain can use the fallback result directly; IP-based conditions determine whether the primary result should be replaced by the fallback result. Neither is a connection-routing rule: using fallback resolution does not mean the website connection will use a proxy.

Use explicit IP conditions before adding geographic checks

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: redir-host
  default-nameserver:
    - 223.5.5.5
  nameserver:
    - https://dns.alidns.com/dns-query
  fallback:
    - https://1.1.1.1/dns-query
    - https://8.8.8.8/dns-query
  fallback-filter:
    geoip: false
    ipcidr:
      - 0.0.0.0/32
      - 127.0.0.0/8

This example explicitly disables GeoIP filtering and uses only two IP ranges as filter conditions: if the primary resolver returns an address in 0.0.0.0/32 or 127.0.0.0/8, the fallback result is used. This is a teaching example, not a comprehensive way to identify every abnormal DNS response. Before deployment, confirm that both fallback DoH services are reachable on your network.

Loopback addresses can also be intentional results for local development, ad blocking, or an organization's internal policies. Don't assume every unusual address is an error, and don't add the entire private address space to the filter and expect internal domains to keep resolving as before.

What geoip and domain control

  • With geoip: true and geoip-code: CN, filtering checks the geographic location of the IP returned by the primary resolver. Results outside the specified region may be replaced by the fallback result. The check uses IP geolocation data, not page content.
  • GeoIP checks depend on the relevant data. Missing or outdated data, or IP geolocation that doesn't match the service's actual location, can all affect results. A geographic match does not prove that a DNS response is correct.
  • domain can list domain patterns that should use fallback, such as +.example.com. Here, example.com is a syntax example; in practice, add only domains with a clear need.
  • fallback-filter does not filter all undesirable content returned by fallback upstreams, and it is not an ad-blocking list.

dns-hijack: send port 53 queries to built-in DNS

After configuring upstreams, verify that app queries actually reach the core. In TUN mode, dns-hijack matches DNS traffic passing through TUN and sends it to built-in DNS for handling. It addresses where queries enter; it does not replace nameserver or fix an unreachable upstream.

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

Merge this snippet at the same level as the earlier dns: section. any:53 matches UDP queries on port 53, while tcp://any:53 adds TCP DNS. Standard DNS uses more than UDP; retries after truncated responses and some app behavior may use TCP.

auto-route automatically configures routes to send traffic through TUN and usually requires the appropriate system permissions. Depending on the platform, the client may start the core through a service mode or an authorization flow. If route creation fails, seeing TUN marked as enabled in the UI is not enough to confirm that traffic is being intercepted.

The platform also affects what can be intercepted. Queries to a local network DNS server, a loopback address, or a specific interface may not follow the expected TUN path. This is especially worth checking when the system uses a router as its DNS server. Verify with actual queries and logs rather than assuming any means every DNS request on the operating system.

Fake-IP and subscription overrides: two common sources of confusion

An address starting with 198.18 is not necessarily a DNS error

With enhanced-mode: fake-ip, the core can return a mapped address to the app, then use the mapping to associate the domain with subsequent connections. A common setting is fake-ip-range: 198.18.0.1/16. If you see an address in this range, first check the current enhanced mode instead of immediately changing fallback.

A Fake-IP response does not mean the core never needs a real DNS lookup; whether it resolves later and which upstream it uses also depend on connection handling and policy. fake-ip-filter controls which domains do not receive Fake-IP responses. It is separate from fallback-filter, which selects between upstream results. For internal apps that need real addresses, first check domain exclusions and the internal DNS path.

Edits to a cached subscription file may be lost on update

Many clients combine subscriptions, local overrides, and UI settings into a runtime configuration. Direct edits to a downloaded subscription file may be overwritten the next time it updates. Keeping multiple DNS configuration sources can also mean the effective value isn't the one you just edited.

  1. Back up the working configuration first, and note the current system proxy and TUN toggle states.
  2. Use a persistent override method supported by your client, and keep DNS changes in one clear source.
  3. Reload the configuration, then inspect the effective dns and tun sections. Check the listening port and indentation level.
  4. Update the subscription once, then check that the override is still in place. Don't test only after the initial import.

Test in order: built-in DNS first, then system interception

Changing upstreams, enabling Fake-IP, and turning on TUN all at once makes it hard to isolate the cause of a failure. First test resolution with redir-host and 127.0.0.1:1053, then restore only the features you need, one at a time. The commands below are diagnostic examples, not test results from this site's network.

Step 1: Check the configuration and query the listening port directly

mihomo -t -f config.yaml

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

The first command requires mihomo to be available locally and points to the configuration file in use. For a core managed by a client, use the client's configuration check instead. The next two commands work on systems with dig installed and test UDP and TCP queries, respectively. Check status, ANSWER SECTION, and the actual response—not just whether the command exits.

On Windows, start nslookup in interactive mode, then specify the port and server. Set the DNS port to 1053; do not point it at an HTTP/SOCKS mixed proxy port.

nslookup
set port=1053
server 127.0.0.1
example.com
exit

Step 2: Compare a direct query with the system's default query

  1. If a direct query to 1053 times out, first check whether the core is running, whether the port is listening, and whether the logs show upstream connection errors.
  2. If the direct query works but nslookup example.com fails without a server specified, focus on system DNS, TUN routing, and the hijack scope.
  3. If the command line works but only the browser fails, check Secure DNS, proxy settings, and browser cache. Successful DNS resolution does not prove that the destination's TCP or TLS connection is working.
  4. If you still get old results after changing the configuration, reload the core and clear relevant app caches. On Windows, run ipconfig /flushdns to clear the system DNS cache, but this does not clear every cache maintained by the core or browser.
SymptomCheck firstDon't start by
No response on port 1053enable, port conflicts, core logsRepeatedly changing connection routing rules
Primary upstream works, fallback times outFallback service reachability and its outbound routeAdding even more unreachable upstreams
Only internal domains failInternal DNS, domain-specific resolution, and Fake-IP exclusionsSending every query to public DNS
Fake-IP returned, but webpages won't loadWhether subsequent connections still pass through the same coreAssuming DNS poisoning based only on a mapped address

You can reduce the final check to three questions: Did the request reach built-in DNS? Did the upstream return a usable result? Was the subsequent connection handled as expected? nameserver and fallback determine the resolution sources, fallback-filter selects the result, and dns-hijack handles the TUN query entry point. Change one part at a time so each configuration change can be matched to the symptoms. For more on tuning proxy groups and TUN, see the mihomo Advanced Configuration Guide.