Documentation
¶
Overview ¶
Package dnsresolvecache persists successful DNS resolutions from net/dnscache to disk, one JSON file per hostname, so that a later tailscaled boot with misconfigured DNS can still find last-known-good IPs for critical hostnames such as the control plane. It is intended to eventually replace the DERP-based bootstrap DNS in net/dnsfallback.
To keep bogus answers (say, from a captive portal's DNS server) off disk, a resolution is not written when it happens. It is instead held in memory as pending until a TLS connection to one of the resolution's IPs presents a certificate chain that is valid for that hostname; only then is the record flushed to disk. The chain is checked independently of the connection's own TLS configuration, which for the control plane's Noise connection deliberately tolerates interception. A captive portal cannot present a valid certificate for a hostname it is impersonating, so its answers are never persisted. That is also the invalidation contract: a hostname's file is only ever written or replaced by a newer resolution that was itself verified this way; there is no expiry. Verification currently comes from dnscache.TLSDialer (used by the control plane connection), so other hostnames resolve normally but are not persisted.
A file is rewritten only when its contents change, so its modification time records when the answer last changed, not when it was last confirmed.
This package is linked into tailscaled by default and omitted from tsnet. Nothing here is automatic for tsnet-based apps: to use it, they must both blank-import this package and configure the cache directory themselves by invoking dnscache.HookSetCacheDir, which is otherwise only called by tailscaled at startup.
This package's state is process-global. In tsnet-based apps running multiple tsnet.Server instances in one process, only the cache directory from the first dnscache.HookSetCacheDir call is used; later calls are ignored and all servers share the first cache.