diff --git a/cmd/tailgrok/main.go b/cmd/tailgrok/main.go deleted file mode 100644 index 02fb769e7765d0055f91efa3769e3edeca336b40..0000000000000000000000000000000000000000 --- a/cmd/tailgrok/main.go +++ /dev/null @@ -1,130 +0,0 @@ -package main - -import ( - "bytes" - "context" - "crypto/rand" - "encoding/hex" - "encoding/json" - "flag" - "fmt" - "net/http" - "net/url" - "os" - "path/filepath" - "strings" - - "go.jolheiser.com/tailroute" - "golang.org/x/oauth2/clientcredentials" -) - -func main() { - fs := flag.NewFlagSet("tailgrok", flag.ExitOnError) - if err := fs.Parse(os.Args[1:]); err != nil { - panic(err) - } - - if fs.NArg() < 1 { - panic("tailgrok requires a target URL to proxy") - } - - target, err := url.Parse(fs.Arg(0)) - if err != nil { - panic(err) - } - - homeDir, err := os.UserHomeDir() - if err != nil { - panic(err) - } - cfgPath := filepath.Join(homeDir, ".config", "tailgrok", "config.json") - - b, err := os.ReadFile(cfgPath) - if err != nil { - panic(err) - } - var cfg Config - if err := json.Unmarshal(b, &cfg); err != nil { - panic(err) - } - - clientSecret, err := cfg.ClientSecret() - if err != nil { - panic(err) - } - - oauthConfig := &clientcredentials.Config{ - ClientID: cfg.ClientID, - ClientSecret: clientSecret, - TokenURL: "https://api.tailscale.com/api/v2/oauth/token", - } - client := oauthConfig.Client(context.Background()) - - payload, err := json.Marshal(M{ - "description": "tailgrok", - "capabilities": M{ - "devices": M{ - "create": M{ - "reusable": false, - "ephemeral": true, - "preauthorized": true, - "tags": []string{"tag:funnel", "tag:tailgrok"}, - }, - }, - }, - "expirySeconds": 5, - }) - if err != nil { - panic(err) - } - authTokenReq, err := http.NewRequest(http.MethodPost, "https://api.tailscale.com/api/v2/tailnet/-/keys", bytes.NewReader(payload)) - if err != nil { - panic(err) - } - resp, err := client.Do(authTokenReq) - if err != nil { - panic(err) - } - defer resp.Body.Close() - tsKey := struct { - Key string `json:"key"` - }{} - if err := json.NewDecoder(resp.Body).Decode(&tsKey); err != nil { - panic(err) - } - os.Setenv("TS_AUTHKEY", tsKey.Key) - - tmp, err := os.MkdirTemp(os.TempDir(), "tailgrok-*") - if err != nil { - panic(err) - } - defer os.RemoveAll(tmp) - - random := make([]byte, 8) - if _, err := rand.Read(random); err != nil { - panic(err) - } - id := hex.EncodeToString(random) - - fmt.Printf("https://%s.serval-vibes.ts.net\n", id) - r := tailroute.Proxy(target, true) - r.Ephemeral = true - if err := r.Serve(id, tmp); err != nil { - panic(err) - } -} - -type M = map[string]any - -type Config struct { - ClientID string `json:"clientID"` - ClientSecretFile string `json:"clientSecretFile"` -} - -func (c Config) ClientSecret() (string, error) { - b, err := os.ReadFile(c.ClientSecretFile) - if err != nil { - return "", err - } - return strings.TrimSpace(string(b)), nil -} diff --git a/cmd/tailproxy/main.go b/cmd/tailproxy/main.go index 9b658d80932c62e62834ed835ce415b474558277..fd08e895ac2ae318c3c552ac524cd96578671279 100644 --- a/cmd/tailproxy/main.go +++ b/cmd/tailproxy/main.go @@ -3,6 +3,8 @@ import ( "flag" "fmt" + "net/http" + "net/http/httputil" "net/url" "os" @@ -38,7 +40,16 @@ if err != nil { panic(err) } - r := tailroute.Proxy(proxyURL, args.Funnel) + proxy := httputil.NewSingleHostReverseProxy(proxyURL) + handler := http.HandlerFunc(proxy.ServeHTTP) + + r := tailroute.Router{ + Tailnet: handler, + } + if args.Funnel { + r.Funnel = handler + } + if err := r.Serve(args.Hostname, args.DataDir); err != nil { panic(err) } diff --git a/tailproxy.go b/tailproxy.go deleted file mode 100644 index 462a3d6803b83480e2fa8d914834f81b4bfff3da..0000000000000000000000000000000000000000 --- a/tailproxy.go +++ /dev/null @@ -1,26 +0,0 @@ -package tailroute - -import ( - "net/http" - "net/http/httputil" - "net/url" -) - -func Proxy(target *url.URL, funnel bool) Router { - proxy := httputil.NewSingleHostReverseProxy(target) - proxyDirector := proxy.Director - proxy.Director = func(r *http.Request) { - proxyDirector(r) - r.Host = target.Host - r.Header.Set("X-Forwarded-Host", r.Header.Get("Host")) - } - handler := http.HandlerFunc(proxy.ServeHTTP) - - r := Router{ - Tailnet: handler, - } - if funnel { - r.Funnel = handler - } - return r -} diff --git a/tailroute.go b/tailroute.go index f14ce246a4abd1478cb383469ec13a365a6256e1..98ed6f7df00cfdc912cb6fa6c1201549496d3790 100644 --- a/tailroute.go +++ b/tailroute.go @@ -24,10 +24,9 @@ isTailnet ) type Router struct { - Funnel http.Handler - Tailnet http.Handler - Logger logger.Logf - Ephemeral bool + Funnel http.Handler + Tailnet http.Handler + Logger logger.Logf } func (router Router) serve(ln net.Listener) error { @@ -85,15 +84,13 @@ if err := os.MkdirAll(dataDir, os.ModePerm); err != nil { return fmt.Errorf("could not create data dir: %w", err) } s := &tsnet.Server{ - Hostname: hostname, - Dir: dataDir, - Logf: router.Logger, - Ephemeral: router.Ephemeral, + Hostname: hostname, + Dir: dataDir, + Logf: router.Logger, } if err := s.Start(); err != nil { return err } - defer s.Close() lc, err := s.LocalClient() if err != nil { @@ -128,7 +125,7 @@ var lnHttps net.Listener if router.Funnel == nil { lnHttps, err = s.ListenTLS("tcp", ":443") } else { - lnHttps, err = s.ListenFunnel("tcp", ":80") + lnHttps, err = s.ListenFunnel("tcp", ":443") } if err != nil { return fmt.Errorf("can't listen https: %w", err)