Make SSL cipher suite configurable (#17440)
This commit is contained in:
parent
9f14fe43c6
commit
c96be0cd98
9 changed files with 266 additions and 54 deletions
|
@ -5,7 +5,6 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/fcgi"
|
"net/http/fcgi"
|
||||||
|
@ -20,14 +19,6 @@ func runHTTP(network, listenAddr, name string, m http.Handler) error {
|
||||||
return graceful.HTTPListenAndServe(network, listenAddr, name, m)
|
return graceful.HTTPListenAndServe(network, listenAddr, name, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runHTTPS(network, listenAddr, name, certFile, keyFile string, m http.Handler) error {
|
|
||||||
return graceful.HTTPListenAndServeTLS(network, listenAddr, name, certFile, keyFile, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func runHTTPSWithTLSConfig(network, listenAddr, name string, tlsConfig *tls.Config, m http.Handler) error {
|
|
||||||
return graceful.HTTPListenAndServeTLSConfig(network, listenAddr, name, tlsConfig, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NoHTTPRedirector tells our cleanup routine that we will not be using a fallback http redirector
|
// NoHTTPRedirector tells our cleanup routine that we will not be using a fallback http redirector
|
||||||
func NoHTTPRedirector() {
|
func NoHTTPRedirector() {
|
||||||
graceful.GetManager().InformCleanup()
|
graceful.GetManager().InformCleanup()
|
||||||
|
|
191
cmd/web_https.go
Normal file
191
cmd/web_https.go
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/graceful"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"github.com/klauspost/cpuid/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var tlsVersionStringMap = map[string]uint16{
|
||||||
|
"": tls.VersionTLS12, // Default to tls.VersionTLS12
|
||||||
|
"tlsv1.0": tls.VersionTLS10,
|
||||||
|
"tlsv1.1": tls.VersionTLS11,
|
||||||
|
"tlsv1.2": tls.VersionTLS12,
|
||||||
|
"tlsv1.3": tls.VersionTLS13,
|
||||||
|
}
|
||||||
|
|
||||||
|
func toTLSVersion(version string) uint16 {
|
||||||
|
tlsVersion, ok := tlsVersionStringMap[strings.TrimSpace(strings.ToLower(version))]
|
||||||
|
if !ok {
|
||||||
|
log.Warn("Unknown tls version: %s", version)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return tlsVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
var curveStringMap = map[string]tls.CurveID{
|
||||||
|
"x25519": tls.X25519,
|
||||||
|
"p256": tls.CurveP256,
|
||||||
|
"p384": tls.CurveP384,
|
||||||
|
"p521": tls.CurveP521,
|
||||||
|
}
|
||||||
|
|
||||||
|
func toCurvePreferences(preferences []string) []tls.CurveID {
|
||||||
|
ids := make([]tls.CurveID, 0, len(preferences))
|
||||||
|
for _, pref := range preferences {
|
||||||
|
id, ok := curveStringMap[strings.TrimSpace(strings.ToLower(pref))]
|
||||||
|
if !ok {
|
||||||
|
log.Warn("Unknown curve: %s", pref)
|
||||||
|
}
|
||||||
|
if id != 0 {
|
||||||
|
ids = append(ids, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
|
||||||
|
var cipherStringMap = map[string]uint16{
|
||||||
|
"rsa_with_rc4_128_sha": tls.TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
"rsa_with_3des_ede_cbc_sha": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
"rsa_with_aes_128_cbc_sha": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
"rsa_with_aes_256_cbc_sha": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
"rsa_with_aes_128_cbc_sha256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
"rsa_with_aes_128_gcm_sha256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
"rsa_with_aes_256_gcm_sha384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
"ecdhe_ecdsa_with_rc4_128_sha": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
"ecdhe_ecdsa_with_aes_128_cbc_sha": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
"ecdhe_ecdsa_with_aes_256_cbc_sha": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
"ecdhe_rsa_with_rc4_128_sha": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
"ecdhe_rsa_with_3des_ede_cbc_sha": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
"ecdhe_rsa_with_aes_128_cbc_sha": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
"ecdhe_rsa_with_aes_256_cbc_sha": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
"ecdhe_ecdsa_with_aes_128_cbc_sha256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
"ecdhe_rsa_with_aes_128_cbc_sha256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
"ecdhe_rsa_with_aes_128_gcm_sha256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
"ecdhe_ecdsa_with_aes_128_gcm_sha256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
"ecdhe_rsa_with_aes_256_gcm_sha384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
"ecdhe_ecdsa_with_aes_256_gcm_sha384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
"ecdhe_rsa_with_chacha20_poly1305_sha256": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
"ecdhe_ecdsa_with_chacha20_poly1305_sha256": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
"ecdhe_rsa_with_chacha20_poly1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||||
|
"ecdhe_ecdsa_with_chacha20_poly1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||||
|
"aes_128_gcm_sha256": tls.TLS_AES_128_GCM_SHA256,
|
||||||
|
"aes_256_gcm_sha384": tls.TLS_AES_256_GCM_SHA384,
|
||||||
|
"chacha20_poly1305_sha256": tls.TLS_CHACHA20_POLY1305_SHA256,
|
||||||
|
}
|
||||||
|
|
||||||
|
func toTLSCiphers(cipherStrings []string) []uint16 {
|
||||||
|
ciphers := make([]uint16, 0, len(cipherStrings))
|
||||||
|
for _, cipherString := range cipherStrings {
|
||||||
|
cipher, ok := cipherStringMap[strings.TrimSpace(strings.ToLower(cipherString))]
|
||||||
|
if !ok {
|
||||||
|
log.Warn("Unknown cipher: %s", cipherString)
|
||||||
|
}
|
||||||
|
if cipher != 0 {
|
||||||
|
ciphers = append(ciphers, cipher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ciphers
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultCiphers uses hardware support to check if AES is specifically
|
||||||
|
// supported by the CPU.
|
||||||
|
//
|
||||||
|
// If AES is supported AES ciphers will be preferred over ChaCha based ciphers
|
||||||
|
// (This code is directly inspired by the certmagic code.)
|
||||||
|
func defaultCiphers() []uint16 {
|
||||||
|
if cpuid.CPU.Supports(cpuid.AESNI) {
|
||||||
|
return defaultCiphersAESfirst
|
||||||
|
}
|
||||||
|
return defaultCiphersChaChaFirst
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultCiphersAES = []uint16{
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultCiphersChaCha = []uint16{
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultCiphersAESfirst = append(defaultCiphersAES, defaultCiphersChaCha...)
|
||||||
|
defaultCiphersChaChaFirst = append(defaultCiphersChaCha, defaultCiphersAES...)
|
||||||
|
)
|
||||||
|
|
||||||
|
// runHTTPs listens on the provided network address and then calls
|
||||||
|
// Serve to handle requests on incoming TLS connections.
|
||||||
|
//
|
||||||
|
// Filenames containing a certificate and matching private key for the server must
|
||||||
|
// be provided. If the certificate is signed by a certificate authority, the
|
||||||
|
// certFile should be the concatenation of the server's certificate followed by the
|
||||||
|
// CA's certificate.
|
||||||
|
func runHTTPS(network, listenAddr, name, certFile, keyFile string, m http.Handler) error {
|
||||||
|
tlsConfig := &tls.Config{}
|
||||||
|
if tlsConfig.NextProtos == nil {
|
||||||
|
tlsConfig.NextProtos = []string{"h2", "http/1.1"}
|
||||||
|
}
|
||||||
|
|
||||||
|
if version := toTLSVersion(setting.SSLMinimumVersion); version != 0 {
|
||||||
|
tlsConfig.MinVersion = version
|
||||||
|
}
|
||||||
|
if version := toTLSVersion(setting.SSLMaximumVersion); version != 0 {
|
||||||
|
tlsConfig.MaxVersion = version
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set curve preferences
|
||||||
|
tlsConfig.CurvePreferences = []tls.CurveID{
|
||||||
|
tls.X25519,
|
||||||
|
tls.CurveP256,
|
||||||
|
}
|
||||||
|
if curves := toCurvePreferences(setting.SSLCurvePreferences); len(curves) > 0 {
|
||||||
|
tlsConfig.CurvePreferences = curves
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set cipher suites
|
||||||
|
tlsConfig.CipherSuites = defaultCiphers()
|
||||||
|
if ciphers := toTLSCiphers(setting.SSLCipherSuites); len(ciphers) > 0 {
|
||||||
|
tlsConfig.CipherSuites = ciphers
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig.Certificates = make([]tls.Certificate, 1)
|
||||||
|
|
||||||
|
certPEMBlock, err := os.ReadFile(certFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to load https cert file %s for %s:%s: %v", certFile, network, listenAddr, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
keyPEMBlock, err := os.ReadFile(keyFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to load https key file %s for %s:%s: %v", keyFile, network, listenAddr, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig.Certificates[0], err = tls.X509KeyPair(certPEMBlock, keyPEMBlock)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to create certificate from cert file %s and key file %s for %s:%s: %v", certFile, keyFile, network, listenAddr, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return graceful.HTTPListenAndServeTLSConfig(network, listenAddr, name, tlsConfig, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runHTTPSWithTLSConfig(network, listenAddr, name string, tlsConfig *tls.Config, m http.Handler) error {
|
||||||
|
return graceful.HTTPListenAndServeTLSConfig(network, listenAddr, name, tlsConfig, m)
|
||||||
|
}
|
|
@ -55,6 +55,23 @@ func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler)
|
||||||
tlsConfig := magic.TLSConfig()
|
tlsConfig := magic.TLSConfig()
|
||||||
tlsConfig.NextProtos = append(tlsConfig.NextProtos, "h2")
|
tlsConfig.NextProtos = append(tlsConfig.NextProtos, "h2")
|
||||||
|
|
||||||
|
if version := toTLSVersion(setting.SSLMinimumVersion); version != 0 {
|
||||||
|
tlsConfig.MinVersion = version
|
||||||
|
}
|
||||||
|
if version := toTLSVersion(setting.SSLMaximumVersion); version != 0 {
|
||||||
|
tlsConfig.MaxVersion = version
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set curve preferences
|
||||||
|
if curves := toCurvePreferences(setting.SSLCurvePreferences); len(curves) > 0 {
|
||||||
|
tlsConfig.CurvePreferences = curves
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set cipher suites
|
||||||
|
if ciphers := toTLSCiphers(setting.SSLCipherSuites); len(ciphers) > 0 {
|
||||||
|
tlsConfig.CipherSuites = ciphers
|
||||||
|
}
|
||||||
|
|
||||||
if enableHTTPChallenge {
|
if enableHTTPChallenge {
|
||||||
go func() {
|
go func() {
|
||||||
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
|
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
|
||||||
|
|
|
@ -51,6 +51,16 @@ RUN_MODE = ; prod
|
||||||
;REDIRECT_OTHER_PORT = false
|
;REDIRECT_OTHER_PORT = false
|
||||||
;PORT_TO_REDIRECT = 80
|
;PORT_TO_REDIRECT = 80
|
||||||
;;
|
;;
|
||||||
|
;; Minimum and maximum supported TLS versions
|
||||||
|
;SSL_MIN_VERSION=TLSv1.2
|
||||||
|
;SSL_MAX_VERSION=
|
||||||
|
;;
|
||||||
|
;; SSL Curve Preferences
|
||||||
|
;SSL_CURVE_PREFERENCES=X25519,P256
|
||||||
|
;;
|
||||||
|
;; SSL Cipher Suites
|
||||||
|
;SSL_CIPHER_SUITES=; Will default to "ecdhe_ecdsa_with_aes_256_gcm_sha384,ecdhe_rsa_with_aes_256_gcm_sha384,ecdhe_ecdsa_with_aes_128_gcm_sha256,ecdhe_rsa_with_aes_128_gcm_sha256,ecdhe_ecdsa_with_chacha20_poly1305,ecdhe_rsa_with_chacha20_poly1305" if aes is supported by hardware, otherwise chacha will be first.
|
||||||
|
;;
|
||||||
;; Timeout for any write to the connection. (Set to 0 to disable all timeouts.)
|
;; Timeout for any write to the connection. (Set to 0 to disable all timeouts.)
|
||||||
;PER_WRITE_TIMEOUT = 30s
|
;PER_WRITE_TIMEOUT = 30s
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -310,6 +310,42 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||||
|
|
||||||
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, allows redirecting http requests on `PORT_TO_REDIRECT` to the https port Gitea listens on.
|
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, allows redirecting http requests on `PORT_TO_REDIRECT` to the https port Gitea listens on.
|
||||||
- `PORT_TO_REDIRECT`: **80**: Port for the http redirection service to listen on. Used when `REDIRECT_OTHER_PORT` is true.
|
- `PORT_TO_REDIRECT`: **80**: Port for the http redirection service to listen on. Used when `REDIRECT_OTHER_PORT` is true.
|
||||||
|
- `SSL_MIN_VERSION`: **TLSv1.2**: Set the minimum version of ssl support.
|
||||||
|
- `SSL_MAX_VERSION`: **\<empty\>**: Set the maximum version of ssl support.
|
||||||
|
- `SSL_CURVE_PREFERENCES`: **X25519,P256**: Set the prefered curves,
|
||||||
|
- `SSL_CIPHER_SUITES`: **ecdhe_ecdsa_with_aes_256_gcm_sha384,ecdhe_rsa_with_aes_256_gcm_sha384,ecdhe_ecdsa_with_aes_128_gcm_sha256,ecdhe_rsa_with_aes_128_gcm_sha256,ecdhe_ecdsa_with_chacha20_poly1305,ecdhe_rsa_with_chacha20_poly1305**: Set the preferred cipher suites.
|
||||||
|
- If there is not hardware support for AES suites by default the cha cha suites will be preferred over the AES suites
|
||||||
|
- supported suites as of go 1.17 are:
|
||||||
|
- TLS 1.0 - 1.2 cipher suites
|
||||||
|
- "rsa_with_rc4_128_sha"
|
||||||
|
- "rsa_with_3des_ede_cbc_sha"
|
||||||
|
- "rsa_with_aes_128_cbc_sha"
|
||||||
|
- "rsa_with_aes_256_cbc_sha"
|
||||||
|
- "rsa_with_aes_128_cbc_sha256"
|
||||||
|
- "rsa_with_aes_128_gcm_sha256"
|
||||||
|
- "rsa_with_aes_256_gcm_sha384"
|
||||||
|
- "ecdhe_ecdsa_with_rc4_128_sha"
|
||||||
|
- "ecdhe_ecdsa_with_aes_128_cbc_sha"
|
||||||
|
- "ecdhe_ecdsa_with_aes_256_cbc_sha"
|
||||||
|
- "ecdhe_rsa_with_rc4_128_sha"
|
||||||
|
- "ecdhe_rsa_with_3des_ede_cbc_sha"
|
||||||
|
- "ecdhe_rsa_with_aes_128_cbc_sha"
|
||||||
|
- "ecdhe_rsa_with_aes_256_cbc_sha"
|
||||||
|
- "ecdhe_ecdsa_with_aes_128_cbc_sha256"
|
||||||
|
- "ecdhe_rsa_with_aes_128_cbc_sha256"
|
||||||
|
- "ecdhe_rsa_with_aes_128_gcm_sha256"
|
||||||
|
- "ecdhe_ecdsa_with_aes_128_gcm_sha256"
|
||||||
|
- "ecdhe_rsa_with_aes_256_gcm_sha384"
|
||||||
|
- "ecdhe_ecdsa_with_aes_256_gcm_sha384"
|
||||||
|
- "ecdhe_rsa_with_chacha20_poly1305_sha256"
|
||||||
|
- "ecdhe_ecdsa_with_chacha20_poly1305_sha256"
|
||||||
|
- TLS 1.3 cipher suites
|
||||||
|
- "aes_128_gcm_sha256"
|
||||||
|
- "aes_256_gcm_sha384"
|
||||||
|
- "chacha20_poly1305_sha256"
|
||||||
|
- Aliased names
|
||||||
|
- "ecdhe_rsa_with_chacha20_poly1305" is an alias for "ecdhe_rsa_with_chacha20_poly1305_sha256"
|
||||||
|
- "ecdhe_ecdsa_with_chacha20_poly1305" is alias for "ecdhe_ecdsa_with_chacha20_poly1305_sha256"
|
||||||
- `ENABLE_LETSENCRYPT`: **false**: If enabled you must set `DOMAIN` to valid internet facing domain (ensure DNS is set and port 80 is accessible by letsencrypt validation server).
|
- `ENABLE_LETSENCRYPT`: **false**: If enabled you must set `DOMAIN` to valid internet facing domain (ensure DNS is set and port 80 is accessible by letsencrypt validation server).
|
||||||
By using Lets Encrypt **you must consent** to their [terms of service](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf).
|
By using Lets Encrypt **you must consent** to their [terms of service](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf).
|
||||||
- `LETSENCRYPT_ACCEPTTOS`: **false**: This is an explicit check that you accept the terms of service for Let's Encrypt.
|
- `LETSENCRYPT_ACCEPTTOS`: **false**: This is an explicit check that you accept the terms of service for Let's Encrypt.
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -69,7 +69,7 @@ require (
|
||||||
github.com/kevinburke/ssh_config v1.1.0 // indirect
|
github.com/kevinburke/ssh_config v1.1.0 // indirect
|
||||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
|
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
|
||||||
github.com/klauspost/compress v1.13.1
|
github.com/klauspost/compress v1.13.1
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
github.com/klauspost/cpuid/v2 v2.0.9
|
||||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||||
github.com/lib/pq v1.10.2
|
github.com/lib/pq v1.10.2
|
||||||
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
|
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
|
||||||
|
|
|
@ -95,48 +95,14 @@ func (srv *Server) ListenAndServe(serve ServeFunction) error {
|
||||||
return srv.Serve(serve)
|
return srv.Serve(serve)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServeTLS listens on the provided network address and then calls
|
|
||||||
// Serve to handle requests on incoming TLS connections.
|
|
||||||
//
|
|
||||||
// Filenames containing a certificate and matching private key for the server must
|
|
||||||
// be provided. If the certificate is signed by a certificate authority, the
|
|
||||||
// certFile should be the concatenation of the server's certificate followed by the
|
|
||||||
// CA's certificate.
|
|
||||||
func (srv *Server) ListenAndServeTLS(certFile, keyFile string, serve ServeFunction) error {
|
|
||||||
config := &tls.Config{}
|
|
||||||
if config.NextProtos == nil {
|
|
||||||
config.NextProtos = []string{"h2", "http/1.1"}
|
|
||||||
}
|
|
||||||
|
|
||||||
config.Certificates = make([]tls.Certificate, 1)
|
|
||||||
|
|
||||||
certPEMBlock, err := os.ReadFile(certFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Failed to load https cert file %s for %s:%s: %v", certFile, srv.network, srv.address, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
keyPEMBlock, err := os.ReadFile(keyFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Failed to load https key file %s for %s:%s: %v", keyFile, srv.network, srv.address, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
config.Certificates[0], err = tls.X509KeyPair(certPEMBlock, keyPEMBlock)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Failed to create certificate from cert file %s and key file %s for %s:%s: %v", certFile, keyFile, srv.network, srv.address, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return srv.ListenAndServeTLSConfig(config, serve)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListenAndServeTLSConfig listens on the provided network address and then calls
|
// ListenAndServeTLSConfig listens on the provided network address and then calls
|
||||||
// Serve to handle requests on incoming TLS connections.
|
// Serve to handle requests on incoming TLS connections.
|
||||||
func (srv *Server) ListenAndServeTLSConfig(tlsConfig *tls.Config, serve ServeFunction) error {
|
func (srv *Server) ListenAndServeTLSConfig(tlsConfig *tls.Config, serve ServeFunction) error {
|
||||||
go srv.awaitShutdown()
|
go srv.awaitShutdown()
|
||||||
|
|
||||||
tlsConfig.MinVersion = tls.VersionTLS12
|
if tlsConfig.MinVersion == 0 {
|
||||||
|
tlsConfig.MinVersion = tls.VersionTLS12
|
||||||
|
}
|
||||||
|
|
||||||
l, err := GetListener(srv.network, srv.address)
|
l, err := GetListener(srv.network, srv.address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -33,13 +33,6 @@ func HTTPListenAndServe(network, address, name string, handler http.Handler) err
|
||||||
return server.ListenAndServe(lHandler)
|
return server.ListenAndServe(lHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPListenAndServeTLS listens on the provided network address and then calls Serve
|
|
||||||
// to handle requests on incoming connections.
|
|
||||||
func HTTPListenAndServeTLS(network, address, name, certFile, keyFile string, handler http.Handler) error {
|
|
||||||
server, lHandler := newHTTPServer(network, address, name, handler)
|
|
||||||
return server.ListenAndServeTLS(certFile, keyFile, lHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPListenAndServeTLSConfig listens on the provided network address and then calls Serve
|
// HTTPListenAndServeTLSConfig listens on the provided network address and then calls Serve
|
||||||
// to handle requests on incoming connections.
|
// to handle requests on incoming connections.
|
||||||
func HTTPListenAndServeTLSConfig(network, address, name string, tlsConfig *tls.Config, handler http.Handler) error {
|
func HTTPListenAndServeTLSConfig(network, address, name string, tlsConfig *tls.Config, handler http.Handler) error {
|
||||||
|
|
|
@ -114,6 +114,10 @@ var (
|
||||||
LetsEncryptTOS bool
|
LetsEncryptTOS bool
|
||||||
LetsEncryptDirectory string
|
LetsEncryptDirectory string
|
||||||
LetsEncryptEmail string
|
LetsEncryptEmail string
|
||||||
|
SSLMinimumVersion string
|
||||||
|
SSLMaximumVersion string
|
||||||
|
SSLCurvePreferences []string
|
||||||
|
SSLCipherSuites []string
|
||||||
GracefulRestartable bool
|
GracefulRestartable bool
|
||||||
GracefulHammerTime time.Duration
|
GracefulHammerTime time.Duration
|
||||||
StartupTimeout time.Duration
|
StartupTimeout time.Duration
|
||||||
|
@ -618,6 +622,10 @@ func NewContext() {
|
||||||
}
|
}
|
||||||
LetsEncryptDirectory = sec.Key("LETSENCRYPT_DIRECTORY").MustString("https")
|
LetsEncryptDirectory = sec.Key("LETSENCRYPT_DIRECTORY").MustString("https")
|
||||||
LetsEncryptEmail = sec.Key("LETSENCRYPT_EMAIL").MustString("")
|
LetsEncryptEmail = sec.Key("LETSENCRYPT_EMAIL").MustString("")
|
||||||
|
SSLMinimumVersion = sec.Key("SSL_MIN_VERSION").MustString("")
|
||||||
|
SSLMaximumVersion = sec.Key("SSL_MAX_VERSION").MustString("")
|
||||||
|
SSLCurvePreferences = sec.Key("SSL_CURVE_PREFERENCES").Strings(",")
|
||||||
|
SSLCipherSuites = sec.Key("SSL_CIPHER_SUITES").Strings(",")
|
||||||
Domain = sec.Key("DOMAIN").MustString("localhost")
|
Domain = sec.Key("DOMAIN").MustString("localhost")
|
||||||
HTTPAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0")
|
HTTPAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0")
|
||||||
HTTPPort = sec.Key("HTTP_PORT").MustString("3000")
|
HTTPPort = sec.Key("HTTP_PORT").MustString("3000")
|
||||||
|
|
Reference in a new issue