Impedir que o nginx redirecione o tráfego de https para http quando usado como proxy reverso

16

Aqui está o meu abreviado nginx vhost conf:

upstream gunicorn {
    server 127.0.0.1:8080 fail_timeout=0;
}

server {
    listen 80;
    listen 443 ssl;
    server_name domain.com ~^.+\.domain\.com$;

    location / {
        try_files $uri @proxy;
    }

    location @proxy {
        proxy_pass_header Server;
        proxy_redirect off;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_connect_timeout 10;
        proxy_read_timeout 120;
        proxy_pass http://gunicorn;
    }
}

O mesmo servidor precisa atender HTTP e HTTPS; no entanto, quando o upstream emite um redirecionamento (por exemplo, após o processamento de um formulário), todas as solicitações HTTPS são redirecionadas para HTTP. A única coisa que encontrei que corrigirá esse problema é proxy_redirecta seguinte:

proxy_redirect http:// https://;

Isso funciona maravilhosamente para solicitações provenientes de HTTPS, mas se um redirecionamento for emitido por HTTP, ele também será redirecionado para HTTPS, o que é um problema.

Por desespero, tentei:

if ($scheme = 'https') {
    proxy_redirect http:// https://;
}

Mas o nginx reclama que proxy_redirectnão é permitido aqui.

A única outra opção em que posso pensar é definir os dois servidores separadamente e configurá-los proxy_redirectapenas no servidor SSL, mas então eu duplicaria o restante do conf (há muita serverdiretiva que eu omiti por questão de simplicidade). Eu sei que também poderia usar uma includediretiva para fatorar a redundância, mas eu realmente quero manter apenas um arquivo conf sem nenhuma dependência.

Então, primeiro, há algo que está faltando que negará completamente o problema? Ou, segundo, se não, existe outra maneira (além de incluir um arquivo externo) de fatorar as informações de configuração redundantes para que eu possa separar as versões HTTP e HTTPS da configuração do servidor?

Chris Pratt
fonte

Respostas:

29

Bem, eu me inspirei um pouco e tentei:

proxy_redirect http:// $scheme://;

O que parece fazer o truque. Isso ainda parece hacky para mim, portanto continuo recebendo qualquer orientação sobre qualquer coisa que possa estar fazendo de maneira errada ou menos hacky para alcançar o mesmo resultado.

Chris Pratt
fonte
De fato, essa parece ser a maneira "oficial" de fazê-lo ... consulte wiki.nginx.org/SSL-Offloader #
Hendy Irawan
O link acima para o wiki nginx não funciona mais, a nova localização é nginx.com/resources/wiki/start/topics/examples/SSL-Offloader
Paul Tobias
Isso não vai funcionar se a sua localização não tem uma barra no final
hdave
deus do caralho maldito, por que não pode software apenas esperar viver por trás de um proxy reverso (ou pelo menos maldito respeito X-transmitido-Scheme ou qualquer blet +?
Axel Latvala
5

A outra solução é indicar ao upstream se a solicitação é HTTP ou HTTPS e solicitar o redirecionamento correspondente. Adicionar isso na configuração do nginx definiria um cabeçalho para o upstream inspecionar.

proxy_set_header    X-Scheme $scheme;
mgorven
fonte
Ah, agora vejo que você já tem essa configuração.
mgorven
Sim. Mas agradeço a tentativa de ajudar, no entanto.
31812 Chris Pratt
4
Este parece ser um cabeçalho complicado. Eu acho que o X-Forwarded-Proto é melhor
vladkras