IRC & SSL
Cette page explique un peu comment manipuler les certificats SSL et comment faire en sorte de vérifier les certificats lorsqu'on se connecte à IRC en SSL avec le client WeeChat.
Sommaire
C'est quoi ?
Un certificat est un message signé numériquement qui vous assure d'une information :
Le premier certificat qui va vous intéresser dit : "Voici K_S, la clé de irc.domain.com"
Ainsi, quand vous établissez une connexion avec irc.domain.com, vous utiliserez K_S pour chiffrer votre message afin que seul le serveur que vous cherchez à contacter puisse le déchiffrer. On ne s'intéressera pas ici à ce certificat, mais il faut comprendre qu'il est à l'origine de tout le processus.
Comment pouvez-vous être sûr que personne n'a altéré K_S sur le chemin et que donc K_S est bien la clé de irc.domain.com et non pas celle de Charlie, sur le trajet, qui peut donc lire votre message ?
Il existe un autre type de certificat qui dit "Je suis A, voici ma clé K_A, j'atteste que K_S est bien la clé de irc.domain.com"
- Le principe est que si on fait confiance à A, on peut vérifier que le message est correctement signé, et donc faire confiance à la clé K_S.
- Ainsi de suite, B se porte garant de A, etc…
En haut de la chaîne1, on finit par arriver à "Je suis X, j'atteste que K_X est bien la clé de X.", qu'on appelle un certificat racine.
Donc il y a bien un moment où il va falloir faire confiance à quelqu'un. Votre navigateur a une liste d'autorités de certification auxquelles il fait confiance pour signer d'autres certificats. Parfois, comme ici, le certificat racine est signé par les clés GPG de personnes.
Comment on manipule ça ?
On va faire joujou avec les certificats du Cr@ns.
Pour récupérer le certificat, on fait ça :
openssl s_client -showcerts -connect irc.crans.org:6697 < /dev/null
openssl est une commande qui permet de faire plein de choses, notamment de se comporter comme un client qui fait du SSL.
s_client nous met en mode client
-showcerts demande de montrer le certificat fournit par le serveur à la connexion
-connect précise où on se connecte. On se connecte au serveur irc.crans.org sur le port 6697, qui est le port par défaut du procotole IRC en SSL.
< /dev/null sert à envoyer "rien" à la commande, parce que sinon openssl attend qu'on parle avec le serveur irc, alors que tout ce qui nous intéresse nous, c'est le certificat
Attention les yeux, ça raconte plein de choses. Je ne recopie2 ici que la partie qui nous intéresse, qui est au début (s'ensuivent un certain nombre d'explications) :
--- Certificate chain 0 s:/CN=irc.crans.org i:/O=CAcert Inc./OU=http://www.CAcert.org/CN=CAcert Class 3 Root -----BEGIN CERTIFICATE----- MIIF5zCCA8+gAwIBAgIDAggAMA0GCSqGSIb3DQEBBQUAMFQxFDASBgNVBAoTC0NB […] SJIvOl1BQTp+VmIE30a/+1mVOFxXUVpbosM7QrdCFTcswl10cGaCDx2z9VfHDWCb alurbr6Awj5T7Rz/LhYYTc+8oZRbuQ239qf5 -----END CERTIFICATE----- 1 s:/O=CAcert Inc./OU=http://www.CAcert.org/CN=CAcert Class 3 Root i:/O=Root CA/OU=http://www.cacert.org/CN=CA Cert Signing Authority/emailAddress=support@cacert.org -----BEGIN CERTIFICATE----- MIIHWTCCBUGgAwIBAgIDCkGKMA0GCSqGSIb3DQEBCwUAMHkxEDAOBgNVBAoTB1Jv […] d+pLncdBu8fA46A/5H2kjXPmEkvfoXNzczqA6NXLji/L6hOn1kGLrPo8idck9U60 4GGSt/M3mMS+lqO3ig== -----END CERTIFICATE----- 2 s:/O=Root CA/OU=http://www.cacert.org/CN=CA Cert Signing Authority/emailAddress=support@cacert.org i:/O=Root CA/OU=http://www.cacert.org/CN=CA Cert Signing Authority/emailAddress=support@cacert.org -----BEGIN CERTIFICATE----- MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 […] zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD -----END CERTIFICATE----- --- Server certificate subject=/CN=irc.crans.org issuer=/O=CAcert Inc./OU=http://www.CAcert.org/CN=CAcert Class 3 Root ---
Il y a 3 certificats (0, 1, 2), dont on nous donne un bout du contenu, la partie la plus importante :
i: pour issuer, c'est-à-dire, qui émet ce certificat.
s: pour subject, c'est-à-dire, qui est attesté par ce certificat.
- Donc I se porte garant de S.
- Pour dire qui ils sont, ils utlisent des champs du certificat, tels que CN (Common Name), O (Organization), OU (Organization Unit)
Qu'est-ce qu'il faut comprendre dans tout ça ?
- Déjà, on voit que le subject 2 est aussi l'issuer 1, et le subject 1 est aussi l'issuer 0. Donc les maillons de cette chaîne s'accrochent bien les uns aux autres.
On voit aussi que l'issuer 2 et le subject 2 sont identiques, c'est le certificat racine. Ici il s'agit du certificat racine de CaCert.
Enfin, l'élément qui nous intéresse le plus là-dedans, c'est le CN du subject du certificat 0 : irc.crans.org. Si on fait confiance au certificat 2, on fera donc confiance au fait qu'on est en train de chiffrer notre communication de manière à ce que seul le serveur irc.crans.org puisse nous déchiffrer.
Faites attention, jusqu'ici, on n'a rien vérifié, on a juste regardé. Tout ça peut très bien être un tissu de mensonges. Vérifier que 2 signe correctement 1 et 1 signe correctement 0, c'est votre client qui le fera à la connexion, pour peu que vous lui ayez donné le certificat 2 en lui disant de lui faire confiance.
Dans WeeChat
Cas idéal
On va d'abord s'intéresser au cas du réseau Cr@ns, parce qu'il est facile.
Dans le shell
Pour récupérer le certificat, vous pouvez exécuter la commande de la section précédente et récupérer le certifiat racine (le 3 ème bloc) depuis -----BEGIN CERTIFICATE----- jusqu'à -----END CERTIFICATE----- inclus. Vous le copiez dans un fichier cacert.crt.
Pour vérifier que celui-ci est de confiance, vous pouvez demander à une nounou de vous le signer, ou faire un acte de foi, qu'on appelle le TOFU3.
Vous allez avoir besoin de faire ça pour chaque certificat racine des serveurs IRC auxquels vous voulez vous connecter. Vous pouvez donc les mettre chacun dans un fichier .crt et faire ensuite :
cat *.crt > allca.pem
Dans WeeChat
Il faut tout d'abord spécifier à WeeChat le fichier contenant les certificats auxquels vous faites confiance :
/set weechat.network.gnutls_ca_file ~/.weechat/ssl/allca.pem
(ce chemin n'est qu'un exemple, c'est celui que j'utilise moi)
Ensuite, créer le serveur auquel vous désirez vous connecter :
/server add crans irc.crans.org/6697 -ssl -autoconnect
Enfin, dire à WeeChat que vous voulez vérifier le certificat de ce serveur :
/set irc.server.crans.ssl_verify on
(Si vous ne faites pas ça, la valeur de irc.server_default.ssl_verify est utilisée)
Tester :
/connect crans
Si ça marche, vous devez voir quelque part :
crans -- | gnutls : le certificat de l'hôte est de confiance
Cas intermédiaire
Pour le serveur irc.ulminfo.fr le port SSL est 6666. Cependant l'authentification par certificat client (voir plus bas) n'est pas en place ici.
Cas un peu moins simple
On va prendre l'exemple de irc.hackint.org
Leur site nous apprend que le port SSL conseillé est 9999, donc allons-y :
openssl s_client -showcerts -connect irc.hackint.org:9999 < /dev/null --- Certificate chain 0 s:/C=US/ST=Florida/L=Tampa/O=Hack.INT IRC Network/CN=morgan.hackint.org i:/C=DE/O=Hack.INT IRC network/CN=hackint.org IRC network CA/emailAddress=hc@hackint.org -----BEGIN CERTIFICATE----- MIIFMzCCBBugAwIBAgIDAOAMMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNVBAYTAkRF […] qy+RMd7NzjjI7qNjHMEYF3rcQaMyuSAKaRQAgI3NpBJjSu5nt6tLWSK9OQk79iOL qxXp3vILWfAl9xou8m0sijGx1EEUV/+EyJJEFSTZhwAXtHudxO+a -----END CERTIFICATE----- --- Server certificate subject=/C=US/ST=Florida/L=Tampa/O=Hack.INT IRC Network/CN=morgan.hackint.org issuer=/C=DE/O=Hack.INT IRC network/CN=hackint.org IRC network CA/emailAddress=hc@hackint.org --- […]
Déjà, on note que irc.hackint.org résoud sur plusieurs IP, chacune donnant un certificat différent.
Un seul certificat, pas de racine.
En fait, la racine est fournie sur le site : http://hackint.org/hackint-cacert.pem
On ajoute donc ce certificat dans notre allca.pem, et comme il signe chacun des certificats différents des différentes IP de irc.hackint.org, tout roule.
Cas plus perturbant
irc.freenode.net port 6697. Aussi plusieurs IP, la chaîne ne remonte pas jusqu'à la racine, mais à un certificat de Gandi.
J'ai jouté ce certificat dans mon allca.pem.
Cas chiant
Sur irc.t411.me, port 6697, on trouve un certificat qui n'a pas de champ CN, donc WeeChat ne peut rien vérifier.
Heureusement, WeeChat propose un autre moyen de vérifier un certificat : enregistrer son fingerprint.
On récupère le certificat :
openssl s_client -showcerts -connect irc.t411.me:6697 < /dev/null > t411.bof
On affiche son fingerprint :
openssl x509 -fingerprint -in t411.bof | head -n 1 | sed s/://g
(L'appel à head puis à sed permet juste d'afficher le fingerprint sous la forme sous laquelle WeeChat le veut.)
Reste à le donner à manger à WeeChat :
/server add t411 irc.t411.me/6697 -ssl /set irc.server.t411.ssl_fingerprint B6FE630CADE147BAECF07231DBB99E621104D118 /set irc.server.t411.ssl_verify on
WeeChat vérifiera à chaque connexion que le certificat a ce fingerprint, et que donc c'est le certificat auquel vous faites confiance. Le lecteur attentif aura remarqué à ce stade, qu'il s'agit ici aussi d'un cas de TOFU.
S'authentifier avec CertFP
Une fois que vous utilisez une connexion chiffrée par le certificat d'un serveur IRC il est également possible de s'y connecter en utilisant un certificat SSL côté client. Ceci permet de s'authentifier automatiquement auprès de NickServ sans avoir à envoyer un mot de passe.
Il faut déjà avoir enregistré un compte auprès de NickServ :
/msg NickServ REGISTER <password> <email>
Une fois ceci fait, il suffit de procéder aux étapes suivantes :
Création du certificat
La commande SSL suivante permet de créer clef et certificat autosigné (ça suffira dans notre cas) et de stocker le tout dans un fichier.
openssl req -nodes -x509 -new -newkey rsa:4096 -sha512 -days 36500 -out client.pem -keyout client.pem
Pour récupérer la fingerprint :
openssl x509 -in client.pem -outform der | sha1sum -b | cut -d' ' -f1
Configurez ensuite votre client pour utiliser ce certificat.
Une fois votre client configuré, faites un premier /reconnect et identifiez vous une dernière fois auprès de NickServ avec votre mot de passe. Enfin, associez votre compte avec le certificat généré plus haut :
/msg NickServ CERT ADD #fingerprint
où #fingerprint est l'empreinte récupérée ci-dessus. Vous serez maintenant authentifié automatiquement dès que vous vous connecterez.
Configuration du client WeeChat
Il faut au préalable avoir enregistré une configuration pour le serveur du Crans dans WeeChat. On va supposer que le serveur s'appelle "crans".
Créez un dossier dans ~/.weechat (si ce n'est pas déjà fait) et déplacez-y le certificat :
mkdir ~/.weechat/ssl mv client.pem ~/.weechat/ssl
Ensuite dans WeeChat :
/set irc.server.crans.addresses irc.crans.org/6697 /set irc.server.crans.ssl on /set irc.server.crans.ssl_verify on /set irc.server.crans.ssl_cert %h/ssl/client.pem /set irc.server.crans.sasl_mechanism external /save
Configuration du client IRSSI
Déplacez le certificat client.pem dans le dossier ~/.irssi/certs/. Il faut ensuite aller modifier la configuration de votre serveur dans le fichier ~/.irssi/config :
{ address = "irc.crans.org"; chatnet = "crans"; port = "6697"; use_tls = "yes"; tls_cert = "~/.irssi/certs/client.pem"; tls_verify = "yes"; autoconnect = "yes"; }
Puis faites un /reload.
Mais en bas de ma liste, parce qu'elle est dans un ordre logique, pédagogique. C'est d'ailleurs dans cet ordre que sont présentés les chaînes de certificats sur Internet. (1)
Oui, les blocs de base64 sont bien plus long que ça, mais ils ne servent à rien sur cette page. (2)
Trust On First Use : on fait confiance la première fois, et les fois suivantes on vérifie que c'est le même. (3)