5. RESOLVER (RESOLVERS)
5.1. Einführung (Introduction)
Resolver sind Programme, die Benutzerprogramme mit Domänennamensservern verbinden. Im einfachsten Fall empfängt ein Resolver eine Anfrage von einem Benutzerprogramm (z.B. E-Mail-Programme, TELNET, FTP) in Form eines Unterprogrammaufrufs, Systemaufrufs usw. und gibt die gewünschten Informationen in einem Format zurück, das mit den Datenformaten des lokalen Hosts kompatibel ist.
Der Resolver befindet sich auf derselben Maschine wie das Programm, das die Dienste des Resolvers anfordert, aber er muss möglicherweise Nameserver auf anderen Hosts konsultieren. Da ein Resolver möglicherweise mehrere Nameserver konsultieren oder die angeforderten Informationen in einem lokalen Cache haben muss, kann die Zeit, die ein Resolver für die Fertigstellung benötigt, von Millisekunden bis zu mehreren Sekunden erheblich variieren.
Ein sehr wichtiges Ziel des Resolvers ist es, Netzwerkverzögerungen und Nameserver-Last von den meisten Anfragen zu eliminieren, indem sie aus seinem Cache früherer Ergebnisse beantwortet werden. Daraus folgt, dass Caches, die von mehreren Prozessen, Benutzern, Maschinen usw. gemeinsam genutzt werden, effizienter sind als nicht gemeinsam genutzte Caches.
5.2. Client-Resolver-Schnittstelle (Client-resolver interface)
5.2.1. Typische Funktionen (Typical functions)
Die Client-Schnittstelle zum Resolver wird von den Konventionen des lokalen Hosts beeinflusst, aber die typische Resolver-Client-Schnittstelle hat drei Funktionen:
1. Übersetzung von Hostname in Hostadresse (Host name to host address translation)
Diese Funktion ist oft so definiert, dass sie eine frühere HOSTS.TXT-basierte Funktion nachahmt. Bei Angabe einer Zeichenkette möchte der Aufrufer eine oder mehrere 32-Bit-IP-Adressen. Unter dem DNS übersetzt sich dies in eine Anfrage nach Typ-A-RRs. Da das DNS die Reihenfolge der RRs nicht beibehält, kann diese Funktion wählen, die zurückgegebenen Adressen zu sortieren oder die "beste" Adresse auszuwählen, wenn der Dienst nur eine Wahl an den Client zurückgibt. Beachten Sie, dass eine Rückgabe mehrerer Adressen empfohlen wird, aber eine einzelne Adresse möglicherweise der einzige Weg ist, frühere HOSTS.TXT-Dienste zu emulieren.
2. Übersetzung von Hostadresse in Hostname (Host address to host name translation)
Diese Funktion folgt oft der Form früherer Funktionen. Bei Angabe einer 32-Bit-IP-Adresse möchte der Aufrufer eine Zeichenkette. Die Oktette der IP-Adresse werden umgekehrt, als Namenskomponenten verwendet und mit "IN-ADDR.ARPA" suffixiert. Eine Typ-PTR-Abfrage wird verwendet, um den RR mit dem primären Namen des Hosts zu erhalten. Beispielsweise sucht eine Anfrage nach dem Hostnamen, der der IP-Adresse 1.2.3.4 entspricht, nach PTR-RRs für den Domänennamen "4.3.2.1.IN-ADDR.ARPA".
3. Allgemeine Suchfunktion (General lookup function)
Diese Funktion ruft beliebige Informationen aus dem DNS ab und hat kein Gegenstück in früheren Systemen. Der Aufrufer liefert einen QNAME, QTYPE und QCLASS und möchte alle übereinstimmenden RRs. Diese Funktion wird oft das DNS-Format für alle RR-Daten anstelle des lokalen Hosts verwenden und gibt alle RR-Inhalte (z.B. TTL) anstelle einer verarbeiteten Form mit lokalen Zitierkonventionen zurück.
Ergebnistypen (Result types)
Wenn der Resolver die angegebene Funktion ausführt, hat er normalerweise eines der folgenden Ergebnisse an den Client zurückzugeben:
-
Ein oder mehrere RRs, die die angeforderten Daten liefern (One or more RRs giving the requested data): In diesem Fall gibt der Resolver die Antwort im entsprechenden Format zurück.
-
Ein Namensfehler (NE) (A name error): Dies geschieht, wenn der referenzierte Name nicht existiert. Beispielsweise kann ein Benutzer einen Hostnamen falsch eingegeben haben.
-
Ein Daten-nicht-gefunden-Fehler (A data not found error): Dies geschieht, wenn der referenzierte Name existiert, aber Daten des entsprechenden Typs nicht vorhanden sind. Beispielsweise würde eine Hostadressfunktion, die auf einen Mailboxnamen angewendet wird, diesen Fehler zurückgeben, da der Name existiert, aber kein Adress-RR vorhanden ist.
Es ist wichtig zu beachten, dass die Funktionen zur Übersetzung zwischen Hostnamen und Adressen die Fehlerbedingungen "Namensfehler" und "Daten nicht gefunden" in einen einzigen Fehlerrückgabetyp kombinieren können, aber die allgemeine Funktion sollte dies nicht tun. Ein Grund dafür ist, dass Anwendungen möglicherweise zuerst nach einem Informationstyp über einen Namen fragen, gefolgt von einer zweiten Anfrage an denselben Namen nach einem anderen Informationstyp; wenn die beiden Fehler kombiniert werden, können nutzlose Abfragen die Anwendung verlangsamen.
5.2.2. Aliase (Aliases)
Beim Versuch, eine bestimmte Anfrage aufzulösen, kann der Resolver feststellen, dass der betreffende Name ein Alias ist. Beispielsweise könnte der Resolver feststellen, dass der für die Hostname-zu-Adresse-Übersetzung angegebene Name ein Alias ist, wenn er den CNAME-RR findet. Wenn möglich, sollte die Aliasbedingung vom Resolver zum Client zurückgemeldet werden.
In den meisten Fällen startet ein Resolver die Abfrage einfach beim neuen Namen neu, wenn er auf einen CNAME trifft. Bei Ausführung der allgemeinen Funktion sollte der Resolver jedoch keine Aliase verfolgen, wenn der CNAME-RR mit dem Abfragetyp übereinstimmt. Dies ermöglicht Abfragen, die fragen, ob ein Alias vorhanden ist. Wenn beispielsweise der Abfragetyp CNAME ist, ist der Benutzer am CNAME-RR selbst interessiert und nicht an den RRs beim Namen, auf den er zeigt.
Mit Aliasen können mehrere Sonderbedingungen auftreten. Mehrere Ebenen von Aliasen sollten aufgrund ihres Mangels an Effizienz vermieden werden, sollten aber nicht als Fehler signalisiert werden. Aliasschleifen und Aliase, die auf nicht existierende Namen zeigen, sollten erfasst und eine Fehlerbedingung an den Client zurückgegeben werden.
5.2.3. Temporäre Ausfälle (Temporary failures)
In einer weniger als perfekten Welt werden alle Resolver gelegentlich nicht in der Lage sein, eine bestimmte Anfrage aufzulösen. Diese Bedingung kann durch einen Resolver verursacht werden, der aufgrund eines Linkausfalls oder Gateway-Problems vom Rest des Netzwerks getrennt wird, oder seltener durch gleichzeitigen Ausfall oder Nichtverfügbarkeit aller Server für eine bestimmte Domäne.
Es ist wichtig, dass diese Art von Bedingung nicht als Name- oder Daten-nicht-vorhanden-Fehler an Anwendungen gemeldet wird. Diese Art von Verhalten ist für Menschen ärgerlich und kann Chaos anrichten, wenn E-Mail-Systeme das DNS verwenden.
Während es in einigen Fällen möglich ist, mit einem solchen temporären Problem umzugehen, indem die Anfrage unbegrenzt blockiert wird, ist dies normalerweise keine gute Wahl, insbesondere wenn der Client ein Serverprozess ist, der zu anderen Aufgaben übergehen könnte. Die empfohlene Lösung besteht darin, immer temporäre Ausfälle als eines der möglichen Ergebnisse einer Resolver-Funktion zu haben, auch wenn dies die Emulation bestehender HOSTS.TXT-Funktionen schwieriger machen kann.
5.3. Resolver-Interna (Resolver internals)
Jede Resolver-Implementierung verwendet leicht unterschiedliche Algorithmen und verbringt typischerweise viel mehr Logik mit der Behandlung von Fehlern verschiedener Art als mit typischen Vorkommnissen. Dieser Abschnitt skizziert eine empfohlene Grundstrategie für den Resolver-Betrieb, überlässt Details jedoch [RFC-1035].
5.3.1. Stub-Resolver (Stub resolvers)
Eine Option zur Implementierung eines Resolvers besteht darin, die Auflösungsfunktion aus der lokalen Maschine zu verschieben und in einen Nameserver zu verschieben, der rekursive Abfragen unterstützt. Dies kann eine einfache Methode bieten, Domänendienste in einem PC bereitzustellen, dem die Ressourcen fehlen, um die Resolver-Funktion auszuführen, oder kann den Cache für ein ganzes lokales Netzwerk oder eine Organisation zentralisieren.
Alles, was der verbleibende Stub benötigt, ist eine Liste von Nameserver-Adressen, die die rekursiven Anfragen ausführen werden. Dieser Resolver-Typ benötigt die Informationen vermutlich in einer Konfigurationsdatei, da ihm wahrscheinlich die Raffinesse fehlt, sie in der Domänendatenbank zu lokalisieren. Der Benutzer muss auch überprüfen, dass die aufgelisteten Server den rekursiven Dienst ausführen werden; ein Nameserver ist frei, rekursive Dienste für beliebige oder alle Clients abzulehnen. Der Benutzer sollte den lokalen Systemadministrator konsultieren, um Nameserver zu finden, die bereit sind, den Dienst auszuführen.
Diese Art von Dienst leidet unter einigen Nachteilen. Da die rekursiven Anfragen eine beliebige Zeit zur Ausführung benötigen können, kann der Stub Schwierigkeiten haben, Neuübertragungsintervalle zu optimieren, um sowohl mit verlorenen UDP-Paketen als auch mit toten Servern umzugehen; der Nameserver kann leicht von einem zu eifrigen Stub überlastet werden, wenn er Neuübertragungen als neue Anfragen interpretiert. Die Verwendung von TCP kann eine Antwort sein, aber TCP kann durchaus Lasten auf die Fähigkeiten des Hosts legen, die denen eines echten Resolvers ähnlich sind.
5.3.2. Ressourcen (Resources)
Zusätzlich zu seinen eigenen Ressourcen kann der Resolver auch gemeinsamen Zugriff auf Zonen haben, die von einem lokalen Nameserver gepflegt werden. Dies gibt dem Resolver den Vorteil eines schnelleren Zugriffs, aber der Resolver muss darauf achten, niemals gecachte Informationen Zonendaten überschreiben zu lassen. In dieser Diskussion ist der Begriff "lokale Informationen" so gemeint, dass er die Vereinigung des Caches und solcher gemeinsam genutzter Zonen bedeutet, mit dem Verständnis, dass autoritative Daten immer bevorzugt gegenüber gecachten Daten verwendet werden, wenn beide vorhanden sind.
Der folgende Resolver-Algorithmus geht davon aus, dass alle Funktionen in eine allgemeine Suchfunktion konvertiert wurden, und verwendet die folgenden Datenstrukturen, um den Status einer laufenden Anfrage im Resolver darzustellen:
SNAME
Der Domänenname, nach dem wir suchen.
STYPE
Der QTYPE der Suchanfrage.
SCLASS
Der QCLASS der Suchanfrage.
SLIST
Eine Struktur, die die Nameserver und die Zone beschreibt, die der Resolver derzeit zu abfragen versucht. Diese Struktur verfolgt die aktuelle beste Schätzung des Resolvers darüber, welche Nameserver die gewünschten Informationen enthalten; sie wird aktualisiert, wenn eintreffende Informationen die Schätzung ändern. Diese Struktur enthält das Äquivalent eines Zonennamens, die bekannten Nameserver für die Zone, die bekannten Adressen für die Nameserver und Verlaufsinformationen, die verwendet werden können, um vorzuschlagen, welcher Server wahrscheinlich der beste ist, um als nächstes zu versuchen. Das Zonennamen-Äquivalent ist eine Übereinstimmungszählung der Anzahl der Labels von der Wurzel abwärts, die SNAME mit der abgefragten Zone gemeinsam hat; dies wird als Maß dafür verwendet, wie "nah" der Resolver an SNAME ist.
SBELT
Eine "Sicherheitsgurt"-Struktur derselben Form wie SLIST, die aus einer Konfigurationsdatei initialisiert wird und Server auflistet, die verwendet werden sollten, wenn der Resolver keine lokalen Informationen hat, um die Nameserver-Auswahl zu leiten. Die Übereinstimmungszählung wird -1 sein, um anzuzeigen, dass bekannt ist, dass keine Labels übereinstimmen.
CACHE
Eine Struktur, die die Ergebnisse aus früheren Antworten speichert. Da Resolver für das Verwerfen alter RRs verantwortlich sind, deren TTL abgelaufen ist, konvertieren die meisten Implementierungen das in ankommenden RRs angegebene Intervall in eine Art absolute Zeit, wenn der RR im Cache gespeichert wird. Anstatt die TTLs einzeln herunterzuzählen, ignoriert oder verwirft der Resolver alte RRs einfach, wenn er im Verlauf einer Suche auf sie stößt, oder verwirft sie während periodischer Durchläufe, um den von alten RRs verbrauchten Speicher zurückzugewinnen.
5.3.3. Algorithmus (Algorithm)
Der Algorithmus auf oberster Ebene hat vier Schritte:
-
Prüfen Sie, ob sich die Antwort in lokalen Informationen befindet, und falls ja, geben Sie sie an den Client zurück.
-
Finden Sie die besten Server zum Fragen.
-
Senden Sie ihnen Abfragen, bis eine eine Antwort zurückgibt.
-
Analysieren Sie die Antwort, entweder:
a. Wenn die Antwort die Frage beantwortet oder einen Namensfehler enthält, cachen Sie die Daten und geben Sie sie an den Client zurück.
b. Wenn die Antwort eine bessere Delegierung an andere Server enthält, cachen Sie die Delegierungsinformationen und gehen Sie zu Schritt 2.
c. Wenn die Antwort einen CNAME zeigt und das nicht die Antwort selbst ist, cachen Sie den CNAME, ändern Sie den SNAME auf den kanonischen Namen im CNAME-RR und gehen Sie zu Schritt 1.
d. Wenn die Antwort einen Serverausfall oder andere bizarre Inhalte zeigt, löschen Sie den Server aus der SLIST und gehen Sie zurück zu Schritt 3.
Schritt 1: Lokale Informationen durchsuchen (Step 1: Search local information)
Schritt 1 durchsucht den Cache nach den gewünschten Daten. Wenn die Daten im Cache sind, wird angenommen, dass sie gut genug für die normale Verwendung sind. Einige Resolver haben eine Option an der Benutzerschnittstelle, die den Resolver zwingen wird, die gecachten Daten zu ignorieren und einen autoritativen Server zu konsultieren. Dies wird nicht als Standard empfohlen. Wenn der Resolver direkten Zugriff auf die Zonen eines Nameservers hat, sollte er überprüfen, ob die gewünschten Daten in autoritativer Form vorhanden sind, und wenn ja, die autoritativen Daten bevorzugt vor gecachten Daten verwenden.
Schritt 2: Beste Server finden (Step 2: Find best servers)
Schritt 2 sucht nach einem Nameserver, nach dem die erforderlichen Daten gefragt werden können. Die allgemeine Strategie besteht darin, nach lokal verfügbaren Nameserver-RRs zu suchen, beginnend bei SNAME, dann dem übergeordneten Domänennamen von SNAME, dem Großelternteil und so weiter in Richtung Wurzel. Wenn SNAME also Mockapetris.ISI.EDU wäre, würde dieser Schritt nach NS-RRs für Mockapetris.ISI.EDU suchen, dann ISI.EDU, dann EDU und dann . (die Wurzel). Wenn eine Liste von Nameservern gefunden wird, sollte der Resolver sie nach Präferenz und erwarteter Leistung sortieren. Der Resolver sollte dann versuchen, die Server in dieser Reihenfolge zu kontaktieren, beginnend mit dem am meisten bevorzugten.
Schritt 3: Abfragen senden (Step 3: Send queries)
Schritt 3 sendet Abfragen aus, bis eine Antwort empfangen wird. Der Grundalgorithmus besteht darin, alle Adressen für alle Server mit einer Zeitüberschreitung zwischen jeder Übertragung zu durchlaufen. Der Resolver sollte UDP für Abfragen verwenden, wenn möglich, und nur TCP verwenden, wenn die Antwort abgeschnitten ist oder wenn der Resolver bereit ist, die Kosten für den TCP-Verbindungsaufbau und -abbau zu zahlen.
Schritt 4: Antwort analysieren (Step 4: Analyze response)
Schritt 4 analysiert Antworten. Der Resolver sollte beim Parsen von Antworten sehr paranoid sein. Er sollte auch überprüfen, dass die Antwort mit der Abfrage übereinstimmt, die er gesendet hat, unter Verwendung des ID-Feldes in der Antwort.