réécrire http vers https avec ngnix derrière l'équilibreur de charge

13

J'utilise un équilibreur de charge Rackspace qui me permet de configurer ma clé ssl / pem à l'intérieur du panneau d'administration. Tout fonctionne bien, je peux utiliser les protocoles http et https. Mais si j'essaye de rediriger http vers https en utilisant:

server{
  listen *:80;
  server_name mydomain.com www.mydomain.com; 
  rewrite ^ https://mydomain.com$request_uri? permanent;

... je reçois une boucle de redirection. Je me rends compte que je n'écoute pas le port 443 mais c'est parce que l'équilibreur de charge a géré cela pour moi. J'ai également essayé d'envelopper la réécriture en if ($scheme ~* http){vain.

L'autre partie de ma question est que je voudrais supprimer www de l'url, puis-je le faire avec une seule réécriture? La réécriture ci-dessus ne devrait-elle pas également s'en occuper?

Merci de votre aide!

jwerre
la source
L'équilibreur de charge devrait vous envoyer une indication si la connexion était HTTPS. Demandez Rackspace. (Oh, et vous ne voulez probablement pas vous débarrasser de www ...)
Michael Hampton
Intéressant, j'examinerai cela. Pourquoi pensez-vous que je ne devrais pas me débarrasser de www?
jwerre

Réponses:

14

sciurus a raison dans la mesure où les équilibreurs de charge cloud de Rackspace définissent le X-Forwarded-Proto sur https lorsque SSL est déchargé sur l'équilibreur de charge. Afin d'éviter une boucle de redirection dans nginx, vous devriez pouvoir ajouter ce qui suit à la locationsection dans la configuration de vhost:

if ($http_x_forwarded_proto = "http") {
            rewrite  ^/(.*)$  https://mydomain.com/$1 permanent;
}

Cela devrait éviter la boucle de redirection infinie lors de la redirection des requêtes non https vers https.

slade
la source
18

En utilisant les variables serveur intégrées de nginx $request_uriet $server_namevous pouvez le faire sans utiliser d'expressions régulières. Ajoutez ce qui suit au locationbloc de votre serveur et vous avez terminé:

if ($http_x_forwarded_proto = "http") {
    return 301 https://$server_name$request_uri;
}

Cela suppose que votre équilibreur de charge envoie l'en- $http_x_forwarded_prototête avec la demande à vos instances backend. D'autres en-têtes communs incluent $http_x_forwarded_schemeet aussi juste $scheme.

Plus d'informations peuvent être trouvées dans la documentation nginx Pitfalls and Common Mistakes : https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#taxing-rewrites

Luke Peterson
la source
5
Devrait certainement utiliser return over rewrite. A voté.
designermonkey
1
Vous pouvez utiliser à la $hostplace de$server_name
Yossi
ne fonctionne pas avec nom_serveur _; il faut donc utiliser la variable $ host comme l'a suggéré @Yossi.
Razvan Grigore
1

L'équilibreur de charge vous parle toujours via http. Ce qui se passe est

  1. Le navigateur demande le port 80 sur l'équilibreur de charge
  2. L'équilibreur de charge effectue une demande de port 80 sur votre serveur Web
  3. Votre serveur web envoie une redirection à l'utilisateur
  4. L'utilisateur demande au port 443 sur l'équilibreur de charge

Les étapes 2 à 4 se répètent jusqu'à ce que le navigateur détecte la boucle de redirection et abandonne.

EDIT: pour résoudre ce problème, effectuez la réécriture uniquement lorsque l'en-tête X-Forwarded-Proto est défini sur http. Cet en-tête est la façon dont l'équilibreur de charge de Rackspace indique à votre serveur Web le protocole via lequel il a reçu la demande.

sciurus
la source
Je suppose que cela expliquerait pourquoi $ server_protocol retourne toujours HTTP
jwerre
Vous avez donc répondu pourquoi cela se produit ... des suggestions sur la façon de résoudre ce problème?
jwerre