feature/appconnectors: start making it modular

Saves 45 KB.

Updates #12614

Change-Id: Iaeb73e69633878ce0a0f58c986024784bbe218f1
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2025-09-30 13:11:48 -07:00
committed by Brad Fitzpatrick
parent 9386a101d8
commit 6c6a1d8341
15 changed files with 263 additions and 157 deletions

View File

@@ -51,9 +51,6 @@ var c2nHandlers = map[methodAndPath]c2nHandler{
// SSH
req("/ssh/usernames"): handleC2NSSHUsernames,
// App Connectors.
req("GET /appconnector/routes"): handleC2NAppConnectorDomainRoutesGet,
// Linux netfilter.
req("POST /netfilter-kind"): handleC2NSetNetfilterKind,
}
@@ -294,27 +291,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
appConnector := b.AppConnector()
if appConnector == nil {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(res)
return
}
res.Domains = 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")

View File

@@ -398,9 +398,10 @@ type LocalBackend struct {
}
// HealthTracker returns the health tracker for the backend.
func (b *LocalBackend) HealthTracker() *health.Tracker {
return b.health
}
func (b *LocalBackend) HealthTracker() *health.Tracker { return b.health }
// Logger returns the logger for the backend.
func (b *LocalBackend) Logger() logger.Logf { return b.logf }
// UserMetricsRegistry returns the usermetrics registry for the backend
func (b *LocalBackend) UserMetricsRegistry() *usermetric.Registry {
@@ -4154,6 +4155,9 @@ func (b *LocalBackend) SetUseExitNodeEnabled(actor ipnauth.Actor, v bool) (ipn.P
// MaybeClearAppConnector clears the routes from any AppConnector if
// AdvertiseRoutes has been set in the MaskedPrefs.
func (b *LocalBackend) MaybeClearAppConnector(mp *ipn.MaskedPrefs) error {
if !buildfeatures.HasAppConnectors {
return nil
}
var err error
if ac := b.AppConnector(); ac != nil && mp.AdvertiseRoutesSet {
err = ac.ClearRoutes()
@@ -4770,6 +4774,9 @@ func (b *LocalBackend) blockEngineUpdates(block bool) {
// current network map and preferences.
// b.mu must be held.
func (b *LocalBackend) reconfigAppConnectorLocked(nm *netmap.NetworkMap, prefs ipn.PrefsView) {
if !buildfeatures.HasAppConnectors {
return
}
const appConnectorCapName = "tailscale.com/app-connectors"
defer func() {
if b.hostinfo != nil {
@@ -4943,7 +4950,9 @@ func (b *LocalBackend) authReconfig() {
b.logf("[v1] authReconfig: ra=%v dns=%v 0x%02x: %v", prefs.RouteAll(), prefs.CorpDNS(), flags, err)
b.initPeerAPIListener()
b.readvertiseAppConnectorRoutes()
if buildfeatures.HasAppConnectors {
b.readvertiseAppConnectorRoutes()
}
}
// shouldUseOneCGNATRoute reports whether we should prefer to make one big
@@ -6363,6 +6372,9 @@ func (b *LocalBackend) OfferingExitNode() bool {
// OfferingAppConnector reports whether b is currently offering app
// connector services.
func (b *LocalBackend) OfferingAppConnector() bool {
if !buildfeatures.HasAppConnectors {
return false
}
b.mu.Lock()
defer b.mu.Unlock()
return b.appConnector != nil
@@ -6372,6 +6384,9 @@ func (b *LocalBackend) OfferingAppConnector() bool {
//
// TODO(nickkhyl): move app connectors to [nodeBackend], or perhaps a feature package?
func (b *LocalBackend) AppConnector() *appc.AppConnector {
if !buildfeatures.HasAppConnectors {
return nil
}
b.mu.Lock()
defer b.mu.Unlock()
return b.appConnector
@@ -6917,6 +6932,9 @@ func (b *LocalBackend) DebugBreakDERPConns() error {
// ObserveDNSResponse passes a DNS response from the PeerAPI DNS server to the
// App Connector to enable route discovery.
func (b *LocalBackend) ObserveDNSResponse(res []byte) error {
if !buildfeatures.HasAppConnectors {
return nil
}
var appConnector *appc.AppConnector
b.mu.Lock()
if b.appConnector == nil {
@@ -7020,6 +7038,9 @@ func namespaceKeyForCurrentProfile(pm *profileManager, key ipn.StateKey) ipn.Sta
const routeInfoStateStoreKey ipn.StateKey = "_routeInfo"
func (b *LocalBackend) storeRouteInfo(ri *appc.RouteInfo) error {
if !buildfeatures.HasAppConnectors {
return feature.ErrUnavailable
}
b.mu.Lock()
defer b.mu.Unlock()
if b.pm.CurrentProfile().ID() == "" {
@@ -7034,6 +7055,9 @@ func (b *LocalBackend) storeRouteInfo(ri *appc.RouteInfo) error {
}
func (b *LocalBackend) readRouteInfoLocked() (*appc.RouteInfo, error) {
if !buildfeatures.HasAppConnectors {
return nil, feature.ErrUnavailable
}
if b.pm.CurrentProfile().ID() == "" {
return &appc.RouteInfo{}, nil
}

View File

@@ -745,7 +745,7 @@ func (h *peerAPIHandler) handleDNSQuery(w http.ResponseWriter, r *http.Request)
// 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() {
if buildfeatures.HasAppConnectors && h.ps.b.OfferingAppConnector() {
if err := h.ps.b.ObserveDNSResponse(res); err != nil {
h.logf("ObserveDNSResponse error: %v", err)
// This is not fatal, we probably just failed to parse the upstream