First, determine whether the problem is a DNS leak

A DNS leak usually means domain lookups bypass the expected Clash or mihomo DNS processing chain and are handled directly by the operating system, router, browser security DNS, or an ISP resolver. Even when web traffic is proxied, DNS queries may still leave through the local network separately. An outside observer can therefore see the queried domains, while users may encounter incorrect resolution, poisoned results, unexpected rule matches, or different behavior for the same site across applications.

Seeing a local ISP DNS server does not automatically mean the configuration has failed. First define the expected behavior: if nameserver in the configuration intentionally points to a local public DNS service, seeing that provider on a test page is normal. If the intended setup uses a specific DoH, DoT, or remote resolver, but the test repeatedly shows a router address, broadband provider resolver, or corporate DNS, investigate further.

Common symptoms

  • The browser works normally, but curl, a software updater, or a game platform cannot connect to the same domain.
  • After switching proxy nodes, the DNS test always shows the local broadband provider's resolver.
  • The rules use domain matching, but the logs show only IP addresses, so the DOMAIN-SUFFIX rule does not work as expected.
  • With TUN enabled, some sites return content for the wrong region; disabling TUN restores the expected result.
  • The same domain resolves to different addresses in the browser, nslookup, and Clash logs.
  • The configuration uses fake-ip, but system lookups return a public IP instead of an address in the 198.18.0.0/16 range.

Record a baseline before changing the configuration

  1. Record the current client, core version, and name of the configuration file in use.
  2. Confirm whether the mode is Rule, Global, or Direct, and record the states of TUN and the system proxy.
  3. Clear the browser and system DNS caches, then repeat the test twice.
  4. Test the browser, command line, and one standalone application separately so one program's behavior is not treated as a system-wide conclusion.
  5. Check the Clash logs for DNS requests, rule matches, and connection targets.

When only the system proxy is enabled, ordinary DNS queries from the operating system may not be intercepted. An HTTP or SOCKS proxy handles application connections, while the system resolver may still send UDP 53 requests to the DNS servers configured on the network adapter. TUN combined with DNS hijacking covers more applications, but only when TUN, routing, the DNS listen address, and hijacking rules are all active.

Cross-check with a browser test and command-line tools

How to use browser DNS leak tests correctly

Open a reputable DNS leak test page, run the standard test first, and then run the extended test. Before testing, disable other proxy extensions, keep one browser window open, and refresh the page. Results usually list resolver IPs, network organizations, and regions. Compare them with the DoH, DoT, or regular DNS providers in your configuration instead of checking only whether the region matches the proxy node.

Browsers may use their own secure DNS. Chrome, Edge, and Firefox can bypass the operating system resolver and send queries directly to the DoH service selected in the browser. A browser test page therefore shows only that browser's path at that moment; it cannot by itself prove that Clash controls the entire system.

  • In Chromium-based browsers, check Settings → Privacy and security → Security → Use secure DNS.
  • In Firefox, check Settings → Privacy & Security → DNS over HTTPS.
  • When testing Clash DNS interception, temporarily disable browser secure DNS. After verification, decide whether to re-enable it based on the actual design.
  • If browser DoH remains enabled, treat it as a separate resolution path; it cannot be used to verify Clash's dns section.

Query the Clash DNS listen port directly

Assuming the configuration contains listen: 127.0.0.1:1053, Windows, macOS, or Linux systems with dig installed can query that port directly:

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA

In fake-ip mode, an A record usually returns a reserved address from 198.18.0.0/16, such as 198.18.0.23. This is not the target site's real address; it is a virtual address used by the core to map the domain. When a subsequent connection hits that address, the core restores the original domain and selects a proxy policy according to the rules.

If the configuration uses enhanced-mode: redir-host, the result is usually the real public IP. In that case, the presence or absence of 198.18.x.x cannot determine whether a leak exists; use logs, packet captures, and upstream resolver results to confirm the path.

Check the DNS currently used by the system

Windows PowerShell can show the DNS addresses for each network adapter:

Get-DnsClientServerAddress |
  Where-Object {$_.ServerAddresses.Count -gt 0} |
  Format-Table InterfaceAlias, AddressFamily, ServerAddresses

If the result is still a router address such as 192.168.1.1, that is common when only the system proxy is used. Whether TUN should change it to a loopback address depends on the client implementation. Many mihomo clients intercept UDP 53 through DNS hijacking instead of permanently changing the adapter DNS. Do not manually set every adapter to 127.0.0.1 without understanding the client's behavior; if the core exits, the entire system may lose DNS resolution.

On Linux with systemd-resolved, run:

resolvectl status
resolvectl query example.com

On macOS, view the system resolver order with:

scutil --dns
dscacheutil -q host -a name example.com

Use a packet capture to check for direct port 53 traffic

If the results are still unclear, capture DNS traffic during the test. On Linux, use the following command to observe traditional UDP and TCP DNS:

sudo tcpdump -ni any 'port 53'

On Windows, use the built-in pktmon, or set a dns or udp.port == 53 filter in a network analysis tool. After running a test query, packets sent directly from the physical adapter to the router or an ISP DNS server indicate that traditional DNS is still bypassing the expected path. DoH uses port 443 and DoT uses port 853, so filtering only port 53 will not detect them; check the destination IP, process, and Clash logs as well.

Understand fake-ip, redir-host, and DNS hijacking

How fake-ip works

  1. The application asks the system to resolve a domain.
  2. The query is sent to the Clash DNS listener or intercepted by the TUN DNS hijacking rule.
  3. The core returns a virtual address from the 198.18.0.0/16 range and stores the mapping between the virtual address and domain.
  4. The application connects to the virtual address, and TUN or the transparent proxy layer intercepts the connection.
  5. The core restores the original domain, applies domain rules, and establishes the real connection through the selected policy group.

This approach reduces the loss of rule information caused by early local resolution and makes domain-based routing easier. It does not mean that upstream DNS disappears. The core may still need to resolve proxy server domains, direct-connection targets, or excluded domains, so default-nameserver, nameserver, proxy-server-nameserver, and rule behavior must still be configured correctly.

When redir-host is a better fit

redir-host returns the real IP to the application and is usually straightforward for compatibility, but the relationship between domains and connections may rely more heavily on sniffing, caching, and mappings. For extensive domain rules, TUN interception, and complex routing, mihomo generally works better with fake-ip. For LAN device discovery, printers, game logins, corporate intranets, or applications that require real DNS results, add specific domains to fake-ip-filter first instead of disabling fake-ip entirely.

What belongs in fake-ip-filter

Domains in the filter list bypass virtual-address handling. Base the list on actual failures and avoid broad wildcard rules. Common starting points include:

fake-ip-filter:
  - "*.lan"
  - "*.local"
  - "localhost"
  - "time.*.com"
  - "time.*.gov"
  - "ntp.*.com"
  - "+.stun.*.*"
  - "+.stun.*.*.*"

*.local is commonly used for mDNS and LAN service discovery; NTP, STUN, and other protocols may also depend on special resolution or direct-address behavior. Different mihomo versions and client templates may already include default filters. When merging subscription configurations, inspect the final active configuration first so a custom list does not overwrite the client's compatibility rules.

DNS hijacking is not malicious tampering

In a TUN configuration, dns-hijack redirects DNS requests for specified destinations to the core. For example, any:53 intercepts requests sent to port 53 at any address. This addresses applications that bypass the system DNS and query a fixed server directly. Browser DoH uses HTTPS on port 443, so it is not captured by any:53.

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

Field formats and protocol support may differ between core versions. Before editing, confirm in the client's Settings → Core or About page that mihomo is actually being used, then validate the syntax with the configuration checker. Editing only the original subscription file is usually insufficient because an update may overwrite the changes; prefer the client's override, merge, or Mixin features.

A mihomo DNS configuration to use as a starting point

The following configuration helps explain how the fields relate. The listen port is set to 1053 to avoid directly conflicting with an existing system service on port 53. The actual interception method is determined by the client's TUN and DNS hijacking settings.

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

  fallback:
    - tls://1.1.1.1:853
    - https://1.1.1.1/dns-query

  fallback-filter:
    geoip: true
    geoip-code: CN
    ipcidr:
      - 240.0.0.0/4

  fake-ip-filter:
    - "*.lan"
    - "*.local"
    - "localhost"
    - "time.*.com"
    - "time.*.gov"
    - "ntp.*.com"
    - "+.stun.*.*"
    - "+.stun.*.*.*"

default-nameserver: resolve the upstream servers themselves

default-nameserver resolves the domains of DoH and DoT upstream servers and other domains required for basic connectivity. It usually contains DNS servers specified as directly reachable IP addresses. It is not the sole resolver for every business domain. If a DoH address is written only as a domain name without a working bootstrap resolver, a dependency loop can occur: the DoH domain must be resolved before DoH can be used, but no available server can resolve it.

nameserver: the primary resolution path

nameserver contains the primary upstreams for ordinary domain queries. The example uses HTTPS DNS to encrypt query contents between the device and resolver. Two upstreams provide availability redundancy; they do not necessarily run one after another in list order. Exact concurrency, caching, and result selection depend on the core implementation and version.

Regular UDP DNS can also be written as 223.5.5.5, but queries are transmitted using the traditional DNS protocol. DoT uses a format such as tls://1.1.1.1:853, while DoH uses a complete HTTPS URL. A configuration loading successfully does not mean the network allows access to the relevant port; check the logs for timeouts, failed TLS handshakes, or certificate errors.

fallback and fallback-filter: filter backup results

fallback provides another group of resolvers, while fallback-filter determines when backup results are used. In the example, geoip: true and geoip-code: CN use an IP geolocation database to evaluate results; special ranges such as 240.0.0.0/4 can be used as filters for abnormal results.

This mechanism depends on accurate GeoIP data. CDN addresses, Anycast addresses, and newly allocated ranges may be classified incorrectly, so geographic checks are not absolute. If a site behaves abnormally only when fallback is enabled, first check what each resolver group returns, then adjust the domain policy or filter conditions.

ipv6: enable it according to network conditions

The example uses ipv6: false, which suits networks without stable IPv6, proxy nodes without IPv6 support, or troubleshooting that should start with a narrower scope. If both the local network and proxy chain fully support IPv6, change it to true and check TUN routing, the proxy egress, and AAAA queries. Disabling AAAA responses alone cannot fix every IPv6 bypass; existing IPv6 connections and application-level resolution must also be checked separately.

Fix DNS bypass issues in order

Step 1: confirm the final active configuration

The subscription, client overrides, and runtime settings may combine to generate the final configuration. In the client, open Configuration → Current Configuration or Configuration → View Runtime Configuration, and confirm that dns.enable, enhanced-mode, the listen address, and TUN settings are present. Menu names vary slightly by client, but inspect the configuration actually loaded by the core, not the original YAML in the subscription download directory.

Step 2: check whether the port is listening

On Windows, run:

Get-NetTCPConnection -LocalPort 1053 -ErrorAction SilentlyContinue
Get-NetUDPEndpoint -LocalPort 1053 -ErrorAction SilentlyContinue

On macOS or Linux, run:

lsof -nP -iTCP:1053 -iUDP:1053
ss -lntup | grep 1053

If there is no listening result, check the core logs first. Common causes include incorrect YAML indentation, a port already in use, the client not loading the edited configuration, and security software blocking the core from binding the port. If you switch to another port, such as 1054, update both the direct-query command and the client's interception settings.

Step 3: verify direct and system queries separately

  1. Use dig @127.0.0.1 -p 1053 to confirm that Clash DNS itself responds.
  2. Use dig example.com or nslookup example.com without specifying a server to check the system's default path.
  3. Test separately with TUN enabled and disabled, and record the returned addresses.
  4. Open a browser DNS test page and confirm whether browser secure DNS affects the result.
  5. Check the core logs for the test domain and the final matched rule and policy.

If a direct Clash query works but the system's default query still uses the router, the problem is in the interception layer, not nameserver itself. Check whether TUN actually started, whether it has the required system permissions, whether DNS hijacking is active, and whether the current adapter is excluded. If the direct query also times out, fix the DNS listener or upstream connection first.

Step 4: clear caches and test again

Clear the Windows system DNS cache:

ipconfig /flushdns

On macOS, run:

sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

Linux caching depends on the distribution. With systemd-resolved, run:

sudo resolvectl flush-caches

Then fully quit and reopen the browser. Reloading a page does not clear the browser's own host cache or existing connections. For chat clients, game platforms, and sync tools that keep connections open, quit the processes and start them again.

Step 5: handle DoH built into browsers and applications

If command-line and system queries already enter Clash but the browser test still shows another resolver group, check browser secure DNS first. Some security products, enterprise clients, and mobile applications also include built-in DoH. Their HTTPS requests may pass through Clash as ordinary web traffic or be routed directly by the rules, but either way they do not enter Clash's local DNS module.

There are two approaches: disable the application's built-in DoH and let the system hand DNS to Clash, or keep application DoH enabled and define explicit routing rules for it. The first is easier to control and troubleshoot; the second suits scenarios that require application-specific resolution policies. Avoid maintaining multiple unknown upstreams at once, or test results may vary by application and domain.

Common configuration mistakes and fixes

Setting nameserver without enabling DNS

dns:
  enable: false
  nameserver:
    - https://dns.alidns.com/dns-query

When enable: false is set, the upstream settings that follow will not create the expected local DNS service. Change it to true, then check the listen port and interception method.

Exposing the listen address to the LAN

listen: 0.0.0.0:1053 listens on every interface. Use this only when LAN devices need to treat the machine as a DNS server, and restrict the source addresses with a firewall. For a single machine, bind to 127.0.0.1:1053 to reduce unnecessary LAN exposure.

Mistaking fake-ip results for poisoned responses

198.18.x.x is the normal virtual address range for fake-ip. After seeing this address, test the application connection and rule match instead of adding it to hosts or sending it directly. If an application is genuinely incompatible, add its exact domain to fake-ip-filter.

Letting multiple programs use port 53

Local ad blockers, virtual machine software, container services, and other proxy tools may all listen on port 53. Two programs cannot reliably occupy the same port on the same address and protocol. You can have Clash listen on 1053 and forward to it from a front-end DNS service, or stop the conflicting service and let Clash handle DNS. After making changes, check both UDP and TCP listeners.

Assuming the system proxy provides global DNS interception

The system proxy mainly affects applications that support HTTP proxy settings. DNS, game traffic, command-line tools, and programs that ignore the system proxy may continue to connect directly. For broader interception, use TUN and confirm that auto-routing, adapter detection, DNS hijacking, and system permissions are all active. TUN is not simply a “stronger proxy” switch; it changes the network stack path, so change only one option at a time while troubleshooting.

Post-fix acceptance checklist

  • The core logs show no DNS upstream timeouts, listen failures, or configuration field errors.
  • dig @127.0.0.1 -p 1053 returns a result within a normal response time.
  • In fake-ip mode, the test domain returns an address in the 198.18.0.0/16 range.
  • After TUN is enabled, the system's default query appears in the Clash logs with the corresponding domain.
  • Packet captures on the physical adapter no longer show unexpected direct UDP or TCP 53 queries.
  • The browser secure DNS state matches the current design and no longer creates an unknown independent path.
  • The resolver services shown by the DNS test page match the nameserver and fallback design.
  • If LAN, NTP, STUN, or corporate intranet domains are incompatible, they are handled with precise fake-ip-filter rules.
  • Overrides survive subscription updates, and the results remain unchanged after restarting the client and device.

The key to troubleshooting DNS leaks is to split the path into stages: first confirm that Clash DNS responds, then confirm that operating system queries enter the core, and finally check for independent DoH in browsers and applications. Test pages, command-line tools, logs, and packet captures must corroborate one another. Replacing a single nameserver address usually cannot fix an interception-layer problem; the path is stable only when the listener, hijacking, upstreams, and application behavior all agree.