DNS Config 12-minute read

Clash DNS Leak Test: Configure fake-ip to Prevent DNS Leaks

Test for DNS leaks, then configure mihomo’s enhanced-mode, nameserver, and fallback settings with a ready-to-use example.

Define what counts as a DNS leak

A DNS leak occurs when DNS queries take an unexpected route. For example, you may expect both a website connection and its DNS lookup to go through a proxy, but a test shows that your local ISP handled the lookup. Being able to open a webpage doesn’t prove that DNS took the right path, and enabling fake-ip alone doesn’t guarantee that queries can’t leak.

When troubleshooting, check three stages separately: which resolver the app queries, how Clash handles the query, and which connection the core uses to reach the upstream DNS server. fake-ip mainly changes the second stage: it returns a mapped address to the app, then the core recovers the domain from the connection and applies routing rules. It isn’t an encryption protocol and won’t automatically take over DNS for every app.

  • System proxy: Primarily affects apps that honor the system proxy settings; it doesn’t take over every DNS query on the device.
  • TUN mode: Can capture more network traffic, but you still need to check routing, DNS hijacking, IPv6, and interactions with other VPNs.
  • DoH: Sends DNS traffic over HTTPS to reduce exposure in transit. Direct DoH and DoH over a proxy still follow different network paths.

This configuration is for Clash Meta, which uses the mihomo core. Older versions of Clash and different clients may not support the same fields or overrides. Check the core name on the client’s About or core information page before making changes.

Test procedure: capture a baseline, then compare with the proxy on

Round 1: Record the resolvers on your local network

  1. Test on a trusted personal network. Disconnect other VPNs first to avoid overlapping traffic-capture rules.
  2. Turn off Clash’s system proxy and TUN. Open a trusted DNS leak test site, such as DNSLeakTest. Run the Standard test and note the resolver IPs, providers, and test time.
  3. If you normally rely on a proxy to access the internet and the test page won’t load with the proxy off, skip this round. There’s no need to change your router just to get a baseline.

Round 2: Enable the proxy and test again

Start the current configuration and make sure the proxy group is using a working node. Run the same test again, then run the Extended test. Check whether any resolvers from your local ISP show up again. Open another site to check your exit IP, and record the “web exit” and “DNS resolvers” separately—don’t treat them as one metric.

Test resultPossible causeNext step
Web traffic uses the proxy, but the resolver is still your local ISPSystem DNS isn’t being intercepted, or a DNS rule allows direct connectionsCheck TUN, port 53 hijacking, and the active configuration
A public DNS provider appearsIt may be the core’s upstream resolver or the browser’s Secure DNSCompare with your upstream settings and temporarily turn off browser Secure DNS to test again
The resolver’s location differs from the proxy node’s locationPublic DNS may use anycast or a different exit pointCheck the provider and connection logs; don’t rely on the country label alone
The test times out, but cached pages still loadNew domain lookups fail, but existing connections still workCheck DoH connectivity and DNS resolution for the proxy node’s domain

The test page shows which resolver handled recursive lookups for its test domains. It can’t independently prove that every app follows the same path. Results may also change if you switch browsers or networks, or enable another VPN. Don’t end your investigation based on a green result from a single test.

Configure fake-ip: check the proxy group, then merge the DNS section

This DNS section is intended to be merged into an existing mihomo configuration; it isn’t a complete subscription file. It assumes your current configuration has a proxy group named PROXY with a working proxy node selected—not DIRECT. If your group is actually named “Node Selection,” change both instances of #PROXY to #Node Selection. The suffix explicitly sets the outbound policy for upstream DNS connections.

Back up the original configuration, then replace its existing top-level dns: section. Don’t add a second section with the same name. Save the change using the client’s override or merge feature so subscription updates don’t overwrite it. After saving, check the final active configuration.

DNS section in the existing config
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"
    - "localhost"
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  proxy-server-nameserver:
    - https://dns.alidns.com/dns-query
  nameserver:
    - "https://1.1.1.1/dns-query#PROXY"
  fallback:
    - "https://9.9.9.9/dns-query#PROXY"
  fallback-filter:
    geoip: false
    ipcidr:
      - 0.0.0.0/8
      - 127.0.0.0/8

This example explicitly routes upstream lookups for regular domains through PROXY, while keeping bootstrap and proxy-node domain lookups on a direct connection. It does not guarantee that “all DNS goes through the proxy.” To keep your local network from seeing any plaintext DNS, you’ll also need to design a separate bootstrap resolution path and verify that the node can connect on a cold start.

enable, listen, and enhanced-mode

enable: true enables DNS in the core. listen: 127.0.0.1:1053 listens on port 1053 at the local loopback address, avoiding accidental exposure of the resolver to your LAN. Setting this address alone won’t point system DNS to it. Most system DNS settings accept only a server address, not a custom port such as 1053.

enhanced-mode: fake-ip enables address mapping. The example uses the 198.18.0.0/16 address pool, a reserved range for benchmarking—not real public website addresses. A regular domain lookup returning an address like 198.18.0.2 can be normal; this is just an example, and the actual assigned address can vary.

nameserver and proxy-node domain lookups

nameserver specifies the upstream resolver for regular queries. The example uses a DoH address in IP form to avoid resolving the upstream’s hostname first, and #PROXY sets the proxy policy. Keep the quotes to prevent YAML from misinterpreting special characters.

proxy-server-nameserver resolves the hostnames of proxy servers. Before a node connects, its hostname can’t depend on that same node for resolution—that would create a dependency loop. The example uses direct DoH for this step. default-nameserver provides bootstrap resolution for DNS service hostnames. Assess what each setting exposes separately; they don’t handle regular website lookups.

fallback isn’t simply a backup after a timeout

fallback and fallback-filter determine how results are selected; they don’t mean “query the backup only after the primary DNS times out.” Depending on the core’s query path, both upstreams may be queried in parallel. The example routes both through PROXY so the fallback doesn’t become an unexpected direct exit.

GeoIP filtering is disabled here, leaving only filtering for specified anomalous address ranges. This avoids default geolocation checks changing the expected results. The short list isn’t a complete solution for detecting DNS poisoning. A fake-ip response is a mapped address; it doesn’t mean every query immediately triggers lookups for all real addresses. If you only need one trusted upstream, remove fallback and fallback-filter to simplify the setup first.

TUN and DNS hijacking: route system queries through the core

Once the DNS section is ready, you still need to make sure requests reach the core. To capture regular system DNS queries on a desktop, enable TUN in a mihomo client that supports it. Merge the following snippet into the existing top-level tun: section. If your client manages TUN through its UI, use the final configuration generated by the client.

TUN config snippet
tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  strict-route: true
  dns-hijack:
    - any:53
    - tcp://any:53
  • auto-route creates the routes needed for traffic capture. This usually requires administrator privileges or the client’s system service.
  • dns-hijack sends regular UDP and TCP queries on port 53 that have entered TUN to the internal DNS resolver. It’s not a universal interceptor for every DNS protocol.
  • strict-route can limit some bypass behavior, but its effects vary by operating system. It may also affect LAN access or compatibility with other VPNs.
  • Browser DoH uses HTTPS, while DoT typically uses port 853. Neither is a regular port 53 query, so check the routing for these connections separately.

Don’t copy the automatic routing snippet as-is for setups with multiple network adapters, virtual machines, corporate VPNs, or a bypass router. First identify the default outbound adapter, then check the logs for routing loops. If enabling TUN cuts off the network, turn it off to restore connectivity and troubleshoot one setting at a time. Don’t change DNS, routing, and the proxy node all at once.

Verify the configuration: check the port, mapped addresses, and actual exit separately

Start by querying the core directly on port 1053

Run the following command in a macOS or Linux terminal with dig installed. It targets the local core directly, regardless of where system DNS currently points. On Windows, you can also test the port in an interactive nslookup session.

macOS / Linux
dig @127.0.0.1 -p 1053 example.com A
Windows: enter these commands in order
nslookup
server 127.0.0.1
set port=1053
set type=A
example.com
exit

A regular domain that doesn’t match any filter rule will usually return an A record from the address pool. If the query times out, first check that the core loaded successfully, port 1053 isn’t occupied, and the logs don’t report unknown fields. If direct queries work but system apps still bypass the core, the issue is with traffic capture—not the upstream DNS. Don’t keep switching resolvers.

Then clear the cache and check connections

  1. On Windows, run ipconfig /flushdns to clear the system DNS cache. Browsers may also retain their own cache and connections, so fully quit and reopen the browser before testing again.
  2. In Chrome, go to Settings → Privacy and security → Security and check “Use secure DNS.” To isolate variables, you can temporarily turn it off, then restore your preferred setting after testing.
  3. Check the client’s connection panel to see whether upstream connections to 1.1.1.1:443 and 9.9.9.9:443 use the expected proxy. Logs may look different between clients; you don’t need to see a new connection for every query.
  4. Run the DNS leak test again. Compare the resolver providers first, then use the exit IP and logs to assess the result—don’t rely on the map location alone.

System and browser settings may be managed by organizational policies. If this is a work device, check your organization’s requirements first; don’t disable security policies just to run a test. A regular DNS test also isn’t a WebRTC test. Check separately if you’re concerned about a webpage exposing a local or public IP address.

Common issues: IPv6, LAN access, and subscription overrides

Why is there still IPv6 traffic after setting ipv6: false?

ipv6: false in the DNS section mainly affects how the core handles AAAA queries; it doesn’t disable IPv6 across the operating system. Apps may still make IPv6 connections because of cached results, hard-coded IPv6 addresses, browser-based resolution, or network interfaces that aren’t being captured. If you need IPv6, configure and test traffic capture end to end. If you don’t need it for now, check both system and client settings rather than changing just one DNS field.

Can’t access a printer, NAS, or LAN hostname?

First determine whether the issue is DNS resolution or routing. fake-ip-filter prevents matching domains from returning mapped addresses; it doesn’t automatically send those domains to your router’s DNS. If your LAN resolver is 192.168.1.1, you can configure nameserver-policy for internal domains after confirming your actual subnet. The example below shows fields to merge—don’t create another top-level DNS section.

Merge into the existing DNS section
  nameserver-policy:
    "+.lan":
      - 192.168.1.1

These LAN DNS queries are intentionally kept local and shouldn’t be confused with accidental leaks for public websites. .local is commonly used for mDNS; don’t assume a router’s regular DNS resolver can answer those queries. If you can’t reach the NAS by its LAN IP either, check TUN routing and the firewall first.

Why do the results change after a subscription update?

The client may regenerate the configuration, or the subscription may add nameserver-policy, extra DNS upstreams, or other routing fields. Editing a file in the editor doesn’t mean the running core is using it. After each update, check the active DNS and TUN settings and the proxy group name, then run a quick test. If you use respect-rules to make DNS follow routing rules, design the corresponding rules and node bootstrap resolution separately. Don’t mix that approach with the explicit outbound settings in this guide and guess at the results.

Done: keep a repeatable test record

Record four things: the core and configuration used, browser Secure DNS status, proxy exit, and DNS resolver providers detected. A good result matches your intended setup: regular queries use the specified proxy upstream, any local lookups are intentional, and the node bootstrap path is understood. fake-ip handles address mapping, TUN captures traffic, and the upstream and outbound policy determine the DNS route. All three work together to make the configuration verifiable.

Download Clash