56 votes

Comment rediriger HTTPS vers HTTP sur NGINX?

Y a-t-il un moyen de rediriger les demandes HTTPS vers HTTP en ajoutant une règle dans le fichier vhost du domaine?

56voto

Srikar Appal Points 26892

Pourquoi quelque chose comme ça est-il utile? Au premier regard, je n'étais pas sûr que cela puisse être fait. Mais cela posait une question intéressante.

Vous pourriez essayer de mettre une déclaration de redirection dans votre fichier de configuration et redémarrer votre serveur. Deux possibilités pourraient se produire:

  1. Le serveur émettra la redirection - ce que vous semblez vouloir.
  2. Le serveur effectuera d'abord l'échange https, puis émettra la redirection, dans ce cas, quel est l'intérêt?

J'ajouterai plus si je trouve quelque chose de plus concret.

MISE À JOUR: (quelques heures plus tard) Vous pourriez essayer ceci. Vous devez mettre ceci dans votre fichier nginx.conf -

server {
       listen 443;
       server_name _ *; 
       rewrite ^(.*) http://$host$1 permanent;
 }

Envoie une redirection permanente au client. Je suppose que vous utilisez le port 443 (par défaut) pour le https.

server {
    listen      80;
    server_name _ *;
    ...
}

Ajoutez ceci pour que vos requêtes http normales sur le port 80 ne soient pas perturbées.

MISE À JOUR: 18 décembre 2016 - server_name _ devrait être utilisé au lieu de server_name _ * dans les versions nginx > 0.6.25 (merci à @Luca Steeb)

51voto

Zenexer Points 4192

rewrite et if devraient être évités avec Nginx. La célèbre phrase est : "Nginx n'est pas Apache" : en d'autres termes, Nginx a de meilleures façons de gérer les URL que la réécriture. return fait toujours techniquement partie du module de réécriture, mais il ne comporte pas le surcoût de rewrite, et n'est pas aussi sujet aux problèmes que if.

Nginx a une page entière sur pourquoi if est "maléfique". Il fournit également une page constructive expliquant pourquoi rewrite et if sont mauvais, et comment vous pouvez contourner cela. Voici ce que la page a à dire concernant rewrite et if :

C'est une façon incorrecte, fastidieuse et inefficace de le faire.

Vous pouvez résoudre ce problème de manière appropriée en utilisant return :

server {
    listen 443 ssl;

    # Vous aurez besoin d'un certificat générique si vous souhaitez spécifier plusieurs
    # noms de domaine ici.
    server_name domain.example www.domain.example;

    # Si vous avez un certificat partagé entre plusieurs serveurs,
    # vous pouvez les déplacer en dehors du bloc `server`.
    ssl_certificate /chemin/vers/cert.pem;
    ssl_certificate_key /chemin/vers/cert.key;

    # 301          indique une redirection permanente. Si votre redirection est
    #              temporaire, vous pouvez la changer en 302 ou omettre le numéro
    #              complètement.
    # $http_host   est le nom d'hôte et, le cas échéant, le port - contrairement à $host,
    #              qui ne fonctionnera pas sur des ports non standard
    # $request_uri est l'URI brute demandée par le client, y compris éventuellement
    #              une chaîne de requête
    return 301 http://$http_host$request_uri;
}

Si vous attendez beaucoup de robots n'envoyant pas d'en-tête Host, vous pouvez utiliser $host au lieu de $http_host tant que vous restez sur les ports 80 et 443. Sinon, vous devrez dynamiquement remplir un substitut $http_host. Ce code est efficace et sûr tant qu'il apparaît à la racine de server (plutôt que dans un bloc location), malgré l'utilisation de if. Cependant, vous devriez utiliser un serveur par défaut pour que cela soit applicable, ce qui devrait être évité avec https.

set $request_host $server_name:$server_port;
if ($http_host) {
    set $request_host $http_host;
}

Si vous souhaitez imposer SSL/TLS pour des chemins spécifiques, mais l'interdire autrement :

server {
    listen 443 ssl;
    server_name domain.example;

    ssl_certificate /chemin/vers/cert.pem;
    ssl_certificate_key /chemin/vers/cert.key;

    location / {
        return 301 http://$host$request_uri;
    }

    location /secure/ {
        try_files $uri =404;
    }
}

server {
    listen 80;
    server_name domain.example;

    location / {
        try_files $uri =404;
    }

    location /secure/ {
        return 301 https://$http_host$request_uri;
    }
}

Si votre serveur n'est pas en communication directe avec le client - par exemple, si vous utilisez CloudFlare - les choses se compliquent un peu. Vous devrez vous assurer que tout serveur en communication directe avec le client ajoute un en-tête X-Forwarded-Proto approprié à la requête.

L'utilisation de ceci est une proposition compliquée ; pour une explication détaillée, consultez IfIsEvil. Pour que cela soit utile, le bloc if ne peut pas être à l'intérieur d'un bloc location, pour diverses raisons complexes. Cela force l'utilisation de rewrite pour les tests d'URI. En bref, si vous devez utiliser ceci sur un serveur en production... ne le faites pas. Pensez-y de cette façon : si vous avez dépassé Apache, vous avez dépassé cette solution.

/secure, /secure/, et tout ce qui est dans /secure/ imposera https, tandis que toutes les autres URI imposeront http. La construction PCRE (?!) est une assertion de recherche négative. (?:) est un groupe non capturant.

server {
    # Si vous utilisez https entre les serveurs, vous devrez modifier le bloc listen
    # et vous assurer que les déclarations ssl_* appropriées sont présentes ou
    # héritées.
    listen 80;
    server_name domain.example;

    if ($http_x_forwarded_proto = https) {
        rewrite ^(?!/secure)/ http://$http_host$request_uri? permanent;
    }
    if ($http_x_forwarded_proto != https) {
        rewrite ^/secure(?:/|$) https://$http_host$request_uri? permanent;
    }
}

6voto

ansiart Points 1666
emplacement / {
    si ($scheme = https) {
        réécrire ^(.*)? http://$http_host$1 permanent;
    }
}

6voto

mc0e Points 414

Cette question aurait été mieux adaptée au site serverfault.com.

Une meilleure façon de rediriger vers http:

server {
   listen 443;
   return 301 http://$host$request_uri;
}

Cela évite à la fois la clause 'if' et l'expression régulière dans la réécriture qui sont des fonctionnalités des autres solutions à ce jour. Les deux ont des implications en termes de performance, bien que en pratique, il faudrait avoir beaucoup de trafic avant que cela ne soit important.

En fonction de votre configuration, vous voudrez probablement également spécifier une adresse IP dans la clause listen, et peut-être une clause servername ci-dessus. Tel qu'il est, cela s'appliquera à toutes les demandes de port 443 pour tous les noms de domaine. En général, vous voulez une adresse IP par domaine avec https, donc lier le ci-dessus à une IP est plus pertinent que de le lier à un nom de domaine, mais il existe des variations, par exemple lorsque tous les domaines sont des sous-domaines d'un domaine.

MODIFIER: La TLS est quasi universelle maintenant, et avec elle l'Identification du Nom du Serveur (SNI) qui permet des sites HTTPS sur plusieurs domaines partageant une seule IP. Il y a un bon article disponible ici

1voto

Goody Points 41

Ouvrez le fichier de configuration Nginx pour votre domaine. Ce fichier est généralement situé dans le répertoire /etc/nginx/sites-available/ sur les systèmes Linux. Ensuite, dans le bloc de serveur pour la configuration HTTPS (SSL), ajoutez les lignes suivantes pour effectuer la redirection :

    server {
    listen 443 ssl;
    server_name votre-domaine.com;
    ssl_certificate /chemin/vers/votre/certificat/ssl.crt;
    ssl_certificate_key /chemin/vers/votre/cle/privee.key;

    # Effectuer la redirection HTTPS vers HTTP
    location / {
        return 301 http://$host$request_uri;
    }

    # Les réglages de configuration SSL supplémentaires vont ici
    }

Enregistrez et quittez l'éditeur de texte, puis testez votre configuration Nginx avec :

sudo nginx -t

Si le terminal affiche "ok" et "valide", vous pouvez recharger la configuration Nginx en utilisant :

sudo systemctl reload nginx

Cette configuration redirigera toutes les demandes HTTPS vers HTTP avec une redirection 301 (permanente).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X