Structure des paquets DNS


Préface


J'ai décidé d'écrire un renifleur DNS, pour ainsi dire, juste pour le plaisir. Il suffit de voir quelles adresses se résolvent sur mon système. Le protocole est ancien, il devrait y avoir beaucoup de documentation. Beaucoup. Mais tous les articles sont très incomplets et se terminent, au moment le plus intéressant. Oui, il y a rfc1035, mais je voudrais en russe et avec des explications. En fait sur l'accumulation d'expérience et l'analyse d'un package cet article a mûri. Il est conçu pour ceux qui comprennent ce qu'est le DNS et comprennent qu'il existe des demandes et des réponses. Pour ceux qui veulent comprendre un peu la structure de ce protocole.

L'article concerne la théorie, puis un peu de pratique.

Structure des paquets DNS


+---------------------+ | Header |  +---------------------+ | Question |   +---------------------+ | Answer |   +---------------------+ | Authority |      +---------------------+ | Additional |     +---------------------+ 

En - tête - L'en-tête du paquet DNS, composé de 12 octets.

Section Question - dans cette section, le client DNS transmet des requêtes au serveur DNS en informant du nom pour lequel il est nécessaire de résoudre (résoudre) l'enregistrement DNS, ainsi que de quel type (NS, A, TXT, etc.). Lorsqu'il répond, le serveur copie ces informations et les rend au client dans la même section.

Section Réponse - le serveur indique au client la réponse ou plusieurs réponses à la demande, dans laquelle il rapporte les données ci-dessus.

Section faisant autorité - contient des informations sur les serveurs faisant autorité qui ont obtenu les informations incluses dans la section de réponse DNS.

Section des enregistrements supplémentaires - enregistrements supplémentaires qui se rapportent à la demande, mais ne sont pas strictement des réponses à la question.

Il peut y avoir plusieurs ou quelques entrées dans les sections. Tout est déterminé par le titre.

Structure d'en-tête DNS


  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 bits) - ce champ est utilisé comme identifiant de transaction unique. Indique que le paquet appartient à la même session «demande-réponse» et occupe 16 bits.

QR (1 bit) - ce bit est utilisé pour identifier si le paquet est une demande (QR = 0) ou une réponse (QR = 1).

Opcode (4 bits) - en utilisant ce code, le client peut spécifier le type de demande, où la valeur habituelle est:

  • 0 - demande standard
  • 1 - requête inverse,
  • 2 - demande l'état du serveur.
  • 3-15 - réservé pour l'avenir.

AA (1 bit) - ce champ n'a de sens que dans les réponses DNS du serveur et indique si la réponse fait autorité ou non.

TC (1 bit) - cet indicateur est défini dans le paquet de réponse si le serveur n'a pas pu mettre toutes les informations nécessaires dans le paquet en raison des restrictions existantes.

RD (1 bit) - cet indicateur d'un bit est défini dans la demande et copié dans la réponse. Si l'indicateur est défini dans la demande, cela signifie que le client demande au serveur de ne pas lui donner de réponses intermédiaires, mais de renvoyer uniquement l'adresse IP.

RA (1 bit) - envoyé uniquement dans les réponses et signale que le serveur prend en charge la récursivité

Z (3 bits) - sont réservés et toujours égaux à zéro.

RCODE (4 bits) - ce champ est utilisé pour informer les clients si la demande s'est terminée avec succès ou avec une erreur.

  • 0 - signifie que la demande a été passée sans erreur;
  • 1 - l'erreur est due au fait que le serveur n'a pas pu comprendre le formulaire de demande;
  • 2 - cette erreur avec un fonctionnement incorrect du serveur de noms;
  • 3 - le nom qui permet au client n'existe pas dans ce domaine;
  • 4 - le serveur ne peut pas répondre à la demande de ce type;
  • 5 - ce code signifie que le serveur ne peut pas satisfaire la demande du client en raison de restrictions de sécurité administratives.

QDCOUNT (16 bits) - le nombre d'enregistrements dans la section de requête
ANCOUNT (16 bits) - le nombre d'entrées dans la section des réponses
NSCOUNT (16 bits) - nombre d'entrées dans la section Autorité
ARCOUNT (16 bits) - le nombre d'enregistrements dans la section des enregistrements supplémentaires

Structure de la section de demande


  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 - Chaque enregistrement de demande et de réponse commence par NAME. Il s'agit du nom de domaine auquel cet enregistrement est lié ou auquel «appartient». Il est codé comme une série de balises. À ce stade, nous devrions nous attarder plus en détail.

Dans les articles que j'ai vus, ils oublient de dire que le protocole DNS d'origine fournit deux types d'étiquettes, qui sont déterminées par les deux premiers bits:

00 (étiquette standard) - signifie que les 6 bits restants déterminent la longueur de l'étiquette, suivie d'un nombre donné d'octets. Par conséquent, la longueur de l'étiquette ne peut pas dépasser 63 octets (par exemple, nslookup affichera le message «n'est pas un nom légal (étiquette trop longue)» lorsque vous essayez de dégriser un hôte avec une étiquette longue). L'enregistrement se termine avec le code 0x00.
11 (étiquette compressée) - puis les 14 bits suivants définissent un lien vers l'adresse de départ de la série d'étiquettes. Comme l'expérience l'a montré, il peut également contenir une étiquette compressée vers une autre adresse. Dans la demande, en règle générale, il n'y a pas de telles étiquettes.

En outre, l'étiquette peut contenir la valeur 0x00 (longueur nulle), ce qui signifie qu'il s'agit du nom de domaine racine (racine).

La longueur maximale de NAME est <= 255. C'est pour des raisons de facilité d'implémentation.

QTYPE - Le type d'enregistrement DNS que nous recherchons (NS, A, TXT, etc.).
QCLASS - La classe de demande de définition (IN pour Internet).

Structure de la section Réponse


  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 - Même format que QNAME dans la section des demandes.
TYPE - type d'enregistrement de ressource. Définit le format et le but de cet enregistrement de ressource.
CLASS - classe d'enregistrement de ressource; on pense théoriquement que le DNS peut être utilisé non seulement avec TCP / IP, mais aussi avec d'autres types de réseaux, le code dans le champ de classe détermine le type de réseau. Fondamentalement IN pour Internet (Code 0x0001)
TTL - (Time To Live) - la durée de stockage valide pour cet enregistrement de ressource dans le cache d'un serveur DNS non réactif.
RDLENGTH - longueur du champ de données (RDATA).
RDATA - champ de données dont le format et le contenu dépendent du type d'enregistrement.

Pratique


Considérez un package à partir d'une vraie demande et réponse. Lancez votre sniffer préféré et résolvez habrahabr.ru.

Demande



Analysons la structure d'en-tête DNS.

ID de transaction = 0x9bce

Viennent ensuite les drapeaux. 01 00 est représenté comme une valeur binaire 0'0000'0'0'1'0'000'0000 (ci-après, je sépare les bits avec une apostrophe pour une meilleure représentation visuelle de la division des drapeaux)
QR = 0 - signifie que ce paquet est une demande;
Opcode = 0000 - Demande standard;
AA = 0 - ce champ n'a de sens que dans les réponses DNS, donc toujours 0;
TC = 0 - ce champ n'a de sens que dans les réponses DNS, donc toujours 0;
RD = 1 - Veuillez renvoyer uniquement l'adresse IP;
RA = 0 - envoyé uniquement par le serveur;
Z = 000 - toujours des zéros, champ réservé;
RCODE = 0000 - Tout s'est passé sans erreur

QDCOUNT = 00 01 - 1 entrée dans la section de requête
ANCOUNT = 00 00 - La demande est toujours 0, section pour les réponses
NSCOUNT = 00 00 - La demande est toujours 0, section pour les réponses
ARCOUNT = 00 00 - La demande est toujours 0, section pour les réponses
Ensuite, nous avons les sections de demande et de réponse. Avec une entrée.
Le premier octet que nous avons est 0x09, imaginez-le comme une valeur binaire 00'001001. Les deux premiers bits passent à 00, ce qui signifie qu'il s'agit d'une étiquette régulière. Longueur d'étiquette 9 octets (b001001). «68 61 62 72 61 68 61 62 72». Ce sont 9 octets. Il dit «habrahabr» (en hexadécimal). Allez-y. Octet 0x02. Les deux premiers bits sont 00, puis à nouveau une étiquette régulière d'une longueur de 2 octets. Les voici: «72 75». Il est écrit «ru». Allez-y. Octet 0x00. Cela signifie la fin de l'entrée hôte. Nous avons obtenu deux mots «habrahabr» et «ru». Nous les unissons avec un point, nous obtenons "habrahabr.ru", c'est l'hôte que nous avons demandé.
QTYPE = 0x0001 - correspond au type A (demande d'adresse hôte)
QCLASS = 0x0001 - Correspond à la classe IN.

La réponse



Analysons la structure d'en-tête DNS.

ID de transaction = 0x9bce. Il doit s'agir exactement de l'ID de la demande.
Drapeaux à nouveau. 81 80 représente la valeur binaire 1'0000'0'0'1'1'000'0000
QR = 1 - signifie que ce paquet est la réponse;
Opcode = 0000 - Demande standard;
AA = 0 - Le serveur ne fait pas autorité pour le domaine;
TC = 0 - Toutes les informations tiennent dans un seul paquet;
RD = 1 - Veuillez renvoyer uniquement l'adresse IP;
RA = 1 - Le serveur prend en charge la récursivité;
Z = 000 - toujours des zéros, champ réservé;
RCODE = 0000 - Tout s'est passé sans erreur

QDCOUNT = 00 01 - 1 entrée dans la section de requête
ANCOUNT = 00 01 - Maintenant, nous avons une entrée dans la réponse
NSCOUNT = 00 00 - La demande est toujours 0, section pour les réponses
ARCOUNT = 00 00 - La demande est toujours 0, section pour les réponses

Ensuite, nous avons les sections de demande et de réponse. Avec deux entrées. Un enregistrement de la demande, un autre enregistrement avec la réponse. Je ne peindrai pas la section de demande, elle sera toujours 1v1 identique à celle du package de demande. Passez à la section des réponses.

Le premier octet est 0x09, les deux premiers bits sont 00, ce qui signifie une étiquette régulière d'une longueur de 9 octets. Lisez 9 octets, obtenez "HABRAHABR". Vient ensuite 0XC0 (b11000000). Comme vous pouvez le voir, les deux premiers bits ont une valeur de 11, ce qui signifie que nous avons une liaison compressée. Nous regardons les 8 bits suivants (nous avons 0x16 (b00010110)) et combinons avec les 6 derniers bits actuels. Nous obtenons b00000000010110. Lien vers le 22e octet du paquet DNS (02 72 75 00). À partir de l'octet 22, nous obtenons à nouveau les étiquettes. Par les mêmes règles. Nous l'obtenons .ru. Nous combinons tout ce que nous avons reçu, il s'avère "HABRAHABR.ru" Ceci est l'hôte, qui sera discuté plus loin.

QTYPE = 0x0001 - correspond au type A (demande d'adresse hôte)
QCLASS = 0x0001 - Correspond à la classe IN.
TTL = 0x00000c90 - mise à jour des données 3216 secondes.
RDLENGTH = 0x0004 - La longueur des données est de 4 octets.
RDATA = "b2 f8 ed 44".

Comme déjà mentionné, le format et le contenu dépendent du type d'enregistrement. Le type d'enregistrement que nous avons est «A». Donc, pour obtenir l'IP, nous devons lire 4 octets. Chaque octet est l'octet correspondant de l'adresse IP, écrit en hexadécimal.

Nous obtenons l'IP: b2.f8.ed.44 ou "178.248.237.68". Ce qui était nécessaire pour recevoir.

Par exemple, pour le type NS, le format serait:

  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / NSDNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 

Et nous lirions le nom selon les règles de QNAME.

Source: https://habr.com/ru/post/fr478652/


All Articles