From 2d56be0ebb29f27849180c9967a97120b365e282 Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Mon, 7 Feb 2022 15:22:07 +0100 Subject: [PATCH 1/7] Fix Kubernetes TCP examples --- docs/content/middlewares/tcp/inflightconn.md | 2 +- docs/content/middlewares/tcp/overview.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/middlewares/tcp/inflightconn.md b/docs/content/middlewares/tcp/inflightconn.md index 73e9e0df0..036ca74e1 100644 --- a/docs/content/middlewares/tcp/inflightconn.md +++ b/docs/content/middlewares/tcp/inflightconn.md @@ -14,7 +14,7 @@ labels: ```yaml tab="Kubernetes" apiVersion: traefik.containo.us/v1alpha1 -kind: Middleware +kind: MiddlewareTCP metadata: name: test-inflightconn spec: diff --git a/docs/content/middlewares/tcp/overview.md b/docs/content/middlewares/tcp/overview.md index 1fd53a963..8fc5f4919 100644 --- a/docs/content/middlewares/tcp/overview.md +++ b/docs/content/middlewares/tcp/overview.md @@ -36,7 +36,7 @@ spec: --- apiVersion: traefik.containo.us/v1alpha1 -kind: Middleware +kind: MiddlewareTCP metadata: name: foo-ip-whitelist spec: @@ -47,7 +47,7 @@ spec: --- apiVersion: traefik.containo.us/v1alpha1 -kind: IngressRoute +kind: IngressRouteTCP metadata: name: ingressroute spec: From 4da33c2bc261b0691b2ede95a34716a12554a964 Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Wed, 9 Feb 2022 09:58:08 +0100 Subject: [PATCH 2/7] Fix metrics bucket key high cardinality --- docs/content/migration/v2.md | 8 +++ .../content/observability/metrics/overview.md | 55 ++++++++++++++----- pkg/middlewares/metrics/metrics.go | 19 ++++++- pkg/middlewares/metrics/metrics_test.go | 31 +++++++++++ 4 files changed, 96 insertions(+), 17 deletions(-) diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index 1793ddd4c..41329d7f4 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -438,3 +438,11 @@ To enable HTTP/3 on an EntryPoint, please check out the [HTTP/3 configuration](. In `v2.6`, the [Kubernetes Gateway API provider](../providers/kubernetes-gateway.md) now only supports the version [v1alpha2](https://gateway-api.sigs.k8s.io/v1alpha2/guides/getting-started/) of the specification and [route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces. Therefore, the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-gateway.md#definitions) definitions must be updated. + +## v2.6.0 to v2.6.1 + +In `v2.6.1`, the metrics system does not support any more custom HTTP method verbs to prevent potential metrics cardinality overhead. +In consequence, for metrics having the method label, +if the HTTP method verb of a request is not one defined in the set of common methods for [`HTTP/1.1`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) +or the [`PRI`](https://datatracker.ietf.org/doc/html/rfc7540#section-11.6) verb (for `HTTP/2`), +the value for the method label becomes `EXTENSION_METHOD`, instead of the request's one. diff --git a/docs/content/observability/metrics/overview.md b/docs/content/observability/metrics/overview.md index 13ef7aa79..0d1eae97a 100644 --- a/docs/content/observability/metrics/overview.md +++ b/docs/content/observability/metrics/overview.md @@ -61,7 +61,7 @@ traefik_config_last_reload_success The expiration date of certificates. -Available labels: `cn`, `sans`, `serial`. +[Labels](#labels): `cn`, `sans`, `serial`. ```dd tab="Datadog" tls.certs.notAfterTimestamp @@ -93,7 +93,7 @@ traefik_tls_certs_not_after The total count of HTTP requests received by an entrypoint. -Available labels: `code`, `method`, `protocol`, `entrypoint`. +[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`. ```dd tab="Datadog" entrypoint.request.total @@ -116,7 +116,7 @@ traefik_entrypoint_requests_total The total count of HTTPS requests received by an entrypoint. -Available labels: `tls_version`, `tls_cipher`, `entrypoint`. +[Labels](#labels): `tls_version`, `tls_cipher`, `entrypoint`. ```dd tab="Datadog" entrypoint.request.tls.total @@ -139,7 +139,7 @@ traefik_entrypoint_requests_tls_total Request processing duration histogram on an entrypoint. -Available labels: `code`, `method`, `protocol`, `entrypoint`. +[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`. ```dd tab="Datadog" entrypoint.request.duration @@ -162,7 +162,7 @@ traefik_entrypoint_request_duration_seconds The current count of open connections on an entrypoint. -Available labels: `method`, `protocol`, `entrypoint`. +[Labels](#labels): `method`, `protocol`, `entrypoint`. ```dd tab="Datadog" entrypoint.connections.open @@ -194,7 +194,7 @@ traefik_entrypoint_open_connections The total count of HTTP requests handled by a router. -Available labels: `code`, `method`, `protocol`, `router`, `service`. +[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`. ```dd tab="Datadog" router.request.total @@ -217,7 +217,7 @@ traefik_router_requests_total The total count of HTTPS requests handled by a router. -Available labels: `tls_version`, `tls_cipher`, `router`, `service`. +[Labels](#labels): `tls_version`, `tls_cipher`, `router`, `service`. ```dd tab="Datadog" router.request.tls.total @@ -240,7 +240,7 @@ traefik_router_requests_tls_total Request processing duration histogram on a router. -Available labels: `code`, `method`, `protocol`, `router`, `service`. +[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`. ```dd tab="Datadog" router.request.duration @@ -263,7 +263,7 @@ traefik_router_request_duration_seconds The current count of open connections on a router. -Available labels: `method`, `protocol`, `router`, `service`. +[Labels](#labels): `method`, `protocol`, `router`, `service`. ```dd tab="Datadog" router.connections.open @@ -297,7 +297,7 @@ traefik_router_open_connections The total count of HTTP requests processed on a service. -Available labels: `code`, `method`, `protocol`, `service`. +[Labels](#labels): `code`, `method`, `protocol`, `service`. ```dd tab="Datadog" service.request.total @@ -320,7 +320,7 @@ traefik_service_requests_total The total count of HTTPS requests processed on a service. -Available labels: `tls_version`, `tls_cipher`, `service`. +[Labels](#labels): `tls_version`, `tls_cipher`, `service`. ```dd tab="Datadog" router.service.tls.total @@ -343,7 +343,7 @@ traefik_service_requests_tls_total Request processing duration histogram on a service. -Available labels: `code`, `method`, `protocol`, `service`. +[Labels](#labels): `code`, `method`, `protocol`, `service`. ```dd tab="Datadog" service.request.duration @@ -366,7 +366,7 @@ traefik_service_request_duration_seconds The current count of open connections on a service. -Available labels: `method`, `protocol`, `service`. +[Labels](#labels): `method`, `protocol`, `service`. ```dd tab="Datadog" service.connections.open @@ -389,7 +389,7 @@ traefik_service_open_connections The count of requests retries on a service. -Available labels: `service`. +[Labels](#labels): `service`. ```dd tab="Datadog" service.retries.total @@ -412,7 +412,7 @@ traefik_service_retries_total Current service's server status, described by a gauge with a value of 0 for a down server or a value of 1 for an up server. -Available labels: `service`, `url`. +[Labels](#labels): `service`, `url`. ```dd tab="Datadog" service.server.up @@ -430,3 +430,28 @@ traefik_service_server_up # Default prefix: "traefik" {prefix}.service.server.up ``` + +## Labels + +Here is a comprehensive list of labels that are provided by the metrics: + +| Label | Description | example | +|---------------|---------------------------------------|----------------------------| +| `cn` | Certificate Common Name | "example.com" | +| `code` | Request code | "200" | +| `entrypoint` | Entrypoint that handled the request | "example_entrypoint" | +| `method` | Request Method | "GET" | +| `protocol` | Request protocol | "http" | +| `router` | Router that handled the request | "example_router" | +| `sans` | Certificate Subject Alternative NameS | "example.com" | +| `serial` | Certificate Serial Number | "123..." | +| `service` | Service that handled the request | "example_service@provider" | +| `tls_cipher` | TLS cipher used for the request | "TLS_FALLBACK_SCSV" | +| `tls_version` | TLS version used for the request | "1.0" | +| `url` | Service server url | "http://example.com" | + +!!! info "`method` label value" + + If the HTTP method verb on a request is not one defined in the set of common methods for [`HTTP/1.1`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) + or the [`PRI`](https://datatracker.ietf.org/doc/html/rfc7540#section-11.6) verb (for `HTTP/2`), + then the value for the method label becomes `EXTENSION_METHOD`. diff --git a/pkg/middlewares/metrics/metrics.go b/pkg/middlewares/metrics/metrics.go index 1f216393b..a491401cb 100644 --- a/pkg/middlewares/metrics/metrics.go +++ b/pkg/middlewares/metrics/metrics.go @@ -159,12 +159,27 @@ func containsHeader(req *http.Request, name, value string) bool { return false } +// getMethod returns the request's method. +// It checks whether the method is a valid UTF-8 string. +// To restrict the (potentially infinite) number of accepted values for the method, +// and avoid unbounded memory issues, +// values that are not part of the set of HTTP verbs are replaced with EXTENSION_METHOD. +// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods +// https://datatracker.ietf.org/doc/html/rfc2616/#section-5.1.1. func getMethod(r *http.Request) string { if !utf8.ValidString(r.Method) { - log.Warnf("Invalid HTTP method encoding: %s", r.Method) + log.WithoutContext().Warnf("Invalid HTTP method encoding: %s", r.Method) return "NON_UTF8_HTTP_METHOD" } - return r.Method + + switch r.Method { + case "HEAD", "GET", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", // https://datatracker.ietf.org/doc/html/rfc7231#section-4 + "PATCH", // https://datatracker.ietf.org/doc/html/rfc5789#section-2 + "PRI": // https://datatracker.ietf.org/doc/html/rfc7540#section-11.6 + return r.Method + default: + return "EXTENSION_METHOD" + } } type retryMetrics interface { diff --git a/pkg/middlewares/metrics/metrics_test.go b/pkg/middlewares/metrics/metrics_test.go index 596ac6abe..9390e49f5 100644 --- a/pkg/middlewares/metrics/metrics_test.go +++ b/pkg/middlewares/metrics/metrics_test.go @@ -4,6 +4,7 @@ import ( "net/http" "net/http/httptest" "reflect" + "strings" "testing" "github.com/go-kit/kit/metrics" @@ -98,3 +99,33 @@ func TestCloseNotifier(t *testing.T) { }) } } + +func Test_getMethod(t *testing.T) { + testCases := []struct { + method string + expected string + }{ + { + method: http.MethodGet, + expected: http.MethodGet, + }, + { + method: strings.ToLower(http.MethodGet), + expected: "EXTENSION_METHOD", + }, + { + method: "THIS_IS_NOT_A_VALID_METHOD", + expected: "EXTENSION_METHOD", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.method, func(t *testing.T) { + t.Parallel() + + request := httptest.NewRequest(test.method, "http://example.com", nil) + assert.Equal(t, test.expected, getMethod(request)) + }) + } +} From 0c83ee736ca4aa93bba2d4cce4c00fd247785915 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Thu, 10 Feb 2022 10:42:07 +0100 Subject: [PATCH 3/7] Apply the same approach as the rules system on the TLS configuration choice Co-authored-by: Julien Salleyron --- pkg/server/router/tcp/router.go | 37 +++++++- pkg/server/router/tcp/router_test.go | 133 ++++++++++++++++++++------- 2 files changed, 132 insertions(+), 38 deletions(-) diff --git a/pkg/server/router/tcp/router.go b/pkg/server/router/tcp/router.go index abe31d180..277080835 100644 --- a/pkg/server/router/tcp/router.go +++ b/pkg/server/router/tcp/router.go @@ -177,8 +177,8 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string // Domain Fronting if !strings.EqualFold(host, serverName) { - tlsOptionSNI := findTLSOptionName(tlsOptionsForHost, serverName) - tlsOptionHeader := findTLSOptionName(tlsOptionsForHost, host) + tlsOptionHeader := findTLSOptionName(tlsOptionsForHost, host, true) + tlsOptionSNI := findTLSOptionName(tlsOptionsForHost, serverName, false) if tlsOptionHeader != tlsOptionSNI { log.WithoutContext(). @@ -322,16 +322,43 @@ func (m *Manager) buildTCPHandler(ctx context.Context, router *runtime.TCPRouter return tcp.NewChain().Extend(*mHandler).Then(sHandler) } -func findTLSOptionName(tlsOptionsForHost map[string]string, host string) string { +func findTLSOptionName(tlsOptionsForHost map[string]string, host string, fqdn bool) string { + name := findTLSOptName(tlsOptionsForHost, host, fqdn) + if name != "" { + return name + } + + name = findTLSOptName(tlsOptionsForHost, strings.ToLower(host), fqdn) + if name != "" { + return name + } + + return traefiktls.DefaultTLSConfigName +} + +func findTLSOptName(tlsOptionsForHost map[string]string, host string, fqdn bool) string { tlsOptions, ok := tlsOptionsForHost[host] if ok { return tlsOptions } - tlsOptions, ok = tlsOptionsForHost[strings.ToLower(host)] + if !fqdn { + return "" + } + + if last := len(host) - 1; last >= 0 && host[last] == '.' { + tlsOptions, ok = tlsOptionsForHost[host[:last]] + if ok { + return tlsOptions + } + + return "" + } + + tlsOptions, ok = tlsOptionsForHost[host+"."] if ok { return tlsOptions } - return traefiktls.DefaultTLSConfigName + return "" } diff --git a/pkg/server/router/tcp/router_test.go b/pkg/server/router/tcp/router_test.go index 156721aa6..cdf7c3bbc 100644 --- a/pkg/server/router/tcp/router_test.go +++ b/pkg/server/router/tcp/router_test.go @@ -59,7 +59,6 @@ func TestRuntimeConfiguration(t *testing.T) { }, "bar": { TCPRouter: &dynamic.TCPRouter{ - EntryPoints: []string{"web"}, Service: "foo-service", Rule: "HostSNI(`foo.bar`)", @@ -136,7 +135,6 @@ func TestRuntimeConfiguration(t *testing.T) { }, "bar": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, Service: "foo-service", Rule: "Host(`bar.foo`) && PathPrefix(`/path`)", @@ -240,7 +238,6 @@ func TestRuntimeConfiguration(t *testing.T) { }, "bar": { TCPRouter: &dynamic.TCPRouter{ - EntryPoints: []string{"web"}, Service: "foo-service", Rule: "HostSNI(`foo.bar`)", @@ -340,9 +337,26 @@ func TestRuntimeConfiguration(t *testing.T) { } func TestDomainFronting(t *testing.T) { + tlsOptionsBase := map[string]traefiktls.Options{ + "default": { + MinVersion: "VersionTLS10", + }, + "host1@file": { + MinVersion: "VersionTLS12", + }, + "host1@crd": { + MinVersion: "VersionTLS12", + }, + } + + entryPoints := []string{"web"} + tests := []struct { desc string routers map[string]*runtime.RouterInfo + tlsOptions map[string]traefiktls.Options + host string + ServerName string expectedStatus int }{ { @@ -350,7 +364,7 @@ func TestDomainFronting(t *testing.T) { routers: map[string]*runtime.RouterInfo{ "router-1@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host1.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -359,12 +373,15 @@ func TestDomainFronting(t *testing.T) { }, "router-2@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host2.local`)", TLS: &dynamic.RouterTLSConfig{}, }, }, }, + tlsOptions: tlsOptionsBase, + host: "host1.local", + ServerName: "host2.local", expectedStatus: http.StatusMisdirectedRequest, }, { @@ -372,7 +389,7 @@ func TestDomainFronting(t *testing.T) { routers: map[string]*runtime.RouterInfo{ "router-1@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host1.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -381,7 +398,7 @@ func TestDomainFronting(t *testing.T) { }, "router-2@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host2.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -389,6 +406,9 @@ func TestDomainFronting(t *testing.T) { }, }, }, + tlsOptions: tlsOptionsBase, + host: "host1.local", + ServerName: "host2.local", expectedStatus: http.StatusOK, }, { @@ -396,7 +416,7 @@ func TestDomainFronting(t *testing.T) { routers: map[string]*runtime.RouterInfo{ "router-1@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host1.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -405,7 +425,7 @@ func TestDomainFronting(t *testing.T) { }, "router-2@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host1.local`) && PathPrefix(`/foo`)", TLS: &dynamic.RouterTLSConfig{ Options: "default", @@ -414,7 +434,7 @@ func TestDomainFronting(t *testing.T) { }, "router-3@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host2.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -422,6 +442,9 @@ func TestDomainFronting(t *testing.T) { }, }, }, + tlsOptions: tlsOptionsBase, + host: "host1.local", + ServerName: "host2.local", expectedStatus: http.StatusMisdirectedRequest, }, { @@ -429,7 +452,7 @@ func TestDomainFronting(t *testing.T) { routers: map[string]*runtime.RouterInfo{ "router-1@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host1.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -438,7 +461,7 @@ func TestDomainFronting(t *testing.T) { }, "router-2@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host1.local`) && PathPrefix(`/bar`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -447,7 +470,7 @@ func TestDomainFronting(t *testing.T) { }, "router-3@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host2.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -455,6 +478,9 @@ func TestDomainFronting(t *testing.T) { }, }, }, + tlsOptions: tlsOptionsBase, + host: "host1.local", + ServerName: "host2.local", expectedStatus: http.StatusOK, }, { @@ -462,7 +488,7 @@ func TestDomainFronting(t *testing.T) { routers: map[string]*runtime.RouterInfo{ "router-1@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host1.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -471,7 +497,7 @@ func TestDomainFronting(t *testing.T) { }, "router-2@crd": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host2.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1", @@ -479,6 +505,9 @@ func TestDomainFronting(t *testing.T) { }, }, }, + tlsOptions: tlsOptionsBase, + host: "host1.local", + ServerName: "host2.local", expectedStatus: http.StatusMisdirectedRequest, }, { @@ -486,7 +515,7 @@ func TestDomainFronting(t *testing.T) { routers: map[string]*runtime.RouterInfo{ "router-1@file": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host1.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1@crd", @@ -495,7 +524,7 @@ func TestDomainFronting(t *testing.T) { }, "router-2@crd": { Router: &dynamic.Router{ - EntryPoints: []string{"web"}, + EntryPoints: entryPoints, Rule: "Host(`host2.local`)", TLS: &dynamic.RouterTLSConfig{ Options: "host1@crd", @@ -503,25 +532,63 @@ func TestDomainFronting(t *testing.T) { }, }, }, + tlsOptions: tlsOptionsBase, + host: "host1.local", + ServerName: "host2.local", expectedStatus: http.StatusOK, }, + { + desc: "Request is misdirected when server name is empty and the host name is an FQDN, but router's rule is not", + routers: map[string]*runtime.RouterInfo{ + "router-1@file": { + Router: &dynamic.Router{ + EntryPoints: entryPoints, + Rule: "Host(`host1.local`)", + TLS: &dynamic.RouterTLSConfig{ + Options: "host1@file", + }, + }, + }, + }, + tlsOptions: map[string]traefiktls.Options{ + "default": { + MinVersion: "VersionTLS13", + }, + "host1@file": { + MinVersion: "VersionTLS12", + }, + }, + host: "host1.local.", + expectedStatus: http.StatusMisdirectedRequest, + }, + { + desc: "Request is misdirected when server name is empty and the host name is not FQDN, but router's rule is", + routers: map[string]*runtime.RouterInfo{ + "router-1@file": { + Router: &dynamic.Router{ + EntryPoints: entryPoints, + Rule: "Host(`host1.local.`)", + TLS: &dynamic.RouterTLSConfig{ + Options: "host1@file", + }, + }, + }, + }, + tlsOptions: map[string]traefiktls.Options{ + "default": { + MinVersion: "VersionTLS13", + }, + "host1@file": { + MinVersion: "VersionTLS12", + }, + }, + host: "host1.local", + expectedStatus: http.StatusMisdirectedRequest, + }, } for _, test := range tests { t.Run(test.desc, func(t *testing.T) { - entryPoints := []string{"web"} - tlsOptions := map[string]traefiktls.Options{ - "default": { - MinVersion: "VersionTLS10", - }, - "host1@file": { - MinVersion: "VersionTLS12", - }, - "host1@crd": { - MinVersion: "VersionTLS12", - }, - } - conf := &runtime.Configuration{ Routers: test.routers, } @@ -529,7 +596,7 @@ func TestDomainFronting(t *testing.T) { serviceManager := tcp.NewManager(conf) tlsManager := traefiktls.NewManager() - tlsManager.UpdateConfigs(context.Background(), map[string]traefiktls.Store{}, tlsOptions, []*traefiktls.CertAndStores{}) + tlsManager.UpdateConfigs(context.Background(), map[string]traefiktls.Store{}, test.tlsOptions, []*traefiktls.CertAndStores{}) httpsHandler := map[string]http.Handler{ "web": http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {}), @@ -545,9 +612,9 @@ func TestDomainFronting(t *testing.T) { require.True(t, ok) req := httptest.NewRequest(http.MethodGet, "/", nil) - req.Host = "host1.local" + req.Host = test.host req.TLS = &tls.ConnectionState{ - ServerName: "host2.local", + ServerName: test.ServerName, } rw := httptest.NewRecorder() From 6bcfba43c879df414ba6476d12d3b46f59d30730 Mon Sep 17 00:00:00 2001 From: luckielordie Date: Thu, 10 Feb 2022 15:00:09 +0000 Subject: [PATCH 4/7] Rename Datadog span tags --- docs/content/migration/v2.md | 6 +++ pkg/middlewares/tracing/forwarder.go | 4 +- pkg/middlewares/tracing/forwarder_test.go | 48 +++++++++++------------ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index 41329d7f4..95b3b636a 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -441,8 +441,14 @@ Therefore, the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#r ## v2.6.0 to v2.6.1 +### Metrics + In `v2.6.1`, the metrics system does not support any more custom HTTP method verbs to prevent potential metrics cardinality overhead. In consequence, for metrics having the method label, if the HTTP method verb of a request is not one defined in the set of common methods for [`HTTP/1.1`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) or the [`PRI`](https://datatracker.ietf.org/doc/html/rfc7540#section-11.6) verb (for `HTTP/2`), the value for the method label becomes `EXTENSION_METHOD`, instead of the request's one. + +### Tracing + +In `v2.6.1`, the Datadog tags added to a span changed from `service.name` to `traefik.service.name` and from `router.name` to `traefik.router.name`. diff --git a/pkg/middlewares/tracing/forwarder.go b/pkg/middlewares/tracing/forwarder.go index c65d322e1..51c313f4c 100644 --- a/pkg/middlewares/tracing/forwarder.go +++ b/pkg/middlewares/tracing/forwarder.go @@ -43,8 +43,8 @@ func (f *forwarderMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Reques span, req, finish := tr.StartSpanf(req, ext.SpanKindRPCClientEnum, "forward", opParts, "/") defer finish() - span.SetTag("service.name", f.service) - span.SetTag("router.name", f.router) + span.SetTag("traefik.service.name", f.service) + span.SetTag("traefik.router.name", f.router) ext.HTTPMethod.Set(span, req.Method) ext.HTTPUrl.Set(span, req.URL.String()) span.SetTag("http.host", req.Host) diff --git a/pkg/middlewares/tracing/forwarder_test.go b/pkg/middlewares/tracing/forwarder_test.go index d8b1cbb99..1253412d3 100644 --- a/pkg/middlewares/tracing/forwarder_test.go +++ b/pkg/middlewares/tracing/forwarder_test.go @@ -36,12 +36,12 @@ func TestNewForwarder(t *testing.T) { router: "some-service.domain.tld", expected: expected{ Tags: map[string]interface{}{ - "http.host": "www.test.com", - "http.method": "GET", - "http.url": "http://www.test.com/toto", - "service.name": "some-service.domain.tld", - "router.name": "some-service.domain.tld", - "span.kind": ext.SpanKindRPCClientEnum, + "http.host": "www.test.com", + "http.method": "GET", + "http.url": "http://www.test.com/toto", + "traefik.service.name": "some-service.domain.tld", + "traefik.router.name": "some-service.domain.tld", + "span.kind": ext.SpanKindRPCClientEnum, }, OperationName: "forward some-service.domain.tld/some-service.domain.tld", }, @@ -56,12 +56,12 @@ func TestNewForwarder(t *testing.T) { router: "some-service-100.slug.namespace.environment.domain.tld", expected: expected{ Tags: map[string]interface{}{ - "http.host": "www.test.com", - "http.method": "GET", - "http.url": "http://www.test.com/toto", - "service.name": "some-service-100.slug.namespace.environment.domain.tld", - "router.name": "some-service-100.slug.namespace.environment.domain.tld", - "span.kind": ext.SpanKindRPCClientEnum, + "http.host": "www.test.com", + "http.method": "GET", + "http.url": "http://www.test.com/toto", + "traefik.service.name": "some-service-100.slug.namespace.environment.domain.tld", + "traefik.router.name": "some-service-100.slug.namespace.environment.domain.tld", + "span.kind": ext.SpanKindRPCClientEnum, }, OperationName: "forward some-service-100.slug.namespace.enviro.../some-service-100.slug.namespace.enviro.../bc4a0d48", }, @@ -76,12 +76,12 @@ func TestNewForwarder(t *testing.T) { router: "some-service1.namespace.environment.domain.tld", expected: expected{ Tags: map[string]interface{}{ - "http.host": "www.test.com", - "http.method": "GET", - "http.url": "http://www.test.com/toto", - "service.name": "some-service1.namespace.environment.domain.tld", - "router.name": "some-service1.namespace.environment.domain.tld", - "span.kind": ext.SpanKindRPCClientEnum, + "http.host": "www.test.com", + "http.method": "GET", + "http.url": "http://www.test.com/toto", + "traefik.service.name": "some-service1.namespace.environment.domain.tld", + "traefik.router.name": "some-service1.namespace.environment.domain.tld", + "span.kind": ext.SpanKindRPCClientEnum, }, OperationName: "forward some-service1.namespace.environment.domain.tld/some-service1.namespace.environment.domain.tld", }, @@ -96,12 +96,12 @@ func TestNewForwarder(t *testing.T) { router: "some-service1.backend.namespace.environment.domain.tld", expected: expected{ Tags: map[string]interface{}{ - "http.host": "www.test.com", - "http.method": "GET", - "http.url": "http://www.test.com/toto", - "service.name": "some-service1.frontend.namespace.environment.domain.tld", - "router.name": "some-service1.backend.namespace.environment.domain.tld", - "span.kind": ext.SpanKindRPCClientEnum, + "http.host": "www.test.com", + "http.method": "GET", + "http.url": "http://www.test.com/toto", + "traefik.service.name": "some-service1.frontend.namespace.environment.domain.tld", + "traefik.router.name": "some-service1.backend.namespace.environment.domain.tld", + "span.kind": ext.SpanKindRPCClientEnum, }, OperationName: "forward some-service1.frontend.namespace.envir.../some-service1.backend.namespace.enviro.../fa49dd23", }, From e97aa6515b45c61e5ea7580f8f12640ffcc0ed87 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 14 Feb 2022 14:08:07 +0100 Subject: [PATCH 5/7] Update test certificates --- integration/fixtures/https/rootcas/https.toml | 28 +++++--- integration/fixtures/https/rootcas/local.crt | 28 +++++--- .../server_entrypoint_tcp_http3_test.go | 69 ++++++++++++------- pkg/tls/tlsmanager_test.go | 67 +++++++++++------- 4 files changed, 121 insertions(+), 71 deletions(-) diff --git a/integration/fixtures/https/rootcas/https.toml b/integration/fixtures/https/rootcas/https.toml index 2525c7473..37e450fc9 100644 --- a/integration/fixtures/https/rootcas/https.toml +++ b/integration/fixtures/https/rootcas/https.toml @@ -9,18 +9,24 @@ # Use certificate in net/internal/testcert.go rootCAs = [ """ -----BEGIN CERTIFICATE----- -MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS +MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw -MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB -iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4 -iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul -rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO -BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw -AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA -AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9 -tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs -h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM -fblo6RBxUQ== +MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r +bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U +aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P +YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk +POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu +h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE +AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv +bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI +5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv +cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2 ++tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B +grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK +5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/ +WkBKOclmOV2xlTVuPw== -----END CERTIFICATE----- """] diff --git a/integration/fixtures/https/rootcas/local.crt b/integration/fixtures/https/rootcas/local.crt index 07457e03e..1b683072e 100644 --- a/integration/fixtures/https/rootcas/local.crt +++ b/integration/fixtures/https/rootcas/local.crt @@ -1,14 +1,20 @@ -----BEGIN CERTIFICATE----- -MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS +MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw -MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB -iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4 -iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul -rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO -BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw -AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA -AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9 -tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs -h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM -fblo6RBxUQ== +MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r +bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U +aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P +YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk +POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu +h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE +AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv +bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI +5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv +cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2 ++tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B +grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK +5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/ +WkBKOclmOV2xlTVuPw== -----END CERTIFICATE----- diff --git a/pkg/server/server_entrypoint_tcp_http3_test.go b/pkg/server/server_entrypoint_tcp_http3_test.go index 480bdb713..bdd44e0cb 100644 --- a/pkg/server/server_entrypoint_tcp_http3_test.go +++ b/pkg/server/server_entrypoint_tcp_http3_test.go @@ -17,38 +17,57 @@ import ( // LocalhostCert is a PEM-encoded TLS cert with SAN IPs // "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT. // generated from src/crypto/tls: -// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h +// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h var ( localhostCert = traefiktls.FileOrContent(`-----BEGIN CERTIFICATE----- -MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS +MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw -MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB -iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4 -iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul -rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO -BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw -AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA -AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9 -tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs -h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM -fblo6RBxUQ== +MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r +bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U +aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P +YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk +POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu +h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE +AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv +bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI +5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv +cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2 ++tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B +grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK +5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/ +WkBKOclmOV2xlTVuPw== -----END CERTIFICATE-----`) // LocalhostKey is the private key for localhostCert. localhostKey = traefiktls.FileOrContent(`-----BEGIN RSA PRIVATE KEY----- -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 +ZboOWVe3icTy64BT3OQhmg== -----END RSA PRIVATE KEY-----`) ) diff --git a/pkg/tls/tlsmanager_test.go b/pkg/tls/tlsmanager_test.go index 06b364ea1..63f13fe17 100644 --- a/pkg/tls/tlsmanager_test.go +++ b/pkg/tls/tlsmanager_test.go @@ -17,35 +17,54 @@ import ( // go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h var ( localhostCert = FileOrContent(`-----BEGIN CERTIFICATE----- -MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS +MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw -MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB -iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4 -iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul -rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO -BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw -AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA -AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9 -tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs -h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM -fblo6RBxUQ== +MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r +bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U +aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P +YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk +POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu +h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE +AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv +bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI +5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv +cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2 ++tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B +grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK +5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/ +WkBKOclmOV2xlTVuPw== -----END CERTIFICATE-----`) // LocalhostKey is the private key for localhostCert. localhostKey = FileOrContent(`-----BEGIN RSA PRIVATE KEY----- -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 +ZboOWVe3icTy64BT3OQhmg== -----END RSA PRIVATE KEY-----`) ) From d9fbb5e25cb928f9cb5154e0909a318b84e854e9 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 14 Feb 2022 17:18:08 +0100 Subject: [PATCH 6/7] Use CNAME for SNI check on host header Co-authored-by: Julien Salleyron --- cmd/traefik/traefik.go | 2 +- pkg/middlewares/snicheck/snicheck.go | 107 ++++++++++++++++++ pkg/middlewares/snicheck/snicheck_test.go | 60 ++++++++++ pkg/server/middleware/chainbuilder.go | 5 +- pkg/server/router/tcp/router.go | 77 +------------ pkg/server/server_entrypoint_tcp.go | 26 +++-- .../server_entrypoint_tcp_http3_test.go | 2 +- pkg/server/server_entrypoint_tcp_test.go | 6 +- 8 files changed, 192 insertions(+), 93 deletions(-) create mode 100644 pkg/middlewares/snicheck/snicheck.go create mode 100644 pkg/middlewares/snicheck/snicheck_test.go diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 91a6d4d74..b0db4aabc 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -191,7 +191,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err // Entrypoints - serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints) + serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints, staticConfiguration.HostResolver) if err != nil { return nil, err } diff --git a/pkg/middlewares/snicheck/snicheck.go b/pkg/middlewares/snicheck/snicheck.go new file mode 100644 index 000000000..e18b605cb --- /dev/null +++ b/pkg/middlewares/snicheck/snicheck.go @@ -0,0 +1,107 @@ +package snicheck + +import ( + "net" + "net/http" + "strings" + + "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" + traefiktls "github.com/traefik/traefik/v2/pkg/tls" +) + +// SNICheck is an HTTP handler that checks whether the TLS configuration for the server name is the same as for the host header. +type SNICheck struct { + next http.Handler + tlsOptionsForHost map[string]string +} + +// New creates a new SNICheck. +func New(tlsOptionsForHost map[string]string, next http.Handler) *SNICheck { + return &SNICheck{next: next, tlsOptionsForHost: tlsOptionsForHost} +} + +func (s SNICheck) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + if req.TLS == nil { + s.next.ServeHTTP(rw, req) + return + } + + host := getHost(req) + serverName := strings.TrimSpace(req.TLS.ServerName) + + // Domain Fronting + if !strings.EqualFold(host, serverName) { + tlsOptionHeader := findTLSOptionName(s.tlsOptionsForHost, host, true) + tlsOptionSNI := findTLSOptionName(s.tlsOptionsForHost, serverName, false) + + if tlsOptionHeader != tlsOptionSNI { + log.WithoutContext(). + WithField("host", host). + WithField("req.Host", req.Host). + WithField("req.TLS.ServerName", req.TLS.ServerName). + Debugf("TLS options difference: SNI:%s, Header:%s", tlsOptionSNI, tlsOptionHeader) + http.Error(rw, http.StatusText(http.StatusMisdirectedRequest), http.StatusMisdirectedRequest) + return + } + } + + s.next.ServeHTTP(rw, req) +} + +func getHost(req *http.Request) string { + h := requestdecorator.GetCNAMEFlatten(req.Context()) + if h != "" { + return h + } + + h = requestdecorator.GetCanonizedHost(req.Context()) + if h != "" { + return h + } + + host, _, err := net.SplitHostPort(req.Host) + if err != nil { + host = req.Host + } + + return strings.TrimSpace(host) +} + +func findTLSOptionName(tlsOptionsForHost map[string]string, host string, fqdn bool) string { + name := findTLSOptName(tlsOptionsForHost, host, fqdn) + if name != "" { + return name + } + + name = findTLSOptName(tlsOptionsForHost, strings.ToLower(host), fqdn) + if name != "" { + return name + } + + return traefiktls.DefaultTLSConfigName +} + +func findTLSOptName(tlsOptionsForHost map[string]string, host string, fqdn bool) string { + if tlsOptions, ok := tlsOptionsForHost[host]; ok { + return tlsOptions + } + + if !fqdn { + return "" + } + + if last := len(host) - 1; last >= 0 && host[last] == '.' { + if tlsOptions, ok := tlsOptionsForHost[host[:last]]; ok { + return tlsOptions + } + + return "" + } + + if tlsOptions, ok := tlsOptionsForHost[host+"."]; ok { + return tlsOptions + } + + return "" +} diff --git a/pkg/middlewares/snicheck/snicheck_test.go b/pkg/middlewares/snicheck/snicheck_test.go new file mode 100644 index 000000000..a9d57bdf6 --- /dev/null +++ b/pkg/middlewares/snicheck/snicheck_test.go @@ -0,0 +1,60 @@ +package snicheck + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSNICheck_ServeHTTP(t *testing.T) { + testCases := []struct { + desc string + tlsOptionsForHost map[string]string + host string + expected int + }{ + { + desc: "no TLS options", + expected: http.StatusOK, + }, + { + desc: "with TLS options", + tlsOptionsForHost: map[string]string{ + "example.com": "foo", + }, + expected: http.StatusOK, + }, + { + desc: "server name and host doesn't have the same TLS configuration", + tlsOptionsForHost: map[string]string{ + "example.com": "foo", + }, + host: "example.com", + expected: http.StatusMisdirectedRequest, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}) + + sniCheck := New(test.tlsOptionsForHost, next) + + req := httptest.NewRequest(http.MethodGet, "https://localhost", nil) + if test.host != "" { + req.Host = test.host + } + + recorder := httptest.NewRecorder() + + sniCheck.ServeHTTP(recorder, req) + + assert.Equal(t, test.expected, recorder.Code) + }) + } +} diff --git a/pkg/server/middleware/chainbuilder.go b/pkg/server/middleware/chainbuilder.go index 1f7a70ef3..418bdfd14 100644 --- a/pkg/server/middleware/chainbuilder.go +++ b/pkg/server/middleware/chainbuilder.go @@ -9,7 +9,6 @@ import ( "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" metricsmiddleware "github.com/traefik/traefik/v2/pkg/middlewares/metrics" - "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" mTracing "github.com/traefik/traefik/v2/pkg/middlewares/tracing" "github.com/traefik/traefik/v2/pkg/tracing" "github.com/traefik/traefik/v2/pkg/tracing/jaeger" @@ -20,7 +19,6 @@ type ChainBuilder struct { metricsRegistry metrics.Registry accessLoggerMiddleware *accesslog.Handler tracer *tracing.Tracing - requestDecorator *requestdecorator.RequestDecorator } // NewChainBuilder Creates a new ChainBuilder. @@ -29,7 +27,6 @@ func NewChainBuilder(staticConfiguration static.Configuration, metricsRegistry m metricsRegistry: metricsRegistry, accessLoggerMiddleware: accessLoggerMiddleware, tracer: setupTracing(staticConfiguration.Tracing), - requestDecorator: requestdecorator.New(staticConfiguration.HostResolver), } } @@ -49,7 +46,7 @@ func (c *ChainBuilder) Build(ctx context.Context, entryPointName string) alice.C chain = chain.Append(metricsmiddleware.WrapEntryPointHandler(ctx, c.metricsRegistry, entryPointName)) } - return chain.Append(requestdecorator.WrapHandler(c.requestDecorator)) + return chain } // Close accessLogger and tracer. diff --git a/pkg/server/router/tcp/router.go b/pkg/server/router/tcp/router.go index 277080835..0a97a10b3 100644 --- a/pkg/server/router/tcp/router.go +++ b/pkg/server/router/tcp/router.go @@ -5,12 +5,11 @@ import ( "crypto/tls" "errors" "fmt" - "net" "net/http" - "strings" "github.com/traefik/traefik/v2/pkg/config/runtime" "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/middlewares/snicheck" "github.com/traefik/traefik/v2/pkg/rules" "github.com/traefik/traefik/v2/pkg/server/provider" tcpservice "github.com/traefik/traefik/v2/pkg/server/service/tcp" @@ -161,38 +160,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string } } - sniCheck := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - if req.TLS == nil { - handlerHTTPS.ServeHTTP(rw, req) - return - } - - host, _, err := net.SplitHostPort(req.Host) - if err != nil { - host = req.Host - } - - host = strings.TrimSpace(host) - serverName := strings.TrimSpace(req.TLS.ServerName) - - // Domain Fronting - if !strings.EqualFold(host, serverName) { - tlsOptionHeader := findTLSOptionName(tlsOptionsForHost, host, true) - tlsOptionSNI := findTLSOptionName(tlsOptionsForHost, serverName, false) - - if tlsOptionHeader != tlsOptionSNI { - log.WithoutContext(). - WithField("host", host). - WithField("req.Host", req.Host). - WithField("req.TLS.ServerName", req.TLS.ServerName). - Debugf("TLS options difference: SNI=%s, Header:%s", tlsOptionSNI, tlsOptionHeader) - http.Error(rw, http.StatusText(http.StatusMisdirectedRequest), http.StatusMisdirectedRequest) - return - } - } - - handlerHTTPS.ServeHTTP(rw, req) - }) + sniCheck := snicheck.New(tlsOptionsForHost, handlerHTTPS) router.HTTPSHandler(sniCheck, defaultTLSConf) @@ -321,44 +289,3 @@ func (m *Manager) buildTCPHandler(ctx context.Context, router *runtime.TCPRouter return tcp.NewChain().Extend(*mHandler).Then(sHandler) } - -func findTLSOptionName(tlsOptionsForHost map[string]string, host string, fqdn bool) string { - name := findTLSOptName(tlsOptionsForHost, host, fqdn) - if name != "" { - return name - } - - name = findTLSOptName(tlsOptionsForHost, strings.ToLower(host), fqdn) - if name != "" { - return name - } - - return traefiktls.DefaultTLSConfigName -} - -func findTLSOptName(tlsOptionsForHost map[string]string, host string, fqdn bool) string { - tlsOptions, ok := tlsOptionsForHost[host] - if ok { - return tlsOptions - } - - if !fqdn { - return "" - } - - if last := len(host) - 1; last >= 0 && host[last] == '.' { - tlsOptions, ok = tlsOptionsForHost[host[:last]] - if ok { - return tlsOptions - } - - return "" - } - - tlsOptions, ok = tlsOptionsForHost[host+"."] - if ok { - return tlsOptions - } - - return "" -} diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index bf62b47eb..395720555 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -11,6 +11,7 @@ import ( "syscall" "time" + "github.com/containous/alice" "github.com/pires/go-proxyproto" "github.com/sirupsen/logrus" "github.com/traefik/traefik/v2/pkg/config/static" @@ -18,9 +19,11 @@ import ( "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/forwardedheaders" + "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/server/router" "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v2/pkg/types" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) @@ -60,7 +63,7 @@ func (h *httpForwarder) Accept() (net.Conn, error) { type TCPEntryPoints map[string]*TCPEntryPoint // NewTCPEntryPoints creates a new TCPEntryPoints. -func NewTCPEntryPoints(entryPointsConfig static.EntryPoints) (TCPEntryPoints, error) { +func NewTCPEntryPoints(entryPointsConfig static.EntryPoints, hostResolverConfig *types.HostResolverConfig) (TCPEntryPoints, error) { serverEntryPointsTCP := make(TCPEntryPoints) for entryPointName, config := range entryPointsConfig { protocol, err := config.GetProtocol() @@ -74,7 +77,7 @@ func NewTCPEntryPoints(entryPointsConfig static.EntryPoints) (TCPEntryPoints, er ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName)) - serverEntryPointsTCP[entryPointName], err = NewTCPEntryPoint(ctx, config) + serverEntryPointsTCP[entryPointName], err = NewTCPEntryPoint(ctx, config, hostResolverConfig) if err != nil { return nil, fmt.Errorf("error while building entryPoint %s: %w", entryPointName, err) } @@ -130,7 +133,7 @@ type TCPEntryPoint struct { } // NewTCPEntryPoint creates a new TCPEntryPoint. -func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint) (*TCPEntryPoint, error) { +func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint, hostResolverConfig *types.HostResolverConfig) (*TCPEntryPoint, error) { tracker := newConnectionTracker() listener, err := buildListener(ctx, configuration) @@ -140,14 +143,16 @@ func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint) (*T rt := &tcp.Router{} - httpServer, err := createHTTPServer(ctx, listener, configuration, true) + reqDecorator := requestdecorator.New(hostResolverConfig) + + httpServer, err := createHTTPServer(ctx, listener, configuration, true, reqDecorator) if err != nil { return nil, fmt.Errorf("error preparing httpServer: %w", err) } rt.HTTPForwarder(httpServer.Forwarder) - httpsServer, err := createHTTPServer(ctx, listener, configuration, false) + httpsServer, err := createHTTPServer(ctx, listener, configuration, false, reqDecorator) if err != nil { return nil, fmt.Errorf("error preparing httpsServer: %w", err) } @@ -500,16 +505,19 @@ type httpServer struct { Switcher *middlewares.HTTPHandlerSwitcher } -func createHTTPServer(ctx context.Context, ln net.Listener, configuration *static.EntryPoint, withH2c bool) (*httpServer, error) { +func createHTTPServer(ctx context.Context, ln net.Listener, configuration *static.EntryPoint, withH2c bool, reqDecorator *requestdecorator.RequestDecorator) (*httpServer, error) { httpSwitcher := middlewares.NewHandlerSwitcher(router.BuildDefaultHTTPRouter()) + next, err := alice.New(requestdecorator.WrapHandler(reqDecorator)).Then(httpSwitcher) + if err != nil { + return nil, err + } + var handler http.Handler - var err error handler, err = forwardedheaders.NewXForwarded( configuration.ForwardedHeaders.Insecure, configuration.ForwardedHeaders.TrustedIPs, - httpSwitcher) - + next) if err != nil { return nil, err } diff --git a/pkg/server/server_entrypoint_tcp_http3_test.go b/pkg/server/server_entrypoint_tcp_http3_test.go index bdd44e0cb..b0759ef48 100644 --- a/pkg/server/server_entrypoint_tcp_http3_test.go +++ b/pkg/server/server_entrypoint_tcp_http3_test.go @@ -91,7 +91,7 @@ func TestHTTP3AdvertisedPort(t *testing.T) { HTTP3: &static.HTTP3Config{ AdvertisedPort: 8080, }, - }) + }, nil) require.NoError(t, err) router := &tcp.Router{} diff --git a/pkg/server/server_entrypoint_tcp_test.go b/pkg/server/server_entrypoint_tcp_test.go index 6b461632c..ab49cd5a9 100644 --- a/pkg/server/server_entrypoint_tcp_test.go +++ b/pkg/server/server_entrypoint_tcp_test.go @@ -79,7 +79,7 @@ func testShutdown(t *testing.T, router *tcp.Router) { Address: "127.0.0.1:0", Transport: epConfig, ForwardedHeaders: &static.ForwardedHeaders{}, - }) + }, nil) require.NoError(t, err) conn, err := startEntrypoint(entryPoint, router) @@ -162,7 +162,7 @@ func TestReadTimeoutWithoutFirstByte(t *testing.T) { Address: ":0", Transport: epConfig, ForwardedHeaders: &static.ForwardedHeaders{}, - }) + }, nil) require.NoError(t, err) router := &tcp.Router{} @@ -198,7 +198,7 @@ func TestReadTimeoutWithFirstByte(t *testing.T) { Address: ":0", Transport: epConfig, ForwardedHeaders: &static.ForwardedHeaders{}, - }) + }, nil) require.NoError(t, err) router := &tcp.Router{} From 84a081054688349fa4e2513599e3bf2395331492 Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Mon, 14 Feb 2022 17:44:08 +0100 Subject: [PATCH 7/7] Prepare release v2.6.1 --- CHANGELOG.md | 17 +++++++++++++++++ script/gcg/traefik-bugfix.toml | 10 +++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31915fed5..4c1c4d84d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +## [v2.6.1](https://github.com/traefik/traefik/tree/v2.6.1) (2022-02-14) +[All Commits](https://github.com/traefik/traefik/compare/v2.6.0...v2.6.1) + +**Bug fixes:** +- **[acme]** Add domain to HTTP challenge errors ([#8740](https://github.com/traefik/traefik/pull/8740) by [ldez](https://github.com/ldez)) +- **[metrics]** Fix metrics bucket key high cardinality ([#8761](https://github.com/traefik/traefik/pull/8761) by [tomMoulard](https://github.com/tomMoulard)) +- **[middleware,tls]** Use CNAME for SNI check on host header ([#8773](https://github.com/traefik/traefik/pull/8773) by [ldez](https://github.com/ldez)) +- **[middleware,tracing]** Rename Datadog span tags ([#8323](https://github.com/traefik/traefik/pull/8323) by [luckielordie](https://github.com/luckielordie)) +- **[tls]** Apply the same approach as the rules system on the TLS configuration choice ([#8764](https://github.com/traefik/traefik/pull/8764) by [ldez](https://github.com/ldez)) + +**Documentation:** +- **[acme]** Add Hurricane Electric to acme documentation ([#8746](https://github.com/traefik/traefik/pull/8746) by [vladshub](https://github.com/vladshub)) +- **[acme]** Clarify that ACME challenge is mandatory ([#8739](https://github.com/traefik/traefik/pull/8739) by [mpl](https://github.com/mpl)) +- **[http3]** Explain a bit more around enabling HTTP3 ([#8731](https://github.com/traefik/traefik/pull/8731) by [SantoDE](https://github.com/SantoDE)) +- **[metrics]** Fix mixups in metrics documentation ([#8752](https://github.com/traefik/traefik/pull/8752) by [tomMoulard](https://github.com/tomMoulard)) +- **[middleware,k8s/crd]** Fix Kubernetes TCP examples ([#8759](https://github.com/traefik/traefik/pull/8759) by [sylr](https://github.com/sylr)) + ## [v2.6.0](https://github.com/traefik/traefik/tree/v2.6.0) (2022-01-24) [All Commits](https://github.com/traefik/traefik/compare/v2.5.0-rc1...v2.6.0) diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index 83e4b4e09..84ee76471 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v2.5.7 -CurrentRef = "v2.5" -PreviousRef = "v2.5.6" -BaseBranch = "v2.5" -FutureCurrentRefName = "v2.5.7" +# example new bugfix v2.6.1 +CurrentRef = "v2.6" +PreviousRef = "v2.6.0" +BaseBranch = "v2.6" +FutureCurrentRefName = "v2.6.1" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10