Frage Wie erzwinge oder umleitung zu SSL in nginx?


Ich habe eine Anmeldeseite in einer Subdomain wie: https://signup.example.com

Es sollte nur über HTTPS zugänglich sein, aber ich bin besorgt, dass die Leute irgendwie über HTTP darauf stolpern und einen 404 bekommen könnten.

Mein html / server block in nginx sieht so aus:

html {
  server {
    listen 443;
    server_name signup.example.com;

    ssl                        on;
    ssl_certificate        /path/to/my/cert;
    ssl_certificate_key  /path/to/my/key;

    ssl_session_timeout 30m;

    location / {
      root /path/to/my/rails/app/public;
      index index.html;
        passenger_enabled on;
    }
  }
}

Was kann ich hinzufügen, damit Leute, die gehen http://signup.example.com umgeleitet werden zu https://signup.example.com ? (Zugegeben, es gibt Rails-Plugins, die erzwingen können.) SSL aber hoffte, das zu vermeiden)


210
2018-03-22 18:45


Ursprung


Mögliches Duplikat von Wie kann ich in Nginx alle http-Anfragen in https umschreiben, während ich die Unterdomäne beibehalte? - Nasreddine


Antworten:


Gemäß nginx FallstrickeEs ist etwas besser, die unnötige Aufnahme wegzulassen $request_uri stattdessen. Hängen Sie in diesem Fall ein Fragezeichen an, um zu verhindern, dass nginx irgendwelche Abfrageargumente verdoppelt.

server {
    listen      80;
    server_name signup.mysite.com;
    rewrite     ^   https://$server_name$request_uri? permanent;
}

137
2018-03-22 19:22



Oder, gemäß der Website, die Sie verlinkt haben, "BESSER": return 301 http://domain.com$request_uri; - nh2
ein Kommentar. Der $ Servername $ übernimmt die erste Variable Servername. Seien Sie sich dessen bewusst, wenn Sie in Ihrer Konfiguration nicht FQN-Namen haben - engineerDave
@ nh2 Dies ist ein weiterer Fall, in dem die Dokumentation seit der Verwendung falsch ist return 301... verursacht einen "zu viele Umleitungen" Fehler, während die Umschreibmethode tatsächlich funktioniert. - Mike Bethany
Das ist jetzt auch als "BAD" dokumentiert. @MikeBethany return 301 funktioniert, es sei denn, (ich schätze) du trigest es aus ebenfalls für korrekte URLs, indem Sie auf beide Ports hören (Beispiel für Config. Auslösen des Problems: Take serverfault.com/a/474345/29689's erste Antwort und das If weglassen. - Blaisorblade
Ich frage mich, was sich im Laufe der Jahre verändert hat und ob diese andere Antwort besser ist: serverfault.com/a/337893/119666 - Ryan


Der beste Weg, wie es in das offizielle How-To ist mit den return Richtlinie:

server {
    listen      80;
    server_name signup.mysite.com;
    return 301 https://$server_name$request_uri;
}

237
2017-09-03 23:50



kürzeste Antwort und funktionierte perfekt in meinem Fall - mateusz.fiolka
Dies wird generell empfohlen, da a zurückgegeben wird 301 Moved Permanently (Ihre Links sind dauerhaft verschoben) sowie neu schreiben - sgb
Dies funktioniert nicht, da es zu einem "zu vielen Umleitungen" -Fehler kommt, selbst wenn Sie dies eingestellt haben proxy_set_header X-Forwarded-Proto https; - Mike Bethany
@MikeBethany definierst du listen 443; im selben Block? - Joe B
Dies sollte die akzeptierte Antwort sein. - sjas


Dies ist der korrekte und effizienteste Weg, wenn Sie alles in einem Serverblock behalten wollen:

server {
    listen   80;
    listen   [::]:80;
    listen   443 default_server ssl;

    server_name www.example.com;

    ssl_certificate        /path/to/my/cert;
    ssl_certificate_key  /path/to/my/key;

    if ($scheme = http) {
        return 301 https://$server_name$request_uri;
    }
}

Alles andere oben, mit "rewrite" oder "if ssl_protocol" usw. ist langsamer und schlechter.

Hier ist das gleiche, aber noch effizienter, indem nur das Umschreiben des HTTP-Protokolls ausgeführt wird, wird vermieden, dass die $ -Schema-Variable bei jeder Anforderung überprüft werden muss. Aber im Ernst, es ist so eine kleine Sache, dass Sie sie nicht trennen müssen.

server {
    listen   80;
    listen   [::]:80;

    server_name www.example.com;

    return 301 https://$server_name$request_uri;
}
server {
    listen   443 default_server ssl;

    server_name www.example.com;

    ssl_certificate        /path/to/my/cert;
    ssl_certificate_key  /path/to/my/key;
}

108
2018-01-31 20:43



Großartig, einige Feiglinge wählten diese Antwort ohne zu sagen, warum, obwohl diese Antwort richtig ist. Vielleicht noch eine dieser "ob ist böse" Kultisten. Wenn Sie die Nginx-Dokumentation über If lesen, werden Sie wissen, dass IfIsNOTEvil nur von CERTAIN innerhalb eines location {} -Kontextes verwendet wird, was wir hier nicht tun. Meine Antwort ist absolut die richtige Art, Dinge zu tun! - DELETEDACC
Ich habe das nicht abgelehnt, aber ich möchte darauf hinweisen, dass die Standardeinstellung in den neuesten Versionen auf "default_server" geändert wurde. - spuder
Die erste Lösung kann nicht die effizienteste sein, wenn die zweite noch effizienter ist. Und du hast sogar beschrieben, warum du keins verwenden solltest, wenn es da ist: "es vermeidet, die $ Schema-Variable bei jeder Anfrage prüfen zu müssen". Der Punkt, ohne Wenns zu verwenden, ist nicht nur Leistung, sondern auch deklarativ und nicht zwingend. - pepkin88
+1 für if ($ schema = http) - Fernando Kosh
Sollte $ host hier verwenden, wie in den anderen Antworten erwähnt. - Artem Russakovskii


Wenn Sie die neue duale HTTP- und HTTPS-Serverdefinition verwenden, können Sie Folgendes verwenden:

server {
    listen   80;
    listen   [::]:80;
    listen   443 default ssl;

    server_name www.example.com;

    ssl_certificate        /path/to/my/cert;
    ssl_certificate_key  /path/to/my/key;

    if ($ssl_protocol = "") {
       rewrite ^   https://$server_name$request_uri? permanent;
    }
}

Dies scheint für mich zu funktionieren und verursacht keine Umleitungsschleifen.

Bearbeiten:

Ersetzt:

rewrite ^/(.*) https://$server_name/$1 permanent;

mit Pratiks Neuschreiblinie.


56
2017-08-08 11:12



@DavidPashley hat deine Lösung wie ein Zauber für mich funktioniert. Vielen Dank - Jayesh Gopalan
If you are using the new dual HTTP and HTTPS server definition dann solltest du es trennen. - VBart
elegant und funktioniert perfekt! - jipipayo
Dies war die einzige Lösung, die für mich mit meiner Laravel / Homestead Nginx-Konfiguration funktionierte. - Jared Eitnier
Auch die Neuschreiblinie sollte sein return 301 https://$server_name$request_uri; wie dies die bevorzugte Methode ist. - Jared Eitnier


Noch eine Variante, die den Header Host: request erhält und dem Beispiel "GOOD" folgt nginx Fallstricke:

server {
    listen   10.0.0.134:80 default_server;

    server_name  site1;
    server_name  site2;
    server_name  10.0.0.134;

    return 301 https://$host$request_uri;
}

Hier sind die Ergebnisse. Beachten Sie, dass mit $server_name anstatt $host würde immer umleiten https://site1.

# curl -Is http://site1/ | grep Location
Location: https://site1/

# curl -Is http://site2/ | grep Location
Location: https://site2/


# curl -Is http://site1/foo/bar | grep Location
Location: https://site1/foo/bar

# curl -Is http://site1/foo/bar?baz=qux | grep Location
Location: https://site1/foo/bar?baz=qux

27
2018-04-11 12:20



Note that using $server_name instead of $host would always redirect to https://site1 ist das nicht was $request_uri ist für? - Jürgen Paul
$request_uri enthält keinen Host- oder Domänennamen. Mit anderen Worten, es beginnt immer mit einem "/" Zeichen. - Peter
Beste Antwort bei weitem. - Ashesh
Ich bin mir nicht sicher, warum diese Antwort so niedrig ist. Es ist das einzige, das es wert ist, benutzt zu werden. - zopieux
Ich kann nicht glauben, dass so viele Leute $ server_name benutzen, das ist der richtige Weg - Greg Ennis


Stellen Sie sicher, dass Sie bei allen Cookies "sicher" sind, sonst werden sie über die HTTP-Anfrage gesendet und könnten von einem Tool wie Firesheep gepackt werden.


3
2018-03-23 00:40





server {
    listen x.x.x.x:80;

    server_name domain.tld;
    server_name www.domian.tld;
    server_name ipv4.domain.tld;

    rewrite     ^   https://$server_name$request_uri? permanent;
}

Das funktioniert besser, denke ich. x.x.x.x bezieht sich auf die IP Ihres Servers. Wenn Sie mit Plesk 12 arbeiten, können Sie dies tun, indem Sie die Datei "nginx.conf" im Verzeichnis "/var/www/vhosts/system/domain.tld/conf" für die gewünschte Domäne ändern. Vergessen Sie nicht, den nginx-Dienst nach dem Speichern der Konfiguration neu zu starten.


1
2017-08-23 19:40



rewrite ^ https://$host$request_uri? permanent;  wäre eine bessere Lösung, da Sie möglicherweise mehrere Servernamen auf einem vhost haben


Ich denke, das ist die einfachste Lösung. Erzwingt sowohl Nicht-HTTPS- als auch Nicht-WWW-Verkehr nur für HTTPS und www.

server {
    listen 80;
    listen 443 ssl;

    server_name domain.tld www.domain.tld;

    # global HTTP handler
    if ($scheme = http) {
        return 301 https://www.domain.tld$request_uri;
    }

    # global non-WWW HTTPS handler
    if ($http_host = domain.tld) {
        return 303 https://www.domain.tld$request_uri;
    }
}

EDIT - Apr 2018: Lösung ohne IFs kann in meinem Beitrag hier gefunden werden: https://stackoverflow.com/a/36777526/6076984


0
2018-04-21 18:30



Sind die Bedingungen in der Welt nicht schlecht und ineffizient? - PKHunter
Ja, das sind sie im Allgemeinen. Aber für diese einfachen Überprüfungen würde ich nicht raten. Ich habe eine richtige Konfigurationsdatei, die mehr Code-Schreiben beinhaltet, aber IFs vollständig vermeidet. - stamster
Google empfiehlt, 301 statt 303 zu verwenden. Quelle: support.google.com/webmasters/answer/6073543?hl=de - dylanh724
@DylanHunt - Ich habe 303 nur zum Testen verlassen, notiere, dass der erste Handler auf 301 gesetzt wurde, nur 2. Ich habe vergessen zu ändern :) Auch, Lösung ohne IF's: stackoverflow.com/a/36777526/6076984 - stamster