Como evitar o redirecionamento do nginx de HTTPS para HTTP na AWS?

2

Eu tenho um site veiculado pela nginx atrás de um balanceador de carga do AWS ELB. Apenas HTTPS está ativado no balanceador de carga.

Solicitar arquivos individuais ou diretórios com uma barra final funciona bem. No entanto, solicitar diretórios sem uma barra final não funciona.

A razão é que, quando eu solicito o diretório sem a barra final, nginx redireciona para o caminho com a barra final (tudo bem), mas também muda de HTTPS para HTTP. O balanceador de carga está configurado para permitir apenas HTTPS, de modo que não funcione (tempo limite).

No arquivo de log do nginx, posso ver que a solicitação atinge nginx e que é o nginx que responde com o Redirecionamento permanente 301 (portanto, não é um problema com a configuração do balanceador de carga).

10.100.10.15 - - [24/Nov/2017:15:41:08 +0000] "GET /admin HTTP/1.1" 301 178 "-" "Wget/1.18 (darwin16.0.0)"

Quando eu solicito o URL por meio de curl , vejo o redirecionamento:

$ curl -v https://example.com/admin
*   Trying 1.2.3.4...
* TCP_NODELAY set
* Connected to example.com (1.2.3.4) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: example.com
* Server certificate: Amazon
* Server certificate: Amazon Root CA 1
* Server certificate: Starfield Services Root Certificate Authority - G2
> GET /admin HTTP/1.1
> Host: example.com
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Date: Mon, 27 Nov 2017 09:19:05 GMT
< Content-Type: text/html
< Content-Length: 178
< Connection: keep-alive
< Server: nginx
< Location: http://example.com/admin/
< X-UA-Compatible: IE=Edge
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host example.com left intact

Meu arquivo de configuração do nginx é apenas

server {
    root /var/www;
}

O /etc/nginx/nginx.conf é aqui .

Eu tentei server_name_in_redirect off , mas isso não fez diferença alguma.

Eu gostaria de evitar colocar o nome do host no arquivo de configuração, porque ele é empacotado em uma imagem do Docker que é então implementada em hosts diferentes (QA, Prod, etc.).

Eu gostaria que o nginx fizesse esse redirecionamento, mas fique em HTTPS. O que posso fazer?

    
por Adrian Smith 24.11.2017 / 17:09

3 respostas

3

O melhor lugar para corrigir o problema é onde a conexão SSL é finalizada. Se estivesse executando nginx , você usaria uma instrução proxy_redirect para mapear http to https no cabeçalho Location . Não conheço o AWS ELB, por isso não posso comentar como corrigi-lo lá.

Certas circunstâncias fazem com que nginx responda com um redirecionamento e presume que o esquema é o mesmo que o esquema usado para se conectar a ele (ou seja, do AWS ELB). AFAIK existem três maneiras de atenuar o problema no servidor nginx de backend.

1) A partir da versão 1.11.8, a instrução absolute_redirect off; fará com que o cabeçalho Location use uma URL relativa, o que significa que o esquema e o nome de domínio estão ausentes.

server {
    absolute_redirect off;
    ...
}

Veja este documento para saber mais.

2) Inibir o comportamento de anexar um / para diretórios à direita usando uma instrução try_files :

server {
    root /path/to/files;

    location / {
        try_files $uri =404;
    }
    ...
}

Veja este documento para saber mais.

3) Corrija o problema com uma instrução return explícita.

server {
    root /path/to/files;

    location ~ [^/]$ {
        if (-d $request_filename) {
            return 302 https://$host$uri/$is_args$args;
        }
    }

    location / {
    }
    ...
}

Veja este documento para saber mais e esta advertência sobre o uso de if .

    
por 28.11.2017 / 10:47
1

Tente isso

server {
  root /var/www;
  include /etc/nginx/basic.conf;
  try_files $uri $uri/;
}

Se isso não funcionar, edite sua pergunta para incluir o que estiver em basic.conf e nginx.conf. Também faça um curl mostrando o problema, incluindo os cabeçalhos de resposta e o único arquivo de log de acesso Nginx correspondente.

    
por 24.11.2017 / 20:19
0

Você pode tentar usar uma sentença "evil if":

server {
    ...
    if ($http_x_forwarded_proto = 'http' ) {
        rewrite ^ https://$host$request_uri? permanent;
    }
    ...
}
    
por 28.11.2017 / 12:39