Home ¦ Posts ¦ RSS

Testing NGINX HTTP/2 support

HTTP/2 and SPDY indicator showing HTTP/2 is active on this site

NGINX Inc. just made available a patch which adds preliminary, alpha-level support for HTTP/2 to their popular HTTP server. This is a significant event for the HTTP/2 adoption process considering the popularity of NGINX.

NGINX Inc. announced their plans back in February:

We’re pleased to announce that we plan to release versions of both NGINX and NGINX Plus by the end of 2015 that will include support for HTTP/2.

I'm currently trying out NGINX with HTTP/2 on this very blog. There are also other server alternatives out there, each one offering a different degree of maturity.

NGINX decided to implement HTTP/2 only over TLS, which is a trend followed by many of the early implementations. This means that you need a proper SSL certificate to test it, as well as a fairly recent (>= 1.0.2) version of OpenSSL with ALPN baked-in.

In order to use the new OpenSSL, you can statically link NGINX against it by following the instructions in the NGINX blog. You don't need to perform a system-wide installation, NGINX will conveniently compile and link against the OpenSSL sources specified with the parameter --with-openssl=/path/to/openssl-1.0.2d.

In my case, I did something slightly different. I had already installed OpenSSL packages from Ubuntu 15.10 because other software I'm testing requires a system-wide installation. For reference (but again, only for testing purposes):

$ mkdir OpenSSL; cd OpenSSL
$ REPO=https://launchpad.net/ubuntu/+archive/primary/+files
$ wget $REPO/openssl_1.0.2d-0ubuntu1_amd64.deb
$ wget $REPO/libssl1.0.0_1.0.2d-0ubuntu1_amd64.deb
$ wget $REPO/libssl-dev_1.0.2d-0ubuntu1_amd64.deb
$ wget $REPO/libssl-doc_1.0.2d-0ubuntu1_all.deb
$ sudo dpkg -i *.deb

Once you have followed the build instruction on the NGINX website you will be able to use the following configuration which will give you an HTTP/2-capable virtualhost, redirecting all non-SSL traffic to it.

server {
   listen       443 ssl http2;
   server_name  giuseppeciotta.net;

   ssl_certificate      /opt/nginx/ssl/giuseppeciottanet.crt;
   ssl_certificate_key  /opt/nginx/ssl/giuseppeciottanet.key;

   location / {
       root   /var/www/giuseppeciotta.net;
       index  index.html;
   }
}

server {
    listen       80;
    server_name  giuseppeciotta.net;
    return       301 https://$server_name$request_uri;
}

NGINX will fallback to HTTP/1.1 in case the HTTP/2 ALPN handshake fails.

Please note that there are more things to do in order to have a robust HTTPS configuration. Enabling HTTP Strict Transport Security, disabling SSLv3 or selecting appropriate ciphers just to mention a few. Here I'm showing the absolute minimum you need to do to be able to speak HTTP/2 with your server.

To verify your installation, you can browse your webserver using recent versions of Chrome or Firefox. They both support HTTP/2.

With Chrome, you should look for the "protocol" column in the browser developer tools. You can add it by right-clicking on the table headers if it's not there. If everything goes well it will display h2, the short name of the HTTP/2 protocol.

Chrome developer tools showing the h2 protocol used while browsing this server

With Firefox, you should look under the network pane for a response header called X-Firefox-Spdy, which will hold the h2 value for HTTP/2 connections. Please note that this header is put there by Firefox and it's not something returned by the server.

Firefox developer tools showing the h2 protocol used while browsing this server

There are also extensions for both browsers which show you the current protocol being used: HTTP/2 and SPDY indicator for Chrome and HTTP/2 and SPDY indicator for Firefox.

Finally, you can also test the low-level ALPN negotiation with the openssl binary (remember >= 1.0.2 only):

(echo | openssl s_client -alpn h2 -connect giuseppeciotta.net:443) | grep ALPN
...
ALPN protocol: h2

Please note that as of today, some HTTP/2 testing tools will check for earlier drafts of the protocol, which corresponds to ALPN protocol identifiers like h2-14, h2-15 and so on. The final revision of the RFC specifies that the final protocol identifier is h2, which is what NGINX uses.

Happy experimenting!

© Giuseppe Ciotta. Built using Pelican. Theme on github.