What Counts as a DNS Leak?

Clash shows an active proxy connection, but a DNS leak test lists your local ISP. That’s a common starting point for troubleshooting—but seeing multiple DNS addresses does not automatically mean there’s a leak. First, define your goal: should only domains routed through the proxy use proxy DNS, or should every public DNS query—apart from those needed to resolve node hostnames—go through a specified exit? These goals have different success criteria.

Here, a DNS leak means a domain query did not follow the intended policy and was instead sent to the system resolver, local network, or another unauthorized resolver. Leak test sites typically show the recursive resolvers that handled their test queries—not your computer’s configured DNS addresses or the proxy node itself. So a mismatch between the DNS server’s location and your apparent web location is a clue, not proof of a leak.

What you seePossible causeWhat to check next
A local ISP resolver appearsSystem queries aren’t being intercepted, or the rules explicitly allow direct DNSCompare the rules with traffic on port 53
A public DNS provider appearsThe core or browser is using that serviceCheck whether the upstream and exit are expected
The resolver and proxy node are in different countriesAnycast routing, recursive resolver egress, or geolocation database differencesCheck routing in the connection logs
Multiple addresses appear on each testOne service may use multiple recursive resolvers, or queries may take different routesCompare the providers, not just the IP count

Run a Reproducible DNS Leak Test

Record your setup, then change one variable at a time

  1. Note the client and core names and versions, and whether you’re using the system proxy or TUN. The examples here are for mihomo and may not work as-is with the discontinued legacy Clash core.
  2. Quit other VPNs, accelerators, and proxy tools. Keep just one client running to prevent virtual adapters and DNS settings from interfering with each other.
  3. Open dnsleaktest.com in your browser. Run the Standard test, then the Extended test. Record resolver IPs, provider names, test time, and your apparent web IP—not just the listed country.
  4. Run a baseline test with the proxy off, then test again with your target configuration enabled. The baseline uses your local network directly, so don’t run it in environments with strict network isolation requirements.
  5. After changing the configuration, reload the core, clear system DNS caches, and fully quit and reopen the browser before testing again. Use the same node, network, and test site so you can compare results.

On Windows, run ipconfig /flushdns in a terminal to clear the system DNS cache. This won’t clear the browser’s own DNS cache or reset all mihomo runtime state. If results don’t change, restart the browser and core before concluding that the configuration hasn’t taken effect.

Separate Browser Results from System Results

Browser Secure DNS may send queries directly over HTTPS, bypassing the system’s port 53 DNS path. To troubleshoot, search your browser settings for “Secure DNS” and temporarily turn it off for comparison. Once core interception is working, decide whether to turn it back on and add an explicit proxy rule for the DoH connection. A successful browser test also doesn’t prove that command-line tools, games, or other apps use the same route.

For example, a comparison log might read: “System proxy: ISP and public DNS detected; TUN: only the configured public DNS detected.” That’s just a sample format, not a test result. Keep your own results and use the core’s connection logs to verify what changed.

Enable fake-ip and Set Explicit DNS Upstreams

Back up your working configuration before editing. Subscription updates may overwrite changes, so use your client’s override or merge feature. If you’re unsure how merging works, make a separate local copy for testing. The final effective configuration should contain only one top-level dns: section; don’t paste a duplicate at the end of the file.

This mihomo DNS snippet must be merged into your existing configuration, including its proxies, proxy groups, and rules. It sends general queries to Cloudflare DoH and routes qq.com and its subdomains to a mainland China DoH service. This is an explicit split-DNS policy—not a guarantee that all queries go through the proxy.

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "*.lan"
    - "*.local"
  respect-rules: true
  default-nameserver:
    - 223.5.5.5
  proxy-server-nameserver:
    - https://223.5.5.5/dns-query
  nameserver:
    - https://1.1.1.1/dns-query
  nameserver-policy:
    "+.qq.com":
      - https://223.5.5.5/dns-query
  • listen: 127.0.0.1:1053 listens on the local machine only; it doesn’t expose a DNS service to your LAN. System DNS settings generally can’t use a custom port such as 1053, so you’ll also need TUN interception or a system-supported local forwarder.
  • 198.18.0.1/16 is the virtual IP pool used here. It’s normal for apps to receive addresses from this range. If your network already uses it, resolve the conflict first.
  • Domains listed in fake-ip-filter receive real IP addresses instead. This is mainly for compatibility with use cases such as LAN device discovery. It’s not a routing rule and doesn’t mean those queries will necessarily go direct.
  • proxy-server-nameserver resolves proxy server hostnames, avoiding a circular dependency where connecting to a node requires DNS, but DNS is waiting for the node connection. This lookup may not occur if the node is configured by IP address.
  • default-nameserver handles bootstrap lookups, such as resolving DNS server hostnames. If a regular DNS query uses it, your local network may see the bootstrap hostname. This does not mean all application queries use that server.

Use nameserver-policy and Routing Rules to Choose the DNS Exit

nameserver-policy determines which resolver handles a domain; respect-rules: true makes DNS upstream connections follow routing rules. They solve different problems. Switching to a public DNS provider outside mainland China does not guarantee that queries will go through a proxy.

Assuming your configuration already has a working proxy group named Proxy, add the following two rules to your existing rules: list, before any rules that might match first. Don’t replace the entire rules list with these lines, and don’t save them unless the proxy group exists.

rules:
  - IP-CIDR,1.1.1.1/32,Proxy,no-resolve
  - IP-CIDR,223.5.5.5/32,DIRECT,no-resolve

The first rule routes connections to the example DNS upstream at 1.1.1.1:443 through the specified proxy group; the second sends the mainland China upstream direct. no-resolve prevents an extra DNS lookup just to evaluate this IP rule. Rules are matched in order, so an earlier, broader direct rule may prevent these rules from taking effect.

Test Proxy-Only DNS and Split DNS Separately

  • For split DNS in mainland China: Keep the example nameserver-policy and allow the specified domains to use a DNS provider in mainland China. Random test domains usually won’t match this policy, so they should use the general upstream.
  • For stricter proxy-only DNS: Remove exceptions that send specific domains to a DNS provider in mainland China, and check other upstreams, fallback resolvers, and direct-DNS settings. Bootstrap lookups for node hostnames still need a separate plan; deleting one line doesn’t guarantee that all DNS traffic is contained.
  • For corporate or campus networks: Internal domains may need to use local DNS. Check with your network administrator and keep any required split-DNS rules. Don’t send batches of internal domain queries to a public provider.

To verify, search the client’s connection list for 1.1.1.1 and check whether the destination port is 443 and the matched policy is the intended proxy group. Clients vary in how they display internal DNS connections. If nothing appears, check debug logs and capture network traffic—don’t assume “not visible” means “no request.”

Use TUN to Capture System DNS and Intercept Port 53

The system proxy mainly affects apps that honor proxy settings; it doesn’t automatically capture every system DNS request. To cover more apps, enable a virtual network adapter in a client that supports mihomo TUN and merge the following configuration. Setup may require administrator privileges or installation of a virtual adapter service.

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

Here, any:53 and tcp://any:53 capture regular UDP and TCP DNS traffic passing through TUN, respectively. They can’t automatically rewrite an app’s HTTPS-based DNS queries to use the core, or capture connections that never pass through the virtual adapter. Actual coverage depends on the operating system, routing table, and client permissions.

Local Verification Steps

  1. Confirm the client reports that TUN is running and the logs show no permission errors, virtual adapter creation failures, or route installation failures.
  2. Before running nslookup example.com 127.0.0.1, make sure something is listening on local port 53. This guide uses port 1053, so a failed command doesn’t by itself indicate a DNS problem.
  3. If dig is installed, run the command below to test the core directly on port 1053. When fake-ip is active, the response will usually be in the 198.18.0.0/16 range.
  4. Then run nslookup example.com 8.8.8.8 to check whether regular system queries are being intercepted. Verify with the logs; the server name shown by the command alone doesn’t prove interception is working.
  5. Finally, rerun the browser-based leak test and check that commonly used apps can connect as expected.
dig @127.0.0.1 -p 1053 example.com A
nslookup example.com 8.8.8.8

On Windows 11, go to Settings → Network & internet → Proxy and check for manual proxy settings left behind by other tools. TUN and the system proxy can work together, depending on the client, but for troubleshooting, start with one clearly defined interception path and restore other features one at a time.

Remaining Risks: IPv6, Browser DoH, and Caches

The DNS IPv6 Setting Is Separate from System IPv6

In this example, dns.ipv6: false controls how the core handles AAAA queries. It doesn’t disable IPv6 in the operating system or automatically stop apps from using IPv6 addresses they resolved themselves. Cached results, built-in app DoH, and static addresses may still use another route. Test IPv4 and IPv6 egress separately. If your client can’t fully capture IPv6, temporarily disable IPv6 on the test adapter for comparison, then decide on a long-term approach once you know the cause.

Handle DNS Traffic Outside Port 53 Separately

DoT commonly uses TCP port 853, while DoH usually uses HTTPS on port 443 and may also use UDP 443 over HTTP/3. A port 53 rule in dns-hijack won’t convert these encrypted connections into regular DNS. For Secure DNS built into a browser or app, either make it use the system resolver or configure proxy rules for its DNS provider connection to match your goal.

Use a Packet Capture to Check for Unexpected Plaintext Queries

If you have a packet capture tool, use the display filter udp.port == 53 || tcp.port == 53 on the physical network adapter to inspect traffic during the test. Compare query domains, destination addresses, and timestamps with the logs. DNS packets on the TUN adapter may be part of the internal interception process; to check for leaks, focus on whether the physical adapter sends queries to unexpected external DNS servers.

Not seeing traffic on port 53 doesn’t mean there’s no DNS traffic—DoH and DoT are encrypted. Conversely, bootstrap lookups for proxy nodes, LAN devices, or other processes shouldn’t automatically be blamed on the page you’re testing. Identify the source by process, domain, and timestamp.

Validate the Configuration and Know How to Roll Back

A reliable validation should cover at least three things: the resolvers match your expectations, DNS upstream connections use the intended exit, and apps can access the services they need. A test page showing “no local address” doesn’t rule out broken internal domains, node resolution loops, or other apps bypassing the proxy.

  • Configuration won’t load: Check YAML indentation, duplicate top-level keys, and unrecognized options. Confirm the running core is mihomo; the client’s appearance doesn’t tell you which core version it uses.
  • All domains time out: First check that the node connects and its hostname resolves through the dedicated upstream. Then check the proxy route for 1.1.1.1:443. Don’t change the node, DNS, and rules all at once when troubleshooting.
  • Tests pass but internal sites won’t open: Check whether internal domains require local DNS, and review fake-ip-filter and split-DNS policies. Don’t just expand the filter list without checking the real upstream.
  • The problem returns after a subscription update: Compare the effective configuration before and after the update. Make sure DNS, TUN, and rule overrides are still present; don’t rely only on the text saved in the editor.
  • You lose connectivity after closing the client: Check whether system DNS, manual proxy settings, and routes have been restored. Turn off TUN and quit the client first, then restore network settings from your backup.

fake-ip maps domains to addresses, nameserver-policy selects resolvers, routing rules choose the egress for upstream connections, and TUN expands system traffic interception. Testing these four layers separately makes it easier to find the cause than repeatedly toggling a “leak protection” switch. For a primer on split tunneling and subscription setup, see the Clash configuration guide; for field details, see the full documentation.