diff --git a/cmd/tailscaled/depaware-minlinux.txt b/cmd/tailscaled/depaware-minlinux.txt index 5d8f2ea92..fc56c1b23 100644 --- a/cmd/tailscaled/depaware-minlinux.txt +++ b/cmd/tailscaled/depaware-minlinux.txt @@ -4,7 +4,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L filippo.io/edwards25519/field from filippo.io/edwards25519 github.com/bits-and-blooms/bitset from github.com/gaissmai/bart L github.com/coreos/go-iptables/iptables from tailscale.com/util/linuxfw - L github.com/digitalocean/go-smbios/smbios from tailscale.com/posture github.com/gaissmai/bart from tailscale.com/net/ipset+ github.com/go-json-experiment/json from tailscale.com/types/opt+ github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json+ @@ -53,7 +52,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de 💣 go4.org/mem from tailscale.com/control/controlbase+ go4.org/netipx from tailscale.com/ipn/ipnlocal+ tailscale.com from tailscale.com/version - tailscale.com/appc from tailscale.com/ipn/ipnlocal tailscale.com/atomicfile from tailscale.com/ipn+ tailscale.com/client/tailscale/apitype from tailscale.com/ipn/ipnlocal+ tailscale.com/clientupdate from tailscale.com/ipn/ipnlocal+ @@ -131,7 +129,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/omit from tailscale.com/ipn/conffile tailscale.com/paths from tailscale.com/cmd/tailscaled+ 💣 tailscale.com/portlist from tailscale.com/ipn/ipnlocal - tailscale.com/posture from tailscale.com/ipn/ipnlocal tailscale.com/proxymap from tailscale.com/tsd tailscale.com/safesocket from tailscale.com/cmd/tailscaled+ tailscale.com/syncs from tailscale.com/cmd/tailscaled+ @@ -143,14 +140,13 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/tstime/mono from tailscale.com/net/tstun+ tailscale.com/tstime/rate from tailscale.com/derp+ tailscale.com/tsweb/varz from tailscale.com/cmd/tailscaled+ - tailscale.com/types/appctype from tailscale.com/ipn/ipnlocal tailscale.com/types/dnstype from tailscale.com/client/tailscale/apitype+ tailscale.com/types/empty from tailscale.com/ipn+ tailscale.com/types/flagtype from tailscale.com/cmd/tailscaled tailscale.com/types/ipproto from tailscale.com/ipn+ tailscale.com/types/key from tailscale.com/cmd/tailscaled+ tailscale.com/types/lazy from tailscale.com/util/cloudenv+ - tailscale.com/types/logger from tailscale.com/appc+ + tailscale.com/types/logger from tailscale.com/clientupdate+ tailscale.com/types/logid from tailscale.com/cmd/tailscaled+ tailscale.com/types/netlogtype from tailscale.com/net/connstats+ tailscale.com/types/netmap from tailscale.com/control/controlclient+ @@ -162,16 +158,16 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/tkatype from tailscale.com/control/controlclient+ - tailscale.com/types/views from tailscale.com/appc+ + tailscale.com/types/views from tailscale.com/control/controlclient+ tailscale.com/util/cibuild from tailscale.com/health - tailscale.com/util/clientmetric from tailscale.com/appc+ + tailscale.com/util/clientmetric from tailscale.com/cmd/tailscaled+ tailscale.com/util/cloudenv from tailscale.com/hostinfo+ tailscale.com/util/cmpver from tailscale.com/clientupdate+ tailscale.com/util/ctxkey from tailscale.com/derp+ 💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+ L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics+ - tailscale.com/util/dnsname from tailscale.com/appc+ - tailscale.com/util/execqueue from tailscale.com/appc+ + tailscale.com/util/dnsname from tailscale.com/hostinfo+ + tailscale.com/util/execqueue from tailscale.com/control/controlclient tailscale.com/util/goroutines from tailscale.com/ipn/ipnlocal tailscale.com/util/groupmember from tailscale.com/ipn/ipnauth 💣 tailscale.com/util/hashx from tailscale.com/util/deephash @@ -179,7 +175,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/util/httpm from tailscale.com/clientupdate/distsign+ tailscale.com/util/lineiter from tailscale.com/hostinfo+ L tailscale.com/util/linuxfw from tailscale.com/net/netns+ - tailscale.com/util/mak from tailscale.com/appc+ + tailscale.com/util/mak from tailscale.com/control/controlclient+ tailscale.com/util/multierr from tailscale.com/cmd/tailscaled+ tailscale.com/util/must from tailscale.com/clientupdate/distsign+ tailscale.com/util/nocasemaps from tailscale.com/types/ipproto @@ -193,7 +189,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/util/ringbuffer from tailscale.com/wgengine/magicsock tailscale.com/util/set from tailscale.com/control/controlclient+ tailscale.com/util/singleflight from tailscale.com/control/controlclient+ - tailscale.com/util/slicesx from tailscale.com/appc+ + tailscale.com/util/slicesx from tailscale.com/control/controlclient+ tailscale.com/util/syspolicy from tailscale.com/control/controlclient+ tailscale.com/util/syspolicy/internal from tailscale.com/util/syspolicy+ tailscale.com/util/syspolicy/internal/loggerx from tailscale.com/util/syspolicy+ @@ -309,7 +305,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de html from net/http/pprof+ io from archive/tar+ io/fs from archive/tar+ - L io/ioutil from github.com/digitalocean/go-smbios/smbios+ + L io/ioutil from github.com/godbus/dbus/v5+ iter from github.com/go-json-experiment/json/jsontext+ log from expvar+ log/internal from log diff --git a/ipn/ipnlocal/c2n.go b/ipn/ipnlocal/c2n.go index 7688dfe63..0b354e755 100644 --- a/ipn/ipnlocal/c2n.go +++ b/ipn/ipnlocal/c2n.go @@ -24,12 +24,10 @@ import ( "tailscale.com/envknob" "tailscale.com/ipn" "tailscale.com/net/sockstats" - "tailscale.com/posture" "tailscale.com/tailcfg" "tailscale.com/util/clientmetric" "tailscale.com/util/goroutines" "tailscale.com/util/set" - "tailscale.com/util/syspolicy" "tailscale.com/version" "tailscale.com/version/distro" ) @@ -63,12 +61,6 @@ var c2nHandlers = map[methodAndPath]c2nHandler{ req("GET /update"): handleC2NUpdateGet, req("POST /update"): handleC2NUpdatePost, - // Device posture. - req("GET /posture/identity"): handleC2NPostureIdentityGet, - - // App Connectors. - req("GET /appconnector/routes"): handleC2NAppConnectorDomainRoutesGet, - // Linux netfilter. req("POST /netfilter-kind"): handleC2NSetNetfilterKind, @@ -220,26 +212,6 @@ func handleC2NSockStats(b *LocalBackend, w http.ResponseWriter, r *http.Request) fmt.Fprintf(w, "debug info: %v\n", sockstats.DebugInfo()) } -// handleC2NAppConnectorDomainRoutesGet handles returning the domains -// that the app connector is responsible for, as well as the resolved -// IP addresses for each domain. If the node is not configured as -// an app connector, an empty map is returned. -func handleC2NAppConnectorDomainRoutesGet(b *LocalBackend, w http.ResponseWriter, r *http.Request) { - b.logf("c2n: GET /appconnector/routes received") - - var res tailcfg.C2NAppConnectorDomainRoutesResponse - if b.appConnector == nil { - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(res) - return - } - - res.Domains = b.appConnector.DomainRoutes() - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(res) -} - func handleC2NSetNetfilterKind(b *LocalBackend, w http.ResponseWriter, r *http.Request) { b.logf("c2n: POST /netfilter-kind received") @@ -320,49 +292,6 @@ func handleC2NUpdatePost(b *LocalBackend, w http.ResponseWriter, r *http.Request res.Started = true } -func handleC2NPostureIdentityGet(b *LocalBackend, w http.ResponseWriter, r *http.Request) { - b.logf("c2n: GET /posture/identity received") - - res := tailcfg.C2NPostureIdentityResponse{} - - // Only collect posture identity if enabled on the client, - // this will first check syspolicy, MDM settings like Registry - // on Windows or defaults on macOS. If they are not set, it falls - // back to the cli-flag, `--posture-checking`. - choice, err := syspolicy.GetPreferenceOption(syspolicy.PostureChecking) - if err != nil { - b.logf( - "c2n: failed to read PostureChecking from syspolicy, returning default from CLI: %s; got error: %s", - b.Prefs().PostureChecking(), - err, - ) - } - - if choice.ShouldEnable(b.Prefs().PostureChecking()) { - res.SerialNumbers, err = posture.GetSerialNumbers(b.logf) - if err != nil { - b.logf("c2n: GetSerialNumbers returned error: %v", err) - } - - // TODO(tailscale/corp#21371, 2024-07-10): once this has landed in a stable release - // and looks good in client metrics, remove this parameter and always report MAC - // addresses. - if r.FormValue("hwaddrs") == "true" { - res.IfaceHardwareAddrs, err = posture.GetHardwareAddrs() - if err != nil { - b.logf("c2n: GetHardwareAddrs returned error: %v", err) - } - } - } else { - res.PostureDisabled = true - } - - b.logf("c2n: posture identity disabled=%v reported %d serials %d hwaddrs", res.PostureDisabled, len(res.SerialNumbers), len(res.IfaceHardwareAddrs)) - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(res) -} - func (b *LocalBackend) newC2NUpdateResponse() tailcfg.C2NUpdateResponse { // If NewUpdater does not return an error, we can update the installation. // diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index ee2c07064..9628413ad 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -38,7 +38,6 @@ import ( "go4.org/netipx" "golang.org/x/net/dns/dnsmessage" - "tailscale.com/appc" "tailscale.com/client/tailscale/apitype" "tailscale.com/clientupdate" "tailscale.com/control/controlclient" @@ -78,7 +77,6 @@ import ( "tailscale.com/taildrop" "tailscale.com/tsd" "tailscale.com/tstime" - "tailscale.com/types/appctype" "tailscale.com/types/dnstype" "tailscale.com/types/empty" "tailscale.com/types/key" @@ -238,10 +236,9 @@ type LocalBackend struct { conf *conffile.Config // latest parsed config, or nil if not in declarative mode pm *profileManager // mu guards access filterHash deephash.Sum - httpTestClient *http.Client // for controlclient. nil by default, used by tests. - ccGen clientGen // function for producing controlclient; lazily populated - sshServer SSHServer // or nil, initialized lazily. - appConnector *appc.AppConnector // or nil, initialized when configured. + httpTestClient *http.Client // for controlclient. nil by default, used by tests. + ccGen clientGen // function for producing controlclient; lazily populated + sshServer SSHServer // or nil, initialized lazily. // notifyCancel cancels notifications to the current SetNotifyCallback. notifyCancel context.CancelFunc cc controlclient.Client @@ -2107,7 +2104,6 @@ func (b *LocalBackend) Start(opts ipn.Options) error { hostinfo.FrontendLogID = opts.FrontendLogID hostinfo.Userspace.Set(b.sys.IsNetstack()) hostinfo.UserspaceRouter.Set(b.sys.IsNetstackRouter()) - hostinfo.AppConnector.Set(b.appConnector != nil) b.logf.JSON(1, "Hostinfo", hostinfo) // TODO(apenwarr): avoid the need to reinit controlclient. @@ -3782,19 +3778,6 @@ func (b *LocalBackend) SetUseExitNodeEnabled(v bool) (ipn.PrefsView, error) { return b.editPrefsLockedOnEntry(mp, unlock) } -// MaybeClearAppConnector clears the routes from any AppConnector if -// AdvertiseRoutes has been set in the MaskedPrefs. -func (b *LocalBackend) MaybeClearAppConnector(mp *ipn.MaskedPrefs) error { - var err error - if b.appConnector != nil && mp.AdvertiseRoutesSet { - err = b.appConnector.ClearRoutes() - if err != nil { - b.logf("appc: clear routes error: %v", err) - } - } - return err -} - func (b *LocalBackend) EditPrefs(mp *ipn.MaskedPrefs) (ipn.PrefsView, error) { if mp.SetsInternal() { return ipn.PrefsView{}, errors.New("can't set Internal fields") @@ -4103,76 +4086,6 @@ func (b *LocalBackend) blockEngineUpdates(block bool) { b.mu.Unlock() } -// reconfigAppConnectorLocked updates the app connector state based on the -// current network map and preferences. -// b.mu must be held. -func (b *LocalBackend) reconfigAppConnectorLocked(nm *netmap.NetworkMap, prefs ipn.PrefsView) { - const appConnectorCapName = "tailscale.com/app-connectors" - defer func() { - if b.hostinfo != nil { - b.hostinfo.AppConnector.Set(b.appConnector != nil) - } - }() - - if !prefs.AppConnector().Advertise { - b.appConnector = nil - return - } - - shouldAppCStoreRoutes := b.ControlKnobs().AppCStoreRoutes.Load() - if b.appConnector == nil || b.appConnector.ShouldStoreRoutes() != shouldAppCStoreRoutes { - var ri *appc.RouteInfo - var storeFunc func(*appc.RouteInfo) error - if shouldAppCStoreRoutes { - var err error - ri, err = b.readRouteInfoLocked() - if err != nil { - ri = &appc.RouteInfo{} - if err != ipn.ErrStateNotExist { - b.logf("Unsuccessful Read RouteInfo: ", err) - } - } - storeFunc = b.storeRouteInfo - } - b.appConnector = appc.NewAppConnector(b.logf, b, ri, storeFunc) - } - if nm == nil { - return - } - - // TODO(raggi): rework the view infrastructure so the large deep clone is no - // longer required - sn := nm.SelfNode.AsStruct() - attrs, err := tailcfg.UnmarshalNodeCapJSON[appctype.AppConnectorAttr](sn.CapMap, appConnectorCapName) - if err != nil { - b.logf("[unexpected] error parsing app connector mapcap: %v", err) - return - } - - // Geometric cost, assumes that the number of advertised tags is small - selfHasTag := func(attrTags []string) bool { - return nm.SelfNode.Tags().ContainsFunc(func(tag string) bool { - return slices.Contains(attrTags, tag) - }) - } - - var ( - domains []string - routes []netip.Prefix - ) - for _, attr := range attrs { - if slices.Contains(attr.Connectors, "*") || selfHasTag(attr.Connectors) { - domains = append(domains, attr.Domains...) - routes = append(routes, attr.Routes...) - } - } - slices.Sort(domains) - slices.SortFunc(routes, func(i, j netip.Prefix) int { return i.Addr().Compare(j.Addr()) }) - domains = slices.Compact(domains) - routes = slices.Compact(routes) - b.appConnector.UpdateDomainsAndRoutes(domains, routes) -} - // authReconfig pushes a new configuration into wgengine, if engine // updates are not currently blocked, based on the cached netmap and // user prefs. @@ -4187,7 +4100,6 @@ func (b *LocalBackend) authReconfig() { dohURL, dohURLOK := exitNodeCanProxyDNS(nm, b.peers, prefs.ExitNodeID()) dcfg := dnsConfigForNetmap(nm, b.peers, prefs, b.keyExpired, b.logf, version.OS()) // If the current node is an app connector, ensure the app connector machine is started - b.reconfigAppConnectorLocked(nm, prefs) closing := b.shutdownCalled b.mu.Unlock() @@ -6085,14 +5997,6 @@ func (b *LocalBackend) OfferingExitNode() bool { return def4 && def6 } -// OfferingAppConnector reports whether b is currently offering app -// connector services. -func (b *LocalBackend) OfferingAppConnector() bool { - b.mu.Lock() - defer b.mu.Unlock() - return b.appConnector != nil -} - // allowExitNodeDNSProxyToServeName reports whether the Exit Node DNS // proxy is allowed to serve responses for the provided DNS name. func (b *LocalBackend) allowExitNodeDNSProxyToServeName(name string) bool { @@ -6722,103 +6626,9 @@ func (b *LocalBackend) DoSelfUpdate() { } } -// ObserveDNSResponse passes a DNS response from the PeerAPI DNS server to the -// App Connector to enable route discovery. -func (b *LocalBackend) ObserveDNSResponse(res []byte) { - var appConnector *appc.AppConnector - b.mu.Lock() - if b.appConnector == nil { - b.mu.Unlock() - return - } - appConnector = b.appConnector - b.mu.Unlock() - - appConnector.ObserveDNSResponse(res) -} - // ErrDisallowedAutoRoute is returned by AdvertiseRoute when a route that is not allowed is requested. var ErrDisallowedAutoRoute = errors.New("route is not allowed") -// AdvertiseRoute implements the appc.RouteAdvertiser interface. It sets a new -// route advertisement if one is not already present in the existing routes. -// If the route is disallowed, ErrDisallowedAutoRoute is returned. -func (b *LocalBackend) AdvertiseRoute(ipps ...netip.Prefix) error { - finalRoutes := b.Prefs().AdvertiseRoutes().AsSlice() - newRoutes := false - - for _, ipp := range ipps { - if !allowedAutoRoute(ipp) { - continue - } - if slices.Contains(finalRoutes, ipp) { - continue - } - - // If the new prefix is already contained by existing routes, skip it. - if coveredRouteRangeNoDefault(finalRoutes, ipp) { - continue - } - - finalRoutes = append(finalRoutes, ipp) - newRoutes = true - } - - if !newRoutes { - return nil - } - - _, err := b.EditPrefs(&ipn.MaskedPrefs{ - Prefs: ipn.Prefs{ - AdvertiseRoutes: finalRoutes, - }, - AdvertiseRoutesSet: true, - }) - return err -} - -// coveredRouteRangeNoDefault checks if a route is already included in a slice of -// prefixes, ignoring default routes in the range. -func coveredRouteRangeNoDefault(finalRoutes []netip.Prefix, ipp netip.Prefix) bool { - for _, r := range finalRoutes { - if r == tsaddr.AllIPv4() || r == tsaddr.AllIPv6() { - continue - } - if ipp.IsSingleIP() { - if r.Contains(ipp.Addr()) { - return true - } - } else { - if r.Contains(ipp.Addr()) && r.Contains(netipx.PrefixLastIP(ipp)) { - return true - } - } - } - return false -} - -// UnadvertiseRoute implements the appc.RouteAdvertiser interface. It removes -// a route advertisement if one is present in the existing routes. -func (b *LocalBackend) UnadvertiseRoute(toRemove ...netip.Prefix) error { - currentRoutes := b.Prefs().AdvertiseRoutes().AsSlice() - finalRoutes := currentRoutes[:0] - - for _, ipp := range currentRoutes { - if slices.Contains(toRemove, ipp) { - continue - } - finalRoutes = append(finalRoutes, ipp) - } - - _, err := b.EditPrefs(&ipn.MaskedPrefs{ - Prefs: ipn.Prefs{ - AdvertiseRoutes: finalRoutes, - }, - AdvertiseRoutesSet: true, - }) - return err -} - // namespace a key with the profile manager's current profile key, if any func namespaceKeyForCurrentProfile(pm *profileManager, key ipn.StateKey) ipn.StateKey { return pm.CurrentProfile().Key + "||" + key @@ -6826,36 +6636,6 @@ func namespaceKeyForCurrentProfile(pm *profileManager, key ipn.StateKey) ipn.Sta const routeInfoStateStoreKey ipn.StateKey = "_routeInfo" -func (b *LocalBackend) storeRouteInfo(ri *appc.RouteInfo) error { - b.mu.Lock() - defer b.mu.Unlock() - if b.pm.CurrentProfile().ID == "" { - return nil - } - key := namespaceKeyForCurrentProfile(b.pm, routeInfoStateStoreKey) - bs, err := json.Marshal(ri) - if err != nil { - return err - } - return b.pm.WriteState(key, bs) -} - -func (b *LocalBackend) readRouteInfoLocked() (*appc.RouteInfo, error) { - if b.pm.CurrentProfile().ID == "" { - return &appc.RouteInfo{}, nil - } - key := namespaceKeyForCurrentProfile(b.pm, routeInfoStateStoreKey) - bs, err := b.pm.Store().ReadState(key) - ri := &appc.RouteInfo{} - if err != nil { - return nil, err - } - if err := json.Unmarshal(bs, ri); err != nil { - return nil, err - } - return ri, nil -} - // seamlessRenewalEnabled reports whether seamless key renewals are enabled // (i.e. we saw our self node with the SeamlessKeyRenewal attr in a netmap). // This enables beta functionality of renewing node keys without breaking diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 979e1ed41..b57ebc7ba 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -522,7 +522,7 @@ func (h *peerAPIHandler) replyToDNSQueries() bool { return true } b := h.ps.b - if !b.OfferingExitNode() && !b.OfferingAppConnector() { + if !b.OfferingExitNode() { // If we're not an exit node or app connector, there's // no point to being a DNS server for somebody. return false @@ -605,12 +605,6 @@ func (h *peerAPIHandler) handleDNSQuery(w http.ResponseWriter, r *http.Request) } return } - // TODO(raggi): consider pushing the integration down into the resolver - // instead to avoid re-parsing the DNS response for improved performance in - // the future. - if h.ps.b.OfferingAppConnector() { - h.ps.b.ObserveDNSResponse(res) - } if pretty { // Non-standard response for interactive debugging. diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index c55351458..316721cae 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -1139,12 +1139,6 @@ func (h *Handler) servePrefs(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - if err := h.b.MaybeClearAppConnector(mp); err != nil { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusInternalServerError) - json.NewEncoder(w).Encode(resJSON{Error: err.Error()}) - return - } var err error prefs, err = h.b.EditPrefs(mp) if err != nil {