From 21c8b8cc472eef908cd3a50ac7c3f053dd8df195 Mon Sep 17 00:00:00 2001 From: Simon Rozet Date: Wed, 16 Aug 2023 03:31:26 +0200 Subject: [PATCH] fold everything into main.go The code is easier to follow this way, there's very little of it anyway. --- main.go | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ tsproxy.go | 96 ------------------------------------------------------ 2 files changed, 87 insertions(+), 96 deletions(-) delete mode 100644 tsproxy.go diff --git a/main.go b/main.go index 0e5862d..7fb631d 100644 --- a/main.go +++ b/main.go @@ -3,14 +3,17 @@ package main import ( "context" "crypto/tls" + "encoding/json" "errors" "flag" "fmt" "net" "net/http" + "net/http/httputil" "net/url" "os" "path/filepath" + "sort" "strconv" "strings" "syscall" @@ -22,6 +25,7 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" "tailscale.com/client/tailscale" + "tailscale.com/client/tailscale/apitype" "tailscale.com/tsnet" tslogger "tailscale.com/types/logger" ) @@ -288,3 +292,86 @@ func tsproxy(ctx context.Context) error { return g.Run() } + +type tailscaleLocalClient interface { + WhoIs(context.Context, string) (*apitype.WhoIsResponse, error) +} + +func newReverseProxy(logger *slog.Logger, lc tailscaleLocalClient, url *url.URL) http.HandlerFunc { + // TODO(sr) Instrument proxy.Transport + rproxy := &httputil.ReverseProxy{ + Rewrite: func(req *httputil.ProxyRequest) { + req.SetURL(url) + req.SetXForwarded() + req.Out.Host = req.In.Host + }, + } + rproxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) + logger.Error("upstream error", lerr(err)) + } + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + whois, err := lc.WhoIs(r.Context(), r.RemoteAddr) + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + logger.Error("tailscale whois", lerr(err)) + return + } + + if whois.Node == nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + logger.Error("tailscale whois", slog.String("err", "node missing")) + return + } + + if whois.UserProfile == nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + logger.Error("tailscale whois", slog.String("err", "user profile missing")) + return + } + + // Proxy requests from tagged nodes as is. + if whois.Node.IsTagged() { + rproxy.ServeHTTP(w, r) + return + } + + req := r.Clone(r.Context()) + req.Header.Set("X-Webauth-User", whois.UserProfile.LoginName) + req.Header.Set("X-Webauth-Name", whois.UserProfile.DisplayName) + rproxy.ServeHTTP(w, req) + }) +} + +func serveDiscovery(self string, targets []target) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var tgs []string + tgs = append(tgs, self) + for _, t := range targets { + if t.magicDNS == "" { + continue + } + if !t.prometheus { + continue + } + tgs = append(tgs, t.magicDNS) + } + sort.Strings(tgs) + buf, err := json.Marshal([]struct { + Targets []string `json:"targets"` + }{ + {Targets: tgs}, + }) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json; charset=utf-8") + _, _ = w.Write(buf) + }) +} + +func lerr(err error) slog.Attr { + return slog.String("err", err.Error()) +} diff --git a/tsproxy.go b/tsproxy.go deleted file mode 100644 index d7c04ae..0000000 --- a/tsproxy.go +++ /dev/null @@ -1,96 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "log/slog" - "net/http" - "net/http/httputil" - "net/url" - "sort" - - "tailscale.com/client/tailscale/apitype" -) - -type tailscaleLocalClient interface { - WhoIs(context.Context, string) (*apitype.WhoIsResponse, error) -} - -func newReverseProxy(logger *slog.Logger, lc tailscaleLocalClient, url *url.URL) http.HandlerFunc { - // TODO(sr) Instrument proxy.Transport - rproxy := &httputil.ReverseProxy{ - Rewrite: func(req *httputil.ProxyRequest) { - req.SetURL(url) - req.SetXForwarded() - req.Out.Host = req.In.Host - }, - } - rproxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) { - http.Error(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) - logger.Error("upstream error", lerr(err)) - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - whois, err := lc.WhoIs(r.Context(), r.RemoteAddr) - if err != nil { - http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - logger.Error("tailscale whois", lerr(err)) - return - } - - if whois.Node == nil { - http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - logger.Error("tailscale whois", slog.String("err", "node missing")) - return - } - - if whois.UserProfile == nil { - http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - logger.Error("tailscale whois", slog.String("err", "user profile missing")) - return - } - - // Proxy requests from tagged nodes as is. - if whois.Node.IsTagged() { - rproxy.ServeHTTP(w, r) - return - } - - req := r.Clone(r.Context()) - req.Header.Set("X-Webauth-User", whois.UserProfile.LoginName) - req.Header.Set("X-Webauth-Name", whois.UserProfile.DisplayName) - rproxy.ServeHTTP(w, req) - }) -} - -func serveDiscovery(self string, targets []target) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var tgs []string - tgs = append(tgs, self) - for _, t := range targets { - if t.magicDNS == "" { - continue - } - if !t.prometheus { - continue - } - tgs = append(tgs, t.magicDNS) - } - sort.Strings(tgs) - buf, err := json.Marshal([]struct { - Targets []string `json:"targets"` - }{ - {Targets: tgs}, - }) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", "application/json; charset=utf-8") - _, _ = w.Write(buf) - }) -} - -func lerr(err error) slog.Attr { - return slog.String("err", err.Error()) -} -- 2.51.2