Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 88 additions & 50 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ var (
// The version is set by the build command.
version string

// The TLS Certificate/Key pair
tlsCertificate string
tlsKey string

// httpd
httpAddr string
httpHost string
Expand Down Expand Up @@ -90,6 +94,8 @@ func init() {
cli.StringVar(&backlink, "backlink", "", "backlink (optional)")
cli.StringVar(&httpHost, "http-host", "", "HTTP host")
cli.StringVar(&httpAddr, "http-addr", ":80", "HTTP listen address")
cli.StringVar(&tlsCertificate, "certificate", "", "enable TLS using a custom certificate/key pair")
cli.StringVar(&tlsKey, "key", "", "enable TLS using a custom certificate/key pair")
Comment thread
jinncoder marked this conversation as resolved.
Outdated
cli.BoolVar(&httpInsecure, "http-insecure", false, "enable sessions cookies for http (no https) not recommended")
cli.BoolVar(&letsencrypt, "letsencrypt", true, "enable TLS using Let's Encrypt on port 443")
cli.BoolVar(&showVersion, "version", false, "display version and exit")
Expand Down Expand Up @@ -199,12 +205,16 @@ func main() {
//
// Server
//

httpTimeout := 10 * time.Minute
maxHeaderBytes := 10 * (1024 * 1024)

if tlsCertificate != "" && tlsKey != "" {
Comment thread
jinncoder marked this conversation as resolved.
logger.Info("Unable to leverage both Let's Encrypt and certificate/key flags at the same time - using the certificate/key pair...")
letsencrypt = false
}
Comment thread
jinncoder marked this conversation as resolved.

// Plain text web server for use behind a reverse proxy.
if !letsencrypt {
if !letsencrypt && tlsCertificate == "" || tlsKey == "" {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if !letsencrypt && tlsCertificate == "" || tlsKey == "" {
if !letsencrypt || tlsCertificate == "" || tlsKey == "" {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when:
  le == false 
  kp == true

(!le || kp) then pass (which we don't want, correct?)

when:
  le == false 
  kp == true

(!le && cert) then fail (which is what we want, no?)

So it should stay a && and not be changed to a || - or am I missing it?

httpd := &http.Server{
Handler: r,
Addr: net.JoinHostPort(httpIP, httpPort),
Expand All @@ -213,6 +223,7 @@ func main() {
MaxHeaderBytes: maxHeaderBytes,
}
hostport := net.JoinHostPort(httpHost, httpPort)

if httpPort == "80" {
hostport = httpHost
}
Expand All @@ -224,48 +235,8 @@ func main() {
logger.Fatal(httpd.ListenAndServe())
}

// Let's Encrypt TLS mode

// autocert
certmanager := autocert.Manager{
Prompt: autocert.AcceptTOS,
Cache: autocert.DirCache(filepath.Join(datadir, "letsencrypt")),
HostPolicy: func(_ context.Context, host string) error {
host = strings.TrimPrefix(host, "www.")
if host == httpHost {
return nil
}
if host == config.FindInfo().Domain {
return nil
}
return fmt.Errorf("autocert: host %q not permitted by HostPolicy", host)
},
}

// http redirect to https and Let's Encrypt auth
go func() {
redir := httprouter.New()
redir.GET("/*path", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
r.URL.Scheme = "https"
r.URL.Host = httpHost
http.Redirect(w, r, r.URL.String(), http.StatusFound)
})

httpd := &http.Server{
Handler: certmanager.HTTPHandler(redir),
Addr: net.JoinHostPort(httpIP, "80"),
WriteTimeout: httpTimeout,
ReadTimeout: httpTimeout,
MaxHeaderBytes: maxHeaderBytes,
}
if err := httpd.ListenAndServe(); err != nil {
logger.Fatalf("http server on port 80 failed: %s", err)
}
}()

// TLS
tlsConfig := tls.Config{
GetCertificate: certmanager.GetCertificate,
NextProtos: []string{"http/1.1"},
Rand: rand.Reader,
PreferServerCipherSuites: true,
Expand All @@ -281,29 +252,86 @@ func main() {
},
}

// Let's Encrypt TLS mode
if letsencrypt {
// autocert
certmanager := autocert.Manager{
Prompt: autocert.AcceptTOS,
Cache: autocert.DirCache(filepath.Join(datadir, "letsencrypt")),
HostPolicy: func(_ context.Context, host string) error {
host = strings.TrimPrefix(host, "www.")

if host == httpHost {
return nil
}

if host == config.FindInfo().Domain {
return nil
}
return fmt.Errorf("autocert: host %q not permitted by HostPolicy", host)
},
}

tlsConfig.GetCertificate = certmanager.GetCertificate

// http redirect to https and Let's Encrypt auth
go func() {
redir := httprouter.New()
redir.GET("/*path", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
r.URL.Scheme = "https"
r.URL.Host = httpHost
http.Redirect(w, r, r.URL.String(), http.StatusFound)
})

httpd := &http.Server{
Handler: certmanager.HTTPHandler(redir),
Addr: net.JoinHostPort(httpIP, "80"),
WriteTimeout: httpTimeout,
ReadTimeout: httpTimeout,
MaxHeaderBytes: maxHeaderBytes,
}

if err := httpd.ListenAndServe(); err != nil {
logger.Fatalf("http server on port 80 failed: %s", err)
}
}()
}

// Using a certificate/key pair from disk
if tlsCertificate != "" && tlsKey != "" {
var certificates []tls.Certificate
cert, err := tls.LoadX509KeyPair(tlsCertificate, tlsKey)

if err != nil {
logger.Fatal(err.Error())
os.Exit(20)
Comment thread
jinncoder marked this conversation as resolved.
Outdated
Comment thread
jinncoder marked this conversation as resolved.
Outdated
}

certificates = append(certificates, cert)

tlsConfig.Certificates = certificates
} else if tlsCertificate != "" || tlsKey != "" {
logger.Fatal("You must define both a certificate and a key")
os.Exit(30)
Comment thread
jinncoder marked this conversation as resolved.
Outdated
}

// Override default for TLS.
if httpPort == "80" {
httpPort = "443"
httpAddr = net.JoinHostPort(httpIP, httpPort)
}

httpsd := &http.Server{
Handler: r,
Addr: httpAddr,
WriteTimeout: httpTimeout,
ReadTimeout: httpTimeout,
MaxHeaderBytes: maxHeaderBytes,
}

// Enable TCP keep alives on the TLS connection.
tcpListener, err := net.Listen("tcp", httpAddr)

if err != nil {
logger.Fatalf("listen failed: %s", err)
return
}
tlsListener := tls.NewListener(tcpKeepAliveListener{tcpListener.(*net.TCPListener)}, &tlsConfig)

hostport := net.JoinHostPort(httpHost, httpPort)

if httpPort == "443" {
hostport = httpHost
}
Expand All @@ -312,6 +340,15 @@ func main() {
Host: hostport,
Path: "/",
})

httpsd := &http.Server{
Handler: r,
Addr: httpAddr,
WriteTimeout: httpTimeout,
ReadTimeout: httpTimeout,
MaxHeaderBytes: maxHeaderBytes,
}

Comment on lines +344 to +

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to check out the PR on my own machine but this looks like it's in the wrong place.

logger.Fatal(httpsd.Serve(tlsListener))
}

Expand Down Expand Up @@ -397,6 +434,7 @@ func configureSAML() error {
return nil
}

// BestDomain will attempt to isloate the domain this binary is running from
Comment thread
jack1902 marked this conversation as resolved.
Outdated
func BestDomain() string {
domain := config.FindInfo().Domain
if domain != "" {
Expand Down