SwordArMor

Comprendre les grands principes du SSL/TLS

Histoire et terminologie

SSL est un acronyme anglais voulant dire Secure Sockets Layer. Il a été initialement développé par Netscape Communications (qui a développé Netscape Navigator qui a servi de base à Mozilla pour firefox). Il existe en trois versions : SSLv1, SSLv2 et SSLv3. Aucune de ces versions n’est plus utilisée de nos jours (ou alors par des gens inconscients) car il est possible d’utiliser des failles inhérentes au protocole afin de déchiffrer le trafic.
Il a ensuite été remplacé par TLS (pour Transport Layer Security). Ce dernier existe également en trois versions : TLSv1.0, TLSv1.1 et TLSv1.2. Une version 1.3 est actuellement en cours de développement mais encore au stade de brouillon à l’IETF.
Par abus de langage, et comme je vais le faire tout au long de cet article, on utiliser souvent le terme SSL pour parler de TLS.

Cas d’usage

Le SSL est un standard de chiffrement très utilisé sur Internet. Par exemple, vous l’utilisez en visitant ce blog ainsi que tous les sites dont l’URL commence par https://.
Il est également utilisé dans le mail, avec jabber, sur IRC, etc.

Grands principes

Chiffrement

Comme beaucoup de protocoles de chiffrement de nos jours, SSL se base sur de la cryptographie asymétrique, c’est à dire avec une clé publique et une clé privée. La clé publique est le certificat, généré par une autorité de certification comme nous le verrons plus tard et la clé privée est générée (ainsi que le CSR) par l’administrateur du serveur et y reste ; c’est le propre d’une clé privée, sinon elle n’est plus tellement privée et il y a un souci. Comme toujours, la clé publique est dérivée de la clé publique et l’une ne peut pas fonctionner sans l’autre.
Cependant, comme le chiffrement asymétrique coûte cher en ressources, une fois la session établie entre le client et le serveur, une clé symétrique est négociée pour une durée limitée et c’est cette clé qui servira à chiffrer les données qui transitent.
Nous n’utilisons pas une clé symétrique dès le début car dans ce cas, tout le monde devrait connaître cette clé pour déchiffrer du contenu, et donc tout le monde pourrait ré-utiliser cette clé pour se faire passer pour le serveur (et donc intercepter le trafic chiffré et en connaître le contenu).

Authentification

Dans un contexte de chiffrement se pose toujours la question de l’authenticité du pair avec lequel on discute. En effet, ce n’est pas le tout de chiffrer pour empêcher les grandes oreilles de mettre leur nez où elle ne devrait pas, mais encore faut il le faire avec la bonne personne.
Admettons que vous chiffriez une conversation mais en se connectant au mauvais serveur. Ce serveur peut très bien déchiffrer ce qui passe, le lire et le re-chiffrer pour l’envoyer à qui de droit. Tout l’intérêt du chiffrement est donc perdu et personne ne se rendrait compte de la supercherie.
Généralement, on se contente de vérifier l’identité du serveur, mais on peut aussi vérifier celle du client. Dans le cas du serveur, on se base généralement sur le nom de domaine (www.swordarmor.fr pour ce qui nous concerne) et dans le cas du client on se base généralement sur l’adresse mail (alarig@swordarmor.fr en ce qui me concerne).

Afin de répondre à ce problème, nous faisons intervenir un tiers de confiance (sic), ce sont les fameuses CA – pour Certification Autorities en anglais, soit autorités de certification en français. Il s’agit de grands organismes en charge de distribuer – souvent contre finances – des certificats x509 (du nom de la norme qui les défini) aux personnes physiques ou morales qui en font la demande. On dit aussi « signer un certificat ».
Ces organismes ont leur propre certificat déjà enregistré dans les navigateurs (dans le cas du web, mais c’est le cas pour tout client supportant le SSL). Votre certificat ayant été signé par une de ces entités, le navigateur peut vérifier sa validité en établissant une chaîne de confiance. Théoriquement, ça semble sympathique, sauf qu’en fait non. Toute CA enregistrée dans le navigateur peut émettre n’importe quel certificat, y compris des certificats pour des noms de domaines qui ont déjà été singés. Ainsi, une autorité peu scrupuleuse peut parfaitement fournir des certificats valides sans se préoccuper de savoir si la personne qui en fait la demande le fait légitimement ou non. On peut par exemple citer Symantec qui signe des certificats pour les proxy de Blue Coat Systems, ces derniers pouvant donc intercepter le trafic SSL qui y passe ; et on sait que cette entreprise est pour le moins controversée.

Intégrité

SSL est aussi en charge de s’assurer que les données n’ont pas été altérées entre ce que le serveur a envoyé et ce que le client a reçu. En effet, il est nécessaire de s’assurer que les données reçues par le client sont bien celles envoyées par le serveur et qu’elle n’ont pas été modifiées sur le chemin.
C’est là qu’intervient la HMAC. Il s’agît d’un calcul mathématique relativement compliqué se basant sur une fonction de hachage cryptographique combiné avec une clé secrète.

En pratique

Afin de proposer votre site en HTTPS, vous devez disposer d’un HTTPd compatible avec le SSL. C’est le cas de la plupart d’entre eux. Pour ne pas m’éterniser sur des exemples de configuration, je me contenterai de nginx et apache2.

Génération d’un CSR et d’une clé privée

Le CSR est un fichier que devrez envoyer à l’autorité de certification afin qu’elle vous signe un certificat. Ce CSR doit à minima contenir le nom qui doit être certifié (soit le nom DNS du site dans notre cas) mais il est possible d’y ajouter d’autres champs comme la localisation ou l’identité de l’organisation qui demande le certificat. Le FQDN doit être donné à la question « Common Name (e.g. server FQDN or YOUR name) ». Nous devons aussi générer la clé privée associée au futur certificat.
La génération se fait avec openssl (ou libressl ;).

openssl req -nodes -newkey RSA:4096 -keyout exemple.org.key -out exemple.org.csr
Une fois que le CSR est généré, transmettez le à l’autorité de certification et elle vous donnera un certificat. Placez le tout dans /etc/ssl/httpd/.
Ensuite, assurez vous que la clé ne soit pas ouverte à tous vents. Un petit chmod 600 /etc/ssl/httpd/exemple.org.key ne fera pas de mal.

Je ne copie ici que la partie spécifique au SSL, le reste du fichier de configuration est le même.

nginx

server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;

	ssl_certificate		/etc/ssl/httpd/exemple.org-chained.crt;
	ssl_certificate_key	/etc/ssl/nginx/exemple.org.key;
Nous remarquons que j’ai donné le fichier /etc/ssl/httpd/exemple.org-chained.crt et non /etc/ssl/httpd/exemple.org.crt comme certificat. En effet, afin de reconstituer la chaîne de certificats, le client HTTP a besoin que l’on lui envoie le certificat racine de la CA qui a signé le certificat. On chaîne donc les deux certificats dans un seul. Pour cela il faut télécharger le certificat racine depuis le site de la CA puis concaténer les deux :
cat /etc/ssl/httpd/exemple.org.crt $root_ca_cert.crt > /etc/ssl/httpd/exemple.org-chained.crt
Les plus avisés d’entre vous auront peut-être remarqué le http2 sur les lignes listen. Ce mot clé indique à nginx de supporter le protocole HTTP/2 en plus de HTTP/1.0 et HTTP/1.1 ; il est optionnel.

apache2

<VirtualHost *:443>
	SSLEngine		on
	SSLCertificateFile	/etc/ssl/httpd/exemple.org.crt
	SSLCertificateKeyFile	/etc/ssl/nginx/exemple.org.key
	SSLCACertificateFile	/etc/ssl/certs/$root_ca_cert.crt
	SSLVerifyClient		None
Contrairement à nginx, apache demande la certificat racine et le certificat du serveur dans un fichier séparé.

Complément

J’avais écrit une doc similaire à destination des administrateurs de grifon dans ma jeunesse. Elle vous permettra peut-être d’éclaircir des points qui ne le sont pas ici.

Supplément

Comme nous avons pu le constater, il existe quelques bémols au HTTPS dûs à la conception de x509. Il existe des moyens de s’en prévenir, mais ils sont encore peu développés. J’ai appelé le DANE et le TLSA : The DNS-Based Authentication of Named Entities (DANE) Transport Layer Security (TLS) Protocol: TLSA.
Ce standard permet de publier un condensat de tout ou partie de sa chaîne de certificats (juste le sien, juste celui de la CA, juste la clé publique, etc.) dans le DNS à condition que la zone soit signée avec DNSSEC. Cela permet de se dispenser de CA car la vérification est directement faite par le client. Le wiki de grifon me semble être un bon point d’entrée pour le moment. J’écrirai un article plus détaillé ici-même plus tard.
Côté client, firefox ne supporte pas nativement la vérification du TLSA, mais les auteur de knot ont écrit un plugin prévu à cet effet, il s’appelle DNSSEC/TLSA Validator.
Avec firefox vous pouvez également vérifier que le certificat du site que vous visitez n’a pas été remplacé inopinément avec Certificate Patrol.

Les confs apache et nginx que je propose plus haut sont prévues pour « juste marcher », mais vous pouvez les durcir en empêchant les ciphers faibles ou en forçant la connexion en HTTPS sur votre site. Attention, ici j’active l’HSTS, entrez à vos risques et périls.
Pour nginx :

server {
	listen		80;
	listen		[::]:80;
	rewrite		^/(.*)$ https://exemple.org/$1 permanent;
	server_name	exemple.org
}
ssl_ciphers "AES128+EECDH:AES128+EDH";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_stapling on; # Requires nginx >= 1.3.7
ssl_stapling_verify on; # Requires nginx => 1.3.7

ssl_dhparam /etc/nginx/ssl/dhparams2048.pem;
Et pour apache :
<VirtualHost *:80>
	RewriteEngine	on
	RewriteCond 	%{HTTPS} !=on
	RewriteRule	.* https://%{SERVER_NAME}%{REQUEST_URI} [NE,R,L]

	ServerName	exemple.org
</VirtualHost>
<IfDefine SSL>
SSLCipherSuite EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
</IfDefine>

Script de regénération d’un certificat let’s encrypt à la création d’un site sur wordpress

Dans le cadre de gozmail, nous proposons également l’hébergement de blogs pour nos adhérents. Nous utilisons wordpress car il dispose d’une fonctionnalité qui permet de créer un réseau de sites. Ainsi, chaque adhérent dispose de sonsite.log.bzh et ne peut pas aller fouiner chez son voisin.

Au ...

Lire la suite

Mettre en œuvre BCP38 avec un routeur FreeBSD en utilisant pf

BCP38 (pour Best Current Practice numéro 38) est un document de l’IETF qui présente les bonnes pratiques en matière de filtrage de trafic, notamment vis à vis de l’IP source. En effet, par défaut un routeur ne regarde que les IPs de destinations afin de savoir vers où ...

Lire la suite

Gestion automatique de DNSSEC avec OpenDNSSEC et nsd

Introduction

J’avais déjà parlé du DNSSEC avec knot. Ici l’article sera similaire mais utilisera deux daemons différents, nsd pour le serveur faisant autorité et OpenDNSSEC pour la gestion du DNSSEC.
Alors là, il va y avoir des petits malins qui vont me dire « oui mais tu sais déjà ...

Lire la suite

Le MTU et le MSS

En théorie

Le MTU est la taille maximale qu’un paquet peut avoir lors de son transport sur le réseau. Elle est généralement de 1500 octets. À partir de ce MTU, nous calculons le MSS, c’est à dire la quantité maximale de données que nous pouvons atteindre dans un ...

Lire la suite

Gestion automatique de DNSSEC avec knot

Depuis quelques temps, je me suis mis au DNSSEC. Comme je suis feignant, je n’ai pas envie de re-signer ma zone à la main tous les jours :) Comme j’ai vu que knot savait gérer la signature DNSSEC comme un grand, je me suis dit que ça serait une ...

Lire la suite

Complétion de dig avec zsh

J’utilise zsh comme shell par défaut sur mon laptop. J’en suis satisfait, sauf que je n’avais pas de complétion pour la commande dig(1).
En demandant comment utiliser la complétion de bash pour cette commande, un gentil monsieur a tout simplement écrit un script de complétion pour ...

Lire la suite

Problèmes avec systemd et pourquoi j’aime l’init de BSD

Lire la suite

Mise en place d’un tunnel L2TP chiffré avec IPsec autentifié avec radius

Cette infrastructure a été mise en œuvre au sein de grifon afin de fournir un VPN le plus proche possible de la collecte ADSL.

Côté serveur

Le radius

Le radius sert à authentifier les utilisateurs et à donner les autorisations qui leur sont relatives (comme par exemple, quelle adresse IP ...

Lire la suite

Réplication master/master entre deux serveurs mail avec dovecot-dsync

En gros, ça sert à éviter de faire exploser votre queue de mails

Peut-être avez-vous déjà un serveur mail secondaire pour votre domaine, qui discutent entre eux avec du SMTP tout simple. Cela fonctionne très bien tant que le serveur principal n’est pas trop longtemps dans le noir, sinon ...

Lire la suite

Page 1 / 3 »