From 56fb6636c47beba32916fec721290671ea98f5f8 Mon Sep 17 00:00:00 2001 From: Miciah Masters Date: Fri, 7 Feb 2020 12:29:21 -0500 Subject: [PATCH 1/2] Omit brackets around IPv4 addresses in v4v6 mode Do not put brackets around an IPv4 address in the Forwarded header. RFC 7239 dictates that the host name in the header should be an IPv4 address (without brackets) or an IPv6 address with brackets. This commit fixes bug 1801407. https://bugzilla.redhat.com/show_bug.cgi?id=1801407 * images/router/haproxy/conf/haproxy-config.template: Don't quote IPv4 addresses in v4v6 mode. --- .../haproxy/conf/haproxy-config.template | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/images/router/haproxy/conf/haproxy-config.template b/images/router/haproxy/conf/haproxy-config.template index ae117eca..0efdaf4f 100644 --- a/images/router/haproxy/conf/haproxy-config.template +++ b/images/router/haproxy/conf/haproxy-config.template @@ -498,8 +498,12 @@ backend {{genBackendNamePrefix $cfg.TLSTermination}}:{{$cfgIdx}} http-request add-header X-Forwarded-Proto http if !{ ssl_fc } http-request add-header X-Forwarded-Proto https if { ssl_fc } http-request add-header X-Forwarded-Proto-Version h2 if { ssl_fc_alpn -i h2 } - {{- if matchPattern "(v4)?v6" $router_ip_v4_v6_mode }} + {{- if eq "v4v6" $router_ip_v4_v6_mode }} # See the quoting rules in https://tools.ietf.org/html/rfc7239 for IPv6 addresses (v4 addresses get translated to v6 when in hybrid mode) + acl ipv6_addr src -m sub : + http-request add-header Forwarded for=\"[%[src]]\";host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] if ipv6_addr + http-request add-header Forwarded for=%[src];host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] if !ipv6_addr + {{- else if eq "v6" $router_ip_v4_v6_mode }} http-request add-header Forwarded for=\"[%[src]]\";host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] {{- else }} http-request add-header Forwarded for=%[src];host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] @@ -511,8 +515,12 @@ backend {{genBackendNamePrefix $cfg.TLSTermination}}:{{$cfgIdx}} http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto-Version h2 if { ssl_fc_alpn -i h2 } - {{- if matchPattern "(v4)?v6" $router_ip_v4_v6_mode }} + {{- if eq "v4v6" $router_ip_v4_v6_mode }} # See the quoting rules in https://tools.ietf.org/html/rfc7239 for IPv6 addresses (v4 addresses get translated to v6 when in hybrid mode) + acl ipv6_addr src -m sub : + http-request set-header Forwarded for=\"[%[src]]\";host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] if ipv6_addr + http-request set-header Forwarded for=%[src];host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] if !ipv6_addr + {{- else if eq "v6" $router_ip_v4_v6_mode }} http-request set-header Forwarded for=\"[%[src]]\";host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] {{- else }} http-request set-header Forwarded for=%[src];host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] @@ -524,8 +532,12 @@ backend {{genBackendNamePrefix $cfg.TLSTermination}}:{{$cfgIdx}} http-request set-header X-Forwarded-Proto http if !{ ssl_fc } !{ req.hdr(X-Forwarded-Proto) -m found } http-request set-header X-Forwarded-Proto https if { ssl_fc } !{ req.hdr(X-Forwarded-Proto) -m found } http-request set-header X-Forwarded-Proto-Version h2 if { ssl_fc_alpn -i h2 } !{ req.hdr(X-Forwarded-Proto-Version) -m found } - {{- if matchPattern "(v4)?v6" $router_ip_v4_v6_mode }} + {{- if eq "v4v6" $router_ip_v4_v6_mode }} # See the quoting rules in https://tools.ietf.org/html/rfc7239 for IPv6 addresses (v4 addresses get translated to v6 when in hybrid mode) + acl ipv6_addr src -m sub : + http-request set-header Forwarded for=\"[%[src]]\";host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] if ipv6_addr !{ req.hdr(Forwarded) -m found } + http-request set-header Forwarded for=%[src];host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] if !ipv6_addr !{ req.hdr(Forwarded) -m found } + {{- else if eq "v6" $router_ip_v4_v6_mode }} http-request set-header Forwarded for=\"[%[src]]\";host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] if !{ req.hdr(Forwarded) -m found } {{- else }} http-request set-header Forwarded for=%[src];host=%[req.hdr(host)];proto=%[req.hdr(X-Forwarded-Proto)] if !{ req.hdr(Forwarded) -m found } From 74c2d9397cb8e92c28642f56e46fd29a08d8f64b Mon Sep 17 00:00:00 2001 From: Miciah Masters Date: Fri, 5 Feb 2021 18:56:15 -0500 Subject: [PATCH 2/2] Bind v4 and v6 addresses separately in frontends Use separate bind lines for IPv4 and IPv6. Using "bind :::80 v4v6" causes HAProxy to listen on v4 and v6 addresses but translate v4 source addresses into v6 addresses, which can be seen in HTTP headers. Using separate bind lines causes HAProxy to report source addresses faithfully. * images/router/haproxy/conf/haproxy-config.template: Use separate bind lines for IPv4 and IPv6 listening addresses. --- images/router/haproxy/conf/haproxy-config.template | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/images/router/haproxy/conf/haproxy-config.template b/images/router/haproxy/conf/haproxy-config.template index 0efdaf4f..e6aa1632 100644 --- a/images/router/haproxy/conf/haproxy-config.template +++ b/images/router/haproxy/conf/haproxy-config.template @@ -163,7 +163,8 @@ listen stats {{ if .BindPorts -}} frontend public {{ if eq "v4v6" $router_ip_v4_v6_mode }} - bind :::{{env "ROUTER_SERVICE_HTTP_PORT" "80"}} v4v6 + bind :{{env "ROUTER_SERVICE_HTTP_PORT" "80"}} + bind :::{{env "ROUTER_SERVICE_HTTP_PORT" "80"}} v6only {{- else if eq "v6" $router_ip_v4_v6_mode }} bind :::{{env "ROUTER_SERVICE_HTTP_PORT" "80"}} v6only {{- else }} @@ -216,7 +217,8 @@ frontend public_ssl option tcplog {{- end }} {{ if eq "v4v6" $router_ip_v4_v6_mode }} - bind :::{{env "ROUTER_SERVICE_HTTPS_PORT" "443"}} v4v6 + bind :{{env "ROUTER_SERVICE_HTTPS_PORT" "443"}} + bind :::{{env "ROUTER_SERVICE_HTTPS_PORT" "443"}} v6only {{- else if eq "v6" $router_ip_v4_v6_mode }} bind :::{{env "ROUTER_SERVICE_HTTPS_PORT" "443"}} v6only {{- else }}