controlknobs.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package controlknobs contains client options configurable from control which can be turned on
  4. // or off. The ability to turn options on and off is for incrementally adding features in.
  5. package controlknobs
  6. import (
  7. "sync/atomic"
  8. "tailscale.com/syncs"
  9. "tailscale.com/tailcfg"
  10. "tailscale.com/types/opt"
  11. )
  12. // Knobs is the set of knobs that the control plane's coordination server can
  13. // adjust at runtime.
  14. type Knobs struct {
  15. // DisableUPnP indicates whether to attempt UPnP mapping.
  16. DisableUPnP atomic.Bool
  17. // KeepFullWGConfig is whether we should disable the lazy wireguard
  18. // programming and instead give WireGuard the full netmap always, even for
  19. // idle peers.
  20. KeepFullWGConfig atomic.Bool
  21. // RandomizeClientPort is whether control says we should randomize
  22. // the client port.
  23. RandomizeClientPort atomic.Bool
  24. // OneCGNAT is whether the the node should make one big CGNAT route
  25. // in the OS rather than one /32 per peer.
  26. OneCGNAT syncs.AtomicValue[opt.Bool]
  27. // ForceBackgroundSTUN forces netcheck STUN queries to keep
  28. // running in magicsock, even when idle.
  29. ForceBackgroundSTUN atomic.Bool
  30. // DisableDeltaUpdates is whether the node should not process
  31. // incremental (delta) netmap updates and should treat all netmap
  32. // changes as "full" ones as tailscaled did in 1.48.x and earlier.
  33. DisableDeltaUpdates atomic.Bool
  34. // PeerMTUEnable is whether the node should do peer path MTU discovery.
  35. PeerMTUEnable atomic.Bool
  36. // DisableDNSForwarderTCPRetries is whether the DNS forwarder should
  37. // skip retrying truncated queries over TCP.
  38. DisableDNSForwarderTCPRetries atomic.Bool
  39. // SilentDisco is whether the node should suppress disco heartbeats to its
  40. // peers.
  41. SilentDisco atomic.Bool
  42. // LinuxForceIPTables is whether the node should use iptables for Linux
  43. // netfiltering, unless overridden by the user.
  44. LinuxForceIPTables atomic.Bool
  45. // LinuxForceNfTables is whether the node should use nftables for Linux
  46. // netfiltering, unless overridden by the user.
  47. LinuxForceNfTables atomic.Bool
  48. // SeamlessKeyRenewal is whether to enable the alpha functionality of
  49. // renewing node keys without breaking connections.
  50. // http://go/seamless-key-renewal
  51. SeamlessKeyRenewal atomic.Bool
  52. // ProbeUDPLifetime is whether the node should probe UDP path lifetime on
  53. // the tail end of an active direct connection in magicsock.
  54. ProbeUDPLifetime atomic.Bool
  55. // AppCStoreRoutes is whether the node should store RouteInfo to StateStore
  56. // if it's an app connector.
  57. AppCStoreRoutes atomic.Bool
  58. // UserDialUseRoutes is whether tsdial.Dialer.UserDial should use routes to determine
  59. // how to dial the destination address. When true, it also makes the DNS forwarder
  60. // use UserDial instead of SystemDial when dialing resolvers.
  61. UserDialUseRoutes atomic.Bool
  62. // DisableSplitDNSWhenNoCustomResolvers indicates that the node's DNS manager
  63. // should not adopt a split DNS configuration even though the Config of the
  64. // resolver only contains routes that do not specify custom resolver(s), hence
  65. // all DNS queries can be safely sent to the upstream DNS resolver and the
  66. // node's DNS forwarder doesn't need to handle all DNS traffic.
  67. // This is for now (2024-06-06) an iOS-specific battery life optimization,
  68. // and this knob allows us to disable the optimization remotely if needed.
  69. DisableSplitDNSWhenNoCustomResolvers atomic.Bool
  70. // DisableLocalDNSOverrideViaNRPT indicates that the node's DNS manager should not
  71. // create a default (catch-all) Windows NRPT rule when "Override local DNS" is enabled.
  72. // Without this rule, Windows 8.1 and newer devices issue parallel DNS requests to DNS servers
  73. // associated with all network adapters, even when "Override local DNS" is enabled and/or
  74. // a Mullvad exit node is being used, resulting in DNS leaks.
  75. // We began creating this rule on 2024-06-14, and this knob
  76. // allows us to disable the new behavior remotely if needed.
  77. DisableLocalDNSOverrideViaNRPT atomic.Bool
  78. // DisableCryptorouting indicates that the node should not use the
  79. // magicsock crypto routing feature.
  80. DisableCryptorouting atomic.Bool
  81. // DisableCaptivePortalDetection is whether the node should not perform captive portal detection
  82. // automatically when the network state changes.
  83. DisableCaptivePortalDetection atomic.Bool
  84. }
  85. // UpdateFromNodeAttributes updates k (if non-nil) based on the provided self
  86. // node attributes (Node.Capabilities).
  87. func (k *Knobs) UpdateFromNodeAttributes(capMap tailcfg.NodeCapMap) {
  88. if k == nil {
  89. return
  90. }
  91. has := capMap.Contains
  92. var (
  93. keepFullWG = has(tailcfg.NodeAttrDebugDisableWGTrim)
  94. disableUPnP = has(tailcfg.NodeAttrDisableUPnP)
  95. randomizeClientPort = has(tailcfg.NodeAttrRandomizeClientPort)
  96. disableDeltaUpdates = has(tailcfg.NodeAttrDisableDeltaUpdates)
  97. oneCGNAT opt.Bool
  98. forceBackgroundSTUN = has(tailcfg.NodeAttrDebugForceBackgroundSTUN)
  99. peerMTUEnable = has(tailcfg.NodeAttrPeerMTUEnable)
  100. dnsForwarderDisableTCPRetries = has(tailcfg.NodeAttrDNSForwarderDisableTCPRetries)
  101. silentDisco = has(tailcfg.NodeAttrSilentDisco)
  102. forceIPTables = has(tailcfg.NodeAttrLinuxMustUseIPTables)
  103. forceNfTables = has(tailcfg.NodeAttrLinuxMustUseNfTables)
  104. seamlessKeyRenewal = has(tailcfg.NodeAttrSeamlessKeyRenewal)
  105. probeUDPLifetime = has(tailcfg.NodeAttrProbeUDPLifetime)
  106. appCStoreRoutes = has(tailcfg.NodeAttrStoreAppCRoutes)
  107. userDialUseRoutes = has(tailcfg.NodeAttrUserDialUseRoutes)
  108. disableSplitDNSWhenNoCustomResolvers = has(tailcfg.NodeAttrDisableSplitDNSWhenNoCustomResolvers)
  109. disableLocalDNSOverrideViaNRPT = has(tailcfg.NodeAttrDisableLocalDNSOverrideViaNRPT)
  110. disableCryptorouting = has(tailcfg.NodeAttrDisableMagicSockCryptoRouting)
  111. disableCaptivePortalDetection = has(tailcfg.NodeAttrDisableCaptivePortalDetection)
  112. )
  113. if has(tailcfg.NodeAttrOneCGNATEnable) {
  114. oneCGNAT.Set(true)
  115. } else if has(tailcfg.NodeAttrOneCGNATDisable) {
  116. oneCGNAT.Set(false)
  117. }
  118. k.KeepFullWGConfig.Store(keepFullWG)
  119. k.DisableUPnP.Store(disableUPnP)
  120. k.RandomizeClientPort.Store(randomizeClientPort)
  121. k.OneCGNAT.Store(oneCGNAT)
  122. k.ForceBackgroundSTUN.Store(forceBackgroundSTUN)
  123. k.DisableDeltaUpdates.Store(disableDeltaUpdates)
  124. k.PeerMTUEnable.Store(peerMTUEnable)
  125. k.DisableDNSForwarderTCPRetries.Store(dnsForwarderDisableTCPRetries)
  126. k.SilentDisco.Store(silentDisco)
  127. k.LinuxForceIPTables.Store(forceIPTables)
  128. k.LinuxForceNfTables.Store(forceNfTables)
  129. k.SeamlessKeyRenewal.Store(seamlessKeyRenewal)
  130. k.ProbeUDPLifetime.Store(probeUDPLifetime)
  131. k.AppCStoreRoutes.Store(appCStoreRoutes)
  132. k.UserDialUseRoutes.Store(userDialUseRoutes)
  133. k.DisableSplitDNSWhenNoCustomResolvers.Store(disableSplitDNSWhenNoCustomResolvers)
  134. k.DisableLocalDNSOverrideViaNRPT.Store(disableLocalDNSOverrideViaNRPT)
  135. k.DisableCryptorouting.Store(disableCryptorouting)
  136. k.DisableCaptivePortalDetection.Store(disableCaptivePortalDetection)
  137. }
  138. // AsDebugJSON returns k as something that can be marshalled with json.Marshal
  139. // for debug.
  140. func (k *Knobs) AsDebugJSON() map[string]any {
  141. if k == nil {
  142. return nil
  143. }
  144. return map[string]any{
  145. "DisableUPnP": k.DisableUPnP.Load(),
  146. "KeepFullWGConfig": k.KeepFullWGConfig.Load(),
  147. "RandomizeClientPort": k.RandomizeClientPort.Load(),
  148. "OneCGNAT": k.OneCGNAT.Load(),
  149. "ForceBackgroundSTUN": k.ForceBackgroundSTUN.Load(),
  150. "DisableDeltaUpdates": k.DisableDeltaUpdates.Load(),
  151. "PeerMTUEnable": k.PeerMTUEnable.Load(),
  152. "DisableDNSForwarderTCPRetries": k.DisableDNSForwarderTCPRetries.Load(),
  153. "SilentDisco": k.SilentDisco.Load(),
  154. "LinuxForceIPTables": k.LinuxForceIPTables.Load(),
  155. "LinuxForceNfTables": k.LinuxForceNfTables.Load(),
  156. "SeamlessKeyRenewal": k.SeamlessKeyRenewal.Load(),
  157. "ProbeUDPLifetime": k.ProbeUDPLifetime.Load(),
  158. "AppCStoreRoutes": k.AppCStoreRoutes.Load(),
  159. "UserDialUseRoutes": k.UserDialUseRoutes.Load(),
  160. "DisableSplitDNSWhenNoCustomResolvers": k.DisableSplitDNSWhenNoCustomResolvers.Load(),
  161. "DisableLocalDNSOverrideViaNRPT": k.DisableLocalDNSOverrideViaNRPT.Load(),
  162. "DisableCryptorouting": k.DisableCryptorouting.Load(),
  163. "DisableCaptivePortalDetection": k.DisableCaptivePortalDetection.Load(),
  164. }
  165. }