O Nginx configurado com http2 não fornece HTTP / 2

33

Estou com um problema na minha configuração do Nginx. Atualizei para o nginx 1.9.6 para testar o http / 2, mas ele não funciona no meu servidor.

Eu usei o Ubuntu 14.04.2 LTS

Esta é a saída 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

E esta é a minha configuração de 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;

/...

Se eu navegar para o meu site com a versão mais recente do chrome, ela será veiculada apenas em http / 1.1.

throrin19
fonte
1
Você já conferiu a seção de advertências em nginx.com/blog/nginx-1-9-5
Drifter104
Você limpou o cache do navegador? Tente em uma janela anônima.
JayMcTee
A janela anônima não muda nada. Eu li a seção de advertência e a única parte é o ssl_prefer_server_ciphersmas eu tenho erro não aperto de mão
throrin19
Isto é causado pelo cabeçalho enviado do servidor web é o seu servidor web configurado para enviar HTTP / 2.0
Martin Barker

Respostas:

50

Acabei de encontrar o mesmo problema, mas acho que sei por que isso acontece. O nginx 1.9.6 não é um pacote de ações no Ubuntu 14.04, então você provavelmente está obtendo um PPA do nginx . Tudo bem, mas esses pacotes são construídos com as bibliotecas de estoque da 14.04, ou seja, OpenSSL 1.0.1f. Infelizmente, essa versão do OpenSSL não contém suporte RFC7301 ALPN, necessário para uma negociação HTTP / 2 adequada; ele suporta apenas o NPN agora obsoleto. Parece que o Chrome já removeu o suporte ao NPN, portanto, é incapaz de negociar uma conexão HTTP / 2 sem o ALPN. O Firefox 41, por outro lado, ainda tem suporte a NPN e você deve poder usar HTTP / 2 com isso.

Você pode testar seu servidor como este - precisará do OpenSSL 1.0.2d instalado no seu cliente (execute openssl versionpara verificar):

Teste com ALPN:

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

Se o ALPN estiver funcionando, você deverá ver:

ALPN protocol: h2

caso contrário, você receberá:

No ALPN negotiated

Teste com NPN:

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

Se isso funcionar, você receberá:

Next protocol: (1) h2
No ALPN negotiated

Isso significa que está negociando com êxito uma conexão HTTP / 2 via NPN, que é o que o Firefox faz.

Então, como resolver isso? A única maneira que eu posso ver é instalar uma versão posterior do openssl a partir de um PPA (eu uso essa para o PHP, que também contém o openssl) e criar seu próprio nginx vinculado a ele. Você pode encontrar os parâmetros de configuração para a sua compilação nginx existente executando nginx -V, e poderá usá-la para criar sua própria versão.

Atualização : eu descobri que o motivo pelo qual o Chrome não suporta HTTP / 2 com NPN não é que ele não é compatível com NPN (embora seja descartado em algum momento), mas que especificamente não suporta h2 com NPN, como mostrado na página chrome: // net-internals / # http2:

Informações HTTP / 2 do Chrome

Synchro
fonte
Acabei de notar que você já está executando o openssl 1.0.2d - mas os testes ainda podem ser úteis.
Synchro
Meu pacote nginx é compilado com a versão mais recente do openssl, mas o ubuntu 14.04 tem uma versão desatualizada. Se eu me lembro, é o 1.0.1f
throrin19 /
Sim, foi o que eu disse.
Synchro
Para o primeiro comando, eu tenho um erro unknown option -alpne o segundo comando funciona bem
throrin19
2
Qual é o status disso agora, no final de 2016? Ainda vejo o nginx não servindo arquivos como HTTP2
vsync
3

Versão curta.

Descobri que o antivírus ESET pode impedir que o HTTP / 2 funcione quando a filtragem SSL / TLS está ativada no computador de navegação. Verifique se o seu antivírus não está filtrando o SSL / TLS.


Versão TLDR

Encontrei o mesmo problema que o pôster, mas com uma reviravolta interessante. Atualizei a configuração do meu servidor para o nginx 1.12.1. compilado com o OpenSSL 1.0.2.g e na inspeção inicial, havia "resolvido" o problema do HTTP / 2 não funcionar. No meu navegador, pude ver que o certificado do servidor foi verificado pelo Let's Encrypt. O conteúdo também estava sendo veiculado com HTTP / 2.

Algum tempo depois, descobri que a mesma página e os mesmos recursos não estavam mais sendo servidos por HTTP / 2. Por coincidência, o site não foi mais verificado pelo Let's Encrypt, mas pelo Eset? !!?! Para minha surpresa, o novo problema do http2 não teve nada a ver com a configuração do meu servidor. Aconteceu que eu estava com a filtragem SSL / TLS no meu antivírus no meu computador local e isso estava causando o problema. A solução foi desativar a filtragem SSL / TLS no antivírus. Depois de desligá-lo (e reiniciar o computador), o HTTP / 2 funcionou novamente e o certificado foi verificado pelo Let's Encrypt novamente.

Para obter instruções sobre como desativar o SSL / TLS no ESET, consulte http://support.eset.com/kb3126/?locale=en_US

TryHarder
fonte
Este foi o problema no meu caso. Me salvou de insanidade, uma vez que estava trabalhando em um navegador (o que não foi filtrado pelo firewall), mas não em qualquer outro
Dev
Você é um super gênio. Era a ESET e eu havia passado meus quatro dias encontrando o problema. Eu apenas tentei todo o possível neste mundo do Linux. Eu simplesmente não posso acreditar que era a ESET e estava martelando meu VPS.
Abdul Jabbar WebBestow
1
Abri um tíquete de suporte em forum.eset.com/topic/…
Abdul Jabbar WebBestow
1

Como Synchro diz em sua resposta, o problema é que a maioria dos pacotes nginx não são criados com o OpenSSL 1.0.2. A compilação do ALPN requer símbolos apenas presentes na fonte de desenvolvimento OpenSSL relevante.

Você pode tentar usar a distribuição oficial do nginx , selecionando xenial em vez de confiável. Isso funciona para mim com o Debian Jessie e o jessie-backports OpenSSL 1.0.2 - pode funcionar para você. No entanto, esteja ciente de que é uma configuração não suportada - reconstruí-la é a resposta "correta".

GreenReaper
fonte