Подтвердить что ты не робот

Как перенаправить HTTPS в HTTP на NGINX?

Есть ли способ перенаправить HTTPS-запросы в HTTP, добавив правило в файл vhost домена?

4b9b3361

Ответ 1

Почему это так полезно? Сначала я не был уверен, можно ли это сделать. Но это представляло интересный вопрос.

Вы можете попробовать поставить оператор перенаправления в свой файл конфигурации и перезапустить сервер. Возможны две возможности:

  • Сервер выдаст перенаправление - то, что вам кажется нужным.
  • Сервер сначала сделает обмен https, а THEN выдаст перенаправление, и в этом случае, что точка?

Будет добавлено больше, если я придумаю что-то более конкретное.

ОБНОВЛЕНИЕ: (пару часов спустя) Вы можете попробовать это. Вы должны поместить это в свой файл nginx.conf -

server {
       listen 443;
       server_name _ *;
       rewrite ^(.*) http://$host$1 permanent;
 }

Отправляет постоянный переадресацию клиенту. Я предполагаю, что вы используете порт 443 (по умолчанию) для https.

server {
    listen      80;
    server_name _ *;
    ...
}

Добавьте это так, чтобы ваши обычные HTTP-запросы на порт 80 не пострадали.

ОБНОВЛЕНИЕ: 18 декабря 2016 г. - server_name _ следует использовать вместо server_name _ * в версиях nginx > 0.6.25 (благодаря @Luca Steeb)

Ответ 2

rewrite и if следует избегать с помощью Nginx. Известная строка: "Nginx - это не Apache": другими словами, Nginx имеет лучшие способы обработки URL-адресов, чем переписывание. return по-прежнему является технически частью модуля перезаписи, но он не несет накладных расходов rewrite и не относится к ним как к if.

Nginx имеет целую страницу на почему if является "злым" . Он также содержит конструктивную страницу, объясняющую почему rewrite и if плохие, и как вы можете обойти это. Здесь, что страница должна сказать относительно rewrite и if:

Это неправильный, громоздкий и неэффективный способ.

Вы можете решить эту проблему правильно, используя return:

server {
    listen 443 ssl;

    # You will need a wildcard certificate if you want to specify multiple
    # hostnames here.
    server_name domain.example www.domain.example;

    # If you have a certificate that is shared among several servers, you
    # can move these outside the `server` block.
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/cert.key;

    # 301          indicates a permanent redirect.  If your redirect is
    #              temporary, you can change it to 302 or omit the number
    #              altogether.
    # $http_host   is the hostname and, if applicable, port--unlike $host,
    #              which will break on non-standard ports
    # $request_uri is the raw URI requested by the client, including any
    #              querystring
    return 301 http://$http_host$request_uri;
}

Если вы ожидаете большого количества ботов, которые не отправляют заголовок Host, вы можете использовать $host вместо $http_host, пока вы будете придерживаться портов 80 и 443. В противном случае вам нужно будет динамически заполнить замену $http_host. Этот код эффективен и безопасен, если он появляется в корневом каталоге server (а не в блоке location), несмотря на использование if. Однако для этого вам нужно будет использовать сервер по умолчанию, который следует избегать с помощью https.

set $request_host $server_name:$server_port;
if ($http_host) {
    set $request_host $http_host;
}

Если вы хотите использовать SSL/TLS для определенных путей, но запретите это иначе:

server {
    listen 443 ssl;
    server_name domain.example;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/cert.key;

    location / {
        return 301 http://$host$request_uri;
    }

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

server {
    listen 80;
    server_name domain.example;

    location / {
        try_files $uri =404;
    }

    location /secure/ {
        return 301 https://$http_host$request_uri;
    }
}

Если ваш сервер не находится в прямой связи с клиентом - например, если вы используете CloudFlare - все становится немного сложнее. Вам необходимо убедиться, что любой сервер, находящийся в прямой связи с клиентом, добавляет в запрос соответствующий заголовок X-Forwarded-Proto.

Использование этого - беспорядочное предложение; для полного объяснения см. IfIsEvil. Чтобы это было полезно, блок if не может находиться внутри блока location по целому ряду сложных причин. Это заставляет использовать rewrite для тестирования URI. Короче говоря, если вам нужно использовать это на производственном сервере... не делайте этого. Подумайте об этом так: если вы переросли Apache, вы переросли это решение.

/secure,/secure/и что-либо в/secure/будет обеспечивать https, тогда как все остальные URI будут применять http. Конструкция (?! ) PCRE представляет собой отрицательное утверждение lookback. (?: ) является группой, не участвующей в съемке.

server {
    # If you're using https between servers, you'll need to modify the listen
    # block and ensure that proper ssl_* statements are either present or
    # inherited.
    listen 80;
    server_name domain.example;

    if ($http_x_forwarded_proto = https) {
        rewrite ^(?!/secure)/ http://$http_host$request_uri? permanent;
    }
    if ($http_x_forwarded_proto != https) {
        rewrite ^/secure(?:/|$) https://$http_host$request_uri? permanent;
    }
}

Ответ 3

location / {
    if ($scheme = https) {
        rewrite ^(.*)? http://$http_host$1 permanent;
    }
}

Ответ 4

этот вопрос лучше всего подходит для сайта serverfault.com.

Лучший способ сделать перенаправление на http:

server {
   listen 443;
   return 301 http://$host$request_uri;
}

Это позволяет избежать как предложения "if", так и регулярного выражения в переписывании, которые являются функциями других решений на сегодняшний день. Оба имеют последствия для производительности, хотя на практике вам придется иметь довольно большой трафик, прежде чем это имеет значение.

В зависимости от вашей установки вы, скорее всего, также захотите указать ip в предложении listen и, возможно, в названии servername. Точно так же он будет применяться ко всем портам 443 запросов для всех доменных имен. Обычно вам нужен IP-адрес для домена с https, поэтому в основном привязка указанного выше к IP-адресу больше, чем привязка его к доменному имени, но там есть варианты, например, где все домены являются субдоменами одного домена.

EDIT: TLS теперь близок к универсальному, а вместе с ним Идентификация имени сервера (SNI), которая позволяет HTTPS-сайтам на нескольких доменах обмениваться одним IP-адресом. Там хорошая рецензия здесь

Ответ 5

Единственное простое правило уже объяснено в сообщении выше меня:

server {
    listen ip:443;
    server_name www.example.com;
    rewrite ^(.*) http://$host$1 permanent;
}

Ответ 6

Это помогло мне:

server {
    listen 443;
    server_name server.org www.server.org;
    rewrite ^ http://$server_name$request_uri? permanent;
}