diff options
Diffstat (limited to 'ipn')
| -rw-r--r-- | ipn/ipnlocal/local.go | 36 | ||||
| -rw-r--r-- | ipn/ipnserver/server.go | 4 |
2 files changed, 40 insertions, 0 deletions
diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index bcad6c64a..d235df451 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -12,6 +12,7 @@ import ( "io" "net" "net/http" + "net/url" "os" "os/exec" "os/user" @@ -3253,3 +3254,38 @@ func (b *LocalBackend) DoNoiseRequest(req *http.Request) (*http.Response, error) } return cc.DoNoiseRequest(req) } + +// ProxyAPIRequestOverNoise sends Tailscale API request r over the +// Noise channel, authenticated as the current node+machine key, to +// the control plane and copies its response back to w. +func (b *LocalBackend) ProxyAPIRequestOverNoise(w http.ResponseWriter, r *http.Request) { + var nodePub key.NodePublic + b.mu.Lock() + if nm := b.netMap; nm != nil { + nodePub = nm.NodeKey + } + b.mu.Unlock() + if nodePub.IsZero() { + http.Error(w, "no node public key", http.StatusBadGateway) + return + } + + outR := r.Clone(r.Context()) + outR.RequestURI = "" + outR.URL.Scheme = "https" + outR.URL.Host = "unused" + + outR.SetBasicAuth(url.QueryEscape(nodePub.String()), "") + res, err := b.DoNoiseRequest(outR) + if err != nil { + http.Error(w, "failed to make backend noise request: "+err.Error(), http.StatusBadGateway) + return + } + for k, vv := range res.Header { + for _, v := range vv { + w.Header().Add(k, v) + } + } + w.WriteHeader(res.StatusCode) + io.Copy(w, res.Body) +} diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index 47b088100..db255c6e0 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -1049,6 +1049,10 @@ func (s *Server) localhostHandler(ci connIdentity) http.Handler { lah.ServeHTTP(w, r) return } + if strings.HasPrefix(r.URL.Path, "/api/") { + s.b.ProxyAPIRequestOverNoise(w, r) + return + } if ci.NotWindows { io.WriteString(w, "<html><title>Tailscale</title><body><h1>Tailscale</h1>This is the local Tailscale daemon.") return |
