dns : rfc 1034 en francais : resolveurs
5. RESOLVEURS
5.1.
IntroductionLes
"résolveurs" sont des programmes qui interfacent les applications utilisateur
aux serveurs de noms de domaines. Dans le cas le plus simple, un résolveur
reçoit une requête provenant d'une application (ex., applications de courrier
électronique, TELNET, FTP) sous la forme d'un appel d'une fonction de
bibliothèque, d'un appel système etc., et renvoie une information sous une forme
compatible avec la représentation locale de données du système.
Le résolveur est situé sur la même
machine que l'application recourant à ses services, mais devra par contre
consulter des serveurs de noms de domaines sur d'autres hôtes. Comme un
résolveur peut avoir besoin de contacter plusieurs serveurs de noms, ou à
l'extrême inverse obtenir les informations directement à partir de son cache
local, le temps de réponse d'un résolveur peut varier selon de grandes
proportions, depuis quelques millisecondes à plusieurs secondes.
L'une des raisons les plus
importantes qui justifient l'existence des résolveurs est d'éliminer le temps
d'acheminement de l'information depuis le réseau, et de décharger simultanément
les serveurs de noms, en répondant à partir des données cachées en local. Il en
résulte qu'un cache partagé entre plusieurs processus, utilisateurs, machines,
etc., sera incomparablement plus efficace qu'une cache non
partagé.
5.2. Interface
résolveur-client
5.2.1. Fonctions
typiquesL'interface
client du résolveur est largement dépendante des conventions de l'hôte local,
mais on peut exprimer trois fonctions typiques qui rentrent dans le cadre de
cette interface :
- translation depuis les noms
d'hôtes vers les adresses d'hôtes.
Cette fonction est souvent définie
à l'image d'anciens mécanismes utilisant les fichiers HOSTS.TXT. A partir
d'une certaine chaîne de caractères donnée, l'appelant désire obtenir une ou
plusieurs adresses IP sur 32 bits. Dans le contexte du DNS, cette demande se
traduit par une requête sur des RR de type A. Comme le DNS ne préserve pas
l'ordre des RR, cette fonction peut choisir de trier et répondre par toutes
les adresses obtenues, ou seulement la "meilleure" adresse si le client est
plus enclin à n'accepter qu'une adresse unique en retour. Notez qu'il est
recommander d'utiliser un retour multiple, mais un retour d'adresse unique
peut dans certains cas être la seule solution pour émuler le fonctionnement
d'anciens services basés sur des fichiers HOSTS.TXT.
- Translation depuis une adresse
vers un nom d'hôte
Cette fonctionnalité suivra
souvent dans sa formulation, la forme de fonctions plus anciennes. A partir
d'une adresse IP 32 bits, le requérant désire une chaîne de caractères donnant
le nom de la machine. Le sens des octets de l'adresse IP sera alors inversé.
Les quatre octets ainsi transformés étant alors utilisé comme composante de
nom, on les suffixera de la chaîne "IN-ADDR.ARPA". Une requête de type PTR est
alors envoyée pour obtenir le RR donnant le nom primaire de l'hôte en
question. Par exemple, une requête à propos de la machine d'adresse IP 1.2.3.4
recherchera des RR PTR pour le nom de domaine
"4.3.2.1.IN-ADDR.ARPA".
- Fonction de recherche
générale
Cette fonction récupère des
informations arbitraire à partir du DNS, et n'a pas de fonctionnalité
antérieure correspondante. Le requérant fournit un QNAME, QTYPE, et une
QCLASS, et désire obtenir tous les RR correspondants. Cette fonction utilisera
de préférence la représentation DNS pour toutes les données des RR plutôt que
celle de l'hôte local, et retournera le contenu de ces RR (ex., TTL) plutôt
qu'une forme traitée selon les conventions locales.
Lorsque le résolveur exécute la
fonction, on pourra s'attendre à l'une des réponses suivantes :
- Un ou plusieurs RR donnant les
données demandées. Dans ce cas, le résolveur fournit la réponse dans le
format approprié.
- Une erreur de nom (NE). Ceci
arrive lorsque le nom présenté n'existe pas. Par exemple, un utilisateur
peut très bien avoir mal orthographié un nom d'hôte.
- Une erreur "donnée non
trouvée". Ceci intervient lorsque le nom demandé existe, mais pas les
données du type spécifié pour le nom demandé. Par exemple, une requête pour
une adresse d'hôte appliquée à un nom de boîte aux lettres retournerait
cette erreur, car le nom existe bel et bien, mais pas le RR donnant une
adresse d'hôte.
Il est important de noter que les
fonctions de translation entre des noms d'hôte et des adresses peuvent
retourner la combinaison d'une "erreur de nom" et d'une erreur "donnée non
trouvée" dans un seul retour d'erreur, alors que la fonction de recherche
générale ne le pourra pas. Une raison pour ceci est que les applications
peuvent dans un premier temps demander un certain type d'information à propos
d'un hôte puis dans une seconde requête un autre type d'information à propos
du même hôte ; si les deux erreurs sont combinées, alors les requêtes inutiles
ralentiraient l'application.
5.2.2.
AliasLorsqu'il
essaie de résoudre une requête particulière, le résolveur peut s'apercevoir que
le nom demandé est un alias. Par exemple, le résolveur s'aperçoit que le
résultat d'une translation est de ce type lorsque le RR renvoyé est un CNAME. Si
possible, ce cas de détection d'un alias devra être signalée au
client.
Dans la plupart des cas, un
résolveur relancera la résolution sur le nouveau nom translaté donné dans le RR
CNAME. Cependant, lors de l'appel à la fonction de recherche généralisée, le
résolveur ne suivra pas la chaîne d'alias lorsque le RR CNAME est reçu en
réponse à une requête sur ce même type. Ceci permet justement d'émettre des
requêtes pour savoir si un alias existe. Autrement dit, si le type de requête
demandé est CNAME, l'utilisateur s'intéresse effectivement au RR CNAME en tant
que tel, et non l'objet final qu'il représente.
Un certain nombre de conditions
spécifiques peuvent apparaître lorsque l'on traite avec des alias. On cherchera
à éviter des longues chaînes de redirection par alias, dans la mesure ou cela
porte atteinte à l'efficacité du système. Par contre, cette situation ne sera
pas signalé comme un cas d'erreur. Inversement, des bouclages d'une chaîne de
redirection par alias ainsi que des alias pointant sur des noms inexistants
devront être signalés comme erreur, laquelle sera reportée au
client.
5.2.3. Fautes
temporairesConcrètement, tous les résolveurs pourront se retrouver
occasionnellement dans l'incapacité d'achever une résolution. Cette situation
peut apparaître lorsqu'un résolveur perd le contact avec une partie du réseau à
cause d'une panne réseau ou d'un routeur, ou, de façon moins courante dans le
cas d'une indisponibilité ou défection simultanée de tous les serveurs
correspondant à une zone.
Il est essentiel que cette classe
d'erreur ne soit pas reportée au client au même titre qu'une erreur de nom ou
que d'une erreur sur l'existence des données. Non seulement ce type d'erreur
irrite notablement l'utilisateur humain, mais peut aussi causer de sérieux
problème lorsqu'une messagerie utilise le DNS.
Il serait possible dans de tels cas
d'erreurs de résoudre cette situation momentanée en bloquant la requête
indéfiniment, dans l'attente de la levée de la condition de faute. Mais il
s'agit d'une mauvaise idée, surtout lorsque le client est un processus serveur
qui pourrait exploiter ce temps d'attente à des tƒches bien plus utiles. La
solution préconisée est de toujours admettre qu'une erreur "temporaire" puisse
être un des résultats possibles de l'appel à une fonction de résolution, même si
cela peut rendre l'émulation de certaines fonctions basées sur le principe du
HOSTS.TXT plus ardue.
5.3. Résolveurs - spécifications
internesToutes les
implémentations de résolveur utilisent des algorithmes sensiblement différents,
et utilisent la plupart de leur code pour traiter les erreurs de toutes natures
plutôt que les occurrences "normales". Cette section expose une stratégie
recommandée de base pour mener les opérations de résolution, les détails pouvant
être trouvés dans la [RFC-1035].
5.3.1. Noyau de résolution
minimalUne
possibilité pour l'implémentation de la fonction résolveur est de déporter la
fonction de résolution au dehors de la machine locale vers un serveur de noms
supportant le mode récursif. Ceci constitue une méthode simple pour offrir le
service de de noms de domaines à un PC un peu faible en ressources, et pour
centraliser le cache pour l'ensemble des machines et utilisateurs d'un réseau
local ou d'une organisation.
Tout ce dont le noyau de résolution
minimal à besoin est une liste d'adresses de serveurs de noms susceptible de
mener la résolution récursive à notre place. Ce type de résolveur aura
certainement besoin de ces informations stockées dans un fichier de
configuration, car il n'aura probablement pas la sophistication suffisante pour
localiser celle-ci dans la base de données des domaines. De plus, l'utilisateur
aura besoin de vérifier que les serveur mentionnés peuvent effectivement fournir
le service récursif ; un serveur de noms quel qu'il soit est tout à fait libre
de refuser le service récursif à une partie ou la totalité de ses clients.
L'utilisateur devra contacter son administrateur local pour savoir quels sont
les serveurs qu'il pourra utiliser.
Ce type de service comporte un
certain nombre de limites et de défauts. Comme les requêtes peuvent être
traitées dans un temps totalement arbitraire, le noyau aura souvent des
difficultés à optimiser les temporisations de retransmission de paquets UDP
signalant des paquets perdus ou des serveurs défaillants ; le serveur de noms
pourra facilement être débordé par un noyau un peu trop zélé, surtout s'il
interprète toutes les retransmissions comme des nouvelles requêtes.
L'utilisation de TCP pourrait être une réponse à ce problème, mais
l'implantation de TCP reviendrait à consommer pratiquement autant de ressources
sur l'hôte qu'un résolveur complet.
5.3.2.
RessourcesEn plus de
ses ressources propres, le résolveur peut aussi disposer d'accès partagés à des
données de zones maintenues par un serveur de noms local. Ceci donne au
résolveur l'avantage d'un accès plus rapide aux données, mais impose que le
résolveur surveille qu'aucune donnée mise en cache ne vienne masquer une donnée
pour cette zone. Dans cette partie, nous appellerons "information locale" la
réunion des informations contenues dans le cache et celles de la zone partagée,
en sous-entendant que les données "autorisées" seront toujours utilisées de
préférence à toute donnée du cache lorsque les deux sont présentes simultanément
en local.
Les algorithmes de résolution qui
suivent supposent que toutes les fonctions ont été exprimées sous forme d'une
fonction de recherche généralisée, et utilisent les structures de données
suivantes pour représenter la progression de la requête au niveau du résolveur
:
SNAME |
le nom de
domaine sur lequel porte la recherche. |
STYPE |
le QTYPE
de la requête. |
SCLASS |
la QCLASS
de la requête. |
SLIST |
une
structure qui décrit les serveurs de noms et la zone concernée par la
requête en cours de traitement par le résolveur. Cette structure garde la
trace des serveurs de noms que le résolveur estime actuellement être les
plus susceptibles de détenir l'information désirée ; cette trace est
remise à jour si l'information arrivant au résolveur est de nature à
remettre en cause cette estimation. Cette structure contiendra un champ
équivalent à un nom de zone, des champs pour représenter les serveurs de
noms identifiés pour cette zone, les adresses de ces derniers, et des
informations de type "historique" permettant d'estimer quel est le serveur
suivant le mieux placé pour obtenir les informations recherchées.
L'équivalent du nom de zone est un décompte du nombre d'identifiants
(considérés à partir de la racine) que SNAME a en commun avec la zone
objet de la recherche courante ; ceci donne une mesure de la "distance"
qui sépare encore le résolveur de SNAME. |
SBELT |
une
structure "ceinture de sécurité" d'une forme identique à SLIST,
initialisée à partir d'un fichier de configuration, et qui liste les
serveurs qui devraient être utilisés lorsque le résolveur ne dispose plus
ou pas assez d'informations locales pour guider la sélection de serveurs
de noms. Le décompte de correspondance sera fixé à -1 pour indiquer
qu'aucun des identifiants ne correspond. |
CACHE |
une
structure qui enregistre les résultats de précédentes réponses. Les
résolveurs sont responsables de la purge des RR dont la durée de vie a
expiré (dans le cache). La plupart des implémentations convertissent
l'intervalle spécifié dans les RR reçus en une sorte de date "absolue" de
péremption lorsque le RR est enregistré dans le cache. Plut"t que
décrémenter les durées de vie individuellement, le résolveur n'a plus qu'à
ignorer ou supprimer les RR "périmés" lorsqu'il les rencontre au cours
d'une recherche, ou encore supprimer les RR dont la date de péremption est
antérieure à la date courante lors d'opérations temporisées de
récupération de mémoire (par destruction des vieux
RR). |
5.3.3.
AlgorithmeL'algorithme de haut niveau contient quatre étapes :
- Vérifier si la réponse est
disponible en local, si c'est le cas on la renvoie au client.
- Déterminer les "meilleurs"
serveurs à contacter.
- Leur envoyer des requêtes jusqu'à
ce qu'un d'eux réponde.
- Analyser la réponse, soit
:
- Si la réponse répond à la
question posée, ou stipule une erreur de nom, retouner l'information au
client et mettre cette information en cache.
- Si la réponse indique une
redirection de "plus grande proximité", mettre en cache les références de ce
nouveau serveur, et retourner à l'étape 2.
- Si la réponse est un CNAME tout
en étant pas la réponse attendue, cacher le CNAME, remplacer le SNAME par le
nom canonique lu dans le RR CNAME et retourner à l'étape 1.
- Si la réponse rend compte d'une
défaillance du serveur ou autre cas bizarre, supprimer le serveur de la
SLIST et retourner à l'étape 3.
L'étape 1 cherche la donnée désirée dans le
cache. Si la donnée y est trouvée, on suppose qu'elle est suffisamment fiable
pour une exploitation "normale". Certains résolveurs disposent d'une option
configurable par l'utilisateur qui force à ignorer les données du cache et à
consulter directement un serveur "autorisé". Ce fonctionnement n'est pas
recommandé par défaut. Si le résolveur dispose d'un accès direct à la définition
de zone d'un serveur de nom local, il cherchera à établir si les données
demandées n'y sont pas présente sous une forme "autorisée". Si oui, on utilisera
de préférence les données "autorisées", plutôt que les données trouvées dans le
cache.
L'étape 2 recherche auprès de quel
serveur de nom l'on va requérir la donnée recherchée. La stratégie usuelle est
de chercher d'abord des RR de serveurs de noms disponibles en local, en partant
du domaine SNAME, puis le père de SNAME, son grand-père, et ainsi de suite vers
la racine. Ainsi, si SNAME était Mockapetris.ISI.EDU, cette étape rechercherait
des RR NS pour le domaine Mockapetris.ISI.EDU, puis ISI.EDU, puis EDU, et enfin
. (la racine). Ces RR NS donnent la liste des noms des hôtes de la zone
co‹ncidant avec ou englobant SNAME. On copie ces noms dans SLIST, puis on
détermine leur adresse à l'aide des données locales. Il peut se produire que
certaines adresses ne puissent pas être identifiées en local. Le résolveur peut
alors adopter plusieurs attitudes ; la plus sage est de "forker" le résolveur
pour créer des processus "fils" dont la tƒche sera de récupérer ces adresses,
tandis que le père continuera la recherche sur les serveurs dont l'adresse est
d'ores et déjà disponible. De façon évidente, les choix et options de design
sont assez complexes et largement fonction des possibilités de l'hôte local. Les
concepteurs de résolveurs devront considéré les priorités dans l'ordre suivant
:
- Brider la quantité de traitement
(nombre de paquets émis, nombre de processus parallèles démarrés) de sorte
qu'une requête ne puisse partir en boucle infinie ou initier une réaction en
chaîne de création de processus et/ou d'émission de requêtes MEME DANS LE CAS
DE DONNEES MAL CONFIGUREES.
- Donner une réponse à chaque fois
que possible.
- Eviter la consommation superflue
de ressources de transmission.
- Donner les réponses aussi vite
que possible.
Si la recherche de RR NS échoue, alors le résolveur initialisera la
SLIST à partir de la structure SBELT. L'idée de base est que, lorsque le
résolveur ne sait pas par où commencer pour rechercher une information, il
utilisera une liste prédéfinie dans un fichier de configuration de serveurs
supposés pouvoir être utiles. Bien qu'il puisse exister certaines situations
particulières, on intégrera usuellement dans cette liste deux serveurs sur la
racine et deux serveurs dans la zone où réside l'hôte. Le chiffre de deux
(minimum) est donné pour assurer la redondance des données. Les serveurs de la
racine pourront permettre un accès éventuel à d'autres parties (en fait, toutes)
de l'espace de domaines. Les deux serveurs locaux permettront au résolveur de
pouvoir être capable de continuer la résolution de noms locaux, même si le
réseau local se retrouve isolé d'Internet suite à la défaillance d'une liaison
ou d'un routeur.
En plus de fournir les adresses et
noms des serveurs, la structure de données SLIST peut être triée de façon à
donner une indication sur le "meilleur" serveur à utiliser, et s'assurer que
toutes les adresses et noms de serveurs seront contactés chacun son tour. Le tri
peut être une simple fonction de préséance des adresses locale sur les autres,
ou peut être une fonction complexe de statistiques sur les événements passés,
telle qu'une analyse des temps de réponse moyens et des taux de
réussite.
L'étape 3 émet des requêtes jusqu'à
ce qu'une réponse soit donnée. La stratégie consiste à utiliser toutes les
adresses à tour de r"le, avec une temporisation donnée entre chaque émission. En
pratique, il est important d'utiliser toutes les adresses d'un hôte "multiport",
sachant qu'une politique de retransmission trop soutenue ralentit la réponse
lorsque de multiples résolveurs sont impliqués dans une recherche sur le même
serveur de nom (et même parfois pour un seul résolveur). La structure SLIST
contient typiquement des données pour contr"ler les temporisations et garder
trace des précédentes transmissions.
L'étape 4 s'occupe de l'analyse des
réponses. Le résolveur devra faire preuve d'une grande parano‹a dans l'analyse
de ces réponses. Il devra en outre que la réponse correspond bien à la requête
émise grƒce à la lecture du champ ID dans la réponse. La réponse idéale
proviendrait d'un serveur "autorisé" donnant les informations (en général
l'adresse) attendues ou encore une erreur de nom. L'information est alors
transmise au client et recopiée dans le cache en prévision d'une requête
identique future si sa durée de vie (TTL) est supérieure à 0.
Si la réponse indique une
redirection à effectuer, le résolveur vérifiera d'abord si le serveur mentionné
est plus "proche" de la réponse que les serveurs dont on dispose dans SLIST.
Ceci sera fait en comparant le décompte d'identifiants correspondants dans SLIST
avec celui obtenu par calcul sur le SNAME dans le RR NS du message de
redirection. Si tel n'est pas le cas, la réponse est considérée comme dénuée
d'intérêt et sera ignorée. Si la redirection est utilisable, le RR NS de
redirection et toute RR d'adresse obtenue pour les serveurs délégués devront
être copiés dans le cache. Les serveurs de noms sont ajoutés à la SLIST, et la
recherche recommence.
Si la réponse contient un CNAME, la
recherche doit être réitérée avec le nom canonique CNAME sauf si la réponse
donnée contient déjà l'information pour ce même nom canonique, où si la requête
originale portait effectivement sur un CNAME lui-même.
Plus de détails et des astuces
d'implémentation peuvent être trouvés dans la [RFC-1035].
|