Question Comment forcer ou rediriger vers SSL dans nginx?


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

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

Mon bloc html / server 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 gens qui vont à http://signup.example.com être redirigé vers https://signup.example.com ? (Pour info je sais qu’il existe des plugins Rails qui peuvent forcer SSL mais espérait éviter cela)


210
2018-03-22 18:45


origine


Double possible de Dans Nginx, comment puis-je réécrire toutes les demandes http en https tout en maintenant le sous-domaine? - Nasreddine


Réponses:


Selon pièges de 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 la requête.

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

137
2018-03-22 19:22



Ou, selon le site que vous avez lié, "MEILLEUR": return 301 http://domain.com$request_uri; - nh2
un commentaire. $ nom_serveur $ prend la première variable nom_serveur. Soyez donc conscient de cela si vous avez des noms non FQN dans votre configuration - engineerDave
@ nh2 C’est un autre cas de documentation erronée car elle utilise return 301... provoque une erreur "trop ​​de redirections" alors que la méthode de réécriture fonctionne réellement. - Mike Bethany
C'est maintenant documenté comme "aussi MAUVAIS". @ MikeBethany return 301 ça marche, à moins que (je suppose) que vous le déclenchiez également pour les URL correctes, en écoutant sur les deux ports (exemple de configuration déclenchant le problème: take serverfault.com/a/474345/29689's répondez d’abord et omettez le si). - Blaisorblade
Je me demande ce qui a changé au fil des ans et si cette autre réponse est meilleure: serverfault.com/a/337893/119666 - Ryan


La meilleure façon décrite dans le tutoriel officiel est en utilisant le return directif:

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

237
2017-09-03 23:50



réponse la plus courte et a parfaitement fonctionné dans mon cas - mateusz.fiolka
Ceci est généralement recommandé car il retourne un 301 Moved Permanently (vos liens ont définitivement bougé) ainsi que la réécriture - sgb
Cela ne fonctionne pas car cela provoque une erreur "trop ​​de redirections" même si vous avez défini proxy_set_header X-Forwarded-Proto https; - Mike Bethany
@ MikeBethany vous définissez listen 443; dans le même bloc? - Joe B
Cela devrait être la réponse acceptée. - sjas


C’est le moyen le plus approprié et le plus efficace de tout conserver dans un bloc de 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 "rewrite" ou "if ssl_protocol" etc. est plus lent et pire.

Voici la même chose, mais encore plus efficace, en ne lançant que la réécriture sur le protocole http, cela évite de vérifier la variable $ scheme à chaque requête. Mais sérieusement, c'est une chose tellement mineure qu'il n'est pas nécessaire 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;
}

108
2018-01-31 20:43



Génial, un lâche a rejeté cette réponse sans dire pourquoi, même si cette réponse est correcte. Peut-être un autre de ces cultistes "si est mauvais". Si vous prenez la peine de lire la documentation de Nginx sur If, vous saurez que IfIsNOTEvil, CERTAINES utilisations l’utilise dans un contexte de localisation {}, ce que nous ne faisons pas ici. Ma réponse est absolument la bonne façon de faire les choses! - DELETEDACC
Je n'ai pas voté contre cela, mais je voudrais souligner que la valeur par défaut a été changée en 'default_server' dans les versions les plus récentes. - spuder
La première solution ne peut pas être la plus efficace si la seconde est encore plus efficace. Et vous avez même expliqué pourquoi vous ne devriez pas utiliser un si: "cela évite de devoir vérifier la variable $ scheme à chaque requête". L'intérêt de ne pas utiliser les ifs ne concerne pas seulement les performances, mais aussi le fait d'être déclaratif et non impératif. - pepkin88
+1 pour si ($ scheme = http) - Fernando Kosh
Devrait utiliser $ host ici, comme mentionné dans les autres réponses. - Artem Russakovskii


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
2017-08-08 11:12



@ DavidPashley votre solution a fonctionné comme un charme pour moi. Merci - Jayesh Gopalan
If you are using the new dual HTTP and HTTPS server definition alors vous devriez le séparer. - VBart
élégant et fonctionne parfaitement! - jipipayo
C’était la seule solution qui fonctionnait pour moi avec ma configuration Laravel / Homestead Nginx. - Jared Eitnier
Aussi la ligne de réécriture doit être return 301 https://$server_name$request_uri; comme c'est la méthode préférée. - Jared Eitnier


Encore une autre variante, qui préserve l’en-tête Host: request et suit l’exemple "GOOD" pièges de 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 serait toujours rediriger 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
2018-04-11 12:20



Note that using $server_name instead of $host would always redirect to https://site1 n'est-ce pas ce que $request_uri est pour? - Jürgen Paul
$request_uri ne contient pas d'hôte ou de nom de domaine. En d'autres termes, il commence toujours par un caractère "/". - Peter
Meilleure réponse de loin. - Ashesh
Je ne suis pas sûr de savoir pourquoi cette réponse est si faible dans les votes. C'est le seul qui vaille la peine d'être utilisé. - zopieux
Je ne peux pas croire que beaucoup de gens utilisent $ server_name c'est la bonne façon de le faire - Greg Ennis


Assurez-vous que les cookies sont sécurisés, sinon ils seront envoyés sur la requête HTTP et pourraient être récupérés par un outil comme Firesheep.


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

Cela fonctionne mieux je pense. x.x.x.x fait référence à l'adresse 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
2017-08-23 19:40



rewrite ^ https://$host$request_uri? permanent;  serait une meilleure solution car vous pourriez avoir plusieurs noms de serveur sur un vhost