it-swarm.com.de

Wie leite ich https: // -Anfragen in NGINX an http: // um?

Gibt es eine Möglichkeit, https: // -Anfragen an http: // umzuleiten, indem Sie eine Regel in der Vhost-Datei der Domäne hinzufügen? Ich benutze NGINX.

34
deb

Warum ist so etwas nützlich? Auf den ersten Blick war ich mir nicht sicher, ob es möglich ist. Es stellte sich jedoch eine interessante Frage.

Sie könnten versuchen, eine Umleitungsanweisung in Ihre Konfigurationsdatei einzufügen und den Server neu zu starten. Es gibt zwei Möglichkeiten:

  1. Der Server gibt die Umleitung aus - was Sie zu wollen scheinen.
  2. Der Server führt zuerst den https-Austausch durch und DANN gibt die Weiterleitung aus. In welchem ​​Fall, was ist der Punkt?

Füge mehr hinzu, wenn ich etwas Konkretes finde.

UPDATE: (einige Stunden später) Sie könnten dies versuchen. Sie müssen dies in Ihre nginx.conf file - einfügen. 

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

Sendet eine permanente Weiterleitung an den Client. Ich gehe davon aus, dass Sie Port 443 (Standard) für https verwenden.

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

Fügen Sie dies hinzu, damit Ihre normalen HTTP-Anforderungen an Port 80 nicht gestört werden.

UPDATE: 18. Dezember 2016 - server_name _ sollte anstelle von server_name _ * in Nginx-Versionen> 0.6.25 verwendet werden (Dank an @Luca Steeb)

32

rewrite und if sollten mit Nginx vermieden werden. Die berühmte Zeile lautet "Nginx ist kein Apache": Mit anderen Worten, Nginx hat bessere Möglichkeiten, URLs zu behandeln als das Umschreiben. return ist technisch immer noch Teil des Umschreibungsmoduls, trägt jedoch nicht den Aufwand von rewrite und ist nicht so abgeneigt wie if.

Nginx hat eine ganze Seite auf warum if "böse" ist . Es enthält auch eine konstruktive Seite, in der warum rewrite und if schlecht sind erklärt wird und wie Sie es umgehen können. Was die Seite zu rewrite und if zu sagen hat:

Dies ist ein falscher, umständlicher und ineffektiver Weg.

Sie können dieses Problem richtig mit return lösen:

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

Wenn Sie mit vielen Bots rechnen, die keinen Host-Header senden, können Sie $Host anstelle von $http_Host verwenden, solange Sie an den Ports 80 und 443 bleiben. Andernfalls müssen Sie einen $http_Host-Ersatz dynamisch auffüllen. Dieser Code ist effizient und sicher, solange er im Stammverzeichnis von server (und nicht in einem location-Block) erscheint, obwohl if verwendet wird. Dazu müssen Sie jedoch einen Standardserver verwenden, der bei https vermieden werden sollte.

set $request_Host $server_name:$server_port;
if ($http_Host) {
    set $request_Host $http_Host;
}

Wenn Sie SSL/TLS für bestimmte Pfade erzwingen möchten, dies jedoch anderweitig untersagen:

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

Wenn Ihr Server nicht direkt mit dem Client kommuniziert - beispielsweise wenn Sie CloudFlare verwenden - werden die Dinge etwas komplizierter. Sie müssen sicherstellen, dass jeder Server, der in direkter Kommunikation mit dem Client steht, der Anforderung einen entsprechenden X-Forwarded-Proto-Header hinzufügt.

Dies zu verwenden ist ein unordentlicher Vorschlag. Eine vollständige Erklärung finden Sie unter IfIsEvil . Damit dies sinnvoll ist, kann sich der if-Block aus verschiedenen komplexen Gründen nicht in einem location-Block befinden. Dies erzwingt die Verwendung von rewrite für URI-Tests. Kurz gesagt, wenn Sie dies auf einem Produktionsserver verwenden müssen ... nicht. Stellen Sie sich das so vor: Wenn Sie Apache entwachsen sind, sind Sie dieser Lösung entwachsen.

/ secure,/secure/und alles in/secure/wird https erzwingen, während alle anderen URIs http erzwingen. Das (?! ) PCRE-Konstrukt ist ein negative Lookahead-Assertion . (?: ) ist eine nicht erfassende Gruppe .

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;
    }
}
29
Zenexer
location / {
    if ($scheme = https) {
        rewrite ^(.*)? http://$http_Host$1 permanent;
    }
}
6
ansiart

diese Frage wäre besser für die Website serverfault.com geeignet.

Eine bessere Möglichkeit, die Weiterleitung an http durchzuführen:

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

Dadurch werden sowohl die 'if'-Klausel als auch der reguläre Ausdruck in der Umschreibung vermieden, die Merkmale der anderen Lösungen sind. Beide haben Auswirkungen auf die Leistung, obwohl Sie in der Praxis ziemlich viel Verkehr haben müssen, bevor es eine Rolle spielt.

Abhängig von Ihrem Setup möchten Sie wahrscheinlich auch eine IP in der Listen-Klausel und möglicherweise eine Servername-Klausel oben angeben. Dies gilt für alle Port-443-Anforderungen für alle Domänennamen. Im Allgemeinen möchten Sie eine IP pro Domäne mit https. Daher ist es meistens wichtiger, das Obige an eine IP-Adresse zu binden, als an einen Domänennamen zu binden. Es gibt jedoch Variationen, z.

BEARBEITEN: TLS ist jetzt nahezu universell und damit die Servernamenidentifikation (SNI), die HTTPS-Sites in mehreren Domänen ermöglicht, die sich eine einzige IP teilen. Es gibt einen guten Bericht hier

4
mc0e

Das hat mir geholfen:

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

Die einzige einfache Regel wird bereits in dem Beitrag über mir erläutert:

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