Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x-forwarded-host & x-forwarded-prefix headers not working after project upgrade to Spring Boot 2.1 #862

Closed
RobMaskell opened this issue Mar 9, 2019 · 25 comments

Comments

@RobMaskell
Copy link

RobMaskell commented Mar 9, 2019

Had a working project, Spring boot / Spring data rest / Spring Hateos and after upgrade to Spring boot 2.1.3 it appears that x-forwarded-prefix and x-forwarded-host are not longer working. x-forwarded-proto and x-forwarded-port are working fine.

Broke it out into the simplest possible app demo.tar.gz to check and still couldn't get it working.

If I run

http -v GET localhost:8081

the result is

GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8081
User-Agent: HTTPie/0.9.8



HTTP/1.1 200 
Content-Type: application/hal+json;charset=UTF-8
Date: Sat, 09 Mar 2019 18:21:59 GMT
Transfer-Encoding: chunked

{
    "_links": {
        "people": {
            "href": "http://localhost:8081/people{?page,size,sort}",
            "templated": true
        },
        "profile": {
            "href": "http://localhost:8081/profile"
        }
    }
}

all ok so far, however when I try

http -v GET localhost:8081 x-forwarded-proto:https x-forwarded-host:example.com:9090 x-forwarded-port:9090 x-forwarded-prefix:/api

I get

GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8081
User-Agent: HTTPie/0.9.8
x-forwarded-host: example.com:9090
x-forwarded-port: 9090
x-forwarded-prefix: /api
x-forwarded-proto: https



HTTP/1.1 200 
Content-Type: application/hal+json;charset=UTF-8
Date: Sat, 09 Mar 2019 18:23:01 GMT
Transfer-Encoding: chunked

{
    "_links": {
        "people": {
            "href": "https://localhost:9090/people{?page,size,sort}",
            "templated": true
        },
        "profile": {
            "href": "https://localhost:9090/profile"
        }
    }
}

I was expecting the links to be of the form https://example.com:9090/api/profile

@gregturn
Copy link
Contributor

gregturn commented Mar 9, 2019

Duplicates #753.

@gregturn gregturn closed this as completed Mar 9, 2019
@RobMaskell
Copy link
Author

But I'm testing with 0.25.1 which fixes 753?

@gregturn
Copy link
Contributor

gregturn commented Mar 9, 2019

Yup

d885cb0 is the fix backported to 0.25.x and released in 0.25.1.release.

@RobMaskell
Copy link
Author

RobMaskell commented Mar 9, 2019

@gregturn I'm obviously being stoopid here, but if I'm using the fixed code, and x-forwarded-proto is working fine so I am using the fixed code, why am I still seeing issues with x-forwarded-host and x-forwarded-prefix?

@gregturn
Copy link
Contributor

gregturn commented Mar 9, 2019

Spring Boot now disables forwarded header handler by default. You have to enable it.

@RobMaskell
Copy link
Author

Sure I saw that so I used server.use-forward-headers=true to do it.

@gregturn
Copy link
Contributor

gregturn commented Mar 9, 2019

And it still doesn’t work?

@RobMaskell
Copy link
Author

Unless I have done something else wrong, it only half works, proto & port are fine, but host & prefix I can't get to work

@gregturn gregturn reopened this Mar 9, 2019
@gregturn
Copy link
Contributor

gregturn commented Mar 9, 2019

Don’t think you can include a port number with x-forwarded-host.

@RobMaskell
Copy link
Author

Yh I wondered about that but I think I just copied what I was getting from Spring Cloud Gateway (I'll have a look at that tomorrow and maybe raise something against that project) but with or without the port appended host doesn't work for me

@RobMaskell
Copy link
Author

And what I did have was working with Spring Boot 2.0, and associated version of Spring Cloud

@gregturn
Copy link
Contributor

To be precise, it's Spring Framework 5.1 and Spring HATEOAS 0.25.1/1.0.0 that requires this shift.

@RobMaskell
Copy link
Author

Yes and I my upgrade from Spring Boot 2.0.x to 2.1.3 has picked up Spring Framework 5.1 and Spring HATEOAS 0.25.1 which is when I noticed this issue.

I tried looking at the code and I wonder if it's the use of URIComponentsBuilder rather that the Servlet version that might be the issue as the former seems to still be accessing x-forwarded-* headers directly where the later explicitly mentions the forwarded headers centralisation in 5.1. But I'm no where near sure, just an idea.

@patbaumgartner
Copy link

Unfortunately, I have the same issue with spring-data-rest. The x-forwarded-prefix was set in the request but spring-data-rest does not render it in the response.

Spring Boot 2.1.3 -> Spring Data Rest Starter

I need to add server.use-forward-headers=true and then only x-forwarded-host (host:port) is rendered in the hypermedia document. If I do not set the property the x-forwarded headers are ignored.

@RobMaskell
Copy link
Author

@patbaumgartner did you actually see the host, not just the port, change in the SDR produced JSON after 2.1.3?

@patbaumgartner
Copy link

@RobMaskell I saw in SDR the host and the port changing. Which is fine. I am missing the x-forwarded-prefix which was not added to the SDR output.

I am using SDR with a Spring Cloud Netfilx Zuul setup and there the prefix was in the past by default the microservice name.

@GoldenToast
Copy link

GoldenToast commented Mar 18, 2019

@patbaumgartner
I have had the same problem. The solution was to use the ForwardedHeaderFilter. You have to register it with the @bean annotation.

@Bean public Filter forwardedHeaderFilter() { return new ForwardedHeaderFilter(); }

https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/web.html#filters-forwarded-headers --> "There are security considerations..."

@RobMaskell
Copy link
Author

@GoldenToast well I'll try it but that is what I thought the property I switched on above would do

@pietjan12
Copy link

@GoldenToast this fixed the problem for me, thanks alot!

@RobMaskell
Copy link
Author

@GoldenToast Thanks yes manual creation of that bean makes it work.

@gregturn I looked for auto config in Spring Boot, or anything in Spring itself for ForwardedHeaderFilter possibly based off the property server.use-forward-headers and there was nothing. So the question then becomes, in my example why were Proto and Port being changed at all... without the bean it should have been ignoring all the x-forwarded-* headers.

I still think something is slightly wrong here.

@gregturn
Copy link
Contributor

Okay, a little extra digging has uncovered:

  1. Spring Boot doesn't currently support all the X-Forwarded-* stuff through that property setting. The docs only list X-Forwarded-For and X-Forwarded-Proto supported by the existing property. Additionally, there are issues with each container regarding these de facto standard headers. Track Boot's support at => Consider using ForwardedHeaderFilter spring-boot#5677

  2. That being said, to enable X-Forwarded-* support, add this to your application:

@Bean
ForwardedHeaderFilter forwardedHeaderFilter() {
    return new ForwardedHeaderFilter();
}

...and Spring Boot will pick up the filter bean and register it with your Spring MVC app. (I don't have the WebFlux counterpart here).

  1. Once you put in this bean, then you can do stuff like this:
curl -v localhost:8080/employees \
    -H 'X-Forwarded-Host: example.com' \
    -H 'X-Forwarded-Port: 9001'  \
    | jsonpp

...and see...

{
  "_embedded": {
    "employees": [
      {
        "id": 1,
        "name": "Bilbo Baggins",
        "role": "burglar",
        "_links": {
          "self": {
            "href": "http://example.com:9001/employees/1"
          },
          "employees": {
            "href": "http://example.com:9001/employees"
          }
        }
      },
      {
        "id": 2,
        "name": "Frodo Baggins",
        "role": "ring bearer",
        "_links": {
          "self": {
            "href": "http://example.com:9001/employees/2"
          },
          "employees": {
            "href": "http://example.com:9001/employees"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://example.com:9001/employees"
    },
    "root": {
      "href": "http://example.com:9001"
    }
  }
}

Bottom line: this should be added to the reference docs so you don't have to dig around in the issues or stackoverflow to get it going.

@RobMaskell
Copy link
Author

x-forwarded-port defo working now as well but fair enough, thanks for the extra investigation, I guess this ticket will help for now

@odrotbohm
Copy link
Member

odrotbohm commented Mar 22, 2019

We've added a section to the reference documentation with #886 covering the header forwarding and the setup required to make it work again. Although currently only documented on master – i.e. for 1.0 – this should work on 0.25 as well. Feel free to comment suggestions for enhancements but bear in mind that we want to include as little information as possible as the actualy mechanism of activation is in Spring Framework / Spring Boot and we want to avoid repeating too much of it to avoid the information to diverge.

@patbaumgartner
Copy link

patbaumgartner commented Mar 22, 2019 via email

@gregturn
Copy link
Contributor

That's on purpose. We don't want to actively document in Spring HATEOAS something maintained in the Spring Framework.

You can open ForwardedHeaderFilter/ForwardedHeaderTransformer in your IDE and see the headers currently supported by Spring Framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants