Understand DNS resolution, rule-based routing, and traffic interception

Clash can connect to a proxy node while some websites still fail to load. The node may be fine: a connection involves at least three steps—resolving a domain to an IP address, choosing an outbound route based on rules, and sending the app's connection through the proxy core. DNS settings mainly handle the first step; TUN and the system proxy determine the third. Changing DNS servers alone won't route traffic from every app.

This guide focuses on mihomo, the core commonly known as Clash Meta. The original Clash, its various forks, and different client interfaces don't all support the same fields. Check the core information or startup logs in your client to confirm which core is running, then use the matching configuration. The app version and core version are separate numbers.

  1. The app sends a DNS query: It may use the operating system's DNS or the browser's own Secure DNS.
  2. The core handles the query: Based on its DNS settings, it returns a real IP address or a fake-ip.
  3. The connection is matched against rules: The domain, destination IP, process, and other details determine whether the connection goes direct or through a proxy policy.

What nameserver, default-nameserver, and fallback each do

nameserver is the pool of upstream servers used for regular domain lookups. default-nameserver is mainly used to resolve the hostnames of DNS upstreams themselves. For example, if an upstream is set to https://dns.alidns.com/dns-query, the core first needs the IP address of dns.alidns.com to establish an encrypted connection. This initial lookup is often called bootstrap resolution.

SettingPurposeCommon misconception
enableEnables the core's DNS service.Queries still need to be routed to the core after this is enabled.
listenSets the DNS listening address and port.This is not an HTTP or SOCKS proxy port.
default-nameserverProvides bootstrap resolution for DNS upstreams specified by hostname.It isn't the default first-choice list for all regular queries.
nameserverHandles regular DNS queries.Don't assume the servers are strictly tried one by one as primary and backup.
fallbackProvides another set of DNS results, with filters used to select the answer.This isn't just a backup list used only when the primary DNS times out.
fallback-filterDetermines which queries or primary results should use fallback.This isn't an ad blocker, and it doesn't choose which proxy node web traffic uses.

Common upstream formats include plain DNS, such as 223.5.5.5; DoT, such as tls://1.1.1.1:853; and DoH, such as https://dns.google/dns-query. Plain DNS typically uses port 53, DoT port 853, and DoH HTTPS on port 443. An open port doesn't guarantee that the service can complete a query—check the results and logs.

Encrypted DNS protects traffic between the client and the DNS resolver. It doesn't automatically make the upstream trustworthy, hide all domain information, or route DNS queries through a proxy node. First confirm that the upstream is reachable on your current network; then decide whether its connection needs to follow proxy rules.

fake-ip vs. redir-host: choose based on compatibility

fake-ip returns a virtual IP managed by the core and stores a mapping between that address and the domain. When the app connects to the address, the core can recover the domain and match it against rules. A commonly used address pool is 198.18.0.1/16, which is reserved for benchmarking—not a website's real server address.

redir-host returns the resolved real IP to the app and uses recorded DNS mappings where possible to identify the domain. If an app uses encrypted DNS itself, or the connection exposes only an IP address, the core may not be able to reliably determine the original domain. Domain sniffing can fill in some gaps, but it doesn't cover every protocol.

  • Try fake-ip first: A good fit for desktop setups that need reliable domain-based routing and have traffic interception configured correctly.
  • Make exceptions for specific domains: If device discovery on your LAN, apps that require real IPs, or connectivity checks stop working, start by adjusting fake-ip-filter.
  • Then consider redir-host: If an app remains incompatible with virtual IPs, switch modes and compare. There's no need to change all your DNS upstreams at once.

When troubleshooting, keep in mind that pinging a fake-ip does not tell you whether the remote website is working. These virtual addresses are used for mapping and traffic interception. Instead, check whether the app can establish a connection and whether the client’s connection details show the correct domain and final policy.

A DNS configuration snippet you can build on

This snippet enables local DNS and shows how to combine fake-ip with two groups of DNS upstreams. It listens on 127.0.0.1:1053, so only the local machine can access it—preventing the device from being unintentionally exposed as a LAN DNS server. Port 1053 isn't the system's default DNS port; the operating system won't send queries to it automatically just because it's in the configuration.

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:
    - localhost
    - "*.lan"
    - "*.local"
    - "+.msftconnecttest.com"
    - "+.msftncsi.com"
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  nameserver:
    - https://dns.alidns.com/dns-query
  fallback:
    - https://dns.google/dns-query
    - https://cloudflare-dns.com/dns-query
  fallback-filter:
    geoip: true
    geoip-code: CN
    ipcidr:
      - 0.0.0.0/32
      - 240.0.0.0/4

Check these three things before applying the configuration

  1. Merge into the existing dns section: Don't add two top-level dns: keys to the same YAML file. Duplicate keys may be overwritten or cause a parsing error. Indent with spaces, not tabs.
  2. Make sure the upstreams are reachable: If your current network can't reach Google or Cloudflare DoH, this fallback configuration won't fix the connection. Use reachable, trusted upstreams or configure a proxy route for DNS upstream connections.
  3. Know what the IPv6 setting affects: dns.ipv6: false stops this DNS service from returning AAAA records. It doesn't disable IPv6 in the operating system or, by itself, prevent apps from sending IPv6 traffic outside the proxy.

Filtering *.local doesn't mean device discovery is being intercepted. Common mDNS traffic uses UDP port 5353 and multicast addresses, unlike regular unicast DNS. If printer, casting, or NAS discovery fails, also check TUN's LAN routing, the system firewall, and multicast handling.

How fallback-filter evaluates DNS results

In the configuration above, geoip: true and geoip-code: CN mean that the fallback result is used when the regular result doesn't match the specified region. ipcidr adds address ranges to exclude, such as 0.0.0.0/32. This check relies on an IP geolocation database, which may not classify every CDN address accurately.

Keep in mind: an IP outside China doesn't mean the result is polluted. Legitimate websites may be hosted in other regions. This is a result-selection strategy designed for a particular network environment, not definitive proof that an answer is genuine or fake. If a site returns a valid IP but loads slowly, check your outbound rules and CDN routing instead of continually adding IP ranges to the filter.

Route specific domains to a different DNS upstream

mihomo also supports nameserver-policy. If you want a certain group of domains to always use a specific DNS server, a policy is usually clearer than continually adding fallback conditions. This partial snippet routes example.com and its subdomains to a specified DoH server; all other queries continue to use the regular configuration.

dns:
  nameserver-policy:
    "+.example.com":
      - https://dns.alidns.com/dns-query

This snippet only demonstrates the policy syntax and must be merged into your existing dns section. For company intranet domains, use the DNS server provided by your company and make sure it's reachable over the VPN or private connection. Switching among public DNS servers won't resolve private records available only on the corporate network.

Avoid dependency loops when routing DNS upstreams through a proxy

mihomo's respect-rules setting can make DNS upstream connections follow routing rules. If you enable it, also configure proxy-server-nameserver properly to resolve the hostnames of proxy node servers. Otherwise, you can end up with a loop: “DNS needs the node, but resolving the node needs DNS.” Leave these options off until the basic configuration is working.

TUN DNS hijacking: route system queries through the core

With system proxy enabled alone, apps that support proxy settings usually send HTTP or SOCKS connections to the core, while the operating system may still send DNS queries to the router or ISP. TUN uses a virtual network interface to capture more IP traffic and can send intercepted DNS requests to the core's DNS service.

Once the client service mode or required permissions are in place, you can use the following mihomo snippet as a reference. Desktop clients often manage TUN settings themselves. If the interface has already generated the same settings, check the effective configuration to prevent the UI and manual overrides from overwriting each other.

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53
  • any:53 matches relevant UDP DNS requests, while tcp://any:53 adds TCP DNS. Both apply to traffic that enters the interception path.
  • auto-route automatically sets up the relevant routes. Test it carefully, as it may affect other VPNs, virtual machines, or corporate security software.
  • auto-detect-interface attempts to identify the outbound network interface. Multi-adapter setups, mobile hotspots, and complex VPN environments may still require you to specify the interface explicitly.

Without TUN, routing system DNS directly to the local machine usually requires a service listening on local port 53, with the system DNS pointed to that address. This involves port conflicts, administrator permissions, and possible clashes with system resolver services. Don't enter the example port 1053 unchanged in a system DNS field that accepts only an IP address.

Troubleshooting in order: DNS failures, fake-ip not working, and DNS leaks

Step 1: Query the core's listening port directly

On Linux or macOS with dig installed, start with the command below. You can run the same test in a Windows terminal that has the tool available. Don't mistake a regular nslookup test on the default port 53 for a test of port 1053.

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp

In fake-ip mode, domains not matched by the filter list should typically resolve to mapped addresses in the 198.18.0.0/16 range. If the request times out, first check that DNS is enabled, the port isn't in use, and the configuration loaded successfully. Getting a fake-ip only confirms that local mapping works; it doesn't prove that real DNS resolution or website access works.

Step 2: Check whether the system and app use the same path

  1. Reload the configuration and check the logs for unknown fields, YAML indentation issues, or port binding errors.
  2. With TUN enabled, visit a test domain in your browser, then check the client's connection details for the domain, matched rule, and outbound policy.
  3. Temporarily turn off the browser's Secure DNS setting and compare the results. If things work again, investigate the browser's DoH route instead of changing only fallback.
  4. Rule out other VPNs, manually configured DNS, and built-in app proxies one by one to avoid multiple interception paths running at once.

Step 3: Clear caches and test again

On Windows, run ipconfig /flushdns. On Linux with systemd-resolved, run sudo resolvectl flush-caches. On macOS, the commonly used command is below. The system cache, browser cache, and the core's fake-ip mappings are separate layers. You may also need to restart the test app or use the client's DNS cache-clearing feature.

sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

After switching from fake-ip to redir-host, make sure apps aren't still holding old virtual addresses. If you clear the core's mappings while the browser still has a fake-ip cached, connections may fail temporarily. Restarting the browser is a more targeted fix than continuing to change rules.

Step 4: Treat DNS leak test results as clues, not conclusions

DNS test sites usually show the egress IP of the recursive resolver, not necessarily your device's or proxy node's IP. A difference between the resolver's region and the node's region doesn't prove that requests bypassed the proxy. First clarify your goal: preventing plaintext DNS queries to your ISP, routing app DNS through a consistent path, or sending a specific upstream through a proxy. Then check logs, connection records, and packet captures if needed.

Wrap up: get the basics working before adding policies

A reliable starting point is a set of reachable DNS upstreams, a clearly chosen resolution mode, and traffic interception that actually works. Verify the DNS service with a query to its local port, then test rules and outbound routing through an app. Add fake-ip-filter, nameserver-policy, or DNS upstream proxy policies only when you've observed a specific problem.

  • LAN domains fail: check intranet DNS, mDNS, and routing before replacing public upstreams.
  • Only one app fails: check its built-in DoH, proxy settings, and fake-ip compatibility first.
  • All domains time out: check the DNS listener, upstream reachability, and possible resolution loops.
  • DNS works but websites won't load: check node connectivity, matched rules, and destination ports. Not every problem is a DNS problem.

Change one setting at a time and save the configuration and error logs from before and after. This makes it easier to identify what actually helped and to roll back quickly after a subscription update, core upgrade, or network change.