Запретить 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, но тогда мне придется дублировать остальную часть conf (в serverдирективе есть много, что я упустил для простоты). Я знаю, что мог бы также использовать includeдирективу, чтобы исключить избыточность, но я действительно хочу сохранить только один conf-файл без каких-либо зависимостей.

Итак, во-первых, есть ли что-то, что я пропускаю, чтобы полностью устранить проблему? Или, во-вторых, если нет, есть ли другой способ (помимо включения внешнего файла) выделить лишнюю информацию конфигурации, чтобы я мог отделить версии конфигурации сервера HTTP и HTTPS?

Крис Пратт
источник

Ответы:

29

Ну, я немного вдохновился и попробовал:

proxy_redirect http:// $scheme://;

Который, кажется, делает трюк. Это все еще кажется мне хакерским, поэтому я по-прежнему приветствую любые указания относительно того, что я могу делать неправильно или менее хакерские способы достижения того же результата.

Крис Пратт
источник
Действительно, это, кажется, "официальный" способ сделать это ... см. Wiki.nginx.org/SSL-Offloader
Hendy
Приведенная выше ссылка на вики nginx больше не работает, новое местоположение - nginx.com/resources/wiki/start/topics/examples/SSL-Offloader
Пол Тобиас,
Это не сработает, если в вашем местоположении нет косой черты
hdave
бог порево блин, почему не программное обеспечение просто ожидать , чтобы жить за обратного прокси - сервера (или по крайней мере проклятый уважение X-Forwarded-схеме или любой другой Blet +?
Axel Латвала
5

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

proxy_set_header    X-Scheme $scheme;
mgorven
источник
Ах, теперь я вижу, что у вас уже есть эта конфигурация.
Mgorven
Ага. Но я ценю попытку помочь, тем не менее.
Крис Пратт
4
Это, кажется, какой-то хитрый заголовок. Я думаю, что X-Forwarded-Proto лучше
vladkras