Skip to content

HTTP/2 and modern TLS support #10043

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

Closed
bclozel opened this issue Aug 18, 2017 · 8 comments
Closed

HTTP/2 and modern TLS support #10043

bclozel opened this issue Aug 18, 2017 · 8 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@bclozel
Copy link
Member

bclozel commented Aug 18, 2017

This is an umbrella issue for HTTP/2 and modern TLS configurations in Spring Boot.

There are a few requirements for running an HTTP/2 server on the JVM:

  1. the embedded server supports TLS 1.2+
  2. the application is properly configured with TLS 1.2+
  3. a certificate that checks the TLS requirements (key length, cipher suite...)

TLS 1.2 support can be achieved in different ways:

  • run the application on JDK9; this might be an easy solution, but it can also be a showstopper for some and this is limited to TLS 1.2, while 1.3 is already being deployed on big infrastructures
  • use "hacks" that replace the JDK TLS implementation; one can do that with a java agent, overriding the boot classpath, etc. This can be a challenge when running the application, depending on the target environment
  • use native bindings; quite well supported already, this also brings additional constraints to environments. But it's more likely to be up-to-date with the latest TLS versions and CVEs

We should consider the following:

  • when possible, we should have a common approach for all supported HTTP servers, as well as MVC and WebFlux
  • we might have to revisit configuration defaults in TLS; we can't certainly push everyone to TLS 1.2 right now, but some certificate requirements are already enforced by browsers for HTTP 1.1
  • maybe we should enabled HTTP/2 by default, i.e. no "http2.enabled" configuration key; we could just detect if the environment supports it and also derive it from the SSL configuration. Explicitely configuring TLS 1.2+ in the SSL configuration key is quite a strong signal already. AFAIU configuring HTTP/2 does not preclude from using HTTP 1.1; on the other hand, clients supporting TLS 1.2+ are quite likely to be HTTP/2 compatible anyway.
  • the setup is likely to be complex, so we should help as much as possible developers with that; we might have to implement new failure analysers
  • we should follow the 12-factor approach and think about deployment concerns (native libraries and/or java agents, jdk constraints)

Note: this issue is not about the Servlet 4.0 support, which is not a requirement for this.

There are already quite a few PRs and issues, but we should decide on a global approach first, and then cherry-pick from those the bits we need: #3350 #3904 #7376 #9431 #9964 #9981 #10041

@olamy
Copy link
Contributor

olamy commented Aug 21, 2017

well I'm not sure about the " i.e. no "http2.enabled" configuration key "
how do you detect users want to use http2?

@bclozel
Copy link
Member Author

bclozel commented Aug 25, 2017

I asked myself those two questions (maybe I'm missing something?):

  1. What happens if you enabled that option but your setup is wrong (wrong TLS version, ciphers, certificate)? You enabled it but it's not working anyway
  2. Is there any situation where you've got all the appropriate onfiguration (again, TLS, etc) but you don't want to support HTTP/2?

In my opinion, in the first case the boolean flag gives the false impression that flipping that flag is all that you need. In the second case, if your HTTP clients support a modern TLS configuration, they will support HTTP/2 anyway.

@olamy
Copy link
Contributor

olamy commented Aug 28, 2017

Well you can use HTTP/2 without ssl. I reckon it's maybe a non usual case as it won't work for browsers. But it can be a use case with APIs only related projects (company internal project to exchange data without need of ssl)

@pvorb
Copy link
Contributor

pvorb commented Sep 20, 2017

@olamy Yes, HTTP/2 without TLS is definitely a use case for using it in your cloud environment (e.g. through Spring Cloud Netflix) where you might not want to manage TLS certificates for services that don't provide public APIs.

@bclozel, @philwebb As you added milestones for this issue, what will be left to do once I have HTTP/2 including TLS working on JDK 9 on all supported Servlet Containers and after I remove the http2.enabled property and enable it by default? (See #9981)

@bclozel
Copy link
Member Author

bclozel commented Sep 20, 2017

@pvorb Your contribution is very useful, but you seem to think that the requirements you've settled on are the ones Spring Boot will choose.

As far as I know, we're still in the process of figuring out what should be the minimum requirements , configuration keys, supported runtimes and deployment model. Those are all tradeoffs.

In the case of Jetty, requiring JDK9 is just an option. We could still go with the bootClasspath or java agent solutions. Or we could even look into the recent integration with native libraries.

@pvorb
Copy link
Contributor

pvorb commented Sep 20, 2017

@bclozel I see my question was a little too direct and misleading. I'm just trying to provide one possible solution that works across all containers. I understand that's not necessarily the way Spring Boot will go in the end.

What I'm looking for is additional feedback for my PR upon which I can further improve the solution.

As far as I know, we're still in the process of figuring out what should be the minimum requirements , configuration keys, supported runtimes and deployment model. Those are all tradeoffs.

Is there some publicly available discussion around these topics? I can't see much progress in the issues and PRs that were linked above.

@olamy
Copy link
Contributor

olamy commented Sep 20, 2017

IMHO springboot shouldn't focus or try to have a common way to configure TLS 1.2. As you can see there are so many options available for each container and it could/will be a pain to have a standard for that :-)
IMHO users should be able to configure as they prefer....
Do you want to introduce any springboot configuration for configuring bootClasspath or java agent?

@bclozel
Copy link
Member Author

bclozel commented Nov 3, 2017

Here's my current take on this:

We should introduce a server.http2.enabled configuration property; I know I didn't want to do that previously and many of you were in favor of that (Sorry!). I thought that we could get away with enabling HTTP/2 by default as soon as TLS1.2 is supported, but this is much more complex than that and this logic really belongs to the web server.

In this issue, we'll cover only Tomcat and Undertow for now; Jetty is scheduled for #10902 (waiting for Jetty 4.3.8 for official support - I got it to work with SNAPSHOTs already), and Reactor Netty doesn't support HTTP/2 yet.

Tomcat

Spring Boot 2.0 ships by default with Tomcat 8.5; with that version, HTTP/2 is only supported if the libtcnative library and its dependencies are installed on the host.

For now, starting a Tomcat 8.5 without that native support logs the following error (but the application still starts):

ERROR 8787 --- [           main] o.a.coyote.http11.Http11NioProtocol      : 
    The upgrade handler [org.apache.coyote.http2.Http2Protocol] 
    for [h2] only supports upgrade via ALPN but has been configured for 
    the ["https-jsse-nio-8443"] connector that does not support ALPN.

I don't know if we should somehow detect that error and fail the application or leave this as it is.

Overriding the tomcat.version to 9.0.1 and running the app with JDK9 works as well, without any native library installed.

Undertow

As of Undertow 1.4, HTTP/2 is supported out of the box without any strong requirement.
As long as Spring Boot developers don't downgrade the version, things should work.

bclozel added a commit that referenced this issue Nov 3, 2017
This commits adds the AprLifecycleListener as a default
LifecycleListener in order to detect and use automatically the
tomcatnative library if it is available, for SSL support.

This feature can be useful for both performance reasons or for
supporting ALPN when using JDK8.

See gh-10043
Closes gh-9964
bclozel added a commit that referenced this issue Nov 3, 2017
This commit adds a new configuration properties class for configuring
HTTP/2 protocol support.
By default, this protocol is disabled as enabling it requires several
manual changes:

* configuring a web server for proper TLS and ALPN support
* configuring a proper SSL certificate

See gh-10043
@bclozel bclozel closed this as completed in bb9396e Nov 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

4 participants