556 votes

Dans Nginx, comment puis-je réécrire toutes les requêtes http en https tout en conservant le sous-domaine ?

Je veux réécrire toutes les requêtes http sur mon serveur web pour en faire des requêtes https, j'ai commencé avec ce qui suit :

server {
    listen      80;

    location / {
      rewrite     ^(.\*)   https://mysite.com$1 permanent;
    }
...

Un problème est que cela supprime toute information sur les sous-domaines (par exemple, node1.mysite.com/dossier), comment puis-je réécrire ce qui précède pour tout rediriger vers https et maintenir le sous-domaine ?

2 votes

Veuillez envisager de déplacer la "réponse acceptée" vers serverfault.com/a/171238/90758 . C'est le bon.

0 votes

Il suffit d'utiliser $server_name au lieu du code dur mysite.com.

806voto

Saif Bechan Points 10842

Méthode correcte dans les nouvelles versions de nginx

Il s'avère que ma première réponse à cette question était correcte à un certain moment, mais elle s'est transformée en un autre piège - pour rester à jour, veuillez vérifier Les pièges de la réécriture fiscale

J'ai été corrigé par de nombreux utilisateurs de SE, donc le crédit leur revient, mais plus important encore, voici le code correct :

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

server {
       listen         443 ssl;
       server_name    my.domain.com;
       # add Strict-Transport-Security to prevent man in the middle attacks
       add_header Strict-Transport-Security "max-age=31536000" always; 

       [....]
}

7 votes

Il faudrait cependant le faire domaine par domaine, non ? Et si vous vouliez l'appliquer à chaque domaine de votre serveur ?

0 votes

Tout cela semble très bien fonctionner. Mais alors, qu'adviendra-t-il des paramètres POST ? Corps/En-têtes ? Quelqu'un a-t-il des idées à ce sujet ?

0 votes

@nembleton Rien ne se passera avec les paramètres. Ils seront simplement transmis à votre application.

291voto

Daniel Jennings Points 2319

NOTE : La meilleure façon de procéder a été fournie par https://serverfault.com/a/401632/3641 - mais est répété ici :

server {
    listen         80;
    return 301 https://$host$request_uri;
}

Dans le cas le plus simple, votre hôte sera modifié pour être le service vers lequel vous voulez les envoyer - cela fera une redirection 301 vers le navigateur et l'URL du navigateur sera mise à jour en conséquence.

Ci-dessous la réponse précédente, qui est inefficace à cause des regex, une simple 301 est très bien comme le montre @kmindi

J'ai utilisé nginx 0.8.39 et plus, et j'ai utilisé ce qui suit :

 server {
       listen 80;
       rewrite ^(.*) https://$host$1 permanent;
 }

Envoie une redirection permanente au client.

15 votes

Je pense qu'il devrait être 80 - car il écoute pour http et dit ensuite au client de revenir en https (443).

4 votes

Cela devrait être la première réponse !

3 votes

C'est la réponse la plus contraignante.

133voto

kmindi Points 1441

Je pense que la meilleure et la seule façon de procéder est d'utiliser une HTTP 301 déplacé de façon permanente une redirection comme celle-ci :

server {
    listen         [::]:80;
    return 301 https://$host$request_uri;
}

Le site HTTP 301 déplacé de façon permanente La redirection est également la plus efficace car il n'y a pas de regex à évaluer, selon la méthode déjà mentionnée. pitfails .


Le nouveau HTTP 308 déplacé de façon permanente préserve la méthode Request et est supporté par les principaux navigateurs . Par exemple, en utilisant 308 empêche les navigateurs de changer la méthode de requête de POST à GET pour la demande de redirection.


Si vous voulez préserver le nom d'hôte et le sous-domaine c'est le chemin.

Ce site fonctionne toujours si vous n'avez pas de DNS car je l'utilise aussi localement. Je demande par exemple avec http://192.168.0.100/index.php et sera redirigé vers exactement https://192.168.0.100/index.php .

J'utilise listen [::]:80 sur mon hôte car j'ai bindv6only réglé sur false pour qu'il se lie aussi à la socket ipv4. changez-le en listen 80 si vous ne voulez pas d'IPv6 ou si vous voulez vous lier ailleurs.

La solution de Saif Bechan utilise le server_name qui dans mon cas est localhost mais qui n'est pas joignable par le réseau.

La solution de Michael Neale est bonne, mais selon les pitfails, il existe une meilleure solution avec la redirection 301 ;)

0 votes

C'est gentil d'essayer de le citer, mais 301 ne fonctionne pas sur HTTPS.

5 votes

Ce qui ne fonctionne pas ? la section serveur indiquée est pour le trafic http non crypté (sans s) qui doit être redirigé en permanence vers le serveur crypté (la section qui écoute sur 443 (https) n'est pas listée)

0 votes

J'ai vérifié que cela fonctionne très bien avec https et tout - @kmindi J'ai mis à jour ma réponse en référence à la vôtre - car je pense que c'est la bonne façon et cela continue à apparaître ! Bon travail.

27voto

Oriol Points 361

Dans le bloc serveur, vous pouvez également effectuer les opérations suivantes :

# Force HTTPS connection. This rules is domain agnostic
if ($scheme != "https") {
    rewrite ^ https://$host$uri permanent;
}

2 votes

Cette configuration a provoqué une boucle de redirection sur mon serveur.

0 votes

Peut-être parce qu'il y a une autre redirection en place ou que https n'est pas activé sur votre site/application.

1 votes

Aucune des autres ne semble fonctionner, sauf celle-ci. Version de nginx utilisée : nginx/1.10.0 (Ubuntu)

20voto

Aleck Landgraf Points 299

La solution ci-dessus n'a pas fonctionné avec les nouveaux sous-domaines qui sont créés en permanence. Par exemple, AAA.exemple.com BBB.exemple.com pour environ 30 sous-domaines.

J'ai finalement réussi à faire fonctionner une configuration avec les éléments suivants :

server {
  listen 80;
  server_name _;
  rewrite ^ https://$host$request_uri? permanent;
}
server {
  listen  443;
  server_name example.com;
  ssl on;
  ssl_certificate /etc/ssl/certs/myssl.crt;
  ssl_certificate_key /etc/ssl/private/myssl.key;
  ssl_prefer_server_ciphers       on;
# ...
# rest of config here
# ...
}

0 votes

Merci ! nginx renvoie soit 301 https://*/ ou annuler la demande prématurément dans les autres réponses ici. server_name _; con $host est la réponse qui a fait l'affaire. +1

1 votes

Celui-ci est optimal ! Cependant, je recommande pour certains de remplacer _ avec le domaine réel, par exemple .domain.com J'avais deux serveurs, et nginx dirigeait accidentellement l'un de mes serveurs vers le serveur par défaut.

1 votes

C'est la seule réponse qui a fonctionné pour moi, merci !

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X