mirror of
https://github.com/tailscale/tailscale.git
synced 2024-12-03 23:15:42 +00:00
cmd/tailtlsproxy: introduce HTTPS proxy bridge
This allows you to bridge existing HTTP/S services into your tailnet using the Let's Encrypt[1] functionality. This will allow you to run multiple services on the same computer and still have them point at different target HTTP services. This also includes an example systemd template unit that lets you easily set up multiple instances of tailtlsproxy on the same machine. [1]: https://tailscale.com/blog/tls-certs/ Signed-off-by: Xe <xe@tailscale.com>
This commit is contained in:
parent
758c37b83d
commit
4d5386001a
86
cmd/tailtlsproxy/main.go
Normal file
86
cmd/tailtlsproxy/main.go
Normal file
@ -0,0 +1,86 @@
|
||||
// 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))
|
||||
}
|
2
cmd/tailtlsproxy/tailtlsproxy-test.defaults
Normal file
2
cmd/tailtlsproxy/tailtlsproxy-test.defaults
Normal file
@ -0,0 +1,2 @@
|
||||
HOSTNAME=test
|
||||
TO=http://127.0.0.1:3030
|
19
cmd/tailtlsproxy/tailtlsproxy@.service
Normal file
19
cmd/tailtlsproxy/tailtlsproxy@.service
Normal file
@ -0,0 +1,19 @@
|
||||
[Unit]
|
||||
Description=Tailscale TLS Proxy bridge for %i
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Environment=HOME=/var/lib/private/tailtlsproxy-%i
|
||||
EnvironmentFile=/etc/default/tailtlsproxy-%i
|
||||
ExecStart=/usr/bin/tailtlsproxy
|
||||
Restart=on-failure
|
||||
RuntimeDirectory=tailtlsproxy-%i
|
||||
RuntimeDirectoryMode=0755
|
||||
StateDirectory=tailtlsproxy-%i
|
||||
StateDirectoryMode=0700
|
||||
CacheDirectory=tailtlsproxy-%i
|
||||
CacheDirectoryMode=0750
|
||||
DynamicUser=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
Loading…
Reference in New Issue
Block a user