diff --git a/framework-docs/modules/ROOT/pages/web/webflux/reactive-spring.adoc b/framework-docs/modules/ROOT/pages/web/webflux/reactive-spring.adoc index 54e44b52822..f3fddd58e1b 100644 --- a/framework-docs/modules/ROOT/pages/web/webflux/reactive-spring.adoc +++ b/framework-docs/modules/ROOT/pages/web/webflux/reactive-spring.adoc @@ -338,21 +338,26 @@ include::partial$web/forwarded-headers.adoc[] [[webflux-forwarded-headers-transformer]] === ForwardedHeaderTransformer -`ForwardedHeaderTransformer` is a component that modifies the host, port, and scheme of -the request, based on forwarded headers, and then removes those headers. If you declare -it as a bean with the name `forwardedHeaderTransformer`, it will be +`ForwardedHeaderTransformer` is a component that modifies the request to match information +from the standard `"Forwarded"` or `"X-Forwarded"` headers, and also removes those headers +to eliminate further impact. If you declare it as a bean with the name +`forwardedHeaderTransformer`, it will be xref:web/webflux/reactive-spring.adoc#webflux-web-handler-api-special-beans[detected] and used. - [[webflux-forwarded-headers-security]] === Security Considerations -There are security considerations for forwarded headers since an application cannot know -if the headers were added by a proxy, as intended, or by a malicious client. This is why -a proxy at the boundary of trust should be configured to remove untrusted forwarded traffic coming -from the outside. You can also configure the `ForwardedHeaderTransformer` with -`removeOnly=true`, in which case it removes but does not use the headers. +Forwarded headers are intended to be set by trusted proxies and never allowed in from the +outside. A proxy at the edge of trust must remove forwarded headers including both the +standard `"Forwarded"` and `"X-Forwarded"` headers, regardless of which one they use, +to protect applications which may check both. +When creating `ForwardedHeaderTransformer` you need to specify whether it should use the +standard `"Forwarded"` or `"X-Forwarded"` headers. If needed `"X-Forwarded-Prefix"` +must be enabled separately through a property on the transformer. + +`ForwardedHeaderTransformer` can be configured in `removeOnly` mode, in which case it removes +forwarded headers from the request without using them. [[webflux-filters]] == Filters diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc index 3e2aad25221..11bd6848a92 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc @@ -24,7 +24,7 @@ ignoring further handling via `FORWARD` dispatches. The filter also provides con over whether the `Filter` gets involved in `ASYNC` and `ERROR` dispatches. Servlet filters can be configured in `web.xml` or via Servlet annotations. -In a Spring Boot application , you can +In a Spring Boot application, you can {spring-boot-docs}/how-to/webserver.html#howto.webserver.add-servlet-filter-listener.spring-bean[declare Filter's as beans] and Boot will have them configured. @@ -51,20 +51,29 @@ include::partial$web/forwarded-headers.adoc[] [[filters-forwarded-headers-non-forwardedheaderfilter]] === ForwardedHeaderFilter -`ForwardedHeaderFilter` is a Servlet filter that modifies the request in order to -a) change the host, port, and scheme based on `Forwarded` headers, and b) to remove those -headers to eliminate further impact. The filter relies on wrapping the request, and -therefore it must be ordered ahead of other filters, such as `RequestContextFilter`, that -should work with the modified and not the original request. +`ForwardedHeaderFilter` is a Servlet filter that modifies the request to match information +from the standard `"Forwarded"` or `"X-Forwarded"` headers, and also removes those headers +to eliminate further impact. The filter wraps the request and must be ordered ahead +of other filters such as `RequestContextFilter` in order for all downstream +handlers to see the modified request. + [[filters-forwarded-headers-security]] === Security Considerations -There are security considerations for forwarded headers since an application cannot know -if the headers were added by a proxy, as intended, or by a malicious client. This is why -a proxy at the boundary of trust should be configured to remove untrusted `Forwarded` -headers that come from the outside. You can also configure the `ForwardedHeaderFilter` -with `removeOnly=true`, in which case it removes but does not use the headers. +Forwarded headers are intended to be set by trusted proxies and never allowed in from the +outside. A proxy at the edge of trust must remove forwarded headers including both the +standard `"Forwarded"` and `"X-Forwarded"` headers, regardless of which one they use, +to protect applications which may check both. + +When creating `ForwardedHeaderFilter` you need to specify whether it should use the +standard `"Forwarded"` or `"X-Forwarded"` headers. If needed `"X-Forwarded-Prefix"` +must be enabled separately through a property on the filter. + +`ForwardedHeaderFilter` can be configured in `removeOnly` mode, in which case it removes +forwarded headers from the request without using them. + + [[filters-forwarded-headers-dispatcher]] === Dispatcher Types diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-uri-building.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-uri-building.adoc index bc0f1bae54d..85da18dc57a 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-uri-building.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-uri-building.adoc @@ -112,8 +112,8 @@ Kotlin:: NOTE: As of 5.1, `ServletUriComponentsBuilder` ignores information from the `Forwarded` and `X-Forwarded-*` headers, which specify the client-originated address. Consider using the -xref:web/webmvc/filters.adoc#filters-forwarded-headers[`ForwardedHeaderFilter`] to extract and use or to discard -such headers. +xref:web/webmvc/filters.adoc#filters-forwarded-headers[`ForwardedHeaderFilter`] +to extract and use or to discard such headers. [[mvc-links-to-controllers]] @@ -261,8 +261,8 @@ Kotlin:: NOTE: As of 5.1, `MvcUriComponentsBuilder` ignores information from the `Forwarded` and `X-Forwarded-*` headers, which specify the client-originated address. Consider using the -xref:web/webmvc/filters.adoc#filters-forwarded-headers[ForwardedHeaderFilter] to extract and use or to discard -such headers. +xref:web/webmvc/filters.adoc#filters-forwarded-headers[ForwardedHeaderFilter] to extract +and use or to discard such headers. [[mvc-links-to-controllers-from-views]] diff --git a/framework-docs/modules/ROOT/partials/web/forwarded-headers.adoc b/framework-docs/modules/ROOT/partials/web/forwarded-headers.adoc index c1f63fad0de..1ba007dec0f 100644 --- a/framework-docs/modules/ROOT/partials/web/forwarded-headers.adoc +++ b/framework-docs/modules/ROOT/partials/web/forwarded-headers.adoc @@ -1,15 +1,30 @@ -As a request goes through proxies such as load balancers the host, port, and -scheme may change, and that makes it a challenge to create links that point to the correct -host, port, and scheme from a client perspective. +As a request goes through a chain of proxies, request details such as the scheme, host, +port, remote address, and local address change. Proxies can insert headers that keep track of +the hops, and that can help to restore the request from the original client's perspective. +This allows an application to create self-reference links for external clients. + +There are two alternatives for headers that proxies can use: + +- {rfc-site}/rfc7239[RFC 7239] defines the `"Forwarded"` HTTP header, a single header with +individual attributes for each component in the chain of proxied requests with the +following syntax. +- `"X-Forwarded-"` prefixed headers are the original approach that predates the standard +and uses a separate header for each request component. + +The Spring Framework supports both approaches. Most proxies today support the original +`"X-Forwarded"` headers only as a de facto standard. + +WARNING: For maximum security, a proxy at the edge of trust must be configured to reset both +the standard `"Forwarded"` and `"X-Forwarded-"` headers regardless of which ones are chosen +for use. Likewise, when configuring forwarded header handling in Spring, you need to indicate +which type of headers to use. More on security considerations later in this section. + -{rfc-site}/rfc7239[RFC 7239] defines the `Forwarded` HTTP header -that proxies can use to provide information about the original request. [[forwarded-headers-non-standard]] -=== Non-standard Headers +=== X-Forwarded Headers -There are other non-standard headers, too, including `X-Forwarded-Host`, `X-Forwarded-Port`, -`X-Forwarded-Proto`, `X-Forwarded-Ssl`, `X-Forwarded-Prefix`, and `X-Forwarded-For`. +This section describes supported `"X-Forwarded"` headers. [[x-forwarded-host]] ==== X-Forwarded-Host