Les DNS adapters (anciennement nommés I/O adapters, de mémoire), qui sont apparus avec la version 1.4 d'OpenDNSSEC, lui permettent de se comporter comme un serveur DNS c'est-à-dire que, plutôt que d'avoir le fichier de zone à signer sur un support de stockage, OpenDNSSEC peut très bien la recevoir depuis un serveur DNS, via un transfert de zone tout à fait standard dans DNS. De même, plutôt que d'écrire la zone signée sur le stockage, OpenDNSSEC peut la distribuer à un serveur DNS qui, lui, la servira à tout l'Internet.
En gros, le tech modifie le fichier de zone et la recharge dans son serveur de noms interne qui fait autorité habituel (BIND, nsd, knot, etc.). Celui-ci envoie une notification à OpenDNSSEC. OpenDNSSEC effectue un transfert de la zone depuis le serveur DNS interne puis signe la zone puis envoie une notification au serveur DNS qui fait autorité exposé sur le net. Ce serveur récupère la zone signée auprès d'OpenDNSSEC en effectuant un transfert de zone.
Cela permet deux choses :
ods-signer sign
) : une équipe, pourquoi pas celle dédiée à la sécurité, met en place, maintient et debug DNSSEC et le reste des techs utilise le DNS comme à son habitude, comme on le voit en cours : modif' du fichier de zone et faire relire son contenu par un serveur de noms bien connu (BIND, la plupart du temps, malheureusement).Évidemment, il est tout à fait possible de mixer les I/O adapters et d'utiliser le stockage comme entrée du signataire DNSSEC et un transfert de zone en sortie du même signataire (configuration du master furtif) ou un transfert de zone en entrée et une écriture sur le stockage en sortie.
Je me suis fait une petite maquette : dns1/198.18.0.1/Debian+BIND9 -> opendnssec/198.18.0.2/Debian+OpenDNSSEC -> dns2/198.18.0.3/Debian+nsd. dns2 est la seule machine accessible depuis Internet. Oui, normalement dns2 devrait être dans un réseau IP différent de dns1.
sudo apt-get install bind9
sudo mkdir -p /var/named/zones/master
sudo chown -R bind:root /var/named
sudo chown -R 555 /var/named
Conf' (/etc/bind/named.conf.local) :
zone "guiguishow.example." IN {
type master;
file "/var/named/zones/master/db.guiguishow.example";
allow-transfer { 198.18.0.2; };
notify yes;
also-notify { 198.18.0.2; };
};
La ligne allow-notify
est importante : par défaut un serveur de noms envoie une notification uniquement aux machines désignées par un enregistrement NS dans la zone. Comme dit, dns1 et OpenDNSSEC n'apparaissent pas dans les enregistrements NS de guiguishow.example.
Pour le contenu du fichier de zone, c'est du classique :
$ORIGIN guiguishow.example.
$TTL 3600
guiguishow.example. IN SOA dns1.guiguishow.example. dnsmaster.guiguishow.example. 2017041200 7200 3600 604800 3600
@ IN NS dns2
dns2 IN A 198.18.0.3
Oui, mon enregistrement SOA est parfaitement valide : le champ mname, « dns1.guiguishow.example » dans cet exemple, doit indiquer le nom de n'importe quel serveur DNS qui fait autorité sur la zone. Par convention, on y met la machine qui est la source de la zone, c'est-à-dire le serveur sur lequel sont effectuées les modifications. Il n'a jamais été question que ce champ contienne forcément le premier NS public de la zone et encore moins que ce nom soit utilisé dans le processus de résolution d'un nom.
Le début ne change pas d'une installation OpenDNSSEC classique.
sudo apt-get install opendnssec opendnssec-enforcer-sqlite3 softhsm
sudo softhsm --init-token --slot 0 --label "OpenDNSSEC"
Puis, on configure le DNS adapters. La première étape est d'indiquer sur quelle-s interface-s et quel port réseau écouter (par défaut : port 53 sur toutes les interfaces) en décommentant le Listener dans conf.xml :
<Listener>
<Interface>
<!-- <Address></Address> -->
<Port>53</Port>
</Interface>
</Listener>
Sans ça, l'erreur « no dnshandler/listener configured, but zones are configured with dns adapters: notify and zone transfer requests will not work properly » apparaît dans les logs.
Ensuite, on configure les serveurs DNS source (dns1) et destination (dns2) dans le fichier /etc/opendnssec/addns.xml :
<?xml version="1.0" encoding="UTF-8"?>
<Adapter>
<DNS>
<Inbound>
<!-- Address of host to request XFR from -->
<RequestTransfer>
<Remote>
<Address>198.18.0.1</Address>
</Remote>
</RequestTransfer>
<!-- Allow NOTIFY messages from host -->
<AllowNotify>
<Peer>
<Prefix>198.18.0.1</Prefix>
</Peer>
</AllowNotify>
</Inbound>
<Outbound>
<!-- Provide XFR to host -->
<ProvideTransfer>
<Peer>
<Prefix>198.18.0.3</Prefix>
</Peer>
</ProvideTransfer>
<!-- Send NOTIFY messages to host -->
<Notify>
<Remote>
<Address>198.18.0.3</Address>
</Remote>
</Notify>
</Outbound>
</DNS>
</Adapter>
Puis, on ajoute notre zone dans /etc/opendnssec/zonelist.xml :
<?xml version="1.0" encoding="UTF-8"?>
<ZoneList>
<Zone name="guiguishow.example">
<Policy>default</Policy>
<SignerConfiguration>/var/lib/opendnssec/signconf/guiguishow.example.xml</SignerConfiguration>
<Adapters>
<Input>
<Adapter type="DNS">/etc/opendnssec/addns.xml</Adapter>
</Input>
<Output>
<Adapter type="DNS">/etc/opendnssec/addns.xml</Adapter>
</Output>
</Adapters>
</Zone>
</ZoneList>
On constate qu'il est tout à fait possible d'avoir plusieurs serveurs DNS en entrée, chacun servant une ou plusieurs zones. Même chose en sortie.
Enfin, on met en place les politiques de signature :
sudo ods-ksmutil setup
sudo apt-get install nsd
sudo mkdir -p /var/named/zones/slave
sudo chown -R nsd:root /var/named
sudo chmod -R 555 /var/named
sudo chmod u+w /var/named/zones/slave
Conf' (/etc/nsd/nsd.conf) :
zone:
name: "guiguishow.example."
zonefile: "/var/named/zones/slave/db.guiguishow.example"
allow-notify: 198.18.0.2 NOKEY
request-xfr: 198.18.0.2 NOKEY
Évidemment, il faut veiller à ne jamais autoriser un transfert de zones entre dns1 et dns2, sinon ça va plutôt mal se passer au moins jusqu'à ce qu'OpenDNSSEC notifie un serial plus important et que dns2 récupère cette zone signée en conséquence.
On lance nsd sur dns2 :
sudo systemctl restart nsd
On lance OpenDNSSEC :
sudo systemctl restart opendnssec-enforcer.service opendnssec-signer.service
On lance BIND sur dns1 :
sudo systemctl restart bind9
dns2 sert bien une zone signée \o/ :
$ dig @::1 +dnssec SOA guiguishow.example
; <<>> DiG 9.9.5-9+deb8u10-Debian <<>> @::1 +dnssec SOA guiguishow.example
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41788
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 3
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;guiguishow.example. IN SOA
;; ANSWER SECTION:
guiguishow.example. 3600 IN SOA dns1.guiguishow.example. dnsmaster.guiguishow.example. 2017041201 7200 3600 604800 3600
guiguishow.example. 3600 IN RRSIG SOA 8 2 3600 20170426074413 20170412150401 18114 guiguishow.example. MgP6rIs4Uf/SDAzFyJnw8w+JWh0EgxrFmbdlpMZxhdaQd/9NOsf07/mg JxV1qQ42xIAMUziF5wn0yX0DOqIr6S2jE+lGLWsRHB2swUQ1eaBsTKlV cLpRoRz6J1XtAha90OggjmGdL8EHMNczdjeYzmXwSAtpFsj20A+CcxYk LfM=
;; AUTHORITY SECTION:
guiguishow.example. 3600 IN NS dns2.guiguishow.example.
guiguishow.example. 3600 IN RRSIG NS 8 2 3600 20170426104704 20170412150401 18114 guiguishow.example. dISERsUbOSL03zWzTKMuoATfYws21RhxekZRjRbn5oFe/HIDxqCar2DQ hj5JxnBwQV9/Kjwa2/ZASBhUqEmzQe3ZCrvPdbTQUFCtoHuRSXtuJMB8 cHot6AuM1MJRkwPEwnem+F9excJR9vX4MRY08+pYEvKHHbz91ysnGkFP ESY=
;; ADDITIONAL SECTION:
dns2.guiguishow.example. 3600 IN A 198.18.0.3
dns2.guiguishow.example. 3600 IN RRSIG A 8 3 3600 20170427015329 20170412150401 18114 guiguishow.example. DSgNZI7MG53qMecbXT+bU73qGY8uu0QTxYrcTrjwFiGU5deUot8CKkEz SNJ/ahBCfpexdpf4IffjHqAw527o2O6OUdqNj6VwYj/wScgdWSZJQhcO wtmTyZwyC1jWviiaVTX/e24coQMFickOjYOSBqiSDeNqe7sPOkT7XHgm qlE=
;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Wed Apr 12 18:05:19 CEST 2017
;; MSG SIZE rcvd: 667
Attention : la commande ods-signer sign
n'a pas d'effet lorsqu'elle est utilisée sur une zone qui utilise un adaptateur DNS en entrée car OpenDNSSEC n'effectue pas un transfert de zone de sa propre initiative. Pour ce faire, il faut soit redémarrer OpenDNSSEC (ce qui est inapproprié !), soit envoyer une notification depuis le serveur DNS interne (exemple avec BIND : sudo rndc reload <nom_zone>
; exemple avec nsd : sudo nsd-control notify <nom_zone>
).