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

13

Aqui está o meu nginx vhost conf abreviado:

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, depois que um formulário é processado), todas as solicitações HTTPS são redirecionadas para HTTP. A única coisa que encontrei para corrigir esse problema é alterar proxy_redirect para o seguinte:

proxy_redirect http:// https://;

Isso funciona maravilhosamente para solicitações vindas de HTTPS, mas se um redirecionamento é emitido por HTTP, ele também redireciona isso para HTTPS, o que é um problema.

Por desespero, eu tentei:

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

Mas o nginx reclama que proxy_redirect não é permitido aqui.

A única outra opção que consigo pensar é definir os dois servidores separadamente e definir proxy_redirect apenas no SSL, mas depois eu teria duplicado o resto do conf (há muita coisa na diretiva server que eu omiti pela simplicidade). Eu sei que eu também poderia usar uma diretiva include para fatorar a redundância, mas eu realmente quero manter apenas um arquivo conf sem quaisquer dependências.

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

    
por Chris Pratt 23.03.2012 / 22:08

2 respostas

24

Bem, eu tenho um pouco de inspiração e tentei:

proxy_redirect http:// $scheme://;

O que parece fazer o truque. Isso ainda parece hacky para mim, por isso ainda agradeço qualquer orientação sobre qualquer coisa que eu possa estar fazendo errado ou maneiras menos hacky para alcançar o mesmo resultado.

    
por 23.03.2012 / 22:24
5

A outra solução é indicar para o upstream se a solicitação é HTTP ou HTTPS e fazer com que ela emita o redirecionamento correspondente. Adicionando isso na configuração do nginx, seria definido um cabeçalho para o upstream para inspecionar.

proxy_set_header    X-Scheme $scheme;
    
por 24.03.2012 / 00:02

Tags