DNSSEC par la pratique (tutoriel Bind9/Debian)

De Ensiwiki
Aller à : navigation, rechercher
DNSSEC: Problèmes de performance et ponts vers d'autres protocoles
Projet Projet de spécialité 2A
Sous-projet Communication et Réseaux
Étudiants Quentin LUC, Cyril LUPO, Thê-Minh TRINH
Promo 2012
Tuteur Martin Heusse (LIG)
Accueil projet: DNSSEC: Problèmes de performances et ponts vers d’autres protocoles

Cet article présente un tutoriel expliquant comment mettre en place une architecture de résolution de nom (DNS puis DNSSEC) sur un réseau de machines virtuelles. En premier lieu, nous nous intéresserons aux configurations de base en configurant une architecture simplifiée avec un client et un serveur de nom, puis nous nous intéresserons à la configuration d'une architecture hiérarchique. Le système d'exploitation utilisé est ici Debian 6.0.1a. On utilisera Bind9.7.3 sur les serveurs DNS.

Mise en place des réseaux

Nous utiliserons ici des réseaux de machines virtuelles. Pour cela, il faut donc créer des interfaces virtuelles sur chaque machine virtuelle.

Relier une interface à Internet

Nous aurons principalement besoin de relier une interface à internet lorsque nous aurons à exporter des fichiers (fichiers de source ou capture) ou télécharger des paquets. Pour cela, il faut configurer une interface virtuelle en NAT puis autoriser la configuration automatique de l’accès à internet via DHCP sur Bind. Je vous conseille personnellement d’avoir au minimum deux interfaces sur la machine sur laquelle vous souhaitez accéder à internet. La première en NAT, la seconde et éventuellement les suivantes sur le/les réseaux virtuels que vous souhaitez.

Le fichier /etc/network/interfaces indique les opérations à réaliser au démarrage pour le réseau. C'est dans ce fichier que l'on doit configurer les interfaces pour que tout fonctionne au démarrage. Par défault, la première interface est configurée en DHCP et c'est donc elle qui va servir pour relier la machine à internet.

Pour configurer les autres interfaces au démarrage, ajoutez à la fin du fichier les lignes suivantes :

auto ethX
iface ethX inet static
    address X.X.X.X
    netmask 255.255.255.255

Ainsi, à chaque démarrage de la machine, l'interface ethX sera activée et aura pour adresse X.X.X.X.


Remarque : Il est possible que vous souhaitiez ne pas avoir accès à internet en permanence et l’activer seulement si nécessaire. Pour cela, il suffit simplement de désactiver l’interface de la machine au démarrage (en passant par le logiciel de virtualisation et pas par Debian). Pour établir une connexion internet, il suffira simplement de l’activer puis de redémarrer le réseau.

Relier une interface à un réseau interne

Les logiciels de virtualisation possède plusieurs sous-réseaux auquel il est possible de connecter des interfaces virtuelles. Il faut donc simplement que deux machines soient reliées au même sous-réseau et que leur adresse IP soient correctement configurées pour qu'elles puissent échanger en toute tranquillité.

Configuration d'une architecture DNS pour Bind9

Architecture à une seule zone

Il s'agira de mettre en place la configuration suivante:

Architecure basique.png

Configuration du client pc1

Sur pc1, il faut préciser sur quel serveur de nom envoyer les requêtes. Pour cela, éditez le fichier /etc/resolv.conf, et remplacez ce qui y est écrit (le resolveur DNS utilisé lors de la dernière requête), par la ligne nameserver 10.0.0.2.

Configuration du serveur de nom pc2

Sur pc2, il faut maintenant configurer le serveur de nom. Le premier fichier à éditer est le fichier de configuration du daemon named. Pour cela remplacez dans /etc/bind/named.conf.options la ligne listen-on {127.0.0.1;} par listen-on {any;}. Ainsi, le serveur de nom va aussi pouvoir écouter les requêtes de pc1.

Il faut maintenant configurer la zone. On veut par exemple un serveur ayant autorité sur la zone .projet., qui contient les enregistrements server.projet, quentin.projet, cyril.projet et theminh.projet. À la fin de /etc/bind/named.conf.local, ajoutez donc:

zone “projet” {
		type master;
		file “/etc/bind/db.projet”;
	};

Il faut maintenant créer le fichier db.projet et insérer les enregistrements voulus.

$TTL	2h
@	IN	SOA	server.projet. postmaster.projet. (
				20110601
				8H
				2H
				1W
				1D
	)

@		IN	NS	server.projet.

server		A	192.168.0.3
cyril		A	192.168.0.41
quentin		A	192.168.10.4
theminh		A	192.168.0.121

Après chaque modification de configuration, redémarrer le daemon named avec la commande /etc/init.d/bind9 restart

Mise en place d'une architecture hiérarchique

Le but de cette partie sera de mettre en, œuvre une architecture DNS hiérarchique, qui consiste à avoir un serveur de nom autoritaire et un sous-domaine se situant dans une autre zone. L'architecture que nous souhaitons mettre en place doit se rapprocher le plus possible de la réalité et ne pas interagir avec les serveurs DNS mondiaux. Par conséquent, nous allons faire en sorte que le serveur autoritaire soit considéré comme le serveur root.

Au niveau réseau, la configuration à mettre en place est donc la suivante :

Architecture hierarchique.png

pc1 est ici un client (le daemon named ne tourne pas sur pc1). pc2 est un serveur de nom récursif (in n'a autorité sur aucune zone). pc3 est un serveur de nom itératif qui a autorité sur la zone projet., qui joue ici le rôle de zone racine. pc4 est un serveur itératif qui a autorité sur la zone quentin.projet. , qui est un sous-domaine de projet.. Il est à noter que pc1, pc3 et pc4 sont sur des sous-réseaux différents.

Congifuration de pc1

Il suffit d'indiquer à pc1 qu'il doit contacter pc2 pour la résolution de noms. On doit donc remplacer le contenu du fichier /etc/resolv.conf par

nameserver 10.0.0.2

Congifuration de pc2

PC2 va ici jouer le rôle de serveur récursif. Par défault, BIND se comporte de cette manière.

La première chose à faire est de vider le fichier /etc/resolv.conf afin que toutes les requêtes soient redirigées directement vers BIND.

Ensuite, BIND connaît par défaut l'adresse de tous les serveurs root de la planète. Il va donc falloir lui indiquer que le seul serveur root qu'il doit contacter est pc3. Pour cela, ouvrez le fichier /etc/bind/db.root et supprimez toutes les lignes autres que les deux premières qu'il faut renseigner comme suit :

.              3600000   IN   NS   projet.
projet.        3600000        A    192.168.0.3

Enfin, je vous conseille de rassembler l'ensemble des include de named.conf dans ce fichier pour que les erreurs soient plus rapidement détectables (la séparation des fichiers est inutile ici, puisque la configuration n'est pas lourde). Vous pouvez tout de même garder la séparation, elle ne change rien à la configuration.

Le contenu du fichier named.conf doit ressembler à celui-ci :

options {
	directory "/var/cache/bind";

	auth-nxdomain no;    # conform to RFC1035
	listen-on { any; };
};

zone "." {
	type hint;
	file "/etc/bind/db.root";
};

Remarque : Pour éviter les effets non-désirés, je vous conseille fortement de supprimer (ou déplacer) les fichiers autres que db.root, named.conf (et ses dérivés) et rndc.key

Congifuration de pc3

PC3 va ici jouer le rôle de serveur autoritaire sur le domaine .projet.

Le premier fichier à éditer est le fichier de configuration du daemon named. Pour cela remplacez dans /etc/bind/named.conf.options la ligne listen-on {127.0.0.1;} par listen-on {any;}. Ainsi, le serveur de nom va aussi pouvoir écouter les requêtes de pc1.

Il faut maintenant configurer la zone. À la fin de /etc/bind/named.conf.local, ajoutez donc :

zone “projet” {
		type master;
		file “/etc/bind/db.projet”;
	};

Il faut maintenant créer le fichier db.projet et insérer les enregistrements voulus. Dans ce cas-ci, le serveur pc4 est un serveur gérant le sous-domaine quentin.projet. Il faut donc lui indiquer un enregistrement NS pour que le serveur récursif demande au sous-domaine. Le fichier db.projet est donc :

$TTL 2h
@	IN	SOA	server.projet. postmaster.projet. (
	20110601
	8H
	2H
	1W
	1D
	)
@	IN	NS	server.projet.
server	A	192.168.0.3
cyril	A	192.168.0.41
theminh	A	192.168.0.121


$ORIGIN	quentin.projet.
@		IN	NS	server
server		A		192.168.10.4

Après chaque modification de configuration, redémarrer le daemon named avec la commande /etc/init.d/bind9 restart

Remarque : Pour éviter les effets non-désirés, je vous conseille fortement de supprimer (ou déplacer) les fichiers autres que db.projet, named.conf (et ses dérivés) et rndc.key


Congifuration de pc4

La configuration est quasiment identique à celle de pc3. Seulement le contenu des fichiers change.

Le premier fichier à éditer est le fichier de configuration du daemon named. Pour cela remplacez dans /etc/bind/named.conf.options la ligne listen-on {127.0.0.1;} par listen-on {any;}. Ainsi, le serveur de nom va aussi pouvoir écouter les requêtes de pc1.

Il faut maintenant configurer la zone. À la fin de /etc/bind/named.conf.local, ajoutez donc :

zone “quentin.projet” {
		type master;
		file “/etc/bind/db.quentin.projet”;
	};

Il faut maintenant créer le fichier db.quentin.projet et insérer les enregistrements voulus. Le fichier db.quentin.projet est donc :

$TTL 2h
@	IN	SOA	server.projet. postmaster.projet. (
	20110601
	8H
	2H
	1W
	1D
	)
@	IN	NS	server.quentin.projet.
server	A	192.168.10.4
ski	A	192.168.10.20
rando	A	192.168.10.51
bateau  A       192.168.10.121

Après chaque modification de configuration, redémarrer le daemon named avec la commande /etc/init.d/bind9 restart

Remarque : Pour éviter les effets non-désirés, je vous conseille fortement de supprimer (ou déplacer) les fichiers autres que db.quentin.projet, named.conf (et ses dérivés) et rndc.key

Captures et Débug

Localisation des logs

Si le serveur ne fonctionne pas comme vous le souhaitez, il est très probable que vous trouviez la source de votre problème (et donc sa solution ;) ) dans le fichier de log de bind.

Celui-ci se situe dans : /var/log/daemon.log

Captures

Le fait que les machines soient toutes sous des sous-réseaux différents complique les captures et l'analyse des paquets échangés sur le réseau. Il est donc fortement recommandé de faire l'ensemble des captures sur pc2 qui est au centre de toutes les communications.

Pour capturer les paquets, on utilise notre très cher tcpdump. Ce logiciel permet seulement de capturer des paquets sur une interface à la fois. Il faut donc le lancer trois fois, pour avoir les paquets sur chacune des trois interfaces de pc2 (c'est la raison pour laquelle il faut le faire sur la même machine, car les horloges des différents systèmes ne sont pas synchronisées). Il est ensuite possible de les rassembler en un fichier par le biais de mergecap (nous n'avons pas réussi à l'installer) ou tout simplement en rapatriant vos fichiers sur votre machine et en le faisant avec Wireshark (File > Merge).

De plus, il est conseillé de vider le cache de chacune des machines sur lesquelles Bind est lancé et de le redémarrer afin d'appliquer l'ensemble des changements effectué. Pour éviter de taper un ensemble de commande assez répétitif, et de switcher trop régulièrement entre les machines virtuelles, nous vous conseillons d'utiliser un script shell qui fera tout automatiquement, pour vous.

Voici le script que nous avons utilisé :

#!/bin/sh

if [ $3 -eq 1 ] ; then

	echo "Redémarrage resolver + vidage du cache"
	rndc flush
	/etc/init.d/bind9 restart


	echo "Redémarrage serveur autoritaire + vidage cache"
	ssh root@192.168.0.3 /etc/init.d/bind9 restart
	ssh root@192.168.0.3 rndc flush


	echo "Redémarrage serveur sous-zone"
	ssh root@192.168.10.4 /etc/init.d/bind9 restart
	ssh root@192.168.10.4 rndc flush
fi

echo "Lancement des captures"
tcpdump -i eth1 -s0 -w sclient.log &
tcpdump -i eth2 -s0 -w serveur_auto.log &
tcpdump -i eth3 -s0 -w serveur_soumis.log &

echo "Requete ski.quentin.projet du client"
ssh root@10.0.0.1 dig $1 $2


killall tcpdump
scp sclient.log root@192.168.0.3:/home/
scp serveur_auto.log root@192.168.0.3:/home/
scp serveur_soumis.log root@192.168.0.3:/home/

echo "Envoi sur ensibm"
ssh root@192.168.0.3 scp /home/sclient.log lupoc@ensibm.imag.fr:.
ssh root@192.168.0.3 scp /home/serveur_auto.log lupoc@ensibm.imag.fr:.
ssh root@192.168.0.3 scp /home/serveur_soumis.log lupoc@ensibm.imag.fr:.

La commande fonctionne ainsi :

./captures [+dnssec] <adresse> [1]

Si le 1 est présent, tous les caches seront vidés et les serveurs redémarrés.

Remarques : Pour que ce script fonctionne, il faut avoir installé des clés ssh de telle sorte que la machine 2 puisse se connecter à la machine 3 sans avoir à redemander le mot de passe à chaque fois, mais aussi entre la machine 3 et votre compte distant (ici c'est ensibm). Pour cela, reportez-vous au tp réseau de première année :)

Implémentation de DNSSEC

L'implémentation de DNSSEC n'est vraiment intéressante que pour une architecture hiérarchique, car le cas basique (client-serveur unique) ne donne pas l'occasion de rencontrer les problématiques de chaîne de confiance et. Toutefois, il est intéressant de s'entrainer au préalable sur une architecture basique avant de se frotter à une architecture hiérarchique. Dans un souci de pédagogie, ce tutoriel suit cette démarche.

DNSSEC sur une seule zone

Il s'agira ici d'implémenter DNSSEC entre le client pc1 et le serveur de nom pc2. Il est à noter qu'ici pc1 est un petit peu plus qu'un client classique car il doit pouvoir vérifier la signature des réponses qu'il reçoit. Le daemon named doit donc aussi tourner sur pc1.

Configuration de pc2

Côté serveur, on commence par créer deux paires de clés :

cd /etc/bind/
dnssec-keygen -f KSK -a RSASHA1 -b 1024 -n ZONE projet
dnssec-keygen -a RSASHA1 -b 1024 -n ZONE projet

Attention ! Notez bien les identifiant des clés pour pouvoir les distinguer par la suite.

Remarque 1 : Sous Debian (et apparemment bien d’autres distributions GNU/Linux), la génération de clés est extrêmement longue. Ceci est dû au fait que le générateur d’aléa (/dev/random) se base sur l’entropie générée par la machine. Et pour une machine à faible entropie, ça peut être long ! Pour nos tests, on se contentera du générateur pseudo-aléatoire en ajoutant l’option : -r /dev/urandom

Remarque 2 : Vous trouverez sûrement dans la littérature sur DNSSEC des remarques sur la taille des clés. La KSK est à renouveler moins souvent que la ZSK, elle peut donc être plus longue. Ici, on a fait le choix que les deux aient la même taille.

Remarque 3 : Vous remarquerez que cette commande créé deux fichier à chaque fois, un fichier .key et un fichier .private, qui correspondent respectivement à la clé publique et à la clé privée.


Le fichier .key contient l'enregistrement DNSKEY de la zone en question :

; This is a key-signing key, keyid 51781, for quentin.projet.
; Created: 20110607122604 (Tue Jun  7 14:26:04 2011)
; Publish: 20110607122604 (Tue Jun  7 14:26:04 2011)
; Activate: 20110607122604 (Tue Jun  7 14:26:04 2011)
quentin.projet. IN DNSKEY 257 3 5 AwEAAfE8ezIHSj+...


Introduisons maintenant les enregistrements DNSKEY des clés dans notre fichier de zone (db.projet).

Ecrivez à la fin de db.projet :

$include nom_du_fichier_KSK.key
$include nom_du_fichier_ZSK.key

Signons maintenant la zone :

dnssec-signzone -t -k clé_KSK.key db.projet -o projet clé_ZSK.key

Ceci crée le fichier projet.signed qui contient l'ensemble des enregistrements de la zone complétés par les enregistrements de DNSSEC (RRSIG et NSEC notamment)


La dernière étape est de modifier /etc/bind/named.conf. Dans named.conf.local, effectuer la modification :

zone “projet” {
	type “master”;
	file “/etc/bind/db.projet.signed”;
};

Dans named.conf.options, ajouter entre les accolades :

dnssec-enable yes;

N’oubliez pas de relancer bind :

/etc/init.d/bind9 restart

Configuration de pc1

Côté client, c'est un peu plus simple !

Dans une architecture à deux ordinateurs, si vous voulez faire de la vérification côté client, voici la démarche à suivre. Premièrement, il faut récupérer la KSK publique. Une fois cela fait, il faut la mettre dans le fichier /etc/trusted-key.key :

tail -n 1 KSK.key > /etc/trusted-key.key #si le fichier existe déjà, faites '>>'

Mainenant, vous pouvez effectuer le test en faisant :

dig +dnssec +sigchase papa.projet

DNSSEC sur une architecture hiérarchique

Nous reprenons la configuration des serveurs telle que nous l'avons laissé dans la section 2.2.

Configuration de pc4

Ce serveur la doit avoir deux paires de clés (une pour la ZSK, et une pour la KSK). Il faut donc effectuer les mêmes opérations que celles décrites ci-dessus, pour le pc2 de l'architecture à deux machines.

  • Génération des paires de clés
  • Insertion dans le fichier de zone
  • Signature de la zone
  • Modification de named.conf :
zone “quentin.projet” {
	type “master”;
	file “/etc/bind/db.quentin.projet.signed”;
};
  • Ajout de l'option dnssec-enabled yes;


Maintenant que toutes ces étapes ont été effectuées, il faut envoyer au serveur autoritaire le fichier contenant l'enregistrement DS de la zone (voir Introduction à DNSSEC) de manière sécurisée et indépendante de DNSSEC (la sécurité importe peu dans le cas présent, mais c'était juste pour la forme).

Cet enregistrement a été créé dans un fichier à part : dsset-quentin.projet. qui contient :

quentin.projet.		IN DS 51781 5 1 3BFA45EC2BF40CC96308A3C3C4D2F55812E17015
quentin.projet.		IN DS 51781 5 2 754505D33985643182D3EF9AA0E47B4D3324A4818EA682BDA79E89DF 76377A74

Configuration de pc3

Ce serveur la doit aussi avoir deux paires de clés (une pour la ZSK, et une pour la KSK). Il faut donc effectuer les mêmes opérations que celles décrites ci-dessus, pour le pc2 de l'architecture à deux machines (avec quelques étapes supplémentaires) :

  • Génération des clés
  • Insertion des enregistrements DNSKEY dans le fichier de zone
  • Récupération du fichier dsset-quentin.projet et insertion de son contenu dans le fichier de zone (db.projet)
  • Signature de la zone
  • Ajout des infos dans named.conf

Voila, c'est tout. Pour les étapes qui ne sont pas détaillées, ce sont exactement les mêmes que celles détaillées ci-dessus.

Configuration de pc1

Le client n'a pas besoin de configuration particulière, il demande juste des réponses dnssec par l'intermédiaire d'un dig +dnssec <nom_domaine>

Configuration de pc2

Le serveur récursif doit simplement connaître la clé publique associée à la KSK du serveur autoritaire. Il faut lui transmettre cette clé par d'autre moyen que DNSSEC, car elle correspond dans notre cas à la trust anchor (voir section 1.4 de l'introduction à DNSSEC).

Une fois le fichier KSK.key récupéré, il faut indiquer dans named.conf qu'on fait confiance à cette clé. Pour cela, il faut rajouter les lignes suivantes :

trusted-keys {
     "projet." 257 3 5 "clé (chaine de caractère)"
};


Remarque : Pour vérifier que pc2 fait bien la vérification des clés et refuse bien les requêtes incorrectes, vous pouvez utiliser l'option dnssec-must-be-secure projet yes; (à rajouter dans accolade options donc), modifier la clé dans trusted-keys et vérifier que le client ne reçoit plus de réponse.

Observations

Les Captures suivantes (Fichier:Captures.tar.gz) retracent l'ensemble des trames que l'on peut observer entre les machines de l'architecture que nous venons de mettre lorsque nous effectuons un requête sur un nom appartenant au sous-domaine quentin.projet. Il est recommandé d'ouvrir ces fichiers avec wireshark.

Le fichier Recursion.pcap retrace les échanges pour une requête valide. Il est à rapproché du schéma suivant:


Requete dnssec.png


remarque: Il est à noter que ce schéma ne prend pas en compte le fait que pc2 commence par contacter pc3 avant. Il commence au moment où pc2 contacte pc4


Le fichier recursion_noexist.pcap retrace les échanges pour une requête invalide. On entend par requête invalide une requête concernant un nom qui n'est dans aucun enregistrement de la zone spécifiée.