Add support for private Tailscale HTTPS

This commit is contained in:
Jan-Lukas Else 2021-09-22 23:55:07 +02:00
parent b4b36d1441
commit 2080058dfe
4 changed files with 593 additions and 48 deletions

View File

@ -35,6 +35,7 @@ type configServer struct {
ShortPublicAddress string `mapstructure:"shortPublicAddress"` ShortPublicAddress string `mapstructure:"shortPublicAddress"`
MediaAddress string `mapstructure:"mediaAddress"` MediaAddress string `mapstructure:"mediaAddress"`
PublicHTTPS bool `mapstructure:"publicHttps"` PublicHTTPS bool `mapstructure:"publicHttps"`
TailscaleHTTPS bool `mapstructure:"tailscaleHttps"`
Tor bool `mapstructure:"tor"` Tor bool `mapstructure:"tor"`
SecurityHeaders bool `mapstructure:"securityHeaders"` SecurityHeaders bool `mapstructure:"securityHeaders"`
CSPDomains []string `mapstructure:"cspDomains"` CSPDomains []string `mapstructure:"cspDomains"`

20
go.mod
View File

@ -34,7 +34,7 @@ require (
github.com/schollz/sqlite3dump v1.3.0 github.com/schollz/sqlite3dump v1.3.0
github.com/snabb/sitemap v1.0.0 github.com/snabb/sitemap v1.0.0
github.com/spf13/cast v1.4.1 github.com/spf13/cast v1.4.1
github.com/spf13/viper v1.8.1 github.com/spf13/viper v1.9.0
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/tdewolff/minify/v2 v2.9.22 github.com/tdewolff/minify/v2 v2.9.22
github.com/thoas/go-funk v0.9.1 github.com/thoas/go-funk v0.9.1
@ -43,15 +43,16 @@ require (
github.com/yuin/goldmark v1.4.1 github.com/yuin/goldmark v1.4.1
// master // master
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38 github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
golang.org/x/net v0.0.0-20210913180222-943fd674d43e golang.org/x/net v0.0.0-20210917221730-978cfadd31cf
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
tailscale.com v1.14.3
willnorris.com/go/microformats v1.1.1 willnorris.com/go/microformats v1.1.1
) )
require ( require (
github.com/andybalholm/cascadia v1.2.0 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect
github.com/boombuler/barcode v1.0.1 // indirect github.com/boombuler/barcode v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
@ -65,7 +66,8 @@ require (
github.com/jonboulle/clockwork v0.2.2 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/lestrrat-go/strftime v1.0.5 // indirect github.com/lestrrat-go/strftime v1.0.5 // indirect
github.com/magiconair/properties v1.8.5 // indirect github.com/magiconair/properties v1.8.5 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.4.2 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect github.com/pelletier/go-toml v1.9.4 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
@ -75,8 +77,12 @@ require (
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect
github.com/tdewolff/parse/v2 v2.5.21 // indirect github.com/tdewolff/parse/v2 v2.5.21 // indirect
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 // indirect go4.org/intern v0.0.0-20210108033219-3eb7198706b2 // indirect
go4.org/mem v0.0.0-20210711025021-927187094b94 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 // indirect
golang.org/x/sys v0.0.0-20210921065528-437939a70204 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
gopkg.in/ini.v1 v1.63.0 // indirect gopkg.in/ini.v1 v1.63.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
inet.af/netaddr v0.0.0-20210903134321-85fa6c94624e // indirect
) )

571
go.sum

File diff suppressed because it is too large Load Diff

49
http.go
View File

@ -2,6 +2,7 @@ package main
import ( import (
"compress/flate" "compress/flate"
"crypto/tls"
"database/sql" "database/sql"
"errors" "errors"
"fmt" "fmt"
@ -19,6 +20,7 @@ import (
"golang.org/x/crypto/acme" "golang.org/x/crypto/acme"
"golang.org/x/crypto/acme/autocert" "golang.org/x/crypto/acme/autocert"
"golang.org/x/net/context" "golang.org/x/net/context"
"tailscale.com/client/tailscale"
) )
const ( const (
@ -62,7 +64,7 @@ func (a *goBlog) startServer() (err error) {
WriteTimeout: 5 * time.Minute, WriteTimeout: 5 * time.Minute,
} }
a.shutdown.Add(shutdownServer(s, "main server")) a.shutdown.Add(shutdownServer(s, "main server"))
if a.cfg.Server.PublicHTTPS { if a.cfg.Server.PublicHTTPS || a.cfg.Server.TailscaleHTTPS {
// Start HTTP server for redirects // Start HTTP server for redirects
httpServer := &http.Server{ httpServer := &http.Server{
Addr: ":http", Addr: ":http",
@ -78,23 +80,34 @@ func (a *goBlog) startServer() (err error) {
}() }()
// Start HTTPS // Start HTTPS
s.Addr = ":https" s.Addr = ":https"
hosts := []string{a.cfg.Server.publicHostname} if a.cfg.Server.TailscaleHTTPS {
if shn := a.cfg.Server.shortPublicHostname; shn != "" { // HTTPS via Tailscale
hosts = append(hosts, shn) s.TLSConfig = &tls.Config{
} GetCertificate: tailscale.GetCertificate,
if mhn := a.cfg.Server.mediaHostname; mhn != "" { }
hosts = append(hosts, mhn) if err = s.ListenAndServeTLS("", ""); err != nil && err != http.ErrServerClosed {
} return err
acmeDir := acme.LetsEncryptURL }
// acmeDir := "https://acme-staging-v02.api.letsencrypt.org/directory" } else {
m := &autocert.Manager{ // Public HTTPS via Let's Encrypt
Prompt: autocert.AcceptTOS, hosts := []string{a.cfg.Server.publicHostname}
HostPolicy: autocert.HostWhitelist(hosts...), if shn := a.cfg.Server.shortPublicHostname; shn != "" {
Cache: &httpsCache{db: a.db}, hosts = append(hosts, shn)
Client: &acme.Client{DirectoryURL: acmeDir}, }
} if mhn := a.cfg.Server.mediaHostname; mhn != "" {
if err = s.Serve(m.Listener()); err != nil && err != http.ErrServerClosed { hosts = append(hosts, mhn)
return err }
acmeDir := acme.LetsEncryptURL
// acmeDir := "https://acme-staging-v02.api.letsencrypt.org/directory"
m := &autocert.Manager{
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist(hosts...),
Cache: &httpsCache{db: a.db},
Client: &acme.Client{DirectoryURL: acmeDir},
}
if err = s.Serve(m.Listener()); err != nil && err != http.ErrServerClosed {
return err
}
} }
} else { } else {
s.Addr = ":" + strconv.Itoa(a.cfg.Server.Port) s.Addr = ":" + strconv.Itoa(a.cfg.Server.Port)