Vorwort
Ich beschloss, sozusagen aus Spaß einen DNS-Sniffer zu schreiben. Sehen Sie einfach, welche Adressen auf meinem System aufgelöst werden. Das Protokoll ist alt, es sollte eine Menge Dokumentation geben. Viel. Aber alle Artikel sind sehr unvollständig und enden im interessantesten Moment. Ja, es gibt rfc1035, aber ich möchte in russischer Sprache und mit Erklärungen. Tatsächlich ist dieser Artikel aufgrund der gesammelten Erfahrung und Analyse eines Pakets gereift. Es ist für diejenigen gedacht, die verstehen, was DNS ist, und wissen, dass es Anfragen und Antworten gibt. Für diejenigen, die ein wenig in die Struktur dieses Protokolls verstehen wollen.
Der Artikel beinhaltet Theorie und dann ein wenig Praxis.
DNS-Paketstruktur
+---------------------+ | Header | +---------------------+ | Question | +---------------------+ | Answer | +---------------------+ | Authority | +---------------------+ | Additional | +---------------------+
Header - Der Header des DNS-Pakets, bestehend aus 12 Oktetten.
Fragenabschnitt - In diesem Abschnitt sendet der DNS-Client Abfragen an den DNS-Server, in denen angegeben wird, für welchen Namen der DNS-Eintrag aufgelöst werden muss (Auflösung) und welcher Typ (NS, A, TXT usw.). Wenn der Server antwortet, kopiert er diese Informationen und gibt sie im selben Abschnitt an den Client zurück.
Antwortbereich - Der Server teilt dem Client die Antwort oder mehrere Antworten auf die Anforderung mit, in denen er die oben genannten Daten meldet.
Autorisierender Abschnitt - enthält Informationen darüber, auf welchen autorisierenden Servern die im DNS-Antwortabschnitt enthaltenen Informationen abgerufen wurden.
Zusätzlicher Datensatzabschnitt - zusätzliche Datensätze, die sich auf die Anfrage beziehen, aber nicht ausschließlich auf die Frage beantwortet werden.
Es können mehrere oder wenige Einträge in Abschnitten vorhanden sein. Alles wird durch die Überschrift bestimmt.
DNS-Header-Struktur
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
ID (16 Bit) - Dieses Feld wird als eindeutige Transaktionskennung verwendet. Zeigt an, dass das Paket zu derselben "Anfrage-Antwort" -Sitzung gehört und 16 Bits belegt.
QR (1 Bit) - Dieses Bit wird verwendet, um zu identifizieren, ob das Paket eine Anforderung (QR = 0) oder eine Antwort (QR = 1) ist.
Opcode (4 Bit) - Mit diesem Code kann der Client die Art der Anforderung angeben, wobei der übliche Wert lautet:
- 0 - Standardanforderung
- 1 - inverse Anfrage,
- 2 - Serverstatus anfordern.
- 3-15 - reserviert für die Zukunft.
AA (1 Bit) - Dieses Feld ist nur in DNS-Antworten vom Server sinnvoll und gibt an, ob die Antwort autorisierend ist oder nicht.
TC (1 Bit) - Dieses Flag wird im Antwortpaket gesetzt, wenn der Server aufgrund bestehender Einschränkungen nicht alle erforderlichen Informationen in das Paket aufnehmen konnte.
RD (1 Bit) - Dieses Ein-Bit-Flag wird in der Anforderung gesetzt und in die Antwort kopiert. Wenn das Flag in der Anfrage gesetzt ist, bedeutet dies, dass der Client den Server auffordert, ihm keine Zwischenantworten mitzuteilen, sondern nur die IP-Adresse zurückzugeben.
RA (1 Bit) - Wird nur in Antworten gesendet und meldet, dass der Server die Rekursion unterstützt
Z (3 Bits) - sind reserviert und immer gleich Null.
RCODE (4 Bit) - In diesem Feld werden Clients benachrichtigt, wenn die Anforderung erfolgreich abgeschlossen wurde oder wenn ein Fehler
aufgetreten ist.
- 0 - bedeutet, dass die Anforderung ohne Fehler übergeben wurde;
- 1 - Der Fehler beruht auf der Tatsache, dass der Server das Anforderungsformular nicht verstehen konnte.
- 2 - dieser Fehler bei fehlerhaftem Betrieb des Nameservers;
- 3 - Der Name, der den Client zulässt, ist in dieser Domäne nicht vorhanden.
- 4 - Der Server kann die Anforderung dieses Typs nicht erfüllen.
- 5 - Dieser Code bedeutet, dass der Server die Clientanforderung aufgrund administrativer Sicherheitsbeschränkungen nicht erfüllen kann.
QDCOUNT (16 Bit) - Die Anzahl der Datensätze im Abfrageabschnitt
ANCOUNT (16 Bit) - Die Anzahl der Einträge im Abschnitt "Antworten"
NSCOUNT (16 Bit) - Anzahl der Einträge in der Authority Section
ARCOUNT (16 Bit) - Die Anzahl der Datensätze im Abschnitt Additional Record
Abschnittsstruktur anfordern
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / QNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QTYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
QNAME - Jeder Anforderungs- und Antwortdatensatz beginnt mit NAME. Dies ist der Domänenname, mit dem dieser Datensatz verknüpft ist oder zu dem "gehört". Es ist als eine Reihe von Tags codiert. An dieser Stelle sollten wir näher darauf eingehen.
In den Artikeln, die ich gesehen habe, vergessen sie zu sagen, dass das ursprüngliche DNS-Protokoll zwei Arten von Bezeichnungen enthält, die durch die ersten beiden Bits bestimmt werden:
00 (Standardbezeichnung) - bedeutet, dass die verbleibenden 6 Bits die Länge der Bezeichnung bestimmen, gefolgt von einer bestimmten Anzahl von Oktetten. Dementsprechend darf die Etikettenlänge nicht mehr als 63 Byte betragen (z. B. zeigt nslookup die Meldung "ist kein gültiger Name (Etikett zu lang)" an, wenn versucht wird, einen Host mit einem langen Etikett zu nüchtern.) Die Aufnahme endet mit dem Code 0x00.
11 (komprimiertes Etikett) - dann definieren die nächsten 14 Bits eine Verknüpfung zur Startadresse der Etikettenserie. Wie die Erfahrung gezeigt hat, kann es auch ein komprimiertes Etikett an eine andere Adresse enthalten. In der Anfrage gibt es in der Regel keine solchen Labels.
Das Label kann auch den Wert 0x00 (Nulllänge) enthalten, was bedeutet, dass es sich um den Stammdomänennamen (root) handelt.
Die maximale Länge von NAME beträgt <= 255. Dies dient der einfacheren Implementierung.
QTYPE - Der Typ des
gesuchten DNS-
Eintrags (NS, A, TXT usw.).
QCLASS - Die definierende Anforderungsklasse (IN für das Internet).
Struktur des Antwortbereichs
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / / / NAME / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| / RDATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
NAME - Gleiches Format wie QNAME im Anfrageabschnitt.
TYPE - Typ des Ressourceneintrags. Definiert das Format und den Zweck dieses Ressourceneintrags.
CLASS - Ressourcendatensatzklasse; Es wird theoretisch angenommen, dass DNS nicht nur mit TCP / IP, sondern auch mit anderen Netzwerktypen verwendet werden kann. Der Code im Klassenfeld bestimmt den Netzwerktyp. Grundsätzlich IN für Internet (Code 0x0001)
TTL - (Time To Live) - Die gültige Speicherzeit für diesen Ressourceneintrag im Cache eines nicht reagierenden DNS-Servers.
RDLENGTH - Datenfeldlänge (RDATA).
RDATA - Datenfeld, dessen Format und Inhalt von der Art des Datensatzes abhängt.
Übe
Betrachten Sie ein Paket aus einer realen Anfrage und Antwort. Starten Sie Ihren Lieblingsschnüffler und lösen Sie habrahabr.ru auf.
Anfrage
Lassen Sie uns die DNS-Header-Struktur analysieren.
Transaktions-ID = 0x9bce
Als nächstes kommen die Fahnen. 01 00 wird als Binärwert 0'0000'0'0'1'0'000'0000 dargestellt (im Folgenden trenne ich die Bits mit einem Apostroph, um die Flag-Teilung besser sichtbar zu machen)
QR = 0 - bedeutet, dass dieses Paket eine Anfrage ist;
Opcode = 0000 - Standardanforderung;
AA = 0 - dieses Feld ist nur in DNS-Antworten sinnvoll, daher immer 0;
TC = 0 - dieses Feld ist nur in DNS-Antworten sinnvoll, daher immer 0;
RD = 1 - Bitte nur die IP-Adresse zurückgeben;
RA = 0 - nur vom Server gesendet;
Z = 000 - immer Nullen, reserviertes Feld;
RCODE = 0000 - Alles verlief fehlerfrei
QDCOUNT = 00 01 - 1 Eintrag im Abfrageabschnitt
ANCOUNT = 00 00 - Die Anfrage ist immer 0, Abschnitt für Antworten
NSCOUNT = 00 00 - Die Anfrage ist immer 0, Abschnitt für Antworten
ARCOUNT = 00 00 - Die Anfrage ist immer 0, Abschnitt für Antworten
Als nächstes haben wir die Anforderungs- und Antwortabschnitte. Mit einem Eintrag.
Das erste Oktett, das wir haben, ist 0x09, stellen Sie es sich als Binärwert 00'001001 vor. Die ersten beiden Bits gehen auf 00, was bedeutet, dass dies ein reguläres Label ist. Etikettenlänge 9 Byte (b001001). "68 61 62 72 61 68 61 62 72". Das sind 9 Bytes. Es heißt "Habrahabr" (hexadezimal). Mach weiter. Oktett 0x02. Die ersten beiden Bits sind 00, dann wieder ein reguläres Label mit einer Länge von 2 Bytes. Hier sind sie: "72 75." Es steht "ru". Mach weiter. Oktett 0x00. Dies bedeutet das Ende des Hosteintrags. Wir haben zwei Wörter "habrahabr" und "ru". Wir vereinen sie mit einem Punkt, wir bekommen "habrahabr.ru", das ist der Gastgeber, den wir angefordert haben.
QTYPE = 0x0001 - Entspricht Typ A (Hostadressanforderung)
QCLASS = 0x0001 - Entspricht der Klasse IN.
Die antwort
Lassen Sie uns die DNS-Header-Struktur analysieren.
Transaktions-ID = 0x9bce. Es muss genau die ID aus der Anfrage sein.
Fahnen wieder. 81 80 stellen den Binärwert 1'0000'0'0'1'1'000'0000 dar
QR = 1 - bedeutet, dass dieses Paket die Antwort ist;
Opcode = 0000 - Standardanforderung;
AA = 0 - Der Server ist nicht autorisierend für die Domäne.
TC = 0 - Alle Informationen passen in ein Paket;
RD = 1 - Bitte nur die IP-Adresse zurückgeben;
RA = 1 - Server unterstützt Rekursion;
Z = 000 - immer Nullen, reserviertes Feld;
RCODE = 0000 - Alles verlief fehlerfrei
QDCOUNT = 00 01 - 1 Eintrag im Abfrageabschnitt
ANCOUNT = 00 01 - Jetzt haben wir einen Eintrag in der Antwort
NSCOUNT = 00 00 - Die Anfrage ist immer 0, Abschnitt für Antworten
ARCOUNT = 00 00 - Die Anfrage ist immer 0, Abschnitt für Antworten
Als nächstes haben wir die Anfrage- und Antwortabschnitte. Mit zwei Einträgen. Ein Datensatz der Anfrage, ein weiterer Datensatz mit der Antwort. Ich werde den Anfrageabschnitt nicht malen, es wird immer 1v1 wie im Anfragepaket sein. Fahren Sie mit dem Antwortabschnitt fort.
Das erste Oktett ist 0x09, die ersten beiden Bits sind 00, was eine reguläre Bezeichnung mit einer Länge von 9 Bytes bedeutet. Lesen Sie 9 Bytes und erhalten Sie "HABRAHABR". Als nächstes kommt 0XC0 (b11000000). Wie Sie sehen, haben die ersten beiden Bits den Wert 11, was bedeutet, dass wir eine komprimierte Verbindung haben. Wir schauen uns die nächsten 8 Bits an (wir haben 0x16 (b00010110)) und kombinieren sie mit den aktuellen letzten 6 Bits. Wir bekommen b00000000010110. Verknüpfung zum 22. Byte des DNS-Pakets (02 72 75 00). Ab dem 22. Oktober bekommen wir die Labels wieder. Nach den gleichen Regeln. Wir bekommen es .ru. Wir kombinieren alles, was wir erhalten haben, es stellt sich heraus, "HABRAHABR.ru" Dies ist der Gastgeber, der weiter besprochen wird.
QTYPE = 0x0001 - Entspricht Typ A (Hostadressanforderung)
QCLASS = 0x0001 - Entspricht der Klasse IN.
TTL = 0x00000c90 - Datenverfügbarkeit 3216 Sekunden.
RDLENGTH = 0x0004 - Die Datenlänge beträgt 4 Oktette.
RDATA = "b2 f8 ed 44".
Wie bereits erwähnt, hängt das Format und der Inhalt von der Art der Aufnahme ab. Die Art der Aufzeichnung, die wir haben, ist „A“. Um die IP zu erhalten, müssen wir 4 Bytes lesen. Jedes Byte ist das entsprechende Oktett der IP-Adresse, hexadezimal geschrieben.
Wir erhalten die IP: b2.f8.ed.44 oder "178.248.237.68". Was war erforderlich, um zu erhalten.
Für den Typ NS wäre das Format beispielsweise:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / NSDNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Und wir würden den Namen nach den Regeln von QNAME lesen.