Drupal 8 , HTTPS et Varnish

Autrefois réservé aux sites demandant des informations critiques, l'utilisation du protocole HTTPS (HTTP + SSL/TLS) est maintenant devenue beaucoup plus populaire. Les initiatives comme Let's Encrypt et le classement amélioré dans Google et les éditeurs de navigateurs, qui marquent comme "non sécurisé" l'usage du protocole HTTP, poussent le monde du web à chiffrer les communications entre les utilisateurs et les serveurs.

Drupal s’accommode assez simplement du HTTPS, la plus grosse partie de la configuration étant à faire côté serveur HTTP. Les complications apparaissent quand on souhaite mettre en place un reverse proxy (ou un proxy cache).

L'exemple le plus commun, pour nous, est l'utilisation de Varnish pour mettre en cache un maximum de données et ainsi améliorer efficacement les performances. Le souci dans ce cas, vient du fait que Varnish ne sait veut pas gérer les communications chiffrées, il faut donc mettre en place une architecture un peu particulière pour réussir à mixer sécurité et performances dans cette situation.

L'idée principale pour réussir cela est de faire ce que l'on appelle techniquement du SSL Offloading ou SSL Termination. Il s'agit de déchiffrer la communication juste avant de passer le flux au reverse proxy. Ainsi, la suite de l'échange se fait en HTTP entre le proxy et le Drupal (qui sont supposés être sur le même serveur ou dans un réseau sécurisé).

Mais il reste encore un soucis dans ce cas, c'est la réponse de Drupal. Étant donné que les visites initiales se font en HTTPS mais que Varnish requête Drupal via le serveur web en HTTP (port 80), Drupal va retourner des pages pouvant contenir des liens en HTTP (l'inclusion des styles ou des javascripts dans certains cas particuliers). Et là, patatra, le visiteur consulte un site en HTTPS mais, reçoit une page en contenu mixé (certaines URLs en HTTP et d'autres en HTTPS) ce qui n'est pas bien accepté par les navigateurs.

Heureusement, ce phénomène est connu et Drupal est capable de se forcer à répondre comme s'il était directement consulté en HTTPS.

Voici un petit schéma présentant le fonctionnement global.

schema général

Dans notre cas nous utilisons le reverse proxy Pound pour mettre fin au chiffrage. Il s'installe simplement et se configure tout aussi simplement. Voici un extrait de la configuration dans laquelle on définit sur quel port il écoute et vers quel port et adresse il va renvoyer la requête. Lors du transfert Pound va utiliser la clé que l'on aura précédemment générée pour déchiffrer le trafic.

Fichier /etc/pound/pound.cfg
[...]
ListenHTTPS
  HeadRemove "X-Forwarded-Proto"
  AddHeader "X-Forwarded-Proto: https"
  Address 0.0.0.0
  Port 443
  ReWriteLocation 0
  Cert "/etc/ssl/pound/server.pem"

  Service
    Backend
      Address 127.0.0.1
      Port 8080
    End
  End

End

On notera en particulier la mise en place de l'en-tête X-Forwarded-Proto à la valeur https. Ce point est essentiel au fonctionnement, c'est en effet cet en-tête qui est utilisé par Drupal pour savoir si la requête s'est faite via une connexion chiffrée et s'il doit donc répondre lui-même en HTTPS.

L'étape suivante est le passage par Varnish. Ici la configuration est plus longue et plus complexe pour gérer spécifiquement Drupal mais reste quasi identique à ce que l'on fait normalement pour du HTTP. Heureusement, il existe de multiples exemples notamment sur le site de Varnish : https://www.varnish-software.com/wiki/content/tutorials/drupal/drupal_vcl.html ou de Drupal : https://www.drupal.org/docs/7/caching-to-improve-performance/varnish-cache

Le point spécifique pour HTTPS, prendre en compte l'en-tête X-Forwarded-Proto dans le hash de requête

[...]
sub vcl_hash {
  # Called after vcl_recv to create a hash value for the request. This is used as a key
  # to look up the object in Varnish.
  [...]

  # Use special internal SSL hash for https content
  # X-Forwarded-Proto is set to https by Pound
  if (req.http.X-Forwarded-Proto ~ "https") {
    hash_data(req.http.X-Forwarded-Proto);
  }
[...]
}

Enfin côté Drupal 8, si l'en-tête X-Forwarded-Proto existe nous devons seulement le prévenir de la présence d'un reverse-proxy.

Fichier /sites/default/settings.php
[...]

$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = array('127.0.0.1');

Sinon, il est possible de spécifier l'en-tête qui contient le protocole utilisé.

$settings['reverse_proxy_proto_header'] = 'X-Forwarded-Proto';

Une fois tout cela fait, votre Drupal devrait correctement répondre avec des URLs en HTTPS, tout en profitant du cache de Varnish.

 

Crédit photo : https://pxhere.com/en/photo/556325

Commentaires

regilero Mardi 19 septembre 2017 - 16:32
Personnellement je ne conseille pas l'utilisation de pound en 2017, le projet est un peu au point mort depuis 2015 (avec des fixs de sécurité dans ses versions expérimentales 2.8a uniquement). Dans la mesure où le terminateur SSL est le premier point de contact avec l'extérieur il vaut mieux qu'il soit bien robuste. Haproxy ou Nginx sont aujourd'hui de bien meilleurs terminateurs SSL. Mais sinon l'essentiel de l'article reste valable, et précieux.
En réponse à par regilero
Bès Mardi 19 septembre 2017 - 18:08
Merci pour l'information ! Il est vrai que parfois on a de vieux mauvais réflexes, je ne connaissais HAProxy que de nom, je viens de tester une installation. Je vais mettre à jour l'article avec tout ça.
DuaelFr Lundi 24 juin 2019 - 14:42

On me souffle dans l'oreillette que la façon qu'a Drupal de gérer les headers venant du reverse proxy ont changé depuis la version 8.7 afin de se rapprocher de la façon dont Symfony le gère. Il faut donc désormais lister les headers autorisés à l'aide de constantes de l'objet Request comme suit :

$settings['reverse_proxy_trusted_headers'] = 
  \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_FOR | 
  \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PROTO | 
  \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PORT;

Votre commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.
Votre adresse servira à afficher un Gravatar et à vous notifier des réponses. Votre commentaire sera anonymisé si ce billet est dépublié pendant plus de 3 mois.
Pour lutter contre le spam notre système enregistre votre adresse IP et votre adresse e-mail si vous la partagez.
Nous vous invitons à consulter notre politique de confidentialité pour comprendre les traitements faits de ces données et comment les rectifier.

À propos de Guillaume

Co-fondateur - Expert technique

Drupalophile depuis 2007, j'ai d’abord construit et développé des sites seul pour Aliasource avant de rapidement rejoindre l’équipe de France 24 où j'ai pu me pencher sur les problématiques liées au déploiement “live” et à la gestion d’environnements multiples pour un site de presse.
J'ai ensuite développé mes compétences au sein de Linagora dans l’encadrement technique des équipes, la formation, l’accompagnement projet et les méthodes agiles.