Skip to content

DNS — mihomo

mihomo's dns: block is large and flat. The core idea: declare a primary resolver list (nameserver) and a fallback list, then filter which queries go to fallback via fallback-filter. Per-domain overrides via nameserver-policy. Optional fake-IP engine for sniffing-friendly routing.

Top-level options

FieldTypeDefaultAllowed valuesDescription
enableboolfalsetrue | falseMaster switch. When false the rest of the block is ignored and the OS resolver is used.
prefer-h3boolfalsetrue | falsePrefer DNS-over-HTTPS/3 (over QUIC) when a server URL supports both H2 and H3.
ipv6boolfalsetrue | falseResolve AAAA records. When false, only A queries are issued.
ipv6-timeoutuint100<milliseconds>Maximum time to wait for a AAAA answer before falling back to IPv4-only. 100ms is the documented default.
use-hostsboolfalsetrue | falseConsult the top-level `hosts:` map before going to network.
use-system-hostsboolfalsetrue | falseAlso consult the OS hosts file (`/etc/hosts`).
respect-rulesboolfalsetrue | falseRun the **routing rules** against DNS queries themselves. When true, a query's outbound is decided by the rules list — useful to route DNS traffic to a specific tunnel.
nameserver[]string[][<URL>]Primary resolver list. Each entry is a URL: `udp://...`, `tcp://...`, `tls://...`, `https://...`, `quic://...`, `system://`, `dhcp://<iface>`, or `rcode://...`.
fallback[]string[][<URL>]Fallback resolver list — consulted when a primary answer is filtered by `fallback-filter` (e.g. domestic-IP answer for a non-domestic query).
fallback-filterRawFallbackFilter{geoip: true, geoip-code: "CN"}RawFallbackFilterFilter that decides when to consult `fallback`. Carries `geoip`, `geoip-code`, `ipcidr`, `domain`, `geosite`.
listenstring(disabled)<host:port>If set, run a local DNS server on this address. The server obeys the same rules as the internal resolver.
enhanced-modeC.DNSModenormalnormal | redir-host | fake-ipDNS-engine mode. `normal` returns real answers; `redir-host` returns the IP but tags the connection with the original domain (for sniffing-friendly routing); `fake-ip` returns synthetic IPs from `fake-ip-range`.
fake-ip-rangestring198.18.0.1/16<CIDR>IPv4 range allocated for fake IPs (mode `fake-ip` only).
fake-ip-range6string(unset)<CIDR>Optional IPv6 range.
fake-ip-filter[]string[]<domain pattern>Domains that should **not** receive a fake IP — pass through to the real resolver instead. Wildcards supported.
fake-ip-filter-modeC.FilterModeblacklistblacklist | whitelistWhether `fake-ip-filter` is a blacklist (filtered domains skip fake-ip) or whitelist (only filtered domains get fake-ip).
fake-ip-ttlint1<seconds>TTL in seconds for fake-IP answers. Low values force clients to re-resolve often, which keeps the fake-ip mapping fresh.
default-nameserver[]string[114.114.114.114, 223.5.5.5, 8.8.8.8, 1.0.0.1][<URL>]Bootstrap resolvers used to resolve the hostnames of the entries in `nameserver`/`fallback` themselves. **Must** be plain IPs — no further resolution allowed.
cache-algorithmstringlrulru | arcEviction algorithm. `arc` (Adaptive Replacement Cache) is occasionally better for workloads with bursty access patterns.
cache-max-sizeint0 (unbounded)<int>Maximum cached entries.
nameserver-policy*orderedmap.OrderedMap[string, any]{}{<domain or rule>: <URL or [URL]>}Per-domain-pattern routing. Keys are domain patterns or `geosite:`/`rule-set:`/`+./` notations; values are resolver URLs. Higher priority than `nameserver`.
proxy-server-nameserver[]string[][<URL>]Resolvers used **specifically** to resolve proxy-server hostnames. Avoids the chicken-and-egg problem of routing a proxy hostname through the proxy that uses it.
proxy-server-nameserver-policy*orderedmap.OrderedMap[string, any]{}{<pattern>: <URL>}Per-domain override of `proxy-server-nameserver`.
direct-nameserver[]string[][<URL>]Resolvers used for DIRECT-routed destinations. Avoids leaking domestic-DNS lookups through the proxy.
direct-nameserver-follow-policyboolfalsetrue | falseApply `nameserver-policy` to `direct-nameserver` queries too.

Source: config/config.go:218-244 · pinned at v1.19.27 (5184081)

Nameserver URL schemes

The nameserver, fallback, default-nameserver, proxy-server-nameserver, and direct-nameserver lists all accept the same URL grammar:

SchemeExampleNotes
(bare IP)223.5.5.5UDP/53
udp://udp://8.8.8.8:53Explicit UDP, optional port
tcp://tcp://8.8.8.8:53DNS-over-TCP
tls://tls://1.1.1.1:853DNS-over-TLS
https://https://doh.pub/dns-queryDNS-over-HTTPS (H2)
quic://quic://dns.adguard-dns.comDNS-over-QUIC
h3://h3://1.1.1.1/dns-queryDoH over HTTP/3
system://system://OS resolver
dhcp://dhcp://eth0DHCP-provided resolver for eth0
rcode://rcode://refusedReturn a fixed RCODE

URL paths after the host can carry an #<proxy> suffix to force the DNS traffic through a named proxy:

yaml
nameserver:
  - https://cloudflare-dns.com/dns-query#proxy

nameserver-policy

The most powerful field. Keys are matchers; values are resolver URL or URL list:

yaml
nameserver-policy:
  "geosite:cn,private":           # GeoSite category match
    - 223.5.5.5
    - 114.114.114.114
  "+.cn":                         # Suffix match — note the +. prefix
    - https://doh.pub/dns-query
  "rule-set:cn":                  # Rule-set reference
    - 223.5.5.5
  "www.example.com":              # Exact domain
    - https://example-dns.com/dns-query

nameserver-policy is consulted before the main nameserver list, so matched domains skip the standard resolver entirely.

fallback-filter

Decides when a primary answer is "suspicious" and triggers a fallback query:

yaml
fallback-filter:
  geoip: true                # Apply GeoIP filtering
  geoip-code: CN             # Treat answers in this country as suspicious-foreign-domain
  ipcidr:
    - 240.0.0.0/4            # Specific CIDR triggers
  geosite:
    - gfw                    # GeoSite categories that must always go to fallback
  domain:
    - +.google.com           # Domain patterns that must always go to fallback

When a primary answer matches geoip-code/ipcidr and the query domain doesn't match geosite/domain, the result is rejected and the fallback list is queried.

Examples

Classic CN-bypass DNS:

yaml
dns:
  enable: true
  prefer-h3: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - '+.lan'
    - '+.local'
    - 'localhost.ptlogin2.qq.com'

  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29

  nameserver:
    - https://doh.pub/dns-query
    - https://dns.alidns.com/dns-query

  fallback:
    - https://1.1.1.1/dns-query
    - https://dns.google/dns-query
    - tls://8.8.4.4:853

  fallback-filter:
    geoip: true
    geoip-code: CN
    geosite:
      - gfw

  nameserver-policy:
    'geosite:cn,private':
      - https://doh.pub/dns-query
    'geosite:gfw,geolocation-!cn':
      - https://1.1.1.1/dns-query
      - https://dns.google/dns-query

  proxy-server-nameserver:
    - https://doh.pub/dns-query

  direct-nameserver:
    - https://doh.pub/dns-query

Local DNS server for downstream devices:

yaml
dns:
  enable: true
  listen: 0.0.0.0:53
  enhanced-mode: redir-host
  nameserver:
    - https://1.1.1.1/dns-query

Notes

  • enhanced-mode: fake-ip is the standard mode for transparent-proxy setups. Real IP resolution happens at the proxy side, not the client side — which means sniffing-aware routing rules can see the original domain.
  • default-nameserver must contain plain IP addresses only. They are used to resolve the hostnames in nameserver / fallback themselves; allowing hostnames here would be a bootstrap cycle.
  • fake-ip-filter accepts the same domain-pattern syntax as routing rules (+.example.com for suffix, geosite:apple for category).
  • proxy-server-nameserver is critical for setups where the proxy server hostname is also a domain in your routing rules. Without it, resolving the proxy hostname can recursively try to route through itself.
  • direct-nameserver keeps direct-bound queries from leaking to the fallback (overseas) resolver. Useful when fallback is your only uncensored path.

Cross-core notes

  • Xray-core uses a flat block with URL-string-or-object servers and per-server domains / expectedIPs / unexpectedIPs. See DNS — Xray-core.
  • sing-box uses typed servers (type: "https", type: "fakeip", …) and a structured DNS rule chain with explicit actions. See DNS — sing-box.

Source: config/config.go:218-244 · v1.19.27 (5184081)

Core Tutorial by Argsment