HTTP2 and Spring Boot

Introduction

HTTP2 is the successor of HTTP/1.1. It enables faster connections, multiplexing and server pushes via TCP. It’s not a completely new protocol, it’s more an evolutionary step to improve HTTP/1.1 that has been in use since 1999. Since that year, many thing have changed: more users, more content, more cyber crime. So, it’s quite obvious that also security issues are in the focus of HTTP2.

In this blog I want to take a closer view on how HTTP2 can be used in a Spring Boot environment. As reference, I set up a project you can see on github: https://github.com/ollihoo/http2go

HTTP2 – the security basics

The RFC7540 has a separate section concerning security. You can find several hints on why the standard recommends secured communication. HTTP2 works on TLS (Transport Layer Security). This on the first glance is no news. But in fact there is something new, it’s TLS ALPN („TLS application-layer negotiation“). This has some impact on (not only) Spring Boot applications. See more details in the next section.

So, HTTP2 definitely says that there CAN be a communication without TLS. Don’t forget the client side: most browsers only support secured HTTP2 communication. Of course, there are ways to avoid TLS, but at the moment it seems that browsers make „h2″/TLS mandatory.

Spring Boot and HTTP2

First of all, not every (servlet) container does support HTTP2 yet. Spring Boot’s standard container Tomcat starts support with Tomcat 9 (not yet released by 1 July 2016). Luckily, Jetty and Undertow already support HTTP2, both can be used by Spring Boot alternatively.

The second challenge concerns TLS ALPN. This protocol isn’t supported by Java JDK 7 and 8. Java JDK 9 is told to natively support TLS ALPN. For Java 7 and 8, there is already a workaround. Unfortunately this support has to be injected during Java VM start. You will find more information later in this blog.

In summary there are four steps to do:

replace tomcat by Undertow

configure Undertow

create a keystore with a server key pair (optionally signed to avoid well-known alerts in browsers)

Replace Tomcat by Undertow

That’s quite simple. This is done by excluding tomcat from spring-boot-starter-web package and adding the spring-boot-starter-undertow package instead. This example shows the gradle configuration (build.gradle). The same way also works in Maven POM:

Okay, assume Undertow is configured. But Spring Boot still wouldn’t work, because there is no key pair needed for TLS. So, let’s create the Keystore.

Create Keystore

Spring Boot can include most options and needed files by a resources directory. We also use that for the keystore. You should replace the keystore.jks file in the reference project. More information about this key generation can be found in the reference’s README.md. The most important step is shown here.

As a result, you should find a new keystore.jks file. Make sure, it is referenced in the application.properties with it’s storepass and keypass to grant access.

Does it run now? Well, yes. But without HTTP2. There is another step to do.

Inject ALPN standard in Java 8

AS already mentioned, HTTP2 uses a new protocol called TLS ALPN (TLS application-layer protocol negotiation). This is the protocol that is also defined in application.properties:

server.ssl.protocol: TLSv1.2

The really last step is now to inject a library called org.mortbay.jetty.alpn:alpn-boot into the JVM. The procedure again is described in the README.md.

The correct alpn-boot library is defined by the JDK you are using. You can find out your version by typing java -version in the command line. Please download the library and make it easily reachable for your Application callup. With the command

This command starts Spring Boot application. The option -Xbootclasspath/p: ensures the integration of TLS ALPN into the security layer. The reason for this complicated way is caused by the lack of an configurable API to the security layer in the Java standard library.

So, Spring Boot is configured to offer HTTP2 endpoints. Try it by starting the reference project.

By simply starting „http://localhost:8080/“ in Firefox, you should see an response header like this:

As you can see here, the protocol used is HTTP/2.0. Awesome. And you see the used protocol „h2“ that is listed in header field „X-Firefox-Spdy“. So this works well.

One last hint: Undertow offers fallback mechanisms that switch back to HTTP/1.1 when there is now ALPN available. There might be more things that cause that. To ensure that your application runs on HTTP2 care about tests.

Summary

HTTP2 is not yet an established standard in web containers. The lack of good support of TLS ALPN makes the delivery more complex than needed. But it’s possible. So, try the future.

There are questions? Let me know! Contact me by mail: oliver at hoogvliet.de