Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

DNS policies and FakeIP

Managed DNS is opt-in. XRAT does not change /etc/resolv.conf, system resolver settings or firewall rules outside the managed TUN lifecycle. Existing proxy-only configurations keep their current behavior.

Named resolvers

Use named resolvers to distinguish direct, proxied and bootstrap DNS traffic:

[dns]
query_strategy = "UseIP"
use_system_hosts = true
bootstrap_resolver = "bootstrap"
final_resolver = "remote"
resolvers = [
  { tag = "bootstrap", address = "udp://1.1.1.1", path = "bootstrap" },
  { tag = "remote", address = "https://dns.google/dns-query", path = "proxy" },
  { tag = "local", address = "udp://192.168.1.1", path = "direct" },
]
rules = [
  { domain = ["router.example"], domain_suffix = ["lan.example"], resolver = "local" },
]

[dns.listener]
enabled = true
host = "127.0.0.1"
port = 1053

Remove legacy dns.servers entries when migrating to named resolvers. Tags must be unique; the xrat- prefix and managed inbound tags such as socks-in, tun-in and api belong to generated internal services. Exact and suffix matchers within a rule mean OR. Rules are ordered before the final resolver. Explicit hosts and successful system-hosts answers take precedence. Xray rejects overlapping rules because its DNS server selection cannot preserve the same first-match contract as sing-box. Sing-box named policies require an explicit UseIP, UseIPv4 or UseIPv6 strategy; UseSystem has no exact mapping. Structured resolver/rule arrays are edited in TOML rather than the scalar settings editor.

The bootstrap resolver must use a literal-IP UDP endpoint and path = "bootstrap". XRAT uses bounded A/AAAA queries before replacing a managed session, validates transactions and questions, follows answer-section CNAME chains, and rejects truncated or unsuccessful responses. TCP fallback for this bootstrap step is unsupported. Proxy hostname pinning preserves TLS SNI and transport Host identity. Sing-box uses the bootstrap tag as its explicit domain resolver. Neither backend falls back to the host resolver for configured named bootstrap.

Resolver endpoints accept UDP, TCP and HTTPS on both engines, and TLS on sing-box. Xray rejects DNS-over-TLS. A +local spelling is accepted for migration; the typed path controls egress. Endpoint credentials, query parameters and fragments are rejected. DNS-over-HTTPS keeps its hostname for certificate verification. DNS failure does not authorize fallback from a proxy resolver to direct traffic.

The listener serves UDP and TCP on a loopback IP. Choose an unused port and point applications at it explicitly. Managed TUN additionally intercepts port 53. Encrypted DNS chosen independently by an application is outside that interception. Test and scan processes use real resolver policies without TUN capture or FakeIP allocation.

Xray DNS outbound

Xray 26.7.11 or newer supports an explicit DNS outbound:

[dns.outbound]
tag = "xrat-dns-out"
user_level = 0
rules = [
  { action = "return", domain = ["full:blocked.example"], query_type = [1, 28], response_code = 5 },
  { action = "hijack" },
]

Rules use Xray domain matcher syntax and numeric DNS record types. hijack answers through the configured internal DNS client; direct forwards the DNS message; drop returns no answer; return constructs a response with the chosen rcode (0..15). The default internal outbound remains generated when TUN or the listener needs it. Explicit configuration replaces that outbound instead of adding a second competing DNS path.

Optional rewrite_network = "tcp" or "udp", rewrite_address and rewrite_port control forwarded DNS destinations. They apply to forwarding, not the internal resolver used by hijack. Configured DNS-outbound routing covers port 53 on managed proxy inbounds as well as the DNS listener. Sing-box rejects this Xray-specific block and uses its native hijack-dns action instead.

FakeIP

Enable FakeIP only after configuring named real resolvers and either the DNS listener or TUN:

[dns.fakeip]
enabled = true
ipv4_range = "198.18.0.0/15"
ipv6_range = ""
pool_size = 65535
exclude = ["router.example"]
persist = false

The IPv4 pool must be a network CIDR within 198.18.0.0/15; an optional IPv6 pool must be a ULA network CIDR. Avoid ranges used by the local network or TUN interface. DNS caching is required for domain recovery. Xray requires query_strategy = "UseIP"; family-only strategies do not allocate FakeIP. pool_size bounds Xray allocations and must fit the IPv4 CIDR. Sing-box uses its CIDR capacity and accepts only the default value for this Xray-specific field.

Explicit hosts retain real answers. Exclusions are exact hostnames: sing-box uses the final real resolver, while Xray resolves a real bootstrap snapshot before startup unless a host override exists. Refresh that snapshot by reconnecting. Xray mappings reset on restart and reject persist = true. Sing-box persistence uses a policy-specific cache with mode 0600 under XRAT’s private runtime directory (0700 on Unix); changing the resolver, pool, rules or hosts selects a different cache. Cache files contain DNS mappings and should remain private to the XRAT user.

Fake addresses work only when connections return through the managed engine. Applications that use cached fake answers after disconnect cannot reach the original destination. FakeIP does not provide a persistent kill switch.

V2Ray advanced DNS, encrypted bootstrap, suffix exclusions and system DNS ownership are explicitly unsupported by this contract.