Как предотвратить перенаправление nginx с HTTPS на HTTP на AWS?

У меня есть веб-сайт, обслуживаемый nginx за балансировщиком нагрузки AWS ELB. На балансировщике нагрузки включен только HTTPS.

Запросы отдельных файлов или каталогов с косой чертой работают нормально. Однако запрос каталогов без косой черты не работает.

Причина в том, что когда я запрашиваю каталог без завершающей косой черты, nginx выполняет перенаправление на путь с конечной косой чертой (это нормально), но также изменяется с HTTPS на HTTP. Балансировщик нагрузки настроен на разрешение только HTTPS, поэтому он не работает (тайм-аут).

В лог-файле nginx я вижу, что запрос достигает nginx, и что это nginx, который отвечает с помощью перманентного перенаправления 301 (так что, например, это не проблема с настройкой балансировщика нагрузки).

10.100.10.15 - - [24/Nov/2017:15:41:08 +0000] "GET /admin HTTP/1.1" 301 178 "-" "Wget/1.18 (darwin16.0.0)"

Когда я запрашиваю URL через curl Я вижу редирект:

$ curl -v https://example.com/admin
*   Trying 1.2.3.4...
* TCP_NODELAY set
* Connected to example.com (1.2.3.4) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: example.com
* Server certificate: Amazon
* Server certificate: Amazon Root CA 1
* Server certificate: Starfield Services Root Certificate Authority - G2
> GET /admin HTTP/1.1
> Host: example.com
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Date: Mon, 27 Nov 2017 09:19:05 GMT
< Content-Type: text/html
< Content-Length: 178
< Connection: keep-alive
< Server: nginx
< Location: http://example.com/admin/
< X-UA-Compatible: IE=Edge
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host example.com left intact

Мой файл конфигурации nginx просто

server {
    root /var/www;
}

/Etc/nginx/nginx.conf здесь.

я пытался server_name_in_redirect off но это не имело никакого значения.

Я бы хотел не указывать имя хоста в файле конфигурации, потому что оно упаковано в образ Docker, который затем развертывается на разных хостах (QA, Prod и т. Д.).

Я хотел бы, чтобы nginx делал это перенаправление, но оставался на HTTPS. Что я могу сделать?

4 ответа

Решение

Лучшее место для решения этой проблемы - соединение с SSL. Если это было запущено nginx, вы бы использовали proxy_redirect заявление к карте http в https в Location заголовок. Я не знаю AWS ELB, поэтому не могу комментировать, как это исправить там.

Определенные обстоятельства вызывают nginx ответить перенаправлением, и предполагается, что схема такая же, как схема, используемая для подключения к ней (т. е. от AWS ELB). AFAIK Есть три способа смягчить проблему в серверной части nginx сервер.


1) Начиная с версии 1.11.8, absolute_redirect off; заявление вызовет Location заголовок, чтобы использовать относительный URL, что означает, что схема и имя домена отсутствуют.

server {
    absolute_redirect off;
    ...
}

Смотрите этот документ для более.


2) Запретить поведение добавления трейлинга / в каталогах с помощью try_files заявление:

server {
    root /path/to/files;

    location / {
        try_files $uri =404;
    }
    ...
}

Смотрите этот документ для более.


3) Исправить проблему с явным return заявление.

server {
    root /path/to/files;

    location ~ [^/]$ {
        if (-d $request_filename) {
            return 302 https://$host$uri/$is_args$args;
        }
    }

    location / {
    }
    ...
}

См. Этот документ для большего, и это предостережение по использованию if,

Попробуй это

server {
  root /var/www;
  include /etc/nginx/basic.conf;
  try_files $uri $uri/;
}

Если это не сработает, пожалуйста, отредактируйте ваш вопрос, чтобы включить все, что есть в basic.conf и nginx.conf. Также выполните скручивание, показывающее проблему, включая заголовки ответа и единственный соответствующий файл журнала доступа Nginx.

Вы можете попытаться использовать предложение "зло, если":

server {
    ...
    if ($http_x_forwarded_proto = 'http' ) {
        rewrite ^ https://$host$request_uri? permanent;
    }
    ...
}

Не тестировалось на AWS, однако я решил использовать эту строку в каждомlocationблокировать:

      proxy_redirect ~^http:(.*)$ https:$1;
Другие вопросы по тегам