82 lines
2.4 KiB
Go
82 lines
2.4 KiB
Go
package app
|
|
|
|
import (
|
|
"crypto/tls"
|
|
stdlog "log"
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/centrifugal/centrifugo/v6/internal/config"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"golang.org/x/crypto/acme"
|
|
"golang.org/x/crypto/acme/autocert"
|
|
)
|
|
|
|
var startHTTPChallengeServerOnce sync.Once
|
|
|
|
func GetTLSConfig(cfg config.Config) (*tls.Config, error) {
|
|
tlsEnabled := cfg.HTTP.TLS.Enabled
|
|
tlsAutocertEnabled := cfg.HTTP.TLSAutocert.Enabled
|
|
tlsAutocertHostWhitelist := cfg.HTTP.TLSAutocert.HostWhitelist
|
|
tlsAutocertCacheDir := cfg.HTTP.TLSAutocert.CacheDir
|
|
tlsAutocertEmail := cfg.HTTP.TLSAutocert.Email
|
|
tlsAutocertServerName := cfg.HTTP.TLSAutocert.ServerName
|
|
tlsAutocertHTTP := cfg.HTTP.TLSAutocert.HTTP
|
|
tlsAutocertHTTPAddr := cfg.HTTP.TLSAutocert.HTTPAddr
|
|
|
|
if tlsAutocertEnabled {
|
|
certManager := autocert.Manager{
|
|
Prompt: autocert.AcceptTOS,
|
|
Email: tlsAutocertEmail,
|
|
}
|
|
if tlsAutocertHostWhitelist != nil {
|
|
certManager.HostPolicy = autocert.HostWhitelist(tlsAutocertHostWhitelist...)
|
|
}
|
|
if tlsAutocertCacheDir != "" {
|
|
certManager.Cache = autocert.DirCache(tlsAutocertCacheDir)
|
|
}
|
|
|
|
if tlsAutocertHTTP {
|
|
startHTTPChallengeServerOnce.Do(func() {
|
|
// getTLSConfig can be called several times.
|
|
acmeHTTPServer := &http.Server{
|
|
Handler: certManager.HTTPHandler(nil),
|
|
Addr: tlsAutocertHTTPAddr,
|
|
ErrorLog: stdlog.New(&httpErrorLogWriter{log.Logger}, "", 0),
|
|
ReadHeaderTimeout: 10 * time.Second,
|
|
ReadTimeout: 30 * time.Second,
|
|
WriteTimeout: 10 * time.Second,
|
|
}
|
|
go func() {
|
|
log.Info().Msgf("serving ACME http_01 challenge on %s", tlsAutocertHTTPAddr)
|
|
if err := acmeHTTPServer.ListenAndServe(); err != nil {
|
|
log.Fatal().Err(err).Msgf("can't create server on %s to serve acme http challenge", tlsAutocertHTTPAddr)
|
|
}
|
|
}()
|
|
})
|
|
}
|
|
|
|
return &tls.Config{
|
|
MinVersion: tls.VersionTLS12,
|
|
GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
|
// See https://github.com/centrifugal/centrifugo/issues/144#issuecomment-279393819
|
|
if tlsAutocertServerName != "" && hello.ServerName == "" {
|
|
hello.ServerName = tlsAutocertServerName
|
|
}
|
|
return certManager.GetCertificate(hello)
|
|
},
|
|
NextProtos: []string{
|
|
"h2", "http/1.1", acme.ALPNProto,
|
|
},
|
|
}, nil
|
|
|
|
} else if tlsEnabled {
|
|
// Autocert disabled - just try to use provided SSL cert and key files.
|
|
return cfg.HTTP.TLS.ToGoTLSConfig("http_server")
|
|
}
|
|
|
|
return nil, nil
|
|
}
|