le vendredi 22 août
Secure Socket Layer
Après avoir joué avec Apache, je me suis intéressé à un autre sujet : SSL. C'est d'ailleurs ce qui m'a prit le plus clair de mon temps. Pour faire fonctionner SSL avec Apache, en faisant tout bien dans les règles de l'art, il faut bien comprendre le fonctionnement de SSL et de ses certificats.
SSL fonctionne avec la notions de tiers de confiance. Un tiers de confiance est une entité reconnue plus ou moins universellement qui certifie l'identité, et donc les certificats qu'on lui présente. On peut citer plusieurs entités comme Thawte ou Verisign pour les connus et les plus chers (et espérons le, les plus sérieuses dans leurs opérations de vérification). Ensuite, pleins d'autres entreprises se sont vue accréditées par les deux premiers cités pour également délivrer des certificats.
Les certificats de ces autorités de certifications sont publics. Par courtoisie, les éditeurs de navigateurs livrent ceux-ci préchargés avec les certificats des autorités de confiances les plus connues. Vous pouvez bien sur rajouter tous les certificats d'autorités de confiance que vous le souhaitez. Par exemple, j'ai pour ma part importé les certificats de CACert.org, qui propose des certificats gratuits basés sur un système de vérification automatisé.
Attention, ajouter un certificat, c'est accorder sa confiance complète à l'organisme sur tous les certificats qu'il pourrait accorder par la suite, et sur tout ceux qu'il a déjà accordé. Ce n'est donc pas une décision à prendre à la légère. C'est une opération qui n'est pas naturelle, aussi, il ne faut le faire qu'une fois que l'on a compris toutes les implications que cela entraîne.
En effet, l'autorité de certification va le plus souvent vérifier que les informations contenues dans un certificat sont bien celles qui sont alléguées. Un certificat peut contenir les informations suivantes :
- le CN, common name, est l'information technique qui permettra au navigateur de s'assurer que le certificat proposé correspond bien à l'url entrée. Il s'agit du nom de domaine.
- le pays
- l'État
- le nom de l'organisation
- l'email
Dans le cas de CACert, le système ne vérifie que le nom de domaine (pour le cas le plus simple), et toutes les autres informations sont effacées du certificat.
La question qui vient à l'esprit, c'est : pourquoi vérifier qu'on parle bien au bon serveur puisqu'on a rentré son adresse dans sa barre d'adresse ? En effet, à moins que les serveurs DNS soient corrompus (risque qu'on ne peut pas exclure), la connexion se fera toujours avec le bon serveur.
Et bien, ce n'est pas aussi simple : d'une part, un serveur DNS est un serveur sur lequel vous n'avez pas forcement la main. Et il s'agit d'un tiers qui n'est pas forcement fiable. Celui de votre entreprise peut vous retourner sur l'adresse d'un proxy transparent, ou tout autre serveur. D'autre part, HTTP a été conçu pour fonctionner via des proxy qui peuvent très bien modifier ou générer les informations sans passer par le serveur auquel vous pensez vous connecter. La vérification du certificat prouve que vous vous adressez bien au serveur que souhaitez joindre, et non pas à un quelconque intermédiaire.
Mais dans ce cas, pourquoi une autorité de confiance ? Cette autorité va vérifier (par courrier, téléphone, huissier ou tout autre méthode qui lui semble pertinente) que les données contenues dans le certificat sont bien celles correspondant au propriétaire. Ainsi, Verisign vérifiera que FNAC SA, propriétaire du certificat (vous pouvez aller vérifier) est bien un nom que peut utiliser la Fnac pour son site web. Il est d'ailleurs amusant de constater que ce certificat n'utilise pas le wildcard * dans son certificat et que donc https://fnac.com ne fonctionne pas, alors que https://www.fnac.com, lui fonctionne.
Le wildcard, qu'est ce que c'est ?
Comme on a pu le constater, le certificat embarque le nom de domaine auquel il est associé. Ainsi, un certificat plo.org ne peut pas fonctionner chez bla.com. Mais c'est plus sévère que ça : un certificat www.fnac.com ne peut pas fonctionner pour fnac.com ! Cela introduit une certaine rigidité dans le système puisqu'il faut un certificat pour chaque domaine et sous domaine que l'on doit administrer. La réponse est venu de certificats wildcards, qui permettent de mettre une étoile * à la place d'un des éléments de l'url, pour que par exemple ftp.fnac.com et www.fnac.com puissent fonctionner avec le même certificat SSL qui contient *.fnac.com. Les wildcard sont très cher et difficile à obtenir auprès de Verisign ou Thawte. Vous pouvez par contre en obtenir un auprès de CACert. Malheureusement, le certificat racine de CACert n'est pas tout le temps inclus dans les navigateurs.
Est ce qu'on peut créer un certificat * ?
Oui, on peut, mais aucune autorité de confiance ne vous le signera. Tout simplement parce que vous ne pourrez jamais justifier de la propriété de tous les domaines. De plus, il vous drait des certificats comme *.*.* si vous voulez un certificat pour www.plop.org.
Et techniquement, comment ça marche ?
Du coté de l'autorité de certification (c'est à dire probablement jamais vous), c'est simple, elle se créé un certificat qu'elle signe elle même. C'est un certificat auto-signé. Sa valeur ne provient que parce qu'il est inclus dans tous les navigateurs. Ainsi, même si vous créez votre propre certificat, il a très peu de chance d'être inclus d'office dans un quelconque navigateur. Vous devrez donc demander à vos utilisateur de l'ajouter eux même, et peu seront enclin à le faire, d'autant plus qu'ils ne connaissent pas votre sérieux. La création d'un certificat passe par la création d'une paire de clé privée / publique.
# génération d'une paire de clés openssl genrsa -aes256 -out privkey.pem # génération d'un certificat auto-signé openssl req -new -x509 -key privkey.pem -out cert.pem
Attention, le fichier privkey.pem ne doit jamais être rendu publique. Sa seule utilisation sera pour la signature future de certificat. Donc, en gros, ce fichier ne bougera pas de machine.
Par contre, le fichier cert.pem est un fichier publique. Vous pouvez (ou pas) le diffuser librement. C'est ce fichier que vos utilisateurs doivent importer dans leurs navigateurs. Suivant leur modèle, cela fonctionnera tout de suite ou cela nécessitera une conversion du format PEM au format DER pour les saveurs Redmond. En tout cas, ce fichier ne contient rien de privé. Par contre, il est inutile de chercher à le modifier, il serait rendu inutilisable.
Attention encore, vous ne pourrez plus rien signer si vous perdez le certificat ou la clé.
Du coté de l'éditeur du serveur SSL (donc peut-être vous un jour), c'est légèrement plus compliqué, vous devez créer une paire de clés comme décrit précédemment (avec les mêmes réserves), ainsi qu'une demande de certificat (en effet un certificat est toujours signé, c'est la définition d'un certificat). Une fois votre demande créé, vous devez l'envoyer à une autorité quelconque pour signature. La procédure est en général un copier coller vers le site de l'autorité de certification (dont vous aurez constaté que le site est sécurisé, mais ce n'est pas indispensable). Une fois signé, vous pourrez constater que la signature de cette demande correspond à l'un des certificat préchargé dans votre navigateur.
# génération d'une paire de clés openssl genrsa -aes256 -out privkey.pem # demande de certificat openssl req -new -out demande -key privkey.pem
Là encore, la clé est privée et secrète. La demande est quant à elle publique même s'il n'y a aucun intérêt à la publier.
Pour signer votre certificat, l'autorité va faire plein de paperasse et de vérification et, entre autre, va signer votre demande, qui se muera en certificat :
# signature d'un certificat avec le certificat de l'autorité openssl x509 -CA ./cert.pem -CAkey ./privkey.pem -req -in ../servercert/demande -out ../servercert/servercert.pem -CAcreateserial
C'est à ce moment qu'elle vérifie que les informations contenues dans le certificat sont exactes. Chez CACert, ils ne certifient que le nom de domaine (pour les certificats de serveur http) et l'adresse email (pour les certificats d'adresse email). Pour vérifier un nom de domaine, ils envoient un marqueur aléatoire à l'une des adresses email trouvées dans le whois. Charge à vous d'aller lire les mails de cette adresse et d'y répondre favorablement.
L'autorité de certification doit faire d'autres démarches, comme par exemple tenir à jour une liste de révocation, etc. Le fonctionnement d'une autorité de certification est un sujet complet et je n'en parlerai pas plus maintenant.
Une fois le certificat récupérer, l'exploitation peut commencer. Dans Apache 2, il suffit de rajouter les directives suivantes dans le contexte approprié :
LoadModule ssl_module modules/mod_ssl.so <IfModule ssl_module> SSLRandomSeed startup builtin SSLRandomSeed connect builtin SSLEngine on SSLCertificateFile /home/manu/perso/web/runtime/ssl/servercert/servercert.pem SSLCertificateKeyFile /home/manu/perso/web/runtime/ssl/servercert/privkey.pem </IfModule>
Le serveur pourra ainsi s'authentifier et déchiffrer tout ce qui lui sera renvoyé.
Une dernière chose, tous les certificat possèdent une date limite d'utilisation : un certificat doit donc être renouvellé régulièrement au risque d'avoir une alerte du navigateur. Ainsi les certificats de Verisign expirent entre 2028 et 2036. Par contre, il y a fort à parier que les certificats que vous achèterez chez eux ne seront pas valable plus d'un an...
