Empêcher Nginx de rediriger le trafic de https vers http lorsqu'il est utilisé comme proxy inverse

16

Voici ma configuration abrégée vhost nginx:

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;
    }
}

Le même serveur doit servir à la fois HTTP et HTTPS, cependant, lorsque l'amont émet une redirection (par exemple, après le traitement d'un formulaire), toutes les demandes HTTPS sont redirigées vers HTTP. La seule chose que j'ai trouvée qui corrigera ce problème est proxy_redirectla suivante:

proxy_redirect http:// https://;

Cela fonctionne à merveille pour les demandes provenant de HTTPS, mais si une redirection est émise via HTTP, elle redirige également celle-ci vers HTTPS, ce qui est un problème.

Par désespoir, j'ai essayé:

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

Mais Nginx se plaint que ce proxy_redirectn'est pas autorisé ici.

La seule autre option à laquelle je peux penser est de définir les deux serveurs séparément et de proxy_redirectne définir que sur le SSL, mais j'aurais alors dupliqué le reste de la conf (il y a beaucoup dans la serverdirective que j'ai omis pour des raisons de simplicité). Je sais que je pourrais également utiliser une includedirective pour prendre en compte la redondance, mais je veux vraiment garder un seul fichier conf sans aucune dépendance.

Donc, d'abord, y a-t-il quelque chose qui me manque qui résoudra complètement le problème? Ou, deuxièmement, sinon, existe-t-il un autre moyen (en plus d'inclure un fichier externe) pour factoriser les informations de configuration redondantes afin que je puisse séparer les versions HTTP et HTTPS de la configuration du serveur?

Chris Pratt
la source

Réponses:

29

Eh bien, j'ai eu un peu d'inspiration et j'ai essayé:

proxy_redirect http:// $scheme://;

Ce qui semble faire l'affaire. Cependant, cela me semble encore hacky, donc je suis toujours heureux de recevoir des conseils sur tout ce que je pourrais faire de mal ou de manière moins hacky pour obtenir le même résultat.

Chris Pratt
la source
En effet, cela semble être la manière "officielle" de le faire ... voir wiki.nginx.org/SSL-Offloader
Hendy Irawan
Le lien ci-dessus vers le wiki nginx ne fonctionne plus, le nouvel emplacement est nginx.com/resources/wiki/start/topics/examples/SSL-Offloader
Paul Tobias
Cela ne fonctionnera pas si votre emplacement ne comporte pas de barre oblique
hdave
putain de dieu, pourquoi les logiciels ne peuvent-ils pas simplement s'attendre à vivre derrière un proxy inverse (ou au moins respectent-ils X-Forwarded-Scheme ou autre? blet +
Axel Latvala
5

L'autre solution consiste à indiquer à l'amont si la demande est HTTP ou HTTPS et à lui faire émettre la redirection correspondante. L'ajout de cela dans la configuration nginx définirait un en-tête à inspecter en amont.

proxy_set_header    X-Scheme $scheme;
mgorven
la source
Ah, je vois maintenant que vous avez déjà cette configuration.
mgorven
Oui. Mais j'apprécie néanmoins la tentative d'aider.
Chris Pratt
4
Cela semble être un en-tête délicat. Je pense que X-Forwarded-Proto est meilleur
vladkras