manager.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package dns
  4. import (
  5. "bufio"
  6. "context"
  7. "encoding/binary"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "net"
  12. "net/netip"
  13. "runtime"
  14. "slices"
  15. "strings"
  16. "sync"
  17. "sync/atomic"
  18. "time"
  19. "tailscale.com/control/controlknobs"
  20. "tailscale.com/feature/buildfeatures"
  21. "tailscale.com/health"
  22. "tailscale.com/net/dns/resolver"
  23. "tailscale.com/net/netmon"
  24. "tailscale.com/net/tsdial"
  25. "tailscale.com/syncs"
  26. "tailscale.com/types/dnstype"
  27. "tailscale.com/types/logger"
  28. "tailscale.com/util/clientmetric"
  29. "tailscale.com/util/dnsname"
  30. "tailscale.com/util/eventbus"
  31. "tailscale.com/util/slicesx"
  32. "tailscale.com/util/syspolicy/policyclient"
  33. )
  34. var (
  35. errFullQueue = errors.New("request queue full")
  36. // ErrNoDNSConfig is returned by RecompileDNSConfig when the Manager
  37. // has no existing DNS configuration.
  38. ErrNoDNSConfig = errors.New("no DNS configuration")
  39. )
  40. // maxActiveQueries returns the maximal number of DNS requests that can
  41. // be running.
  42. const maxActiveQueries = 256
  43. // We use file-ignore below instead of ignore because on some platforms,
  44. // the lint exception is necessary and on others it is not,
  45. // and plain ignore complains if the exception is unnecessary.
  46. // Manager manages system DNS settings.
  47. type Manager struct {
  48. logf logger.Logf
  49. health *health.Tracker
  50. eventClient *eventbus.Client
  51. activeQueriesAtomic int32
  52. ctx context.Context // good until Down
  53. ctxCancel context.CancelFunc // closes ctx
  54. resolver *resolver.Resolver
  55. os OSConfigurator
  56. knobs *controlknobs.Knobs // or nil
  57. goos string // if empty, gets set to runtime.GOOS
  58. mu sync.Mutex // guards following
  59. config *Config // Tracks the last viable DNS configuration set by Set. nil on failures other than compilation failures or if set has never been called.
  60. }
  61. // NewManager created a new manager from the given config.
  62. //
  63. // knobs may be nil.
  64. func NewManager(logf logger.Logf, oscfg OSConfigurator, health *health.Tracker, dialer *tsdial.Dialer, linkSel resolver.ForwardLinkSelector, knobs *controlknobs.Knobs, goos string, bus *eventbus.Bus) *Manager {
  65. if !buildfeatures.HasDNS {
  66. return nil
  67. }
  68. if dialer == nil {
  69. panic("nil Dialer")
  70. }
  71. if dialer.NetMon() == nil {
  72. panic("Dialer has nil NetMon")
  73. }
  74. logf = logger.WithPrefix(logf, "dns: ")
  75. if goos == "" {
  76. goos = runtime.GOOS
  77. }
  78. m := &Manager{
  79. logf: logf,
  80. resolver: resolver.New(logf, linkSel, dialer, health, knobs),
  81. os: oscfg,
  82. health: health,
  83. knobs: knobs,
  84. goos: goos,
  85. }
  86. m.eventClient = bus.Client("dns.Manager")
  87. eventbus.SubscribeFunc(m.eventClient, func(trample TrampleDNS) {
  88. m.mu.Lock()
  89. defer m.mu.Unlock()
  90. if m.config == nil {
  91. m.logf("resolve.conf was trampled, but there is no DNS config")
  92. return
  93. }
  94. m.logf("resolve.conf was trampled, setting existing config again")
  95. if err := m.setLocked(*m.config); err != nil {
  96. m.logf("error setting DNS config: %s", err)
  97. }
  98. })
  99. m.ctx, m.ctxCancel = context.WithCancel(context.Background())
  100. m.logf("using %T", m.os)
  101. return m
  102. }
  103. // Resolver returns the Manager's DNS Resolver.
  104. func (m *Manager) Resolver() *resolver.Resolver {
  105. if !buildfeatures.HasDNS {
  106. return nil
  107. }
  108. return m.resolver
  109. }
  110. // RecompileDNSConfig recompiles the last attempted DNS configuration, which has
  111. // the side effect of re-querying the OS's interface nameservers. This should be used
  112. // on platforms where the interface nameservers can change. Darwin, for example,
  113. // where the nameservers aren't always available when we process a major interface
  114. // change event, or platforms where the nameservers may change while tunnel is up.
  115. //
  116. // This should be called if it is determined that [OSConfigurator.GetBaseConfig] may
  117. // give a better or different result than when [Manager.Set] was last called. The
  118. // logic for making that determination is up to the caller.
  119. //
  120. // It returns [ErrNoDNSConfig] if [Manager.Set] has never been called.
  121. func (m *Manager) RecompileDNSConfig() error {
  122. if !buildfeatures.HasDNS {
  123. return nil
  124. }
  125. m.mu.Lock()
  126. defer m.mu.Unlock()
  127. if m.config != nil {
  128. return m.setLocked(*m.config)
  129. }
  130. return ErrNoDNSConfig
  131. }
  132. func (m *Manager) Set(cfg Config) error {
  133. if !buildfeatures.HasDNS {
  134. return nil
  135. }
  136. m.mu.Lock()
  137. defer m.mu.Unlock()
  138. return m.setLocked(cfg)
  139. }
  140. // GetBaseConfig returns the current base OS DNS configuration as provided by the OSConfigurator.
  141. func (m *Manager) GetBaseConfig() (OSConfig, error) {
  142. if !buildfeatures.HasDNS {
  143. panic("unreachable")
  144. }
  145. return m.os.GetBaseConfig()
  146. }
  147. // setLocked sets the DNS configuration.
  148. //
  149. // m.mu must be held.
  150. func (m *Manager) setLocked(cfg Config) error {
  151. syncs.AssertLocked(&m.mu)
  152. m.logf("Set: %v", logger.ArgWriter(func(w *bufio.Writer) {
  153. cfg.WriteToBufioWriter(w)
  154. }))
  155. rcfg, ocfg, err := m.compileConfig(cfg)
  156. if err != nil {
  157. // On a compilation failure, set m.config set for later reuse by
  158. // [Manager.RecompileDNSConfig] and return the error.
  159. m.config = &cfg
  160. return err
  161. }
  162. m.logf("Resolvercfg: %v", logger.ArgWriter(func(w *bufio.Writer) {
  163. rcfg.WriteToBufioWriter(w)
  164. }))
  165. m.logf("OScfg: %v", logger.ArgWriter(func(w *bufio.Writer) {
  166. ocfg.WriteToBufioWriter(w)
  167. }))
  168. if err := m.resolver.SetConfig(rcfg); err != nil {
  169. m.config = nil
  170. return err
  171. }
  172. if err := m.setDNSLocked(ocfg); err != nil {
  173. return err
  174. }
  175. m.health.SetHealthy(osConfigurationSetWarnable)
  176. m.config = &cfg
  177. return nil
  178. }
  179. func (m *Manager) setDNSLocked(ocfg OSConfig) error {
  180. if err := m.os.SetDNS(ocfg); err != nil {
  181. m.config = nil
  182. m.health.SetUnhealthy(osConfigurationSetWarnable, health.Args{health.ArgError: err.Error()})
  183. return err
  184. }
  185. return nil
  186. }
  187. // compileHostEntries creates a list of single-label resolutions possible
  188. // from the configured hosts and search domains.
  189. // The entries are compiled in the order of the search domains, then the hosts.
  190. // The returned list is sorted by the first hostname in each entry.
  191. func compileHostEntries(cfg Config) (hosts []*HostEntry) {
  192. didLabel := make(map[string]bool, len(cfg.Hosts))
  193. hostsMap := make(map[netip.Addr]*HostEntry, len(cfg.Hosts))
  194. for _, sd := range cfg.SearchDomains {
  195. for h, ips := range cfg.Hosts {
  196. if !sd.Contains(h) || h.NumLabels() != (sd.NumLabels()+1) {
  197. continue
  198. }
  199. ipHosts := []string{string(h.WithTrailingDot())}
  200. if label := dnsname.FirstLabel(string(h)); !didLabel[label] {
  201. didLabel[label] = true
  202. ipHosts = append(ipHosts, label)
  203. }
  204. for _, ip := range ips {
  205. if cfg.OnlyIPv6 && ip.Is4() {
  206. continue
  207. }
  208. if e := hostsMap[ip]; e != nil {
  209. e.Hosts = append(e.Hosts, ipHosts...)
  210. } else {
  211. hostsMap[ip] = &HostEntry{
  212. Addr: ip,
  213. Hosts: ipHosts,
  214. }
  215. }
  216. // Only add IPv4 or IPv6 per host, like we do in the resolver.
  217. break
  218. }
  219. }
  220. }
  221. if len(hostsMap) == 0 {
  222. return nil
  223. }
  224. hosts = slicesx.MapValues(hostsMap)
  225. slices.SortFunc(hosts, func(a, b *HostEntry) int {
  226. if len(a.Hosts) == 0 && len(b.Hosts) == 0 {
  227. return 0
  228. } else if len(a.Hosts) == 0 {
  229. return -1
  230. } else if len(b.Hosts) == 0 {
  231. return 1
  232. }
  233. return strings.Compare(a.Hosts[0], b.Hosts[0])
  234. })
  235. return hosts
  236. }
  237. var osConfigurationReadWarnable = health.Register(&health.Warnable{
  238. Code: "dns-read-os-config-failed",
  239. Title: "Failed to read system DNS configuration",
  240. Text: func(args health.Args) string {
  241. return fmt.Sprintf("Tailscale failed to fetch the DNS configuration of your device: %v", args[health.ArgError])
  242. },
  243. Severity: health.SeverityLow,
  244. DependsOn: []*health.Warnable{health.NetworkStatusWarnable},
  245. })
  246. var osConfigurationSetWarnable = health.Register(&health.Warnable{
  247. Code: "dns-set-os-config-failed",
  248. Title: "Failed to set system DNS configuration",
  249. Text: func(args health.Args) string {
  250. return fmt.Sprintf("Tailscale failed to set the DNS configuration of your device: %v", args[health.ArgError])
  251. },
  252. Severity: health.SeverityMedium,
  253. DependsOn: []*health.Warnable{health.NetworkStatusWarnable},
  254. })
  255. // compileConfig converts cfg into a quad-100 resolver configuration
  256. // and an OS-level configuration.
  257. func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig, err error) {
  258. // The internal resolver always gets MagicDNS hosts and
  259. // authoritative suffixes, even if we don't propagate MagicDNS to
  260. // the OS.
  261. rcfg.Hosts = cfg.Hosts
  262. routes := map[dnsname.FQDN][]*dnstype.Resolver{} // assigned conditionally to rcfg.Routes below.
  263. var propagateHostsToOS bool
  264. for suffix, resolvers := range cfg.Routes {
  265. if len(resolvers) == 0 {
  266. propagateHostsToOS = true
  267. rcfg.LocalDomains = append(rcfg.LocalDomains, suffix)
  268. } else {
  269. routes[suffix] = resolvers
  270. }
  271. }
  272. // Similarly, the OS always gets search paths.
  273. ocfg.SearchDomains = cfg.SearchDomains
  274. if propagateHostsToOS && m.goos == "windows" {
  275. ocfg.Hosts = compileHostEntries(cfg)
  276. }
  277. // Deal with trivial configs first.
  278. switch {
  279. case !cfg.needsOSResolver() || runtime.GOOS == "plan9":
  280. // Set search domains, but nothing else. This also covers the
  281. // case where cfg is entirely zero, in which case these
  282. // configs clear all Tailscale DNS settings.
  283. return rcfg, ocfg, nil
  284. case cfg.hasDefaultIPResolversOnly() && !cfg.hasHostsWithoutSplitDNSRoutes():
  285. // Trivial CorpDNS configuration, just override the OS resolver.
  286. //
  287. // If there are hosts (ExtraRecords) that are not covered by an existing
  288. // SplitDNS route, then we don't go into this path so that we fall into
  289. // the next case and send the extra record hosts queries through
  290. // 100.100.100.100 instead where we can answer them.
  291. //
  292. // TODO: for OSes that support it, pass IP:port and DoH
  293. // addresses directly to OS.
  294. // https://github.com/tailscale/tailscale/issues/1666
  295. ocfg.Nameservers = toIPsOnly(cfg.DefaultResolvers)
  296. return rcfg, ocfg, nil
  297. case cfg.hasDefaultResolvers():
  298. // Default resolvers plus other stuff always ends up proxying
  299. // through quad-100.
  300. rcfg.Routes = routes
  301. rcfg.Routes["."] = cfg.DefaultResolvers
  302. ocfg.Nameservers = cfg.serviceIPs(m.knobs)
  303. return rcfg, ocfg, nil
  304. }
  305. // From this point on, we're figuring out split DNS
  306. // configurations. The possible cases don't return directly any
  307. // more, because as a final step we have to handle the case where
  308. // the OS can't do split DNS.
  309. // Workaround for
  310. // https://github.com/tailscale/corp/issues/1662. Even though
  311. // Windows natively supports split DNS, it only configures linux
  312. // containers using whatever the primary is, and doesn't apply
  313. // NRPT rules to DNS traffic coming from WSL.
  314. //
  315. // In order to make WSL work okay when the host Windows is using
  316. // Tailscale, we need to set up quad-100 as a "full proxy"
  317. // resolver, regardless of whether Windows itself can do split
  318. // DNS. We still make Windows do split DNS itself when it can, but
  319. // quad-100 will still have the full split configuration as well,
  320. // and so can service WSL requests correctly.
  321. //
  322. // This bool is used in a couple of places below to implement this
  323. // workaround.
  324. isWindows := m.goos == "windows"
  325. isApple := (m.goos == "darwin" || m.goos == "ios")
  326. if len(cfg.singleResolverSet()) > 0 && m.os.SupportsSplitDNS() && !isWindows && !isApple {
  327. // Split DNS configuration requested, where all split domains
  328. // go to the same resolvers. We can let the OS do it.
  329. ocfg.Nameservers = toIPsOnly(cfg.singleResolverSet())
  330. ocfg.MatchDomains = cfg.matchDomains()
  331. return rcfg, ocfg, nil
  332. }
  333. // Split DNS configuration with either multiple upstream routes,
  334. // or routes + MagicDNS, or just MagicDNS, or on an OS that cannot
  335. // split-DNS. Install a split config pointing at quad-100.
  336. rcfg.Routes = routes
  337. ocfg.Nameservers = cfg.serviceIPs(m.knobs)
  338. var baseCfg *OSConfig // base config; non-nil if/when known
  339. // Even though Apple devices can do split DNS, they don't provide a way to
  340. // selectively answer ExtraRecords, and ignore other DNS traffic. As a
  341. // workaround, we read the existing default resolver configuration and use
  342. // that as the forwarder for all DNS traffic that quad-100 doesn't handle.
  343. if isApple || !m.os.SupportsSplitDNS() {
  344. // If the OS can't do native split-dns, read out the underlying
  345. // resolver config and blend it into our config. On apple platforms, [OSConfigurator.GetBaseConfig]
  346. // has a tendency to temporarily fail if called immediately following
  347. // an interface change. These failures should be retried if/when the OS
  348. // indicates that the DNS configuration has changed via [RecompileDNSConfig].
  349. cfg, err := m.os.GetBaseConfig()
  350. if err == nil {
  351. baseCfg = &cfg
  352. } else if isApple && err == ErrGetBaseConfigNotSupported {
  353. // This is currently (2022-10-13) expected on certain iOS and macOS
  354. // builds.
  355. } else {
  356. m.health.SetUnhealthy(osConfigurationReadWarnable, health.Args{health.ArgError: err.Error()})
  357. return resolver.Config{}, OSConfig{}, err
  358. }
  359. m.health.SetHealthy(osConfigurationReadWarnable)
  360. }
  361. if baseCfg == nil {
  362. // If there was no base config, then we need to fallback to SplitDNS mode.
  363. ocfg.MatchDomains = cfg.matchDomains()
  364. } else {
  365. // On iOS only (for now), check if all route names point to resources inside the tailnet.
  366. // If so, we can set those names as MatchDomains to enable a split DNS configuration
  367. // which will help preserve battery life.
  368. // Because on iOS MatchDomains must equal SearchDomains, we cannot do this when
  369. // we have any Routes outside the tailnet. Otherwise when app connectors are enabled,
  370. // a query for 'work-laptop' might lead to search domain expansion, resolving
  371. // as 'work-laptop.aws.com' for example.
  372. if m.goos == "ios" && rcfg.RoutesRequireNoCustomResolvers() {
  373. if !m.disableSplitDNSOptimization() {
  374. for r := range rcfg.Routes {
  375. ocfg.MatchDomains = append(ocfg.MatchDomains, r)
  376. }
  377. } else {
  378. m.logf("iOS split DNS is disabled by nodeattr")
  379. }
  380. }
  381. var defaultRoutes []*dnstype.Resolver
  382. for _, ip := range baseCfg.Nameservers {
  383. defaultRoutes = append(defaultRoutes, &dnstype.Resolver{Addr: ip.String()})
  384. }
  385. rcfg.Routes["."] = defaultRoutes
  386. ocfg.SearchDomains = append(ocfg.SearchDomains, baseCfg.SearchDomains...)
  387. }
  388. return rcfg, ocfg, nil
  389. }
  390. func (m *Manager) disableSplitDNSOptimization() bool {
  391. return m.knobs != nil && m.knobs.DisableSplitDNSWhenNoCustomResolvers.Load()
  392. }
  393. // toIPsOnly returns only the IP portion of dnstype.Resolver.
  394. // Only safe to use if the resolvers slice has been cleared of
  395. // DoH or custom-port entries with something like hasDefaultIPResolversOnly.
  396. func toIPsOnly(resolvers []*dnstype.Resolver) (ret []netip.Addr) {
  397. for _, r := range resolvers {
  398. if ipp, ok := r.IPPort(); ok && ipp.Port() == 53 {
  399. ret = append(ret, ipp.Addr())
  400. }
  401. }
  402. return ret
  403. }
  404. // Query executes a DNS query received from the given address. The query is
  405. // provided in bs as a wire-encoded DNS query without any transport header.
  406. // This method is called for requests arriving over UDP and TCP.
  407. //
  408. // The "family" parameter should indicate what type of DNS query this is:
  409. // either "tcp" or "udp".
  410. func (m *Manager) Query(ctx context.Context, bs []byte, family string, from netip.AddrPort) ([]byte, error) {
  411. select {
  412. case <-m.ctx.Done():
  413. return nil, net.ErrClosed
  414. default:
  415. // continue
  416. }
  417. if n := atomic.AddInt32(&m.activeQueriesAtomic, 1); n > maxActiveQueries {
  418. atomic.AddInt32(&m.activeQueriesAtomic, -1)
  419. metricDNSQueryErrorQueue.Add(1)
  420. return nil, errFullQueue
  421. }
  422. defer atomic.AddInt32(&m.activeQueriesAtomic, -1)
  423. return m.resolver.Query(ctx, bs, family, from)
  424. }
  425. const (
  426. // RFC 7766 6.2 recommends connection reuse & request pipelining
  427. // be undertaken, and the connection be closed by the server
  428. // using an idle timeout on the order of seconds.
  429. idleTimeoutTCP = 45 * time.Second
  430. // The RFCs don't specify the max size of a TCP-based DNS query,
  431. // but we want to keep this reasonable. Given payloads are typically
  432. // much larger and all known client send a single query, I've arbitrarily
  433. // chosen 4k.
  434. maxReqSizeTCP = 4096
  435. )
  436. // TrampleDNS is an an event indicating we detected that DNS config was
  437. // overwritten by another process.
  438. type TrampleDNS struct {
  439. LastTrample time.Time
  440. TramplesInTimeout int64
  441. }
  442. // dnsTCPSession services DNS requests sent over TCP.
  443. type dnsTCPSession struct {
  444. m *Manager
  445. conn net.Conn
  446. srcAddr netip.AddrPort
  447. readClosing chan struct{}
  448. responses chan []byte // DNS replies pending writing
  449. ctx context.Context
  450. closeCtx context.CancelFunc
  451. }
  452. func (s *dnsTCPSession) handleWrites() {
  453. defer s.conn.Close()
  454. defer s.closeCtx()
  455. // NOTE(andrew): we explicitly do not close the 'responses' channel
  456. // when this function exits. If we hit an error and return, we could
  457. // still have outstanding 'handleQuery' goroutines running, and if we
  458. // closed this channel they'd end up trying to send on a closed channel
  459. // when they finish.
  460. //
  461. // Because we call closeCtx, those goroutines will not hang since they
  462. // select on <-s.ctx.Done() as well as s.responses.
  463. for {
  464. select {
  465. case <-s.readClosing:
  466. return // connection closed or timeout, teardown time
  467. case resp := <-s.responses:
  468. s.conn.SetWriteDeadline(time.Now().Add(idleTimeoutTCP))
  469. if err := binary.Write(s.conn, binary.BigEndian, uint16(len(resp))); err != nil {
  470. s.m.logf("tcp write (len): %v", err)
  471. return
  472. }
  473. if _, err := s.conn.Write(resp); err != nil {
  474. s.m.logf("tcp write (response): %v", err)
  475. return
  476. }
  477. }
  478. }
  479. }
  480. func (s *dnsTCPSession) handleQuery(q []byte) {
  481. resp, err := s.m.Query(s.ctx, q, "tcp", s.srcAddr)
  482. if err != nil {
  483. s.m.logf("tcp query: %v", err)
  484. return
  485. }
  486. // See note in handleWrites (above) regarding this select{}
  487. select {
  488. case <-s.ctx.Done():
  489. case s.responses <- resp:
  490. }
  491. }
  492. func (s *dnsTCPSession) handleReads() {
  493. defer s.conn.Close()
  494. defer close(s.readClosing)
  495. for {
  496. select {
  497. case <-s.ctx.Done():
  498. return
  499. default:
  500. s.conn.SetReadDeadline(time.Now().Add(idleTimeoutTCP))
  501. var reqLen uint16
  502. if err := binary.Read(s.conn, binary.BigEndian, &reqLen); err != nil {
  503. if err == io.EOF || err == io.ErrClosedPipe {
  504. return // connection closed nominally, we gucci
  505. }
  506. s.m.logf("tcp read (len): %v", err)
  507. return
  508. }
  509. if int(reqLen) > maxReqSizeTCP {
  510. s.m.logf("tcp request too large (%d > %d)", reqLen, maxReqSizeTCP)
  511. return
  512. }
  513. buf := make([]byte, int(reqLen))
  514. if _, err := io.ReadFull(s.conn, buf); err != nil {
  515. s.m.logf("tcp read (payload): %v", err)
  516. return
  517. }
  518. select {
  519. case <-s.ctx.Done():
  520. return
  521. default:
  522. // NOTE: by kicking off the query handling in a
  523. // new goroutine, it is possible that we'll
  524. // deliver responses out-of-order. This is
  525. // explicitly allowed by RFC7766, Section
  526. // 6.2.1.1 ("Query Pipelining").
  527. go s.handleQuery(buf)
  528. }
  529. }
  530. }
  531. }
  532. // HandleTCPConn implements magicDNS over TCP, taking a connection and
  533. // servicing DNS requests sent down it.
  534. func (m *Manager) HandleTCPConn(conn net.Conn, srcAddr netip.AddrPort) {
  535. s := dnsTCPSession{
  536. m: m,
  537. conn: conn,
  538. srcAddr: srcAddr,
  539. responses: make(chan []byte),
  540. readClosing: make(chan struct{}),
  541. }
  542. s.ctx, s.closeCtx = context.WithCancel(m.ctx)
  543. go s.handleReads()
  544. s.handleWrites()
  545. }
  546. func (m *Manager) Down() error {
  547. if !buildfeatures.HasDNS {
  548. return nil
  549. }
  550. m.ctxCancel()
  551. if err := m.os.Close(); err != nil {
  552. return err
  553. }
  554. m.eventClient.Close()
  555. m.resolver.Close()
  556. return nil
  557. }
  558. func (m *Manager) FlushCaches() error {
  559. if !buildfeatures.HasDNS {
  560. return nil
  561. }
  562. return flushCaches()
  563. }
  564. // CleanUp restores the system DNS configuration to its original state
  565. // in case the Tailscale daemon terminated without closing the router.
  566. // No other state needs to be instantiated before this runs.
  567. //
  568. // health must not be nil
  569. func CleanUp(logf logger.Logf, netMon *netmon.Monitor, bus *eventbus.Bus, health *health.Tracker, interfaceName string) {
  570. if !buildfeatures.HasDNS {
  571. return
  572. }
  573. oscfg, err := NewOSConfigurator(logf, health, bus, policyclient.Get(), nil, interfaceName)
  574. if err != nil {
  575. logf("creating dns cleanup: %v", err)
  576. return
  577. }
  578. d := &tsdial.Dialer{Logf: logf}
  579. d.SetNetMon(netMon)
  580. d.SetBus(bus)
  581. dns := NewManager(logf, oscfg, health, d, nil, nil, runtime.GOOS, bus)
  582. if err := dns.Down(); err != nil {
  583. logf("dns down: %v", err)
  584. }
  585. }
  586. var metricDNSQueryErrorQueue = clientmetric.NewCounter("dns_query_local_error_queue")