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?

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.


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;

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.