2010-10-08 7 views

Antwort

28

Warum ist so etwas nützlich? Auf den ersten Blick war ich mir nicht sicher, ob es getan werden könnte. Aber es hat eine interessante Frage gestellt.

Sie könnten versuchen, eine Redirect-Anweisung in Ihre Konfigurationsdatei einzufügen und Ihren Server neu zu starten. Es können zwei Möglichkeiten auftreten:

  1. Der Server wird die Weiterleitung ausgeben - was Sie scheinen wollen.
  2. Der Server wird zuerst den https-Austausch durchführen und dann die Umleitung ausgeben, in welchem ​​Fall, was ist der Punkt?

Wird mehr hinzufügen, wenn ich mit etwas konkreterem komme.

UPDATE:(paar Stunden später) Man könnte dies versuchen. Sie müssen dies in Ihrer nginx.conf Datei setzen -

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

Sendet eine dauerhafte Umleitung an den Client. Ich nehme an, dass Sie Port 443 (Standard) für https verwenden.

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

Fügen Sie dies hinzu, damit Ihre normalen HTTP-Anfragen auf Port 80 ungestört sind.

UPDATE:18. Dezember 2016 - server_name _ sollte statt server_name _ * in nginx Versionen> 0.6.25 (dank @Luca Steeb)

+2

Alte Antwort, aber möchte nur sagen, dass es wegen der „unsicheren Inhalt“ Regel heutzutage nützlich ist. Wenn zum Beispiel ein iframe verwendet wird. –

+1

Eine andere Verwendung ist, wenn Sie eine Reihe von "nicht fortgeführten" 404 Seiten für mehrere Domänen über virtuelle Hosts austeilen. Es ist nicht notwendig, den tatsächlichen verschlüsselten Datenverkehr zu bedienen, und es ist nicht (einfach) möglich, gültige Zertifikate für jede Domain zu erstellen. –

+5

Ein weiterer Grund, warum es nützlich wäre: Ich habe einen Server, der mehrere Domänen hostet. Einer von ihnen hat SSL, aber die anderen Domänen haben keine SSL-Zertifikate.Wenn jemand über HTTPS zu diesen anderen Domains geht, muss er zu HTTP umleiten. –

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

verwendet werden Fügen Sie ein Standort-Flag hinzu, das umfassender ist als/wenn Sie sicherstellen möchten, dass alles übereinstimmt. Aber die Antwort mit dem Server ist wahrscheinlich am besten, um ehrlich zu sein. Wie gehst du mit Voxen um? – ansiart

0

Die einzige einfache Regel erklärt wird bereits verwendet werden, auf dem Post über mir:

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

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

Eine bessere Möglichkeit, die Umleitung zu tun, um http: Dies vermeidet

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

sowohl die ‚if‘ Klausel und die Regex in der Rewrite, die Funktionen der anderen Lösungen auf dem neuesten Stand sind. Beides hat Auswirkungen auf die Leistung, obwohl in der Praxis ziemlich viel Verkehr benötigt wird, bevor es wichtig wäre.

Abhängig von Ihrer Konfiguration möchten Sie wahrscheinlich auch eine IP in der listen Klausel und vielleicht eine Server-Klausel oben angeben. Wie es ist, wird es für alle Port 443-Anfragen für alle Domänennamen gelten. Im Allgemeinen möchten Sie eine IP-Adresse pro Domäne mit https, also ist das Binden von Obigem an eine IP-Adresse mehr als das Verknüpfen mit einem Domainnamen, aber es gibt Varianten, z. B. wo alle Domains Subdomains einer Domain sind.

EDIT: TLS ist jetzt fast universell und mit ihm Server Name Identification (SNI), die für HTTPS-Sites auf mehreren Domänen eine gemeinsame IP-Adresse ermöglicht.Es gibt eine gute Aufzählung here

26

rewrite und if sollte mit Nginx vermieden werden. Die berühmte Zeile lautet: "Nginx ist kein Apache": Mit anderen Worten, Nginx hat bessere Möglichkeiten, mit URLs umzugehen als mit Neuschreiben. return ist immer noch technisch Teil des Rewrite-Moduls, aber es trägt nicht den Overhead von rewrite, und ist nicht so einschränkungsbedürftig wie if.

Nginx hat eine ganze Seite auf why if is "evil". Es stellt auch eine konstruktive Seite zur Verfügung, die why rewrite and if are bad erklärt, und wie man es umgehen kann. Hier ist, was die Seite zu sagen hat über rewrite und if:

This is a wrong, cumbersome, and ineffective way.

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

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 eine Menge von Bots erwarten, die keine Host Header senden Sie Sie können $host anstelle von $http_host verwenden, solange Sie an den Ports 80 und 443 bleiben. Andernfalls müssen Sie einen $http_host Ersatz ersetzen. Dieser Code ist effizient und sicher, solange er im Stammverzeichnis server (statt in einem location Block) erscheint, obwohl if verwendet wird. Sie müssen jedoch einen Standardserver verwenden, damit dies zutrifft, was mit https vermieden werden sollte.

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

Wenn Sie für bestimmte Pfade SSL/TLS erzwingen, aber verbieten es anders:

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 der Server nicht in der direkten Kommunikation mit dem Kunden ist - zum Beispiel, wenn Sie verwende CloudFlare - Dinge werden ein bisschen komplizierter. Sie müssen sicherstellen, dass jeder Server, der direkt mit dem Client kommuniziert, der Anforderung einen entsprechenden Header X-Forwarded-Proto hinzufügt.

Mit diesem ist ein chaotischer Vorschlag; Für eine vollständige Erklärung siehe IfIsEvil. Damit dies nützlich ist, kann der if-Block aus verschiedenen komplexen Gründen nicht in einem location-Block sein. Dies zwingt die Verwendung von rewrite für den URI-Test. Kurz gesagt, wenn Sie dies auf einem Produktionsserver verwenden müssen ... nicht. Stellen Sie sich das so vor: Wenn Sie Apache entwachsen haben, sind Sie dieser Lösung entwachsen.

/secure,/secure /, und alles in/secure/erzwingt https, während alle anderen URIs http erzwingen. Das (?! ) PCRE-Konstrukt ist ein negative lookahead assertion. (?: ) ist ein non-capturing group.

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

Ok, wenn ich es richtig verstanden habe, gibt es keine Möglichkeit, HTTP über einen HTTP-Client zu stellen, der HTTPS anfordert, ohne zuerst eine HTTPS-Verbindung aufzubauen. Sie brauchen also Zertifikate, wenn Sie Leute von https auf http verschieben möchten? – Freek

+1

@Frek Richtig, obwohl Sie immer HTTPS unterstützen sollten; Es ist eine ziemlich einfache, aber effektive Sicherheitsfunktion, und jeder Benutzer, der sich für seine Passwörter interessiert, wird es wollen. Sie können ein kostenloses Zertifikat von [Let's Encrypt] (https://letsencrypt.org/) erhalten. Auch wenn Ihre Website keine sensiblen Informationen enthält, könnte sie als Angriffsvektor verwendet werden. – Zenexer

+0

Wenn Sie sich hinter einem Elastic Load Balancer befinden, der 's' entfernt (https -> http), ist die einzige Lösung, die funktioniert mit if ($ http_x_forwarded_proto = https) ... – jmcollin92

0

Das half mir:

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