<?xml version="1.0" encoding="utf-8"?>
<rfcdesc title="DNS64: DNS extensions for Network Address Translation from IPv6 Clients to IPv4 Servers" num="6147" wg="behave" status="standards">
<authors><author>M. Bagnulo (UC3M)</author><author>A. Sullivan
(Shinkuro)</author><author>P. Matthews
(Alcatel-Lucent)</author><author>I. van Beijnum (IMDEA Networks)</author></authors>
<rfcdate><month>April</month><year>2011</year></rfcdate>
<date>2011-04-28</date>
<content>
<p>Ce nouveau <wikipedia name="Request for comments">RFC</wikipedia> est un composant
indispensable de la nouvelle technique de <wikipedia name="Network address translation">traduction</wikipedia> entre des machines <wikipedia>IPv4</wikipedia>
et <wikipedia>IPv6</wikipedia> (dont une description générale se
trouve dans le <rfc num="6144" local="true"/>). Les machines purement IPv6 ne pouvant
pas initier une communication avec des machines n'ayant qu'une adresse
IPv4, il est nécessaire de les « tromper » en fabriquant dynamiquement
des adresses IPv6. Les machines IPv6 tenteront alors de s'y connecter,
leurs requêtes seront reçues par le traducteur d'adresses, qui pourra
alors les convertir en IPv4 (cf. <rfc num="7915" local="true"/> et <rfc num="6146" local="true"/>).</p>
<p><wikipedia xml:lang="en" name="IPv6 transition mechanisms" anchor="DNS64">DNS64</wikipedia> n'est donc pas utilisable seul. Il
doit se combiner à une machine, typiquement un routeur, qui fait la
traduction d'adresses, dite <link local="nats">NAT64</link>. La
configuration typique des utilisateurs de DNS64 sera un réseau local
purement IPv6 (puisque le stock d'adresses IPv4 est <link
local="epuisement-adresses-ipv4">épuisé</link>), dont le routeur fait
de la traduction NAT64, et qui est muni d'un résolveur
<wikipedia name="Domain Name System">DNS</wikipedia> capable de fabriquer des adresses IPv6 à
partir des adresses v4 des machines externes. En effet, le but du
système NAT64 est de ne pas avoir à modifier les machines, seulement
les équipements d'infrastructure (routeur et résolveur DNS). Les
machines purement v6, ignorantes de la traduction qui se fait entre
leur réseau et le monde extérieur, ne pourraient pas se connecter si
elle ne connaissaient de leur pair qu'une adresse IPv4. NAT64 et son
indispensable compagnon DNS64 rejoignent donc la boîte à outils des
techniques permettant de faire coexister IPv4 et IPv6 (cf. <rfc
num="6144" local="true"/>).</p>
<p>Comment est-ce que le serveur DNS64 synthétise cette adresse IPv6 ?
Supposons qu'une machine IPv6 du réseau local veuille se connecter à
<computer>www.example.com</computer> et que celui-ci n'ait qu'une
adresse v4, mettons <computer>203.0.113.18</computer>. Le navigateur
Web tournant sur le client va faire une requête DNS de type AAAA
(adresse IPv6 ; puisqu'il n'a pas d'IPv4, les requêtes de type A
n'auraient aucun intérêt). Le serveur DNS la reçoit, la relaie et
récupère une réponse vide (le nom existe mais n'a pas d'enregistrement
AAAA). Il tente alors une requête A, reçoit
<computer>203.0.113.18</computer> en réponse et génère l'adresse v6 de
manière purement algorithmique, sans état, en utilisant l'adresse v4
et les paramètres avec lesquels le serveur a été configuré
(typiquement, un préfixe v6). Rappelez-vous donc bien que le serveur
DNS64 et le traducteur doivent être configurés de manière cohérente
(dans la plupart des cas, ils seront sans doute dans la même boîte
mais, conceptuellement, ce sont deux services séparés.)</p>
<!-- Section 2 : résumé non normatif, 3, interactions avec DNSSEC, 4
     terminologie, 5 le protocole, 6 les questions de déploiement, 7
     des exemples. -->
<p>Pour le lecteur pressé qui veut juste une introduction à la norme,
la section 2 est la meilleure lecture. Voici un exemple où une machine purement IPv6 tente de contacter <wikipedia>Twitter</wikipedia>, service purement IPv4 :
<code>
% telnet twitter.com 80
Trying 64:ff9b::80f2:f0f4...
Connected to twitter.com.
Escape character is '^]'.
</code>
C'est le serveur DNS64 qui a généré l'adresse
<computer>64:ff9b::80f2:f0f4</computer> et c'est le traducteur qui
changera les paquets IPv6 en IPv4 à l'aller et en sens inverse au
retour. Twitter et le client purement IPv6 n'y verront que du
feu. Pour le préfixe à utiliser, le serveur DNS64 et le traducteur ont
le choix (cf. <rfc num="6052" local="true"/>) entre un préfixe bien
connu, réservé à la traduction d'adresse (celui utilisé dans
l'exemple, qui avait été testé lors d'une réunion
<wikipedia name="Internet Engineering Task Force">IETF</wikipedia> à <wikipedia>Pékin</wikipedia>) ou bien un
préfixe appartenant à l'opérateur réseau (NSP, pour
<foreign>Network-Specific Prefix</foreign>). La seule contrainte est
qu'il doit être configuré de manière <emphasis>identique</emphasis> dans le serveur DNS64
et dans le traducteur.
</p>
<p>La norme elle-même fait l'objet de la section 5. Elle décrit avec
précision le fonctionnement que j'ai résumé plus haut. Quelques petits
points intéressants :
<enum>
<item>On ne synthétise d'enregistrements que s'il n'y avait pas déjà
un AAAA (section 5.1.1).</item>
<item>Les erreurs (autres que NXDOMAIN - <foreign>No Such
Domain</foreign>) doivent être traitées comme si le AAAA étai
absent (section 5.1.2). Donc, par exemple, SERVFAIL (<foreign>Server
Failure</foreign>) doit être traité comme un NOERROR,ANSWER=0, pour tenir compte des
serveurs assez pourris pour ne pas répondre correctement aux requêtes
AAAA (cf. <rfc num="4074"/>). C'est une violation des normes du DNS, rendue nécessaire par le nombre de serveurs
DNS (ou de <foreign>middlewares</foreign> placés devant eux)
programmés avec les pieds.</item>
<item>La règle précédente, interdisant la synthèse d'enregistrements
AAAA s'il en existe déjà, a quelques exceptions (section
5.1.4). Ainsi, les adresses IPv6 non utilisables globalement comme celles en
<computer>::ffff:0:0/96</computer> doivent être ignorés et le AAAA de
synthèse produit.</item>
<item>Si le AAAA n'existe pas ou est inutilisable (section 5.1.6), le serveur DNS64
demande un enregistrement A (adresse IPv4). S'il n'en trouve pas, il
répond au client « Désolé, aucune réponse ». S'il en trouve un, il
fabrique l'enregistrement AAAA correspondant (typiquement en concaténant le
préfixe IPv6 avec l'adresse IPv4) et le renvoie (la réponse de type A, elle,
n'est pas transmise). La section 5.1.7 donne les détails de cette
synthèse.</item>
<item>Les deux requêtes, pour un enregistrement de type AAAA et pour
un enregistrement de type A, peuvent être faites en parallèle (section
5.1.8). Certes, ce sera un gaspillage si l'enregistrement AAAA existe
(puisque le A sera alors inutile) mais cela permettra de diminuer le
temps total d'attente si le AAAA n'existe pas.</item>
</enum></p>
<p>J'ai dit plus haut que l'adresse IPv6 de synthèse était fabriquée
par concaténation du préfixe IPv6 (configuré à la main dans le serveur
DNS64) et de l'adresse IPv4. Mais, en fait, le RFC n'impose pas
l'utilisation d'un tel
algorithme. La méthode utilisée n'a pas besoin d'être normalisée (elle
n'est pas vue à l'extérieur) et doit seulement être la même sur le
serveur DNS64 et sur le traducteur. La section 5.2 précise plus
rigoureusement les exigences auxsquelles doit obéir cet algorithme. Le
point le plus important est qu'il doit être
<emphasis>réversible</emphasis> : en échange de l'adresse IPv6 de
synthèse, le traducteur doit pouvoir retrouver l'adresse IPv4
originelle. Pour faciliter la vie des administrateurs réseau, un
algorithme doit être obligatoirement présent dans les programmes (mais
ce n'est pas forcément celui que l'administrateur choisira), celui
décrit en section 2 du <rfc num="6052" local="true"/>.</p>
<p>Et que doit faire le serveur DNS64 s'il reçoit des requêtes d'un
autre type que A ou AAAA ? La section 5.3 couvre ce cas. En gros, il
doit les traiter normalement <emphasis>sauf</emphasis> les requêtes de
type PTR (résolution d'une adresse en nom). Dans ce cas, le serveur
doit extraire l'adresse du nom en <computer>ip6.arpa</computer>
(section 2.5 du <rfc num="3596" local="false"/>), regarder si cette
adresse correspond à un des préfixes qu'il gère et, si oui, le serveur
DNS64 a deux possibilités :
<enum>
<item>Répondre immédiatement, avec autorité, en utilisant un nom adapté (qui peut
être le même pour toutes les adresses, mettons <computer>locally-generated-ipv6-address-with-dns64.example.net</computer>). L'avantage est que les clients
DNS verront bien que l'adresse avait été synthétisée, l'inconvénient
est qu'on n'utilisera pas les informations qui pouvaient se trouver
dans le DNS,</item>
<item>Synthétiser les enregistrements PTR à partir de données trouvées
dans le DNS, comme il synthétise des enregistrements AAAA à partir des
A récupérés dans le DNS. Dans ce cas, le serveur DNS64 traduit
l'adresse IPv6 en IPv4, crée un nom dans
<computer>in-addr.arpa</computer>, fait une requête PTR et renvoie le
résultat au client.</item>
</enum></p>
<p>La section 6, sur le déploiement, est consacrée aux problèmes
pratiques qui pourront survenir lorsqu'on utilisera réellement
DNS64. Par exemple, si une machine est <foreign><wikipedia
name="Multi-homing">multi-homée</wikipedia></foreign>, il est possible
que seulement certaines de ses connexions à l'Internet passent par un
traducteur v4-v6. Il faudrait donc idéalement interroger des
résolveurs DNS différents selon l'interface de sortie, et considérer
les résultats comme locaux à l'interface.</p>
<p>Autre problème pratique, le cas d'une machine à double-pile qui
utiliserait DNS64, passant ainsi par le traducteur même lorsque ce
n'est pas nécessaire (section 6.3.2 et 6.3.3). Comme la configuration
par défaut des systèmes d'exploitation est de préférer IPv6 à IPv4, le
cas risque de se produire souvent. Il n'existe pas de moyen simple de
le détecter puisque, pour le client, un serveur DNS64 semble un
serveur comme un autre. Une machine double-pile (IPv4 et
IPv6) ne devrait donc pas utiliser de résolveur DNS64. Mais il peut y
avoir des cas où c'est nécessaire, par exemple si la machine
double-pile n'a une connectivité IPv4 que partielle. Dans ces
conditions, le serveur DNS64 doit exclure les préfixes IPv4 locaux de
la synthèse. On peut donc prévoir quelques problèmes de débogage amusants...</p>
<p>La section 7 décrit des exemples de déploiement, en utilisant les
scénarios du <rfc num="6144" local="true"/>. Par exemple, la section 7.1 cite le cas qui sera sans doute
le plus fréquent au début, une machine H1 réseau purement IPv6 (parce que arrivé
après l'<link local="epuisement-adresses-ipv4">épuisement des adresses
IPv4</link>) qui essaie de se connecter à un serveur H2 situé dans
l'Internet v4 traditionnel. Le traducteur T et le serveur DNS sont
configurés avec le préfixe bien connu
<computer>64:ff9b::/96</computer>. H1 va commencer par faire une
requête AAAA pour <computer>h2.example.com</computer>. Le résolveur
DNS ne trouve pas de AAAA pour ce nom, mais il récupère un
enregistrement de type A, <computer>192.0.2.1</computer>. Il fabrique
alors le AAAA <computer>64:ff9b::c000:201</computer> (qui peut aussi légitimement
s'écrire <computer>64:ff9b::192.0.2.1</computer>). H1 va alors envoyer
un paquet <wikipedia name="Transmission Control Protocol">TCP</wikipedia> <computer>SYN</computer> à
<computer>64:ff9b::c000:201</computer>. Le routeur/traducteur le voit
passer, note le préfixe NAT64 avec lequel il a été configuré et le
traduit en un paquet TCP/IPv4.</p>
<p>Autre exemple, en section 7.3. C'est à peu près l'inverse : une
machine dans un Internet passé presque entièrement en IPv6 essaie de
se connecter à un des derniers serveurs v4 existants. À noter que
DNS64 n'est pas indispensable dans ce cas : on peut simplement
affecter algorithmiquement une adresse IPv6 à toutes les adresses
IPv4, les publier sur des serveurs DNS normaux, et donc
n'utiliser que le traducteur. Toutefois, cette section cite quelques
cas où DNS64 peut être utile, par exemple si les adresses IPv4 sont
affectées dynamiquement.</p>
<p>Fondamentalement, un
serveur DNS64 est un menteur : il fabrique des réponses qui n'existent
pas (Twitter, utilisé dans l'exemple plus haut, n'a pas d'adresse IPv6
à ce jour...). Il a donc des problèmes avec
<wikipedia name="Domain Name System Security Extensions">DNSSEC</wikipedia>, qui a justement été conçu pour détecter
les mensonges. Toute la section 3 est consacrée à discuter ce
problème. Bien sûr, le résolveur DNS64 ment pour la bonne cause. Mais
DNSSEC est au delà du bien et du mal, il se moque des motivations, il
ne regarde que le résultat. Plusieurs cas peuvent se poser (le RFC en
identifie sept !) selon les options indiquées dans la requête DNS et
selon la configuration DNSSEC utilisée. Rappelons que les deux options
importantes pour DNSSEC dans une requête DNS sont le bit DO
(<foreign>DNSSEC OK</foreign>, <rfc num="4035" local="true"/>, section
3.2.1) qui indique si le client DNS comprend
les enregistrements DNSSEC et le bit CD (<foreign>Checking
Disabled</foreign>, <rfc num="4035" local="true"/>, section 3.2.2) qui indique au résolveur que le client fera la
validation lui-même et qu'il faut lui envoyer toute l'information,
même si elle s'avère fausse.</p>
<p>Les différents cas sont donc (je ne les ai pas tous mentionnés,
voir le RFC pour les détails) :
<enum>
<item>Un serveur DNS64 reçoit une requête où DO est à zéro (ce que
font aujourd'hui la plupart des bibliothèques de résolution de noms,
les <foreign>stub resolvers</foreign>). Aucun
problème dans ce cas, le client ne comprend pas DNSSEC, le serveur
DNS64 peut inventer tous les mensonges qu'il veut.</item>
<item>Un serveur DNS64 avec gestion de DNSSEC reçoit une requête avec
DO et CD mis à zéro (c'est typiquement le cas - rare - d'un client qui
veut valider lui-même). Dans ce cas, il doit passer au client toute l'information
obtenue. DNS64 ne marchera <emphasis>pas</emphasis> ici,  le client
n'acceptera pas le AAAA synthétisé comme étant valide. La seule
solution est que le client mette en &#x153;uvre DNS64 lui-même.</item>
<item>Un serveur DNS64 qui valide avec DNSSEC reçoit une requête avec
DO à un et CD à zéro (ce sera sans doute le cas le plus courant dans
le futur). Aucun problème, le serveur DNS64 valide les données
récupérées et répond SERVFAIL (<foreign>Server Failure</foreign>) si
cette validation échoue. Le AAAA synthétisé n'est pas validé avec
DNSSEC mais le client ne le saura pas. Si le bit DO était mis à un, le
serveur DNS64 a juste à mettre le bit AD (<foreign>Authentic
Data</foreign>) à un dans sa réponse (un mensonge pour la bonne
cause ; après tout, si le client DNS n'a pas mis CD à un, c'est qu'il
fait complètement confiance au résolveur).</item>
</enum>
La section 5.5 donne les détails sur le fonctionnement de DNSSEC dans
DNS64. La section 6.2 rappelle les problèmes pratiques de déploiement
de DNS64 si on utilise déjà DNSSEC.</p>
<p>DNS64 pose t-il des problèmes de sécurité ? Pas beaucoup, dit la section
8. Comme indiqué (paragraphes précédents), il peut interférer avec DNSSEC. Et, surtout, il
impose une coordination entre le serveur DNS64 et le traducteur. Si un
attaquant peut modifier la valeur du préfixe du serveur DNS64, il peut
envoyer les paquets où il veut. Donc, attention, la sécurité du
serveur DNS64 est exactement aussi importante que celle du traducteur.</p>
<p>Enfin, l'annexe A explique des motivations pour générer un AAAA alors
qu'il existe déjà. Il se peut que la meilleure route passe plutôt par
le traducteur et donc, dans certains cas, un serveur DNS64 peut offrir
à son administrateur la possibilité de permettre la synthèse
d'enregistrements AAAA même quand un vrai existe.</p>
<p>BIND met en &#x153;uvre DNS64 depuis les versions 9.7.3 et
9.8.0. Voici un exemple de configuration de DNS64 avec une 9.8.0 :
<code>
acl me {
    ::1/128; 127.0.0.0/8;
};
acl rfc1918 { 
    10/8; 192.168/16; 172.16/12; 
};

options {
       ...
       dns64 64:ff9b::/96 { // The well-known prefix
              clients { me; };
              mapped { !rfc1918; any; }; // Never synthetize AAAA records
                     // for private addresses
              exclude { 64:ff9b::/96; ::ffff:0000:0000/96; }; // If the retrieved
              // AAAA record is in that range, do not send it back to the user,
              // synthetize a AAAA.
              //
              // suffix ::42; // Trailing bits. Require some free space (here, 
              // 96 + 32 bits leave no room for trailing bits).
        };
</code>
Le premier préfixe est celui des AAAA synthétisés (ici, le préfixe
bien connu). La directive <computer>clients</computer> réduit le
service DNS64 à certaines machines seulement (celles qui sont
connectées via un traducteur NAT64, relisez les sections 6.3.2 et
6.3.3 du RFC). La directive <computer>mapped</computer> met en
&#x153;uvre la règle d'exclusion des préfixes IPv4 locaux (ici, ceux
du <rfc num="1918" local="true"/>). La directive
<computer>exclude</computer> implémente la règle d'exclusion des
préfixes IPv6 qui ne devraient même pas être mis dans le DNS
global. S'il existe un AAAA, mais qu'il pointe vers un des ces
préfixes, il sera remplacé par un AAAA synthétique. Enfin, la
directive <computer>suffix</computer> permet d'ajouter quelques bits à
la fin du AAAA de synthèse (mais, ici, avec 96 bits pour le préfixe
IPv6 et 32 pour l'adresse IPv4, il n'y a plus de place).</p>
<p>
Voici l'effet du serveur ayant la configuration ci-dessus (il écoute
sur le port 9053) :
<code>
[Adresse IPv6 déjà dans le DNS global.]
% dig +short -p 9053 @::1 AAAA www.ietf.org 
2001:1890:1112:1::20

[Pas d'adresse IPv6 dans le DNS global mais trois adresses IPv4.]
% dig +short -p 9053 @::1 AAAA facebook.com
64:ff9b::453f:bd0b
64:ff9b::453f:bd10
64:ff9b::453f:b50c

[Les requêtes PTR marchent bien, BIND synthétise un CNAME, une des
deux techniques permises par le RFC.]
% dig  -p 9053 @::1 -x 64:ff9b::453f:bd10      
...
;; QUESTION SECTION:
;0.1.d.b.f.3.5.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.9.f.f.4.6.0.0.ip6.arpa. IN PTR

;; ANSWER SECTION:
0.1.d.b.f.3.5.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.9.f.f.4.6.0.0.ip6.arpa. 600 IN CNAME 16.189.63.69.in-addr.arpa.
16.189.63.69.in-addr.arpa. 7172 IN      PTR     www-11-01-ash2.facebook.com.
...

[Ici, le nom a une adresse IPv4 mais privée. L'ACL 'rfc1918' va donc
la bloquer.]
% dig +short -p 9053 @::1 A ciel.administratif.prive.nic.fr                  
10.1.84.200

% dig  -p 9053 @::1 AAAA ciel.administratif.prive.nic.fr                         
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0
                              ^^^^^^^^^
</code>
</p>
<p>Pour comparer, voici une configuration BIND avec un préfixe du FAI
(NSP pour <foreign>Network-Specific Prefix</foreign>). Plus court que
le précédent, il dégage de la place pour le suffixe :
<code>
       dns64 2001:db8:666::/48 { // A Network-Specific Prefix (NSP).
              clients { me; };
              suffix ::42; // Trailing bits.
        };
</code>
Et voici les résultats :
<code>
% dig +short -p 9053 @::1 AAAA facebook.com
2001:db8:666:453f:bd:1000:0:42
2001:db8:666:453f:b5:c00:0:42
2001:db8:666:453f:bd:b00:0:42
</code>
Si vous voulez manipuler les adresses vous-même, voici un joli script
<wikipedia>awk</wikipedia> dû à <link
url="http://twitter.com/gbfo">gbfo</link>, pour traduire les adresses
IPv6 en la v4 correspondant :
<code>
% echo 64:ff9b::453f:bd0b | \
        awk -F: '{h=strtonum("0x" $(NF-1));l=strtonum("0x" $NF);printf("%d.%d.%d.%d\n",h/256,h%256,l/256,l%256);}' 
69.63.189.11
</code>
<!-- Ou bien 64:ff9b::c086:445 en 192.134.4.69 TODO: le refaire en Python--></p>
<p>Question mises en &#x153;uvre de DNS64, outre le cas de BIND, déjà
présenté, il existait une <wikipedia name="Patch (informatique)">rustine</wikipedia> pour
<wikipedia xml:lang="en" name="Unbound (DNS Server)">Unbound</wikipedia>, <link
url="http://ecdysis.viagenie.ca/download.html">chez Viagénie</link>
(avec un très ennuyeux système de formulaire à remplir pour
l'obtenir). Cette rustine porte sur une version ancienne du protocole,
mais Unbound a désormais DNS64 en série.
Il y a aussi <link url="http://ecdysis.viagenie.ca/download.html">au même endroit</link> un serveur DNS64 autonome, écrit en
<wikipedia name="Perl (langage)">Perl</wikipedia>. Ce dernier est très court et peut donc
être un bon moyen de comprendre le protocole, pour ceux qui aiment
lire le <wikipedia>code source</wikipedia>. Enfin, <link
url="http://gblogs.cisco.com/fr-ipv6/2012/01/26/cnr-supporte-dns64/">Cisco
a désormais DNS64</link> sur ses produits.</p>
<p>Voici un exemple de configuration Unbound pour un serveur DNS64 :
<code>
server:
   module-config: "dns64 validator iterator"
   dns64-prefix: 64:ff9b::0/96
</code></p>
<p>Et mon opinion personnelle sur DNS64 ? Je dirais que, certes, c'est un <foreign><wikipedia>hack</wikipedia></foreign>, mais
qu'on a vu pire et que ça traite un vrai problème. DNS64 semble bien pensé, rien n'est oublié et le <wikipedia name="Request for comments">RFC</wikipedia> parle bien de tous
les problèmes, notamment avec DNSSEC.</p>
<p>Pour un récit très détaillé, avec plein de technique, d'un test de
NAT64 avec DNS64, voir l'article de Jérôme Durand « <link
url="http://gblogs.cisco.com/fr-ipv6/2011/09/26/jai-teste-pour-vous-stateful-nat64-avec-dns64/">J'ai
testé pour vous : Stateful NAT64 avec DNS64</link> ».</p>
   <p>Notez qu'il existe des résolveurs DNS publics ayant DNS64
   (évidemment uniquement avec le préfixe bien connu), comme celui de
   Hurricane Electric, <computer>nat64.he.net /
   2001:470:64::1</computer> ou celui de Google,
   <computer>google-public-dns64-b.google.com /
   2001:4860:4860::6464</computer>.</p>
</content>
</rfcdesc>
