7. Resolver Implementation (Implémentation du résolveur)
Les niveaux supérieurs de l'algorithme de résolveur recommandé sont discutés dans RFC-1034. Cette section traite des détails d'implémentation en supposant la structure de base de données suggérée dans la section d'implémentation du serveur de noms de ce mémo.
7.1. Transforming a User Request into a Query (Transformer une requête utilisateur en requête)
La première étape qu'un résolveur entreprend est de transformer la requête du client, énoncée dans un format adapté au système d'exploitation local, en une spécification de recherche pour les RR à un nom spécifique qui correspondent à un QTYPE et QCLASS spécifiques.
Directives de spécification de requête
Préférence de type et classe unique: Dans la mesure du possible, le QTYPE et le QCLASS devraient (SHOULD) correspondre à un type unique et une classe unique, car cela rend l'utilisation des données en cache beaucoup plus simple.
Raison: La présence de données d'un type dans un cache ne confirme pas l'existence ou la non-existence de données d'autres types. Par conséquent, la seule façon d'être sûr est de consulter une source autoritaire.
Limitation QCLASS=*: Si QCLASS=* est utilisé, alors les réponses autoritaires ne seront pas disponibles.
Informations d'état de la requête
Étant donné qu'un résolveur doit être capable de multiplexer plusieurs requêtes s'il doit remplir sa fonction efficacement, chaque requête en attente est généralement représentée dans un bloc d'informations d'état.
Ce bloc d'état contiendra généralement:
1. Horodatage (Timestamp)
Objectif: Indiquant l'heure à laquelle la requête a commencé.
Utilisation:
- L'horodatage est utilisé pour décider si les RR dans la base de données peuvent être utilisés ou sont obsolètes
- Cet horodatage utilise le format de temps absolu précédemment discuté pour le stockage RR dans les zones et les caches
Interprétation TTL:
- Lorsque le TTL d'un RR indique un temps relatif, le RR doit être opportun, car il fait partie d'une zone
- Lorsque le RR a un temps absolu, il fait partie d'un cache, et le TTL du RR est comparé à l'horodatage pour le début de la requête
Avantage des horodatages: L'utilisation de l'horodatage est supérieure à l'utilisation d'un temps actuel, car elle permet aux RR avec des TTL de zéro d'être entrés dans le cache de la manière habituelle, mais toujours utilisés par la requête actuelle, même après des intervalles de plusieurs secondes dus à la charge du système, aux délais de retransmission des requêtes, etc.
2. Paramètres de limitation de travail (Work Limitation Parameters)
Objectif: Une sorte de paramètres pour limiter la quantité de travail qui sera effectuée pour cette requête.
Justification: La quantité de travail qu'un résolveur effectuera en réponse à une requête client doit être limitée pour se protéger contre:
- Les erreurs dans la base de données, telles que les références CNAME circulaires
- Les problèmes opérationnels, tels que le partitionnement réseau qui empêche le résolveur d'accéder aux serveurs de noms dont il a besoin
Implémentation:
- Bien que les limites locales sur le nombre de fois qu'un résolveur retransmettra une requête particulière à une adresse de serveur de noms particulière soient essentielles
- Le résolveur devrait (SHOULD) avoir un compteur global par requête pour limiter le travail sur une seule requête
- Le compteur devrait (SHOULD) être défini sur une valeur initiale et décrémenté chaque fois que le résolveur effectue une action (délai de retransmission, retransmission, etc.)
- Si le compteur passe à zéro, la requête est terminée avec une erreur temporaire
Requêtes parallèles: Notez que si la structure du résolveur permet à une requête d'en démarrer d'autres en parallèle, comme lorsque le besoin d'accéder à un serveur de noms pour une requête provoque une résolution parallèle pour les adresses du serveur de noms, la requête générée devrait (SHOULD) être démarrée avec un compteur inférieur. Cela empêche les références circulaires dans la base de données de déclencher une réaction en chaîne de l'activité du résolveur.
3. Structure de données SLIST
La structure de données SLIST discutée dans RFC-1034.
Objectif: Cette structure garde une trace de l'état d'une requête si elle doit attendre des réponses de serveurs de noms étrangers.
7.2. Sending the Queries (Envoi des requêtes)
Comme décrit dans RFC-1034, la tâche de base du résolveur est de formuler une requête qui répondra à la demande du client et de diriger cette requête vers les serveurs de noms qui peuvent fournir les informations.
Défis de formulation de requête
Le résolveur n'aura généralement que des indices très forts sur les serveurs à interroger, sous la forme de RR NS, et peut devoir:
- Réviser la requête, en réponse aux CNAME
- Réviser l'ensemble des serveurs de noms que le résolveur interroge, en réponse aux réponses de délégation qui pointent le résolveur vers des serveurs de noms plus proches des informations désirées
En plus des informations demandées par le client, le résolveur peut devoir faire appel à ses propres services pour déterminer l'adresse des serveurs de noms qu'il souhaite contacter.
Modèle de résolveur
Le modèle utilisé dans ce mémo suppose que:
- Le résolveur multiplex l'attention entre plusieurs requêtes, certaines du client et certaines générées en interne
- Chaque requête est représentée par certaines informations d'état
- Le comportement souhaité est que le résolveur transmette des requêtes aux serveurs de noms d'une manière qui:
- Maximise la probabilité que la requête soit répondue
- Minimise le temps que prend la requête
- Évite les transmissions excessives
Algorithme clé
L'algorithme clé utilise les informations d'état de la requête pour:
- Sélectionner la prochaine adresse de serveur de noms à interroger
- Calculer un délai qui provoquera la prochaine action si une réponse n'arrive pas
La prochaine action sera généralement une transmission à un autre serveur, mais peut être une erreur temporaire au client.
Initialisation SLIST
Point de départ: Le résolveur commence toujours par une liste de noms de serveurs à interroger (SLIST).
Contenu initial:
- Cette liste sera tous les RR NS qui correspondent à la zone ancêtre la plus proche que le résolveur connaît
- Pour éviter les problèmes de démarrage, le résolveur devrait (SHOULD) avoir un ensemble de serveurs par défaut qu'il interrogera s'il n'a pas de RR NS actuels qui sont appropriés
Ajout d'adresse: Le résolveur ajoute ensuite à SLIST toutes les adresses connues pour les serveurs de noms, et peut démarrer des requêtes parallèles pour acquérir les adresses des serveurs lorsque le résolveur a le nom, mais pas les adresses, pour les serveurs de noms.
Informations historiques
Pour compléter l'initialisation de SLIST, le résolveur attache toutes les informations historiques qu'il a à chaque adresse dans SLIST.
Données historiques typiques:
- Une sorte de moyennes pondérées pour le temps de réponse de l'adresse
- La moyenne au bâton de l'adresse (c'est-à-dire, à quelle fréquence l'adresse a répondu à la requête)
Notes importantes:
- Ces informations devraient (SHOULD) être conservées sur une base par adresse, plutôt que sur une base par serveur de noms, car le temps de réponse et la moyenne au bâton d'un serveur particulier peuvent varier considérablement d'une adresse à l'autre
- Ces informations sont en fait spécifiques à une paire adresse de résolveur / adresse de serveur, donc un résolveur avec plusieurs adresses peut souhaiter conserver des historiques séparés pour chacune de ses adresses
- Pour les adresses qui n'ont pas un tel historique: un temps d'aller-retour attendu de 5-10 secondes devrait (SHOULD) être le pire cas, avec des estimations plus faibles pour le même réseau local, etc.
Gestion de la délégation: Notez que chaque fois qu'une délégation est suivie, l'algorithme du résolveur réinitialise SLIST.
Sélection de serveur et délai
Classement: Les informations établissent un classement partiel des adresses de serveur de noms disponibles.
Stratégie de sélection: Chaque fois qu'une adresse est choisie, l'état devrait (SHOULD) être modifié pour empêcher sa sélection à nouveau jusqu'à ce que toutes les autres adresses aient été essayées.
Calcul du délai: Le délai pour chaque transmission devrait (SHOULD) être 50-100% plus grand que la valeur prédite moyenne pour permettre la variance dans la réponse.
Cas spéciaux
Problème d'amorçage:
- Le résolveur peut rencontrer une situation où aucune adresse n'est disponible pour aucun des serveurs de noms nommés dans SLIST, et où les serveurs dans la liste sont précisément ceux qui seraient normalement utilisés pour rechercher leurs propres adresses
- Cette situation se produit généralement lorsque les RR d'adresse de colle ont un TTL plus petit que les RR NS marquant la délégation, ou lorsque le résolveur met en cache le résultat d'une recherche NS
- Le résolveur devrait (SHOULD) détecter cette condition et redémarrer la recherche à la zone ancêtre suivante, ou alternativement à la racine
Erreurs de serveur:
- Si un résolveur obtient une erreur de serveur ou une autre réponse bizarre d'un serveur de noms, il devrait (SHOULD) le retirer de SLIST
- Le résolveur peut souhaiter planifier une transmission immédiate à la prochaine adresse de serveur candidat
7.3. Processing Responses (Traitement des réponses)
La première étape du traitement des datagrammes de réponse arrivants est d'analyser la réponse.
Procédure d'analyse de réponse
Cette procédure devrait (SHOULD) inclure:
1. Vérification de l'en-tête:
- Vérifier l'en-tête pour le caractère raisonnable
- Rejeter les datagrammes qui sont des requêtes lorsque des réponses sont attendues
2. Analyse de section:
- Analyser les sections du message
- S'assurer que tous les RR sont correctement formatés
3. Vérification TTL (Optionnel):
- En tant qu'étape optionnelle, vérifier les TTL des données arrivantes à la recherche de RR avec des TTL excessivement longs
- Si un RR a un TTL excessivement long, disons supérieur à 1 semaine:
- Soit rejeter la réponse entière
- Soit limiter tous les TTL dans la réponse à 1 semaine
Correspondance de réponse
L'étape suivante consiste à faire correspondre la réponse à une requête de résolveur actuelle.
Stratégie recommandée:
- Effectuer une correspondance préliminaire en utilisant le champ ID dans l'en-tête de domaine
- Ensuite, vérifier que la section question correspond aux informations actuellement désirées
Exigence d'implémentation: Cela nécessite que l'algorithme de transmission consacre plusieurs bits du champ ID de domaine à un identifiant de requête quelconque.
Considérations spéciales
Variation d'adresse source:
- Certains serveurs de noms envoient leurs réponses à partir d'adresses différentes de celle utilisée pour recevoir la requête
- C'est-à-dire qu'un résolveur ne peut pas (CANNOT) compter sur le fait qu'une réponse viendra de la même adresse à laquelle il a envoyé la requête correspondante
- Ce bogue de serveur de noms est généralement rencontré dans les systèmes UNIX
Gestion de retransmission:
- Si le résolveur retransmet une requête particulière à un serveur de noms, il devrait (SHOULD) être capable d'utiliser une réponse de n'importe laquelle des transmissions
- Cependant, s'il utilise la réponse pour échantillonner le temps d'aller-retour pour accéder au serveur de noms:
- Il doit être capable de déterminer quelle transmission correspond à la réponse (et garder les temps de transmission pour chaque message sortant)
- Ou calculer uniquement les temps d'aller-retour basés sur les transmissions initiales
Données de zone manquantes:
- Un serveur de noms n'aura occasionnellement pas une copie actuelle d'une zone qu'il devrait avoir selon certains RR NS
- Le résolveur devrait (SHOULD) simplement retirer le serveur de noms de la SLIST actuelle, et continuer
7.4. Using the Cache (Utilisation du cache)
En général, nous nous attendons à ce qu'un résolveur mette en cache toutes les données qu'il reçoit dans les réponses car elles peuvent être utiles pour répondre aux futures requêtes des clients.
Cependant, il existe plusieurs types de données qui ne devraient pas (SHOULD NOT) être mis en cache:
Données qui ne devraient pas être mises en cache
1. Ensembles incomplets:
- Lorsque plusieurs RR du même type sont disponibles pour un nom de propriétaire particulier, le résolveur devrait (SHOULD) les mettre tous en cache ou aucun d'entre eux
- Lorsqu'une réponse est tronquée, et qu'un résolveur ne sait pas s'il a un ensemble complet, il ne devrait pas (SHOULD NOT) mettre en cache un ensemble de RR possiblement partiel
2. Données non autoritaires sur autoritaires:
- Les données en cache ne devraient jamais (MUST NOT) être utilisées de préférence aux données autoritaires
- Si la mise en cache entraînerait cela, les données ne devraient pas (SHOULD NOT) être mises en cache
3. Résultats de requête inverse:
- Les résultats d'une requête inverse ne devraient pas (SHOULD NOT) être mis en cache
4. Résultats de requête de caractère générique:
- Les résultats des requêtes standard où le QNAME contient des étiquettes
*si les données pourraient être utilisées pour construire des caractères génériques - Raison: Le cache ne contient pas nécessairement les RR existants ou les informations de limite de zone qui sont nécessaires pour restreindre l'application des RR de caractères génériques
5. Données de fiabilité douteuse:
- Données RR dans les réponses de fiabilité douteuse
- Lorsqu'un résolveur reçoit des réponses non sollicitées ou des données RR autres que celles demandées, il devrait (SHOULD) les rejeter sans les mettre en cache
- Implication de base: Toutes les vérifications de cohérence sur un paquet devraient (SHOULD) être effectuées avant que l'un d'entre eux ne soit mis en cache
Stratégie de mise à jour du cache
Lorsqu'un résolveur a un ensemble de RR pour un nom dans une réponse, et souhaite mettre les RR en cache:
- Il devrait (SHOULD) vérifier son cache pour les RR déjà existants
- Selon les circonstances, soit les données dans la réponse, soit le cache est préféré
- Les deux ne devraient jamais être combinés (MUST NOT)
- Si les données dans la réponse proviennent de données autoritaires dans la section réponse, elles sont toujours préférées
Best Practices Summary (Résumé des meilleures pratiques)
Pour une implémentation efficace du résolveur
-
Utiliser des requêtes de type et classe uniques lorsque c'est possible pour une meilleure utilisation du cache
-
Maintenir l'état par requête incluant les horodatages et les compteurs de travail
-
Conserver l'historique par adresse pour la sélection intelligente de serveur
-
Implémenter des stratégies de délai appropriées (50-100% au-dessus du temps prédit)
-
Gérer les cas spéciaux comme les problèmes d'amorçage et les erreurs de serveur
-
Analyser soigneusement les réponses avec des vérifications d'en-tête et de validation de format
-
Mettre en cache sélectivement - toutes les données ne devraient pas être mises en cache
-
Préférer les données autoritaires aux données en cache lorsque les deux sont disponibles
Connexe: Voir 6. Name Server Implementation (Implémentation du serveur de noms) pour les détails côté serveur