fix: hardening to prevent usage of proxy-protocol with proxy-headers (#37463)

* fix: hardening to prevent usage of proxy-protocol with proxy-headers

closes: #37458

Signed-off-by: Steve Hawkins <shawkins@redhat.com>

* Update docs/guides/server/reverseproxy.adoc

Co-authored-by: Martin Bartoš <mabartos@redhat.com>
Signed-off-by: Steven Hawkins <shawkins@redhat.com>

---------

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
Signed-off-by: Steven Hawkins <shawkins@redhat.com>
Co-authored-by: Martin Bartoš <mabartos@redhat.com>
This commit is contained in:
Steven Hawkins 2025-02-24 08:48:06 -05:00 committed by GitHub
parent 9bf0af612a
commit a819a213f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 39 additions and 17 deletions

View File

@ -28,7 +28,7 @@ You only need to proxy port `8443` (or `8080`) even when you use different host
{project_name} will parse the reverse proxy headers based on the `proxy-headers` option which accepts several values:
* By default if the option is not specified, no reverse proxy headers are parsed.
* By default if the option is not specified, no reverse proxy headers are parsed. This should be used when no proxy is in use or with https passthrough.
* `forwarded` enables parsing of the `Forwarded` header as per https://www.rfc-editor.org/rfc/rfc7239.html[RFC7239].
* `xforwarded` enables parsing of non-standard `X-Forwarded-*` headers, such as `X-Forwarded-For`, `X-Forwarded-Proto`, `X-Forwarded-Host`, and `X-Forwarded-Port`.
@ -38,7 +38,7 @@ For example:
<@kc.start parameters="--proxy-headers forwarded"/>
WARNING: If either `forwarded` or `xforwarded` is selected, make sure your reverse proxy properly sets and overwrites the `Forwarded` or `X-Forwarded-*` headers respectively. To set these headers, consult the documentation for your reverse proxy. Misconfiguration will leave {project_name} exposed to security vulnerabilities.
WARNING: If either `forwarded` or `xforwarded` is selected, make sure your reverse proxy properly sets and overwrites the `Forwarded` or `X-Forwarded-*` headers respectively. To set these headers, consult the documentation for your reverse proxy. Do not use `forwarded` or `xforwarded` with https passthrough. Misconfiguration will leave {project_name} exposed to security vulnerabilities.
Take extra precautions to ensure that the client address is properly set by your reverse proxy via the `Forwarded` or `X-Forwarded-For` headers.
If this header is incorrectly configured, rogue clients can set this header and trick {project_name} into thinking the client is connected from a different IP address than the actual address. This precaution can be more critical if you do any deny or allow listing of IP addresses.
@ -146,7 +146,7 @@ For example:
== PROXY Protocol
The `proxy-protocol-enabled` option controls whether the server should use the HA PROXY protocol when serving requests from behind a proxy. When set to true, the remote address returned will be the one from the actual connecting client.
The `proxy-protocol-enabled` option controls whether the server should use the HA PROXY protocol when serving requests from behind a proxy. When set to true, the remote address returned will be the one from the actual connecting client. The value cannot be `true` when using the `proxy-headers` option.
This is useful when running behind a compatible https passthrough proxy because the request headers cannot be manipulated.

View File

@ -13,10 +13,10 @@ public class ProxyOptions {
.category(OptionCategory.PROXY)
.description("The proxy headers that should be accepted by the server. Misconfiguration might leave the server exposed to security vulnerabilities. Takes precedence over the deprecated proxy option.")
.build();
public static final Option<Boolean> PROXY_PROTOCOL_ENABLED = new OptionBuilder<>("proxy-protocol-enabled", Boolean.class)
.category(OptionCategory.PROXY)
.description("Whether the server should use the HA PROXY protocol when serving requests from behind a proxy. When set to true, the remote address returned will be the one from the actual connecting client.")
.description("Whether the server should use the HA PROXY protocol when serving requests from behind a proxy. When set to true, the remote address returned will be the one from the actual connecting client. Cannot be enabled when the `proxy-headers` is used.")
.defaultValue(Boolean.FALSE)
.build();
@ -34,7 +34,7 @@ public class ProxyOptions {
.category(OptionCategory.PROXY)
.defaultValue(Boolean.FALSE)
.build();
public static final Option<List<String>> PROXY_TRUSTED_ADDRESSES = OptionBuilder.listOptionBuilder("proxy-trusted-addresses", String.class)
.category(OptionCategory.PROXY)
.description("A comma separated list of trusted proxy addresses. If set, then proxy headers from other addresses will be ignored. By default all addresses are trusted. A trusted proxy address is specified as an IP address (IPv4 or IPv6) or Classless Inter-Domain Routing (CIDR) notation.")

View File

@ -21,6 +21,11 @@ final class ProxyPropertyMappers {
.build(),
fromOption(ProxyOptions.PROXY_PROTOCOL_ENABLED)
.to("quarkus.http.proxy.use-proxy-protocol")
.validator(v -> {
if (Boolean.parseBoolean(v) && Configuration.getOptionalKcValue(ProxyOptions.PROXY_HEADERS).isPresent()) {
throw new PropertyException("proxy protocol cannot be enabled when using the `proxy-headers` option");
}
})
.build(),
fromOption(ProxyOptions.PROXY_FORWARDED_HOST)
.to("quarkus.http.proxy.enable-forwarded-host")
@ -42,7 +47,7 @@ final class ProxyPropertyMappers {
.build()
};
}
private static void validateAddress(String address) {
if (Inet.parseCidrAddress(address) != null) {
return;

View File

@ -573,4 +573,11 @@ public class PicocliTest extends AbstractConfigurationTest {
nonRunningPicocli = pseudoLaunch("start-dev", "--log=syslog", "--log-syslog-output=json", "--log-syslog-json-format=ecs");
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
}
@Test
public void proxyProtolNotAllowedWithProxyHeaders() {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start-dev", "--proxy-headers=forwarded", "--proxy-protocol-enabled=true");
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString(" protocol cannot be enabled when using the `proxy-headers` option"));
}
}

View File

@ -265,7 +265,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.

View File

@ -316,7 +316,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.

View File

@ -272,7 +272,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.

View File

@ -317,7 +317,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.

View File

@ -222,7 +222,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.

View File

@ -267,7 +267,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.

View File

@ -271,7 +271,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.

View File

@ -316,7 +316,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.

View File

@ -269,7 +269,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.

View File

@ -314,7 +314,8 @@ Proxy:
--proxy-protocol-enabled <true|false>
Whether the server should use the HA PROXY protocol when serving requests from
behind a proxy. When set to true, the remote address returned will be the
one from the actual connecting client. Default: false.
one from the actual connecting client. Cannot be enabled when the
`proxy-headers` is used. Default: false.
--proxy-trusted-addresses <trusted proxies>
A comma separated list of trusted proxy addresses. If set, then proxy headers
from other addresses will be ignored. By default all addresses are trusted.