Troubleshooting 12-minute read

Clash DNS Leak Test and Fix: Prevent Leaks with fake-ip and nameserver-policy

Use a DNS leak test to see whether queries bypass your proxy. Then adjust enhanced-mode, nameserver, and nameserver-policy, route system DNS through TUN, and test again.

First, distinguish DNS leaks from differences in resolver location

Proxying web traffic does not mean DNS queries are proxied too. The system proxy usually affects only apps that honor proxy settings. System lookups, browser Secure DNS, and DoH built into other programs may each use a different route. To fix a leak, identify who is making the query, which resolver it uses, and how connections to that resolver are routed. Switching to fake-ip alone is not enough.

This guide covers the mihomo core. Older versions of Clash and different client wrappers may not support the same fields. Check the core name in your client's core information or startup logs. If configuration validation reports an unknown field, consult the documentation for your current core version; fields with the same name do not necessarily provide the same behavior.

  • DNS leak: A domain lookup you expect to send through a proxy instead goes over your local network to your ISP or another unintended resolver.
  • Different resolver location: The country shown by a test site usually comes from a database lookup of the resolver's egress IP. It does not necessarily show the proxy node's actual location.
  • Intentional direct resolution: Local network names, direct-connection sites, or proxy server hostnames may be resolved directly. Decide which queries may go direct based on your routing goals.

Establish a baseline: check the browser, system, and core separately

Compare results under the same test conditions

  1. Pause other VPN and proxy apps, and stick to one proxy node. Note the current status of the system proxy, TUN, and browser Secure DNS.
  2. Open DNSLeakTest and run the Extended test. Record the resolver IPs, organizations, and locations shown.
  3. If a direct-connection test is acceptable, turn off the proxy and test again to establish a baseline for your local network. Restore the proxy and run a fresh test; results in an old tab may not reflect the current connection.
  4. If the same ISP resolver from the baseline appears with the proxy on, investigate further. Even if only the expected public resolver appears, verify whether the connection to it is direct or proxied.

A test site mainly observes the recursive resolver's egress when it queries authoritative DNS servers. That alone cannot prove the route between your computer and the recursive resolver. Shared resolvers, Anycast, and caching can all affect the results. Use the test alongside your client's connection logs rather than drawing conclusions from a country name alone.

Temporarily standardize the browser's DNS route

In desktop Chrome, go to Settings → Privacy and security → Security → Use secure DNS. To first check the route from your system to mihomo, turn this off temporarily, then decide whether to turn it back on after testing. Organization-managed browsers may prevent you from changing this setting.

Browser DoH uses HTTPS, so it usually does not appear as UDP port 53 traffic. It may still be routed through a proxy under TUN, but setting dns-hijack does not automatically send it to mihomo's DNS module. Note Android's Private DNS separately too, so results from different DNS paths are not conflated.

Check that the core is actually receiving DNS queries

The examples below configure the core to listen on port 1053 on localhost. On macOS or Linux with dig installed, 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 PowerShell on Windows, run the command below to check the system's default DNS route. This is not the same as querying localhost on port 1053 directly. With TUN enabled, also check the core's DNS logs to confirm that the request arrived.

Resolve-DnsName example.com -Type A
Get-DnsClientServerAddress

What fake-ip, nameserver, and bootstrap resolution each do

FieldWhat it doesWhat to check
enhanced-modeChoose a handling mode, such as fake-ip or redir-hostDoes not ensure upstream queries go through a proxy
nameserverConfigure regular upstream resolversResolver address, transport protocol, and outbound policy
nameserver-policySet an upstream resolver for matching domainsCheck for an old policy sending domains back to local DNS
default-nameserverResolve the hostname of a DNS serverCheck whether bootstrap resolution makes an unintended direct connection
proxy-server-nameserverResolve the proxy node's server hostnameAvoid relying on the proxy to connect to the proxy in the first place

fake-ip typically returns a mapped address to the app, then the core associates later connections with the original domain. The 198.18.0.1/16 range used in this example is reserved for benchmarking, not for public website addresses. Seeing an address from this range does not mean website resolution is broken, nor does it prove that upstream queries are protected by a proxy.

fake-ip-filter determines which domains do not receive Fake-IP addresses. Some local network services need real addresses, so add exceptions as needed. Do not put every domain in the filter just to work around a single compatibility issue. The filter changes how response addresses are handled; it does not replace upstream routing rules.

Configure upstream DNS and explicitly set its proxy policy

The following mihomo configuration snippet illustrates the DNS resolution path; it is not a complete configuration file. It assumes your existing configuration defines a policy group named Proxy with an available node. The example sends regular queries and queries for the test domain example.com to upstream resolvers through the proxy, while retaining an explicit direct bootstrap path.

config.yaml · DNS snippet
dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  default-nameserver:
    - 223.5.5.5
  proxy-server-nameserver:
    - https://223.5.5.5/dns-query
  nameserver:
    - "https://1.1.1.1/dns-query#Proxy"
  nameserver-policy:
    "+.example.com":
      - "https://8.8.8.8/dns-query#Proxy"
  • #Proxy assigns an existing outbound policy to this DNS upstream. The policy group name must match exactly, including capitalization. Quotes make it unambiguous that the full address is read as a YAML string.
  • +.example.com matches the domain and its subdomains. This is a reproducible test entry, not a list of real service domains; replace or remove it as needed before deployment.
  • In this example, default-nameserver is a direct bootstrap resolver, and proxy-server-nameserver is also intentionally left on a direct path. If a node's server address is a hostname, this resolver will see that hostname in its query.
  • The example uses DoH endpoints in IP address form to reduce reliance on resolving upstream hostnames. The network must still be able to reach them, certificate validation must succeed, and the proxy node must support the required connection.

Handling an existing respect-rules setting

In mihomo, respect-rules: true lets DNS connections follow routing rules, but following rules does not mean they will always use a proxy: if a rule matches the resolver destination to DIRECT, the connection goes direct. If you use this setting, configure an appropriate proxy-server-nameserver and check how your rules actually match the upstream resolver addresses.

Start with one upstream routing method that is easy to verify, then integrate other settings gradually. Do not add a new set of fallback resolvers, multiple policies, and several layers of rules all at once before testing; otherwise, it is hard to tell which change altered the query route. Do not just append another dns: at the end of the file. Edit the existing mapping to avoid duplicate keys that could override settings or prevent the configuration from loading.

Use TUN to route system DNS: handle port 53 traffic

With only the system proxy enabled, programs that ignore proxy settings may still use system DNS directly. TUN can capture more IP traffic, while DNS hijacking routes traditional DNS queries into the core. The snippet below is for mihomo environments that support the relevant TUN features. The client needs permission to create a virtual network adapter and modify routes.

config.yaml · TUN snippet
tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53

any:53 covers UDP DNS; tcp://any:53 adds TCP DNS. This hijacking applies to connections handled by the TUN path; it does not force DNS changes across the entire local network. Some systems handle routes to local-network DNS servers differently, so check the logs to confirm that requests reach the core.

  • DoH and DoT: DNS over HTTPS commonly uses port 443, while DoT commonly uses port 853. Neither is covered by the port 53 hijacking above. Check their outbound routing policies separately.
  • Multiple network adapters: Ethernet, Wi-Fi, virtual machine adapters, and other VPNs can change the default route. If your connection drops after enabling TUN, first check which outbound adapter was detected automatically.
  • IPv6: dns.ipv6 controls how DNS handles AAAA responses; it is not a system-wide IPv6 switch. Testing only A records does not prove that IPv6 traffic is being captured.
  • Local networks: NAS devices, printers, and corporate network names may need a dedicated resolver. Set policies for those domains separately and include expected direct queries in your test notes.

If you do not plan to use TUN, you may be able to point your operating system's DNS setting to the core's listening address, if the OS supports it. However, standard system DNS settings usually cannot specify a custom port. This example listens on 1053, not the usual system port 53, so entering only 127.0.0.1 will not make it work. Changing the listening port also requires checking permissions and port availability.

Save, clear the cache, and retest: verify the fix in order

Check the active configuration before clearing caches

Clients that manage subscriptions may regenerate the configuration during updates. Use the client's supported override or merge mechanism to save DNS changes, and inspect the final active configuration instead of editing a temporary downloaded file. For a command-line setup, test the configuration first. If the binary is named mihomo, run:

mihomo -t -f config.yaml

Reload only after the test passes. A passing test means the core accepts the configuration; it does not guarantee that nodes, resolvers, or the network are reachable. In a GUI client, check the startup logs after reloading for errors such as a failed DNS listener, insufficient permissions, or a missing policy group.

On Windows, clear the system DNS cache and query again. Browsers may retain their own cache or existing connections, so fully quit and reopen the browser before returning to the test page if needed. On mobile devices, disconnect from and reconnect to the current network before testing again.

ipconfig /flushdns
Resolve-DnsName example.com -Type A

Check all three sources of evidence

  1. Ingress evidence: When the system makes a query, the core receives the DNS request. Verify direct queries to port 1053 separately from queries made through the system DNS settings.
  2. Routing evidence: Connection logs show that connections to the example DoH endpoints 1.1.1.1:443 or 8.8.8.8:443 use the expected proxy policy. If needed, temporarily set log-level: debug to investigate, then restore the original log level.
  3. External evidence: Run the test again and check that the resolver organization matches your expectations and no unintended local ISP resolver appears. A different location alone does not indicate a failure.

Debug logs may contain visited domain names, node addresses, or other network information. Before sharing logs, remove subscription links, credentials, and domains you do not want to disclose. Do not post your full configuration in a public forum.

Common results and what to check next

SymptomCheck first
Browser test passes, but system queries still go directThe browser may use its own DoH; check TUN routing and the system DNS entry point
Fake-IP is returned, but the test result is still unexpectedCheck the upstream outbound policy; Fake-IP does not mean DNS queries use a proxy
All domains time out when the proxy is enabledCheck node hostname bootstrap resolution, policy group names, and DoH reachability
The problem returns after a subscription updateCheck that the override is retained and inspect the DNS fields in the final configuration
Only fails on a corporate network or home NASAssign an accessible local resolver to internal domains and retain the required routes

The goal is to make DNS resolution follow your intended policies, not to leave only one IP on the test page. First decide which domains may be resolved directly, then align the system entry point, core upstreams, and proxy routing. This helps distinguish a real leak from intentional split routing or differences in how resolvers are reported. For more on these fields, see Advanced Setup; for initial setup, see the client setup guide.

Configuration references and verification tools

Clash Client Downloads

Choose a client for your operating system, check its core and TUN support, then follow the guide to import a configuration and verify the DNS route.

Download Clash