From ab93cda676fa25509f69c2348abcde369808546d Mon Sep 17 00:00:00 2001 From: Brett Tofel Date: Mon, 1 Dec 2025 18:48:27 -0500 Subject: [PATCH 1/4] Fix HAProxy redirect: strip port from Host header Previously, when a route was configured with insecureEdgeTerminationPolicy: Redirect, HAProxy would preserve the port from the Host header in the redirect Location. This caused clients to attempt HTTPS connections on port 80 (e.g., https://example.com:80) if the original request included the port. This commit updates the HAProxy template to explicitly strip any port number from the Host header using 'regsub(:[0-9]+$,,)' before constructing the redirect URL. This ensures redirects always go to the default HTTPS port (443). A regression test 'Secure Redirect Strips Port' has been added to pkg/router/router_test.go to verify this configuration generation. --- .../haproxy/conf/haproxy-config.template | 2 +- pkg/router/router_test.go | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/images/router/haproxy/conf/haproxy-config.template b/images/router/haproxy/conf/haproxy-config.template index 7a0129cde..bc0c506d7 100644 --- a/images/router/haproxy/conf/haproxy-config.template +++ b/images/router/haproxy/conf/haproxy-config.template @@ -262,7 +262,7 @@ frontend public # check if we need to redirect/force using https. acl secure_redirect base,map_reg_int(/var/lib/haproxy/conf/os_route_http_redirect.map) -m bool - redirect scheme https if secure_redirect + http-request redirect location https://%[hdr(host),regsub(:[0-9]+$,,)]%[path] code 301 if secure_redirect {{- range $idx, $http_request_header := .HTTPRequestHeaders }} {{- if eq $http_request_header.Action "Set" }} diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index 9ad016594..5a6aa713a 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -909,6 +909,23 @@ func TestConfigTemplate(t *testing.T) { }, }, }, + "Secure Redirect Strips Port": { + mustCreateWithConfig{ + mustCreateRoute: mustCreateRoute{ + name: "secure-redirect-route", + host: "secure.example.com", + time: start, + insecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, + tlsTermination: routev1.TLSTerminationEdge, + }, + mustMatchConfig: mustMatchConfig{ + section: "frontend", + sectionName: "public", + attribute: "http-request", + value: `redirect location https://%[hdr(host),regsub(:[0-9]+$,,)]%[path] code 301 if secure_redirect`, + }, + }, + }, } defer cleanUpRoutes(t) @@ -990,6 +1007,8 @@ type mustCreateRoute struct { // cert is the spec.tls.certificate of the route. It should be // specified only if tlsTermination is "edge" or "reencrypt". cert string + // insecureEdgeTerminationPolicy is the spec.tls.insecureEdgeTerminationPolicy of the route. + insecureEdgeTerminationPolicy routev1.InsecureEdgeTerminationPolicyType // httpHeaders is the spec.httpHeaders of the route. httpHeaders routev1.RouteHTTPHeaders // alternateBackend is the first item in spec.alternateBackends of the route. @@ -1007,11 +1026,12 @@ func (e mustCreateRoute) Apply(h *harness) error { if e.annotations != nil { annotations = e.annotations } - tlsConfig := &routev1.TLSConfig{} + var tlsConfig *routev1.TLSConfig if e.tlsTermination != "" { tlsConfig = &routev1.TLSConfig{ - Termination: routev1.TLSTerminationType(e.tlsTermination), - Certificate: e.cert, + Termination: routev1.TLSTerminationType(e.tlsTermination), + Certificate: e.cert, + InsecureEdgeTerminationPolicy: e.insecureEdgeTerminationPolicy, } } serviceName := "service" + e.name From 4c48ef9a17eb2ae433791e57cdde9406256620d1 Mon Sep 17 00:00:00 2001 From: Brett Tofel Date: Tue, 2 Dec 2025 09:41:21 -0500 Subject: [PATCH 2/4] Fix go formatting Signed-off-by: Brett Tofel --- pkg/router/router_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index 5a6aa713a..b464d6b7b 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -912,9 +912,9 @@ func TestConfigTemplate(t *testing.T) { "Secure Redirect Strips Port": { mustCreateWithConfig{ mustCreateRoute: mustCreateRoute{ - name: "secure-redirect-route", - host: "secure.example.com", - time: start, + name: "secure-redirect-route", + host: "secure.example.com", + time: start, insecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, tlsTermination: routev1.TLSTerminationEdge, }, From 1cb0bb18b77a941b23f3554a499150afd2423b7c Mon Sep 17 00:00:00 2001 From: Brett Tofel Date: Tue, 2 Dec 2025 11:12:22 -0500 Subject: [PATCH 3/4] Use req.hdr(host) and 302 code for redirect --- images/router/haproxy/conf/haproxy-config.template | 2 +- pkg/router/router_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/images/router/haproxy/conf/haproxy-config.template b/images/router/haproxy/conf/haproxy-config.template index bc0c506d7..96e2a4fad 100644 --- a/images/router/haproxy/conf/haproxy-config.template +++ b/images/router/haproxy/conf/haproxy-config.template @@ -262,7 +262,7 @@ frontend public # check if we need to redirect/force using https. acl secure_redirect base,map_reg_int(/var/lib/haproxy/conf/os_route_http_redirect.map) -m bool - http-request redirect location https://%[hdr(host),regsub(:[0-9]+$,,)]%[path] code 301 if secure_redirect + http-request redirect location https://%[req.hdr(host),regsub(:[0-9]+$,,)]%[path] code 302 if secure_redirect {{- range $idx, $http_request_header := .HTTPRequestHeaders }} {{- if eq $http_request_header.Action "Set" }} diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index b464d6b7b..dc51a290d 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -922,7 +922,7 @@ func TestConfigTemplate(t *testing.T) { section: "frontend", sectionName: "public", attribute: "http-request", - value: `redirect location https://%[hdr(host),regsub(:[0-9]+$,,)]%[path] code 301 if secure_redirect`, + value: `redirect location https://%[req.hdr(host),regsub(:[0-9]+$,,)]%[path] code 302 if secure_redirect`, }, }, }, From 340ce0f74b5a135e4c331d8b563fc013150c599b Mon Sep 17 00:00:00 2001 From: Brett Tofel Date: Wed, 17 Dec 2025 08:55:16 -0500 Subject: [PATCH 4/4] Fix: Preserve query strings during HTTPS redirection --- images/router/haproxy/conf/haproxy-config.template | 2 +- pkg/router/router_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/images/router/haproxy/conf/haproxy-config.template b/images/router/haproxy/conf/haproxy-config.template index 96e2a4fad..e7f89360c 100644 --- a/images/router/haproxy/conf/haproxy-config.template +++ b/images/router/haproxy/conf/haproxy-config.template @@ -262,7 +262,7 @@ frontend public # check if we need to redirect/force using https. acl secure_redirect base,map_reg_int(/var/lib/haproxy/conf/os_route_http_redirect.map) -m bool - http-request redirect location https://%[req.hdr(host),regsub(:[0-9]+$,,)]%[path] code 302 if secure_redirect + http-request redirect location https://%[req.hdr(host),regsub(:[0-9]+$,,)]%[url] code 302 if secure_redirect {{- range $idx, $http_request_header := .HTTPRequestHeaders }} {{- if eq $http_request_header.Action "Set" }} diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index dc51a290d..ee14c4fb1 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -922,7 +922,7 @@ func TestConfigTemplate(t *testing.T) { section: "frontend", sectionName: "public", attribute: "http-request", - value: `redirect location https://%[req.hdr(host),regsub(:[0-9]+$,,)]%[path] code 302 if secure_redirect`, + value: `redirect location https://%[req.hdr(host),regsub(:[0-9]+$,,)]%[url] code 302 if secure_redirect`, }, }, },