5. RÉSOLVEURS (RESOLVERS)
5.1. Introduction
Les résolveurs sont des programmes qui font l'interface entre les programmes utilisateur et les serveurs de noms de domaine. Dans le cas le plus simple, un résolveur reçoit une demande d'un programme utilisateur (par exemple, programmes de messagerie, TELNET, FTP) sous la forme d'un appel de sous-routine, d'un appel système, etc., et renvoie l'information désirée dans un format compatible avec les formats de données de l'hôte local.
Le résolveur est situé sur la même machine que le programme qui demande les services du résolveur, mais il peut avoir besoin de consulter des serveurs de noms sur d'autres hôtes. Parce qu'un résolveur peut avoir besoin de consulter plusieurs serveurs de noms, ou peut avoir l'information demandée dans un cache local, la durée qu'un résolveur prendra pour se terminer peut varier considérablement, de millisecondes à plusieurs secondes.
Un objectif très important du résolveur est d'éliminer le délai réseau et la charge du serveur de noms de la plupart des demandes en y répondant à partir de son cache de résultats antérieurs. Il s'ensuit que les caches qui sont partagés par plusieurs processus, utilisateurs, machines, etc., sont plus efficaces que les caches non partagés.
5.2. Interface client-résolveur (Client-resolver interface)
5.2.1. Fonctions typiques (Typical functions)
L'interface client au résolveur est influencée par les conventions de l'hôte local, mais l'interface résolveur-client typique a trois fonctions :
1. Traduction de nom d'hôte en adresse d'hôte (Host name to host address translation)
Cette fonction est souvent définie pour imiter une fonction précédente basée sur HOSTS.TXT. Étant donné une chaîne de caractères, l'appelant veut une ou plusieurs adresses IP de 32 bits. Sous le DNS, elle se traduit en une demande de RRs de type A. Puisque le DNS ne préserve pas l'ordre des RRs, cette fonction peut choisir de trier les adresses renvoyées ou de sélectionner la "meilleure" adresse si le service ne renvoie qu'un seul choix au client. Notez qu'un retour d'adresses multiples est recommandé, mais une seule adresse peut être le seul moyen d'émuler les services HOSTS.TXT précédents.
2. Traduction d'adresse d'hôte en nom d'hôte (Host address to host name translation)
Cette fonction suivra souvent la forme de fonctions précédentes. Étant donné une adresse IP de 32 bits, l'appelant veut une chaîne de caractères. Les octets de l'adresse IP sont inversés, utilisés comme composants de nom, et suffixés avec "IN-ADDR.ARPA". Une requête de type PTR est utilisée pour obtenir le RR avec le nom principal de l'hôte. Par exemple, une demande pour le nom d'hôte correspondant à l'adresse IP 1.2.3.4 cherche des RRs PTR pour le nom de domaine "4.3.2.1.IN-ADDR.ARPA".
3. Fonction de recherche générale (General lookup function)
Cette fonction récupère des informations arbitraires du DNS, et n'a pas de contrepartie dans les systèmes précédents. L'appelant fournit un QNAME, QTYPE et QCLASS, et veut tous les RRs correspondants. Cette fonction utilisera souvent le format DNS pour toutes les données RR au lieu de celui de l'hôte local, et renvoie tout le contenu RR (par exemple, TTL) au lieu d'une forme traitée avec des conventions de citation locales.
Types de résultats (Result types)
Lorsque le résolveur exécute la fonction indiquée, il a généralement l'un des résultats suivants à renvoyer au client :
-
Un ou plusieurs RRs donnant les données demandées (One or more RRs giving the requested data) : Dans ce cas, le résolveur renvoie la réponse dans le format approprié.
-
Une erreur de nom (NE) (A name error) : Cela se produit lorsque le nom référencé n'existe pas. Par exemple, un utilisateur peut avoir mal saisi un nom d'hôte.
-
Une erreur de données non trouvées (A data not found error) : Cela se produit lorsque le nom référencé existe, mais que les données du type approprié n'existent pas. Par exemple, une fonction d'adresse d'hôte appliquée à un nom de boîte aux lettres renverrait cette erreur puisque le nom existe, mais aucun RR d'adresse n'est présent.
Il est important de noter que les fonctions de traduction entre les noms d'hôtes et les adresses peuvent combiner les conditions d'erreur "erreur de nom" et "données non trouvées" en un seul type de retour d'erreur, mais la fonction générale ne devrait pas. Une raison à cela est que les applications peuvent demander d'abord un type d'information sur un nom suivi d'une deuxième demande au même nom pour un autre type d'information ; si les deux erreurs sont combinées, alors des requêtes inutiles peuvent ralentir l'application.
5.2.2. Alias (Aliases)
En tentant de résoudre une demande particulière, le résolveur peut trouver que le nom en question est un alias. Par exemple, le résolveur pourrait trouver que le nom donné pour la traduction de nom d'hôte en adresse est un alias lorsqu'il trouve le RR CNAME. Si possible, la condition d'alias devrait être signalée du résolveur au client.
Dans la plupart des cas, un résolveur redémarre simplement la requête au nouveau nom lorsqu'il rencontre un CNAME. Cependant, lors de l'exécution de la fonction générale, le résolveur ne devrait pas poursuivre les alias lorsque le RR CNAME correspond au type de requête. Cela permet des requêtes qui demandent si un alias est présent. Par exemple, si le type de requête est CNAME, l'utilisateur est intéressé par le RR CNAME lui-même, et non par les RRs au nom vers lequel il pointe.
Plusieurs conditions spéciales peuvent se produire avec les alias. Plusieurs niveaux d'alias devraient être évités en raison de leur manque d'efficacité, mais ne devraient pas être signalés comme une erreur. Les boucles d'alias et les alias qui pointent vers des noms non existants devraient être capturés et une condition d'erreur renvoyée au client.
5.2.3. Échecs temporaires (Temporary failures)
Dans un monde moins que parfait, tous les résolveurs seront occasionnellement incapables de résoudre une demande particulière. Cette condition peut être causée par un résolveur qui devient séparé du reste du réseau en raison d'une défaillance de lien ou d'un problème de passerelle, ou moins souvent par une défaillance coïncidente ou l'indisponibilité de tous les serveurs pour un domaine particulier.
Il est essentiel que ce type de condition ne soit pas signalé comme une erreur de nom ou de données non présentes aux applications. Ce type de comportement est ennuyeux pour les humains, et peut causer des ravages lorsque les systèmes de messagerie utilisent le DNS.
Bien que dans certains cas il soit possible de traiter un tel problème temporaire en bloquant la demande indéfiniment, ce n'est généralement pas un bon choix, en particulier lorsque le client est un processus serveur qui pourrait passer à d'autres tâches. La solution recommandée est de toujours avoir l'échec temporaire comme l'un des résultats possibles d'une fonction de résolveur, même si cela peut rendre l'émulation des fonctions HOSTS.TXT existantes plus difficile.
5.3. Structures internes du résolveur (Resolver internals)
Chaque implémentation de résolveur utilise des algorithmes légèrement différents, et passe généralement beaucoup plus de logique à traiter les erreurs de différentes sortes que les occurrences typiques. Cette section décrit une stratégie de base recommandée pour l'opération du résolveur, mais laisse les détails à [RFC-1035].
5.3.1. Résolveurs stub (Stub resolvers)
Une option pour implémenter un résolveur est de déplacer la fonction de résolution hors de la machine locale et dans un serveur de noms qui supporte les requêtes récursives. Cela peut fournir une méthode facile de fournir un service de domaine dans un PC qui manque de ressources pour exécuter la fonction de résolveur, ou peut centraliser le cache pour tout un réseau local ou une organisation.
Tout ce dont le stub restant a besoin est une liste d'adresses de serveurs de noms qui effectueront les demandes récursives. Ce type de résolveur a vraisemblablement besoin de l'information dans un fichier de configuration, car il manque probablement de la sophistication pour la localiser dans la base de données de domaine. L'utilisateur doit également vérifier que les serveurs listés effectueront le service récursif ; un serveur de noms est libre de refuser d'effectuer des services récursifs pour n'importe quel ou tous les clients. L'utilisateur devrait consulter l'administrateur système local pour trouver des serveurs de noms disposés à effectuer le service.
Ce type de service souffre de certains inconvénients. Puisque les demandes récursives peuvent prendre une durée arbitraire pour s'exécuter, le stub peut avoir des difficultés à optimiser les intervalles de retransmission pour traiter à la fois les paquets UDP perdus et les serveurs morts ; le serveur de noms peut être facilement surchargé par un stub trop zélé s'il interprète les retransmissions comme de nouvelles demandes. L'utilisation de TCP peut être une réponse, mais TCP peut bien placer des charges sur les capacités de l'hôte qui sont similaires à celles d'un vrai résolveur.
5.3.2. Ressources (Resources)
En plus de ses propres ressources, le résolveur peut également avoir un accès partagé aux zones maintenues par un serveur de noms local. Cela donne au résolveur l'avantage d'un accès plus rapide, mais le résolveur doit faire attention à ne jamais laisser les informations mises en cache remplacer les données de zone. Dans cette discussion, le terme "information locale" signifie l'union du cache et de telles zones partagées, avec la compréhension que les données autoritatives sont toujours utilisées de préférence aux données mises en cache lorsque les deux sont présentes.
L'algorithme de résolveur suivant suppose que toutes les fonctions ont été converties en une fonction de recherche générale, et utilise les structures de données suivantes pour représenter l'état d'une demande en cours dans le résolveur :
SNAME
Le nom de domaine que nous recherchons.
STYPE
Le QTYPE de la demande de recherche.
SCLASS
Le QCLASS de la demande de recherche.
SLIST
Une structure qui décrit les serveurs de noms et la zone que le résolveur essaie actuellement d'interroger. Cette structure garde une trace de la meilleure estimation actuelle du résolveur sur quels serveurs de noms détiennent l'information désirée ; elle est mise à jour lorsque l'information arrivante change l'estimation. Cette structure inclut l'équivalent d'un nom de zone, les serveurs de noms connus pour la zone, les adresses connues pour les serveurs de noms, et les informations d'historique qui peuvent être utilisées pour suggérer quel serveur est susceptible d'être le meilleur à essayer ensuite. L'équivalent du nom de zone est un comptage de correspondance du nombre d'étiquettes de la racine vers le bas que SNAME a en commun avec la zone interrogée ; ceci est utilisé comme mesure de la "proximité" du résolveur à SNAME.
SBELT
Une structure de "ceinture de sécurité" de la même forme que SLIST, qui est initialisée à partir d'un fichier de configuration, et liste les serveurs qui devraient être utilisés lorsque le résolveur n'a pas d'information locale pour guider la sélection du serveur de noms. Le comptage de correspondance sera -1 pour indiquer qu'aucune étiquette n'est connue pour correspondre.
CACHE
Une structure qui stocke les résultats des réponses précédentes. Puisque les résolveurs sont responsables de jeter les anciens RRs dont le TTL a expiré, la plupart des implémentations convertissent l'intervalle spécifié dans les RRs arrivants en une sorte de temps absolu lorsque le RR est stocké dans le cache. Au lieu de compter les TTLs individuellement, le résolveur ignore ou jette simplement les anciens RRs lorsqu'il les rencontre au cours d'une recherche, ou les jette lors de balayages périodiques pour récupérer la mémoire consommée par les anciens RRs.
5.3.3. Algorithme (Algorithm)
L'algorithme de niveau supérieur a quatre étapes :
-
Voir si la réponse est dans l'information locale, et si oui la renvoyer au client.
-
Trouver les meilleurs serveurs à interroger.
-
Leur envoyer des requêtes jusqu'à ce que l'un renvoie une réponse.
-
Analyser la réponse, soit :
a. Si la réponse répond à la question ou contient une erreur de nom, mettre les données en cache ainsi que les renvoyer au client.
b. Si la réponse contient une meilleure délégation vers d'autres serveurs, mettre l'information de délégation en cache, et aller à l'étape 2.
c. Si la réponse montre un CNAME et que ce n'est pas la réponse elle-même, mettre le CNAME en cache, changer le SNAME en nom canonique dans le RR CNAME et aller à l'étape 1.
d. Si la réponse montre une défaillance de serveur ou d'autres contenus bizarres, supprimer le serveur de la SLIST et revenir à l'étape 3.
Étape 1 : Rechercher l'information locale (Step 1: Search local information)
L'étape 1 recherche le cache pour les données désirées. Si les données sont dans le cache, elles sont supposées être assez bonnes pour une utilisation normale. Certains résolveurs ont une option à l'interface utilisateur qui forcera le résolveur à ignorer les données mises en cache et à consulter un serveur autoritatif. Cela n'est pas recommandé par défaut. Si le résolveur a un accès direct aux zones d'un serveur de noms, il devrait vérifier si les données désirées sont présentes sous forme autoritative, et si oui, utiliser les données autoritatives de préférence aux données mises en cache.
Étape 2 : Trouver les meilleurs serveurs (Step 2: Find best servers)
L'étape 2 cherche un serveur de noms à qui demander les données requises. La stratégie générale est de chercher des RRs de serveur de noms disponibles localement, en commençant à SNAME, puis le nom de domaine parent de SNAME, le grand-parent, et ainsi de suite vers la racine. Ainsi si SNAME était Mockapetris.ISI.EDU, cette étape chercherait des RRs NS pour Mockapetris.ISI.EDU, puis ISI.EDU, puis EDU, puis . (la racine). Lorsqu'une liste de serveurs de noms est trouvée, le résolveur devrait les trier selon la préférence et les performances attendues. Le résolveur devrait alors essayer de contacter les serveurs dans cet ordre, en commençant par le plus préféré.
Étape 3 : Envoyer des requêtes (Step 3: Send queries)
L'étape 3 envoie des requêtes jusqu'à ce qu'une réponse soit reçue. L'algorithme de base est de faire le tour de toutes les adresses pour tous les serveurs avec un délai d'attente entre chaque transmission. Le résolveur devrait utiliser UDP pour les requêtes lorsque c'est possible, et n'utiliser TCP que lorsque la réponse est tronquée ou lorsque le résolveur est prêt à payer le coût de l'établissement et de la fermeture de connexion TCP.
Étape 4 : Analyser la réponse (Step 4: Analyze response)
L'étape 4 analyse les réponses. Le résolveur devrait être très paranoïaque dans son analyse des réponses. Il devrait également vérifier que la réponse correspond à la requête qu'il a envoyée en utilisant le champ ID dans la réponse.