Browse Source

issue #193 - added TLS 1.3 support for Go 1.13 or higher. (#203)

- adds TLS 1.3 and new cipher-suites as config options
- remove SSLv3 and the TLS_FALLBACK_SCSV ciphersuite from the sample configuration
- removes SSLv3 and the TLS_FALLBACK_SCSV ciphersuite when building with Go 1.14 or above
- remove Go 1.10 and Go 1.9 from Travis CI tests, add Go 1.13
Flashmob 5 years ago
parent
commit
de9b608138
9 changed files with 47 additions and 17 deletions
  1. 1 2
      .travis.yml
  2. 1 1
      README.md
  3. 9 6
      config.go
  4. 4 4
      goguerrilla.conf.sample
  5. 1 1
      guerrilla.go
  6. 2 2
      server.go
  7. 1 1
      server_test.go
  8. 15 0
      tls_go1.13.go
  9. 13 0
      tls_go1.14.go

+ 1 - 2
.travis.yml

@@ -1,10 +1,9 @@
 language: go
 language: go
 sudo: false
 sudo: false
 go:
 go:
-  - 1.9
-  - 1.10.x
   - 1.11.x
   - 1.11.x
   - 1.12.x
   - 1.12.x
+  - 1.13.x
   - master
   - master
 
 
 cache:
 cache:

+ 1 - 1
README.md

@@ -270,7 +270,7 @@ Using Nginx as a proxy
 
 
 For such purposes as load balancing, terminating TLS early,
 For such purposes as load balancing, terminating TLS early,
  or supporting SSL versions not supported by Go (highly not recommended if you
  or supporting SSL versions not supported by Go (highly not recommended if you
- want to use older SSL versions), 
+ want to use older TLS/SSL versions), 
  it is possible to [use NGINX as a proxy](https://github.com/flashmob/go-guerrilla/wiki/Using-Nginx-as-a-proxy).
  it is possible to [use NGINX as a proxy](https://github.com/flashmob/go-guerrilla/wiki/Using-Nginx-as-a-proxy).
 
 
 
 

+ 9 - 6
config.go

@@ -98,9 +98,13 @@ type ServerTLSConfig struct {
 // https://golang.org/pkg/crypto/tls/#pkg-constants
 // https://golang.org/pkg/crypto/tls/#pkg-constants
 // Ciphers introduced before Go 1.7 are listed here,
 // Ciphers introduced before Go 1.7 are listed here,
 // ciphers since Go 1.8, see tls_go1.8.go
 // ciphers since Go 1.8, see tls_go1.8.go
+// ....... since Go 1.13, see tls_go1.13.go
 var TLSCiphers = map[string]uint16{
 var TLSCiphers = map[string]uint16{
 
 
-	// // Note: Generally avoid using CBC unless for compatibility
+	// Note: Generally avoid using CBC unless for compatibility
+	// The following ciphersuites are not configurable for TLS 1.3
+	// see tls_go1.13.go for a list of ciphersuites always used in TLS 1.3
+
 	"TLS_RSA_WITH_3DES_EDE_CBC_SHA":        tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
 	"TLS_RSA_WITH_3DES_EDE_CBC_SHA":        tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
 	"TLS_RSA_WITH_AES_128_CBC_SHA":         tls.TLS_RSA_WITH_AES_128_CBC_SHA,
 	"TLS_RSA_WITH_AES_128_CBC_SHA":         tls.TLS_RSA_WITH_AES_128_CBC_SHA,
 	"TLS_RSA_WITH_AES_256_CBC_SHA":         tls.TLS_RSA_WITH_AES_256_CBC_SHA,
 	"TLS_RSA_WITH_AES_256_CBC_SHA":         tls.TLS_RSA_WITH_AES_256_CBC_SHA,
@@ -120,13 +124,12 @@ var TLSCiphers = map[string]uint16{
 	"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384":   tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
 	"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384":   tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
 	"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
 	"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
 
 
-	// Include to prevent downgrade attacks
-	"TLS_FALLBACK_SCSV": tls.TLS_FALLBACK_SCSV,
+	// see tls_go1.13 for new TLS 1.3 ciphersuites
+	// Note that TLS 1.3 ciphersuites are not configurable
 }
 }
 
 
 // https://golang.org/pkg/crypto/tls/#pkg-constants
 // https://golang.org/pkg/crypto/tls/#pkg-constants
 var TLSProtocols = map[string]uint16{
 var TLSProtocols = map[string]uint16{
-	"ssl3.0": tls.VersionSSL30,
 	"tls1.0": tls.VersionTLS10,
 	"tls1.0": tls.VersionTLS10,
 	"tls1.1": tls.VersionTLS11,
 	"tls1.1": tls.VersionTLS11,
 	"tls1.2": tls.VersionTLS12,
 	"tls1.2": tls.VersionTLS12,
@@ -174,7 +177,7 @@ func (c *AppConfig) Load(jsonBytes []byte) error {
 		}
 		}
 	}
 	}
 
 
-	// read the timestamps for the ssl keys, to determine if they need to be reloaded
+	// read the timestamps for the TLS keys, to determine if they need to be reloaded
 	for i := 0; i < len(c.Servers); i++ {
 	for i := 0; i < len(c.Servers); i++ {
 		if err := c.Servers[i].loadTlsKeyTimestamps(); err != nil {
 		if err := c.Servers[i].loadTlsKeyTimestamps(); err != nil {
 			return err
 			return err
@@ -404,7 +407,7 @@ func (sc *ServerConfig) emitChangeEvents(oldServer *ServerConfig, app Guerrilla)
 	}
 	}
 }
 }
 
 
-// Loads in timestamps for the ssl keys
+// Loads in timestamps for the TLS keys
 func (sc *ServerConfig) loadTlsKeyTimestamps() error {
 func (sc *ServerConfig) loadTlsKeyTimestamps() error {
 	var statErr = func(iface string, err error) error {
 	var statErr = func(iface string, err error) error {
 		return fmt.Errorf(
 		return fmt.Errorf(

+ 4 - 4
goguerrilla.conf.sample

@@ -31,8 +31,8 @@
                 "tls_always_on":false,
                 "tls_always_on":false,
                 "private_key_file":"/path/to/pem/file/test.com.key",
                 "private_key_file":"/path/to/pem/file/test.com.key",
                 "public_key_file":"/path/to/pem/file/test.com.crt",
                 "public_key_file":"/path/to/pem/file/test.com.crt",
-                "protocols" : ["ssl3.0", "tls1.2"],
-                "ciphers" : ["TLS_FALLBACK_SCSV", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_RSA_WITH_RC4_128_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"],
+                "protocols" : ["tls1.0", "tls1.2"],
+                "ciphers" : ["TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_RSA_WITH_RC4_128_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"],
                 "curves" : ["P256", "P384", "P521", "X25519"],
                 "curves" : ["P256", "P384", "P521", "X25519"],
                 "client_auth_type" : "NoClientCert"
                 "client_auth_type" : "NoClientCert"
             }
             }
@@ -50,8 +50,8 @@
                 "public_key_file":"/path/to/pem/file/test.com.crt",
                 "public_key_file":"/path/to/pem/file/test.com.crt",
                  "start_tls_on":false,
                  "start_tls_on":false,
                  "tls_always_on":true,
                  "tls_always_on":true,
-                 "protocols" : ["ssl3.0", "tls1.2"],
-                 "ciphers" : ["TLS_FALLBACK_SCSV", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_RSA_WITH_RC4_128_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"],
+                 "protocols" : ["tls1.0", "tls1.2"],
+                 "ciphers" : ["TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_RSA_WITH_RC4_128_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"],
                  "curves" : ["P256", "P384", "P521", "X25519"],
                  "curves" : ["P256", "P384", "P521", "X25519"],
                  "client_auth_type" : "NoClientCert"
                  "client_auth_type" : "NoClientCert"
             }
             }

+ 1 - 1
guerrilla.go

@@ -320,7 +320,7 @@ func (g *guerrilla) subscribeEvents() {
 	// TLS changes
 	// TLS changes
 	events[EventConfigServerTLSConfig] = serverEvent(func(sc *ServerConfig) {
 	events[EventConfigServerTLSConfig] = serverEvent(func(sc *ServerConfig) {
 		if server, err := g.findServer(sc.ListenInterface); err == nil {
 		if server, err := g.findServer(sc.ListenInterface); err == nil {
-			if err := server.configureSSL(); err == nil {
+			if err := server.configureTLS(); err == nil {
 				g.mainlog().Infof("Server [%s] new TLS configuration loaded", sc.ListenInterface)
 				g.mainlog().Infof("Server [%s] new TLS configuration loaded", sc.ListenInterface)
 			} else {
 			} else {
 				g.mainlog().WithError(err).Errorf("Server [%s] failed to load the new TLS configuration", sc.ListenInterface)
 				g.mainlog().WithError(err).Errorf("Server [%s] failed to load the new TLS configuration", sc.ListenInterface)

+ 2 - 2
server.go

@@ -113,13 +113,13 @@ func newServer(sc *ServerConfig, b backends.Backend, mainlog log.Logger) (*serve
 	}
 	}
 	server.setConfig(sc)
 	server.setConfig(sc)
 	server.setTimeout(sc.Timeout)
 	server.setTimeout(sc.Timeout)
-	if err := server.configureSSL(); err != nil {
+	if err := server.configureTLS(); err != nil {
 		return server, err
 		return server, err
 	}
 	}
 	return server, nil
 	return server, nil
 }
 }
 
 
-func (s *server) configureSSL() error {
+func (s *server) configureTLS() error {
 	sConfig := s.configStore.Load().(ServerConfig)
 	sConfig := s.configStore.Load().(ServerConfig)
 	if sConfig.TLS.AlwaysOn || sConfig.TLS.StartTLSOn {
 	if sConfig.TLS.AlwaysOn || sConfig.TLS.StartTLSOn {
 		cert, err := tls.LoadX509KeyPair(sConfig.TLS.PublicKeyFile, sConfig.TLS.PrivateKeyFile)
 		cert, err := tls.LoadX509KeyPair(sConfig.TLS.PublicKeyFile, sConfig.TLS.PrivateKeyFile)

+ 1 - 1
server_test.go

@@ -222,7 +222,7 @@ func TestTLSConfig(t *testing.T) {
 			Protocols:      []string{"tls1.0", "tls1.2"},
 			Protocols:      []string{"tls1.0", "tls1.2"},
 		},
 		},
 	})
 	})
-	if err := s.configureSSL(); err != nil {
+	if err := s.configureTLS(); err != nil {
 		t.Error(err)
 		t.Error(err)
 	}
 	}
 
 

+ 15 - 0
tls_go1.13.go

@@ -0,0 +1,15 @@
+// +build go1.13
+
+package guerrilla
+
+import "crypto/tls"
+
+// TLS 1.3 was introduced in go 1.12 as an option and enabled for production in go 1.13
+// release notes: https://golang.org/doc/go1.12#tls_1_3
+func init() {
+	TLSProtocols["tls1.3"] = tls.VersionTLS13
+
+	TLSCiphers["TLS_AES_128_GCM_SHA256"] = tls.TLS_AES_128_GCM_SHA256
+	TLSCiphers["TLS_AES_256_GCM_SHA384"] = tls.TLS_AES_256_GCM_SHA384
+	TLSCiphers["TLS_CHACHA20_POLY1305_SHA256"] = tls.TLS_CHACHA20_POLY1305_SHA256
+}

+ 13 - 0
tls_go1.14.go

@@ -0,0 +1,13 @@
+// +build !go1.14
+
+package guerrilla
+
+import "crypto/tls"
+
+func init() {
+
+	TLSProtocols["ssl3.0"] = tls.VersionSSL30 // deprecated since GO 1.13, removed 1.14
+
+	// Include to prevent downgrade attacks (SSLv3 only, deprecated in Go 1.13)
+	TLSCiphers["TLS_FALLBACK_SCSV"] = tls.TLS_FALLBACK_SCSV
+}