mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-28 05:00:08 +00:00
dnstype.Resolver adds a boolean UseWithExitNode that controls whether the resolver should be used in tailscale exit node contexts (not wireguard exit nodes). If UseWithExitNode resolvers are found, they are installed as the global resolvers. If no UseWithExitNode resolvers are found, the exit node resolver continues to be installed as the global resolver. Split DNS Routes referencing UseWithExitNode resolvers are also installed. Updates #8237 Fixes tailscale/corp#30906 Fixes tailscale/corp#30907 Signed-off-by: Michael Ben-Ami <mzb@tailscale.com>
77 lines
2.7 KiB
Go
77 lines
2.7 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
// Package dnstype defines types for working with DNS.
|
|
package dnstype
|
|
|
|
//go:generate go run tailscale.com/cmd/viewer --type=Resolver --clonefunc=true
|
|
|
|
import (
|
|
"net/netip"
|
|
"slices"
|
|
)
|
|
|
|
// Resolver is the configuration for one DNS resolver.
|
|
type Resolver struct {
|
|
// Addr is the address of the DNS resolver, one of:
|
|
// - A plain IP address for a "classic" UDP+TCP DNS resolver.
|
|
// This is the common format as sent by the control plane.
|
|
// - An IP:port, for tests.
|
|
// - "https://resolver.com/path" for DNS over HTTPS; currently
|
|
// as of 2022-09-08 only used for certain well-known resolvers
|
|
// (see the publicdns package) for which the IP addresses to dial DoH are
|
|
// known ahead of time, so bootstrap DNS resolution is not required.
|
|
// - "http://node-address:port/path" for DNS over HTTP over WireGuard. This
|
|
// is implemented in the PeerAPI for exit nodes and app connectors.
|
|
// - [TODO] "tls://resolver.com" for DNS over TCP+TLS
|
|
Addr string `json:",omitempty"`
|
|
|
|
// BootstrapResolution is an optional suggested resolution for the
|
|
// DoT/DoH resolver, if the resolver URL does not reference an IP
|
|
// address directly.
|
|
// BootstrapResolution may be empty, in which case clients should
|
|
// look up the DoT/DoH server using their local "classic" DNS
|
|
// resolver.
|
|
//
|
|
// As of 2022-09-08, BootstrapResolution is not yet used.
|
|
BootstrapResolution []netip.Addr `json:",omitempty"`
|
|
|
|
// UseWithExitNode designates that this resolver should continue to be used when an
|
|
// exit node is in use. Normally, DNS resolution is delegated to the exit node but
|
|
// there are situations where it is preferable to still use a Split DNS server and/or
|
|
// global DNS server instead of the exit node.
|
|
UseWithExitNode bool `json:",omitempty"`
|
|
}
|
|
|
|
// IPPort returns r.Addr as an IP address and port if either
|
|
// r.Addr is an IP address (the common case) or if r.Addr
|
|
// is an IP:port (as done in tests).
|
|
func (r *Resolver) IPPort() (ipp netip.AddrPort, ok bool) {
|
|
if r.Addr == "" || r.Addr[0] == 'h' || r.Addr[0] == 't' {
|
|
// Fast path to avoid ParseIP error allocation for obviously not IP
|
|
// cases.
|
|
return
|
|
}
|
|
if ip, err := netip.ParseAddr(r.Addr); err == nil {
|
|
return netip.AddrPortFrom(ip, 53), true
|
|
}
|
|
if ipp, err := netip.ParseAddrPort(r.Addr); err == nil {
|
|
return ipp, true
|
|
}
|
|
return
|
|
}
|
|
|
|
// Equal reports whether r and other are equal.
|
|
func (r *Resolver) Equal(other *Resolver) bool {
|
|
if r == nil || other == nil {
|
|
return r == other
|
|
}
|
|
if r == other {
|
|
return true
|
|
}
|
|
|
|
return r.Addr == other.Addr &&
|
|
slices.Equal(r.BootstrapResolution, other.BootstrapResolution) &&
|
|
r.UseWithExitNode == other.UseWithExitNode
|
|
}
|