Après avoir décrit signer une zone DNS sous Bind9, et ensuite comment gérer la signature d'une zone DNS avec OpenDNSSEC 1.3, je me suis rendu compte récemment que j'avais négligé d'activer la vérification des signatures DNSSEC :

ssh -v -o verifyHostKeyDNS=yes mnemosyne.daedelys.org
[...]
debug1: found 2 insecure fingerprints in DNS
debug1: matching host key fingerprint found in DNS

Ce qui comme le montre cet exemple fait dire à SSH qu'il ne peut pas vérifier les empreintes SSHFP.

Et en effet si nous demandons le drapeau ad (authentic data) dans la requête DNS :

dig +ad mnemosyne.daedelys.org in SSHFP 
; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> +ad mnemosyne.daedelys.org in SSHFP
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56640
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 5, ADDITIONAL: 6

nous ne l'avons pas dans la réponse.

Que cela ne tienne, nous allons donc configurer BIND9 pour vérifier les signatures des enregistrements.

Configuration de BIND9

J'ai installé BIND9 par les paquets d'une Debian 7 «Wheezy». Cette documentation est donc valable pour la version 9.8.4

/usr/sbin/named -v
BIND 9.8.4-rpz2+rl005.12-P1

Pour valider les signatures avec BIND9 il nous faudra ajouter dans le bloc options ( sous Debian généralement dans le fichier /etc/bind/named.conf.options) les options suivantes :

dnssec-enable
active le support DNSSEC dans BIND9
dnssec-validation
active la validation des signatures DNSSEC

soit

        // on met en place la validation DNSSEC.
        dnssec-enable yes;
        dnssec-validation yes;

La valeur auto à l'option dnssec-validation utilise une version de la clef publique de la zone DNS racine potentiellement fourni par BIND9 . La documentation de BIND9 décrit l'utilisation des ancres de confiance par ordre de préséance :

  1. la configuration faite par l'utilisateur
  2. le fichier binds.key défini par l'option bindkeys-file du bloc options (par défaut /etc/bind/bind.keys sous Debian)
  3. les valeurs compilés par défauts défini dans le fichier bin/named/bind.keys.h lors de la compilation de BIND9

La valeur yes à l'option dnssec-validation force une configuration manuelle du bloc managed-keys :

 managed-keys {
                /* root Key */
        "." initial-key         D1 D2 D3 "Key" ;
};

ici

"."
indique la zone concerné par la clef
initial-key
indique que la clé doit ếtre utilisé pour démarrer le processus demaintenance de clef décrit dans RFC 5011

Les paramètres suivants reprennent un enregistrement DNSKEY

D1
ce nombre représente les drapeaux (Flags) il vaut soit :

  • 0 : aucun drapeau de valorisé
  • 256 : le drapeau de clef de zone (Zone Key flag) est valorisé, il indique que l'enregistrement concerne une clef de zone - typiquement une clé de type ZSK (Zone Signing Key).
  • 257: Le drapeau de point d'entrée sécurisé (Secure Entry Point) est valorisé, il affirme que cette clé est utilisable comme point d'entrée pour vérifier les autres clefs - typiquement une clé de type KSK (Key Signing Key). Ce type de clef peut être utilisé pour la configuration du bloc managed-keys
D2
ce nombre représente la version du protocole, soit actuellement 3.
D3
ce nombre représente l'algorithme utilisé par la clef publique, les différentes valeurs possibles sont normalisé par l'IANA.
"Key"
la valeur de la clef publique.

Nous devenons maintenant indiquer la bonne clef publique, en essayant de valider son authenticité.

Récupération de la clef public signant la zone racine

Empreinte de l'empreinte de la clef public fournie par le gestionnaire

Nous allons ensuite récupérer l'empreinte de cette clef depuis le site DNSSEC de l'IANA Deux fichiers sont nécessaires :

gpg --verify root-anchors.asc root-anchors.xml
gpg: Signature faite le mer. 07 juil. 2010 00:49:10 CEST avec la clef DSA d'identifiant 0F6C91D2
gpg: Impossible de vérifier la signature : clef publique introuvable

GPG nous indique que nous n'avons pas la clef, nous devons donc la récupérer. Nous pouvons utiliser pour cela l'utilitaire keylookup ( paquet Debian : signing-party) en lui fournissant l'identifiant :

keylookup --keyserver pool.sks-keyservers.net 0F6C91D2
gpg: recherche de « 0F6C91D2 » sur le serveur hkp pool.sks-keyservers.net
Dialog not executeable/installed. Falling back to Whiptail
Calling GnuPG...
gpg: WARNING: standard input reopened
gpg: demande de la clef 0F6C91D2 sur le serveur hkp pool.sks-keyservers.net
gpg: clef 0F6C91D2 : clef publique « DNSSEC Manager <dnssec@iana.org> » importée
gpg: 3 marginale(s) nécessaire(s), 1 complète(s) nécessaire(s),
     modèle de confiance PGP
gpg: profondeur : 0  valables :   1  signées :   1
     confiance : 0 i., 0 n.d., 0 j., 0 m., 0 t., 1 u.
gpg: profondeur : 1  valables :   1  signées :   0
     confiance : 0 i., 0 n.d., 0 j., 0 m., 1 t., 0 u.
gpg:       Quantité totale traitée : 1
gpg:                     importées : 1

Nous pouvons maintenant vérifier le fichier :

gpg --verify root-anchors.asc root-anchors.xml
gpg: Signature faite le mer. 07 juil. 2010 00:49:10 CEST avec la clef DSA d'identifiant 0F6C91D2
gpg: Bonne signature de « DNSSEC Manager <dnssec@iana.org> »
gpg: Attention : cette clef n'est pas certifiée avec une signature de confiance.
gpg:             Rien n'indique que la signature appartient à son propriétaire.
Empreinte de clef principale : 2FBB 91BC AAEE 0ABE 1F80  31C7 D1AF BCE0 0F6C 91D2

GPG nous indique que nous ne faisons pas confiance à la clef, si nous fessions confiance à la clef nous aurions eu le résultat suivant :

gpg --verify root-anchors.asc root-anchors.xml
gpg: Signature faite le mer. 07 juil. 2010 00:49:10 CEST avec la clef DSA d'identifiant 0F6C91D2
gpg: Bonne signature de « DNSSEC Manager <dnssec@iana.org> »

Nous faisons dans le premier cas confiance sans s'être assuré de l'identité et la confiance du signataire. Pour avoir une confiance totale, nous devrions utiliser la Toile de Confiance (Web of Trust). Mais cela sort (malheureusement) du cadre de cet article.

Vérification de la clef public fournie par le gestionnaire =

Nous récupérons donc la clef par un canal non sécurisé :

dig +noall +multi  +answer DNSKEY . > root-dnskey

Les options à dig permette de :

+noall
déactive toutes les options d'affichages
+multiline
active l'affichage multi ligne
+answer
affiche l'impression des réponses

Nous obtenons ainsi un fichier root-dnskey que nous pouvons donner à l'utilitaire dnssec-dsfromkey qui permet de générer l'enregistrement DS :

dnssec-dsfromkey -f root-dnskey .
. IN DS 19036 8 1 B256BD09DC8DD59F0E0F0D8541B8328DD986DF6E
. IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32 F24E8FB5

Les options à dnssec-dsfromkey définissent :

-f root-dnskey
Le nom du fichier à lire (sous le format zone)
.
Le nom de la zone (ici la racine)

Il faut ensuite vérifier que le contenu du fichier root-anchors.xml est bien l'une des lignes de la sortie de dnssec-dsfromkey, les espaces blancs ne sont pas significatifs.

<?xml version="1.0" encoding="UTF-8"?>
<TrustAnchor id="AD42165F-3B1A-4778-8F42-D34A1D41FD93" source="http://data.iana.org/root-anchors/root-anchors.xml">
<Zone>.</Zone>
<KeyDigest id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00">
<KeyTag>19036</KeyTag>
<Algorithm>8</Algorithm>
<DigestType>2</DigestType>
<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
</KeyDigest>
</TrustAnchor>                  

Ce qui est le cas, nous pouvons donc copier la clef ZSK (Zone Signing Key) du fichier root-dnskey :

7393 IN DNSKEY 257 3 8 (
                                AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQ
                                bSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh
                                /RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWA
                                JQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXp
                                oY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3
                                LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGO
                                Yl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGc
                                LmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=
                                ) ; key id = 19036

en n'oubliant pas de mettre entre double guillemet la clef public, ce qui donne :

managed-keys {
                /* root Key */
        "." initial-key         257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQ
                                bSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh
                                /RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWA
                                JQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXp
                                oY68LsvPVjR0ZSwzz1apAWvN9dlzEheX7ICJBBtuA6G3
                                LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGO
                                Yl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGc
                                LmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=" ;
};

Attention : Pour éviter des copiés-collés sans compréhension, la clef publique dans l'exemple précédent est invalide.

Nous avons maintenant un résolveur DNS qui valide les signatures :

  dig +ad mnemosyne.daedelys.org in SSHFP

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> +ad mnemosyne.daedelys.org in SSHFP
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14441
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 5, ADDITIONAL: 5

;; QUESTION SECTION:
;mnemosyne.daedelys.org.                IN      SSHFP

Ce qui permet de faire du SSH sans soucis :

ssh -v -o verifyHostKeyDNS=yes mnemosyne.daedelys.org
[...]
debug1: found 2 secure fingerprints in DNS
debug1: matching host key fingerprint found in DNS