Fake DNS
Fake DNS is opt-in on a server (including WireGuard) or TUN configuration:
dns: servers: "tls://1.1.1.1" fake_ip: trueIt intercepts logical TCP and UDP destinations on port 53 after inbound
authentication/admission, before destination rules. It does not open a DNS
listener or intercept encrypted DNS. Intercepted DNS is answered locally or
forwarded through dns.servers, never to the application’s requested resolver.
An explicit rule override to port 53 is ordinary forwarding, not interception.
A/AAAA synthesis creates scoped mappings. Later connections to those addresses
restore the hostname before routing or hostname sniffing. A restored hostname is
resolved normally when a rule or direct connection needs a real IP; a proxy can
receive the hostname instead. With sniff: true, visible TLS SNI or HTTP Host
takes precedence for hostname rules only; the restored name remains the
connection target and is what IP rules resolve. Both hints are client-controlled,
so a different sniffed name can bypass a hostname deny rule on the restored name.
Unmapped addresses inside the receiving context’s ranges fail closed. Addresses
from another context’s non-overlapping range are not recognized and are routed
as ordinary IPs. Overlapping ranges may map to an unrelated hostname in the
receiving context. Use one shared named DNS group for inbounds serving the same clients.
Established flows keep their chosen target.
false disables the feature. An options object enables it with these defaults:
fake_ip: ipv4_range: "198.18.0.0/15" ipv6_range: null max_entries: 65536 bypass_domains: [] missing_family: forward https_records: forward state_file: null- Pools must be CIDRs with usable addresses; reserve non-conflicting ranges and route them through the same ingress. The base and base+1 addresses are reserved, as is IPv4 broadcast. Real upstream, bootstrap, proxy, configured forwarding/fallback targets, and literal rule-override addresses cannot be inside any active or retained fake range. These checks apply even to inbounds without Fake DNS or with it explicitly disabled.
- TUN interface and gateway addresses cannot overlap any active or retained pool, except its reserved base+1 address. An address inside overlapping pools must be reserved in every one of them, regardless of the TUN’s DNS context.
max_entriesbounds retained domain mappings, not the allocation range. Least-recently-used domains are evicted; sequential allocation traverses the entire range before reuse. Synthetic answers have a 60-second TTL. This is not a guarantee that a mapping remains valid for 60 seconds under pressure.bypass_domainsuses the normal hostname-mask suffix matching, including subdomains. Excluded names and IP-shaped questions are forwarded.missing_family: forwardforwards queries for a disabled family;nodatareturns an empty successful answer instead.https_records: forwardpreserves HTTPS/SVCB answers;suppressreturns empty successful answers for both types. Forwarded address hints and ECH can bypass hostname-based routing; suppression trades away those capabilities.- Other record types use real upstream exchange. Valid negative/error answers are retained. Multi-question queries receive FORMERR; TSIG/SIG(0), zone transfers, and non-query operations are refused. Synthesized answers are unsigned and do not claim DNSSEC authentication.
Named DNS groups share one pool across every referencing inbound:
- dns_group: shared-fake dns_servers: ["tls://1.1.1.1"] fake_ip: true- address: "0.0.0.0:1080" protocol: {type: socks} dns: {servers: shared-fake}Inline fake_ip creates a private context, even when servers references a
named group. Omit the inline override to share the group’s mappings. Combining
fake-enabled groups requires an explicit policy on the composed group.
Private context identity uses the server transport and configured listen addresses
(including their order), or the Unix socket path. TUN contexts use device_name
(default when omitted); WireGuard contexts use the
name/public-key identity. Changing these inputs changes
private pool and snapshot ownership.
Use a named dns_group when ownership must survive listener changes or address
reordering. An existing state file with a different owner is rejected.
Compatible reloads retain mappings, including explicit disable/re-enable under
the same group/inline identity. Pool ranges, capacity, or state-file ownership
changes require restart. Without state_file, restart loses the mappings.
Previously active synthetic ranges and endpoints remain excluded from real DNS,
carrier resolution, and configured forwarding/override targets until restart,
including after a context is removed.
With a state file, snapshots are private, atomically replaced, locked against
multiple writers, and checked for pool and context identity compatibility. Create its parent directory
before startup; protect it because the file records queried domains. State filenames
must not end in .lock (case-insensitive); that suffix is reserved for ownership locks. Cursor
reservations are persisted before issuance; a crash can lose recent mappings,
which then fail closed rather than restoring an obsolete owner. Back up or
explicitly remove incompatible state before changing its pool configuration.
Persistent families need at least two allocatable addresses, and persistent pools
are limited to 383,473 entries to fit the snapshot read limit; unusually long
context names reduce the available snapshot capacity. Reservations may
skip unused addresses after restart; Windows power-loss durability and state-file
ACLs require platform-specific verification.
Omitted servers uses system DNS. Desktop discovery is a periodically refreshed
endpoint snapshot, not the OS’s complete split/scoped DNS policy. Keep discovered
resolvers and any loopback stub’s own upstream traffic outside TUN capture to
avoid recursive interception. Android/iOS hosts must supply underlying real
dns.servers explicitly; automatic VPN system discovery is not supported.
Host-local TUN deployments should configure explicit real upstreams: native
hostname lookups can otherwise re-enter the host’s intercepted resolver.
Fake-enabled system configurations fail startup if no usable endpoints can be
discovered. Later upstream failures produce DNS failure, not a public-provider fallback.
UDP and HTTP/3 upstreams remain direct-only; TCP/TLS/HTTPS can use client chains.
DNS client chains use the configured bootstrap resolver. Downstream proxy
hostnames remain unresolved when passed through a proxy that supports remote
name resolution; Shoes cannot inspect addresses resolved by that remote proxy.
Rule downloads instead pre-resolve downstream proxies through their guarded
bootstrap resolver.
UDP truncation retries TCP only when that transport is explicitly configured.
Groups with mixed upstream settings try their remaining configured resolvers for
a complete successful or negative reply before returning a truncated answer.
The retained truncated reply is returned if fallback fails or reaches the
forwarding deadline; it still passes the real-address guards.
Local UDP DNS peers process one query at a time with bounded backpressure; a
forwarded query can delay subsequent synthetic answers until its deadline.
SOCKS, UoT, H2MUX, XUDP, Hysteria2, and TUIC preserve the original logical reply address. Snell’s reply format supports only IP addresses: hostname-addressed DNS requires a real lookup for its reply identity and fails if that lookup fails. Literal-address DNS interception remains fully local on Snell.