Defining a DNS Leak: Start with the Expected Resolution Path
A Clash DNS leak usually means domain lookups are taking a different path than intended. For example, application traffic may use a proxy while the system still sends DNS queries to the router or ISP. Websites may load and your public IP may belong to a proxy node, even though DNS queries are taking another route. That’s why you need to verify website access and DNS handling separately.
Start by defining your goal: should all traditional DNS queries be handled by the local core, or should upstream DNS traffic also use the proxy? The first is about capturing DNS traffic; the second also depends on the routing policy for upstream connections. Using DoH or DoT encrypts DNS queries, but doesn’t by itself prove they’re sent through a proxy node.
- Client: Manages configuration, system proxy settings, service permissions, and interface toggles.
- Core: Handles DNS resolution, Fake-IP mapping, rule matching, and connection forwarding.
- Subscription: Provides nodes, rules, or a complete configuration; updates may overwrite local changes.
- Applications: May use the system resolver or built-in DoH, bypassing system DNS settings.
Testing: Check Egress, Resolvers, and Local Traffic Separately
Step 1: Establish a Baseline with the Proxy Off
In a test environment where direct internet access is permitted, turn off the system proxy and TUN. Record your public IP, system DNS servers, and the resolver information shown by a DNS leak test. Don’t disable established network policies on corporate networks or managed devices without authorization. Use this baseline for comparison; a test site’s reported country or city alone doesn’t prove a leak.
On Windows, use PowerShell to check the DNS servers for each network adapter. Wi-Fi, Ethernet, VPN, and virtual adapters may all be present, so don’t rely only on the first entry shown in the current interface.
Get-DnsClientServerAddress -AddressFamily IPv4
Get-DnsClientServerAddress -AddressFamily IPv6
ipconfig /all
Step 2: Repeat the Same Tests with Your Configuration Enabled
- Enable the system proxy or TUN mode you intend to use, then confirm the active configuration and selected policy group.
- Check your public IP again and note whether the browser’s Secure DNS setting is enabled.
- Run a DNS leak test and record the resolver IPs, their reported locations, and the test time—not just a “passed” message.
- Check the client’s connection list or debug logs for upstream DNS connections. Verify the destination address and the actual outbound policy.
- Repeat the lookup with a domain that isn’t cached to avoid mistaking a cache hit for a DNS failure.
Public DNS providers may use anycast and distributed egress. A test site’s reported resolver location may differ from the connection’s entry point and doesn’t have to match the proxy node’s city. If your configuration intentionally uses a local resolver for certain domains, local results may be expected. What matters is whether the results match your domain policies and outbound connection records.
Step 3: Verify the Core on a Specific Local Port
If the core listens on 127.0.0.1:1053, use dig with an explicit port to test the DNS service. The 1053 port here is an example, not a default for every client. If dig isn’t installed, there’s no need to switch tools just for this test.
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA
A successful query to the local listening port only confirms that the core’s DNS service responds. Test real application requests too, to verify that system DNS, TUN hijacking, and browser resolution all behave as expected. On Windows, nslookup uses port 53 by default, so a failed default-port query doesn’t prove that a service listening on port 1053 is broken.
Fake-IP: Preserving Domain Mappings Doesn’t Encrypt DNS
enhanced-mode: fake-ip makes the core return a virtual address for eligible domains and maintain a mapping between each domain and its virtual address. When an application connects to that address, the core can recover the domain for rule matching or pass it to a proxy for outbound handling. The real address may only need to be resolved later, during connection setup, or may be handled by the remote proxy, depending on the protocol and outbound implementation.
A common Fake-IP address pool is 198.18.0.1/16. This range is used for virtual mappings; it isn’t a node’s public egress IP. A query returning an address from this range usually means the mode is working as intended. Don’t use it as a remote server address or add it manually to your system’s public DNS list.
| Setting | What it does | What it doesn’t guarantee on its own |
|---|---|---|
fake-ip | Returns a virtual address and stores the domain mapping | Encrypts upstream queries or routes them through a proxy |
redir-host | Returns the actual resolved address to the application | That application DNS queries always reach the core |
fake-ip-filter | Applies filter rules to matching domains, often returning real addresses | Replacing proxy routing rules |
LAN discovery, some device admin pages, and applications that require real IP addresses may need exceptions. Start with specific domains before widening the scope. Adding many public domains to the Fake-IP filter list changes DNS behavior and makes results harder to interpret. The filter list controls how DNS answers are returned; rules control connection routing. They aren’t interchangeable.
Nameserver Configuration: Separate Regular and Bootstrap Resolution
This mihomo DNS snippet illustrates the fields; it isn’t a complete subscription. Keep your existing nodes, policy groups, and rules, and merge the relevant fields into the active configuration. Use only one dns key at each YAML level. If your client uses overrides or merged configurations, check the merged result—not just the text in the editor.
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"
- "localhost"
default-nameserver:
- 223.5.5.5
nameserver:
- https://dns.alidns.com/dns-query
proxy-server-nameserver:
- https://dns.alidns.com/dns-query
listen: Bind to the loopback address to avoid exposing the DNS service directly to your LAN. If other devices need access, configure the access boundaries separately.default-nameserver: Primarily resolves the hostnames of DNS upstreams, solving the startup problem of needing to know the resolver address first.nameserver: The upstream resolver list for regular domain lookups; domain policies and other fields can also affect how queries are handled.proxy-server-nameserver: Resolves proxy node hostnames, avoiding reliance on a proxy route that isn’t available yet.ipv6: false: Disables IPv6 DNS responses in this DNS module. It doesn’t turn off IPv6 in the operating system or block all IPv6 connections.
Don’t disable certificate verification to make DoH work. Check the system clock, upstream address, network connectivity, and bootstrap resolution first. If DNS upstreams must also follow routing rules, mihomo supports settings such as respect-rules, but you must also account for node hostname resolution and the outbound dependencies of DNS upstreams. Adding respect-rules: true without checking your rules may create a resolution loop or still route queries directly.
Fallback and Domain Policies: Backup Resolvers May Be Queried in Parallel
It’s easy to assume fallback means “try the backup DNS only if the first one times out.” In common fallback resolution flows, the core may query the primary and fallback resolvers at the same time, then choose a result based on fallback-filter. So adding a public resolver as a fallback doesn’t mean it won’t receive queries during normal operation.
fallback-filter can influence result selection based on geolocation, IP ranges, domains, and other conditions. Geo databases can be outdated, and CDNs may return addresses from other regions; a region code isn’t a universal test for DNS tampering. For troubleshooting, start with a set of verifiable upstreams and add fallback only if needed. This is usually easier to diagnose than stacking multiple resolvers at once.
Route Specific Domains to an Upstream: nameserver-policy
LAN hostnames usually need an internal DNS server. This example routes +.home.arpa to 192.168.1.1; use it only if that address is the resolver for your current network. This is an explicitly retained local lookup path, so don’t judge it by whether every query comes from a proxy node.
dns:
nameserver-policy:
"+.home.arpa":
- 192.168.1.1
This is only a field snippet. Merge it into the existing dns mapping above; don’t append a second copy at the end of the file. For domains that need real LAN addresses, also check the Fake-IP filter policy. Resolving a domain through internal DNS doesn’t automatically route its application traffic over the LAN; the connection rules must allow the relevant local access.
TUN DNS Hijacking: Capturing Port 53 Doesn’t Capture Every Resolver
A system proxy mainly affects applications that honor proxy settings; it doesn’t centrally capture system DNS. TUN mode captures traffic through a virtual network adapter and routes. Combined with dns-hijack, it can send matching traditional DNS requests to the core. The following snippet requires client service permissions and platform support; merge it with your existing TUN configuration.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
any:53 matches UDP queries on port 53, while tcp://any:53 adds TCP port 53. Actual capture still depends on OS routing, the TUN stack, excluded networks, and other VPNs. In particular, use packet captures to confirm whether requests to a LAN DNS server enter TUN. Retest after switching network adapters; don’t verify only on the network active at startup.
Three Traffic Types to Handle Separately
- Browser DoH: Usually appears as an HTTPS connection on port 443 and isn’t automatically redirected by port 53 hijacking rules. For troubleshooting, temporarily turn off Secure DNS in the browser or include it in an explicit encrypted DNS setup.
- DoT and other encrypted DNS: DoT commonly uses TCP port 853. Check app-level encrypted DNS against its actual protocol and outbound connection.
- IPv6 and multiple network adapters: Capturing IPv4 doesn’t prove IPv6 is captured too. Check IPv6 routes, DNS addresses, and client support; don’t rely only on the
dns.ipv6setting.
For packet captures, use udp.port == 53 || tcp.port == 53 as a Wireshark display filter. Persistent plaintext DNS traffic on a physical adapter going to an unexpected resolver is worth investigating. Queries on loopback or virtual adapters before interception don’t necessarily indicate a leak. The filter can’t show the contents of DoH queries or prove that no DNS traffic uses other ports.
Troubleshooting Steps and Configuration Checks
| Symptom | Check first | How to verify |
|---|---|---|
| No response on local port 1053 | DNS toggle, port conflict, configuration load errors | Check core startup logs and listening ports |
| Local queries work, but browser results differ | Browser Secure DNS, cache, proxy extensions | Standardize DNS settings, then retest with a new domain |
| All domains time out after enabling TUN | Permissions, upstream reachability, resolution loops | First verify node hostname resolution and bootstrap DNS |
| Public domains work, but LAN hostnames fail | Domain upstream policy, Fake-IP filters, LAN rules | Query the LAN DNS server and core DNS separately |
| Issue returns after a subscription update | Override order and active configuration | Compare DNS and TUN fields before and after the update |
After changing the resolution mode or upstreams, clear the relevant caches and retest. On Windows, run ipconfig /flushdns to clear the system cache. Browsers and cores may maintain separate caches, which you’ll need to clear through their own settings or by restarting them. Existing connections may not trigger a new lookup; create a new connection for testing instead of merely refreshing a page with a long-lived connection.
- Configuration loaded: The core loads successfully, and its DNS listening address and port match the test command.
- Traffic captured: Traditional DNS requests from real applications reach the core as expected, and any exception paths have a clear purpose.
- Upstreams verified: You can identify which upstream handles regular lookups, bootstrap resolution, and node hostname resolution.
- Outbound routing verified: DNS upstream connections that should use the proxy match the correct policy; don’t infer this from the DoH address alone.
- Persistent after restart: Retest after restarting the client, updating subscriptions, and switching networks to confirm the configuration persists.
DNS leak prevention isn’t a single toggle. It depends on how applications resolve domains, system routing, core settings, and upstream egress. Fake-IP handles domain mapping, nameserver defines DNS resolvers, and TUN hijacking captures eligible requests. Test each separately to find where a problem occurs. For more concepts, see the Fake-IP protocol reference; for importing and overriding configurations, see the user guide.