Depuis quelques temps, je me suis mis au DNSSEC. Comme je suis feignant, je n’ai pas envie de re-signer ma zone à la main tous les jours :) Comme j’ai vu que knot savait gérer la signature DNSSEC comme un grand, je me suis dit que ça serait une bonne occasion de l’essayer.
Installation
Je suis sous FreeBSD et j’ai choisi d’utiliser les ports.
root@kaiminus:~ # cd /usr/ports/dns/knot2/
root@kaiminus:/usr/ports/dns/knot2 # make install clean
root@kaiminus:~ # echo 'knot_enable="YES"' >> /etc/rc.conf
root@kaiminus:~ # echo 'knot_config="/usr/local/etc/knot/knot.conf"' >> \
/etc/rc.conf
Configuration de base
La configuration de knot se base sur du YAML. Il faut commencer par définir les options du serveur en lui-même, puis les serveurs avec qui le votre va parler (pour la réplication de zone), mettre en place des acl et enfin définir les zone.
# configuration de base
server:
# Listen on all configured IPv4 interfaces.
listen: 0.0.0.0@53
# Listen on all configured IPv6 interfaces.
listen: ::@53
# User for running the server.
user: knot:knot
log:
# Log info and more serious events to syslog.
- target: /var/log/knot.log
any: info
# Si on veut utiliser une clé pour s’authentifier auprès d’autres serveurs
key:
- id: blah
algorithm: hmac-sha256
secret: "blah2="
# On précise les autres serveurs
remote:
- id: ttn
address: 2a01:6600:8081:c600::1
- id: bulbizarre
address: 2a01:240:fe00:82af:764f:b47e:d131:85e4
key: blah
# Les ACL (tout le monde n’a pas le droit de faire le même chose)
- id: acl_allow_nokey
address: [2a01:6600:8081:c600::1]
action: [transfer, notify]
- id: acl_key
address: 2a01:240:fe00:82af:764f:b47e:d131:85e4
action: transfer
key: blah
# Slave zones
# reverse jaguar (florizarre)
- domain: 4.0.8.0.0.4.1.8.8.5.0.0.a.2.ip6.arpa
master: bulbizarre
acl: acl_key
# Master zones
zone:
- domain: swordarmor.fr
file: "/usr/local/etc/knot/swordarmor.fr.zone"
acl: [acl_allow_nokey, acl_key]
notify: [ttn, bulbizarre]
Signature automatique DNSSEC
Pour ma part, j’ai choisi la gestion automatique des clés. La façon de faire varie légèrement en fonction de la version (post ou pre 2.3). Je ne sais pas exactement si c’est à cette version que ça a changé, mais en tout cas c’est là que je m’en suis rendu compte.
Avant la version 2.3
Il nous faut d’abord dire à knot où seront stockées les clés.
template:
- id: default
storage: "/usr/local/etc/knot/var"
kasp-db: kasp
Si votre knot ne tourne pas en root (ce qui est une bonne idée), ce
répertoire doit appartenir à knot (ou à l’utilisateur qui le fait tourner
si ce n’est pas knot).
# mkdir -p /usr/local/etc/knot/var/kasp
# chown -R knot /usr/local/etc/knot/var
# cd /usr/local/etc/knot/var/kasp
# keymgr init
# keymgr policy add rsa algorithm RSASHA256 zsk-size 1024 ksk-size 2048
# keymgr zone add swordarmor.fr policy rsa
Ensuite, on rajoute dnssec-signing: on
au domaine swordarmor.fr
et knot se débrouille tout seul :)
À partir de la 2.3
À partir de cette version nous n’avons même plus besoin de nous soucier de
la gestion de la base de clés ; knot gère tout. Il suffit juste d’ajouter
dnssec-signing: on
et dnssec-policy: default
à
notre configuration de zone et le tour est joué.
Ça doit donner un truc qui ressemble à ça au final :
zone:
- domain: log.bzh
file: "log.bzh.zone"
acl: acl_slaves
notify: [togepi, bihen]
dnssec-signing: on
dnssec-policy: default
Publication de la clé DNSSEC dans la zone parente
Il existe deux types de bureaux d’enregistrement : ceux qui veulent un DS
et ceux qui veulent une clé DNSKEY complète.
Publication de la clé DNSKEY
Ancienne méthode
Si l’on a précisé une kasp dans la conf, les clés se trouveront dedans. Si
ce n’et pas le cas, ce sera dans storage. Comme à l’époque où je me suis mis
à knot il fallait un kasp, mes clés sont dans
/usr/local/etc/knot/var/kasp/
. Dedans nous trouvons un fichier
avec un nom qui ressemble à zone_swordarmor.fr.json
. Nous
l’ouvrons (par exemple avec cat) et dans ce JSON, nous avons une section
"ksk": true
. On y trouve aussi l’entrée algorithm
et public_key
. Il faut prendre ces deux valeurs et les
reporter dans l’interface de son bureau d’enregistrement.
Vous devez
donc avoir un formulaire qui ressemble à la capture si dessous. Il faut
bien faire attention à préciser le bon algorithme et à publier la KSK.
Nouvelle méthode
Depuis knot 2.4, les clés ne sont plus stockées dans un JSON, il n’est donc plus possible d’utiliser un bête cat. Par contre, il est maintenant possible d’interroger knot en local pour avoir la clé actuellement servie :
root@argall:~# knotc zone-read swordarmor.fr @ DNSKEY
[swordarmor.fr.] swordarmor.fr. 10800 DNSKEY 256 3 13 iy2V9pyqoImi7WmhTbkjntLt8FyK4/XxPrN9kDsweXjnKtl8DvFStjKwgMnJNKpkr3U2xsWx70o2xbLHLdgUbg==
[swordarmor.fr.] swordarmor.fr. 10800 DNSKEY 257 3 13 Uk3Vek1FDqzgQlI39NZcPKfpVex8unrHPmBLURrZCSjyje2o2UQel2FBGl2xHMl7qtcijj0x/g1n6tEmpio/jQ==
Pour lire cet enregistrement, il faut se référer aux RFC 4034, section 2
et 6605.
L’enregistrement qui nous intéresse est le second, avec le tag 257, il
correspond à notre KSK.
Ici nous avons donc affaire à une clé
condensée avec ECDSAP256SHA256 (algorithme 13) et dont le résultat est
« Uk3Vek1FDqzgQlI39NZcPKfpVex8unrHPmBLURrZCSjyje2o2UQel2FBGl2xHMl7qtcijj0x/g1n6tEmpio/jQ== ».
Exemple avec gandi
Ensuite, nous nous rendons sur la page « Gérer le DNSSEC » de son domaine
et nous remplissons les champs en fonction du résultat des champs
précédents.
J’ai délibérément fait le choix de ne pas publier la ZSK, car ce n’est pas
nécessaire pour que le DNSSEC fonctionne correctement et qu’elle change
régulièrement.
(cette capture étant plus vielle que la mise a jour de l’article, elle
contient une clé différente de l’extraction avec la nouvelle méthode)
Publication d’un DS
Knot ne gère pas nativement l’export du DS, mais nous pouvons utiliser la
commande drill
du paquet ldnsutils
à la place.
argall ~ # apt-get install ldnsutils
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
ldnsutils
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 142 kB of archives.
After this operation, 561 kB of additional disk space will be used.
Get:1 http://mirrors.online.net/debian/ jessie/main ldnsutils amd64 1.6.17-5+b1 [142 kB]
Fetched 142 kB in 0s (2,857 kB/s)
Selecting previously unselected package ldnsutils.
(Reading database ... 37564 files and directories currently installed.)
Preparing to unpack .../ldnsutils_1.6.17-5+b1_amd64.deb ...
Unpacking ldnsutils (1.6.17-5+b1) ...
Processing triggers for man-db (2.7.0.2-5) ...
Setting up ldnsutils (1.6.17-5+b1) ...
Ici la clé qui nous intéresse est la 28666 puisque c’est elle la KSK (cf.
les commentaires des enregistrements DNSKEY).
argall ~ # drill @argall.gozmail.bzh -s gozmail.net DNSKEY
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 15512
;; flags: qr aa rd ; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; gozmail.net. IN DNSKEY
;; ANSWER SECTION:
gozmail.net. 10800 IN DNSKEY 256 3 13 mIXljDQFdQIqixY5pmsgzCewpK+KbQPS1lqFV5iGzxXez8mTBT30uquL7Y/K2ZWGk3vMkGc/MN5Kp0hLVFS5Pg== ;{id = 34200 (zsk), size = 256b}
gozmail.net. 10800 IN DNSKEY 257 3 13 xi9r6PYVykH5Xxk7iJKL9LfS6B/ka04+aJW5E8O2At+sdfwhH2wTvX+pPUYBjTNI54iRFofJFOajrIPrdzcV2g== ;{id = 28666 (ksk), size = 256b}
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 0 msec
;; SERVER: 127.0.0.1
;; WHEN: Thu Nov 17 15:28:58 2016
;; MSG SIZE rcvd: 189
;
; equivalent DS records for key 34200:
; sha1: gozmail.net. 10800 IN DS 34200 13 1 01349b4563e4f7ab36b2b4b54f98c300d6a8da88
; sha256: gozmail.net. 10800 IN DS 34200 13 2 a8a6af6404675d34bd933fbdb8539118d021bcd56876dcccaebeb777c21eb28b
;
; equivalent DS records for key 28666:
; sha1: gozmail.net. 10800 IN DS 28666 13 1 888e055ab8523ac1c847fd12d8d03ec88586c3b7
; sha256: gozmail.net. 10800 IN DS 28666 13 2 a211a1a59a553710f127cf77b1a09af8eaf0249b505337bd8e3dc615f649014d
Dans mon exemple, argall.gozmail.bzh est le master et gozmail.net est le
domaine dont on veut avoir le DS.
Je vous déconseille très fortement d’utiliser le DS sha1. Cet algorithme de condensat est en effet considéré comme ayant des risques de collision. Par contre le sha256 n’a pas (encore) ce souci.
Mise à jour d’une zone
La méthode normale pour mettre à jour une zone avec knot est l’utilisation
de la commande knotc
avec les actions zone-begin
,
zone-set
, zone-commit
, etc. C’est très pratique
dans un script, ça évite du sed, grep, awk, mais je trouve ça lourd de
manière interactive.
Il n’est pas possible non plus d’éditer directement le fichier de zone
renseigné dans la conf car knot réorganise le fichier à sa façon et on ne
retrouve plus ses petits.
Je filoute donc un peu en ayant un fichier de zone non signé (en
.zone.nodnssec) dont je fais ce que je veux et un fichier de zone qui est
dans la conf de knot (en .zone) et qui est donc signé régulièrement.
Ce que je fais, c’est que j’édite la zone non-signée, je mets ce que je
veux dedans, je la copie par dessus la zone signée, puis je demande à knot
de recharger la zone. Il va alors la modifier comme il veut pour ajouter
les signatures DNSSEC et l’avoir à sa convenance, mais j’aurais toujours
ma zone non-signée à côté, avec mon organisation à moi. Par contre, il ne
faut pas oublie d’incrémenter le serial, de préférence sous le format
YYYYMMDDNN car les renouvellements de clé DNSSEC font incrémenter le sérial
même si on ne modifie pas la zone à la main.
Par exemple, si je veux modifier la zone log.bzh
stockée dans
/var/lib/knot/log.bzh.zone
ça done un truc comme ça :
Et hop, j’ai ma zone modifiée, re-signée, et distribuée sur tous les
masters.
master # vim /var/lib/knot/log.bzh.zone.nodnssec
Là je fais les modifs que je veux.
master # cp /var/lib/knot/log.bzh.zone.nodnssec /var/lib/knot/log.bzh.zone
master # knotc zone-reload log.bzh
OK
Premières impressions sur knot
C’est la première fois que j’utilise knot, et je dois dire que je ne suis
pas déçu. Le seul souci que j’ai eu était sur le choix de l’adresse IP
source lors des réponses, et ce bug a été corrigé à peu près une semaine
après l’avoir reporté.
De plus, leur doc est vraiment très bien faite, et ça c’est pas négligeable.