tailscale/cmd/tailtlsproxy/main.go

87 lines
1.9 KiB
Go
Raw Normal View History

// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"crypto/tls"
"flag"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"time"
"tailscale.com/client/tailscale"
"tailscale.com/tsnet"
)
func envOr(name, def string) string {
if val, ok := os.LookupEnv(name); ok {
return val
}
return def
}
var (
bind = flag.String("bind", ":443", "TCP hostport to bind to for TLS http traffic")
hostname = flag.String("hostname", envOr("HOSTNAME", "toolname"), "hostname to register on tailnet (can be set with $HOSTNAME)")
auth = flag.Bool("auth", false, "if set, authenticate with tailscale (enables verbose logging)")
v = flag.Bool("v", false, "if set, enable verbose tailscale logs")
to = flag.String("to", envOr("TO", "http://127.0.0.1:3030"), "HTTP/S url to reverse proxy to (can be set with $TO)")
)
func main() {
os.Setenv("TAILSCALE_USE_WIP_CODE", "true")
flag.Parse()
srv := tsnet.Server{
Hostname: *hostname,
}
if *auth || *v {
srv.Logf = log.Printf
} else {
srv.Logf = func(string, ...interface{}) {}
}
if *auth {
os.Setenv("TS_LOGIN", "1")
}
ln, err := srv.Listen("tcp", *bind)
if err != nil {
log.Fatal(err)
}
u, err := url.Parse(*to)
if err != nil {
log.Fatalf("%s wasn't a valid URL: %v", *to, err)
}
h := httputil.NewSingleHostReverseProxy(u)
ln = tls.NewListener(ln, &tls.Config{
GetCertificate: func(chi *tls.ClientHelloInfo) (*tls.Certificate, error) {
c, err := tailscale.GetCertificate(chi)
if err != nil {
log.Println(err)
}
return c, err
},
})
s := &http.Server{
IdleTimeout: 5 * time.Minute,
Addr: *bind,
Handler: h,
}
log.Printf("listening for https on https://%s.your.tailcert.domain and forwarding to %s", *hostname, *to)
log.Fatal(s.Serve(ln))
}