Не дозволяйте nginx перенаправляти трафік з https на http, коли він використовується як зворотний проксі


16

Ось мій скорочений 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;
    }
}

Один і той же сервер повинен обслуговувати і HTTP, і HTTPS, однак, коли висхідний потік видає переспрямування (наприклад, після обробки форми), усі запити HTTPS переспрямовуються на HTTP. Єдине, що я виявив, що виправить це питання, - це змінити proxy_redirectнаступне:

proxy_redirect http:// https://;

Це чудово працює для запитів, що надходять від HTTPS, але якщо перенаправлення видається через HTTP, воно також перенаправляє його на HTTPS, що є проблемою.

З відчаю я спробував:

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

Але nginx скаржиться, що proxy_redirectтут заборонено.

Єдиний інший варіант, про який я можу придуматись, - це визначити два сервери окремо і встановити proxy_redirectлише один на SSL, але тоді я б дублював решту конф server. Я знаю, що я міг би також використовувати includeдирективу, щоб визначити надмірність, але я дуже хочу зберегти лише один конф-файл без будь-яких залежностей.

Отже, по-перше, чи є щось, що мені не вистачає, що повністю зніме проблему? Або, по-друге, якщо ні, чи є інший спосіб (крім включення зовнішнього файлу) виділити зайву інформацію конфігурації, щоб я міг відокремити версії HTTP та HTTPS серверної конфігурації?

Відповіді:


29

Ну, я трохи надихнувся і спробував:

proxy_redirect http:// $scheme://;

Який, здається, робить трюк. Мені це все ще здається гакітним, тому я все ще вітаю будь-які вказівки щодо того, що я можу робити неправильно або менш хитрі способи досягнення того ж результату.


Дійсно, це, мабуть, є "офіційним" способом зробити це ... дивіться wiki.nginx.org/SSL-Offloader
Хенді Іраван

Наведене вище посилання на вікі nginx більше не працює, нове місце розташування - nginx.com/resources/wiki/start/topics/examples/SSL-Offloader
Пол Тобіас

Це не спрацює, якщо на вашому розташуванні немає
кінцевої

Боже, чорт, чорт, чому програмне забезпечення не може просто розраховувати жити за зворотним проксі-сервером (або, принаймні, чорт поважати X-Forwarded-схему чи що завгодно? blet +
Axel

5

Інше рішення полягає в тому, щоб вказати вгору про те, чи є запит HTTP або HTTPS, і чи видавати йому відповідне переспрямування. Додавання цього в конфігурації nginx встановило б заголовок для висхідного потоку для перевірки.

proxy_set_header    X-Scheme $scheme;

А, я бачу, що ви вже маєте таку конфігурацію.
mgorven

Так. Але я вдячний спробі допомогти.
Кріс Пратт

4
Це, здається, є деяким хитрим заголовком. Я думаю, що X-Forwarded-Proto краще
vladkras
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.