Welcome! Log In Create A New Profile

Advanced

Зацикливание на редиректе

August 03, 2017 05:16AM
Доброго дня сообществу! Прошу совета по проблеме.
Собственно, редирект с www на https без-www

server {
    #1 http to https without www
    listen 1.2.3.4:80;
    server_name www.test.com test.com;
    rewrite ^ https://test.com$request_uri? permanent;
}

server {
    #2 https with www to https without www
    listen 1.2.3.4:443 ssl;
    server_name www.test.com;
    rewrite ^ https://test.com$request_uri? permanent;
}

server {
    #3 https without www
    listen 1.2.3.4:443 ssl;
    server_name test.com;
    ...
}

Насколько я понял из документации (http://nginx.org/ru/docs/http/ngx_http_core_module.html#var_host), переменная $host принимает значения "в порядке приоритета: имя хоста из строки запроса, или имя хоста из поля Host заголовка запроса, или имя сервера, соответствующего запросу"

Судя по логам, это не совсем так.
По крайней мере, в моем случае (nginx/1.10.2), переменная $host получает имя хоста из строки запроса только если не указано поле host заголовка. Т.е. обрабатывается ситуация с HTTP/1.0, без $http_host в заголовке. Но если в заголовке задать какое-то (любое) значение $http_host, это же значение получает и $host.

Далее (http://nginx.org/ru/docs/http/request_processing.html): nginx "сопоставляет значение поля Host заголовка запроса с директивами server_name в блоках server, которые соответствуют IP-адресу и порту". Т.е. все-таки $http_host. А туда можно прописать что угодно.
Я не рассматриваю сейчас ситуацию, когда в $http_host прописано имя, не совпадающее с перечисленными в server_name. Это все благополучно фильтруется и отправляется на 444. Также, я не рассматриваю браузеры, которые отправляют правильный $http_host и получают правильные редиректы.

Вот такой случай:
curl -ILH 'Host: www.test.com' https://test.com

Если бы переменная $host получила значение в порядке приоритета, оно было бы test.com (имя хоста из строки запроса). Тогда можно было бы реализовать такой костыль, как фильтрация по условию "$host не равно $http_host". Но в запросе присутствует заголовок host, и обе переменные $host и $http_host получают одно и то же значение www.test.com , отфильтровать невозможно.
Имя www.test.com перечислено в server_name, в итоге такой запрос успешно проходит фильтрацию. После сопоставления значения $http_host с server_name, nginx отправляет запрос в секцию 2, откуда возвращается 301 и новый location https://test.com , т.е. на выходе получаем тот же самый запрос (curl -ILH 'Host: www.test.com' https://test.com) и, естесвенно, зацикливание на второй секции:

curl -ILH 'Host: www.test.com' https://test.com
HTTP/1.1 301 Moved Permanently
..........
Location: https://test.com/

HTTP/1.1 301 Moved Permanently
..........
Location: https://test.com/

..........

Это баг или фича? Или я что-то делаю не так? Как это побороть?
Спасибо.
--_______________________________________________
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru
Subject Author Posted

Зацикливание на редиректе

CoDDoC August 03, 2017 05:16AM

Re: Зацикливание на редиректе

Валентин Бартенев August 05, 2017 02:48PM

Re[2]: Зацикливание на редиректе

CoDDoC August 07, 2017 02:12AM

Re: Зацикливание на редиректе

Валентин Бартенев August 07, 2017 06:26AM

Re: Зацикливание на редиректе

Валентин Бартенев August 07, 2017 06:38AM

Re[2]: Зацикливание на редиректе

CoDDoC August 07, 2017 08:28AM

Re: Зацикливание на редиректе

Валентин Бартенев August 07, 2017 09:14AM

Re[2]: Зацикливание на редиректе

CoDDoC August 08, 2017 01:22AM

Re: Зацикливание на редиректе

Иван August 08, 2017 06:00AM



Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 306
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready