diff --git a/docs/content/https/tls.md b/docs/content/https/tls.md
index b7321413c..7dc9bc975 100644
--- a/docs/content/https/tls.md
+++ b/docs/content/https/tls.md
@@ -553,4 +553,38 @@ spec:
clientAuthType: RequireAndVerifyClientCert
```
+### Disable Session Tickets
+
+_Optional, Default="false"_
+
+When set to true, Traefik disables the use of session tickets, forcing every client to perform a full TLS handshake instead of resuming sessions.
+
+```yaml tab="File (YAML)"
+# Dynamic configuration
+
+tls:
+ options:
+ default:
+ disableSessionTickets: true
+```
+
+```toml tab="File (TOML)"
+# Dynamic configuration
+
+[tls.options]
+ [tls.options.default]
+ disableSessionTickets = true
+```
+
+```yaml tab="Kubernetes"
+apiVersion: traefik.io/v1alpha1
+kind: TLSOption
+metadata:
+ name: default
+ namespace: default
+
+spec:
+ disableSessionTickets: true
+```
+
{!traefik-for-business-applications.md!}
diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml
index 1c54defe8..9915ff223 100644
--- a/docs/content/reference/dynamic-configuration/file.toml
+++ b/docs/content/reference/dynamic-configuration/file.toml
@@ -570,6 +570,7 @@
curvePreferences = ["foobar", "foobar"]
sniStrict = true
alpnProtocols = ["foobar", "foobar"]
+ disableSessionTickets = true
preferServerCipherSuites = true
[tls.options.Options0.clientAuth]
caFiles = ["foobar", "foobar"]
@@ -581,6 +582,7 @@
curvePreferences = ["foobar", "foobar"]
sniStrict = true
alpnProtocols = ["foobar", "foobar"]
+ disableSessionTickets = true
preferServerCipherSuites = true
[tls.options.Options1.clientAuth]
caFiles = ["foobar", "foobar"]
diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml
index 2a8956bbc..30f0afa59 100644
--- a/docs/content/reference/dynamic-configuration/file.yaml
+++ b/docs/content/reference/dynamic-configuration/file.yaml
@@ -644,6 +644,7 @@ tls:
alpnProtocols:
- foobar
- foobar
+ disableSessionTickets: true
preferServerCipherSuites: true
Options1:
minVersion: foobar
@@ -663,6 +664,7 @@ tls:
alpnProtocols:
- foobar
- foobar
+ disableSessionTickets: true
preferServerCipherSuites: true
stores:
Store0:
diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
index 90a1dca49..0c5aaf043 100644
--- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
+++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
@@ -2540,6 +2540,10 @@ spec:
items:
type: string
type: array
+ disableSessionTickets:
+ description: DisableSessionTickets disables TLS session resumption
+ via session tickets.
+ type: boolean
maxVersion:
description: |-
MaxVersion defines the maximum TLS version that Traefik will accept.
diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md
index 4d218e599..65f3b8760 100644
--- a/docs/content/reference/dynamic-configuration/kv-ref.md
+++ b/docs/content/reference/dynamic-configuration/kv-ref.md
@@ -415,6 +415,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/tls/options/Options0/clientAuth/clientAuthType` | `foobar` |
| `traefik/tls/options/Options0/curvePreferences/0` | `foobar` |
| `traefik/tls/options/Options0/curvePreferences/1` | `foobar` |
+| `traefik/tls/options/Options0/disableSessionTickets` | `true` |
| `traefik/tls/options/Options0/maxVersion` | `foobar` |
| `traefik/tls/options/Options0/minVersion` | `foobar` |
| `traefik/tls/options/Options0/preferServerCipherSuites` | `true` |
@@ -428,6 +429,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/tls/options/Options1/clientAuth/clientAuthType` | `foobar` |
| `traefik/tls/options/Options1/curvePreferences/0` | `foobar` |
| `traefik/tls/options/Options1/curvePreferences/1` | `foobar` |
+| `traefik/tls/options/Options1/disableSessionTickets` | `true` |
| `traefik/tls/options/Options1/maxVersion` | `foobar` |
| `traefik/tls/options/Options1/minVersion` | `foobar` |
| `traefik/tls/options/Options1/preferServerCipherSuites` | `true` |
diff --git a/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml b/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml
index 9995d0af7..c4d3b0f81 100644
--- a/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml
+++ b/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml
@@ -83,6 +83,10 @@ spec:
items:
type: string
type: array
+ disableSessionTickets:
+ description: DisableSessionTickets disables TLS session resumption
+ via session tickets.
+ type: boolean
maxVersion:
description: |-
MaxVersion defines the maximum TLS version that Traefik will accept.
diff --git a/docs/content/reference/routing-configuration/http/tls/tls-options.md b/docs/content/reference/routing-configuration/http/tls/tls-options.md
index f2f6f478b..992b3497c 100644
--- a/docs/content/reference/routing-configuration/http/tls/tls-options.md
+++ b/docs/content/reference/routing-configuration/http/tls/tls-options.md
@@ -225,4 +225,38 @@ tls:
clientAuthType = "RequireAndVerifyClientCert"
```
+### Disable Session Tickets
+
+_Optional, Default="false"_
+
+When set to true, Traefik disables the use of session tickets, forcing every client to perform a full TLS handshake instead of resuming sessions.
+
+```yaml tab="File (YAML)"
+# Dynamic configuration
+
+tls:
+ options:
+ default:
+ disableSessionTickets: true
+```
+
+```toml tab="File (TOML)"
+# Dynamic configuration
+
+[tls.options]
+ [tls.options.default]
+ disableSessionTickets = true
+```
+
+```yaml tab="Kubernetes"
+apiVersion: traefik.io/v1alpha1
+kind: TLSOption
+metadata:
+ name: default
+ namespace: default
+
+spec:
+ disableSessionTickets: true
+```
+
{!traefik-for-business-applications.md!}
diff --git a/docs/content/reference/routing-configuration/kubernetes/crd/http/tlsoption.md b/docs/content/reference/routing-configuration/kubernetes/crd/http/tlsoption.md
index 7152b9af8..6887e8516 100644
--- a/docs/content/reference/routing-configuration/kubernetes/crd/http/tlsoption.md
+++ b/docs/content/reference/routing-configuration/kubernetes/crd/http/tlsoption.md
@@ -46,16 +46,17 @@ spec:
## Configuration Options
-| Field | Description | Default | Required |
-|:----------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------|:---------|
-| `minVersion` | Minimum TLS version that is acceptable. | "VersionTLS12" | No |
-| `maxVersion` | Maximum TLS version that is acceptable.
We do not recommend setting this option to disable TLS 1.3. | | No |
-| `cipherSuites` | List of supported [cipher suites](https://godoc.org/crypto/tls#pkg-constants) for TLS versions up to TLS 1.2.
[Cipher suites defined for TLS 1.2 and below cannot be used in TLS 1.3, and vice versa.](https://tools.ietf.org/html/rfc8446)
With TLS 1.3, [the cipher suites are not configurable](https://golang.org/doc/go1.12#tls_1_3) (all supported cipher suites are safe in this case). | | No |
-| `curvePreferences` | List of the elliptic curves references that will be used in an ECDHE handshake, in preference order.
Use curves names from [`crypto`](https://godoc.org/crypto/tls#CurveID) or the [RFC](https://tools.ietf.org/html/rfc8446#section-4.2.7).
See [CurveID](https://godoc.org/crypto/tls#CurveID) for more information. | | No |
-| `clientAuth.secretNames` | Client Authentication (mTLS) option.
List of names of the referenced Kubernetes [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/) (in TLSOption namespace).
The secret must contain a certificate under either a `tls.ca` or a `ca.crt` key. | | No |
-| `clientAuth.clientAuthType` | Client Authentication (mTLS) option.
Client authentication type to apply. Available values [here](#client-authentication-mtls). | | No |
-| `sniStrict` | Allow rejecting connections from clients connections that do not specify a server_name extension.
The [default certificate](../../../http/tls/tls-certificates.md#default-certificate) is never served is the option is enabled. | false | No |
-| `alpnProtocols` | List of supported application level protocols for the TLS handshake, in order of preference.
If the client supports ALPN, the selected protocol will be one from this list, and the connection will fail if there is no mutually supported protocol. | "h2, http/1.1, acme-tls/1" | No |
+| Field | Description | Default | Required |
+|:----------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------|:---------|
+| `minVersion` | Minimum TLS version that is acceptable. | "VersionTLS12" | No |
+| `maxVersion` | Maximum TLS version that is acceptable.
We do not recommend setting this option to disable TLS 1.3. | | No |
+| `cipherSuites` | List of supported [cipher suites](https://godoc.org/crypto/tls#pkg-constants) for TLS versions up to TLS 1.2.
[Cipher suites defined for TLS 1.2 and below cannot be used in TLS 1.3, and vice versa.](https://tools.ietf.org/html/rfc8446)
With TLS 1.3, [the cipher suites are not configurable](https://golang.org/doc/go1.12#tls_1_3) (all supported cipher suites are safe in this case). | | No |
+| `curvePreferences` | List of the elliptic curves references that will be used in an ECDHE handshake, in preference order.
Use curves names from [`crypto`](https://godoc.org/crypto/tls#CurveID) or the [RFC](https://tools.ietf.org/html/rfc8446#section-4.2.7).
See [CurveID](https://godoc.org/crypto/tls#CurveID) for more information. | | No |
+| `clientAuth.secretNames` | Client Authentication (mTLS) option.
List of names of the referenced Kubernetes [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/) (in TLSOption namespace).
The secret must contain a certificate under either a `tls.ca` or a `ca.crt` key. | | No |
+| `clientAuth.clientAuthType` | Client Authentication (mTLS) option.
Client authentication type to apply. Available values [here](#client-authentication-mtls). | | No |
+| `sniStrict` | Allow rejecting connections from clients connections that do not specify a server_name extension.
The [default certificate](../../../http/tls/tls-certificates.md#default-certificate) is never served is the option is enabled. | false | No |
+| `alpnProtocols` | List of supported application level protocols for the TLS handshake, in order of preference.
If the client supports ALPN, the selected protocol will be one from this list, and the connection will fail if there is no mutually supported protocol. | "h2, http/1.1, acme-tls/1" | No |
+| `disableSessiontTickets` | Allow disabling the use of session tickets, forcing every client to perform a full TLS handshake instead of resuming sessions. | false | No |
### Client Authentication (mTLS)
@@ -75,8 +76,8 @@ The `clientAuth.clientAuthType` option governs the behaviour as follows:
When no TLS options are specified in an `IngressRoute`/`IngressRouteTCP`, the `default` option is used.
The default behavior is summed up in the table below:
-| Configuration | Behavior |
-|:--------------------------|:-----------------------------------------------------------|
-| No `default` TLS Option | Default internal set of TLS Options by default. |
-| One `default` TLS Option | Custom TLS Options applied by default. |
+| Configuration | Behavior |
+|:--------------------------|:------------------------------------------------------------|
+| No `default` TLS Option | Default internal set of TLS Options by default. |
+| One `default` TLS Option | Custom TLS Options applied by default. |
| Many `default` TLS Option | Error log + Default internal set of TLS Options by default. |
diff --git a/docs/content/reference/routing-configuration/other-providers/kv.md b/docs/content/reference/routing-configuration/other-providers/kv.md
index dc64e82f4..963d83cb0 100644
--- a/docs/content/reference/routing-configuration/other-providers/kv.md
+++ b/docs/content/reference/routing-configuration/other-providers/kv.md
@@ -594,11 +594,12 @@ You can declare UDP Routers and/or Services using KV.
With the KV provider, you configure some parameters of the TLS connection using the `tls/options` key. For example, you can define a basic setup like this:
-| Key (Path) | Value |
-|---------------------------------------------------------------------------------|------------------|
-| `traefik/tls/options/Options0/alpnProtocols/0` | `foobar` |
-| `traefik/tls/options/Options0/cipherSuites/0` | `foobar` |
-| `traefik/tls/options/Options0/clientAuth/caFiles/0` | `foobar` |
+| Key (Path) | Value |
+|------------------------------------------------------|----------|
+| `traefik/tls/options/Options0/alpnProtocols/0` | `foobar` |
+| `traefik/tls/options/Options0/cipherSuites/0` | `foobar` |
+| `traefik/tls/options/Options0/clientAuth/caFiles/0` | `foobar` |
+| `traefik/tls/options/Options0/disableSessiontickets` | `true` |
For more information on the available TLS options that can be configured, please refer to the [TLS Options](../http/tls/tls-options.md) page.
@@ -606,9 +607,9 @@ For more information on the available TLS options that can be configured, please
You can configure Traefik to use an ACME provider (like Let's Encrypt) to generate the default certificate. The configuration to resolve the default certificate should be defined in a TLS store:
-| Key (Path) | Value |
-|---------------------------------------------------------------------------------|----------------|
-| `traefik/tls/stores/Store0/defaultGeneratedCert/domain/main` | `foobar` |
-| `traefik/tls/stores/Store0/defaultGeneratedCert/domain/sans/0` | `foobar` |
-| `traefik/tls/stores/Store0/defaultGeneratedCert/domain/sans/1` | `foobar` |
-| `traefik/tls/stores/Store0/defaultGeneratedCert/resolver` | `foobar` |
+| Key (Path) | Value |
+|----------------------------------------------------------------|----------|
+| `traefik/tls/stores/Store0/defaultGeneratedCert/domain/main` | `foobar` |
+| `traefik/tls/stores/Store0/defaultGeneratedCert/domain/sans/0` | `foobar` |
+| `traefik/tls/stores/Store0/defaultGeneratedCert/domain/sans/1` | `foobar` |
+| `traefik/tls/stores/Store0/defaultGeneratedCert/resolver` | `foobar` |
diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml
index 90a1dca49..0c5aaf043 100644
--- a/integration/fixtures/k8s/01-traefik-crd.yml
+++ b/integration/fixtures/k8s/01-traefik-crd.yml
@@ -2540,6 +2540,10 @@ spec:
items:
type: string
type: array
+ disableSessionTickets:
+ description: DisableSessionTickets disables TLS session resumption
+ via session tickets.
+ type: boolean
maxVersion:
description: |-
MaxVersion defines the maximum TLS version that Traefik will accept.
diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options.yml
index 123abc113..453851da8 100644
--- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options.yml
+++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options.yml
@@ -30,6 +30,7 @@ spec:
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384
+ disableSessionTickets: true
clientAuth:
secretNames:
- secret-ca1
diff --git a/pkg/provider/kubernetes/crd/fixtures/with_tls_options.yml b/pkg/provider/kubernetes/crd/fixtures/with_tls_options.yml
index f4bb0850a..5ca5954e2 100644
--- a/pkg/provider/kubernetes/crd/fixtures/with_tls_options.yml
+++ b/pkg/provider/kubernetes/crd/fixtures/with_tls_options.yml
@@ -30,6 +30,7 @@ spec:
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384
+ disableSessionTickets: true
clientAuth:
secretNames:
- secret-ca1
diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go
index 566a2bc39..2b374eeba 100644
--- a/pkg/provider/kubernetes/crd/kubernetes.go
+++ b/pkg/provider/kubernetes/crd/kubernetes.go
@@ -1273,6 +1273,8 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options
tlsOption.ALPNProtocols = tlsOptionsCRD.Spec.ALPNProtocols
}
+ tlsOption.DisableSessionTickets = tlsOptionsCRD.Spec.DisableSessionTickets
+
tlsOptions[id] = tlsOption
}
diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go
index e14eef1ef..93b43fdfb 100644
--- a/pkg/provider/kubernetes/crd/kubernetes_test.go
+++ b/pkg/provider/kubernetes/crd/kubernetes_test.go
@@ -732,7 +732,8 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
},
ClientAuthType: "VerifyClientCertIfGiven",
},
- SniStrict: true,
+ SniStrict: true,
+ DisableSessionTickets: true,
ALPNProtocols: []string{
"h2",
"http/1.1",
@@ -3401,7 +3402,8 @@ func TestLoadIngressRoutes(t *testing.T) {
},
ClientAuthType: "VerifyClientCertIfGiven",
},
- SniStrict: true,
+ SniStrict: true,
+ DisableSessionTickets: true,
ALPNProtocols: []string{
"h2",
"http/1.1",
diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go
index 61b88fa3e..178100cd9 100644
--- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go
+++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go
@@ -44,7 +44,8 @@ type TLSOptionSpec struct {
// ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference.
// More info: https://doc.traefik.io/traefik/v3.3/https/tls/#alpn-protocols
ALPNProtocols []string `json:"alpnProtocols,omitempty"`
-
+ // DisableSessionTickets disables TLS session resumption via session tickets.
+ DisableSessionTickets bool `json:"disableSessionTickets,omitempty"`
// PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
// It is enabled automatically when minVersion or maxVersion is set.
// Deprecated: https://github.com/golang/go/issues/45430
diff --git a/pkg/tls/tls.go b/pkg/tls/tls.go
index c8964d0ed..d98fc9483 100644
--- a/pkg/tls/tls.go
+++ b/pkg/tls/tls.go
@@ -18,13 +18,14 @@ type ClientAuth struct {
// Options configures TLS for an entry point.
type Options struct {
- MinVersion string `json:"minVersion,omitempty" toml:"minVersion,omitempty" yaml:"minVersion,omitempty" export:"true"`
- MaxVersion string `json:"maxVersion,omitempty" toml:"maxVersion,omitempty" yaml:"maxVersion,omitempty" export:"true"`
- CipherSuites []string `json:"cipherSuites,omitempty" toml:"cipherSuites,omitempty" yaml:"cipherSuites,omitempty" export:"true"`
- CurvePreferences []string `json:"curvePreferences,omitempty" toml:"curvePreferences,omitempty" yaml:"curvePreferences,omitempty" export:"true"`
- ClientAuth ClientAuth `json:"clientAuth,omitempty" toml:"clientAuth,omitempty" yaml:"clientAuth,omitempty"`
- SniStrict bool `json:"sniStrict,omitempty" toml:"sniStrict,omitempty" yaml:"sniStrict,omitempty" export:"true"`
- ALPNProtocols []string `json:"alpnProtocols,omitempty" toml:"alpnProtocols,omitempty" yaml:"alpnProtocols,omitempty" export:"true"`
+ MinVersion string `json:"minVersion,omitempty" toml:"minVersion,omitempty" yaml:"minVersion,omitempty" export:"true"`
+ MaxVersion string `json:"maxVersion,omitempty" toml:"maxVersion,omitempty" yaml:"maxVersion,omitempty" export:"true"`
+ CipherSuites []string `json:"cipherSuites,omitempty" toml:"cipherSuites,omitempty" yaml:"cipherSuites,omitempty" export:"true"`
+ CurvePreferences []string `json:"curvePreferences,omitempty" toml:"curvePreferences,omitempty" yaml:"curvePreferences,omitempty" export:"true"`
+ ClientAuth ClientAuth `json:"clientAuth,omitempty" toml:"clientAuth,omitempty" yaml:"clientAuth,omitempty"`
+ SniStrict bool `json:"sniStrict,omitempty" toml:"sniStrict,omitempty" yaml:"sniStrict,omitempty" export:"true"`
+ ALPNProtocols []string `json:"alpnProtocols,omitempty" toml:"alpnProtocols,omitempty" yaml:"alpnProtocols,omitempty" export:"true"`
+ DisableSessionTickets bool `json:"disableSessionTickets,omitempty" toml:"disableSessionTickets,omitempty" yaml:"disableSessionTickets,omitempty" export:"true"`
// Deprecated: https://github.com/golang/go/issues/45430
PreferServerCipherSuites *bool `json:"preferServerCipherSuites,omitempty" toml:"preferServerCipherSuites,omitempty" yaml:"preferServerCipherSuites,omitempty" export:"true"`
diff --git a/pkg/tls/tlsmanager.go b/pkg/tls/tlsmanager.go
index ecf9692cf..7fcbeab76 100644
--- a/pkg/tls/tlsmanager.go
+++ b/pkg/tls/tlsmanager.go
@@ -325,7 +325,8 @@ func getDefaultCertificate(ctx context.Context, tlsStore Store, st *CertificateS
// creates a TLS config that allows terminating HTTPS for multiple domains using SNI.
func buildTLSConfig(tlsOption Options) (*tls.Config, error) {
conf := &tls.Config{
- NextProtos: tlsOption.ALPNProtocols,
+ NextProtos: tlsOption.ALPNProtocols,
+ SessionTicketsDisabled: tlsOption.DisableSessionTickets,
}
if len(tlsOption.ClientAuth.CAFiles) > 0 {
diff --git a/pkg/tls/tlsmanager_test.go b/pkg/tls/tlsmanager_test.go
index 340c57081..f6df9c3c8 100644
--- a/pkg/tls/tlsmanager_test.go
+++ b/pkg/tls/tlsmanager_test.go
@@ -331,6 +331,7 @@ func TestManager_Get_DefaultValues(t *testing.T) {
config, _ := tlsManager.Get("default", "default")
assert.Equal(t, uint16(tls.VersionTLS12), config.MinVersion)
assert.Equal(t, []string{"h2", "http/1.1", "acme-tls/1"}, config.NextProtos)
+ assert.False(t, config.SessionTicketsDisabled)
assert.Equal(t, []uint16{
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,