April 11, 2015

Negotiating HTTP/2

ALPN And The TLS Handshake

The HTTP/2 specification was approved on February 18, 2015 and implementation has already begun. In this post, I'll attempt to explain how HTTP/2 will be negotiated in today's web.

TL;DR: HTTP/2 in the browser uses ALPN to extend TLS by including the protocol negotiation in the exchange of hello messages. The client provides a list of protocols it speaks and the server responds with its selected protocol. No additional round-trip required.

A Little Background On HTTP/2

As a front-end developer, the main benefit of HTTP/2 is the evaporation of the cost of multiple HTTP requests. With HTTP/2, once a connection has been negotiated, the server can push resources over the existing connection that it knows a client will need without waiting for the client to ask for them. Further, HTTP introduces multiplexing, which eliminates the "head-of-line blocking" problem—where a single transaction can prevent other transactions from taking place—by allowing for multiple requests and responses to be in transit simultaneously.

To address these issues in HTTP/1, a number of tactics have been used to reduce the number of HTTP requests like the concatenation of static assets and image spriting. Domain sharding is another hack used to overcome the limitations of HTTP/1, which restricts the number of connections allowed for a given host. Perhaps with the advent of HTTP/2, these practices will soon be seen as anachronisms of a fledgling internet!

The Handshake

When an HTTP/2 connection is negotiated with the browser as the client, two separate concerns need to be addressed:

  1. Agree on a protocol
  2. Establish a secure connection

Agreeing On A Protocol

Since clients and servers may speak different versions of HTTP, it is necessary to establish an agreed upon version for each connection. Here is how Daniel Stenberg explains the negotiation over unencrypted HTTP in his excellent introduction to HTTP/2:

[The client makes a request to] the server with an Upgrade: header. If the server speaks http2 it responds with a "101 Switching" status and from then on it speaks http2 on that connection. You of course realize that this upgrade procedure costs a full network round-trip, but the upside is that a http2 connection should be possible to keep alive and re-use to a larger extent than HTTP1 connections generally are.

If the server in the above example doesn't speak HTTP/2, it will ignore the header and respond normally.

This explanation describes the protocol negotiation over unencrypted HTTP, but since Chrome and Firefox have both stated that they will only be implementing HTTP/2 over TLS, for the purposes of web development, this might as well be a requirement of the protocol.

Establishing a Secure Connection

To understand how HTTP/2 will be negotiated over TLS, it is useful to know a little about the TLS handshake. Here's a summary of the process from the TLS specification:

  • Exchange hello messages to agree on algorithms, exchange random values, and check for session resumption.

  • Exchange the necessary cryptographic parameters to allow the client and server to agree on a premaster secret.

  • Exchange certificates and cryptographic information to allow the client and server to authenticate themselves.

  • Generate a master secret from the premaster secret and exchanged random values.

  • Provide security parameters to the record layer.

  • Allow the client and server to verify that their peer has calculated the same security parameters and that the handshake occurred without tampering by an attacker.

This handshake happens over two round-trips, with additional steps to verify the validity of certificates being optional. If a client has a previous session cached, an abbreviated handshake can be used, allowing a secure connection to be established in a single round trip.

Enter: The Application-Layer Protocol Negotiation

Rather than agreeing on a protocol and establishing a secure connection in separate steps, HTTP/2 seeks to batch these concerns into a single step using a TLS extension called the Application-Layer Protocol Negotiation (ALPN).

The ALPN extension seeks to avoid an additional network round-trip by bundling the protocol negotiation with the exchange of hello messages. As part of the initial request (ClientHello), the client provides a list of protocols which it supports. The server then selects a protocol from that list and sends that selection back to the client along with its part of the TLS handshake (ServerHello). For previously established connections, the protocol selection can be negotiated over an abbreviated hand shake.

What's The Big Deal?

Modern sites often require dozens of connections to serve even more objects. Over TLS, each of those connections requires an additional handshake. With HTTP/2, all of the content from a single host can be served over a single connection. This eliminates not only the need to open and close of each additional connection, but also the need for an additional TLS handshake per connection.

HTTP/2 is more than a big win in the battle against latency, it's a big win for security too.