NSD + dnssec (deuxieme coup)
#1

Kuniyoshi ayant pris la décision surprenante et courageuse de gérer sa zone dns(sec) en hors-sol, je me vois contraint de me débrouiller tout seul.

Je requiert donc votre sagesse collective sur le sujet.

Je ne souhaites plus utiliser ZTK, parce que le logiciel n'est pas vraiment à jour, je doute qu'il propose des algos à courbes Edwards prochainement…

Idem, si je pouvais éviter OpenDNSSEC. Quand j'ai essayé de l'installer il y a quelques années, c'était une usine à gaz de dépendances diverses.

Donc si je pouvais concevoir un système de scripts simples avec ldns à appeler via cron, ce serait bien. Voici l'état de mes réflexions :
  • Tous les mois, on génère les ZSK(n+1) qui seront utilisées le mois prochain.
  • … met en place les ZSK(n) qui ont été générées le mois précédent.
  • … met à la retraite les ZSK(n-1)
  • … détruit les ZSK(n-2)
… où n indique le mois qui commence où les clés sont utilisées pour signer.

Si vous avez du mal à suivre la suite d'évennements au dessus, pensez aux divers ages de la vie (ça correspond parfaitement) :
  • naissance et glandage durant un temps
  • travail
  • retraite et glandage à nouveau
  • mort

Tout ça serait lancé via le script monthly d'OBSD. Le problème est de garder la trace de quelle ZSK est en charge (quelle clé signe, travaille…) actuellement. Il faut aussi prévoir un minimum de conf : quel algo(s) utiliser ? quelle taille de clés ? Pourrait-on régler ça via un fichier de conf' minimaliste voir directement l'écrire dans le fichier de zone ?

Tous les X jours (X serait 4 ou 5 dans mon cas), la zone serait signée. Retour à la question précédente : comment savoir quelle clé est active maintenant ? Comment specifier ca dans la conf ?

Il y a aussi la question de la séparation et protection correcte des clés privées.

Le fichier résultat (zone.signed) serait mis en place directement dans le chroot de NSD et ce dernier rechargé. Tous ces scripts doivent prendre en parametres le nom du domaine au minimum.

D'autres questions interessantes vont maintenant arriver (posées par vous).
Répondre
#2

Je me suis résolu à installer et utiliser OpenDNSSEC. Ce truc est une usine à gaz, pas KISS, mais il fait le job correctement.
Répondre
#3

Dommage que tu abandonnes, l'idée de scripts pour gérer le tout me plaît bien.
Je ne connais pas ldns, mais à l'occasion j'y jetterai un oeil. Scripter le tout pour enregistrer les éléments dans un fichier doit pouvoir se faire bien.

zkt fait bien le boulot aussi, au lieu de l'abandonner aider le projet pourrait être une bonne idée aussi Smile
Répondre
#4

Alors ZKT fait effectivement super bien le boulot, de ce côté là, c'est clair. Sauf qu'il y a pas de dev très actif. J'ai pas l'impression qu'on puisse avoir des clés à courbes Ed bientôt, ce qui serait pourtant cool.

Comment pourrais-je aider concretement ? Je vois pas. Moi coder ? Déjà qu'un script c'est l'aventure... (à l'université, j'étais le meilleur en code. Sauf qu'ils formaient pas des ing' info, mais des ing' GC).

Concernant ldns, je suis toujours ouvert. Il y a divers problematiques et je sais pas trop comment les résoudre :
  • La rotation des clés doit se faire de manière fluide.
  • On doit pouvoir savoir relativement facilement quelle sont les clés qui signent actuellement (parmi toutes celles présentes dans la zone).
  • Si possible des mécanismes d'auto-controle simples (genre : si la clé est trop jeune, on la met pas en charge tout de suite) ce qui permet d'éviter de faire des conneries quand on fait les choses "à la main".
  • Si possible encore, un truc récapitulatif (quelles clés, quel age, etc...) comme zkt-ls.

Ca a l'air éxigeant comme ca, mais en même temps, dnssec c'est le truc qui peut être bien casse-gueule. Je dirais que le problème principal c'est le numero 2.

Tu parles d'envoyer des élements dans un fichier (genre conf' temporelle). Ouais, à priori pourquoi pas. Sauf que, qu'est-ce qu'il se passe si une commande foire au milieu du script ?

On assume aussi bien entendu qu'on utilise des valeurs saines à la conception, de sorte qu'il y a pas trop de marge de manoeuvre pour se casser la gueule effectivement (je pense typiquement au renouvellement des ZSK : on fait ca mensuellement via le script monthly. Comme ca on est sûr de notre coup. Et on organise le reste autour de ca.). Mais qu'est-ce qui se passe si à l'improviste comme ca, j'ai besoin de commencer à signer avec une clé plus tôt ?

Autre chose : ldns crée les fichiers dans le rep courant. Ce qui fait que lorsque tu crée tes ZSK, il faut soit les créer directos dans un dossier inaccessible en lecture au monde, soit deplacer les clés privées après (pour protection : même chose que les certs tls). Et ldns donne aussi des noms standard aux clés (c'est le truc de ZKT pour savoir quelle clé est active : le nom de fichier est different).

Donc si on veut faire un système de scripts avec ldns, pourquoi pas. Mais je suis pas tout seul. J'aimerais bien par exemple avoir l'avis de Penguoin, comment il ferait ca. Faut debattre, regarder, comparer.
Répondre
#5

Bon, je poursuis l'idée (mouais...).

Mettons nous dans un repertoire specifique (/var/ldnscript) avec permissions rw------ et créons un rep pour chaque zone dns signée. Dedans, un script créera un dossier zsk et un autre ksk. Ce dossier contiendra un fichier de conf' basique pour la zone en question (à voir comment on passe la conf' en question aux commandes).

Lors de la génération des clés, le nom de la clé est écrit dans un fichier "generated". Lors de la géneration de la clé suivante, ce fichier "generated" est déplacé en "active", etc... Seules les clés dans le fichier "active" sont utilisées pour la signature.

Voila, vous en pensez quoi ?
Répondre
#6

Est-ce que pour les noms des fichiers de signature, tu peux utiliser la datation, tel que :

fichier_AAAAMM.key

???

Si oui, comparez le fichier généré pour tel mois avec le mois en cours n'est strictement rien !

Le premier mois d'usage, je génère la clé de ce mois, et la clé du mois prochain portant la datation du mois prochain, etc...
La clé active est forcément celle du mois en cours Wink

----

Concernant les fichiers de conf basique, si les scripts sont du *sh* (shell), aucun problème.
La norme la plus facile à utiliser est le format INI !

Code :
[section1]
var = valeur

[sect2]
bla = blabla

Beaucoup de langage l'utilise assez bien voire facilement, tel python...

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#7

Non, ldns crée un ensemble clé publique + privée + ds de cette forme :

K<mom de zone>+<num d'alg>+<num de clé>.ds .key .private

La sortie de la commande est justement le nom total de la cle.

On peut tester la date de création du fichier, non ? -> juste pour empecher la mise en charge de la clé avant qu'elle soit effectivement répandue. Sa mise en charge "normale" serait toujours le 1er du mois.
Répondre
#8

Et, alors, si tu scripts quelque soit le langage, il est toujours possible de renommer la clé avec une datation...
Et, si absolument besoin d'un format de nom pour la clé active, il est toujours aussi aisé de renommer la clé à activer pour qu'elle corresponde à la nécessité...

non ?!

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#9

On peut renommer les fichiers effectivement. Mais il faut aussi dans ce cas se souvenir de quelle clé privée vient avec quoi...

En revanche modifier l'extension des clés en fonction des états est possible.
Répondre
#10

Autre pensée... la gestion de la zone (zone dns et config dnssec simpliste) pourrait se faire via un depot git. Qu'en pensez-vous ?
Répondre
#11

Pour se souvenir, tu renommes tes trois fichiers avec la meme datation Wink

À quoi te servirait le dépôt git ?

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#12

Le git serait un utilitaire secondaire. C'est absolument pas l'objectif actuel.

Il permettrait d'avoir un historique des changement de la zone. On mettrait en place un hook git qui signerait alors la nouvelle version lors de chaque push. Accessoirement, on pourrait administrer le bordel dans un editeur texte un peu plus sophistiqué que nano, sans toutes les contraintes de la ligne de commande.
Répondre
#13

Tout ceci est semble faisable. Je n'ai pas le temps de m'y pencher maintenant pour scripter, mais ça sera fait très certainement un de ces .
Répondre
#14

Je suis en train de faire. Je butte toujours sur UN truc : quelle(s) clés sont actives (et comment conserver cette info de manière correcte et utilisable...). Je pense qu'il faut mettre ca dans un fichier texte...

J'arrive à signer la zone, mettre X clés dedans et je sais dans quel ordre ca signe.
Répondre
#15

Pourquoi pas dans un fichier texte ?
Tu choisis toi-même sa structure pour le réutiliser ensuite. OpenBSD utilise souvent le séparateur '|' (spamd), ça permet de mettre plusieurs informations par ligne à propos d'un élément, et de récupérer celui souhaité avec "cut"
Répondre
#16

Et mettre ça dans des répertoires spécifique ? Peut être plus simple que de lire/écrire un fichier.

« La perfection est atteinte, non pas lorsqu'il n'y a plus rien à ajouter, mais lorsqu'il n'y a plus rien à retirer. » Antoine de Saint-Exupéry
Répondre
#17

Est ce que couple cela avec les logs avec une sous rubrique serait pas mieux ?.
Répondre
#18

Les clés dans un dossier, pourquoi pas, sauf qu'il faut quand meme explorer le dossier. En effet, ldns demande en argument le nom simple des clés. On peut pas se contenter de dire "signe avec n'importe quelle clé se trouvant dans le repertoire actif" (dans l'idée il y aurait une seule clé dans ce repertoire).

Par ex, mon script fonctionne auj' comme ca (en test, pas en prod' ) :

/var/ldns/$DOMAIN/zsk/K22decembre.eu.+010+07043.key (et d'autres clés dans le dossier, ainsi qu'un fichier keys où on a la liste des clés avec algo et états).

et l'appel de la commande de signature (je suis là dans le rep' $DOMAIN) :

/usr/local/bin/ldns-signzone -i $DEBUT -e $FIN -n -s $(head -n 1000 /dev/random | sha256 | cut -b 1-16) -t $RUN -o $DOMAIN -f $DOMAIN.signed tmp ksk/$KSK zsk/$ZSK

$ZSK correspond à "K22decembre.eu.+010+07043" (même combat pour $KSK)
Répondre
#19

Bon, voici les scripts. Pour rappel, la philosophie générale des scripts, c'est de faire KISS à fond: pas de subtilités. On ne vérifie pas notamment si on a besoin de signer (donc si c'est le jour des signatures, on signe, qu'importe que la zone ait été signée hier soir...) ou si les clés sont correctes. L'admin est supposé faire son boulot et pas faire des conneries.

Dans /var/ldnscripts:

Code :
stephane@blackblock:/var/ldnscripts ls -la
total 32
drwxr-xr-x   3 stephane  stephane   512 Sep  1 18:44 .
drwxr-xr-x  45 root      wheel     1024 Aug 27 19:47 ..
-rw-r--r--   1 stephane  stephane   278 Aug 27 19:35 conf
-rwxr-xr-x   1 stephane  stephane   334 Aug 29 22:33 ksk-gen
-rwxr-xr-x   1 stephane  stephane   967 Aug 29 22:34 rollover
-rwxr-xr-x   1 stephane  stephane  1092 Aug 31 22:25 signing
drwxr-xr-x   4 root      stephane   512 Aug 29 22:31 zones
-rwxr-xr-x   1 stephane  stephane   396 Aug 29 22:32 zsk-gen

Celui là sera invoqué pour signer la zone. Je prévois de le lancer tous les quatre ou cinq jours en tâche cron.

signing
Code :
#!/bin/sh

cd /var/ldnscripts/

if [[ -r /var/ldnscripts/conf ]]
then
        . /var/ldnscripts/conf
fi

DOMAIN=$1
cd zones/$DOMAIN

if [[ -r $NS_REP/$DOMAIN.conf ]]
then
        . $NS_REP/$DOMAIN.conf
fi

# create a complete zone file with the current time as SOA
/usr/local/bin/ldns-read-zone -S unixtime $NS_REP/$DOMAIN > tmp

# ... with all the keys in the zone
for KEY in 'ksk/*.key'; do
    cat $KEY >> tmp
done

for KEY in 'zsk/*.key'; do
    cat $KEY >> tmp
done

DEBUT=$(date +%s)
FIN=$(($DEBUT+$VALIDITY * 24 * 3600))

# If several keys  active -> check which one has the good algo (if no active key with algo : we are rolling over the algorithm).
# if several keys active with good algo -> take the first one. Admin get to tidy the place
# WARNING : no check of age of keys !

if [[ $(grep active ksk/keys|cut -f 1 -d " ") > 1 ]]
then
        KSK=$(grep active ksk/keys|grep $ALG|head -n 1|cut -f 1 -d " ")
else
        KSK=$(grep active ksk/keys|head -n 1|cut -f 1 -d " ")
fi


if [[ $(grep active zsk/keys|cut -f 1 -d " ") > 1 ]]
then
        ZSK=$(grep active zsk/keys|grep $ALG|head -n 1|cut -f 1 -d " ")
else
        ZSK=$(grep active zsk/keys|head -n 1|cut -f 1 -d " ")
fi

echo "KSK:"
cat ksk/keys | while read line
do
echo "$line"
done
echo " "

echo "ZSK:"
cat zsk/keys | while read line
do
echo "$line"
done

/usr/local/bin/ldns-signzone -i $DEBUT -e $FIN -n -s $(head -n 1000 /dev/random | sha256 | cut -b 1-16) -t $RUN -o $DOMAIN -f /var/nsd/$DOMAIN.signed tmp ksk/$KSK zsk/$ZSK

#/usr/sbin/nsd-control reload $DOMAIN
#/usr/sbin/nsd-control notify $DOMAIN

Ici, on génère les ksk:

ksk-gen
Code :
#!/bin/sh

if [[ -r /var/ldnscripts/conf ]]
then
        . /var/ldnscripts/conf
fi

DOMAIN=$1

mkdir -m 0600 -p zones/$DOMAIN/ksk
cd zones/$DOMAIN

if [[ -r $NS_REP/$DOMAIN.conf ]]
then
        . $NS_REP/$DOMAIN.conf
fi

cd ksk

if [ $(date +%d) > 15 ]
then
        echo "Wait for next month (change the algo in the conf if you need)."
else
        KEY=$(/usr/local/bin/ldns-keygen -k -a $ALG -b $KSK_BITS $DOMAIN)

        echo $KEY $ALG "generated" >> keys
fi

Après avoir crée la KSK, il faut signer la zone via l'appel du script précédent, puis enregistrer le DS dans le registre. Si la commande est lancée trop tard dans le mois, on risque de mettre la clé en activité avant qu'elle soit diffusée dans le DNS. D'où le blocage avec message.

zsk-gen
Code :
#!/bin/sh
if [[ -r /var/ldnscripts/conf ]]
then
        . /var/ldnscripts/conf
fi

DOMAIN=$1

mkdir -m 0600 -p zones/$DOMAIN/zsk
cd zones/$DOMAIN

if [[ -r $NS_REP/$DOMAIN.conf ]]
then
        . $NS_REP/$DOMAIN.conf
fi

cd zsk

if [ $(date +%d) > 15 ]
then
        echo "Wait for next month. Just change the algorithm in the conf if you need, and the next rollover will create a key."
else
        #create
        KEY=$(/usr/local/bin/ldns-keygen -a $ALG -b $ZSK_BITS $DOMAIN)

        echo $KEY $ALG "generated" >> keys
        rm $KEY.ds
fi

Idem, on crée la clé zsk. Si on veut changer l'algo des clés, il suffit de mettre à jour le fichier de conf. La prochaine clé sera crée avec le nouvel algo, puis chargée lors du rollover suivant.

rollover
Code :
#!/bin/sh

TYPE=$1
DOMAIN=$2

mkdir -m 0600 -p zones/$DOMAIN

DIR=$PWD

if [[ -r /var/ldnscripts/conf ]]
then
        . /var/ldnscripts/conf
fi

case $TYPE in
    -z|--zsk|ZSK|Zsk )
        TYPE=zsk
        #
        # same time we roll zsk (as usual), we check existence of new ksk, then mark it active
        #
        if $(grep generated zones/$DOMAIN/ksk/keys|cut -f 1 -d " ")
        then
                sed -i 's/active/retire/' $DOMAIN/ksk/keys
                sed -i 's/generated/active/' $DOMAIN/ksk/keys
        fi
        ;;

    -k|--ksk|KSK|Ksk )
            TYPE=ksk;;
                #
                # If we launch a ksk rollover, we just create a new ksk.
                # The next zsk rollover will mark it active.
                # You have around three weeks to get the new ksk in the TLD before it gets active.
esac

cd zones/$DOMAIN/$TYPE

LIST=$(grep retire keys|cut -f 1 -d " ")
echo $LIST

for KEY in $LIST; do
     rm -f $KEY.private
     rm -f $KEY.key
     rm -f $KEY.ds
done

touch keys
sed -i /'retire'/d keys

sed -i 's/active/retire/' keys

sed -i 's/generated/active/' keys

cd $DIR

./$TYPE-gen $DOMAIN

Lors d'un rollover, on décale simplement les clés (generated -> active -> retire -> rm), puis on crée une nouvelle clé. Après le script, il doit y avoir une signature de zone (qui chargera la nouvelle clé) avec la clé nouvellement active. Alors oui, c'est bete, on a en vitesse de croisière trois ZSK dans la zone, mais on est sûrs que la clé sera bien diffusée au moment de sa mise en charge, et on minimise le risque d'erreur.

Un rollover ZSK met aussi en activité la clé KSK qui a été crée il y a un mois max (et 15 jours minimum). On espère que l'admin s'est donné le temps sur ces 15 jours pour mettre la clé dans le registre.

Il y aura un rollover ZSK+signature lancé par le script monthly (tout le truc est construit comme ca. J'aurais aimé mettre des durée de validité aux clés, mais ldns a pas cette option). Actuellement c'est lancé via le script weekly (premier test cette nuit).

Voila le fichier de conf:
Code :
# repository where to find unsigned zone file and specific conf
NS_REP=/etc/ns

# algorithm to use. They are listed : ldns-keygen -a list
ALG=RSASHA512

# length of the zsk
ZSK_BITS=1024

KSK_BITS=2048

# validity of signatures in days
VALIDITY=7

#NSEC3
NSEC3_ALG=SHA-1
RUN=24

Chaque zone peut avoir sa propre conf', qui viendra alors dans le même dossier que le fichier de zone non signé.

Voila, désolé pour le post long, mais il fallait. Des remarques ? Critiques constructives svp...

Peut etre que je peux mutualiser le code de generation des clés...
Répondre
#20

Intéressant !

Tu ne voudrais pas mettre le nom du script avant le code correspondant, ou dans des commentaires...
Ça aidera mieux à la lecture Wink
Et, ça me permettra de t'aider à le factoriser... parce que oui, c'est possible ! :p

Une première "correction" que tu peux apporter est de ce genre :

Code :
if [[ -r /var/ldnscripts/conf ]]
then
        . /var/ldnscripts/conf
fi

par :

Code :
[ -r /var/ldnscripts/conf ] && . /var/ldnscripts/conf

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#21

noms des scripts au dessus : OK.

Voici une proposition de factorisation de code pour la generation des clés :

keygen
Code :
#!/bin/sh

[ -r /var/ldnscripts/conf ] && . /var/ldnscripts/conf

TYPE=$1
DOMAIN=$2

case $TYPE in
    -z|--zsk|ZSK|Zsk )
        TYPE=zsk
        ARG="-a $ALG -b $ZSK_BITS $DOMAIN"
        ;;

    -k|--ksk|KSK|Ksk )
        ARG="-k -a $ALG -b $KSK_BITS $DOMAIN"
        TYPE=ksk;;
esac

mkdir -m 0600 -p zones/$DOMAIN/$TYPE
cd zones/$DOMAIN/$TYPE

[ -r $NS_REP/$DOMAIN.conf ] && . $NS_REP/$DOMAIN.conf

if [ $(date +%d) > 15 ]
then
        echo "Wait for next month (change the algo in the conf if you need)."
else
        KEY=$(/usr/local/bin/ldns-keygen $ARG)

        echo $KEY $ALG "generated" >> keys
fi
Répondre
#22

Aaaah, merci, je vais tester ça ce mois-ci.
Euh, pas contre, je ne vois aucun intérêt à ces factorisations, mis à part rendre la lecture du code plus complexe. Mais bon, à chacun sa façon de coder Wink
Répondre
#23

Les factorisation (dans le cas des clés) c'est parce que c'est le même code, à deux options près : la taille des clés et -k (pour KSK).
Répondre
#24

Encore quelques peaufinages et je commence à écrire un article de blog tout bien expliqué. Tu pourras alors t'y référer (en brouillon au début). Mais je laisse encore tourner à blanche pendant au moins deux semaines.
Répondre
#25

Bien tout ça, je préfère à zkt en plus.
Je voudrais bien un git pour éventuellement contribuer d'ici quelques semaines.
Répondre


Sujets apparemment similaires…
Sujet / Auteur Réponses Affichages Dernier message
Dernier message par 22decembre
19-08-2017, 08:20:41

Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)