3 Answers
3

I've just run into the same problem, but I think I know why it happens. nginx 1.9.6 is not a stock package on Ubuntu 14.04, so you're probably getting it from an nginx PPA. That's fine, but those packages are built with the stock libraries from 14.04, which is to say OpenSSL 1.0.1f. Unfortunately that version of OpenSSL does not contain RFC7301ALPN support which is needed for proper HTTP/2 negotiation; it only supports the now-deprecated NPN. It looks like Chrome has already removed support for NPN, so it's incapable of negotiating an HTTP/2 connection without ALPN. Firefox 41 on the other hand, still has NPN support and you should be able to use HTTP/2 with that.

You can test your server like this - you will need OpenSSL 1.0.2d installed on your client (run openssl version to check):

That means that it's successfully negotiating an HTTP/2 connection via NPN, which is what Firefox does.

So how to solve this? The only way I can see is to install a later build of openssl from a PPA (I use this one for PHP, which also contains openssl) and build your own nginx linked to it. You can find the config params for your existing nginx build by running nginx -V, and you should be able to use that to build your own version.

Update: I've discovered that the reason that Chrome doesn't support HTTP/2 with NPN is not that it doesn't support NPN (though it will be dropped at some point), but that it specifically doesn't support h2 with NPN, as shown on the chrome://net-internals/#http2 page:

I found that ESET antivirus can prevent HTTP/2 from working when SSL/TLS filtering is turned on, on the browsing computer. Check to see that your antivirus is not filtering the SSL/TLS.

TLDR version

I ran into the same problem as the poster, but with an interesting twist. I upgraded my server configuration to nginx 1.12.1. compiled with OpenSSL 1.0.2.g and on initial inspection it had “solved” the problem of HTTP/2 not working. In my browser, I could see that the server certificate was verified by Let’s Encrypt. Content was also being served with HTTP/2.

Some time later, I found that the very same page and same resources were no longer being served over HTTP/2. Coincidentally, the site was no longer verified by Let’s Encrypt, but by Eset?!!?! To my amazement, the new http2 problem had nothing to do with my server configuration at all. It turned out that I had SSL/TLS filtering on in my antivirus on my local computer and this was causing the issue. The solution was to turn off SSL/TLS filtering in the antivirus. Once I had turned it off (and rebooted the computer) HTTP/2 worked again and the certificate was verified by Let’s Encrypt again.

This was the issue in my case. Saved me from insanity as it was working in one browser(which was not filtered by firewall) but not in any other
– DevSep 21 '18 at 11:42

You are a super genius. It was ESET and I had spent my 4 days in finding the problem. I just tried everything possible in this world of Linux. I just can't believe it was ESET and I was hammering my VPS.
– Abdul Jabbar WebBestowNov 20 '18 at 20:30

As Synchro says in his answer, the issue is most nginx packages are not built with OpenSSL 1.0.2. Compilation of ALPN requires symbols only present in the relevant OpenSSL development source.

You could try using the official nginx distribution, selecting xenial rather than trusty. This works for me with Debian Jessie and jessie-backports OpenSSL 1.0.2 - it may work for you. However, be aware that it is an unsupported configuration - rebuilding it is the "right" answer.