web-dev-qa-db-fra.com

Comment forcer ou rediriger vers SSL dans nginx?

J'ai une page d'inscription sur un sous-domaine comme: https://signup.example.com

Il ne devrait être accessible que via HTTPS, mais je crains que les gens ne tombent dessus en quelque sorte via HTTP et obtiennent un 404.

Mon bloc html/serveur dans nginx ressemble à ceci:

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

Que puis-je ajouter pour que les personnes qui se rendent sur http://signup.example.com être redirigé vers https://signup.example.com? (Pour info je sais qu'il y a Rails plugins qui peuvent forcer SSL mais j'espérais éviter ça))

223
Callmeed

Selon pièges nginx , il est légèrement préférable d'omettre la capture inutile, en utilisant $request_uri au lieu. Dans ce cas, ajoutez un point d'interrogation pour empêcher nginx de doubler les arguments de requête.

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

La meilleure façon, comme décrit dans le guide officiel , est d'utiliser la directive return :

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

C'est la manière correcte et la plus efficace si vous voulez tout garder dans un seul bloc serveur:

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

Tout le reste ci-dessus, en utilisant "réécriture" ou "si ssl_protocol" etc est plus lent et pire.

Voici la même chose, mais encore plus efficace, en exécutant uniquement la réécriture sur le protocole http, cela évite d'avoir à vérifier la variable $ schéma à chaque demande. Mais sérieusement, c'est une chose si mineure que vous n'avez pas besoin de les séparer.

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

Si vous utilisez la nouvelle définition de serveur double HTTP et HTTPS, vous pouvez utiliser les éléments suivants:

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

Cela semble fonctionner pour moi et ne provoque pas de boucles de redirection.

Modifier:

Remplacé:

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

avec la ligne de réécriture de Pratik.

56
David Pashley

Encore une autre variante, qui préserve l'en-tête Host: request et suit l'exemple "GOOD" sur pièges nginx :

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

Voici les résultats. Notez que l'utilisation de $server_name au lieu de $Host redirigerait toujours vers 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
Peter

Assurez-vous de définir "sécurisé" sur tous les cookies, sinon ils seront envoyés sur la demande HTTP et pourraient être récupérés par un outil comme Firesheep.

3
W. Andrew Loe III
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;
}

Cela fonctionne mieux je pense. x.x.x.x fait référence à l'IP de votre serveur. Si vous travaillez avec Plesk 12, vous pouvez le faire en modifiant le fichier "nginx.conf" dans le répertoire "/var/www/vhosts/system/domain.tld/conf" pour le domaine de votre choix. N'oubliez pas de redémarrer le service nginx après avoir enregistré la configuration.

1
Caner SAYGIN

Je pense que c'est la solution la plus simple. Force le trafic non HTTPS et non WWW vers HTTPS et www uniquement.

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: La solution sans IF peut être trouvée dans mon article ici: https://stackoverflow.com/a/36777526/6076984

0
stamster