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

Value "wss" for HTTP Header "X-Forwarded-Proto" should be consistently handled #27084

Closed
jhyot opened this issue Jun 24, 2021 · 2 comments
Closed
Labels
for: external-project For an external project and not something we can fix status: invalid An issue that we don't feel is valid

Comments

@jhyot
Copy link

jhyot commented Jun 24, 2021

I have noticed that a HTTP(S) request with the header X-Forwarded-Proto: wss can cause problems in the Spring Boot web stack, at least with Tomcat + Spring MVC (+ Spring Websocket). X-Forwarded-Proto is not standardized, but nevertheless a heavily used header. In the past (or currently still) there seems to be an assumption that only "http" and "https" are valid values (see e.g. MDN and other sources when searching for the header name on the web).

But at least one popular proxy, Traefik, has decided to use "ws" and "wss" in the header, see traefik/traefik#6388. When using Traefik as a reverse proxy in front of Spring Boot, we ran into issues with Websockets because of incorrect or inconsistent handling regarding the said header in the web/servlet stack.

It would be good if Spring Boot could ensure via configuration, code, and/or working with upstream dependencies, that "wss" is handled consistently like "https" in all situations. Based on my observations I would propose that X-Forwarded-Proto: wss gets mapped into the ServletRequest.scheme value "https" (and "ws" -> "http") because that seems the most compatible way.

Putting "wss" into ServletRequest.scheme seems to lead to problems. A same-origin check that compares the value of the Origin header (where "https" would be the protocol) with the servlet request url would fail, as did happen for us in the Spring Websocket code. I also know of at least one library that fails completely when it encounters scheme=wss in the ServletRequest object.

The following examples show the instances of incorrect/inconsistent handling of the header that we found during debugging our problem. There might be other places.

Tomcat RemoteIpValve

If server.forward-headers-strategy is set to "native", then Spring Boot adds the RemoteIpValve to Tomcat. This valve currently maps a "wss" header to scheme=http, secure=false. This is clearly incorrect.

Note that Tomcat has added handling for "ws" and "wss" into their websocket code (i.e. they have recognized the issue as well): apache/tomcat#311. But there remain hardcoded checks in other places as shown above. I've not opened an issue with Tomcat, since I thought to leave it for you to decide how and where to handle this issue.

Spring Web

If server.forward-headers-strategy is set to "framework", then Spring Boot registers a ForwardedHeaderFilter. This filter and its dependency UriComponentsBuilder.fromHttpRequest(request) have hardcoded checks for "http" and "https" in multiple places ([1], [2]), but leaves an unrecognized X-Forwarded-Proto value alone. Depending on which other X-Forwarded headers are present, it maps a https/wss request on port 443 to the following servlet properties: scheme=wss, port=80, secure=false or scheme=wss, port=443, secure=false. This is incorrect, and as mentioned before, scheme=wss does not seem very compatible anyway.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jun 24, 2021
@wilkinsona
Copy link
Member

Thanks for the report but, as you have identified, this is out of Spring Boot's control. While we could open issues with Tomcat and Spring Framework, it would be better for you to do so. You have real-world experience of the problem and can provide any details the Tomcat and Spring Framework teams may need without someone on the Spring Boot team slowing things down and possibly introducing inaccuracies while acting as an intermediary.

@wilkinsona wilkinsona added for: external-project For an external project and not something we can fix status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 24, 2021
@jhyot
Copy link
Author

jhyot commented Jun 24, 2021

For reference: spring-projects/spring-framework#27097

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

3 participants