Как перенаправить https: / / запросы на http: / / в NGINX?

есть ли способ перенаправить https:// запросы на http://, добавив правило в файл vhost домена? Я использую NGINX.

6 ответов


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

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

  1. сервер выдаст перенаправление-то, что вы, кажется, хотите.
  2. сервер сначала сделает обмен https, а затем выдаст перенаправление, в этом случае, что смысл?

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

обновление: (пару часов спустя) Ты можешь попробовать это. Вы должны положить это в свой nginx.conf -

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

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

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

добавьте это, чтобы ваши обычные http-запросы на порту 80 были непотревоженный.

обновление: 18 декабря 2016 - server_name _ вместо server_name _ * в версиях nginx > 0.6.25 (благодаря @Luca Steeb)


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

Nginx имеет целую страницу на почему if это "зло". Он также предоставляет конструктивную страницу, объясняющую почему rewrite и if есть плохо!--32-->, и как вы можете обойти это. Вот что страница должна сказать относительно 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. The (?! ) конструкция PCRE является отрицательное утверждение lookahead. (?: ) это группа без захвата.

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;
    }
}

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

этот вопрос был бы лучше подходит для 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. Там хорошая запись здесь


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

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

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

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