diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index c864a81a0..70bf87b70 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -536,6 +536,8 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo needsCaptiveDetection: make(chan bool), } + sys.NoiseRoundTripper.Set(noiseRoundTripper{b}) + nb := newNodeBackend(ctx, b.logf, b.sys.Bus.Get()) b.currentNodeAtomic.Store(nb) nb.ready() @@ -7274,6 +7276,15 @@ func (b *LocalBackend) DoNoiseRequest(req *http.Request) (*http.Response, error) return cc.DoNoiseRequest(req) } +// noiseRoundTripper adapts LocalBackend.DoNoiseRequest to http.RoundTripper. +type noiseRoundTripper struct { + lb *LocalBackend +} + +func (n noiseRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + return n.lb.DoNoiseRequest(req) +} + // ActiveSSHConns returns the number of active SSH connections, // or 0 if SSH is not linked into the binary or available on the platform. func (b *LocalBackend) ActiveSSHConns() int { diff --git a/tsd/tsd.go b/tsd/tsd.go index 615c9c0e7..98b6a6bd3 100644 --- a/tsd/tsd.go +++ b/tsd/tsd.go @@ -20,6 +20,7 @@ package tsd import ( "crypto/x509" "fmt" + "net/http" "reflect" "tailscale.com/control/controlknobs" @@ -64,6 +65,10 @@ type System struct { PolicyClient SubSystem[policyclient.Client] HealthTracker SubSystem[*health.Tracker] + // NoiseRoundTripper, if set, provides an http.RoundTripper that + // sends requests over the control plane Noise connection. + NoiseRoundTripper SubSystem[http.RoundTripper] + // ExtraRootCAs, if non-nil, specifies additional trusted root CAs // beyond the system roots. On Android, this includes user-installed // CA certificates that Go's crypto/x509 does not see.