formations/cesi/hebergement_web/03-https.md

6.2 KiB

% Introduction au HTTPS % Sylvain Eliade — S.C.O.P. Cadoles % Mai 2019

Introduction au HTTPS

  • HTTP encapsulé dans une connexion chiffrée
  • Historiquement avec le protocole SSL
  • Aujourd'hui c'est TLS

Chiffrement à clé publique et privée

  • La clé publique est distribuée (non secrète) et ne sert qu'à chiffrer
  • La clé privée est secrète et sert à déchiffrer

Le serveur possède une clé privée (secrète) et une clé publique (appelée certificat), signée par une autorité.


Certificats

  • Prouve l'identité du propriétaire du certificat
  • Doivent être signés par une autorité reconnue (ou plusieurs)
  • Peuvent être signés par soi-même (self signed) mais c'est relou (difficile à utiliser), et du coup ça ne prouve pas grand chose

Autorités

  • Système hiérarchique (une autorité peut signer des certificats d'une sous-autorité, etc.) : on parle de chaîne de certificats
  • Combine des acteurs publics (états, ministères, etc.) et privés (entreprises)
  • On doit avoir confiance envers ces autorités
  • Chaque OS a un « app store » de certificats d'autorités (paquet ca-certificates dans Debian/Ubuntu)
  • Système centralisé, moyennement sûr (nombreux cas d'autorités qui font n'importe quoi)
  • Un peu mieux depuis Let's Encrypt

Phase de négociation (handshake) TLS


En simplifié :

  1. Le client se connecte au serveur, lui indique les protocoles cryptographiques qu'il supporte (cipher suite)
  2. Le serveur lui répond, en indiquant le protocole choisi, ainsi que son certificat public (signé par une autorité).
  3. Le client vérifie le certificat.
  4. Échange de clé entre le client et le serveur. Cette clé est spécifique à cette session entre client et serveur.

Ensuite le client et le serveur communiquent en HTTP entre eux, mais tout est chiffré à l'aide des clés échangées.


La phase de négociation ne se reproduit pas à chaque requête HTTP : normalement la connexion TLS reste ouverte une ou deux minutes, permettant de faire passer d'autres requêtes.

De même, les étapes 1 à 3 peuvent être ignorées quand le serveur et le client se connaissent déjà et ont encore les infos de chacun en cache.


Vérification OCSP

A l'étape 3, le client peut aller vérifier auprès d'un serveur OCSP (Online Certificate Status Protocol) que le certificat du serveur est bien valide.

De nos jours, le serveur peut s'en charger lui-même (OCSP stapling), il envoie une certification OCSP (avec la date) au client : évite un aller-retour du client avec le serveur OCSP.


SNI (Server Name Indication)

Rappel du HTTP : le nom d'hôte demandé est transmis dans l'entête Host de la requête HTTP.

Donc : l'hôte demandé est dans la requête chiffrée, AVANT que le serveur web ne puisse savoir quel certificat utiliser pour le HTTPS !

Solution : le SNI !


  • Le nom d'hôte demandé est inscrit dans la connexion TLS par le client
  • Très bien supporté de nos jours (si pas supporté : utilisation du vhost par défaut)
  • Inconvénient : le nom n'est pas chiffré (possibilité d'interception pour voir quel site vous visitez)

Configuration Apache HTTPS

Attention : il faut créer un vhost différent, car le port est différent.

<VirtualHost *:443>
	ServerName cesi.test
	SSLEngine on
	SSLCertificateFile "/var/www/certs/cesi.cert"
	SSLCertificateKeyFile "/var/www/certs/cesi.private"
</VirtualHost>

Si on a un site en HTTPS il est recommandé que la version HTTP ne fasse que rediriger vers le site en HTTPS (plus simple niveau config serveur).


Let's Encrypt

  • Autorité de certification à but non lucratif qui délivre des certificats signés gratuits.
  • Avant LE, il fallait payer (en général cher) pour avoir un certificat signé par une autorité !
  • Inconvénient : durée du certificat limitée à 90 jours.
  • Inconvénient : ne marche pas pour les domaines privés (réseau privé).
  • Plusieurs manières de valider qu'on est bien propriétaire d'un domaine : HTTP ou DNS
  • Plusieurs clients : certbot, dehydrated, etc.

Let's Encrypt : certbot

  • # apt install certbot python-certbot-apache
  • # certbot --apache

C'est tout, il va poser des questions et va tout configurer à votre place… Mais des fois ça ne marche pas trop du coup quand notre configuration est un peu complexe.


Let's Encrypt : dehydrated

Plus léger que certbot, un peu plus manuel.

  • # apt install dehydrated dehydrated-apache2
  • Ajouter les noms de domaine dans le fichier /etc/dehydrated/domains.txt (un par ligne)
  • Lancer dehydrated -c
  • Configurer son vhost :
SSLCertificateFile  /var/lib/dehydrated/certs/example.org/fullchain.pem
SSLCertificateKeyFile /var/lib/dehydrated/certs/example.org/privkey.pem

Tester la config et recharger Apache.


Attention !

Dans certains cas, apache2ctl configtest ne renvoie pas d'erreur s'il y a un problème au niveau des certificats, mais ensuite le reload (ou graceful) plantera !

Exemple : si on utilise chain.pem de Let's encrypt (qui ne contient que la chaîne de certification, et pas le certificat lui-même) à la place de fullchain.pem.

Solution : vérifier /var/log/apache2/error.log après un reload si on a modifié des trucs dans la config SSL !


Exercice 1

Installer dehydrated et le configurer pour le domaine cesi.sylvain.eliade.net. Lancer dehydrated.

Il va tenter de vérifier l'appartenance du domaine et échouer (logique). A la place, prendre les fichiers .pem fournis et les recopier dans le bon répertoire.

Configurer un vhost Apache pour ce domaine, utilisant les certificats fournis. Ne pas oublier d'activer mod_ssl : a2enmod ssl et redémarrer Apache.

Dans /etc/hosts inscrire une ligne avec 127.0.0.1 cesi.sylvain.eliade.net.

Tester la config avec curl, et si possible le navigateur de la machine hôte.

Exercice 2 (facultatif)

Générer un certificat auto-signé :

# mkdir /etc/ssl/localcerts/
# openssl req -new -x509 -days 365 -nodes -out /etc/ssl/localcerts/apache.pem -keyout /etc/ssl/localcerts/apache.key

Le mettre en place dans Apache, et vérifier que ça fonctionne avec un navigateur (qui affichera un message d'avertissement).