Leiten Sie Nicht-Www mit Nginx zu Www über SSL um


25

Beim Versuch, https://example.com zu https://www.example.com umzuleiten, ist ein Fehler aufgetreten .

Wenn ich zu https://example.com gehe, wird der page / 200-Status nicht umgeleitet und zurückgegeben.

Ich möchte das nicht, ich möchte, dass es zu https://www.example.com umleitet .

Wenn ich zu http://example.com gehe , wird auf https://www.example.com weitergeleitet

Kann mir jemand sagen, wo ich falsch liege?

Dies sind meine Standard- und Standard-SSL-Konfigurationsdateien:

default.conf

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

default-ssl.conf

upstream app_server_ssl {
    server unix:/tmp/unicorn.sock fail_timeout=0;
}

server {
    server_name example.com;
    return 301 https://www.example.com$request_uri
}
server {
    server_name www.example.com;

    listen 443;
    root /home/app/myproject/current/public;
    index index.html index.htm;

    error_log /srv/www/example.com/logs/error.log info;
    access_log /srv/www/example.com/logs/access.log combined;

    ssl on;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_certificate /srv/www/example.com/keys/ssl.crt;
    ssl_certificate_key /srv/www/example.com/keys/www.example.com.key;
    ssl_ciphers AES128-SHA:RC4-MD5:ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:RSA+3DES:!ADH:!AECDH:!MD5:AES128-SHA;
    ssl_prefer_server_ciphers on;

    client_max_body_size 20M;


    try_files $uri/index.html $uri.html $uri @app;


    # CVE-2013-2028 http://mailman.nginx.org/pipermail/nginx-announce/2013/000112.html
    if ($http_transfer_encoding ~* chunked) {
            return 444;
        }

    location @app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app_server_ssl;
    }

    error_page 500 502 503 504 /500.html;

    location = /500.html {
        root /home/app/example/current/public;
    }
}

1
Was bringt es, 2 conf-Dateien zu erstellen?
Sandip Subedi

Trennung von Bedenken, die Nicht-SSL-Konfiguration war so klein, dass es am besten schien, sie von der Nur-SSL-Konfiguration zu trennen.
Thomas V.

Antworten:


34

listenIn der Datei fehlt eine Anweisung default-ssl.conf. Fügen Sie listen 443;in dieser Direktive hinzu

server {
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

Wenn Sie diese Anweisung weglassen, geht nginx standardmäßig davon aus, dass Sie Port 80 überwachen möchten. Hier die Dokumentation dieses Standardverhaltens.


Edit: Danke für den Kommentar von @TeroKilkanen.

Hier die komplette Konfiguration für deine default-ssl.conf

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /srv/www/example.com/keys/ssl.crt;
    ssl_certificate_key /srv/www/example.com/keys/www.example.com.key;
    return 301 https://www.example.com$request_uri;
}

Anmerkung : Sie können die ssl on;Direktive durch listen 443 ssl;eine Empfehlung aus der Nginx-Dokumentation ersetzen .


4
Sie müssen in diesem Block auch Anweisungen ssl_certificateund ssl_certificate_keyAnweisungen einrichten und verwenden, listen 443 ssl;damit es sich um einen SSL-vhost handelt.
Tero Kilkanen

Bitte posten Sie den Inhalt der aktuellen default-ssl.conf. Vielleicht hat ein Tippfehler oder ein Nachbestellungsproblem das verursacht.
Masegaloeh

Das ist peinlich: \ Der Täter war eine doppelte Nginx-Konfiguration in / etc / nginx / sites-enabled, /etc/nginx/sites-enabled/default-ssl.backup hat alle Weiterleitungen in default-ssl gestört. Dummer Fehler.
Thomas V.

also musste ich 2 zertifikate ausstellen: für www-domain und für nicht-www-domain
vladkras 20.07.17

Wie kann dies an Port 5007 erreicht werden: example.com:5007 bis example.com:5007
CP3O

5

Geben Sie einfach eine if-Anweisung ein und Sie sollten auf dem Weg sein. Ich habe die Ergebnisse in curl.exe -I überprüft und alle Fälle außer https://www.example.com werden als 301 behandelt. SSL ist schwierig, da es überprüft wird, bevor Sie die Umleitung von 301-URLs erhalten. Daher erhalten Sie Zertifikatfehler.

Persönlich entferne ich gerne die WWWs von der Domain, aber ich habe meinen Code unten geschrieben, um Ihre Frage zu beantworten.

server {
listen 443 ssl;
listen [::]:443 ssl; # IPV6

server_name example.com www.example.com; # List all variations here

# If the domain is https://example.com, lets fix it!

if ($host = 'example.com') {
  return 301 https://www.example.com$request_uri;
}

# If the domain is https://www.example.com, it's OK! No changes necessary!

... # SSL .pem stuff
...
}

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

# If the domain is http://example.com or https://www.example.com, let's change it to https!

server_name example.com www.example.com;
return 310 https://www.example.com$request_uri;
}

3

Ich verwende dazu eine if-Anweisung innerhalb des SSL-Serverblocks, die zu https von www umleitet

ssl_certificate /srv/www/example.com/keys/ssl.crt;
ssl_certificate_key /srv/www/example.com/keys/www.example.com.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES128-SHA:RC4-MD5:ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:RSA+3DES:!ADH:!AECDH:!MD5:AES128-SHA;
ssl_prefer_server_ciphers on;
client_max_body_size 20M;

upstream app_server_ssl {
    server unix:/tmp/unicorn.sock fail_timeout=0;
}

server {
    server_name example.com;
    return 301 https://www.example.com$request_uri
}

server {
    listen 443 default_server ssl;
    server_name www.example.com;

    # redirect https://example.com to https://www.example.com
    # mainly for SEO purposes etc
    #we will use a variable to do that
    set $redirect_var 0;

    if ($host = 'example.com') {
      set $redirect_var 1;
    }
    if ($host = 'www.example.com') {
      set $redirect_var 1;
    }

    if ($redirect_var = 1) {
      return 301 https://www.example.com$request_uri;
    } 

    try_files $uri/index.html $uri.html $uri @app;

    # CVE-2013-2028 http://mailman.nginx.org/pipermail/nginx-announce/2013/000112.html
    if ($http_transfer_encoding ~* chunked) {
            return 444;
        }

    location @app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app_server_ssl;
    }

    error_page 500 502 503 504 /500.html;

    location = /500.html {
        root /home/app/example/current/public;
    }
}

Natürlich, wann immer Sie eine if-Anweisung in einer nginx-Konfigurationsdatei verwenden möchten; Sie sollten gelesen haben: https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/


die Bedingung if ($host = 'www.example.com')ist nicht erforderlich.
Karl.S

2

Es ist jetzt 2018 und ich dachte mir, dass ich es noch einmal versuchen sollte, falls jemand nach einer einfachen Lösung sucht.

Mein Ansatz als relativ Neuling ist es, die Dinge so einfach wie möglich zu gestalten. Grundsätzlich möchten Sie sowohl http://example.com als auch https://example.com zu https : // www .example.com umleiten . Und dass es Ihnen nur gelingt, http://example.com umzuleiten

Dies ist eine recht einfache Operation, die nur zwei Serverblöcke erfordert (ich werde dies kurz in einer einzigen Konfigurationsdatei demonstrieren).

# 1. Server block to redirect all non-www and/or non-https to https://www
server {
    # listen to the standard http port 80
    listen 80; 

    # Now, since you want to route https://example.com to http://www.example.com....
    # you need to get this block to listen on https port 443 as well
    # alternative to defining 'ssl on' is to put it with listen 443
    listen 443 ssl; 

    # define server_name
    server_name example.com *.example.com; 

    # DO NOT (!) forget your ssl certificate and key
    ssl_certificate PATH_TO_YOUR_CRT_FILE;
    ssl_certificate_key PATH_TO_YOUR_KEY_FILE; 

    # permanent redirect
    return 301 https://www.example.com$request_uri;  
    # hard coded example.com for legibility 
}
# end of server block 1. nearly there....

# 2. Server block for the www (primary) domain
# note that this is the block that will ultimately deliver content
server {
    # define your server name
    server_name www.example.com; 

    # this block only cares about https port 443
    listen 443 ssl;

    # DO NOT (!) forget your ssl certificate and key
    ssl_certificate PATH_TO_YOUR_CRT_FILE;
    ssl_certificate_key PATH_TO_YOUR_KEY_FILE; 

    # define your logging .. access , error , and the usual 

    # and of course define your config that actually points to your service
    # i.e. location / { include proxy_params; proxy_pass PATH_TO_SOME_SOCKET; }
}
# End of block 2.
# voilà! 

Jetzt sollten sowohl http://example.com als auch https://example.com zu https://www.example.com umleiten . Grundsätzlich leitet dieses Setup alles, was nicht unter www und / oder unter https angegeben ist, an https: // www weiter .


-1

Umleiten aller Anfragen an https://www.example

Erstellen Sie einen Serverblock für die Umleitungs- und Primärdomäne auf Ihrem SSL-Port (normalerweise 443) sowie auf dem Standard-HTTP-Port 80

# non-www to ssl www redirect
server {
  listen 80; 
  listen 443 ssl;
  server_name example.com;
  return 301 https://www.example.com$request_uri;
  # ... ssl certs
}

# ssl setup for www (primary) domain
server {
  listen 80;
  listen 443 ssl;
  server_name www.example.com;
  if ($scheme = http) {
    return 301 https://www.example.com$request_uri;
  }
  # ... the rest of your config + ssl certs
}

speichern und mit folgen sudo nginx -s reload

Dies wird umleiten

http://example      301 -> https://www.example
https://example     301 -> https://www.example
http://www.example  301 -> https://www.example
https://www.example 200

;In der if-Klausel fehlt im zweiten Serverblock ein. Es sollte seinreturn 301 https://www.example.com$request_uri;
Lukas Oppermann

1
Aber würde das überhaupt funktionieren? Kann es hören für httpauf 443?
Lukas Oppermann

Sie haben Recht, ich vermisse hören 80, ich habe es hinzugefügt.
lfender6445
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.