diff --git a/configuration.go b/configuration.go index 9235eb723..57c0b54b2 100644 --- a/configuration.go +++ b/configuration.go @@ -177,10 +177,33 @@ type Redirect struct { // TLS configures TLS for an entry point type TLS struct { + MinVersion string + CipherSuites []string Certificates Certificates ClientCAFiles []string } +// Map of allowed TLS minimum versions +var minVersion = map[string]uint16{ + `VersionTLS10`: tls.VersionTLS10, + `VersionTLS11`: tls.VersionTLS11, + `VersionTLS12`: tls.VersionTLS12, +} + +// Map of TLS CipherSuites from crypto/tls +var cipherSuites = map[string]uint16{ + `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`: tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA`: tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + `TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA`: tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + `TLS_RSA_WITH_AES_128_GCM_SHA256`: tls.TLS_RSA_WITH_AES_128_GCM_SHA256, + `TLS_RSA_WITH_AES_256_GCM_SHA384`: tls.TLS_RSA_WITH_AES_256_GCM_SHA384, + `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_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA`: tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + `TLS_RSA_WITH_3DES_EDE_CBC_SHA`: tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, +} + // Certificates defines traefik certificates type // Certs and Keys could be either a file path, or the file content itself type Certificates []Certificate diff --git a/docs/toml.md b/docs/toml.md index e428fe10d..5179bba18 100644 --- a/docs/toml.md +++ b/docs/toml.md @@ -183,6 +183,20 @@ Supported filters: # address = ":80" # [entryPoints.http.auth.basic] # users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] +# +# To specify an https entrypoint with a minimum TLS version, and specifying an array of cipher suites (from crypto/tls): +# [entryPoints] +# [entryPoints.https] +# address = ":443" +# [entryPoints.https.tls] +# MinVersion = "VersionTLS12" +# CipherSuites = ["TLS_RSA_WITH_AES_256_GCM_SHA384"] +# [[entryPoints.https.tls.certificates]] +# CertFile = "integration/fixtures/https/snitest.com.cert" +# KeyFile = "integration/fixtures/https/snitest.com.key" +# [[entryPoints.https.tls.certificates]] +# CertFile = "integration/fixtures/https/snitest.org.cert" +# KeyFile = "integration/fixtures/https/snitest.org.key" [entryPoints] [entryPoints.http] @@ -464,12 +478,12 @@ address = ":8080" # To enable basic auth on the webui # with 2 user/pass: test:test and test2:test2 # Passwords can be encoded in MD5, SHA1 and BCrypt: you can use htpasswd to generate those ones -# [web.auth.basic] +# [web.auth.basic] # users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"] # To enable digest auth on the webui # with 2 user/realm/pass: test:traefik:test and test2:traefik:test2 # You can use htdigest to generate those ones -# [web.auth.basic] +# [web.auth.basic] # users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] ``` diff --git a/server.go b/server.go index 42c1b464d..b7e9106a8 100644 --- a/server.go +++ b/server.go @@ -387,6 +387,24 @@ func (server *Server) createTLSConfig(entryPointName string, tlsOption *TLS, rou // BuildNameToCertificate parses the CommonName and SubjectAlternateName fields // in each certificate and populates the config.NameToCertificate map. config.BuildNameToCertificate() + //Set the minimum TLS version if set in the config TOML + if minConst, exists := minVersion[server.globalConfiguration.EntryPoints[entryPointName].TLS.MinVersion]; exists { + config.PreferServerCipherSuites = true + config.MinVersion = minConst + } + //Set the list of CipherSuites if set in the config TOML + if server.globalConfiguration.EntryPoints[entryPointName].TLS.CipherSuites != nil { + //if our list of CipherSuites is defined in the entrypoint config, we can re-initilize the suites list as empty + config.CipherSuites = make([]uint16, 0) + for _, cipher := range server.globalConfiguration.EntryPoints[entryPointName].TLS.CipherSuites { + if cipherConst, exists := cipherSuites[cipher]; exists { + config.CipherSuites = append(config.CipherSuites, cipherConst) + } else { + //CipherSuite listed in the toml does not exist in our listed + return nil, errors.New("Invalid CipherSuite: " + cipher) + } + } + } return config, nil } diff --git a/traefik.sample.toml b/traefik.sample.toml index 8974013e7..0a71359f9 100644 --- a/traefik.sample.toml +++ b/traefik.sample.toml @@ -204,7 +204,20 @@ # address = ":80" # [entryPoints.http.auth.basic] # users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] - +# +# To specify an https entrypoint with a minimum TLS version, and specifying an array of cipher suites (from crypto/tls): +# [entryPoints] +# [entryPoints.https] +# address = ":443" +# [entryPoints.https.tls] +# MinVersion = "VersionTLS12" +# CipherSuites = ["TLS_RSA_WITH_AES_256_GCM_SHA384"] +# [[entryPoints.https.tls.certificates]] +# CertFile = "integration/fixtures/https/snitest.com.cert" +# KeyFile = "integration/fixtures/https/snitest.com.key" +# [[entryPoints.https.tls.certificates]] +# CertFile = "integration/fixtures/https/snitest.org.cert" +# KeyFile = "integration/fixtures/https/snitest.org.key" # Enable retry sending request if network error # @@ -250,12 +263,12 @@ # To enable basic auth on the webui # with 2 user/pass: test:test and test2:test2 # Passwords can be encoded in MD5, SHA1 and BCrypt: you can use htpasswd to generate those ones -# [web.auth.basic] +# [web.auth.basic] # users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"] # To enable digest auth on the webui # with 2 user/realm/pass: test:traefik:test and test2:traefik:test2 # You can use htdigest to generate those ones -# [web.auth.basic] +# [web.auth.basic] # users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"]