29

My Spring Boot 2.2.0 application with Spring Web MVC is running behind a reverse proxy. How can Spring cope properly with X-Forwarded-{Prefix,Host,Proto}-headers to recognize the actual request made to the server?

phip1611
  • 5,460
  • 4
  • 30
  • 57

1 Answers1

61

With Spring Boot <= 2.1.x you had to provide a ForwardedHeaderFilter-Bean. Since Spring Boot 2.2.0 you don't have to do this anymore. Just add server.forward-headers-strategy=NATIVE or server.forward-headers-strategy=FRAMEWORK to your application.properties-file.

NATIVE means that the servlet container (e.g. undertow, tomcat) is resolving the x-forwarded-*-headers which is fine in most cases. If you rely on X-Forwarded-Prefix than you must use FRAMEWORK so that request.getContextPath() is set properly.


Example:

  1. User types into browser: https://mydomain.tld/my-microservice/actuator
  2. the microservice "my-microservice" (e.g. user-service) shall handle the request; it's running on localhost:8080
  3. reverse-proxy forwards the request like this:

    // Forwarded-Request from Reverse Proxy to your microservice
    GET http://localhost:8080/actuator/
    X-Forwarded-Host: mydomain.tld
    X-Forwarded-Proto: https
    X-Forwarded-Prefix: /my-microservice
    

Debugging into a HttpServletRequest will result in:

request.getRequestURL(): "https://mydomain.tld/my-microservice/actuator/"
request.getScheme(): "https"
request.getContextPath(): "/my-microservice"
new UrlPathHelper().getPathWithinApplication(request): "/actuator"
phip1611
  • 5,460
  • 4
  • 30
  • 57
  • 12
    **DO NOT USE** `server.forward-headers-strategy=FRAMEWORK` unless you know what you are doing i.e unless you trust your reverse-proxy. A malicious client can add any headers they want, and then ... KABOOM. – jumping_monkey Apr 03 '20 at 02:00
  • You can also add custom proxy headers for server.forward-headers-strategy=native too. Best option is to write a custom Zuul Filter that will occur after PreDecorationFilter in spring cloud. PreDecorationFilter is looking to see if these headers are set (in both framework and native strategies) and then is "changing" host if they are. I'm not exactly sure why they did this. Proxy headers aren't marked as Forbidden headers, so maybe they're not considered a security risk and this concern is just paranoia – mljohns89 Apr 06 '20 at 20:43
  • @jumping_monkey In which cases is this a real problem? In my experience the spring boot application is always **only** reachable **on localhost** on the machine and one reverse proxy is running. The only reverse proxy, why shouldn't I trust it? And anyway, why is this problem restricted to FRAMEWORK? What is different in the resolution of the forwarded headers in tomcat? It's basically the same problem? – phip1611 May 25 '20 at 14:42
  • 3
    Hey @phip1611, good question. Basically, how do you know that the `forwarded headers` have been added by the proxy and can be trusted or by a malicious client? This security consideration is also highlighted [here](https://docs.spring.io/spring/docs/5.2.6.RELEASE/spring-framework-reference/web.html#filters-forwarded-headers) – jumping_monkey May 26 '20 at 02:30
  • 4
    _Thanks_, this was driving me insane. I was having major problems with Swagger UI because we serve on the root of the container, but through a path prefix in K8s and Swagger was redirecting requests to the route. The solution was to use the `framework` level `forward-headers-strategy` and add an Ingress label `nginx.ingress.kubernetes.io/x-forwarded-prefix: "${k8s_app_path}"` where that variable is the prefix the application is being served through. – Elven Spellmaker Jul 29 '20 at 14:19
  • 1
    After reading and reading and reading, i do not know how i missed this, thanks a ton! – thechaoticpanda Nov 28 '20 at 08:14
  • You can use server.use-forward-headers set to true on Spring boot version between 1.3.0 & 2.2.0 https://docs.spring.io/spring-boot/docs/2.1.16.RELEASE/reference/htmlsingle/#howto-use-behind-a-proxy-server – Vsoma Nov 23 '21 at 23:09