配置了 http2 的 Nginx 无法提供 HTTP/2

配置了 http2 的 Nginx 无法提供 HTTP/2

我的 Nginx 配置有问题。我升级到 nginx 1.9.6 来测试 http/2,但它在我的服务器上不起作用。

我使用的是 ubuntu 14.04.2 LTS

这是 nginx -V 输出:

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

这是我的 vhost 配置:

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;

/...

如果我使用最新版本的 chrome 导航到我的网站,它仅通过 http/1.1 提供服务。

答案1

我刚刚遇到了同样的问题,但我想我知道为什么会发生这种情况。nginx 1.9.6 不是 Ubuntu 14.04 上的库存包,所以你可能从nginx PPA。这很好,但这些软件包是使用 14.04 版的库存库构建的,也就是说 OpenSSL 1.0.1f。不幸的是,该版本的 OpenSSL 不包含RFC7301 阿尔及利亚国家铁路网络支持正确的 HTTP/2 协商;它仅支持现已弃用的 NPN。Chrome 似乎已经取消了对 NPN 的支持,因此它无法在没有 ALPN 的情况下协商 HTTP/2 连接。另一方面,Firefox 41 仍然支持 NPN,您应该能够使用 HTTP/2。

您可以像这样测试您的服务器 - 您需要在客户端上安装 OpenSSL 1.0.2d(运行openssl version检查):

使用 ALPN 进行测试:

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

如果 ALPN 正常工作,您应该会看到:

ALPN protocol: h2

否则你会得到:

No ALPN negotiated

使用 NPN 进行测试:

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

如果有效,您将获得:

Next protocol: (1) h2
No ALPN negotiated

这意味着它成功通过 NPN 协商 HTTP/2 连接,这正是 Firefox 所做的。

那么如何解决这个问题?我能想到的唯一方法是从 PPA 安装更高版本的 openssl(我使用这个适用于 PHP,其中还包含 openssl) 并构建链接到它的自己的 nginx。您可以通过运行 找到现有 nginx 构建的配置参数nginx -V,并且您应该能够使用它来构建您自己的版本。

更新:我发现 Chrome 不支持带有 NPN 的 HTTP/2 的原因并不是它不支持 NPN(尽管它在某个时候会被放弃),而是它特别不支持带有 NPN 的 h2,如 chrome://net-internals/#http2 页面所示:

Chrome HTTP/2 信息

答案2

简洁版本。

我发现,在浏览计算机上启用 SSL/TLS 过滤时,ESET 防病毒软件会阻止 HTTP/2 运行。检查您的防病毒软件是否未过滤 SSL/TLS。


TLDR 版本

我遇到了与发帖人相同的问题,但有一个有趣的变化。我将服务器配置升级到 nginx 1.12.1。使用 OpenSSL 1.0.2.g 编译,初步检查发现它“解决”了 HTTP/2 无法正常工作的问题。在我的浏览器中,我可以看到服务器证书已通过 Let's Encrypt 验证。内容也通过 HTTP/2 提供。

一段时间后,我发现同一个页面和资源不再通过 HTTP/2 提供。巧合的是,该网站不再由 Let's Encrypt 验证,而是由 Eset 验证?!?!令我惊讶的是,新的 http2 问题与我的服务器配置完全无关。原来,我在本地计算机上的防病毒软件中启用了 SSL/TLS 过滤,这导致了问题。解决方案是关闭防病毒软件中的 SSL/TLS 过滤。关闭后(并重新启动计算机),HTTP/2 再次正常工作,证书再次由 Let's Encrypt 验证。

有关如何在 ESET 中关闭 SSL/TLS 的说明,请查看http://support.eset.com/kb3126/?locale=en_US

答案3

正如 Synchro 在他的回答中所说,问题是大多数 nginx 包不是用 OpenSSL 1.0.2 构建的。ALPN 的编译需要符号仅存在于相关的OpenSSL开发源中。

您可以尝试使用官方 nginx 发行版,选择 xenial 而不是 trusty。对于我来说,Debian Jessie 和 jessie-backports OpenSSL 1.0.2 可以解决这个问题 - 对您来说可能也行得通。但是,请注意,这是一个不受支持的配置 - 重建它是“正确”的答案。

相关内容