33

I have a problem with my Nginx configuration. I upgraded to nginx 1.9.6 to test http/2 but it does not work on my server.

I used ubuntu 14.04.2 LTS

This is the nginx -V output :

nginx version: nginx/1.9.6
built with OpenSSL 1.0.2d 9 Jul 2015
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-pcre-jit --with-debug --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_realip_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module --with-http_v2_module --with-stream --with-ipv6 --with-mail --with-mail_ssl_module --with-openssl=/build/nginx-GFP362/nginx-1.9.6/debian/openssl-1.0.2d --add-module=/build/nginx-GFP362/nginx-1.9.6/debian/modules/nginx-auth-pam --add-module=/build/nginx-GFP362/nginx-1.9.6/debian/modules/nginx-echo --add-module=/build/nginx-GFP362/nginx-1.9.6/debian/modules/nginx-upstream-fair --add-module=/build/nginx-GFP362/nginx-1.9.6/debian/modules/nginx-dav-ext-module --add-module=/build/nginx-GFP362/nginx-1.9.6/debian/modules/nginx-cache-purge

And this is my vhost config :

server {
    listen         80;
    server_name    localhost;
    return         301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2; ## listen for ipv4; this line is default and implied

    root /var/www/rendez-vous;
    index index.phtml index.html index.htm;

    # Make site accessible from http://localhost/
    server_name localhost;
    ssl_certificate /etc/nginx/certificates/myeventsportal/server.crt;
    ssl_certificate_key /etc/nginx/certificates/myeventsportal/server.key;

/...

If I navigate to my site with the latest version of chrome, it is only served over http/1.1.

4
  • 1
    Have you checked the caveats section on nginx.com/blog/nginx-1-9-5
    – Drifter104
    Commented Oct 29, 2015 at 12:00
  • Did you wipe your browser cache? Try from an Incognito Window.
    – JayMcTee
    Commented Oct 29, 2015 at 13:58
  • The incognito Window change nothing. I read the caveat section and the only part is the ssl_prefer_server_ciphers but i have not handshake error
    – throrin19
    Commented Oct 29, 2015 at 15:52
  • This is caused by the header sent from the web server is your web server configured to send HTTP/2.0 Commented Nov 2, 2015 at 17:14

3 Answers 3

54
+50

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 RFC7301 ALPN 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):

Test with ALPN:

echo | openssl s_client -alpn h2 -connect yourserver.example.com:443 | grep ALPN

If ALPN is working, you should see:

ALPN protocol: h2

otherwise you'll get:

No ALPN negotiated

Test with NPN:

echo | openssl s_client -nextprotoneg h2 -connect yourserver.example.com:443

If that works, you will get:

Next protocol: (1) h2
No ALPN negotiated

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:

Chrome HTTP/2 info

11
  • I just noticed that you are already running openssl 1.0.2d - but the tests may still prove useful.
    – Synchro
    Commented Nov 3, 2015 at 12:59
  • My nginx package is compiled with the latest openssl version but ubuntu 14.04 has an outdated version. If i remember, it's the 1.0.1f
    – throrin19
    Commented Nov 3, 2015 at 13:56
  • Yes, that's what I said.
    – Synchro
    Commented Nov 3, 2015 at 13:57
  • 1
    For the first command, i got an error unknown option -alpn and the second command works fine
    – throrin19
    Commented Nov 3, 2015 at 14:09
  • 2
    What's the status of this now, at the edge of 2016? I still see nginx not serving files as HTTP2
    – vsync
    Commented Dec 30, 2016 at 21:31
3

Short version.

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.

For instructions on how to turn off SSL/TLS in ESET, check out http://support.eset.com/kb3126/?locale=en_US

3
  • 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
    – Dev
    Commented Sep 21, 2018 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. Commented Nov 20, 2018 at 20:30
  • 1
    I have opened a support ticket at forum.eset.com/topic/… Commented Nov 22, 2018 at 11:28
1

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .