Vérification d'empreinte lors d'une connexion SSH

Lors d'une première connexion via SSH, il vous est demandé de faire confiance au serveur selon l'empreinte de la clé qui vous est proposée :

$ ssh serveur.example.net
The authenticity of host 'serveur.example.net (192.168.1.2)' can't be established.
RSA key fingerprint is e9:8b:c4:5b:8f:bc:98:07:5f:20:ff:c4:23:7f:cb:aa.
Are you sure you want to continue connecting (yes/no)?

Bien évidemment, une application scrupuleuse des pratiques de sécurité informatique voudrait que l'on vérifie auprès de l'administrateur du-dit serveur que l'empreinte correspond effectivement.

Si celui-ci a malencontreusement oublié quelle est cette empreinte, il est simple et rapide de la retrouver via la commande suivante :

$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub

Cette méthode fonctionne bien, mais ne peut malheureusement pas s'appliquer de manière large : qui est la personne à contacter ? Est-elle joignable ? N'y a t-il pas eu confusion entre le serveur prod-1 et prod-2 ?

Il faudrait donc pouvoir disposer d'une liste publiée et vérifiable, qui serait tenue à jour par l'administrateur. Une publication sur une page web accessible en HTTPS pourrait être un bon début. Un fichier texte signé via GPG serait une meilleure solution. Mais il faudrait alors savoir quelle méthode est utilisée selon le serveur ; ce qui soulève d'autres complications.

Sachant que le service DNS propose de publier des enregistrements de chaîne de caractères (TXT, voir la RFC 1035 paragraphe 3.3.14) il y aurait là une possibilité intéressante : créer un enregistrement TXT correspondant au serveur et proposant l'empreinte souhaitée.

$ dig +short TXT serveur.example.net
"e9:8b:c4:5b:8f:bc:98:07:5f:20:ff:c4:23:7f:cb:aa"

Effectivement avec une petite requête DNS nous obtenons l'information sans déranger personne et la vérification peut se faire de visu.

Sauf qu'utiliser un enregistrement TXT est finalement une solution "bricolée" ; il existe une solution plus élégante : un enregistrement SSHFP. SSHFP ? Pour SSH FingerPrint et qui est présenté dans la RFC 4255.

La mise en place est un peu différente : il faut cette fois préciser l'algorithme de signature utilisé (RSA ou DSA) et le type de fingerprint utilisé. Pour ce dernier, les choses sont simples, il n'y a que SHA1.

L'enregistrement de l'empreinte ne correspond pas directement à celle-ci mais doit être généré via la même commande ssh-keygen mais avec une autre option :

$ ssh-keygen -r serveur.example.net
serveur.example.net IN SSHFP 1 1 be118d5c121604d82f1d867b9ed0345a5bde8d7c
serveur.example.net IN SSHFP 2 1 548f43dcd0d196644942b11ff609dcabb82231f4

Sont proposés les enregistrements pour une signature RSA (code 1) et DSA (code 2) à inclure dans notre fichier de zone DNS ; nous n'utiliserons que le premier.

Nous pouvons procéder à une nouvelle requête pour retrouver l'information :

$ dig +short SSHFP serveur.example.net
1 1 BE118D5C121604D82F1D867B9ED0345A5BDE8D7C

Mais quel est donc l'intérêt de cet enregistrement ? Il n'est pas possible de le comparer directement à l'empreinte proposée lors de la connexion SSH initiale, ce n'est pas plus pratique qu'un enregistrement TXT.

De fait, l'intérêt n'est pas pour l'utilisateur humain, il faut se reposer sur les facilités proposées par le client OpenSSH qui propose une option à cet effet :

$ ssh -o "VerifyHostKeyDNS ask" serveur.example.net
The authenticity of host 'serveur.example.net (192.168.1.2)' can't be established.
RSA key fingerprint is e9:8b:c4:5b:8f:bc:98:07:5f:20:ff:c4:23:7f:cb:aa.
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?

Toute la magie se retrouve dans l'indication Matching host key fingerprint found in DNS.

Reste que cette solution ne fonctionne à ma connaissance qu'avec le client OpenSSH ; je n'ai pas testé ce qui est disponible avec d'autres clients comme PuTTY par exemple.

Il semble donc nécessaire de proposer à la fois un enregistrement SSHFP et TXT pour annoncer les empreintes d'un serveur SSH selon que le client soit capable ou non de faire une vérification automatique (et pour une vérification manuelle, je rappelle que la commande dig est disponible pour MS Windows dans le paquet BIND prévu pour cette plate-forme).

Reste un dernier point non négligeable : DNS n'est pas une source d'information fiable. Pour remédier à cela il faudra mettre en place DNSSEC.

Ce qui sera le sujet d'un futur article.

publié le 9 décembre 2010