Forcer le https avec haproxy devant varnish (devant apache et/ou nginx)

Bon, étant assez bordélique de nature, je vais parler de comment tripatouiller varnish que j’ai un peu présenté dans le Billet de présentation de mon infra  et haproxy (dont j’ai pas encore beaucoup causé), pour forcer le https.

Donc en fait, devant Varnish j’ai un service haproxy qui tourne pour servir de terminaison TLS mais un (fort joli) dessin valant mieux qu’un long discours, voici à quoi ressemble une requête arrivant chez moi.

Schéma d'une requêtte http(s)
Paint 4 ever

Ce que j’ai essayé de (mal) représenter c’est le parcours d’une requête http(s) arrivant chez moi.
Si c’est du http, le client cause directement à Varnish qui cause au serveur « backend ».
Si c’est du https, le client cause à haproxy qui cause à Varnish qui cause au serveur « backend », c’est donc pas du TLS de bout en bout ce qui est sans doute un péché mortel chez les pastafariens.

Ceci étant dit, si je veux maintenant forcer le https, j’ai quand même un petit soucis (en fait plusieurs).
1. Le serveur de backend ne voit pas qu’il sait causer en https (en tout cas joomla et wordpress ont tendance à être comme saint thomas, si leur serveur web ne cause pas sur le port 443, ils pensent être inaccessibles en https.)
2. Varnish ne peut pas systématiquement rediriger sur haproxy, puisque haproxy lui renvoie tout, ça ferait donc une boucle de redirection, ça devient lassant et pas très efficace pour servir une page web.

La solution c’est d’ajouter un header spécifique aux requêtes passant par haproxy, et de ne rediriger dans varnish que celles n’ayant pas ce header.

Alors la config dans haproxy est hyper basique, on ajoute juste une ligne dans la partie frontend : http-request set-header X-I-CAN-HAS-TLS ON

Dans varnish c’est un tout petit peu plus compliqué, il faut d’abord détecter si ce header est présent dans la partie vcl_recv :
if (req.http.X-I-CAN-HAS-TLS != « ON ») {
set req.http.x-redir = « https:// » + req.http.host + req.url;
return(synth(007, « Moved permanently »));
}

Puis dans vcl_synth on redirige à coup de http 301 :
if (resp.status == 007) {
   set resp.http.Location = req.http.x-redir;
   set resp.status = 301;
   return (deliver);
}

Ainsi, on a une redirection permanente et les moteurs de recherche se mettent à jour pour remplacer les liens de http vers https, et bien, sur on peut filtrer pour exclure certains hôtes (genre wordpress ^^) temporairement ou pas (procrastination rulez).

 

 

 

 

 

 

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *