diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 77930754b..151e71e58 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -3,7 +3,6 @@ package main import ( "context" "crypto/x509" - "encoding/json" "fmt" "io" stdlog "log" @@ -40,6 +39,7 @@ import ( "github.com/traefik/traefik/v3/pkg/provider/traefik" "github.com/traefik/traefik/v3/pkg/proxy" "github.com/traefik/traefik/v3/pkg/proxy/httputil" + "github.com/traefik/traefik/v3/pkg/redactor" "github.com/traefik/traefik/v3/pkg/safe" "github.com/traefik/traefik/v3/pkg/server" "github.com/traefik/traefik/v3/pkg/server/middleware" @@ -104,12 +104,11 @@ func runCmd(staticConfiguration *static.Configuration) error { log.Info().Str("version", version.Version). Msgf("Traefik version %s built on %s", version.Version, version.BuildDate) - jsonConf, err := json.Marshal(staticConfiguration) + redactedStaticConfiguration, err := redactor.RemoveCredentials(staticConfiguration) if err != nil { - log.Error().Err(err).Msg("Could not marshal static configuration") - log.Debug().Interface("staticConfiguration", staticConfiguration).Msg("Static configuration loaded [struct]") + log.Error().Err(err).Msg("Could not redact static configuration") } else { - log.Debug().RawJSON("staticConfiguration", jsonConf).Msg("Static configuration loaded [json]") + log.Debug().RawJSON("staticConfiguration", []byte(redactedStaticConfiguration)).Msg("Static configuration loaded [json]") } if staticConfiguration.Global.CheckNewVersion { diff --git a/docs/content/https/tls.md b/docs/content/https/tls.md index 7dc9bc975..e022118b8 100644 --- a/docs/content/https/tls.md +++ b/docs/content/https/tls.md @@ -384,11 +384,11 @@ spec: ### Curve Preferences -This option allows to set the preferred elliptic curves in a specific order. +This option allows to set the enabled elliptic curves for key exchange. The names of the curves defined by [`crypto`](https://godoc.org/crypto/tls#CurveID) (e.g. `CurveP521`) and the [RFC defined names](https://tools.ietf.org/html/rfc8446#section-4.2.7) (e. g. `secp521r1`) can be used. -See [CurveID](https://godoc.org/crypto/tls#CurveID) for more information. +See [CurvePreferences](https://godoc.org/crypto/tls#Config.CurvePreferences) and [CurveID](https://godoc.org/crypto/tls#CurveID) for more information. ```yaml tab="File (YAML)" # Dynamic configuration diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index d0a879781..74e6e3ea1 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -706,3 +706,14 @@ and Traefik now keeps them encoded to avoid any ambiguity. | `/foo/../bar` | PathPrefix(`/bar`) | Match | Match | | `/foo/%2E%2E/bar` | PathPrefix(`/foo`) | Match | No match | | `/foo/%2E%2E/bar` | PathPrefix(`/bar`) | No match | Match | + +## v2.11.28 + +### MultiPath TCP + +Since `v2.11.28`, the MultiPath TCP support introduced with `v2.11.26` has been removed. +It appears that enabling MPTCP on some platforms can cause Traefik to stop with the following error logs message: + +- `set tcp X.X.X.X:X->X.X.X.X:X: setsockopt: operation not supported` + +However, it can be re-enabled by setting the `multipathtcp` variable in the GODEBUG environment variable, see the related [go documentation](https://go.dev/doc/godebug#go-124). 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 59fc65910..6a1aca029 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -2533,7 +2533,7 @@ spec: type: object curvePreferences: description: |- - CurvePreferences defines the preferred elliptic curves in a specific order. + CurvePreferences defines the preferred elliptic curves. More info: https://doc.traefik.io/traefik/v3.4/https/tls/#curve-preferences items: type: string diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsoptions.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsoptions.yaml new file mode 100644 index 000000000..6c7fdc914 --- /dev/null +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsoptions.yaml @@ -0,0 +1,114 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: tlsoptions.traefik.containo.us +spec: + group: traefik.containo.us + names: + kind: TLSOption + listKind: TLSOptionList + plural: tlsoptions + singular: tlsoption + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. + More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TLSOptionSpec defines the desired state of a TLSOption. + properties: + alpnProtocols: + description: |- + ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. + More info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols + items: + type: string + type: array + cipherSuites: + description: |- + CipherSuites defines the list of supported cipher suites for TLS versions up to TLS 1.2. + More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites + items: + type: string + type: array + clientAuth: + description: ClientAuth defines the server's policy for TLS Client + Authentication. + properties: + clientAuthType: + description: ClientAuthType defines the client authentication + type to apply. + enum: + - NoClientCert + - RequestClientCert + - RequireAnyClientCert + - VerifyClientCertIfGiven + - RequireAndVerifyClientCert + type: string + secretNames: + description: SecretNames defines the names of the referenced Kubernetes + Secret storing certificate details. + items: + type: string + type: array + type: object + curvePreferences: + description: |- + CurvePreferences defines the preferred elliptic curves. + More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences + items: + type: string + type: array + maxVersion: + description: |- + MaxVersion defines the maximum TLS version that Traefik will accept. + Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + Default: None. + type: string + minVersion: + description: |- + MinVersion defines the minimum TLS version that Traefik will accept. + Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + Default: VersionTLS10. + type: string + preferServerCipherSuites: + description: |- + 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 + type: boolean + sniStrict: + description: SniStrict defines whether Traefik allows connections + from clients connections that do not specify a server_name extension. + type: boolean + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml b/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml index 758a0ab96..07d7b9d03 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml @@ -78,7 +78,7 @@ spec: type: object curvePreferences: description: |- - CurvePreferences defines the preferred elliptic curves in a specific order. + CurvePreferences defines the preferred elliptic curves. More info: https://doc.traefik.io/traefik/v3.4/https/tls/#curve-preferences items: type: string 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 992b3497c..2cea7c661 100644 --- a/docs/content/reference/routing-configuration/http/tls/tls-options.md +++ b/docs/content/reference/routing-configuration/http/tls/tls-options.md @@ -106,7 +106,7 @@ tls: ### Curve Preferences -This option allows to set the preferred elliptic curves in a specific order. +This option allows to set the preferred elliptic curves. The names of the curves defined by [`crypto`](https://godoc.org/crypto/tls#CurveID) (e.g. `CurveP521`) and the [RFC defined names](https://tools.ietf.org/html/rfc8446#section-4.2.7) (e. g. `secp521r1`) can be used. 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 6887e8516..76bb932cf 100644 --- a/docs/content/reference/routing-configuration/kubernetes/crd/http/tlsoption.md +++ b/docs/content/reference/routing-configuration/kubernetes/crd/http/tlsoption.md @@ -51,7 +51,7 @@ spec: | `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 | +| `curvePreferences` | List of the elliptic curves references that will be used in an ECDHE handshake.
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 | @@ -60,7 +60,7 @@ spec: ### Client Authentication (mTLS) -The `clientAuth.clientAuthType` option governs the behaviour as follows: +The `clientAuth.clientAuthType` option governs the behavior as follows: - `NoClientCert`: disregards any client certificate. - `RequestClientCert`: asks for a certificate but proceeds anyway if none is provided. diff --git a/docs/content/routing/providers/kubernetes-crd.md b/docs/content/routing/providers/kubernetes-crd.md index d19c4c66c..fd47e8813 100644 --- a/docs/content/routing/providers/kubernetes-crd.md +++ b/docs/content/routing/providers/kubernetes-crd.md @@ -1671,7 +1671,7 @@ or referencing TLS options in the [`IngressRoute`](#kind-ingressroute) / [`Ingre | [2] | `minVersion` | Defines the [minimum TLS version](../../https/tls.md#minimum-tls-version) that is acceptable. | | [3] | `maxVersion` | Defines the [maximum TLS version](../../https/tls.md#maximum-tls-version) that is acceptable. | | [4] | `cipherSuites` | list of supported [cipher suites](../../https/tls.md#cipher-suites) for TLS versions up to TLS 1.2. | -| [5] | `curvePreferences` | List of the [elliptic curves references](../../https/tls.md#curve-preferences) that will be used in an ECDHE handshake, in preference order. | +| [5] | `curvePreferences` | List of the [elliptic curves references](../../https/tls.md#curve-preferences) that will be used in an ECDHE handshake. | | [6] | `clientAuth` | determines the server's policy for TLS [Client Authentication](../../https/tls.md#client-authentication-mtls). | | [7] | `clientAuth.secretNames` | 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. | | [8] | `clientAuth.clientAuthType` | defines the client authentication type to apply. The available values are: `NoClientCert`, `RequestClientCert`, `VerifyClientCertIfGiven` and `RequireAndVerifyClientCert`. | diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index 59fc65910..6a1aca029 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -2533,7 +2533,7 @@ spec: type: object curvePreferences: description: |- - CurvePreferences defines the preferred elliptic curves in a specific order. + CurvePreferences defines the preferred elliptic curves. More info: https://doc.traefik.io/traefik/v3.4/https/tls/#curve-preferences items: type: string diff --git a/pkg/plugins/client.go b/pkg/plugins/client.go index ac4e71bcf..8d119ddec 100644 --- a/pkg/plugins/client.go +++ b/pkg/plugins/client.go @@ -238,6 +238,9 @@ func (c *Client) Unzip(pName, pVersion string) error { return nil } + // Unzip as a generic archive if the module unzip fails. + // This is useful for plugins that have vendor directories or other structures. + // This is also useful for wasm plugins. return c.unzipArchive(pName, pVersion) } @@ -278,32 +281,52 @@ func unzipFile(f *zipa.File, dest string) error { defer func() { _ = rc.Close() }() + // Split to discard the first part of the path when the archive is a Yaegi go plugin with vendoring. + // In this case the path starts with `[organization]-[project]-[release commit sha1]/`. pathParts := strings.SplitN(f.Name, "/", 2) - - var pp string + var fileName string if len(pathParts) < 2 { - pp = pathParts[0] + fileName = pathParts[0] } else { - pp = pathParts[1] + fileName = pathParts[1] } - p := filepath.Join(dest, pp) + // Validate and sanitize the file path. + cleanName := filepath.Clean(fileName) + if strings.Contains(cleanName, "..") { + return fmt.Errorf("invalid file path in archive: %s", f.Name) + } + + filePath := filepath.Join(dest, cleanName) + absFilePath, err := filepath.Abs(filePath) + if err != nil { + return fmt.Errorf("resolving file path: %w", err) + } + + absDest, err := filepath.Abs(dest) + if err != nil { + return fmt.Errorf("resolving destination directory: %w", err) + } + + if !strings.HasPrefix(absFilePath, absDest) { + return fmt.Errorf("file path escapes destination directory: %s", absFilePath) + } if f.FileInfo().IsDir() { - err = os.MkdirAll(p, f.Mode()) + err = os.MkdirAll(filePath, f.Mode()) if err != nil { - return fmt.Errorf("unable to create archive directory %s: %w", p, err) + return fmt.Errorf("unable to create archive directory %s: %w", filePath, err) } return nil } - err = os.MkdirAll(filepath.Dir(p), 0o750) + err = os.MkdirAll(filepath.Dir(filePath), 0o750) if err != nil { - return fmt.Errorf("unable to create archive directory %s for file %s: %w", filepath.Dir(p), p, err) + return fmt.Errorf("unable to create archive directory %s for file %s: %w", filepath.Dir(filePath), filePath, err) } - elt, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + elt, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { return err } diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go index af8aceeb5..f32953423 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go @@ -34,7 +34,7 @@ type TLSOptionSpec struct { // CipherSuites defines the list of supported cipher suites for TLS versions up to TLS 1.2. // More info: https://doc.traefik.io/traefik/v3.4/https/tls/#cipher-suites CipherSuites []string `json:"cipherSuites,omitempty"` - // CurvePreferences defines the preferred elliptic curves in a specific order. + // CurvePreferences defines the preferred elliptic curves. // More info: https://doc.traefik.io/traefik/v3.4/https/tls/#curve-preferences CurvePreferences []string `json:"curvePreferences,omitempty"` // ClientAuth defines the server's policy for TLS Client Authentication. diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index ea8ea6e48..16c6e3fa0 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -476,6 +476,13 @@ func buildListener(ctx context.Context, name string, config *static.EntryPoint) if listener == nil { listenConfig := newListenConfig(config) + + // TODO: Look into configuring keepAlive period through listenConfig instead of our custom tcpKeepAliveListener, to reactivate MultipathTCP? + // MultipathTCP is not supported on all platforms, and is notably unsupported in combination with TCP keep-alive. + if !strings.Contains(os.Getenv("GODEBUG"), "multipathtcp") { + listenConfig.SetMultipathTCP(false) + } + listener, err = listenConfig.Listen(ctx, "tcp", config.GetAddress()) if err != nil { return nil, fmt.Errorf("error opening listener: %w", err)