Skip to content

DNS

While the tunnel is running, DNS queries from the system are answered by MeowX. How they are answered — fake addresses or real ones, and which upstream servers are asked — is configured in the dns: section, plus the app’s DNS mode setting.

dns:
enable: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- +.lan
- +.local
default-nameserver:
- 192.0.2.53
nameserver:
- https://dns.example.com/dns-query#Proxy
direct-nameserver:
- https://dns.example.net/dns-query
nameserver-policy:
geosite:cn: https://dns.example.net/dns-query
+.example.com: [tls://dns.example.net]
Key Type Default Description
enable bool — Always set to true by MeowX; see DNS mode.
enhanced-mode string see DNS mode fake-ip or redir-host.
fake-ip-range string 198.18.0.1/16 IPv4 range for fake addresses.
fake-ip-filter list see below Domains that get real answers in fake-ip mode.
ipv6 bool false Whether real IPv6 (AAAA) answers are returned. See ipv6.
nameserver list 1.1.1.1, 8.8.8.8 Main upstream servers.
default-nameserver list [] IP-address servers used to resolve the host names of other DNS servers.
direct-nameserver list [] Servers for resolving domains that go DIRECT.
proxy-server-nameserver list [] Servers for resolving your nodes’ server addresses.
nameserver-policy map {} Per-domain or per-GeoSite servers.

Top-level hosts is covered below.

The app’s DNS mode setting has three choices:

Setting Effective enhanced-mode
Follow subscription (default) The subscription’s own dns.enhanced-mode. If the subscription doesn’t set one, redir-host.
Redir-Host redir-host, whatever the subscription says.
Fake-IP fake-ip, whatever the subscription says.

When it builds the active configuration, MeowX:

  • sets dns.enable: true (MeowX always handles DNS while the tunnel runs);
  • writes the effective enhanced-mode;
  • in fake-ip mode, adds fake-ip-range: 198.18.0.1/16 and a default fake-ip-filter if the file has none. The default filter is +.lan, +.local, +.msftconnecttest.com, +.msftncsi.com, *.battlenet.com.cn, time.*.com, time.*.apple.com, time-ios.apple.com, +.ntp.org, +.pool.ntp.org, mtalk.google.com, *.mtalk.google.com, alt1-mtalk.google.com, alt2-mtalk.google.com;
  • if the file has no dns section at all, uses a built-in fallback section with public DNS-over-HTTPS servers.

Everything else in your dns section is kept exactly as written, including the order of nameserver-policy.

Each domain gets a unique address from fake-ip-range, and connections to that address are mapped back to the domain. Rules always see the domain, and no real DNS lookup happens unless a rule needs the IP (see Rules → no-resolve) or the connection goes DIRECT.

  • Fake answers have a TTL of 1 second.
  • Up to 8192 domains are mapped at once; older mappings are reused when the pool is full.
  • AAAA, HTTPS and SVCB queries for fake-ip domains always get an empty answer, regardless of dns.ipv6. This stops apps from bypassing the fake address through IPv6 hints.
  • Domains matching fake-ip-filter get real answers. Filter patterns use the same syntax as a domain rule provider (example.com, *.example.com, +.example.com, .example.com). geosite: and rule-set: entries in the filter are not supported and are ignored.
  • fake-ip-range must be a valid IPv4 range; if it can’t be parsed, fake-ip is off and DNS behaves like redir-host. Keep the default unless you have a reason to change it. On Mac, a range inside a local network range (such as 10.0.0.0/8 or 192.168.0.0/16) would be excluded from the tunnel.
  • If an app reuses a fake address it cached before the tunnel restarted, MeowX tries to recover the domain by sniffing; if it can’t, the connection is refused instead of being sent to a meaningless address.

Queries are forwarded to the upstream servers and real addresses are returned. MeowX remembers which domain each answer belonged to (the most recent 4096 answers), so a later connection to that IP can still be matched by domain rules. Sniffing is tried first, and covers apps that use their own DNS.

For each query, the first step that applies wins:

  1. DNS overrides set in the app.
  2. hosts (A and AAAA only).
  3. fake-ip, in fake-ip mode, for domains not in fake-ip-filter.
  4. IPv6 off: AAAA, HTTPS and SVCB queries get an empty answer when dns.ipv6 is false.
  5. Upstream: nameserver-policy, or else nameserver. If every upstream fails, the answer is SERVFAIL.

Plain UDP DNS queries to port 53 inside the tunnel are answered this way. Apps that use their own encrypted DNS (DoH / DoT) bypass it; sniffing still recovers the domain for routing in that case.

Form Protocol Default port
192.0.2.53, 192.0.2.53:5353 UDP 53
udp://192.0.2.53 UDP 53
tcp://192.0.2.53 DNS over TCP 53
tls://dns.example.com DNS over TLS 853
https://dns.example.com/dns-query DNS over HTTPS 443 (path defaults to /dns-query)
  • A server given by host name is resolved through default-nameserver first; without one, the system resolver is used.
  • Not supported: quic:// (DoQ), h3://, dhcp://, system, and IPv6 literal addresses for UDP / TCP / DoT servers. Such entries don’t work; remove them.
  • Parameters after & (such as &h3=true, &ecs=…) are ignored.
  • If none of the nameserver entries is usable, MeowX falls back to 1.1.1.1 and 8.8.8.8.

When a list has several servers, MeowX queries them in parallel and takes the first good answer (SERVFAIL and REFUSED don’t count as good). It then remembers the fastest server and asks it first next time, bringing in the others if it doesn’t answer within 1.5 seconds. Each query has a 5-second budget. Answers are cached for their TTL, at most one hour.

Append # and a proxy group or node name to send that server’s queries through the proxy:

dns:
nameserver:
- https://dns.example.com/dns-query#Proxy
- tls://192.0.2.1#🇯🇵 Japan
Suffix Effect
#GroupOrNodeName Query through that group or node. The name is case-sensitive and may contain emoji.
#DIRECT Query directly (same as no suffix).
#RULES Accepted; currently behaves like #DIRECT.

Through a proxy, udp:// and plain servers are queried with DNS over TCP. DoT and DoH through a proxy use MeowX’s own TLS client, which requires the DNS server to support TLS 1.3.

Used only to resolve the host names of other DNS servers (for example the dns.example.com in https://dns.example.com/dns-query). Entries must be IP addresses; host-name entries are ignored.

Used when a connection goes DIRECT and MeowX has to resolve its domain itself (for example in fake-ip mode). If empty, default-nameserver is used, and if that is empty too, nameserver. nameserver-policy is not applied to these lookups.

Typical use: resolve directly-connected (often domestic) sites with a nearby resolver while nameserver goes through the proxy.

Used to resolve the server addresses of your nodes. If empty, direct-nameserver is used, then default-nameserver, then nameserver. nameserver-policy is not applied to these lookups.

Sends matching domains to specific servers instead of nameserver. Values can be a single server or a list.

dns:
nameserver-policy:
"geosite:cn,private": https://dns.example.net/dns-query
"+.example.com": [tls://dns.example.net, 192.0.2.53]
"www.example.com": 192.0.2.54
Key form Matches
example.com Exactly that domain.
*.example.com Exactly one level of subdomain.
+.example.com The domain and all subdomains.
.example.com All subdomains, not the domain itself.
geosite:cat1,cat2 Domains in any of the listed GeoSite categories.
rule-set:… Not supported (ignored).

Order works as in mihomo:

  • Consecutive domain keys form one group. Within a group, the most specific match wins regardless of order — in the example, www.example.com uses 192.0.2.54 even though +.example.com is written first.
  • Each geosite: key (and each ignored rule-set: key) is its own step and splits domain groups apart.
  • Steps are checked in the order written; the first match decides.

The policy applies to queries answered by the tunnel’s DNS and to lookups MeowX makes for rules. It does not apply to direct-nameserver and proxy-server-nameserver lookups.

Top-level hosts maps a domain to fixed addresses:

hosts:
router.example.com: 192.168.1.1
dual.example.com: [192.0.2.10, 2001:db8::10]
  • Keys match the domain exactly. Wildcard keys (*.example.com, +.example.com) are not supported.
  • Values must be IP addresses (one or a list, IPv4 and/or IPv6). Domain-name values (aliases) are not supported, and an entry without any valid IP is ignored.
  • A query for a hosts domain is answered from hosts with a 10-second TTL: A from the IPv4 entries, AAAA from the IPv6 entries. If there’s no entry of the requested family, the answer is empty; the upstream isn’t asked.
  • hosts is also used when MeowX resolves domains itself (for DIRECT connections, IP rules and node addresses).
  • dns.use-hosts and dns.use-system-hosts are ignored; hosts always applies.

dns.ipv6 controls whether real IPv6 addresses are handed to apps:

  • false (default): AAAA, HTTPS and SVCB queries get an empty answer (outside of hosts and DNS overrides), so apps connect over IPv4.
  • true: in redir-host mode, and for fake-ip-filter domains, AAAA / HTTPS / SVCB queries are forwarded upstream.
  • In fake-ip mode, fake-ip domains never get AAAA answers either way.

These dns keys are read by mihomo but have no effect in MeowX:

Key Note
fallback, fallback-filter Not supported. A warning is logged if fallback is set. Use nameserver-policy to split domestic and foreign domains instead.
listen MeowX’s DNS listens inside the tunnel only.
use-hosts, use-system-hosts hosts always applies; system hosts are not read.
respect-rules Upstream servers are reached directly unless they have a #group suffix.
prefer-h3, cache-algorithm, fake-ip-filter-mode, fake-ip-range6 Not supported.