lalahop

DNSSEC pour 2013

Pour cette nouvelle année, j'ai décidé de signer mes zones avec DNSSEC. Ce billet est donc une sorte de retour d'expérience/un avis mélangé à un semblant de tutoriel OpenDNSSEC.

Table des matières

Ressources

Si vous débutez avec DNSSEC, je vous recommande la lecture suivante : DNS : Attaques et sécurisation.

Pour suivre la suite de ce billet, je vous recommande aussi la lecture suivante : RFC 6781: DNSSEC Operational Practices, Version 2 chez Stéphane Bortzmeyer.

Objectifs

  • Signer une zone qui se trouve en dessous de fr. La zone fr. est signée et accepte les délégations signées donc pas de problèmes particuliers à envisager.
  • Signer guiguishow.info. La zone info. est signée mais la soumission de délégations signées n'est pas encore ouverte à tous. Il faudra donc utiliser DLV et le registre DLV de l'ISC.
  • Signer des zones reverse v6 déléguées par Hurricane Electric (6in4). HE ne signe pas ses zones donc il faudra utiliser DLV et le registre DLV de l'ISC.

Note : je crois savoir que DLV est très peu utilisé. DNSSEC étant peu utilisé, en utilisant DLV, vous vous adressez à une masse très faible car l'usage de DLV pour valider une zone nécessite que le résolveur soit configuré et ce, avec le même registre DLV que celui que vous avez choisi pour soumettre votre délégation signée. Mais c'est "fun" en attendant la signature de plus de TLD.

Motivations

Mes motivations sont très simples : "for ze fun" et confronter la théorie (mes connaissances) à la réalité. Pour ce dernier point, un labo Netkit n'est pas suffisant pour avoir une vision complète de tous les aspects de DNSSEC et notamment de l'aspect opérationnel.

Données techniques

Avant de commencer, il faut bien comprendre que les bonnes valeurs pour ces "paramètres" ne sont pas fixes : les valeurs optimales sont encore en discussion (quelle durée de vie pour une clé ? pour une signature ?) et les valeurs réelles dépendent de vos choix et de votre infrastructure.

On veut que les zones soient signées hors-ligne : ce n'est pas le serveur maître faisant autorité sur la zone qui la signera.

Les paramètres des clés sont classiques. Choix du modèle à 2 paires de clés (qui n'est pas obligatoire). KSK : RSASHA256 - 2048 bits - durée de vie d'un an. ZSK : RSASHA256 - 1024 bits - durée de vie d'un mois.

Pour les signatures, une durée de vie d'une semaine est convenable.

Pour la preuve de non-existence, j'utiliserai NSEC3 : 10 itérations, sel de taille 8 changeant tous les 7 jours. Une sorte de compromis entre le RFC 5155 qui recommande de changer le sel à chaque signature et le RFC 6781 qui recommande de le changer en même temps que la ZSK. Après coup, l'usage de NSEC3 est le choix que je pourrais le plus remettre en question : mes zones sont "banales" : un SOA, des NS, un MX, un CNAME www, un A, un AAA, ... Rien qui ne puisse pas être très facilement deviné. L'usage de NSEC n'aurait pas été un problème.

La cryptographie employée par DNSSEC demande de la rigueur et une maintenance régulière sous peine de rendre une zone non-validable pendant un certain temps (qui dépend des TTL). J'ai décidé d'utiliser OpenDNSSEC, un logiciel qui prend en charge un certain nombre d'opérations (génération des clés, signature des zones, remplacement (rollover) des clés) et permet de limiter les erreurs lors de la réalisation des tâches restantes (soumission du DS à la zone parente lors d'un rollover de la KSK, par exemple).

Avant de continuer, je vous conseille les documentations suivantes concernant OpenDNSSEC :

Valider une zone en utilisant le registre DLV de l'ISC

Avant de commencer, nous allons voir comment configurer Unbound pour valider une zone en utilisant le registre DLV de l'ISC. Ce registre est simplement le plus gros registre DLV d'où mon choix pour publier mes DLV dans ce registre.

Dans un premier temps, il faut ajouter une ligne dans le fichier de configuration (/etc/unbound/unbound.conf) :

dlv-anchor-file: "/var/lib/unbound/dlv.isc.org.key"

Ensuite, il faut créer le fichier dlv.isc.org.key. Pour trouver la dernière KSK du registre en usage, voir : ISC's DLV Registry. À l'heure actuelle, mon fichier contient donc :

dlv.isc.org. IN DNSKEY 257 3 5 BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2 brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+ 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5 ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt TDN0YUuWrBNh

Un reload d'Unbound et c'est prêt.

Pour tester : DLV Test Zones par DNS-OARC. Il faut que dig vous affiche le flag "AD". Si vous avez envie de rigoler, je vous conseille de résoudre les autres noms (a.nsec.dlvtest.dns-oarc.net txt, b.nsec.dlvtest.dns-oarc.net txt, ..., z.nsec.dlvtest.dns-oarc.net txt) car chaque lettre = un mot 😀 . Oui, un rien m'amuse. 😛

Installer OpenDNSSEC

L'installation d'OpenDNSSEC sous Debian est capricieuse : le dépôt squeeze-backports fournit une version en état de marche. Pour les dépôts stable et testing, je reste bloqué sur une erreur lors du lancement des démons :

ods-enforcerd: Error creating key in repository SoftHSM
ods-enforcerd: generate key pair: CKR_GENERAL_ERROR

Ce message d'erreur apparaît sur la liste de diffusion des devs d'OpenDNSSEC mais elle n'est pas résolue. Me concernant, ce n'est pas bien grave puisque j'utilise les backports pour installer certaines des applications de mon serveur, mais je voulais le signaler.

ÉDIT du 19/05/2013 à 21h00 : Une solution se trouve en filigrane ici : [Opendnssec-user] Error creating key in repository SoftHSM. On ajoute donc l'user opendnssec au groupe softhsm (voir ci-dessous) puis on applique les droits nécessaires sur le fichier /var/lib/softhsm/slot0.db : root:softhsm, 664. Ça marche sans problèmes sur une Wheezy sans avoir recours aux backports. Fin de l'édit

Sur une Squeeze utilisant les backports, l'installation se résume à :

apt-get install softhsm opendnssec
adduser opendnssec softhsm

L'ajout de l'utilisateur opendnssec au groupe softhsm permet d'éviter l'erreur :

SoftHSM: C_Initialize: Could not open the config file: /etc/softhsm/softhsm.conf

Mise en place basique du couple SoftHSM/OpenDNSSEC

Tout est détaillé sur le blog de S. Bortzmeyer dont j'ai donné le lien ci-dessus donc je vais être léger sur cette partie.

SoftHSM

Initialiser notre HSM :

softhsm --init-token --slot 0 --label "OpenDNSSEC"

Une petite astuce en passant : si vous oubliez le SO PIN de votre SoftHSM, il y a moyen de rattraper le coup (de reinit le SO PIN). D'abord, il faut calculer le hash de votre mot de passe via la fonction de hachage sha256 :

echo -n "123412341234" | shasum -a 256 | tr '[:lower:]' '[:upper:]'

Attention : ici, le SO PIN est 1234, pas 123412341234 ! Il faut chaîner 3 fois de suite le SO PIN désiré pour obtenir le bon hash.

Ensuite, comme SoftHSM utilise, par défaut, sqlite, le changement du SO PIN revient à une simple requête SQL (en root, bien sûr) :

sqlite3 /var/lib/softhsm/slot0.db
sqlite> UPDATE Token SET value='66C782E8F95BA958F28ADAAE576C42A263C2449AF416FB844499BEF7FD41B2D0' WHERE variableID='1';

Bien sûr, remplacez "66C782E8F95BA958F28ADAAE576C42A263C2449AF416FB844499BEF7FD41B2D0" par le hash obtenu à l'étape précédente.

OpenDNSSEC

D'abord, il faut modifier le fichier /etc/opendnssec/conf.xml pour décommenter le bloc concernant le dépôt SoftHSM et changer l'user PIN voire le label du token si vous l'avez modifié lors de l'initialisation de softhsm :

        <RepositoryList>
 
                <Repository name="SoftHSM">
                        <Module>/usr/lib/softhsm/libsofthsm.so</Module>
                        <TokenLabel>OpenDNSSEC</TokenLabel>
                        <PIN>1234</PIN>
                        <SkipPublicKey/>
                </Repository>

<!--
                <Repository name="sca6000">
                        <Module>/usr/lib/libpkcs11.so</Module>
                        <TokenLabel>Sun Metaslot</TokenLabel>
                        <PIN>test:1234</PIN>
                        <Capacity>255</Capacity>
                        <RequireBackup/>
                        <SkipPublicKey/>
                </Repository>
-->
 
        </RepositoryList>

Tant qu'on est dans conf.xml, on décommente la ligne suivante :

<NotifyCommand>/usr/sbin/rndc reload %zone</NotifyCommand>

À la fin de la signature, OpenDNSSEC demandera à BIND de recharger la zone.

Ensuite, on ajoute les zones à gérer en modifiant le fichier /etc/opendnssec/zonelist.xml ou en les ajoutant avec la commande ods-ksmutil zone add. Exemple :

ods-ksmutil zone add -z example.com -p default -i /etc/bind/master.example.com -o /etc/bind/master.example.com.signed

Ici, on ajoute la zone example.com, avec la politique "default", en indiquant que le fichier de zone est /etc/bind/master.example.com et que le fichier de zone signé devra être mis dans /etc/bind/master/master.example.com.signed.

On met en place les politiques :

ods-ksmutil setup

Avant-dernière tâche, on pense à éditier son named.conf pour indiquer que le fichier à servir est celui signé, pas l'autre !

Enfin, on lance les démons OpenDNSSEC :

ods-control start

Normalement, la machine se met en route : OpenDNSSEC génère des clés (vérifiable avec la commande ods-ksmutil key list), signe la zone, la fait recharger. Votre serveur de noms devrait maintenant servir des informations signés.

Note : Si vous avez une erreur de ce type dans les logs :

stderr from sorter: /chemin/vers/le/fichier/de/zone/à/signer:7: Unknown RR:

Cela signifie que votre fichier de zone contient des lignes qui contiennent uniquement des espaces et des tabulations. Supprimez les lignes de ce genre et le signer n'échouera plus.

Utilisation de base

Pour finir la mise en place de DNSSEC, il faut attendre que les résolveurs prennent connaissances des clés. OpenDNSSEC indique la date/heure de la prochaine étape :

ods-ksmutil key list
Keys:
Zone:                           Keytype:      State:    Date of next transition:      
guiguishow.info                 KSK           publish   2013-01-11 10:32:52       
guiguishow.info                 ZSK           active    2013-02-01 23:16:34

La clé est publiée dans la zone mais ne sert pas encore à la valider. À la date indiquée, OpenDNSSEC indiquera :

ods-ksmutil key list
Keys:
Zone:                           Keytype:      State:    Date of next transition:      
guiguishow.info                 KSK           ready     waiting for ds-seen ...
guiguishow.info                 ZSK           active    2013-02-01 23:16:34

OpenDNSSEC attend donc de savoir quand le DS apparaîtra dans la zone parente. Il est temps de demander le DS et d'effectuer sa soumission dans la zone parente.

Rappel : un RR DLV a le même format qu'un RR DS, seul le type change.

D'abord, on récupère le DS :

ods-ksmutil key export --ds
;ready KSK DS record (SHA1):
guiguishow.info.	3600	IN	DS	8785 8 1 e46b5d056b0c0bb1176aaa5781676c212e6926a2

;ready KSK DS record (SHA256):
guiguishow.info.	3600	IN	DS	8785 8 2 905147c7558bf1abcc5c6accbc2ad6fcff05d2c82cb18f77e30bf2b9b981427e

Note : chez moi, DNSSEC n'a pas voulu me communiquer les DS alors qu'il m'indiquait un "waiting for ds-seen" ... Je l'ai donc forcé avec "--keystate ready".

Rappel : la soumission d'un DS avec 2 algorithmes de hachage n'est pas obligatoire mais seulement recommandée pour des questions de compatibilité avec les résolveurs qui ne supportent pas SHA256. Comme je considère qu'à moment donné, il faut faire évoluer son parc et comme ma zone utilise RSASHA256, j'ai décidé de ne publier que le hash issu de SHA256 (même si le registre DLV de l'ISC a généré celui issu de la fonction SHA1 et l'a publié automatiquement ...).

Ensuite, on soumet ce DS à la zone parente. La procédure dépend de votre bureau d'enregistrement. Dans le cas de Gandi, il faut la clé publique. Pour cela, rien de mieux, à mon avis, qu'un dig :

dig @127.0.0.1 DNSKEY guiguishow.info
guiguishow.info.	1327	IN	DNSKEY	256 3 8 AwEAAcFrABdS/Osvt5rY20EPOldFT7pFA+ubLRe4+03NpkGkUX52BBFr Vj5Ozj+9MeMC1Q40bNT/cQMZsT3YT/oVcvo+Z+WHhiaI6LV97rlOpbBS 7Q3CwEGJYIy/Qj8PeapLDvzHmXILgJypAvDUNKVPUG7JCn86VnIzesmN wEfN4MhF
guiguishow.info.	1327	IN	DNSKEY	257 3 8 AwEAAbWAbGnXj4waroP0NZLm2RD6AgITwj2wZAvA0y9pKRJRrX946yoO k6p6+gJyqmJ3A+bkEaKUySSlXSPw7xDQJFKx1lz7hivURd1K3LZM+Yc6 sNvw2QPbmpBzNIE2Y9gvrf91DjR638AEHFdVUbg/AACQLzMR16BSQKer n8Za+l+hRwTDvn4+18bXPcnt2Ju5OMssolwwKCIdKlc2VWa4pHA4nDSl o+aylNe2Y6O6jsRRM40o2AE8VAjzFgR17h+4nyT/U9M3D7j/tMo6UaZK 3LNGUB5ZaqNq5/BNumRBqbNOGnszwljWuVwF126KtlO5CzL9RufLjzoR 5ezMs8RJZ7U=

Je devais donc donner ce qui suit à Gandi :

AwEAAbWAbGnXj4waroP0NZLm2RD6AgITwj2wZAvA0y9pKRJRrX946yoO k6p6+gJyqmJ3A+bkEaKUySSlXSPw7xDQJFKx1lz7hivURd1K3LZM+Yc6 sNvw2QPbmpBzNIE2Y9gvrf91DjR638AEHFdVUbg/AACQLzMR16BSQKer n8Za+l+hRwTDvn4+18bXPcnt2Ju5OMssolwwKCIdKlc2VWa4pHA4nDSl o+aylNe2Y6O6jsRRM40o2AE8VAjzFgR17h+4nyT/U9M3D7j/tMo6UaZK 3LNGUB5ZaqNq5/BNumRBqbNOGnszwljWuVwF126KtlO5CzL9RufLjzoR 5ezMs8RJZ7U=

Le registre DLV de l'ISC est moins exigeant : un DS ou un DNSKEY brut fait l'affaire. Exemple :

guiguishow.info.	3600	IN	DS	8785 8 2 905147c7558bf1abcc5c6accbc2ad6fcff05d2c82cb18f77e30bf2b9b981427e

Note : je ne détaille pas la soumission d'une délégation signée au registre DLV de l'ISC car c'est simple (création d'un compte, création de la zone, soumission de la clé, vérification de l'identité, fin) et l'interface web est vraiment bien faite.

On attend que le DS/DLV apparaisse dans la zone parente en testant régulièrement :

dig DLV guiguishow.info.dlv.isc.org 
dig DS mondomaine.fr

Quand la réponse est positive (prenez garde au cache "négatif"), il faut prévenir OpenDNSSEC :

ods-ksmutil key ds-seen --zone guiguishow.info --keytag 8785

OpenDNSSEC marquera la clé comme étant active (clé utilisée pour signer).

Il faudra soit réaliser ces opérations lors de chaque roulement des clés, soit automatiser la procédure (soumettre la clé via l'API de votre bureau d'enregistrement + vérification automatisée de l'apparition du DS/DLV). Pour ce dernier cas, S. Bortzmeyer pointe des scripts qui réalisent ces opérations.

Lorsque vous effectuez des modifications dans vos fichiers de zones, pensez à demander un re-signe de la zone concernée :

ods-signer sign <zone>

Configuration avancée

conf.xml

Pour ma part, je n'ai pas beaucoup modifié ce fichier.

J'ai simplement :

  • activé le dépôt softHSM ;
  • changé la facility syslog (local2) afin de pouvoir séparer les logs d'OpenDNSSEC dans un fichier distinct. Une ligne ressemblant à ça suffit ensuite dans la configuration de rsyslog :
    if $syslogfacility-text == 'local2' or $programname == 'ods-enforcerd' then /var/log/opendnssec.log
    & ~
  • activé l'avertissement des rollover : OpenDNSSEC, prévient, à l'avance, via les logs, d'un rollover "imminent".
    <RolloverNotification>P7D</RolloverNotification>
  • tous les modules d'OpenDNSSEC (enforcer, signer, auditor), fonctionne avec des droits restreints. À ce sujet, la restriction de droits de l'enforcer m'a posé problème : l'enforcer ne pouvait plus se lancer. "ods-enforcerd: /var/lib/opendnssec/db/kasp.db.our_lock could not be opened" apparaissait dans les logs. Il suffit de supprimer le fichier kasp.db.lock et de relancer les démons OpenDNSSEC. En effet, ce fichier appartenait à root quand l'enforcer tournait avec les droits root. L'enforcer, qui a maintenant des droits restreints, ne peut donc pas le modifier/supprimer.

kasp.xml

C'est ici qu'il faut définir les politiques qui seront appliquées aux zones.

Sur la version issue des squeeze-backports, l'algorithme à utiliser pour les clés n'est pas celui que nous voulons : il faut mettre 8 pour RSASHA256. Il me semble aussi que la validité des signatures est trop haute (attaque par rejeu, tout ça, ...). Le reste se configure selon vos propres choix et selon les valeurs recommandées par les RFC/les usages. La documentation officielle est relativement bien faite pour vous accompagner (et ce n'est pas souvent que je dis ça).

Sur les versions récentes (debian testing, ...), les algorithmes et la durée de vie des signatures sont ceux conseillés. Il ne vous reste donc plus qu'à régler selon vos choix, selon votre zone et selon votre zone parente.

Dans mes politiques, j'ai passé le nombre d'itération NSEC3 de 5 à 10 (compromis entre les énormes valeurs conseillées par les RFC (150, ...) et les valeurs appliquées par les TLD (5, 1 voire 0)). J'ai demandé un sel NSEC3 différent tous les 7 jours. Je n'ai pas utilisé de clé de réserve car la fonctionnalité ne semble pas totalement prête (dixit la doc officielle). J'ai utilisé le format de serial "datecounter" pour mes zones.

Ensuite, j'ai adapté les paramètres de ma zone. Cela permet à DNSSEC de mieux calculer le moment propice pour chaque étape d'un remplacement des clés, par exemple. J'ai mis un PropagationDelay à PT12600S pour ma zone : refresh + retry de mes zones + marge supplémentaire. J'ai indiqué un TTL et un minimum de 3600, car c'est les valeurs utilisées par défaut par OpenDNSSEC.

Ensuite, j'ai adapté les paramètres de la zone parente. Là encore, cela permet à DNSSEC de mieux calculer le moment propice pour chaque étape d'un remplacement des clé et surtout de la KSK. J'ai laissé le PropagationDelay à PT9999S car je fais la soumission du DS à la main, donc OpenDNSSEC doit m'attendre et prendre en compte ma disponibilité dans ses calculs. Pour le TTL du DS et du SOA, il est de 172800 secondes pour la zone fr. et de 3600 pour le registre DLV de l'ISC. Pour le paramètre minimum du SOA, il est de 5400 dans la zone fr. et de 3600 dans le registre DLV de l'ISC.

Pour résumer, j'ai conservé la politique par défaut et ajouté deux politiques : une pour ma zone sous fr. et une autre pour mes autres zones car elles utilisent toutes le registre DLV de l'ISC et partagent donc les mêmes paramètres. Par contre la zone fr. n'a pas les mêmes TTL/refresh, ... que le registre DLV de l'ISC, d'où la nécessaire séparation.

zonefetch.xml

OpenDNSSEC n'est pas obligé de récupérer les fichiers de zones à signer sur le système de fichier local : il peut aussi utiliser un transfert de zone (AXFR). Comme cette fonctionnalité ne me convient pas totalement (réglagles globaux, pas par zone, imposible de dire si telle zone doit être récupérée via AXFR alors que telle autre zone doit être récupérée sur le système de fichier local, ...), je ne l'ai pas utilisé. Notons que l'arrivée des adapters dans la version 1.4 devrait permettre d'élargir grandement les possibilités de récupération/d'envoi des zones.

zonelist.xml

Il s'agit simplement des zones à gérer, avec leur politique, le fichier d'entrée et le fichier de sortie. Pas de piège, rien. Du coup, je ne pense pas qu'il soit utile que je détaille.

Conseil

Mon seul conseil sera de bien réfléchir à vos politiques avant de commencer à signer "pour de vrai". Je ne sais pas si je m'y suis mal pris, mais j'ai eu quelques déboires en changeant la politique associée à une zone en cours de route. Et quand je dis "déboirs", je veux dire destruction des clés par OpenDNSSEC et génération d'un nouveau trousseau. Si ça avait été en production à ce moment là, ça aurait causé un roulement brutal et forcé des clés et donc une incapacité à valider la zone temporairement et donc une incapacité d'accéder à mes "services" pour les systèmes/personnes qui utilisent un résolveur validant.

Mon utilisation

Les lecteurs habituels ne doivent pas être surpris que mon utilisation sorte du cadre de base. Je vais détaillé ma situation et ma configuration en me disant que ça peut toujours servir.

Mon infra

J'ai un seul serveur physique. À ce niveau, je n'ai aucun "service" ouvert vers l'exterieur. Viennent ensuite 2 conteneurs LXC qui contiennent chacun un domaine et les services associés.

La solution que j'ai choisi est d'installer OpenDNSSEC directement sur le serveur. Il signera ainsi les zones des 2 domaines. Les avantages sont :

  • Isolation : impossible d'apercevoir OpenDNSSEC depuis les LXC.
  • Accès aux systèmes de fichiers des LXC donc possiblité de lire les fichiers de zones "clairs" et de déposer les fichiers de zones signés.

L'inconvénient est que l'on reste sur la même machine. Je ne suis donc pas dans une signature totalement offline (serveur isolé d'Internet, sauf le temps de transférer le résultat de la signature). Je n'ai pas une grosse infrastructure de dingue, comme certains 😉 donc il m'est difficile d'isoler plus. Il faut nuancer en disant qu'il faut être root ou l'utilisateur opendnssec pour récupérer les clés. Si un attaquant arrive à obtenir une élévation de privilèges, il faut considérer que tout est déjà perdu, et pas seulement les parties privées des clés DNSSEC.

En gros, le scénario est le suivant : OpenDNSSEC générera les fichiers de zones signés dans un dossier de travail (/var/lib/opendnssec, comme par défaut) puis ferra appel à un script bash. Ce script demandera une élévation de privilèges, copiera les fichiers de zones aux bons endroits dans les conteneurs LXC, se connectera, en SSH, dans les conteneurs pour demander à BIND de recharger les zones modifiées.

Mise en place

Sur le signeur

On crée un script que l'on mettra dans /etc/opendnssec avec les bonnes permissions (root - opendnssec - 750) ;

#!/bin/bash
 
if [ $# -ne 1 ]

then
        echo "Trop ou pas assez d'arguments"
        logger "DNSSEC commande-lanceur - Trop ou pas assez d'arguments"
        exit 2
fi

 
if [ $1 = "guiguishow.info" ]
then
        sudo cp /var/lib/opendnssec/signed/guiguishow.info /chemin/vers/le/conteneur/lxc/bind/guiguishow.info.signed
        ssh -i /etc/opendnssec/ssh.key opendnssec@viki.guiguishow.info 'sudo rndc reload && sudo rndc notify guiguishow.info'

        exit 0
fi

Pour chaque nouveau serveur, il suffit d'ajouter un bloc if-then-fi et pour ajouter une zone supplémentaire à un serveur existant, il suffit d'ajouter une condition "OU" au if et les instructions qui vont bien dans le bloc de traitement.

Pour l' élévation de privilèges, il faut modifier le fichier /etc/sudoers en y ajoutant :

opendnssec      ALL=(root)      NOPASSWD:/bin/cp

Enfin, il faut modifier le fichier /etc/opendnssec/conf.xml pour lui indiquer la bonne commande à executer après une signature, c'est-à-dire, appeler notre script bash :

<NotifyCommand>bash /etc/opendnssec/wrapper %zone</NotifyCommand>
Sur les serveurs de noms

On a déjà vu les principaux elements dans un autre billet : DDNS indépendant sur OpenWRT.

Il faut créer un utilisateur dédié (opendnssec, par exemple) sur chaque serveur, lui associer une connexion par clé publique, restreindre ses actions possibles dans la configuration de (ForceCommand) et modifier le sudoers en conséquence pour donner le droit à cet utilisateur de faire recharger les zones. Par exemple :

opendnssec ALL=(root) NOPASSWD:/usr/sbin/rndc

DDNS

Les lecteurs habituels le savent : j'utilise du DDNS pour connaître l'adresse IP de mon OpenWRT qui se trouve derrière une ligne ADSL avec une IP pas toujours fixe.

OpenDNSSEC ne semble pas gérer le DDNS. La fonctionnalité zonefetch permettrait de se mettre en attente d'un notify, de demander la zone via AXFR et de la signer. Mais comme je l'ai déjà dit, zonefetch ne me convient pas dans l'état actuel car une fois la fonctionnalité configurée, OpenDNSSEC tente de récupèrer toutes les zones par ce biais et non une seule ...

Du coup, je me retrouve à bidouiller encore du script shell pas propre. On va suivre approximativement le même plan que dans DDNS indépendant sur OpenWRT : la création d'un utilisateur dédié et la mise en place d'une connexion automatisée par clé publique restent inchangée.

Le script devient :

#!/bin/bash

if [ $# -ne 1 ]
then
        echo "Trop ou pas assez d'arguments"
        logger "DDNS openwrt - Trop ou pas assez d'arguments"
        exit 2
fi
 
 
echo $1 | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}" > /dev/null
if [ $? -ne 0 ]
then
        echo "Le paramètre \"IP\" n'est pas au bon format."
        logger "DDNS openwrt - Paramètre IP pas au bon format."
        exit 2
fi
 
# Un petit délire pas utile : vérifier rapidement l'AS à qui a
# été distribuée l'IP passée en paramètre. Si ce n'est pas l'AS
# de mon FAI, alors soit il y a une erreur, soit le script
# n'est pas lancé depuis l'OpenWRT ... de là à parler d'une
# usurpation ... 
as=`whois $1 | grep origin | grep -oE "AS[0-9]{1,5}"`
if [ $? -eq 0 ] && [ $as != "AS5410" ]
then
        logger "DDNS openwrt - Usurpation"
        exit 1
fi
 
# Si l'IP passée en paramètre est la même que celle 
# actuellement dans la zone, on ne fait rien.
ipActuelle=`dig +short @viki.guiguishow.info openwrt.guiguishow.info`
if [ $ipActuelle !=  $1 ]
then
        sudo sed -i "s/^openwrt[ \t]\{2\}60[ \t]A[ \t]\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/openwrt\t\t60\tA\t$1/g" /chemin/à/travers/container/LXC/vers/fichier/de/zone/guiguishow.info
 
        sudo ods-signer sign guiguishow.info
 
        logger "DDNS openwrt - MAJ OK"

fi

Note : 60 secondes est un TTL qui est trop court pour une zone signée car le résolveur doit demander l'enregsitrement, la signature et remonter la chaîne de confiance asssez souvent. Mais comme je suis censé être le seul utilisateur, je pense qu'un TTL de 60 secondes est tolérable.

Note 2 : On ne fait pas l'incrémentation du serial du SOA car OpenDNSSEC le fait pour nous.

L'utilisateur dédié (openwrt) doit avoir le droit d'écrire dans le fichier de zone ainsi que d'appeler le signer. Il faut donc lui donner la possiblité d'avoir plus de droits tout en limitant les actions possibles. Avec sudo, on rajoute une ligne dans le fichier /etc/sudoers :

openwrt            ALL=(root)      NOPASSWD:/bin/sed,/usr/sbin/ods-signer

Tester

Pour tester votre déploiement, je vous conseille :

  • Zonecheck.
  • dnsviz.net (prend en compte le registre DLV de l'ISC).
  • Le debugger des Verisign Labs (attention : il ne prend en compte le registre DLV de l'ISC).
  • dig sur un résolveur qui fait de la validation. Vous vérifiez toute la chaîne et devez obtenir le drapeau "AD" partout.

Améliorations

La première amélioration que je vise est dépendante de l'évolution d'OpenDNSSEC. En effet, la version 1.4 devrait intégrer des i/o adapters. Ils devraient permettre de faire des choses assez dingues sans bidouilles (sous-entendu bricolage en bash). Je vois la possibilité de faire du DDNS correctement avec une notification de la part du serveur primaire et ods-signer re-signe une zone. Je vois aussi la possibilité de faire une signature offline quasi-parfaite : OpenDNSSEC signe les zones et joue le rôle d'un master furtif. Les zones sont ensuite distribuées par un master et un slave de manière classique.

DNSSEC est mouvant, il faut donc le surveiller. La supervision est donc clairement, une prochaine étape de mon installation. On trouve, sans trop de difficultés, des morceaux de code, par-ci, par-là pour vérifier que les signatures ne sont pas expirées, que les clés correspondent entre une zone parente et une zone enfant, ...

Revoir à la hausse les TTL de mes zones. Je suis parti du TTL appliqué de base par OpenDNSSEC (3600 secondes). Je monterai cette valeur plus tard, pour absorber la charge (si charge il y a). Pour l'instant, en dehors de mon flux RSS, je n'ai pas un afflux massif répété de multiples visiteurs sur mon blog donc mettre un TTL d'une heure ou de 3 heures ou de 5 heures ne changerait rien (sauf à supposer que tous mes visiteurs sont derrière le même résolveur validant) et ferait perdre en souplesse lors d'un changement dans la zone.

Augmenter la sécurité de la partie privée de mes clés (ZSK/KSK). J'ai d'abord pensé à séparer les KSK et les ZSK dans des dépôts différents de mon softhsm. En pratique, OpenDNSSEC permet cela : on peut indiquer, dans chaque politique, où seront stockées les KSK et les ZSK. Néanmoins, avec SoftHSM, tout revient à une base sqlite et donc à une problèmatique de gestion des droits sur un système de fichiers. Si le dépôt contenant les ZSK est compromis, c'est que l'attaquant à la volonté et les droits pour s'y attaquer. Donc, le dépôts des KSK sera trouvé et percer. En pratique, seuls les utilisateurs opendnssec/root ont accès aux dépôts. L'attaquant aura probablement attaqué le compte root avant d'attaquer le compte opendnssec. Et à ce stade là, il y a mieux à faire et il faut considérer que tout, et pas seulement DNSSEC est perdu. J'ai alors pensé à isoler la KSK, plus sensible et plus difficile à remplacer, sur une autre machine. Le problème est que cette clé doit signer le RRset DNSKEY. Les signatures ayant lieu, par défaut, tous les 4 jours, ça nécessite de positionner les clés au bon endroit, au bon moment.

DNSSEC, ce futur

Comme je l'ai écrit en juin 2012, je reste dubitatif sur le déploiement massif de DNSSEC dans les années à venir, encore plus que pour IPv6.

Je vais tenter d'argumenter (peu de noms car je fais des statistiques, pas une distribution de blâmes) :

  • Fin décembre 2012, on parle d'environ 80 TLD signés sur environ 325. Tous les gTLD ne sont pas signés ou n'acceptent pas de délégations signées. C'est encore pire pour les ccTLD. ÉDIT du 12/01/2013 à 12h30 : S. Bortzmeyer me fait remarquer qu'il faudrait nuancer ce point : ".NG [Nigeria] ou .BD [Bangladesh] ne sont pas signés". Fin de l'édit. Il faudrait aussi évaluer les bureaux d'enregistrement pour se faire une idée. ÉDIT du 19/05/2013 à 18h35 : Un lien intéressant pour prendre connaissance des TLD signés : TLD DNSSEC Report. Fin de l'édit.
  • Sous les TLD signés, la quantité de zones signées varie. On parle d'environ 1,3 million de délégations signées sous le ccTLD nl contre environ 20000 sous le ccTLD fr.
  • DNSSEC est une chaîne : un serveur faisant autorité qui diffuse une zone (données utiles + signatures) et des résolveurs qui valident les données obtenues lors de chaque résolution. On a vu, ci-dessus, quelques stats pour les serveurs faisant autorité. Pour le nombre de résolveurs qui font de la validation DNSSEC, on peut regarder (et participer à) l'expérience des Verisign labs. Sur le panel constitué, on constate qu'actuellement, environ 4% des résolveurs font de la validation DNSSEC. D'autres mesures, par pays, sont disponibles ici : Measuring Occurrence of DNSSEC Validation (page 7, figure 8 pour les pressés).
  • Mais DNSSEC, c'est aussi des gens pour le déployer et le maintenir. Je ne suis pas compétent pour estimer les personnes compétentes "en DNSSEC" sur le marché du travail. Par contre, je suis compétent pour "évaluer" l'offre de formation française. Un IUT ne le fait pas étudier en DUT Informatique. Sur 3 parcours (dont 2 orientés réseaux et/ou sécurité) dispensés par des facultés (L1 -> M2), aucun n'inclut DNSSEC. Dans une école d'ingénieur en informatique, pas un mot non plus sur DNSSEC. Je n'ai pas eu de retour sur les formations professionnelles de type L3 Pro/Master Pro. Je sais que certains nuanceront ce point en disant que l'enseignement supérieur donne les bases et que c'est à l'étudiant de faire sa veille technologique. Je n'ai rien contre ce principe, au contraire mais ça va retarder le déploiement d'une évolution comme DNSSEC.

Je vous donne rendez-vous le 01/02/2012, date du rollover ZSK, mais surtout en début d'année prochaine, date du rollover KSK, pour voir si j'ai raté une ou plusieurs étape(s) :P.