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.
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
Votre commentaire
À 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.
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 :