Evite que nginx redirija el tráfico de https a http cuando se usa como proxy inverso


16

Aquí está mi abreviada 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;
    }
}

El mismo servidor necesita servir tanto HTTP como HTTPS, sin embargo, cuando el flujo ascendente emite una redirección (por ejemplo, después de que se procesa un formulario), todas las solicitudes HTTPS se redirigen a HTTP. Lo único que he encontrado que corrige este problema está cambiando proxy_redirecta lo siguiente:

proxy_redirect http:// https://;

Eso funciona de maravilla para las solicitudes que provienen de HTTPS, pero si se emite una redirección a través de HTTP, también se redirige a HTTPS, lo cual es un problema.

Por desesperación, intenté:

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

Pero nginx se queja de que proxy_redirectno está permitido aquí.

La única otra opción que se me ocurre es definir los dos servidores por separado y configurarlos proxy_redirectsolo en el SSL, pero luego habría duplicado el resto de la configuración (hay muchas cosas en la serverdirectiva que omití por simplicidad). Sé que también podría usar una includedirectiva para factorizar la redundancia, pero realmente quiero mantener solo un archivo conf sin ninguna dependencia.

Entonces, primero, ¿hay algo que me falta que niegue el problema por completo? O, en segundo lugar, si no, ¿hay alguna otra forma (además de incluir un archivo externo) para descomponer la información de configuración redundante para que pueda separar las versiones HTTP y HTTPS de la configuración del servidor?

Respuestas:


29

Bueno, me inspiré un poco y probé:

proxy_redirect http:// $scheme://;

Lo que parece hacer el truco. Sin embargo, esto todavía me parece hacky, así que todavía agradezco cualquier orientación sobre cualquier cosa que pueda estar haciendo mal o formas menos hacky de lograr el mismo resultado.


De hecho, esa parece ser la forma "oficial" de hacerlo ... ver wiki.nginx.org/SSL-Offloader
Hendy Irawan

El enlace anterior a la wiki de nginx ya no funciona, la nueva ubicación es nginx.com/resources/wiki/start/topics/examples/SSL-Offloader
Paul Tobias

Esto no funcionará si su ubicación no tiene una barra diagonal
hdave

Maldita sea, ¿por qué el software no puede esperar vivir detrás de un proxy inverso (o al menos respetar el X-Fordered-Scheme o lo que sea? blet +
Axel Latvala

5

La otra solución es indicar a la parte superior si la solicitud es HTTP o HTTPS y hacer que emita la redirección correspondiente. Agregar esto en la configuración de nginx establecería un encabezado para que el upstream lo inspeccione.

proxy_set_header    X-Scheme $scheme;

Ah, ahora veo que ya tienes esa configuración.
mgorven

Sí. Pero aprecio el intento de ayudar, no obstante.
Chris Pratt

44
Esto parece ser un encabezado complicado. Creo que X-Fordered-Proto es mejor
vladkras
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.