Greboca  

Suport technique et veille technologique

Aujourd’hui, les grandes entreprises et administrations publiques hésitent entre continuer à utiliser des logiciels propriétaires ou basculer vers les Logiciels Libres. Pourtant, la plupart des logiciels libres sont capables de bien traiter les données issues des logiciels propriétaire, et parfois avec une meilleur compatibilité.

C’est alors la barrière de la prise en main qui fait peur, et pourtant...

Les logiciels libres

L’aspect « Logiciel Libre » permet une évolution rapide et une plus grande participation des utilisateurs. Les aides et tutoriels foisonnent sur Internet ou sont directement inclus dans le logiciel lui-même.

Enfin, les concepteurs sont plus proches des utilisateurs, ce qui rend les logiciels libres plus agréable à utiliser et conviviaux.

Grâce à la disponibilité des logiciels libres, vous trouverez facilement des services de support techniques et la licence n’est plus un frein à l’utilisation de ces logiciels par votre personnel.

Notre support technique concerne essentiellement les logiciels libres, que ce soit sous forme de services ponctuels ou de tutoriels.

Blog de Stéphane Bortzmeyer  -  Superviser ses signatures DNSSEC

 -  Mars 2019 - 

Le système DNSSEC permet d'authentifier les données distribuées via le DNS et protège donc ainsi des attaques par empoisonnement. C'est un outil nécessaire dans la boîte à outils de sécurisation du DNS. Mais rien n'est gratuit en ce bas monde : la cryptographie protège mais elle complique les choses et crée des risques. Parmi ceux-ci, le risque d'expiration des signatures. Il est donc nécessaire de superviser ses signatures DNSSEC. Comment ? Et avec quoi ?

Si vous voulez une introduction à DNSSEC en français, vous pouvez lire mon exposé à JRES. Notez-y un point important : les signatures des enregistrements DNSSEC expirent au bout d'un moment et il est donc nécessaire de re-signer de temps en temps. Si ce processus de re-signature ne marche pas, les signatures vont finir par expirer, rendant le domaine inutilisable. Voici un exemple de signature DNSSEC :


% dig +dnssec A www.bortzmeyer.org
...
;; ANSWER SECTION:
www.bortzmeyer.org.	68585 IN A 204.62.14.153
www.bortzmeyer.org.	68585 IN RRSIG A 8 3 86400 20140414143956 (
				20140325120748 15774 bortzmeyer.org.
				dgJ3BOjUz3hdlRWEbcFK14Jqyl+az/tas/dKEcBs/2QK
				4vUd2VihXtEmpLQ6D+FVtMh6n7OubrEpLezEGkHtXKOe
				3FO6l+EhrjH82BwjGGnd50RMNDHGk8IR0TOsOj/cNGZM
				V4Gj24mOV5ANbYWxlqWXYPl9BVi81MVhluw9sas= )
...

On voit dans la réponse l'adresse IPv4 du serveur et la signature (enregistrement RRSIG). dig formate la signature de manière lisible par un humain, avec une date de mise en service (inception) au 25 mars et une date d'expiration au 14 avril. Ce jour-là, à 14h39 UTC, la signature expirera (le but est d'éviter les attaques par rejeu). Il faudra donc, avant, signer à nouveau. Dans le cas de bortzmeyer.org, c'est fait avec OpenDNSSEC. On pourrait aussi lancer un dnssec-signzone ou bien un ldns-signzone depuis cron. Ou laisser BIND prendre cela en charge avec son mécanisme de signature automatique. Mais toutes ces solutions ont un point commun, elles sont fragiles. Pendant des mois, elles fonctionnent puis, un jour, un léger changement fait qu'elles ne marchent plus et qu'on risque de ne pas s'en apercevoir. Un exemple qui m'était arrivé en changeant de version de Debian : la bibliothèque de SoftHSM avait changé d'emplacement, le fichier de configuration d'OpenDNSSEC pointait donc au mauvais endroit et le signeur d'OpenDNSSEC ne tournait donc plus. Quelques temps après, bortzmeyer.fr expirait...

Le problème n'est pas spécifique à DNSSEC. Dans toutes les solutions de sécurité, il y a des dates limites, conçues pour éviter qu'un méchant qui aurait mis la main sur des informations secrètes puisse les utiliser éternellement. C'est par exemple pour cela que les certificats X.509 ont une date d'expiration (attention, avec DNSSEC, les clés n'expirent pas, seules les signatures le font). Comme le savent les utilisateurs de HTTPS, il est très fréquent que le webmestre oublie de renouveler les certificats et paf. À part des bonnes procédures (rappel mis dans l'agenda...), la solution est de superviser. Tout responsable sérieux d'un site Web HTTPS supervise l'expiration. Il faut faire la même chose pour DNSSEC.

La solution que je vais montrer ici fonctionne avec ma configuration Icinga mais elle ne repose que sur des outils compatibles avec l'API Nagios donc elle devrait marcher avec beaucoup d'outils de supervision.

Après plusieurs essais (voir les notes de ces essais plus loin), j'ai choisi comme outil de base le script de test de Duane Wessels. Ses spécifications collent parfaitement à ce que je veux : il se connecte à tous les serveurs DNS d'une zone, demande les signatures, regarde les dates d'expiration et peut signaler un avertissement ou une erreur selon des seuils choisis par l'utilisateur. Un exemple à la main :

% perl check_zone_rrsig_expiration -Z nic.fr  
ZONE OK: No RRSIGs expiring in the next 3 days; (1.04s) |time=1.042905s;;;0.000000
On peut choisir les seuils, donc mettons qu'on veut un avertissement s'il reste moins d'une semaine :
% perl check_zone_rrsig_expiration -Z nic.fr -W 7
ZONE WARNING: MX RRSIG expires in 3.7 days at ns6.ext.nic.fr; (0.28s) |time=0.281515s;;;0.000000

Pour installer et exécuter ce script, il faut Perl et certains modules indiqués dans la documentation. Sur ma machine Arch Linux, ils n'étaient pas en paquetage standard, il faut donc utiliser AUR, un dépôt non officiel, accessible avec les commandes pacaur ou yaourt :

% yaourt  -S perl-net-dns perl-net-dns-sec
Attention, si vous n'installez pas tous les paquetages indiqués dans la documentation, vous aurez un message pas clair du tout :
***  WARNING!!!  The program has attempted to call the method
***  "sigexpiration" for the following RR object:
Une fois le programme correctement installé, je vous recommande l'option -d si vous voulez déboguer en détail ce qu'il fait.

On configure ensuite Icinga, par exemple :

  object Host NodeName {
  import "generic-host"
  address = "127.0.0.1"
  address6 = "::1"
  vars.role = "AuthDNS"
  [...]
}

object CheckCommand "CheckDNSSEC" {
  import "plugin-check-command"
  command = [ PluginDir + "/check_zone_rrsig_expiration" ]
  arguments = {
    "-Z" = "$zone$"
    "-W" = "$warn$"
    "-C" = "$crit$"
  }
  vars.warn = "14"
  vars.crit = "7"
}

apply Service "DNSSEC" {
  check_command = "CheckDNSSEC"

  check_interval = 86400
  vars.zone = "example.org"
  assign where host.vars.role == "AuthDNS"
}
(Merci à Xavier Humbert à ce sujet.) Cette configuration était pour Icinga 2. Pour Icinga 1 :
define command {
        command_name    check-zone-rrsig
        command_line    /usr/local/sbin/check_zone_rrsig_expiration -Z $HOSTADDRESS$ -W $ARG1$ -C $ARG2$
        }

...

define service {
       use dns-rrsig-service
       hostgroup_name My-zones
       service_description SIGEXPIRATION
       # Five days left: warning. Two days left: panic.
       check_command   check-zone-rrsig!5!2
}

define host{
        name                            my-zone
        use                      generic-host
	check_command             check-always-up
        check_period                    24x7       
        check_interval                  5
        retry_interval                  1 
        max_check_attempts              3
        contact_groups                  admins 
        notification_period             24x7
        notification_options		u,d,r
        register 0
}

define hostgroup{
       hostgroup_name My-zones
       members bortzmeyer.org,bortzmeyer.fr,etc-etc
}

define host{
       use moi-zone
       host_name bortzmeyer.fr
}
Une fois que c'est fait, on redémarre Icinga. Ici, voici un test avec une zone délibérement cassée (elle a été signée manuellement en indiquant la date d'expiration ldns-signzone -e 20140322100000 -o broken.rd.nic.fr. broken.rd.nic.fr Kbroken.rd.nic.fr.+008+15802 et sans re-signer ensuite). Icinga enverra ce genre d'avertissement :
Notification Type: PROBLEM

Service: DNSRRSIG
Host: broken.rd.nic.fr
Address: broken.rd.nic.fr
State: WARNING

Date/Time: Fri Mar 28 06:50:38 CET 2014

Additional Info:

ZONE WARNING: DNSKEY RRSIG expires in 1.2 days at ns2.bortzmeyer.org: (1.12s)
Puis un CRITICAL puis, lorsque la zone aura vraiment expiré :
Notification Type: PROBLEM

Service: DNSRRSIG
Host: broken.rd.nic.fr
Address: broken.rd.nic.fr
State: CRITICAL

Date/Time: Mon Mar 31 09:10:38 CEST 2014

Additional Info:

ZONE CRITICAL: ns2.bortzmeyer.org has expired RRSIGs: (1.10s)
Si on re-signe à ce moment, le problème disparait :
Notification Type: RECOVERY

Service: DNSRRSIG
Host: broken.rd.nic.fr
Address: broken.rd.nic.fr
State: OK

Date/Time: Mon Mar 31 09:40:38 CEST 2014

Additional Info:

ZONE OK: No RRSIGs expiring in the next 3 days: (1.04s)
Et, dans le journal d'Icinga, cela apparaitra :
[Fri Mar 21 21:40:32 2014] SERVICE ALERT: broken.rd.nic.fr;DNSRRSIG;CRITICAL;SOFT;2;ZONE CRITICAL: DNSKEY RRSIG expires in 0.6 days at ns2.bortzmeyer.org: (1.09s)
...
[Fri Mar 21 21:42:32 2014] SERVICE ALERT: broken.rd.nic.fr;DNSRRSIG;OK;SOFT;3;ZONE OK: No RRSIGs expiring in the next 7 days: (0.68s)

Pour les utilisateurs d'OpenDNSSEC, le paramètre important à régler en même temps que les seuils de la supervision est le paramètre . Comme le dit la documentation : « The signature will be refreshed when the time until the signature expiration is closer than the refresh interval. » Donc, en pratique, c'est la durée qu'il faut indiquer avec l'option -C (seuil critique). Attention, OpenDNSSEC ajoute de légères variations (jitter).

J'ai indiqué plus haut qu'il y avait des alternatives à la solution finalement choisie. Il en existe même une liste sur le site d'Icinga. Voici quelques pistes avec mes commentaires.

J'aurais pu développer une solution complète avec Python et dnspython qui a une bonne gestion de DNSSEC. J'ai réalisé un prototype mais, dans la vie, il faut savoir reconnaître un logiciel meilleur que le sien.

Il y a un outil développé par les gens de .se, dnssec_monitor. Écrit en Perl, il a les mêmes dépendances que le script choisi. Mais je n'arrive pas réellement à comprendre comment il s'intègre avec Nagios.

Il existe un outil en Ruby dans OpenDNSSEC (il est même décrit en détail dans la documentation d'Icinga). Il a pas mal de dépendences Ruby donc j'ai renoncé.

L'outil nagval est très bien mais il n'a pas le même cahier des charges et, notamment, il ne permet pas de tester l'expiration qui va survenir.

Il existe un énorme ensemble de programmes de tests Nagios qui semble intéressant, et qui compte un check_dnssec_expiration. Il se compile bien :

% ./configure --without-man
% make
mais l'exécution est incohérente, une fois sur deux :
% ./dns/check_dnssec_expiration -v -D nic.fr -w 20 -c 3
CRITICAL - SOA is not signed.
La bogue a été signalée à l'auteur mais pas encore résolue. Il semble que l'outil soit très sensible au résolveur utilisé et qu'il faille forcer (via resolv.conf ou via l'option -H) un résolveur rapide et fiable.

Mat a également un script à lui en awk (avec une version en shell). Mais il est à mon avis très dépendant d'un environnement local, pas utilisable tel quel, sans sérieuses modifications, à mon avis. Je cite l'auteur : « c'est tout à fait adaptable, il suffit de remplacer /usr/bin/make -VSIGNED par la liste des fichiers de zones signés et /usr/bin/make -VSIGNED:R:T par l'ensemble des noms des zones. SIGNED étant défini dans le Makefile comme SIGNED!= find -s * -name '*.signed'. ». Du même auteur, un outil permet de tester des fichiers, pas facilement des zones vivantes :

% cat *.signed | awk -f check-expire.awk
Pour tester une zone vivante, il faut que le transfert de zone soit autorisé :
% dig +noall +answer axfr @$SERVERNAME $ZONE | awk -f check-expire.awk

Je n'ai pas encore testé l'outil check_dnssec_expiry.

Enfin, SURFnet a développé un outil (qui dépend de ldns) mais que je n'ai pas réussi à compiler :

...
cc -lcrypto `ldns-config --libs` -o sigvalcheck sigvalcheck.o rrsig_valcheck.o query.o
rrsig_valcheck.o: In function `ldns_rrsig_time_until_expire':
/home/stephane/tmp/sigvalcheck-0.1/rrsig_valcheck.c:42: undefined reference to `ldns_rr_rrsig_expiration'
/home/stephane/tmp/sigvalcheck-0.1/rrsig_valcheck.c:41: undefined reference to `ldns_rdf2native_time_t'

par Stéphane Bortzmeyer

Blog de Stéphane Bortzmeyer

RFC 9460: Service Binding and Parameter Specification via the DNS (SVCB and HTTPS Resource Records)

 -  8 avril - 

Ces deux nouveaux types d'enregistrement DNS, SVCB et sa variante HTTPS, permettent de donner des informations supplémentaires à un client réseau (...)


Un résolveur DNS public en Inde

 -  7 avril - 

J'avais raté l'information : il y a désormais un résolveur DNS public en Inde, dns.nic.in.Il ne semble pas y avoir eu beaucoup de communication (...)


IETF 119 hackathon: compact denial of existence for DNSSEC

 -  22 mars - 

On March 16 and 17 was the IETF hackathon in Brisbane. I worked on a DNSSEC feature called "compact denial of existence", and implemented it (...)


Eaten by the Internet

 -  22 mars - 

Ce court livre en anglais rassemble plusieurs textes sur les questions politiques liées à l'Internet comme la défense de la vie privée, le (...)


La faille DNSSEC KeyTrap

 -  19 mars - 

Le 16 février a été publiée la faille de sécurité DNSSEC KeyTrap. Je sais, c'est un peu tard pour en parler mais c'est quand même utile, non ?KeyTrap (...)