diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 69ff66596..8d48b6d7c 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -247,7 +247,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/net/tsaddr from tailscale.com/ipn+ tailscale.com/net/tsdial from tailscale.com/control/controlclient+ 💣 tailscale.com/net/tshttpproxy from tailscale.com/control/controlclient+ - tailscale.com/net/tstun from tailscale.com/net/dns+ + tailscale.com/net/tstun from tailscale.com/cmd/tailscaled+ tailscale.com/net/wsconn from tailscale.com/control/controlhttp+ tailscale.com/paths from tailscale.com/ipn/ipnlocal+ 💣 tailscale.com/portlist from tailscale.com/ipn/ipnlocal diff --git a/net/dns/manager.go b/net/dns/manager.go index 00fb7029e..1c51ad108 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -19,41 +19,21 @@ import ( "golang.org/x/exp/slices" "tailscale.com/health" "tailscale.com/net/dns/resolver" - "tailscale.com/net/packet" - "tailscale.com/net/tsaddr" "tailscale.com/net/tsdial" - "tailscale.com/net/tstun" "tailscale.com/types/dnstype" - "tailscale.com/types/ipproto" "tailscale.com/types/logger" "tailscale.com/util/clientmetric" "tailscale.com/util/dnsname" "tailscale.com/wgengine/monitor" ) -var ( - magicDNSIP = tsaddr.TailscaleServiceIP() - magicDNSIPv6 = tsaddr.TailscaleServiceIPv6() -) - var ( errFullQueue = errors.New("request queue full") ) -// maxActiveQueries returns the maximal number of DNS requests that be -// can running. -// If EnqueueRequest is called when this many requests are already pending, -// the request will be dropped to avoid blocking the caller. -func maxActiveQueries() int32 { - if runtime.GOOS == "ios" { - // For memory paranoia reasons on iOS, match the - // historical Tailscale 1.x..1.8 behavior for now - // (just before the 1.10 release). - return 64 - } - // But for other platforms, allow more burstiness: - return 256 -} +// maxActiveQueries returns the maximal number of DNS requests that can +// be running. +const maxActiveQueries = 256 // We use file-ignore below instead of ignore because on some platforms, // the lint exception is necessary and on others it is not, @@ -75,13 +55,6 @@ type response struct { type Manager struct { logf logger.Logf - // When netstack is not used, Manager implements magic DNS. - // In this case, responses tracks completed DNS requests - // which need a response, and NextPacket() synthesizes a - // fake IP+UDP header to finish assembling the response. - // - // TODO(tom): Rip out once all platforms use netstack. - responses chan response activeQueriesAtomic int32 ctx context.Context // good until Down @@ -98,10 +71,9 @@ func NewManager(logf logger.Logf, oscfg OSConfigurator, linkMon *monitor.Mon, di } logf = logger.WithPrefix(logf, "dns: ") m := &Manager{ - logf: logf, - resolver: resolver.New(logf, linkMon, linkSel, dialer), - os: oscfg, - responses: make(chan response), + logf: logf, + resolver: resolver.New(logf, linkMon, linkSel, dialer), + os: oscfg, } m.ctx, m.ctxCancel = context.WithCancel(context.Background()) m.logf("using %T", m.os) @@ -316,89 +288,6 @@ func toIPsOnly(resolvers []*dnstype.Resolver) (ret []netip.Addr) { return ret } -// EnqueuePacket is the legacy path for handling magic DNS traffic, and is -// called with a DNS request payload. -// -// TODO(tom): Rip out once all platforms use netstack. -func (m *Manager) EnqueuePacket(bs []byte, proto ipproto.Proto, from, to netip.AddrPort) error { - if to.Port() != 53 || proto != ipproto.UDP { - return nil - } - - if n := atomic.AddInt32(&m.activeQueriesAtomic, 1); n > maxActiveQueries() { - atomic.AddInt32(&m.activeQueriesAtomic, -1) - metricDNSQueryErrorQueue.Add(1) - return errFullQueue - } - - go func() { - resp, err := m.resolver.Query(m.ctx, bs, from) - if err != nil { - atomic.AddInt32(&m.activeQueriesAtomic, -1) - m.logf("dns query: %v", err) - return - } - - select { - case <-m.ctx.Done(): - return - case m.responses <- response{resp, from}: - } - }() - return nil -} - -// NextPacket is the legacy path for obtaining DNS results in response to -// magic DNS queries. It blocks until a response is available. -// -// TODO(tom): Rip out once all platforms use netstack. -func (m *Manager) NextPacket() ([]byte, error) { - var resp response - select { - case <-m.ctx.Done(): - return nil, net.ErrClosed - case resp = <-m.responses: - // continue - } - - // Unused space is needed further down the stack. To avoid extra - // allocations/copying later on, we allocate such space here. - const offset = tstun.PacketStartOffset - - var buf []byte - switch { - case resp.to.Addr().Is4(): - h := packet.UDP4Header{ - IP4Header: packet.IP4Header{ - Src: magicDNSIP, - Dst: resp.to.Addr(), - }, - SrcPort: 53, - DstPort: resp.to.Port(), - } - hlen := h.Len() - buf = make([]byte, offset+hlen+len(resp.pkt)) - copy(buf[offset+hlen:], resp.pkt) - h.Marshal(buf[offset:]) - case resp.to.Addr().Is6(): - h := packet.UDP6Header{ - IP6Header: packet.IP6Header{ - Src: magicDNSIPv6, - Dst: resp.to.Addr(), - }, - SrcPort: 53, - DstPort: resp.to.Port(), - } - hlen := h.Len() - buf = make([]byte, offset+hlen+len(resp.pkt)) - copy(buf[offset+hlen:], resp.pkt) - h.Marshal(buf[offset:]) - } - - atomic.AddInt32(&m.activeQueriesAtomic, -1) - return buf, nil -} - // Query executes a DNS query received from the given address. The query is // provided in bs as a wire-encoded DNS query without any transport header. // This method is called for requests arriving over UDP and TCP. @@ -410,7 +299,7 @@ func (m *Manager) Query(ctx context.Context, bs []byte, from netip.AddrPort) ([] // continue } - if n := atomic.AddInt32(&m.activeQueriesAtomic, 1); n > maxActiveQueries() { + if n := atomic.AddInt32(&m.activeQueriesAtomic, 1); n > maxActiveQueries { atomic.AddInt32(&m.activeQueriesAtomic, -1) metricDNSQueryErrorQueue.Add(1) return nil, errFullQueue diff --git a/wgengine/userspace.go b/wgengine/userspace.go index e96c823a5..51e6d7c43 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -11,7 +11,6 @@ import ( "errors" "fmt" "io" - "net" "net/netip" "reflect" "runtime" @@ -56,13 +55,6 @@ import ( "tailscale.com/wgengine/wglog" ) -const magicDNSPort = 53 - -var ( - magicDNSIP = tsaddr.TailscaleServiceIP() - magicDNSIPv6 = tsaddr.TailscaleServiceIPv6() -) - // Lazy wireguard-go configuration parameters. const ( // lazyPeerIdleThreshold is the idle duration after @@ -462,8 +454,6 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error) e.logf("Starting link monitor...") e.linkMon.Start() - go e.pollResolver() - e.logf("Engine created.") return e, nil } @@ -491,19 +481,6 @@ func echoRespondToAll(p *packet.Parsed, t *tstun.Wrapper) filter.Response { // tailscaled directly. Other packets are allowed to proceed into the // main ACL filter. func (e *userspaceEngine) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper) filter.Response { - // Handle traffic to the service IP. - // TODO(tom): Netstack handles this when it is installed. Rip all - // this out once netstack is used on all platforms. - switch p.Dst.Addr() { - case magicDNSIP, magicDNSIPv6: - err := e.dns.EnqueuePacket(append([]byte(nil), p.Payload()...), p.IPProto, p.Src, p.Dst) - if err != nil { - e.logf("dns: enqueue: %v", err) - } - metricMagicDNSPacketIn.Add(1) - return filter.Drop - } - if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { isLocalAddr, ok := e.isLocalAddr.LoadOk() if !ok { @@ -523,27 +500,6 @@ func (e *userspaceEngine) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper) return filter.Accept } -// pollResolver reads packets from the DNS resolver and injects them inbound. -// -// TODO(tom): Remove this fallback path (via NextPacket()) once all -// platforms use netstack. -func (e *userspaceEngine) pollResolver() { - for { - bs, err := e.dns.NextPacket() - if errors.Is(err, net.ErrClosed) { - return - } - if err != nil { - e.logf("dns: error: %v", err) - continue - } - - // The leading empty space required by the semantics of - // InjectInboundDirect is allocated in NextPacket(). - e.tundev.InjectInboundDirect(bs, tstun.PacketStartOffset) - } -} - var debugTrimWireguard = envknob.RegisterOptBool("TS_DEBUG_TRIM_WIREGUARD") // forceFullWireguardConfig reports whether we should give wireguard our full