mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-26 04:20:33 +00:00
feature/featuretags: add option to turn off DNS
Saves 328 KB (2.5%) off the minimal binary. For IoT devices that don't need MagicDNS (e.g. they don't make outbound connections), this provides a knob to disable all the DNS functionality. Rather than a massive refactor today, this uses constant false values as a deadcode sledgehammer, guided by shotizam to find the largest DNS functions which survived deadcode. A future refactor could make it so that the net/dns/resolver and publicdns packages don't even show up in the import graph (along with their imports) but really it's already pretty good looking with just these consts, so it's not at the top of my list to refactor it more soon. Also do the same in a few places with the ACME (cert) functionality, as I saw those while searching for DNS stuff. Updates #12614 Change-Id: I8e459f595c2fde68ca16503ff61c8ab339871f97 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
a45473c4c5
commit
bcd79b161a
@@ -20,6 +20,7 @@ import (
|
||||
"time"
|
||||
|
||||
"tailscale.com/control/controlknobs"
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/health"
|
||||
"tailscale.com/net/dns/resolver"
|
||||
"tailscale.com/net/netmon"
|
||||
@@ -71,6 +72,9 @@ type Manager struct {
|
||||
//
|
||||
// knobs may be nil.
|
||||
func NewManager(logf logger.Logf, oscfg OSConfigurator, health *health.Tracker, dialer *tsdial.Dialer, linkSel resolver.ForwardLinkSelector, knobs *controlknobs.Knobs, goos string) *Manager {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil
|
||||
}
|
||||
if dialer == nil {
|
||||
panic("nil Dialer")
|
||||
}
|
||||
@@ -97,7 +101,12 @@ func NewManager(logf logger.Logf, oscfg OSConfigurator, health *health.Tracker,
|
||||
}
|
||||
|
||||
// Resolver returns the Manager's DNS Resolver.
|
||||
func (m *Manager) Resolver() *resolver.Resolver { return m.resolver }
|
||||
func (m *Manager) Resolver() *resolver.Resolver {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil
|
||||
}
|
||||
return m.resolver
|
||||
}
|
||||
|
||||
// RecompileDNSConfig recompiles the last attempted DNS configuration, which has
|
||||
// the side effect of re-querying the OS's interface nameservers. This should be used
|
||||
@@ -111,6 +120,9 @@ func (m *Manager) Resolver() *resolver.Resolver { return m.resolver }
|
||||
//
|
||||
// It returns [ErrNoDNSConfig] if [Manager.Set] has never been called.
|
||||
func (m *Manager) RecompileDNSConfig() error {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil
|
||||
}
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if m.config != nil {
|
||||
@@ -120,6 +132,9 @@ func (m *Manager) RecompileDNSConfig() error {
|
||||
}
|
||||
|
||||
func (m *Manager) Set(cfg Config) error {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil
|
||||
}
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
return m.setLocked(cfg)
|
||||
@@ -127,6 +142,9 @@ func (m *Manager) Set(cfg Config) error {
|
||||
|
||||
// GetBaseConfig returns the current base OS DNS configuration as provided by the OSConfigurator.
|
||||
func (m *Manager) GetBaseConfig() (OSConfig, error) {
|
||||
if !buildfeatures.HasDNS {
|
||||
panic("unreachable")
|
||||
}
|
||||
return m.os.GetBaseConfig()
|
||||
}
|
||||
|
||||
@@ -559,6 +577,9 @@ func (m *Manager) HandleTCPConn(conn net.Conn, srcAddr netip.AddrPort) {
|
||||
}
|
||||
|
||||
func (m *Manager) Down() error {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil
|
||||
}
|
||||
m.ctxCancel()
|
||||
if err := m.os.Close(); err != nil {
|
||||
return err
|
||||
@@ -568,6 +589,9 @@ func (m *Manager) Down() error {
|
||||
}
|
||||
|
||||
func (m *Manager) FlushCaches() error {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil
|
||||
}
|
||||
return flushCaches()
|
||||
}
|
||||
|
||||
@@ -577,6 +601,9 @@ func (m *Manager) FlushCaches() error {
|
||||
//
|
||||
// health must not be nil
|
||||
func CleanUp(logf logger.Logf, netMon *netmon.Monitor, health *health.Tracker, interfaceName string) {
|
||||
if !buildfeatures.HasDNS {
|
||||
return
|
||||
}
|
||||
oscfg, err := NewOSConfigurator(logf, health, policyclient.Get(), nil, interfaceName)
|
||||
if err != nil {
|
||||
logf("creating dns cleanup: %v", err)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
"tailscale.com/control/controlknobs"
|
||||
"tailscale.com/feature"
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/health"
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/types/logger"
|
||||
@@ -63,7 +64,7 @@ var (
|
||||
//
|
||||
// The health tracker may be nil; the knobs may be nil and are ignored on this platform.
|
||||
func NewOSConfigurator(logf logger.Logf, health *health.Tracker, _ policyclient.Client, _ *controlknobs.Knobs, interfaceName string) (ret OSConfigurator, err error) {
|
||||
if distro.Get() == distro.JetKVM {
|
||||
if !buildfeatures.HasDNS || distro.Get() == distro.JetKVM {
|
||||
return NewNoopManager()
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/util/dnsname"
|
||||
)
|
||||
@@ -158,6 +159,10 @@ func (a OSConfig) Equal(b OSConfig) bool {
|
||||
// Fixes https://github.com/tailscale/tailscale/issues/5669
|
||||
func (a OSConfig) Format(f fmt.State, verb rune) {
|
||||
logger.ArgWriter(func(w *bufio.Writer) {
|
||||
if !buildfeatures.HasDNS {
|
||||
w.WriteString(`{DNS-unlinked}`)
|
||||
return
|
||||
}
|
||||
w.WriteString(`{Nameservers:[`)
|
||||
for i, ns := range a.Nameservers {
|
||||
if i != 0 {
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
)
|
||||
|
||||
// dohOfIP maps from public DNS IPs to their DoH base URL.
|
||||
@@ -163,6 +165,9 @@ const (
|
||||
|
||||
// populate is called once to initialize the knownDoH and dohIPsOfBase maps.
|
||||
func populate() {
|
||||
if !buildfeatures.HasDNS {
|
||||
return
|
||||
}
|
||||
// Cloudflare
|
||||
// https://developers.cloudflare.com/1.1.1.1/ip-addresses/
|
||||
addDoH("1.1.1.1", "https://cloudflare-dns.com/dns-query")
|
||||
|
||||
@@ -12,10 +12,14 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/health"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if !buildfeatures.HasDNS {
|
||||
return
|
||||
}
|
||||
health.RegisterDebugHandler("dnsfwd", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
n, _ := strconv.Atoi(r.FormValue("n"))
|
||||
if n <= 0 {
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
dns "golang.org/x/net/dns/dnsmessage"
|
||||
"tailscale.com/control/controlknobs"
|
||||
"tailscale.com/envknob"
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/health"
|
||||
"tailscale.com/net/dns/publicdns"
|
||||
"tailscale.com/net/dnscache"
|
||||
@@ -249,6 +250,9 @@ type forwarder struct {
|
||||
}
|
||||
|
||||
func newForwarder(logf logger.Logf, netMon *netmon.Monitor, linkSel ForwardLinkSelector, dialer *tsdial.Dialer, health *health.Tracker, knobs *controlknobs.Knobs) *forwarder {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil
|
||||
}
|
||||
if netMon == nil {
|
||||
panic("nil netMon")
|
||||
}
|
||||
@@ -750,6 +754,9 @@ var optDNSForwardUseRoutes = envknob.RegisterOptBool("TS_DEBUG_DNS_FORWARD_USE_R
|
||||
//
|
||||
// See tailscale/tailscale#12027.
|
||||
func ShouldUseRoutes(knobs *controlknobs.Knobs) bool {
|
||||
if !buildfeatures.HasDNS {
|
||||
return false
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "android", "ios":
|
||||
// On mobile platforms with lower memory limits (e.g., 50MB on iOS),
|
||||
|
||||
@@ -25,6 +25,8 @@ import (
|
||||
dns "golang.org/x/net/dns/dnsmessage"
|
||||
"tailscale.com/control/controlknobs"
|
||||
"tailscale.com/envknob"
|
||||
"tailscale.com/feature"
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/health"
|
||||
"tailscale.com/net/dns/resolvconffile"
|
||||
"tailscale.com/net/netaddr"
|
||||
@@ -254,6 +256,9 @@ func New(logf logger.Logf, linkSel ForwardLinkSelector, dialer *tsdial.Dialer, h
|
||||
func (r *Resolver) TestOnlySetHook(hook func(Config)) { r.saveConfigForTests = hook }
|
||||
|
||||
func (r *Resolver) SetConfig(cfg Config) error {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil
|
||||
}
|
||||
if r.saveConfigForTests != nil {
|
||||
r.saveConfigForTests(cfg)
|
||||
}
|
||||
@@ -279,6 +284,9 @@ func (r *Resolver) SetConfig(cfg Config) error {
|
||||
// Close shuts down the resolver and ensures poll goroutines have exited.
|
||||
// The Resolver cannot be used again after Close is called.
|
||||
func (r *Resolver) Close() {
|
||||
if !buildfeatures.HasDNS {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-r.closed:
|
||||
return
|
||||
@@ -296,6 +304,9 @@ func (r *Resolver) Close() {
|
||||
const dnsQueryTimeout = 10 * time.Second
|
||||
|
||||
func (r *Resolver) Query(ctx context.Context, bs []byte, family string, from netip.AddrPort) ([]byte, error) {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil, feature.ErrUnavailable
|
||||
}
|
||||
metricDNSQueryLocal.Add(1)
|
||||
select {
|
||||
case <-r.closed:
|
||||
@@ -323,6 +334,9 @@ func (r *Resolver) Query(ctx context.Context, bs []byte, family string, from net
|
||||
// GetUpstreamResolvers returns the resolvers that would be used to resolve
|
||||
// the given FQDN.
|
||||
func (r *Resolver) GetUpstreamResolvers(name dnsname.FQDN) []*dnstype.Resolver {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil
|
||||
}
|
||||
return r.forwarder.GetUpstreamResolvers(name)
|
||||
}
|
||||
|
||||
@@ -351,6 +365,9 @@ func parseExitNodeQuery(q []byte) *response {
|
||||
// and a nil error.
|
||||
// TODO: figure out if we even need an error result.
|
||||
func (r *Resolver) HandlePeerDNSQuery(ctx context.Context, q []byte, from netip.AddrPort, allowName func(name string) bool) (res []byte, err error) {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil, feature.ErrUnavailable
|
||||
}
|
||||
metricDNSExitProxyQuery.Add(1)
|
||||
ch := make(chan packet, 1)
|
||||
|
||||
@@ -427,6 +444,9 @@ var debugExitNodeDNSNetPkg = envknob.RegisterBool("TS_DEBUG_EXIT_NODE_DNS_NET_PK
|
||||
// response contains the pre-serialized response, which notably
|
||||
// includes the original question and its header.
|
||||
func handleExitNodeDNSQueryWithNetPkg(ctx context.Context, logf logger.Logf, resolver *net.Resolver, resp *response) (res []byte, err error) {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil, feature.ErrUnavailable
|
||||
}
|
||||
logf = logger.WithPrefix(logf, "exitNodeDNSQueryWithNetPkg: ")
|
||||
if resp.Question.Class != dns.ClassINET {
|
||||
return nil, errors.New("unsupported class")
|
||||
@@ -1247,6 +1267,9 @@ func (r *Resolver) respondReverse(query []byte, name dnsname.FQDN, resp *respons
|
||||
// respond returns a DNS response to query if it can be resolved locally.
|
||||
// Otherwise, it returns errNotOurName.
|
||||
func (r *Resolver) respond(query []byte) ([]byte, error) {
|
||||
if !buildfeatures.HasDNS {
|
||||
return nil, feature.ErrUnavailable
|
||||
}
|
||||
parser := dnsParserPool.Get().(*dnsParser)
|
||||
defer dnsParserPool.Put(parser)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user