Separate DNS resolution, traffic routing, and traffic capture

Clash DNS configuration resolves domain names to IP addresses or, in Fake-IP mode, maps domains to virtual addresses. Rules determine which policy handles a connection; the system proxy and TUN determine which connections reach the core. These layers interact, but they are not interchangeable: setting a public DNS server does not mean browser requests go through a proxy, and enabling TUN does not mean all encrypted DNS traffic is captured.

This guide focuses on mihomo, the successor to Clash Meta. Traditional Clash and different clients do not support exactly the same fields, especially tun and proxy-server-nameserver. Before troubleshooting, check the client’s About page or core information for the actual core name and version—don’t rely on the client’s product name alone.

  • DNS request source: An application, the system resolver, or DNS traffic on port 53 captured by TUN.
  • DNS upstreams: The resolvers configured in lists such as nameserver and fallback.
  • Application traffic route: Determined by rules and proxy policies, not directly by the DNS server’s location.

The dns block: start with a minimal, testable example

For troubleshooting, start with redir-host so you can inspect real addresses. Once you’ve confirmed the upstream is reachable, switch to Fake-IP if needed. This example serves DNS on 127.0.0.1:1053; port 1053 is just an example, not a required default for all clients.

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: redir-host
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  nameserver:
    - https://dns.alidns.com/dns-query
  fallback:
    - https://1.1.1.1/dns-query
  fallback-filter:
    geoip: true
    geoip-code: CN
    ipcidr:
      - 240.0.0.0/4
FieldWhat the example doesWhat to check
enableEnables the core DNS moduleCheck startup logs for DNS initialization errors
listenListens on port 1053 at the loopback addressCheck whether the port is already in use and whether test queries target the right port
ipv6This example does not return AAAA recordsThis does not disable IPv6 networking in the operating system
enhanced-modeUses real-IP resolution modeReturning virtual addresses in Fake-IP mode is expected
default-nameserverResolves the hostnames of DNS upstreamsCheck whether the bootstrap resolver itself is reachable

listen: 127.0.0.1:1053 accepts connections only from the local machine, making it suitable for desktop testing. Changing it to 0.0.0.0:1053 exposes the listener more broadly. If you need to serve devices on your LAN, restrict access with firewall rules to avoid exposing the resolver to untrusted networks.

default-nameserver is not a “third group of backup servers” for regular queries. If an upstream is configured as https://dns.alidns.com/dns-query, the core first needs to resolve that hostname to an IP address. The example uses a numeric address for bootstrapping, so the resolver does not need to rely on itself to start. Regular UDP bootstrap queries are not encrypted like DoH; choose an approach based on your network’s privacy and connectivity requirements.

nameserver and fallback: candidate results, not simple primary and backup servers

nameserver provides regular resolution results

nameserver is the list of regular upstream resolvers. Unless you have configured domain-specific policies, ordinary queries use this list. Multiple addresses do not mean the core tries them strictly in order; it may query several upstreams in parallel and use an available result. Don’t rely on list order to route domains differently.

fallback provides an alternative set of candidate results

With fallback enabled, don’t assume it is queried only after a nameserver times out. In the typical nameserver/fallback mechanism, both groups may be queried in parallel, and fallback-filter helps determine which result to use. This can reduce wait times when the alternative result is needed, but it also means the other group of resolvers may receive the query.

Whether a connection goes through a proxy is a separate issue. Adding https://1.1.1.1/dns-query to fallback does not automatically route that DoH connection through a proxy node. Its actual egress depends on the core version, how the DNS upstream is specified, and related routing settings. If the service is unreachable on your network, resolve the connectivity issue first instead of repeatedly changing filter conditions.

  • To test basic resolution, start with one reachable nameserver and temporarily remove fallback and its filters.
  • If you need to choose between two sets of results, add fallback and configure its filters explicitly.
  • To send specific domains to a particular resolver, use nameserver-policy rather than guessing based on list order.

fallback-filter: how geoip, ipcidr, and domain conditions work

fallback-filter determines when to use fallback results. It is not a firewall rule or a rule for routing application traffic through a proxy. Setting geoip-code: CN does not guarantee that mainland Chinese websites connect directly or that sites in other regions use a proxy.

geoip: check the location associated with nameserver results

With geoip: true and geoip-code: CN, results returned by nameserver that are classified as CN are generally retained; when they do not meet that condition, fallback results are more likely to be used. The decision depends on the GeoIP data used by the core, not the DNS provider’s location. Missing or outdated data, or changes in CDN address attribution, can affect the result.

ipcidr: switch result sources for specific address ranges

In this example, 240.0.0.0/4 sends nameserver results within that range to fallback. It is only an example of a suspicious address range and will not catch every incorrect resolution. Don’t add all private ranges, such as 192.168.0.0/16, to the filter: corporate intranets, router admin pages, and local domains may legitimately resolve to private addresses.

domain: force fallback for specific domains

Unlike IP-based conditions, domain filters can select fallback at the domain level. This separate example disables GeoIP checks and applies the selection logic only to the reserved example domain example.com and its subdomains. In a real configuration, use domains that actually need this behavior.

dns:
  fallback-filter:
    geoip: false
    domain:
      - '+.example.com'

domain, ipcidr, and enabled GeoIP checks can each trigger fallback; all three conditions do not need to match at once. If you want only certain domains to use the alternative upstream group, explicitly disable any unneeded GeoIP condition and check the full configuration for other filters.

nameserver-policy and node hostnames: avoid DNS resolution loops

LAN hostnames generally should not be sent to public resolvers. In mihomo, use nameserver-policy to assign an upstream to specific domains. The address 192.168.1.1 below only works on networks where that address is a local DNS server. Don’t copy it as-is if your gateway is 192.168.50.1.

dns:
  nameserver-policy:
    '+.home.arpa':
      - 192.168.1.1
  proxy-server-nameserver:
    - 223.5.5.5
    - 119.29.29.29

home.arpa is a special-use domain for home networks. Assigning it a separate policy lets a local resolver handle it instead of relying on public fallback resolvers to guess local records. Once a policy matches, the domain follows its dedicated resolution path, so don’t assume it still follows the general nameserver/fallback selection process exactly.

proxy-server-nameserver resolves the hostnames of proxy node servers. This is different from choosing which node to use for queries to destination websites. If DoH requires a proxy connection while the proxy node’s hostname can only be resolved through that DoH service, the configuration has a startup dependency loop. Providing a reachable, independent resolution path for node hostnames reduces this risk. Check support for the field against your actual mihomo version.

Don’t add several routing options at once to fix a single resolution loop. First confirm that the node hostname resolves and that a connection to the node can be established; then decide whether regular DNS should follow application rules. After editing, inspect the final runtime configuration generated by the client to make sure subscription overrides haven’t removed the new fields.

Correct placement and protocol syntax for dns-hijack with TUN

dns-hijack belongs in the top-level tun block, not in dns. It redirects matching DNS traffic that has already entered TUN to the core’s DNS module. This is a common mihomo configuration; before enabling it, make sure the client has permission to create a virtual network interface and modify routes.

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - 'any:53'
    - 'tcp://any:53'
  • any:53: matches UDP DNS requests on port 53 that enter TUN.
  • tcp://any:53: also matches TCP port 53, covering TCP queries and retries after some truncated responses.
  • auto-route: configures the relevant routes automatically; it does not guarantee that local network traffic enters TUN on every platform.
  • auto-detect-interface: attempts to identify the egress interface; check the actual route in multi-adapter setups or environments with another VPN or complex routing.

dns-hijack does not change the system DNS address to 127.0.0.1:1053, nor does it mean you should change the hijack target to port 1053. The former matches requests originally sent to port 53; dns.listen is a separate DNS listening endpoint. They serve different purposes and can be used together.

Why do other DNS connections still appear when hijacking is enabled?

DoH typically uses HTTPS on port 443, DoT usually uses TCP port 853, and DoQ uses UDP port 853. These are not regular DNS requests on port 53, so the two settings above cannot intercept and decrypt them directly. When a browser uses Secure DNS, Android uses Private DNS, or an app has its own resolver, queries may still appear as encrypted application traffic.

Also, traffic to a router on the same subnet may go directly through the physical interface without entering TUN. Check the platform’s routes and system DNS address to confirm the capture path; don’t rely on an enabled toggle alone. If you temporarily disable encrypted DNS in an app to troubleshoot, note the original setting and restore it afterward if needed.

Test with commands: check the listener, then upstreams, then traffic capture

These commands illustrate a test procedure; they are not results measured on a particular network. Keep redir-host enabled initially to avoid Fake-IP addresses obscuring real resolution results. Change one group of fields at a time, then reload the configuration.

Step 1: Query the core’s DNS listener directly

On macOS or Linux, use a terminal with dig to test UDP and TCP separately. On Windows, run the same commands in an environment with the required tools installed; the built-in nslookup can also be used in interactive mode with a custom port.

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
nslookup
server 127.0.0.1
set port=1053
set type=A
example.com
exit

A NOERROR response with an A record in the ANSWER section means that query resolved an address. SERVFAIL indicates a failure in the resolution chain; on timeout, also check the listener, upstreams, and firewall. A NOERROR response without an A record is not necessarily a failure—the domain may not have an A record.

Step 2: Isolate upstream and filter issues

  1. Temporarily remove fallback, keep a single nameserver, and query the same domain again.
  2. Temporarily set the fallback service you want to test as the only nameserver and confirm that it can resolve queries on its own.
  3. Restore both upstream groups, then enable the GeoIP, IP range, or domain conditions one at a time and observe the results.
  4. Use logs to look for upstream connection errors, timeouts, and configuration loading errors. Don’t attribute every issue to DNS poisoning.

Step 3: Test TUN, not the listener again

Querying 127.0.0.1:1053 directly proves only that the listener is available; it does not prove that TUN hijacking works. To test capture, have the system or an app send a request to port 53 on a regular DNS address while you monitor core logs and connection details. If packet capture is available, check whether the original query still leaves through the physical interface. Disable browser DoH during the test, and remember that local caching may prevent a query from being sent at all.

On Windows, run ipconfig /flushdns to clear the system DNS cache. On macOS, run sudo dscacheutil -flushcache and sudo killall -HUP mDNSResponder. Linux cache services vary by distribution; with systemd-resolved, run resolvectl flush-caches. These commands do not clear all browser caches or replace clearing the client’s internal DNS cache.

Common symptoms and final configuration checks

SymptomCheck firstNext step
Queries to port 1053 time outDNS module is disabled, the port is in use, or the upstream is unreachableCheck the runtime configuration and startup logs, then test one upstream on its own
Returns an address beginning with 198.18Fake-IP is enabled in the active configurationCheck the virtual address pool and TUN routes; don’t assume resolution is broken
LAN hostnames fail to resolveQueries are going to public DNS, or private addresses are being filteredSet a local resolution policy for internal domains and check the filter list
All domains time out after enabling a nodeThe node hostname and DNS egress have a dependency loopTest node hostname resolution and the node connection separately
TUN is enabled, but the browser still uses another resolverBrowser Secure DNS is enabled, or the traffic is not entering TUNCheck encrypted DNS, system DNS, and routing separately

For the final configuration, keep only fields with a clear purpose: nameserver handles regular resolution; fallback and its filters select an alternative set of results; nameserver-policy handles specific domains; and dns-hijack captures traditional DNS requests that have entered TUN. Finally, check the runtime configuration after a subscription update and restore any browser, system DNS, or logging settings changed temporarily during troubleshooting. A compact configuration that you can verify layer by layer is easier to maintain than one with ever more public DNS addresses.