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-SUFFIXrule 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 the198.18.0.0/16range.
Record a baseline before changing the configuration
- Record the current client, core version, and name of the configuration file in use.
- Confirm whether the mode is Rule, Global, or Direct, and record the states of TUN and the system proxy.
- Clear the browser and system DNS caches, then repeat the test twice.
- Test the browser, command line, and one standalone application separately so one program's behavior is not treated as a system-wide conclusion.
- 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
dnssection.
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
- The application asks the system to resolve a domain.
- The query is sent to the Clash DNS listener or intercepted by the TUN DNS hijacking rule.
- The core returns a virtual address from the
198.18.0.0/16range and stores the mapping between the virtual address and domain. - The application connects to the virtual address, and TUN or the transparent proxy layer intercepts the connection.
- 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
- Use
dig @127.0.0.1 -p 1053to confirm that Clash DNS itself responds. - Use
dig example.comornslookup example.comwithout specifying a server to check the system's default path. - Test separately with TUN enabled and disabled, and record the returned addresses.
- Open a browser DNS test page and confirm whether browser secure DNS affects the result.
- 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 1053returns a result within a normal response time.- In fake-ip mode, the test domain returns an address in the
198.18.0.0/16range. - 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
nameserverandfallbackdesign. - If LAN, NTP, STUN, or corporate intranet domains are incompatible, they are handled with precise
fake-ip-filterrules. - 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.