Protocole et Formats
Messages DNS et codage
Le Protocole DNS utilise un format de messages commun pour tous les échanges
entre serveurs ou entre client et serveur. Les messages DNS sont acheminés
soit au dessus de UDP, soit au dessus de TCP.
Dans les 2 cas, on utilise le numéro de port prédéfini 53.
Au dessus de UDP, le protocole DNS ne gère pas la segmentation
et impose une taille maximum de message DNS de 512 octets.
UDP sera utilisé par défaut, TCP servira dans le cas de messages dépassant 512 octets
(transfert de zone en particulier).
Messages DNS
Identification | Contrôle |
Nombre de Questions | Nombre de Réponses |
Nombre de "Authority" | Nombre de "Additional" |
Question |
... |
Réponse |
... |
"Authority" |
... |
"Additional" |
... |
Les 6 premiers champs sont chacun sur 16 bits, les autres champs sont
de tailles variables sans contraintes d'alignement autres que les octets.
Les limites de tailles sont de 255 octets pour un Nom-DNS
et de 65535 octets pour un RDATA.
- Le champ Identification sert à identifier si besoin la
réponse à une requête donnée.
- Le champ Contrôle se décompose sous la forme:
QR | OpCode | AA | TC | RD | RA | Z | AD | CD | RCODE |
- 1 bit QR : requête (0) ou réponse (1)
- 4 bits OpCode Type de requête :
- QUERY requête standard
- IQUERY requête inverse (déprécié par RFC3425)
- STATUS Demande d'état du serveur
- NOTIFY Notification de modification de la base (RFC1996)
- UPDATE Mise à jour dynamique de la base (RFC2136)
- 1 bit AA Authoritative Answer, réponse
d'un serveur authoritative (1) ou d'un cache (0)
- 1 bit TC Truncated, message tronqué car trop grand (1), essayer TCP.
- 1 bit RD Recursion Desired, la requête demande une
résolution récursive (1) ou une résolution itérative (0)
- 1 bit RA Recursion Available, le serveur accepte les
résolutions récursives (1) ou non (0)
- 1 bit Zeros, réservé pour extensions
- 1 bit AD Authenticated data, pour extension DNSSEC
- 1 bit CD Checking Disabled, pour extension DNSSEC
- 4 bits Rcode, Code d'erreur : NOERROR, SERVFAIL, NXDOMAIN
(no such domain), REFUSED...
- Les 4 champs Nombre de ... donnent le nombre d'objets dans chacune
des 4 sections suivantes du message.
- La section Question contient des RRs incomplets
{Nom-DNS, TYPE, CLASSE}.
- Les sections Réponse, Authority et
Additional sont constituées de RRs complets
{Nom-DNS, TYPE, CLASSE, TTL, (RDATA_LENGTH), RDATA}
(TYPE, CLASSE et RDATA_LENGTH sont sur 2 octets, TTL est sur 4 octets)
L'existence et le contenu des différentes sections peuvent être
requis ou optionnels suivant les cas. Cela dépendra aussi fortement
de la nature itérative ou récursive de la réponse.
- Le nombre de Question est le plus souvent égal à 1,
mais peut être 0 ou >1 dans certains cas particuliers.
- La section Réponse contient l'ensemble des RRs qui
correspondent dans le DNS à la question posée.
- La section Authority contient les serveurs de noms (RR NS)
Authoritatives liés la question. Dans certains cas,
on peut aussi y trouver le SOA de la zone cible.
- La section Additional contient des informations DNS
complémentaires liées aux RRs des sections précédentes. Par exemple
les adresses (A ou AAAA) des serveurs de noms (NS) ou de messageries (MX).
Pour une réponse itérative (RD=0 ou RA=0), la section
Réponse sera le plus souvent vide (sauf si
le serveur connaît par chance la réponse). La section
Authority contiendra alors un Nom de domaine qui est un Nom
de zone et les Serveurs de Noms associés. Il s'agit de la "meilleure information"
connue par le serveur courant pour résoudre la requête. C'est à dire le plus long suffixe du
nom de la question, dont le serveur courant connaît les Serveurs de Noms. Dans le pire des cas,
c'est la zone Racine.
La section Additional contient alors si possible
(obligatoire pour la GLUE), des adresses de ces serveurs vers qui
on va immédiatement itérer la requête.
Pour une réponse récursive positive (RD=RA=1, Rcode=NOERROR, Nombre de Réponses>0),
la section Réponse contiendra toutes les réponses souhaitées.
La section Authority contiendra le nom de la zone et la liste
des serveurs Authoritative pour la réponse.
Ceci permet éventuellement d'aller vérifier la réponse
à la source si l'on ne fait pas confiance au cache, ou de mémoriser
utilement les serveurs dans le cache pour répondre plus rapidement
à des requêtes voisines ultérieurement (ou à la même requête après
expiration du TTL).
La notion de réponse négative va en pratique couvrir deux cas différents :
- NXDOMAIN le nom dans la requête n'existe pas dans la base DNS. Cela est identifié
dans le message DNS par Rcode=NXDOMAIN.
- NODATA le nom dans la requête existe mais il n'y a pas de RR du TYPE demandé. Le message
contient alors Rcode=NOERROR et Nombre de Réponses=0.
Le mécanisme de cache négatif s'appliquera dans les 2 cas.
Pour une réponse récursive négative (RD=RA=1, NXDOMAIN ou NODATA),
la section Réponse sera vide. La section Authority
contiendra le SOA de la zone afin de donner la valeur du
parametre Negative Cache TTL à utiliser pour cette réponse.
On se reportera à la section exemples dig pour des exemples.
Codage des Noms de Domaine
Le codage des Noms-DNS prend la forme :
N1 | label1 | N2 | label2 | ... | Nn | labeln | 0 |
où N1, N2, ..., Nn sont sur 1 octet la taille
des labels successifs. La taille maximum d'un label est 63 octets à cause de la
compression à venir. La taille maximum d'un nom est arbitrairement de 255 octets
pour "simplifier l'implémentation".
Le label vide (N=0) est uniquement la racine.
Les labels sont constitués d'octets quelconques.
On a par exemple :
où les chiffres en gras sont les valeurs décimales des octets, le
reste est en ASCII.
Compression des Noms de Domaines
Pour économiser la place dans les messages DNS, on peut, et l'on doit,
partager des parties de noms communes dans un même message.
Les 2 bits de poids fort dans le champs longueur d'un label
sont utilisés pour cela :
- si les 2 bits valent 00, on a un champs de longueur de label
sur 1 octet, et longueur < 64
- si les 2 bits valent 11, le champs s'interprète alors sur 2 octets
et le reste du champs (14 bits) va coder un offset dans le message
- le cas 01 est reservé pour extension par EDNS0 (rfc2671)
- le cas 10 est inutilisé
Cet offset sur 14 bits, indique la position en octet de la suite du nom de domaine
par rapport au début du message DNS. Offset=0 correspond au premier octet du champs
Identification.
Exemple :
On considère une requête sur le nom zeratul.ipv6.int-evry.fr.
(cf. exemple dig n.7).
Dans la réponse, le premier nom qui apparaît est celui de la question, il
commencera au 12ième octet du message DNS.
On trouve donc avec OFFSET=12, le codage :
7 | zeratul | 4 | ipv6 | 8 | int-evry | 2 | fr | 0 |
Le même nom apparaît naturellement dans la section Réponse,
il sera alors codé sur seulement 2 octets par :
NB: 192="11000000"
Le nom ipv6.int-evry.fr. apparaît ensuite comme nom de zone
dans la section Authority, il sera alors codé sur 2 octets :
Le nom hugo.int-evry.fr. apparaît aussi comme serveur de zone, il
sera alors codé :
Precisions :
La compression des noms s'applique aussi bien sur le Nom de domaine des
RRs que sur les noms DNS qui apparaissent dans les RDATAs. Cela pose un problème d'extensibilité
au niveau du DNS car les RDATAs contenants des noms ne peuvent être traités de manière opaque
comme une chaîne d'octets. En effet, le codage des RDATAs dépend alors du message qui
les a véhiculé. Ainsi l'introduction d'un nouveau type de RR avec des noms dans
les RDATAs nécessite la mise à jour de tout les serveurs DNS (car ils peuvent servir de cache), ou
l'interdiction de la compression des noms pour les nouveaux RDATAs (cf. RFC3597).