Files
2026-07-24 22:31:52 +03:00

140 lines
6.4 KiB
Plaintext

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.
[[forwarded-headers-non-standard]]
=== X-Forwarded Headers
This section describes supported `"X-Forwarded"` headers.
[[x-forwarded-host]]
==== X-Forwarded-Host
While not standard, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host[`X-Forwarded-Host: <host>`]
is a de-facto standard header that is used to communicate the original host to a
downstream server. For example, if a request of `https://example.com/resource` is sent to
a proxy which forwards the request to `http://localhost:8080/resource`, then a header of
`X-Forwarded-Host: example.com` can be sent to inform the server that the original host was `example.com`.
[[x-forwarded-port]]
==== X-Forwarded-Port
While not standard, `X-Forwarded-Port: <port>` is a de-facto standard header that is used to
communicate the original port to a downstream server. For example, if a request of
`https://example.com/resource` is sent to a proxy which forwards the request to
`http://localhost:8080/resource`, then a header of `X-Forwarded-Port: 443` can be sent
to inform the server that the original port was `443`.
[[x-forwarded-proto]]
==== X-Forwarded-Proto
While not standard, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto[`X-Forwarded-Proto: (https|http)`]
is a de-facto standard header that is used to communicate the original protocol (for example, https / http)
to a downstream server. For example, if a request of `https://example.com/resource` is sent to
a proxy which forwards the request to `http://localhost:8080/resource`, then a header of
`X-Forwarded-Proto: https` can be sent to inform the server that the original protocol was `https`.
[[x-forwarded-ssl]]
==== X-Forwarded-Ssl
While not standard, `X-Forwarded-Ssl: (on|off)` is a de-facto standard header that is used to communicate the
original protocol (for example, https / https) to a downstream server. For example, if a request of
`https://example.com/resource` is sent to a proxy which forwards the request to
`http://localhost:8080/resource`, then a header of `X-Forwarded-Ssl: on` to inform the server that the
original protocol was `https`.
[[x-forwarded-prefix]]
==== X-Forwarded-Prefix
While not standard, https://microsoft.github.io/reverse-proxy/articles/transforms.html#defaults[`X-Forwarded-Prefix: <prefix>`]
is a de-facto standard header that is used to communicate the original URL path prefix to a
downstream server.
Use of `X-Forwarded-Prefix` can vary by deployment scenario, and needs to be flexible to
allow replacing, removing, or prepending the path prefix of the target server.
_Scenario 1: Override path prefix_
[subs="-attributes"]
----
https://example.com/api/{path} -> http://localhost:8080/app1/{path}
----
The prefix is the start of the path before the capture group `+{path}+`. For the proxy,
the prefix is `/api` while for the server the prefix is `/app1`. In this case, the proxy
can send `X-Forwarded-Prefix: /api` to have the original prefix `/api` override the
server prefix `/app1`.
_Scenario 2: Remove path prefix_
At times, an application may want to have the prefix removed. For example, consider the
following proxy to server mapping:
[subs="-attributes"]
----
https://app1.example.com/{path} -> http://localhost:8080/app1/{path}
https://app2.example.com/{path} -> http://localhost:8080/app2/{path}
----
The proxy has no prefix, while applications `app1` and `app2` have path prefixes
`/app1` and `/app2` respectively. The proxy can send ``X-Forwarded-Prefix: `` to
have the empty prefix override server prefixes `/app1` and `/app2`.
[NOTE]
====
A common case for this deployment scenario is where licenses are paid per
production application server, and it is preferable to deploy multiple applications per
server to reduce fees. Another reason is to run more applications on the same server in
order to share the resources required by the server to run.
In these scenarios, applications need a non-empty context root because there are multiple
applications on the same server. However, this should not be visible in URL paths of
the public API where applications may use different subdomains that provides benefits
such as:
* Added security, for example, same origin policy
* Independent scaling of applications (different domain points to different IP address)
====
_Scenario 3: Insert path prefix_
In other cases, it may be necessary to prepend a prefix. For example, consider the
following proxy to server mapping:
[subs="-attributes"]
----
https://example.com/api/app1/{path} -> http://localhost:8080/app1/{path}
----
In this case, the proxy has a prefix of `/api/app1` and the server has a prefix of
`/app1`. The proxy can send `X-Forwarded-Prefix: /api/app1` to have the original prefix
`/api/app1` override the server prefix `/app1`.
[[x-forwarded-for]]
==== X-Forwarded-For
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For[`X-Forwarded-For: <address>`]
is a de-facto standard header that is used to communicate the original `InetSocketAddress` of the client to a
downstream server. For example, if a request is sent by a client at `[fd00:fefe:1::4]` to a proxy at
`192.168.0.1`, the "remote address" information contained in the HTTP request will reflect the actual address of the
client, not the proxy.