node_backend.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package ipnlocal
  4. import (
  5. "cmp"
  6. "context"
  7. "net/netip"
  8. "slices"
  9. "sync"
  10. "sync/atomic"
  11. "go4.org/netipx"
  12. "tailscale.com/feature/buildfeatures"
  13. "tailscale.com/ipn"
  14. "tailscale.com/net/dns"
  15. "tailscale.com/net/tsaddr"
  16. "tailscale.com/syncs"
  17. "tailscale.com/tailcfg"
  18. "tailscale.com/types/dnstype"
  19. "tailscale.com/types/key"
  20. "tailscale.com/types/logger"
  21. "tailscale.com/types/netmap"
  22. "tailscale.com/types/ptr"
  23. "tailscale.com/types/views"
  24. "tailscale.com/util/dnsname"
  25. "tailscale.com/util/eventbus"
  26. "tailscale.com/util/mak"
  27. "tailscale.com/util/slicesx"
  28. "tailscale.com/wgengine/filter"
  29. "tailscale.com/wgengine/magicsock"
  30. )
  31. // nodeBackend is node-specific [LocalBackend] state. It is usually the current node.
  32. //
  33. // Its exported methods are safe for concurrent use, but the struct is not a snapshot of state at a given moment;
  34. // its state can change between calls. For example, asking for the same value (e.g., netmap or prefs) twice
  35. // may return different results. Returned values are immutable and safe for concurrent use.
  36. //
  37. // If both the [LocalBackend]'s internal mutex and the [nodeBackend] mutex must be held at the same time,
  38. // the [LocalBackend] mutex must be acquired first. See the comment on the [LocalBackend] field for more details.
  39. //
  40. // Two pointers to different [nodeBackend] instances represent different local nodes.
  41. // However, there's currently a bug where a new [nodeBackend] might not be created
  42. // during an implicit node switch (see tailscale/corp#28014).
  43. //
  44. // In the future, we might want to include at least the following in this struct (in addition to the current fields).
  45. // However, not everything should be exported or otherwise made available to the outside world (e.g. [ipnext] extensions,
  46. // peer API handlers, etc.).
  47. // - [ipn.State]: when the LocalBackend switches to a different [nodeBackend], it can update the state of the old one.
  48. // - [ipn.LoginProfileView] and [ipn.Prefs]: we should update them when the [profileManager] reports changes to them.
  49. // In the future, [profileManager] (and the corresponding methods of the [LocalBackend]) can be made optional,
  50. // and something else could be used to set them once or update them as needed.
  51. // - [tailcfg.HostinfoView]: it includes certain fields that are tied to the current profile/node/prefs. We should also
  52. // update to build it once instead of mutating it in twelvety different places.
  53. // - [filter.Filter] (normal and jailed, along with the filterHash): the nodeBackend could have a method to (re-)build
  54. // the filter for the current netmap/prefs (see [LocalBackend.updateFilterLocked]), and it needs to track the current
  55. // filters and their hash.
  56. // - Fields related to a requested or required (re-)auth: authURL, authURLTime, authActor, keyExpired, etc.
  57. // - [controlclient.Client]/[*controlclient.Auto]: the current control client. It is ties to a node identity.
  58. // - [tkaState]: it is tied to the current profile / node.
  59. // - Fields related to scheduled node expiration: nmExpiryTimer, numClientStatusCalls, [expiryManager].
  60. //
  61. // It should not include any fields used by specific features that don't belong in [LocalBackend].
  62. // Even if they're tied to the local node, instead of moving them here, we should extract the entire feature
  63. // into a separate package and have it install proper hooks.
  64. type nodeBackend struct {
  65. logf logger.Logf
  66. ctx context.Context // canceled by [nodeBackend.shutdown]
  67. ctxCancel context.CancelCauseFunc // cancels ctx
  68. // filterAtomic is a stateful packet filter. Immutable once created, but can be
  69. // replaced with a new one.
  70. filterAtomic atomic.Pointer[filter.Filter]
  71. // initialized once and immutable
  72. eventClient *eventbus.Client
  73. filterPub *eventbus.Publisher[magicsock.FilterUpdate]
  74. nodeViewsPub *eventbus.Publisher[magicsock.NodeViewsUpdate]
  75. nodeMutsPub *eventbus.Publisher[magicsock.NodeMutationsUpdate]
  76. derpMapViewPub *eventbus.Publisher[tailcfg.DERPMapView]
  77. // TODO(nickkhyl): maybe use sync.RWMutex?
  78. mu syncs.Mutex // protects the following fields
  79. shutdownOnce sync.Once // guards calling [nodeBackend.shutdown]
  80. readyCh chan struct{} // closed by [nodeBackend.ready]; nil after shutdown
  81. // NetMap is the most recently set full netmap from the controlclient.
  82. // It can't be mutated in place once set. Because it can't be mutated in place,
  83. // delta updates from the control server don't apply to it. Instead, use
  84. // the peers map to get up-to-date information on the state of peers.
  85. // In general, avoid using the netMap.Peers slice. We'd like it to go away
  86. // as of 2023-09-17.
  87. // TODO(nickkhyl): make it an atomic pointer to avoid the need for a mutex?
  88. netMap *netmap.NetworkMap
  89. // peers is the set of current peers and their current values after applying
  90. // delta node mutations as they come in (with mu held). The map values can be
  91. // given out to callers, but the map itself can be mutated in place (with mu held)
  92. // and must not escape the [nodeBackend].
  93. peers map[tailcfg.NodeID]tailcfg.NodeView
  94. // nodeByAddr maps nodes' own addresses (excluding subnet routes) to node IDs.
  95. // It is mutated in place (with mu held) and must not escape the [nodeBackend].
  96. nodeByAddr map[netip.Addr]tailcfg.NodeID
  97. }
  98. func newNodeBackend(ctx context.Context, logf logger.Logf, bus *eventbus.Bus) *nodeBackend {
  99. ctx, ctxCancel := context.WithCancelCause(ctx)
  100. nb := &nodeBackend{
  101. logf: logf,
  102. ctx: ctx,
  103. ctxCancel: ctxCancel,
  104. eventClient: bus.Client("ipnlocal.nodeBackend"),
  105. readyCh: make(chan struct{}),
  106. }
  107. // Default filter blocks everything and logs nothing.
  108. noneFilter := filter.NewAllowNone(logger.Discard, &netipx.IPSet{})
  109. nb.filterAtomic.Store(noneFilter)
  110. nb.filterPub = eventbus.Publish[magicsock.FilterUpdate](nb.eventClient)
  111. nb.nodeViewsPub = eventbus.Publish[magicsock.NodeViewsUpdate](nb.eventClient)
  112. nb.nodeMutsPub = eventbus.Publish[magicsock.NodeMutationsUpdate](nb.eventClient)
  113. nb.derpMapViewPub = eventbus.Publish[tailcfg.DERPMapView](nb.eventClient)
  114. nb.filterPub.Publish(magicsock.FilterUpdate{Filter: nb.filterAtomic.Load()})
  115. return nb
  116. }
  117. // Context returns a context that is canceled when the [nodeBackend] shuts down,
  118. // either because [LocalBackend] is switching to a different [nodeBackend]
  119. // or is shutting down itself.
  120. func (nb *nodeBackend) Context() context.Context {
  121. return nb.ctx
  122. }
  123. func (nb *nodeBackend) Self() tailcfg.NodeView {
  124. nb.mu.Lock()
  125. defer nb.mu.Unlock()
  126. if nb.netMap == nil {
  127. return tailcfg.NodeView{}
  128. }
  129. return nb.netMap.SelfNode
  130. }
  131. func (nb *nodeBackend) SelfUserID() tailcfg.UserID {
  132. self := nb.Self()
  133. if !self.Valid() {
  134. return 0
  135. }
  136. return self.User()
  137. }
  138. // SelfHasCap reports whether the specified capability was granted to the self node in the most recent netmap.
  139. func (nb *nodeBackend) SelfHasCap(wantCap tailcfg.NodeCapability) bool {
  140. return nb.SelfHasCapOr(wantCap, false)
  141. }
  142. // SelfHasCapOr is like [nodeBackend.SelfHasCap], but returns the specified default value
  143. // if the netmap is not available yet.
  144. func (nb *nodeBackend) SelfHasCapOr(wantCap tailcfg.NodeCapability, def bool) bool {
  145. nb.mu.Lock()
  146. defer nb.mu.Unlock()
  147. if nb.netMap == nil {
  148. return def
  149. }
  150. return nb.netMap.AllCaps.Contains(wantCap)
  151. }
  152. func (nb *nodeBackend) NetworkProfile() ipn.NetworkProfile {
  153. nb.mu.Lock()
  154. defer nb.mu.Unlock()
  155. return ipn.NetworkProfile{
  156. // These are ok to call with nil netMap.
  157. MagicDNSName: nb.netMap.MagicDNSSuffix(),
  158. DomainName: nb.netMap.DomainName(),
  159. DisplayName: nb.netMap.TailnetDisplayName(),
  160. }
  161. }
  162. // TODO(nickkhyl): update it to return a [tailcfg.DERPMapView]?
  163. func (nb *nodeBackend) DERPMap() *tailcfg.DERPMap {
  164. nb.mu.Lock()
  165. defer nb.mu.Unlock()
  166. if nb.netMap == nil {
  167. return nil
  168. }
  169. return nb.netMap.DERPMap
  170. }
  171. func (nb *nodeBackend) NodeByAddr(ip netip.Addr) (_ tailcfg.NodeID, ok bool) {
  172. nb.mu.Lock()
  173. defer nb.mu.Unlock()
  174. nid, ok := nb.nodeByAddr[ip]
  175. return nid, ok
  176. }
  177. func (nb *nodeBackend) NodeByKey(k key.NodePublic) (_ tailcfg.NodeID, ok bool) {
  178. nb.mu.Lock()
  179. defer nb.mu.Unlock()
  180. if nb.netMap == nil {
  181. return 0, false
  182. }
  183. if self := nb.netMap.SelfNode; self.Valid() && self.Key() == k {
  184. return self.ID(), true
  185. }
  186. // TODO(bradfitz,nickkhyl): add nodeByKey like nodeByAddr instead of walking peers.
  187. for _, n := range nb.peers {
  188. if n.Key() == k {
  189. return n.ID(), true
  190. }
  191. }
  192. return 0, false
  193. }
  194. func (nb *nodeBackend) NodeByID(id tailcfg.NodeID) (_ tailcfg.NodeView, ok bool) {
  195. nb.mu.Lock()
  196. defer nb.mu.Unlock()
  197. if nb.netMap != nil {
  198. if self := nb.netMap.SelfNode; self.Valid() && self.ID() == id {
  199. return self, true
  200. }
  201. }
  202. n, ok := nb.peers[id]
  203. return n, ok
  204. }
  205. func (nb *nodeBackend) PeerByStableID(id tailcfg.StableNodeID) (_ tailcfg.NodeView, ok bool) {
  206. nb.mu.Lock()
  207. defer nb.mu.Unlock()
  208. for _, n := range nb.peers {
  209. if n.StableID() == id {
  210. return n, true
  211. }
  212. }
  213. return tailcfg.NodeView{}, false
  214. }
  215. func (nb *nodeBackend) UserByID(id tailcfg.UserID) (_ tailcfg.UserProfileView, ok bool) {
  216. nb.mu.Lock()
  217. nm := nb.netMap
  218. nb.mu.Unlock()
  219. if nm == nil {
  220. return tailcfg.UserProfileView{}, false
  221. }
  222. u, ok := nm.UserProfiles[id]
  223. return u, ok
  224. }
  225. // Peers returns all the current peers in an undefined order.
  226. func (nb *nodeBackend) Peers() []tailcfg.NodeView {
  227. nb.mu.Lock()
  228. defer nb.mu.Unlock()
  229. return slicesx.MapValues(nb.peers)
  230. }
  231. func (nb *nodeBackend) PeersForTest() []tailcfg.NodeView {
  232. nb.mu.Lock()
  233. defer nb.mu.Unlock()
  234. ret := slicesx.MapValues(nb.peers)
  235. slices.SortFunc(ret, func(a, b tailcfg.NodeView) int {
  236. return cmp.Compare(a.ID(), b.ID())
  237. })
  238. return ret
  239. }
  240. func (nb *nodeBackend) CollectServices() bool {
  241. nb.mu.Lock()
  242. defer nb.mu.Unlock()
  243. return nb.netMap != nil && nb.netMap.CollectServices
  244. }
  245. // AppendMatchingPeers returns base with all peers that match pred appended.
  246. //
  247. // It acquires b.mu to read the netmap but releases it before calling pred.
  248. func (nb *nodeBackend) AppendMatchingPeers(base []tailcfg.NodeView, pred func(tailcfg.NodeView) bool) []tailcfg.NodeView {
  249. var peers []tailcfg.NodeView
  250. nb.mu.Lock()
  251. if nb.netMap != nil {
  252. // All fields on b.netMap are immutable, so this is
  253. // safe to copy and use outside the lock.
  254. peers = nb.netMap.Peers
  255. }
  256. nb.mu.Unlock()
  257. ret := base
  258. for _, peer := range peers {
  259. // The peers in b.netMap don't contain updates made via
  260. // UpdateNetmapDelta. So only use PeerView in b.netMap for its NodeID,
  261. // and then look up the latest copy in b.peers which is updated in
  262. // response to UpdateNetmapDelta edits.
  263. nb.mu.Lock()
  264. peer, ok := nb.peers[peer.ID()]
  265. nb.mu.Unlock()
  266. if ok && pred(peer) {
  267. ret = append(ret, peer)
  268. }
  269. }
  270. return ret
  271. }
  272. // PeerCaps returns the capabilities that remote src IP has to
  273. // ths current node.
  274. func (nb *nodeBackend) PeerCaps(src netip.Addr) tailcfg.PeerCapMap {
  275. nb.mu.Lock()
  276. defer nb.mu.Unlock()
  277. return nb.peerCapsLocked(src)
  278. }
  279. func (nb *nodeBackend) peerCapsLocked(src netip.Addr) tailcfg.PeerCapMap {
  280. if nb.netMap == nil {
  281. return nil
  282. }
  283. filt := nb.filterAtomic.Load()
  284. if filt == nil {
  285. return nil
  286. }
  287. addrs := nb.netMap.GetAddresses()
  288. for i := range addrs.Len() {
  289. a := addrs.At(i)
  290. if !a.IsSingleIP() {
  291. continue
  292. }
  293. dst := a.Addr()
  294. if dst.BitLen() == src.BitLen() { // match on family
  295. return filt.CapsWithValues(src, dst)
  296. }
  297. }
  298. return nil
  299. }
  300. // PeerHasCap reports whether the peer contains the given capability string,
  301. // with any value(s).
  302. func (nb *nodeBackend) PeerHasCap(peer tailcfg.NodeView, wantCap tailcfg.PeerCapability) bool {
  303. if !peer.Valid() {
  304. return false
  305. }
  306. nb.mu.Lock()
  307. defer nb.mu.Unlock()
  308. for _, ap := range peer.Addresses().All() {
  309. if nb.peerHasCapLocked(ap.Addr(), wantCap) {
  310. return true
  311. }
  312. }
  313. return false
  314. }
  315. func (nb *nodeBackend) peerHasCapLocked(addr netip.Addr, wantCap tailcfg.PeerCapability) bool {
  316. return nb.peerCapsLocked(addr).HasCapability(wantCap)
  317. }
  318. func (nb *nodeBackend) PeerHasPeerAPI(p tailcfg.NodeView) bool {
  319. return nb.PeerAPIBase(p) != ""
  320. }
  321. // PeerAPIBase returns the "http://ip:port" URL base to reach peer's PeerAPI,
  322. // or the empty string if the peer is invalid or doesn't support PeerAPI.
  323. func (nb *nodeBackend) PeerAPIBase(p tailcfg.NodeView) string {
  324. nb.mu.Lock()
  325. nm := nb.netMap
  326. nb.mu.Unlock()
  327. return peerAPIBase(nm, p)
  328. }
  329. // PeerIsReachable reports whether the current node can reach p. If the ctx is
  330. // done, this function may return a result based on stale reachability data.
  331. func (nb *nodeBackend) PeerIsReachable(ctx context.Context, p tailcfg.NodeView) bool {
  332. if !nb.SelfHasCap(tailcfg.NodeAttrClientSideReachability) {
  333. // Legacy behavior is to always trust the control plane, which
  334. // isn’t always correct because the peer could be slow to check
  335. // in so that control marks it as offline.
  336. // See tailscale/corp#32686.
  337. return p.Online().Get()
  338. }
  339. nb.mu.Lock()
  340. nm := nb.netMap
  341. nb.mu.Unlock()
  342. if self := nm.SelfNode; self.Valid() && self.ID() == p.ID() {
  343. // This node can always reach itself.
  344. return true
  345. }
  346. return nb.peerIsReachable(ctx, p)
  347. }
  348. func (nb *nodeBackend) peerIsReachable(ctx context.Context, p tailcfg.NodeView) bool {
  349. // TODO(sfllaw): The following does not actually test for client-side
  350. // reachability. This would require a mechanism that tracks whether the
  351. // current node can actually reach this peer, either because they are
  352. // already communicating or because they can ping each other.
  353. //
  354. // Instead, it makes the client ignore p.Online completely.
  355. //
  356. // See tailscale/corp#32686.
  357. return true
  358. }
  359. func nodeIP(n tailcfg.NodeView, pred func(netip.Addr) bool) netip.Addr {
  360. for _, pfx := range n.Addresses().All() {
  361. if pfx.IsSingleIP() && pred(pfx.Addr()) {
  362. return pfx.Addr()
  363. }
  364. }
  365. return netip.Addr{}
  366. }
  367. func (nb *nodeBackend) NetMap() *netmap.NetworkMap {
  368. nb.mu.Lock()
  369. defer nb.mu.Unlock()
  370. return nb.netMap
  371. }
  372. func (nb *nodeBackend) netMapWithPeers() *netmap.NetworkMap {
  373. nb.mu.Lock()
  374. defer nb.mu.Unlock()
  375. if nb.netMap == nil {
  376. return nil
  377. }
  378. nm := ptr.To(*nb.netMap) // shallow clone
  379. nm.Peers = slicesx.MapValues(nb.peers)
  380. slices.SortFunc(nm.Peers, func(a, b tailcfg.NodeView) int {
  381. return cmp.Compare(a.ID(), b.ID())
  382. })
  383. return nm
  384. }
  385. func (nb *nodeBackend) SetNetMap(nm *netmap.NetworkMap) {
  386. nb.mu.Lock()
  387. defer nb.mu.Unlock()
  388. nb.netMap = nm
  389. nb.updateNodeByAddrLocked()
  390. nb.updatePeersLocked()
  391. nv := magicsock.NodeViewsUpdate{}
  392. if nm != nil {
  393. nv.SelfNode = nm.SelfNode
  394. nv.Peers = nm.Peers
  395. nb.derpMapViewPub.Publish(nm.DERPMap.View())
  396. } else {
  397. nb.derpMapViewPub.Publish(tailcfg.DERPMapView{})
  398. }
  399. nb.nodeViewsPub.Publish(nv)
  400. }
  401. func (nb *nodeBackend) updateNodeByAddrLocked() {
  402. nm := nb.netMap
  403. if nm == nil {
  404. nb.nodeByAddr = nil
  405. return
  406. }
  407. // Update the nodeByAddr index.
  408. if nb.nodeByAddr == nil {
  409. nb.nodeByAddr = map[netip.Addr]tailcfg.NodeID{}
  410. }
  411. // First pass, mark everything unwanted.
  412. for k := range nb.nodeByAddr {
  413. nb.nodeByAddr[k] = 0
  414. }
  415. addNode := func(n tailcfg.NodeView) {
  416. for _, ipp := range n.Addresses().All() {
  417. if ipp.IsSingleIP() {
  418. nb.nodeByAddr[ipp.Addr()] = n.ID()
  419. }
  420. }
  421. }
  422. if nm.SelfNode.Valid() {
  423. addNode(nm.SelfNode)
  424. }
  425. for _, p := range nm.Peers {
  426. addNode(p)
  427. }
  428. // Third pass, actually delete the unwanted items.
  429. for k, v := range nb.nodeByAddr {
  430. if v == 0 {
  431. delete(nb.nodeByAddr, k)
  432. }
  433. }
  434. }
  435. func (nb *nodeBackend) updatePeersLocked() {
  436. nm := nb.netMap
  437. if nm == nil {
  438. nb.peers = nil
  439. return
  440. }
  441. // First pass, mark everything unwanted.
  442. for k := range nb.peers {
  443. nb.peers[k] = tailcfg.NodeView{}
  444. }
  445. // Second pass, add everything wanted.
  446. for _, p := range nm.Peers {
  447. mak.Set(&nb.peers, p.ID(), p)
  448. }
  449. // Third pass, remove deleted things.
  450. for k, v := range nb.peers {
  451. if !v.Valid() {
  452. delete(nb.peers, k)
  453. }
  454. }
  455. }
  456. func (nb *nodeBackend) UpdateNetmapDelta(muts []netmap.NodeMutation) (handled bool) {
  457. nb.mu.Lock()
  458. defer nb.mu.Unlock()
  459. if nb.netMap == nil || len(nb.peers) == 0 {
  460. return false
  461. }
  462. // Locally cloned mutable nodes, to avoid calling AsStruct (clone)
  463. // multiple times on a node if it's mutated multiple times in this
  464. // call (e.g. its endpoints + online status both change)
  465. var mutableNodes map[tailcfg.NodeID]*tailcfg.Node
  466. update := magicsock.NodeMutationsUpdate{
  467. Mutations: make([]netmap.NodeMutation, 0, len(muts)),
  468. }
  469. for _, m := range muts {
  470. n, ok := mutableNodes[m.NodeIDBeingMutated()]
  471. if !ok {
  472. nv, ok := nb.peers[m.NodeIDBeingMutated()]
  473. if !ok {
  474. // TODO(bradfitz): unexpected metric?
  475. return false
  476. }
  477. n = nv.AsStruct()
  478. mak.Set(&mutableNodes, nv.ID(), n)
  479. update.Mutations = append(update.Mutations, m)
  480. }
  481. m.Apply(n)
  482. }
  483. for nid, n := range mutableNodes {
  484. nb.peers[nid] = n.View()
  485. }
  486. nb.nodeMutsPub.Publish(update)
  487. return true
  488. }
  489. // unlockedNodesPermitted reports whether any peer with theUnsignedPeerAPIOnly bool set true has any of its allowed IPs
  490. // in the specified packet filter.
  491. //
  492. // TODO(nickkhyl): It is here temporarily until we can move the whole [LocalBackend.updateFilterLocked] here,
  493. // but change it so it builds and returns a filter for the current netmap/prefs instead of re-configuring the engine filter.
  494. // Something like (*nodeBackend).RebuildFilters() (filter, jailedFilter *filter.Filter, changed bool) perhaps?
  495. func (nb *nodeBackend) unlockedNodesPermitted(packetFilter []filter.Match) bool {
  496. nb.mu.Lock()
  497. defer nb.mu.Unlock()
  498. return packetFilterPermitsUnlockedNodes(nb.peers, packetFilter)
  499. }
  500. func (nb *nodeBackend) filter() *filter.Filter {
  501. return nb.filterAtomic.Load()
  502. }
  503. func (nb *nodeBackend) setFilter(f *filter.Filter) {
  504. nb.filterAtomic.Store(f)
  505. nb.filterPub.Publish(magicsock.FilterUpdate{Filter: f})
  506. }
  507. func (nb *nodeBackend) dnsConfigForNetmap(prefs ipn.PrefsView, selfExpired bool, versionOS string) *dns.Config {
  508. nb.mu.Lock()
  509. defer nb.mu.Unlock()
  510. return dnsConfigForNetmap(nb.netMap, nb.peers, prefs, selfExpired, nb.logf, versionOS)
  511. }
  512. func (nb *nodeBackend) exitNodeCanProxyDNS(exitNodeID tailcfg.StableNodeID) (dohURL string, ok bool) {
  513. if !buildfeatures.HasUseExitNode {
  514. return "", false
  515. }
  516. nb.mu.Lock()
  517. defer nb.mu.Unlock()
  518. return exitNodeCanProxyDNS(nb.netMap, nb.peers, exitNodeID)
  519. }
  520. // ready signals that [LocalBackend] has completed the switch to this [nodeBackend]
  521. // and any pending calls to [nodeBackend.Wait] must be unblocked.
  522. func (nb *nodeBackend) ready() {
  523. nb.mu.Lock()
  524. defer nb.mu.Unlock()
  525. if nb.readyCh != nil {
  526. close(nb.readyCh)
  527. }
  528. }
  529. // Wait blocks until [LocalBackend] completes the switch to this [nodeBackend]
  530. // and calls [nodeBackend.ready]. It returns an error if the provided context
  531. // is canceled or if the [nodeBackend] shuts down or is already shut down.
  532. //
  533. // It must not be called with the [LocalBackend]'s internal mutex held as [LocalBackend]
  534. // may need to acquire it to complete the switch.
  535. //
  536. // TODO(nickkhyl): Relax this restriction once [LocalBackend]'s state machine
  537. // runs in its own goroutine, or if we decide that waiting for the state machine
  538. // restart to finish isn't necessary for [LocalBackend] to consider the switch complete.
  539. // We mostly need this because of [LocalBackend.Start] acquiring b.mu and the fact that
  540. // methods like [LocalBackend.SwitchProfile] must report any errors returned by it.
  541. // Perhaps we could report those errors asynchronously as [health.Warnable]s?
  542. func (nb *nodeBackend) Wait(ctx context.Context) error {
  543. nb.mu.Lock()
  544. readyCh := nb.readyCh
  545. nb.mu.Unlock()
  546. select {
  547. case <-ctx.Done():
  548. return ctx.Err()
  549. case <-nb.ctx.Done():
  550. return context.Cause(nb.ctx)
  551. case <-readyCh:
  552. return nil
  553. }
  554. }
  555. // shutdown shuts down the [nodeBackend] and cancels its context
  556. // with the provided cause.
  557. func (nb *nodeBackend) shutdown(cause error) {
  558. nb.shutdownOnce.Do(func() {
  559. nb.doShutdown(cause)
  560. })
  561. }
  562. func (nb *nodeBackend) doShutdown(cause error) {
  563. nb.mu.Lock()
  564. defer nb.mu.Unlock()
  565. nb.ctxCancel(cause)
  566. nb.readyCh = nil
  567. nb.eventClient.Close()
  568. }
  569. // useWithExitNodeResolvers filters out resolvers so the ones that remain
  570. // are all the ones marked for use with exit nodes.
  571. func useWithExitNodeResolvers(resolvers []*dnstype.Resolver) []*dnstype.Resolver {
  572. var filtered []*dnstype.Resolver
  573. for _, res := range resolvers {
  574. if res.UseWithExitNode {
  575. filtered = append(filtered, res)
  576. }
  577. }
  578. return filtered
  579. }
  580. // useWithExitNodeRoutes filters out routes so the ones that remain
  581. // are either zero-length resolver lists, or lists containing only
  582. // resolvers marked for use with exit nodes.
  583. func useWithExitNodeRoutes(routes map[string][]*dnstype.Resolver) map[string][]*dnstype.Resolver {
  584. var filtered map[string][]*dnstype.Resolver
  585. for suffix, resolvers := range routes {
  586. // Suffixes with no resolvers represent a valid configuration,
  587. // and should persist regardless of exit node considerations.
  588. if len(resolvers) == 0 {
  589. mak.Set(&filtered, suffix, make([]*dnstype.Resolver, 0))
  590. continue
  591. }
  592. // In exit node contexts, we filter out resolvers not configured for use with
  593. // exit nodes. If there are no such configured resolvers, there should not be an entry for that suffix.
  594. filteredResolvers := useWithExitNodeResolvers(resolvers)
  595. if len(filteredResolvers) > 0 {
  596. mak.Set(&filtered, suffix, filteredResolvers)
  597. }
  598. }
  599. return filtered
  600. }
  601. // dnsConfigForNetmap returns a *dns.Config for the given netmap,
  602. // prefs, client OS version, and cloud hosting environment.
  603. //
  604. // The versionOS is a Tailscale-style version ("iOS", "macOS") and not
  605. // a runtime.GOOS.
  606. func dnsConfigForNetmap(nm *netmap.NetworkMap, peers map[tailcfg.NodeID]tailcfg.NodeView, prefs ipn.PrefsView, selfExpired bool, logf logger.Logf, versionOS string) *dns.Config {
  607. if nm == nil {
  608. return nil
  609. }
  610. if !buildfeatures.HasDNS {
  611. return &dns.Config{}
  612. }
  613. // If the current node's key is expired, then we don't program any DNS
  614. // configuration into the operating system. This ensures that if the
  615. // DNS configuration specifies a DNS server that is only reachable over
  616. // Tailscale, we don't break connectivity for the user.
  617. //
  618. // TODO(andrew-d): this also stops returning anything from quad-100; we
  619. // could do the same thing as having "CorpDNS: false" and keep that but
  620. // not program the OS?
  621. if selfExpired {
  622. return &dns.Config{}
  623. }
  624. dcfg := &dns.Config{
  625. Routes: map[dnsname.FQDN][]*dnstype.Resolver{},
  626. Hosts: map[dnsname.FQDN][]netip.Addr{},
  627. }
  628. // selfV6Only is whether we only have IPv6 addresses ourselves.
  629. selfV6Only := nm.GetAddresses().ContainsFunc(tsaddr.PrefixIs6) &&
  630. !nm.GetAddresses().ContainsFunc(tsaddr.PrefixIs4)
  631. dcfg.OnlyIPv6 = selfV6Only
  632. wantAAAA := nm.AllCaps.Contains(tailcfg.NodeAttrMagicDNSPeerAAAA)
  633. // Populate MagicDNS records. We do this unconditionally so that
  634. // quad-100 can always respond to MagicDNS queries, even if the OS
  635. // isn't configured to make MagicDNS resolution truly
  636. // magic. Details in
  637. // https://github.com/tailscale/tailscale/issues/1886.
  638. set := func(name string, addrs views.Slice[netip.Prefix]) {
  639. if addrs.Len() == 0 || name == "" {
  640. return
  641. }
  642. fqdn, err := dnsname.ToFQDN(name)
  643. if err != nil {
  644. return // TODO: propagate error?
  645. }
  646. var have4 bool
  647. for _, addr := range addrs.All() {
  648. if addr.Addr().Is4() {
  649. have4 = true
  650. break
  651. }
  652. }
  653. var ips []netip.Addr
  654. for _, addr := range addrs.All() {
  655. if selfV6Only {
  656. if addr.Addr().Is6() {
  657. ips = append(ips, addr.Addr())
  658. }
  659. continue
  660. }
  661. // If this node has an IPv4 address, then
  662. // remove peers' IPv6 addresses for now, as we
  663. // don't guarantee that the peer node actually
  664. // can speak IPv6 correctly.
  665. //
  666. // https://github.com/tailscale/tailscale/issues/1152
  667. // tracks adding the right capability reporting to
  668. // enable AAAA in MagicDNS.
  669. if addr.Addr().Is6() && have4 && !wantAAAA {
  670. continue
  671. }
  672. ips = append(ips, addr.Addr())
  673. }
  674. dcfg.Hosts[fqdn] = ips
  675. }
  676. set(nm.SelfName(), nm.GetAddresses())
  677. for _, peer := range peers {
  678. set(peer.Name(), peer.Addresses())
  679. }
  680. for _, rec := range nm.DNS.ExtraRecords {
  681. switch rec.Type {
  682. case "", "A", "AAAA":
  683. // Treat these all the same for now: infer from the value
  684. default:
  685. // TODO: more
  686. continue
  687. }
  688. ip, err := netip.ParseAddr(rec.Value)
  689. if err != nil {
  690. // Ignore.
  691. continue
  692. }
  693. fqdn, err := dnsname.ToFQDN(rec.Name)
  694. if err != nil {
  695. continue
  696. }
  697. dcfg.Hosts[fqdn] = append(dcfg.Hosts[fqdn], ip)
  698. }
  699. if !prefs.CorpDNS() {
  700. return dcfg
  701. }
  702. for _, dom := range nm.DNS.Domains {
  703. fqdn, err := dnsname.ToFQDN(dom)
  704. if err != nil {
  705. logf("[unexpected] non-FQDN search domain %q", dom)
  706. }
  707. dcfg.SearchDomains = append(dcfg.SearchDomains, fqdn)
  708. }
  709. if nm.DNS.Proxied { // actually means "enable MagicDNS"
  710. for _, dom := range magicDNSRootDomains(nm) {
  711. dcfg.Routes[dom] = nil // resolve internally with dcfg.Hosts
  712. }
  713. }
  714. addDefault := func(resolvers []*dnstype.Resolver) {
  715. dcfg.DefaultResolvers = append(dcfg.DefaultResolvers, resolvers...)
  716. }
  717. addSplitDNSRoutes := func(routes map[string][]*dnstype.Resolver) {
  718. for suffix, resolvers := range routes {
  719. fqdn, err := dnsname.ToFQDN(suffix)
  720. if err != nil {
  721. logf("[unexpected] non-FQDN route suffix %q", suffix)
  722. }
  723. // Create map entry even if len(resolvers) == 0; Issue 2706.
  724. // This lets the control plane send ExtraRecords for which we
  725. // can authoritatively answer "name not exists" for when the
  726. // control plane also sends this explicit but empty route
  727. // making it as something we handle.
  728. dcfg.Routes[fqdn] = slices.Clone(resolvers)
  729. }
  730. }
  731. // If we're using an exit node and that exit node is new enough (1.19.x+)
  732. // to run a DoH DNS proxy, then send all our DNS traffic through it,
  733. // unless we find resolvers with UseWithExitNode set, in which case we use that.
  734. if buildfeatures.HasUseExitNode {
  735. if dohURL, ok := exitNodeCanProxyDNS(nm, peers, prefs.ExitNodeID()); ok {
  736. filtered := useWithExitNodeResolvers(nm.DNS.Resolvers)
  737. if len(filtered) > 0 {
  738. addDefault(filtered)
  739. } else {
  740. // If no default global resolvers with the override
  741. // are configured, configure the exit node's resolver.
  742. addDefault([]*dnstype.Resolver{{Addr: dohURL}})
  743. }
  744. addSplitDNSRoutes(useWithExitNodeRoutes(nm.DNS.Routes))
  745. return dcfg
  746. }
  747. }
  748. // If the user has set default resolvers ("override local DNS"), prefer to
  749. // use those resolvers as the default, otherwise if there are WireGuard exit
  750. // node resolvers, use those as the default.
  751. if len(nm.DNS.Resolvers) > 0 {
  752. addDefault(nm.DNS.Resolvers)
  753. } else if buildfeatures.HasUseExitNode {
  754. if resolvers, ok := wireguardExitNodeDNSResolvers(nm, peers, prefs.ExitNodeID()); ok {
  755. addDefault(resolvers)
  756. }
  757. }
  758. // Add split DNS routes, with no regard to exit node configuration.
  759. addSplitDNSRoutes(nm.DNS.Routes)
  760. // Set FallbackResolvers as the default resolvers in the
  761. // scenarios that can't handle a purely split-DNS config. See
  762. // https://github.com/tailscale/tailscale/issues/1743 for
  763. // details.
  764. switch {
  765. case len(dcfg.DefaultResolvers) != 0:
  766. // Default resolvers already set.
  767. case !prefs.ExitNodeID().IsZero():
  768. // When using an exit node, we send all DNS traffic to the exit node, so
  769. // we don't need a fallback resolver.
  770. //
  771. // However, if the exit node is too old to run a DoH DNS proxy, then we
  772. // need to use a fallback resolver as it's very likely the LAN resolvers
  773. // will become unreachable.
  774. //
  775. // This is especially important on Apple OSes, where
  776. // adding the default route to the tunnel interface makes
  777. // it "primary", and we MUST provide VPN-sourced DNS
  778. // settings or we break all DNS resolution.
  779. //
  780. // https://github.com/tailscale/tailscale/issues/1713
  781. addDefault(nm.DNS.FallbackResolvers)
  782. case len(dcfg.Routes) == 0:
  783. // No settings requiring split DNS, no problem.
  784. }
  785. return dcfg
  786. }