Les RFC (Request For Comments) sont les documents de référence de l'Internet. Produits par l'IETF pour la plupart, ils spécifient des normes, documentent des expériences, exposent des projets...
Leur gratuité et leur libre distribution ont joué un grand rôle dans le succès de l'Internet, notamment par rapport aux protocoles OSI de l'ISO organisation très fermée et dont les normes coûtent cher.
Je ne tente pas ici de traduire les RFC en français (un projet pour cela existe mais je n'y participe pas, considérant que c'est une mauvaise idée), mais simplement, grâce à une courte introduction en français, de donner envie de lire ces excellents documents.
Le public visé n'est pas le gourou mais l'honnête ingénieur ou l'étudiant.
Date de publication du RFC : Août 1996
Auteur(s) du RFC : Masataka Ohta (Computer Center Tokyo Institute of Technology)
Chemin des normes
Première rédaction de cet article le 28 Septembre 2010
Le mécanisme standard de transfert d'une zone
DNS entre deux serveurs faisant autorité
(depuis le maître vers l'esclave) est normalement le transfert de
zones, dit AXFR, aujourd'hui normalisé dans le RFC 5936. Ce mécanisme convient parfaitement aux « petites
zones » (de quelques centaines d'enregistrement au plus) mais achoppe,
par exemple,
lorsqu'un « gros » TLD veut pousser les
changements du jour (ou de l'heure) vers tous ses esclaves. En raison,
entre autre, de l'anycast,
certains de ces esclaves sont situés dans des endroits pas très bien
connectés (comme l'île de la Réunion) et l'envoi d'un fichier de la taille de celui de
.fr (aujourd'hui, 1,8 millions de domaines
et 190 Mo) peut prendre du temps. On peut transférer les zones par
d'autres moyens que le DNS, par exemple
rsync. Mais il existe une solution DNS standard
(qui est celle utilisée par .fr), IXFR
(Incremental Zone Transfer), normalisée dans ce
RFC 1995.
Le principe est simple et résumé en section 2 du RFC. Lorsqu'un
client veut un transfert (typiquement, parce qu'il est esclave et a
appris que sa version de la zone était en retard), il envoie un
message DNS de type IXFR (code 251, AXFR étant 252, cf. http://www.iana.org/assignments/dns-parameters) au maître qui lui transmet alors uniquement
les nouveaux enregistrements. Le serveur IXFR (le maître) doit donc
garder trace des changements entre les différentes versions, pour ne
transmettre que ces changements (BIND ne le
fait, par défaut, que si on utilise les mises à jour dynamiques du
RFC 2136 ; autrement, il faut ajouter l'option
ixfr-from-differences yes;). À noter qu'un
serveur IXFR a toujours le droit de renvoyer la zone complète, par
exemple si le client a un numéro de version trop vieux, ne
correspondant plus à une version qui avait été gardée (voir la section
5).
Comme la réponse IXFR a des chances d'être de petite taille, le serveur a même le droit de répondre en UDP. Autrement, on utilise TCP, comme avec AXFR. Donc, l'algorithme recommandé est, pour le client, d'essayer en UDP d'abord, puis TCP.
La requête IXFR a le format DNS standard (section 3), la section Autorité contenant le SOA de la version courante chez le client. La réponse (section 4) ressemble beaucoup à une réponse AXFR. Elle est composée de séquences, chaque séquence commençant par l'ancien SOA, puis comportant les enregistrements supprimés, puis le nouvel enregistrement SOA, indiquant la version actuelle sur le maître, puis enfin les enregistrements ajoutés. Les séquences sont classés chronologiquement donc on peut voir la réponse IXFR comme un historique des changements. À noter que ce sont bien des enregistrements qui sont transmis, pas des RRsets. Si on a :
foobar IN NS ns1.example.net.
IN NS ns3.example.net.
et qu'on ajoute un serveur ns2.example.net, seul
l'enregistrement NS de ce serveur aura besoin d'être transmis, pas les
trois enregistrements du nouveau RRset.
La réponse commence, comme pour AXFR, par le SOA de la version locale du serveur mais le client peut savoir si sa demande IXFR a reçu une réponse IXFR ou AXFR en examinant le second enregistrement : si la réponse est incrémentale (IXFR), ce second enregistrement est un SOA.
Naturellement, le client IXFR ne doit mettre à jour sa copie locale qu'une fois qu'il a reçu tous les enregistrements. (Dit autrement, IXFR doit être atomique.)
La section 5 spécifie le comportement d'un serveur IXFR pour ce qui concerne les vieilles versions : il n'est évidemment pas obligé de les garder toutes et peut donc supprimer les plus anciennes, pour gagner de la place. C'est d'autant plus important qu'au bout d'un moment, les changements s'accumulant, la réponse IXFR deviendra plus longue que la réponse AXFR ! Remarquons aussi (section 6) que la réponse incrémentale n'est pas forcée de refléter l'histoire exacte des changements : un serveur a le droit de condenser plusieurs changements successifs en un seul. (Les exemples de la section 7 incluent une telle condensation.)
Voyons maintenant un exemple de mise en œuvre, entre deux
BIND 9.7. Deux serveurs font autorité pour
.fr. Sans IXFR, le transfert prend une
demi-minute sur un Ethernet à 100 M/s (et bien
plus longtemps avec des serveurs mal connectés au bout du monde ; il
ne faut pas oublier que .fr a un serveur à
Katmandou, un à Manille,
etc). Sur le
maître, on voit :
28-Sep-2010 10:54:35.388 client 192.0.2.97#56385: transfer of 'fr/IN': AXFR started 28-Sep-2010 10:55:00.162 client 192.0.2.97#56385: transfer of 'fr/IN': AXFR ended
Et sur l'esclave (tous les serveurs utilisent le port 9053, pour des
tests, et pas le port standard 53 ; ainsi, le serveur esclave est configuré
avec masters { 192.0.2.69 port 9053; };) :
28-Sep-2010 10:55:00.182 transfer of 'fr/IN' from 192.0.2.69#9053: \
Transfer completed: 2699 messages, 3965064 records, \
106151552 bytes, 24.857 secs (4270489 bytes/sec)
(Notez au passage que ce sont des enregistrements binaires DNS qui sont transférés, pas un fichier texte, ce qui explique la taille totale plus petite.)
Pour activer IXFR sur la maître, on modifie la configuration du
serveur avec ixfr-from-differences yes; dans la directive
zone :
zone "fr" {
type master;
file "fr";
ixfr-from-differences yes;
};
On ne change rien sur le client IXFR : avec BIND, le client essaie IXFR par défaut. Sur le maître, le transfert est quasi-instantané :
28-Sep-2010 11:05:47.103 client 192.0.2.97#54496: transfer of 'fr/IN': IXFR started 28-Sep-2010 11:05:47.103 client 192.0.2.97#54496: transfer of 'fr/IN': IXFR ended
ce que confirme le journal de l'esclave, à qui il a suffi de transférer dix changements :
28-Sep-2010 11:05:47.049 transfer of 'fr/IN' from 192.0.2.69#9053: \
Transfer completed: 1 messages, 10 records, \
334 bytes, 0.004 secs (83500 bytes/sec)
(Note au passage : pour prévenir un serveur esclave de test, qui ne
reçoit pas les NOTIFY du RFC 1996, qu'un changement a
eu lieu chez le maître, le plus simple est d'envoyer un
NOTIFY forcé. BIND ne permet pas de le faire
facilement mais, si on a
nsd, il suffit de faire un nsd-notify -p 9053 -z
fr NOM-SERVEUR).
On peut aussi admirer le transfert incrémental avec
tshark (l'option -d est
nécessaire car on utilise un port alternatif). Un
domaine a été ajouté, un autre retiré (les deux domaines avaient le
même jeu de serveur) :
% tshark -d tcp.port==9053,dns -d udp.port==9053,dns -r ixfr.pcap
...
3 0.001347 192.0.2.97 -> 192.0.2.69 DNS Standard query SOA fr
4 0.001455 192.0.2.69 -> 192.0.2.97 DNS Standard query response SOA nsmaster.nic.fr
...
10 0.002930 192.0.2.97 -> 192.0.2.69 DNS Standard query IXFR fr
...
12 0.003089 192.0.2.69 -> 192.0.2.97 DNS Standard query response \
SOA nsmaster.nic.fr \
SOA nsmaster.nic.fr NS ns1.example.net NS ns3.example.net \
SOA nsmaster.nic.fr NS ns1.example.net NS ns3.example.net \
SOA nsmaster.nic.fr
On y voit bien le test initial du SOA, puis la requête du client, puis
une séquence composée d'une partie « retrait » et d'une partie « ajouts ».
Le fichier pcap complet est sur pcapr, en http://www.pcapr.net/view/bortzmeyer+pcapr/2010/8/2/6/ixfr.pcap.html.
Si le serveur refuse ou ne peut pas faire un transfert incrémental, le maître BIND indiquera :
28-Sep-2010 10:48:04.007 client 192.0.2.97#45524: transfer of 'fr/IN': AXFR-style IXFR started 28-Sep-2010 10:48:29.802 client 192.0.2.97#45524: transfer of 'fr/IN': AXFR-style IXFR ended
Et l'esclave recevra la totalité de la zone.
Les tests ici ont été faits avec BIND. Et avec nsd ? Il ne peut être qu'esclave : un maître nsd ne sait pas servir des transferts incrémentaux. Lorsque nsd est esclave, il essaie IXFR (en TCP par défaut mais on peut le configurer pour utiliser UDP) puis AXFR. (Il semble qu'il n'envoie pas de requête SOA avant la demande IXFR, la ligne 3 dans la trace Wireshark plus haut ; ce n'est en effet pas imposé par le RFC, puisque l'IXFR contient déjà le numéro de série connu du client.) On peut aussi lui demander de ne pas tenter IXFR :
zone:
name: "langtag.net"
...
request-xfr: AXFR 192.134.7.248 mykey
Ici, en raison du mot-clé AXFR, le serveur
esclave ne tentera pas de faire de l'IXFR. Le même réglage, pour BIND,
ne peut être que global au serveur (dans le bloc
options, request-ixfr no;).
Le fait qu'un serveur puisse répondre à une demande IXFR par une
copie complète de la zone peut être gênant dans certains cas. À la
réunion IETF 75 de
Stockholm en juillet 2009 a été présentée la
proposition IXFR only
(Internet-Draft draft-kerr-ixfr-only)
qui normalisait un nouveau type de requête « IXFR seul » mais qui n'a
pas encore été sérieusement pris en considération.
Date de publication du RFC : Août 1996
Auteur(s) du RFC : IAB & IESG
Pour information
Première rédaction de cet article le 22 Septembre 2005
Un RFC très politique, que ce 1984 qui s'attaque aux restrictions d'usage à la cryptographie. Au moment où il est sorti, la cryptographie était de fait interdite en France (et la situation, si elle s'est améliorée, est encore loin d'être parfaite). Et les États-Unis restreignaient très sévèrement l'exportation de logiciels cryptographiques (là encore, ces restrictions n'ont pas complètement disparu).
Le RFC prend nettement position : l'IAB et l'IESG, ensemble, affirment que la cryptographie forte (pas les systèmes ultra-bridés qui étaient proposés à l'époque avec les navigateurs Web) est indispensable à la sécurité de l'Internet, qu'il n'existe aucune autre méthode réaliste d'assurer une sécurité raisonnable sur un réseau ayant l'architecture de l'Internet et que cette sécurité ne doit pas être sacrifiée aux intérêts des polices et des services secrets.
Le RFC se penche aussi sur des cas plus techniques, comme sur les clés cryptographiques ne servant qu'à la signature, qui ne devraient jamais faire l'objet d'un dépôt de séquestre, puisqu'il n'existe aucune raison légitime de les "saisir".
Ce RFC dont le numéro ne doit rien au hasard, a marqué une étape dans la construction politique de l'Internet.
Date de publication du RFC : Août 1996
Auteur(s) du RFC : Jack McCann (Digital Equipment Corporation), Stephen E. Deering (Xerox Palo Alto Research Center), Jeffrey Mogul (Digital Equipment Corporation, Western Research Laboratory)
Chemin des normes
Première rédaction de cet article le 16 Décembre 2007
Ce RFC est l'adaptation à IPv6 du protocole décrit dans le RFC 1191, protocole qui permet de découvrir la MTU du chemin entre deux machines reliées par Internet.
Avec IPv4, déterminer la MTU maximale du chemin est très utile pour optimiser les performances. Mais elle devient presque indispensable en IPv6, où les routeurs n'ont pas le droit de fragmenter les paquets trop gros (toute fragmentation doit être faite dans la machine de départ). PMTU fait donc quasi-obligatoirement partie d'IPv6 (une alternative est de n'envoyer que des paquets suffisamment petits pour passer partout).
L'algorithme est le même qu'en v4, envoyer des paquets, et voir si on reçoit des paquets ICMP Datagram too big qui contiennent en général la MTU maximale du lien suivant. (Pas de bit DF - Don't fragment - en IPv6 puisque la fragmentation n'est possible qu'à la source. L'annexe A détaille les différences avec l'algorithme IPv4 décrit dans le RFC 1191.)
Comme avec IPv4, l'algorithme PMTU marche mal en pratique car beaucoup de sites filtrent stupidement tous les paquets ICMP et la machine qui tente de faire de la Path MTU discovery n'aura jamais de réponse. IPv6, comme IPv4, devra donc sans doute utiliser la nouvelle technique du RFC 4821
(Un excellent article très complet sur la question est A Tale of Two Protocols: IPv4, IPv6, MTUs and Fragmentation.)
Date de publication du RFC : Février 1996
Auteur(s) du RFC : Yakov Rekhter (Cisco systems), Robert G. Moskowitz (Chrysler Corporation), Daniel Karrenberg (RIPE NCC), Geert Jan de Groot (RIPE NCC), Eliot Lear (Silicon Graphics)
Première rédaction de cet article le 1 Novembre 2007
Depuis longtemps, le manque d'adresses IPv4 se fait sentir. Pour obtenir ces précieuses adresses, il faut remplir de longs documents à envoyer au RIR, ou bien payer son FAI pour une offre « pro » ou n'importe quel autre qualificatif indiquant que, entre autres, on aura d'avantage d'adresses, peut-être un /29 au lieu d'un simple /32 (cf. RFC 2050). D'où la demande pour un stock d'adresses IPv4 privées, non annoncées sur l'Internet et non uniques globalement, mais dans lequel on pourrait piocher à loisir. C'est ce que propose ce RFC, certainement un des plus cités, le "1918" étant devenu synonyme de ressource privée.
Ce RFC est court et pourrait se contenter de lister (section 3) les trois préfixes privés réservés :
Et les bases des RIR, accessibles via whois, reflètent bien cette réservation à l'IANA :
% whois 10.42.0.1 OrgName: Internet Assigned Numbers Authority OrgID: IANA Address: 4676 Admiralty Way, Suite 330 City: Marina del Rey StateProv: CA PostalCode: 90292-6695 Country: US NetRange: 10.0.0.0 - 10.255.255.255 CIDR: 10.0.0.0/8 NetName: RESERVED-10 NetHandle: NET-10-0-0-0-1 Parent: NetType: IANA Special Use NameServer: BLACKHOLE-1.IANA.ORG NameServer: BLACKHOLE-2.IANA.ORG Comment: This block is reserved for special purposes. Comment: Please see RFC 1918 for additional information. Comment: RegDate: Updated: 2002-09-12 ...
Mais l'idée même d'adresses IP privées ne s'est pas imposée sans mal. Un des
principes d'architecture de l'Internet est en effet la
connectivité de bout en bout. Toute machine peut
parler directement à toute autre. C'est l'une des grandes innovations
de l'Internet, tous les réseaux concurrents à l'époque (années 1970 et
80) n'envisageaient que des réseaux isolés. Or, s'il existe des
adresses privées, elles ne sont pas globalement
uniques. Deux machines sur des sites différents peuvent
avoir la même adresses 192.168.1.1. Cela remet donc en cause le modèle
de base et le prédécesseur de notre RFC, le RFC 1597 avait
été fortement critiqué, notamment dans le RFC 1627,
intitulé Network 10 Considered Harmful.
Notre RFC détaille donc aussi, dans ses sections 2 et 4, les motivations de ces adresses privées et explique pourquoi on ne peut pas s'en passer.
Si la poussière soulevée par le débat est bien retombée par la suite, c'est parce qu'on envisageait un déploiement rapide d'IPv6 qui règlerait le problème, grâce à son abondance d'adresses. Ce déploiement ne s'étant pas (encore ?) produit, notre RFC et ses adresses privées continuent à bénéficier d'un grand succès.
Ce succès s'étend même à des domaines non prévus, comme la
documentation, qui devrait normalement utiliser 192.0.2.0/24
(cf. RFC 5737).
Pourquoi ces trois préfixes-là et pas d'autres ? Pour
10.0.0.0/8 la raison semble connue mais pas pour les
autres.
Parfois, ces adresses privées « sortent » même, par accident, du réseau local où elles auraient dû rester confinées, malgré la section 5 du RFC qui explique qu'il ne faut pas le faire. On doit donc prendre soin de les filtrer. Les règles d'ACL d'un coupe-feu commencent souvent par quelque chose du genre (ici, des règles de Netfilter dans le noyau Linux) :
Chain norfc1918 (2 references) target prot opt source destination rfc1918 all -- 172.16.0.0/12 0.0.0.0/0 rfc1918 all -- 192.168.0.0/16 0.0.0.0/0 rfc1918 all -- 10.0.0.0/8 0.0.0.0/0 ... Chain rfc1918 (6 references) target prot opt source destination LOG all -- 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 6 prefix `Shorewall:rfc1918:DROP:' DROP all -- 0.0.0.0/0 0.0.0.0/0
(Dans le cas ci-dessus, les règles sont ajoutées automatiquement par Shorewall.)
De même, un routeur BGP refuse en général de ses pairs des annonces pour ces préfixes (ici, la syntaxe d'IOS) :
! http://www.cymru.com/Bogons/index.html ! Deny any packets from the RFC 1918 netblocks to block ! attacks from commonly spoofed IP addresses. access-list 2010 remark Anti-bogon ACL ! Bogons access-list 2010 deny ip 10.0.0.0 0.255.255.255 any log-input access-list 2010 deny ip 172.16.0.0 0.15.255.255 any log-input access-list 2010 deny ip 192.168.0.0 0.0.255.255 any log-input
Et le nombre de serveurs DNS faisant des
requêtes de type PTR pour ces adresses, et fatiguant ainsi pour rien
les serveurs de in-addr.arpa, a nécessité le déploiement d'un
système dédié pour les absorber, l'AS112.
Aujourd'hui, le petit réseau local typique a donc presque toujours des adresses tirées du RFC 1918, un routeur NAT et/ou des relais applicatifs et une seule adresse IP publique, attribuée par le FAI.
Date de publication du RFC : Janvier 1996
Auteur(s) du RFC : Christopher Davis (Kapor Enterprises, Inc.), Paul Vixie (Vixie Enterprises), Tim Goodwin (Public IP Exchange Ltd (PIPEX)), Ian Dickinson (FORE Systems)
Expérimental
Première rédaction de cet article le 24 Mai 2006
Ce n'est pas une question de vie ou de mort pour l'Internet mais il est quand même bien agréable de pouvoir spécifier la localisation physique d'une machine, en indiquant sa latitude et sa longitude. Notre RFC permet de le faire dans le DNS.
Les applications possibles sont nombreuses : un
traceroute un peu plus explicite,
par exemple, ou bien un lien direct vers Google
Maps ou encore le guidage automatique d'un missile intercontinental vers sa cible. Une
mise en œuvre complète du RFC, en logiciel libre, se trouve dans
le répertoire contrib/query-loc de
BIND (à partir de la version 9.3).
Le système fonctionne avec des enregistrements de type LOC. Voici
un exemple pour nic.af :
% dig +short LOC nic.af. 34 31 0.000 N 69 12 0.000 E 1000.00m 1000m 10000m 10m
qui nous indique que le NIC afghan se trouve à 34°31 de latitude Nord et 69°12 de longitude Est (soit à Kaboul). Les chiffres supplémentaires dans l'enregistrement indiquent la précision, y compris en hauteur.
www.bortzmeyer.org n'a pas aujourd'hui
d'enregistrement LOC. La zone est gérée par le
registrar, Gandi, via une interface qui ne
permettait pas ce type de données. C'est désormais possible (LOC est
un des choix possibles lors de l'édition de la zone sur le Web de
Gandi) mais l'interface est peu pratique (il faut tout calculer soi-même) donc cela atttendra.
Notre RFC permet aussi de trouver un enregistrement LOC à partir
d'une adresse IP. Par exemple, pour 130.104.3.1
:
0.0.104.130.in-addr.arpa nous mène vers
uclouvain.sri.ucl.ac.be),En pratique, notre RFC n'a pas été un grand succès. Très peu d'enregistrements de type LOC se trouvent aujourd'hui dans Internet, ce qui réduit l'intérêt des applications qui les utilisent. Si on veut faire de la géolocalisation, il faut donc plutôt compter sur des bases de données plus ou moins informelles et de plus ou moins bonne qualité, souvent obtenues à partir des bases des RIR.
On trouvera plus de détails sur les enregistrements LOC en http://www.ckdhr.com/dns-loc ou en http://blog.fupps.com/2010/11/14/where-is-your-dns-server-located/. Il existe des services sur le Web qui transforment un nom de domaine en carte, en utilisant les enregistrements LOC, comme http://idefix.net/~koos/kismet/loc2map.php ou http://hewgill.com/tools/dnsloc.
Date de publication du RFC : Juin 1995
Auteur(s) du RFC : Fred Baker (Cisco Systems)
Chemin des normes
Première rédaction de cet article le 31 Octobre 2007
Un RFC de synthèse, qui rassemble tout ce que le fabricant d'un routeur IP doit savoir, parmi tous les RFC dispersés. L'idée était bonne mais, n'ayant jamais été mis à jour, ce RFC contient également pas mal de choses dépassées.
Créer un nouveau routeur IP est un gros travail, en partie parce qu'il faut lire des dizaines de RFC différents, sans avoir de vision d'ensemble et sans toujours pouvoir déterminer facilement ce qu'on doit faire et ce qui est facultatif. D'où l'idée de RFC de synthèse, comme celui-ci pour les routeurs (il succède au RFC 1716) ou comme le RFC 1123 pour les machines « terminales ». Mais, si le principe est bon, l'actualisation d'un tel document s'est révélée difficile. L'IETF travaillant sur la base du volontariat et la mise à jour de grosses synthèses étant moins intéressante que la création de nouveaux protocoles, le RFC a pris sérieusement la poussière. Officiellement, seul le RFC 2644 le modifie mais, en pratique, d'autres points de notre RFC semblent bien dépassés aujourd'hui. Par exemple, rares sont encore les équipements qui utilisent les paquets ICMP de répression de la source (Source Quench, section 4.3.3.3) car ces paquets facilitent trop les DoS. Même chose pour le routage dirigé par la source (source routing).
Ce RFC fait 175 pages et est donc un gros morceau à lire (mais on ne crée pas un nouveau routeur tous les jours). C'est néanmoins une excellente source d'information pour quiconque s'intéresse au fonctionnement réel des réseaux informatiques.
Il commence par rappeler quelques principes généraux (sections 1 et 2), notamment le fait que ce RFC ne remplace pas les RFC standardisant tel ou tel protocole ou comme le principe de robustesse, Be conservative in what you do, be liberal in what you accept from others ou, dit autrement, « Ne faites pas le malin, essayez de coopérer avec les autres, pas de leur prouver qu'ils ont tort ». La section 2, sur l'architecture de l'Internet, est une bonne source sur ce sujet, recommandée à ceux qui apprennent comment fonctionne Internet. Puis chaque section est consacrée à une couche particulière, la section 3 à la couche 2, deux sections, 4 et 5, à la couche 3 (la section 5 s'occupant spécifiquement des cas où le paquet est transmis - forwarding), etc. La section 7, qui concerne la couche application s'occupe notamment des protocoles de routage.
Ainsi, pour citer quelques exemples des règles que pose ce RFC :
Comme noté au début, le RFC n'a jamais été mis à jour donc il ne faut pas espérer y trouver d'informations sur les techniques apparues depuis, comme le NAT ou IPv6.
Date de publication du RFC : Avril 1995
Auteur(s) du RFC : Christian Huitema (INRIA, Sophia-Antipolis), Jon Postel (USC/Information Sciences Institute), Steve Crocker (CyberCash, Inc.)
Pour information
Première rédaction de cet article le 14 Décembre 2006
En effet, chaque RFC a un statut, disponible en ligne ou dans
le fichier texte en ftp://ftp.rfc-editor.org/in-notes/rfc-index.txt. Il peut être
(liste non limitative) :
http://www.rfc-editor.org/rfcxx00.html,Le RFC 791, sur IP est évidemment Full standard (un statut très rare), comme le RFC 1034 sur le DNS ou le RFC 5234 sur ABNF. Le RFC 2821 sur SMTP n'est que proposed standard (probablement parce que personne n'a passé son temps à argumenter pour son avancement). Et notre RFC 1796 lui-même n'est que informational.
Date de publication du RFC : Décembre 1994
Auteur(s) du RFC : Tim Berners-Lee (CERN, World-Wide Web project), Larry Masinter (Xerox PARC), Mark McCahill (University of Minnesota)
Intérêt historique uniquement
Première rédaction de cet article le 24 Janvier 2008
En même temps qu'étaient normalisés les URI, dans le RFC 1630, un effort était en cours pour normaliser leurs prédécesseurs, les URL et cet effort a donné ce RFC.
Ce RFC a aujourd'hui essentiellement un intérêt historique, puisque
la spécification des URI, RFC 3986, le
remplace en grande partie. Il a gardé longtemps son intérêt (et son
statut de norme, désormais perdu) du fait qu'il normalisait certains
plans d'URL comme
news:. Ceux-ci sont désormais dans le RFC 5538.
Les URL sont issus du travail dont le cahier des charges est décrit
dans le RFC 1737. Contrairement aux URI, plus généraux, ils
sont supposés ne servir que lorsqu'on connait la localisation exacte
d'une ressource, de façon à pouvoir la récupérer, ou la mettre à jour
(section 2). En pratique, la distinction n'est pas évidente. Certains
URL ne donnent pas de moyen de récupérer une ressouce (comme
news: que spécifie notre RFC ou bien
mailto:, désormais dans le RFC 6068). Et
même des URL de plan http: peuvent être utilisés
uniquement pour identifier, pas pour récupérer une ressource (c'est
notamment courant dans le monde XML).
Notre RFC décrit donc la syntaxe des URL (sections 2.1 et 5), bien connue désormais qu'on voit des URL même sur le flanc des autobus, et leur encodage (section 2.2, où est documentée la très mauvaise décision d'encoder les octets et pas les caractères Unicode).
La section 3 décrit ensuite les éléments communs à tous les URL
(comme la syntaxe host:port), puis des plans
(scheme) pour plusieurs catégories d'URL. Ces plans
ont presque tous été mis à jour dans des RFC ultérieurs mais certains
restent normalisés uniquement ici comme ftp:.
On trouve des plans très
utilisés comme le célébrissime http:, section 3.3
(désormais dans la section 3.2 du RFC 2616), mais aussi d'autres désormais dépassés comme son défunt
concurrent gopher: (section 3.4, désormais dans le RFC 4266) ou comme l'ancêtre wais:
(section 3.9, officiellement abandonné par le RFC 4156).
Le schéma news:, section 3.6, permet
de récupérer un article d'Usenet sans indiquer
de nom de serveur NNTP.
L'IANA maintient le registre de ces plans.
On notera que notre RFC 1738 normalisait également un
mécanisme pour décrire un URL au milieu de texte brut, en utilisant un
préfixe défini dans l'annexe A,
<URL:http://www.bortzmeyer.org/1738.html>.
Ce mécanisme n'a pas eu de succès et a officiellement été abandonné
par le RFC 3986, annexe C.
Date de publication du RFC : Décembre 1994
Auteur(s) du RFC : Karen Sollins (MIT Laboratory for Computer Science), Larry Masinter (Xerox Palo Alto Research Center)
Pour information
Première rédaction de cet article le 18 Mars 2007
À une époque où le Web était récent, où le navigateur Mosaic venait de sortir et où les experts expliquaient doctement que ce truc, cet Internet n'avait aucun avenir, ce RFC est le premier à avoir mentionné les URN, dans la quête de l'identificateur parfait.
Le Web avait commencé avec les URL mais, pour diverses raisons, ils ne donnaient pas totale satisfaction. De chaudes discussions agitaient la liste uri@bunyip.com. Plusieurs personnes ayant dit « Il faudrait qu'on aie des URN à la place des URL », ce travail a mené à ce RFC.
L'optique est nettement de remplacer les URL, pas seulement de les compléter, puisque dès l'introduction, un URN est défini comme un identificateur unique au niveau mondial,permanent, et fournissant l'accès à une ressource (contrairement à des identificateurs comme les tags du RFC 4151 qui sont juste des identificateurs et ne prétendent pas fournir d'accès).
Il exprime donc le cahier des charges pour les URN, qui ne seront normalisés que plus tard. Idéalement, dit notre RFC, les URN devraient être :
À noter que ce RFC était plutôt en retard en matière d'internationalisation : les URN sont envisagés comme étant uniquement en ASCII, au nom de la facilité de l'échange, ce qui est paradoxal, et en mentionnant le transport par courrier électronique, alors que MIME existait déjà depuis deux ans. (Le RFC 3987 normalisera finalement les IRI, identificateurs en Unicode.)
Une curiosité : la mention des URC, un identificateur pour les méta-données, qui ne prendront jamais.
Date de publication du RFC : Juillet 1994
Auteur(s) du RFC : William Allen Simpson (Daydreamer)
Chemin des normes
Première rédaction de cet article le 25 Avril 2007
L'increvable protocole PPP assure toujours une grande partie des connexions Internet dans le monde. Ce RFC relativement court décrit le fonctionnement de PPP.
PPP, comme son nom l'indique, sert aux liaisons point-à-point, par opposition aux réseaux partagés comme Ethernet. Initialement conçu pour remplacer SLIP sur les liaisons modem ou les liaisons série à très courte distance, ainsi que pour remplacer différents protocoles privés entre routeurs sur les WAN, il continue aujourd'hui sa carrière même sur ADSL avec PPPoE (décrit dans le RFC 2516).
PPP est dérivé de HDLC mais est considérablement plus simple. Il comprend trois parties :
Dans les exemples de configuration PPP suivants, je prendrai comme référence le programme pppd, utilisé sur beaucoup de systèmes Unix, notamment Linux (les utilisateurs de FreeBSD préfèrent en général Userland PPP). Les messages affichés sont extraits du journal de pppd.
Voici par exemple la négociation LCP qui permet aux deux pairs de se mettre d'accord sur les options de la ligne (un gros avantage de PPP par rapport à SLIP) :
Apr 22 09:30:01 ludwigVI pppd[3055]: rcvd [LCP ConfReq id=0x3e <mru 1492> <auth chap MD5> <magic 0x7de8a7c3>] Apr 22 09:30:01 ludwigVI pppd[3055]: sent [LCP ConfReq id=0x1 <mru 1400> <asyncmap 0x0> <magic 0x6a0c5efc> <pcomp> <accomp>] Apr 22 09:30:01 ludwigVI pppd[3055]: sent [LCP ConfAck id=0x3e <mru 1492> <auth chap MD5> <magic 0x7de8a7c3>] Apr 22 09:30:01 ludwigVI pppd[3055]: rcvd [LCP ConfRej id=0x1 <asyncmap 0x0> <pcomp> <accomp>] Apr 22 09:30:01 ludwigVI pppd[3055]: sent [LCP ConfReq id=0x2 <mru 1400> <magic 0x6a0c5efc>] Apr 22 09:30:01 ludwigVI pppd[3055]: rcvd [LCP ConfAck id=0x2 <mru 1400> <magic 0x6a0c5efc>]
On notera que certaines options ont été rejetées par un des
pairs (par exemple la compression pcomp).
PPP permet d'avoir une seule authentification pour tous les protocoles réseaux, gérée par LCP, et reposant en général sur les protocoles PAP ou CHAP.
On voit ici le dialogue CHAP. La machine a reçu un défi CHAP envoyé
par le BAS et répond avec un
NAI (RFC 4282) configuré par l'option name :
Apr 22 09:30:01 ludwigVI pppd[3055]: rcvd [CHAP Challenge id=0x1 <35de4b970986e23fc4447ee4416beada>, name = "BAS-CBV3-1"] Apr 22 09:30:01 ludwigVI pppd[3055]: sent [CHAP Response id=0x1 <c43b7ad1c1cdc8aaa74273efdebb3af0>, name = "bortzmeyer@net2.nerim.nerim"]
LCP permet de définir des tests de la ligne (section 5.8 du RFC). On les active avec les options :
lcp-echo-interval 120 lcp-echo-failure 3
et on peut voir qu'ils sont régulièrement effectués :
Apr 22 09:30:02 ludwigVI pppd[3055]: sent [LCP EchoReq id=0x0 magic=0xa1ce4573] Apr 22 09:30:02 ludwigVI pppd[3055]: rcvd [LCP EchoRep id=0x0 magic=0xe8d1ffb5]
PPP permet de configurer la MRU (Maximum Receive Unit) de la ligne, souvent une source d'ennuis importante (voir par exemple le RFC 4638). Avec pppd, c'est :
mtu 1492 mru 1400
et cela donne, dans la négociation :
Apr 22 09:30:01 ludwigVI pppd[3055]: sent [LCP ConfReq id=0x1 <mru 1400> <asyncmap 0x0> <magic 0x6a0c5efc> <pcomp> <accomp>]
pppd et, bien sûr, le protocole PPP lui-même dispose de nombreuses autres options.
Date de publication du RFC : Juillet 1994
Auteur(s) du RFC : Bob Braden (University of Southern California, Information Sciences Institute)
Intérêt historique uniquement
Première rédaction de cet article le 5 Décembre 2007
Il n'y a pas que des normes qui réussissent, à l'IETF. Il y a aussi des échecs, comme cette amélioration du protocole TCP, T/TCP, qui portait de nombreux espoirs à une époque et est pourtant aujourd'hui abandonnée.
T/TCP, normalisé dans ce RFC, visait à résoudre un problème de TCP : le temps d'établissement de la connexion est souvent supérieur au temps passé à transmettre des données, dès que les données sont peu nombreuses. C'est le cas des protocoles de type requête/réponse comme HTTP (beaucoup de pages Web font moins d'un ou un et demi kilo-octet, soit moins qu'un seul paquet IP) mais aussi du DNS ou de SNMP, que notre RFC cite dans sa section 1. Pour ces protocoles, on souhaiterait typiquement n'envoyer que deux paquets, un pour la question et un pour la réponse, laissant le mécanisme normal de TCP aux transferts de gros fichiers, pour lesquels le temps d'établissement de la connexion est négligeable. Le DNS ou SNMP ont choisi d'utiliser UDP et, comme celui-ci n'offre aucune fiabilité, doivent donc gérer les paquets perdus, les retransmissions, etc. HTTP a choisi d'utiliser TCP, ce qui simplifie la tâche des développeurs d'applications Web mais augmente nettement la durée d'une requête Web typique.
Pourquoi ? À cause d'une fonction essentielle de TCP, le
3-way handshake. TCP ne peut pas envoyer ne
serait-ce qu'un octet de données avant d'avoir terminé l'ouverture de
la connexion et cette ouverture nécessite trois paquets, le paquet de
demande d'ouverture d'une connexion, SYN, le paquet d'acceptation et
d'accusé de réception, SYN+ACK et le paquet d'accusé de réception
ACK. Si le RTT du réseau est important (par
exemple sur les liaisons satellite), la
durée du 3-way handshake pourra être l'essentiel de
la durée de la requête. On peut voir cet effet avec echoping, sur un site
Web (http://www.kame.net/) dont la page d'accueil est
très légère :
% echoping -v -h / www.kame.net This is echoping, version 5.2.0. Trying to connect to internet address 2001:200:0:8002:203:47ff:fea5:3085 80 to transmit 88 bytes... Trying to send 256 bytes to internet address 2001:200:0:8002:203:47ff:fea5:3085... Connected... TCP Latency: 0.331326 seconds Sent (88 bytes)... Application Latency: 0.357898 seconds 3241 bytes read from server. Elapsed time: 0.711559 seconds
Le temps d'établissement de la connexion (TCP latency) est la moitié du temps total. Voici le 3-way handshake correspondant, vu avec tcpdump (le grand S après les adresses IP indique un paquet SYN) :
21:43:15.110842 2001:7a8:7509::1.35261 > 2001:200:0:8002:203:47ff:fea5:3085.80: S 845465777:845465777(0) win 5728 <mss 1432,sackOK,timestamp 10604938 0,nop,wscale 0> 21:43:15.425956 2001:200:0:8002:203:47ff:fea5:3085.80 > 2001:7a8:7509::1.35261: S 3136927327:3136927327(0) ack 845465778 win 65535 <mss 1440,nop,wscale 1,nop,nop,timestamp 476839171 10604938,[|tcp]> [class 0x3] [flowlabel 0x71d12] 21:43:15.426014 2001:7a8:7509::1.35261 > 2001:200:0:8002:203:47ff:fea5:3085.80: . ack 1 win 5728 <nop,nop,timestamp 10605253 476839171>
À la fin de cette échange d'un tiers de seconde, aucune donnée « utile » n'a encore été envoyée.
(Un autre problème de TCP pour ce genre de liens est le délai d'attente à la fin d'une connexion, où chaque machine doit garder un état pour pouvoir traiter correctement les paquets arrivant en retard. Pour un serveur très chargé, gérant beaucoup de requêtes, c'est une vraie contrainte.)
L'idée de base de T/TCP est de transporter dès le premier paquet les données, de façon à ce que l'acceptation de la connexion puisse également porter la réponse. Cela se fait en utilisant une option de TCP, CC (Connection Count) qui indique la présence de données dans le paquet SYN. Le Connection Count sert également de cookie pour garantir qu'on parle bien à la même machine. Un certain nombre de détails doivent être pris en compte pour que cela marche, en conservant la fiabilité de TCP, même si des paquets sont perdus. Ce qui explique que le protocole soit plus complexe que résumé ici (les sections 2 et 3 le détaillent).
Par exemple, comme la connexion ne dure pas longtemps, la mesure du RTT que fait normalement TCP pour optimiser l'utilisation du réseau ne peut avoir lieu. La section 4.3 demande donc qu'une machine T/TCP garde un cache des RTT des différentes machines à laquelle elle parle, pour obtenir approximativement le même effet.
L'idée était donc très tentante et a été promue par plusieurs experts comme W. Richard Stevens, qui s'en est fait l'ardent défenseur. Mais peu de systèmes d'exploitation l'ont implémenté (FreeBSD est la principale exception mais Linux a eu aussi sa version), peu de machines l'ont activé et peu de logiciels s'en servaient (echoping avait une option -r pour T/TCP mais elle a été retirée pour les raisons exposées plus loin, cf. bogue #1350714).
Outre la simple inertie face à la nouveauté, T/TCP a en effet été rapidement victime d'une sécurité plus faible que celle de TCP. Il n'y a pas de miracle : si on va plus vite, on vérifie moins. Alors que les adresses IP d'une connexion TCP sont relativement authentifiées (car le numéro de séquence TCP doit être renvoyé, ce qui impose de donner sa vraie adresse IP pour recevoir les messages), T/TCP n'est guère plus fiable qu'UDP face à l'usurpation d'adresses IP. Comme les réponses sont souvent plus grandes que les requêtes, cela permet en outre une amplification de l'attaque.
Ces failles ont été documentées dans plusieurs articles :
Sur une machine FreeBSD, T/TCP semble coupé par défaut, désormais
(sysctl -a | grep -E 'rfc1644|dropsyn' pour voir
les variables pertinentes).
Finalement, c'est le RFC 4614 qui a marqué l'abandon officiel de T/TCP. Le RFC 6247 entérinera cet abandon en reclassifiant notre RFC 1644 comme « intérêt historique seulement ».
Date de publication du RFC : Juin 1994
Auteur(s) du RFC : Tim Berners-Lee (CERN, World-Wide Web project)
Pour information
Première rédaction de cet article le 26 Février 2007
Les relations des créateurs du Web avec l'IETF n'ont pas toujours été simples et amicales et ce RFC s'est donc vu gratifier d'un avertissement comme quoi l'IETF travaillait à son propre système.
Ce RFC n'en a pas moins été le premier à mentionner les URL (qui ne seront normalisés que plus tard, dans le RFC 1738) et les URN. Aujourd'hui, la norme qui décrit les URI est le RFC 3986 et leurs successeurs internationaux, les IRI sont normalisés dans le RFC 3987.
À propos d'IRI, notons que le jeu de caractères de notre RFC était encore Latin-1 (Unicode n'était pas encore visible sur l'écran radar) et que l'échappement des caractères Latin-1 passait par le %HH où H était un nombre hexadécimal, se limitant ainsi à un seul octet...
Date de publication du RFC : Mai 1994
Auteur(s) du RFC : Rob Austein (Epilogue Technology Corporation), Jon Saperia (Digital Equipment Corporation)
Intérêt historique uniquement
Première rédaction de cet article le 14 Février 2007
Dédié au cas des résolveurs DNS, ce RFC, lancé en même temps que son compagnon, le RFC 1611, connaitra le même sort.
Il sera rabaissé au statut de Historic par le RFC 3197.
Date de publication du RFC : Mai 1994
Auteur(s) du RFC : Rob Austein (Epilogue Technology Corporation), Jon Saperia (Digital Equipment Corporation)
Intérêt historique uniquement
Première rédaction de cet article le 14 Février 2007
Ce RFC, qui n'a jamais connu de déploiement significatif, visait un problème toujours non résolu : un moyen standard de gérer un serveur DNS distant.
Vue la dépendance de l'Internet vis-àvis du DNS, il est curieux de constater qu'il n'existe pas de moyen standard de gérer un serveur DNS à distance, ni pour récupérer de l'information (par exemple les compteurs d'activité), ni pour modifier la configuration du serveur (par exemple pour lui demander d'être secondaire pour une nouvelle zone).
BIND a son programme rndc, qui permet de piloter certaines fonctions du serveur à distance, mais elle est complètement spécifique à ce logiciel. Idem pour des services comme le protocole Supermaster de PowerDNS.
Il y a fort longtemps, le protocole SNMP a suscité beaucoup d'espoir et il était un peu mis « à toutes les sauces ». D'où ce RFC et son compagnon, le RFC 1612, qui normalisaient une MIB pour les serveurs DNS. Notre RFC se chargeai plus spécialement de la MIB pour un serveur, l'autre s'occupant des résolveurs.
Cette MIB était très riche : elle comptait d'innombrables compteurs, mais aussi la liste des zones DNS servies. SNMP permettant l'écriture et pas seulement la lecture, cela rendait apparemment possible de modifier cette liste en vol, de manière standard.
Voici un exemple des compteurs qu'on pouvait y trouver :
dnsServCounterErrors OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of requests the server has processed that were
answered with errors (RCODE values other than 0 and 3)."
REFERENCE
"RFC-1035 section 4.1.1."
::= { dnsServCounter 8 }
À ma connaissance, aucun logiciel n'a jamais mis en œuvre ce RFC. Des années, plus tard, le RFC 3197 a officiellement enterré SNMP pour la gestion des serveurs DNS.
Date de publication du RFC : Août 1993
Auteur(s) du RFC : Jerome H. Saltzer (MIT, Laboratory for Computer Science)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 2 Juillet 2009
Les discussions d'architecture des réseaux à l'IETF ou
dans d'autres communautés techniques achoppent souvent sur le
vocabulaire. Qu'est-ce que le nom d'une machine ?
Qu'identifie t-il réellement ? La clé publique
SSH d'une machine est-elle un nom ? D'ailleurs,
faut-il identifier les machines ? Pourquoi pas les
processus ? Ou les utilisateurs ? Et l'adresse ?
Quel est son statut ?
http://www.foo.example:8080/toto est-il une
adresse bien qu'il inclus un nom ? Il ne s'agit pas uniquement de
pinaillage philosophique. C'est en partie à cause du flou sur les
concepts que les discussions d'architecture tournent en rond et
s'éternisent.
D'innombrables documents, dont ce RFC, ont été produits pour tenter de clarifier la situation. Mais aucune terminologie cohérente n'a été adoptée. Notre RFC 1498 est donc une étape, une des plus souvent citées, dans cette longue liste. Quels sont ses points essentiels ? (Attention si vous distribuez ce document, c'est un des rares RFC qui a une licence qui n'autorise pas une distribution libre.)
Le RFC essaie d'appliquer les principes des systèmes d'exploitation aux réseaux. Les systèmes d'exploitation, eux aussi, doivent identifier les fichiers, les utilisateurs, les disques, les partitions, les parties de la mémoire, etc. Le RFC reprend la terminologie classique (mais très peu appliquée en pratique) de John Shoch, que tous les étudiants des années 1980 et 1990 ont apprise par cœur (Shoch, « A note on Inter-Network Naming, Addressing, and Routing », une copie est disponible sous le nom d'IEN 19 ) :
À noter que cette terminologie, dans notre RFC, ne ne fait pas référence à la forme des identificateurs. Ainsi, un nom peut aussi bien être une suite de lettres ayant un sens qu'une série de chiffres opaques (contrairement à une vision trop simpliste selon laquelle les noms sont juste une forme conviviale des adresses). La terminologie de ce RFC ne sépare donc pas les identificateurs qu'un humain peut traiter et ceux qu'une machine peut traiter.
On peut voir tout de suite (ce point ne figure pas dans le RFC) que cette terminologie ne s'applique pas du tout à l'Internet. Une adresse IP, par exemple, n'identifie pas une position dans la topologie de l'Internet, puisqu'il existe des adresses PI, il y a l'anycast, etc. Un URL est un mélange de nom (la ressource que je veux) et d'adresse (puisqu'il indique où trouver la ressource, avec pas mal de détails de bas niveau comme le numéro de port).
J. Saltzer, donc, procède autrement. Il distingue quatre types d'objets qu'on peut avoir envie d'identifier :
Et Saltzer insiste sur le fait qu'un nom peut prendre plusieurs formes (par exemple une binaire sur le câble et une lisible pour les documentations et les fichiers de configuration), sa nature ne dépend pas de sa forme.
Là encore, même si ce point n'est pas abordé dans le RFC, on peut s'amuser à chercher une correspondance entre ces types et les identificateurs utilisés sur l'Internet :
fr.wikipedia.org au lieu de http://fr.wikipedia.org/),Pour notre RFC, les quatre types d'objets cités ci-dessus ont chacun une identité. Cette identité se maintient même si l'objet change ses liaisons avec les autres objets. Ainsi, un service ne devrait pas changer de nom lorsqu'il migre d'une machine à une autre, une machine (un nœud) ne devrait pas changer de nom lorsqu'il migre d'un point d'attachement à un autre, etc.
L'essentiel, donc, dit le RFC, est la liaison (binding) qui est faite entre un type d'objets et un autre. Ainsi, il doit exister un mécanisme de découverte qui permet de faire la liaison entre un service et la machine sur laquelle il opère. Un autre mécanisme de liaison permet de passer de la machine au point d'attachement. Un dernier fait passer du point d'attachement au chemin. Chacun de ces mécanismes doit également effectuer un choix, car il existe souvent plusieurs réponses.
Dans l'Internet actuel, en l'absence de vrai identificateur de machine, il y a plutôt un mécanisme unique, le DNS, qui sert aux deux premiers rôles. BGP, lui, prend en charge le dernier. (Ils ne sont pas cités dans le RFC.)
Il existe aussi parfois un autre mécanisme préalable aux autres, celui qui permet de trouver l'identificateur du service, c'est par exemple un moteur de recherche. La question est discutée dans le RFC, qui note qu'il n'y a pas toujours une liaison explicite, dans une table, entre l'idée humaine d'un service et son nom formel. Ainsi, changer un nom formel est très difficile (voir l'excellent article Cool URIs don't change).
Le RFC discute ensuite quelques cas de réseaux réels, en tenant de les mettre en correspondance avec les notions de types d'objets et de liaisons. Dans le cas d'Ethernet, l'adresse MAC est très mal nommée puisqu'elle est constante et ne dépend pas de la localisation. C'est en fait plutôt un nom et elle est utilisée comme telle par certains logiciels, par exemple pour le contrôle de la licence d'utilisation. Le cas est en fait plus complexe, par exemple parce qu'une machine a deux cartes Ethernet et peut se connecter à un réseau Ethernet en deux points. Les réseaux réels n'ont pas été conçus selon une architecture propre...
Un autre exemple est le vieux NCP où l'identificateur appelé « nom » était en fait dépendant de la position de la machine. En l'absence de mécanisme de résolution commun, la liaison entre un nom et un point d'attachement était câblée en dur dans toutes les machines du réseau. Changer une machine de place imposait donc de changer son nom... ou de mettre à jour toutes les machines du réseau, ce qui n'est pas mieux. Saltzer argumente donc que la nature d'un identificateur dépend de l'existence ou nom d'un mécanisme de résolution, et donc de l'existence d'une vraie liaison avec les identificateurs des autres types d'objet (Un autre exemple aurait pu être Fidonet.)
Donc, pour résumer ce brillant document :
Date de publication du RFC : Décembre 1992
Auteur(s) du RFC : Christian Huitema (INRIA)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 16 Juillet 2007
Ce RFC décrit une expérience (apparemment sans suite) d'utilisation du DNS pour aider au routage IP. Cette expérience éclaire certains débats actuels sur la séparation de l'identificateur et du localisateur.
Notre RFC s'attaque à un problème récurrent de l'Internet : la croissance des tables de routage, due notamment au multihoming. Si les chiffres donnés dans le RFC font sourire aujourd'hui (« there are already more than 5000 networks announced in the NSFNET routing tables », alors qu'ils sont plus de 200 000 désormais), la question reste la même. Si un site, pour des bonnes raisons, veut se connecter à plusieurs FAI (être multihomé), il doit annoncer une route dans la table de routage globale et celle-ci croît, aux frais des opérateurs Internet.
La solution proposée par Christian Huitema dans ce RFC est de ne
pas annoncer la route vers le réseau du site
multihomé mais de compter sur le
DNS pour la trouver. Le principe est le
suivant : le site multihomé utilise le préfixe
réseau 192.0.2.0/24. Le site ne fait pas de
BGP et ne l'annonce pas dans la table de
routage globale. Il est connecté par deux
fournisseurs, dont les routeurs ont les adresses IP
10.123.6.1 et 172.18.1.3, qui
ne sont pas dans ce préfixe et sont, elles, annoncées en BGP. Le site publie des enregistrements DNS de type
RX qui pointent vers les routeurs des FAI :
2.0.192.in-addr.arpa. IN RX 10.123.6.1
IN RX 172.18.1.3
Le premier routeur qui veut parler à une adresse en
192.0.2.0/24 peut alors utiliser le DNS pour
trouver le routeur de bord de site.
On a donc une vraie séparation de
l'identificateur et du localisateur, l'adresse non-BGPisée
(192.0.2.0/24) étant un identificateur et
l'adresse des routeurs de bord de site étant un localisateur.
Les enregistrements RX ont été nommés par analogie aux MX. En fait, en raison de la difficulté à déployer de nouveaux types d'enregistrement, notre RFC a utilisé des enregistrements de type TXT.
La première idée est de faire faire ce travail de client DNS à chaque routeur du trajet. Mais cela imposerait des délais et un gros trafic DNS. Le RFC spécifie donc en fait que seul le premier routeur fera une requête DNS, puis utiliser la source routing pour que les routeurs suivants n'aient pas ce travail. (On notera que le source routing ne fonctionne plus sur l'Internet d'aujourd'hui, pour des raisons de sécurité.)
L'expérience ne semble pas avoir connu de suite.
Date de publication du RFC : Juin 1992
Auteur(s) du RFC : Keld Simonsen (Rationel Almen Planlaegning)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 4 Octobre 2007
Un ancien RFC, qui représentait une des premières incursions de l'IETF dans le monde complexe des jeux de caractères.
Ce RFC tentait d'énumérer tous les jeux de caractères en usage à l'époque (la bibliographie cite le manuel de VMS, pour le jeu de caractères de ce système !). Les préoccupations d'internationalisation sont anciennes à l'IETF et ce RFC reflète une époque très reculée, où la version 1.0 d'Unicode venait tout juste d'être publié.
Ce RFC est donc essentiellement constitué d'un format pour décrire un jeu de caractères et d'une longue liste de jeux de caractères utilisés à l'époque, en utilisant les noms d'une version préliminaire d'ISO 10646. C'était donc un concurrent direct de la norme Unicode. Cette démarche n'a pas eu un succès fracassant et MIME, par exemple, se contentera d'attribuer un identificateur unique à chaque jeu, sans essayer de le décrire complètement (mais en citant notre RFC). Comparons par exemple l'entrée de notre RFC pour US-ASCII :
&charset ANSI_X3.4-1968 &rem source: ECMA registry &alias iso-ir-6 &alias ANSI_X3.4-1986 &alias ISO_646.irv:1991 &g0esc x2842 &g1esc x2942 &g2esc x2a42 &g3esc x2b42 &alias ASCII &alias ISO646-US &alias US-ASCII &alias us &alias IBM367 &alias cp367 &code 0 NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ '! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT
avec celle d'aujourd'hui, tirée du registre IANA, géré selon le RFC 2978 :
Name: ANSI_X3.4-1968 [RFC1345,KXS2] MIBenum: 3 Source: ECMA registry Alias: iso-ir-6 Alias: ANSI_X3.4-1986 Alias: ISO_646.irv:1991 Alias: ASCII Alias: ISO646-US Alias: US-ASCII (preferred MIME name) Alias: us Alias: IBM367 Alias: cp367 Alias: csASCII
On notera que, pour faire rentrer les jeux de caractères dans un
RFC écrit en ASCII, ce RFC développe un codage
se voulant « intuitif » (la section 2.3 dit The two
characters are chosen so the graphical appearance in the reference set
resembles as much as possible (within the possibilities available) the
graphical appearance of the character.). C'est ainsi que le
é, le « e accent aigü » s'écrit e' et le è, l'« e
accent grave » e!. Voici la seconde moitié de la
table ISO 8859-1, ainsi exprimée :
A! A' A> A? A: AA AE C, E! E' E> E: I! I' I> I: D- N? O! O' O> O? O: *X O/ U! U' U> U: Y' TH ss a! a' a> a? a: aa ae c, e! e' e> e: i! i' i> i: d- n? o! o' o> o? o: -: o/ u! u' u> u: y' th y:
Date de publication du RFC : Mars 1992
Auteur(s) du RFC : David L. Mills (University of Delaware, Electrical Engineering Department)
Chemin des normes
Première rédaction de cet article le 10 Avril 2009
Dans tout système technique complexe, comme l'Internet, on a besoin d'horloges correctes. À tout moment, on lit l'heure et on en tient compte. Par exemple, l'ingénieur système qui lit les journaux d'un serveur a besoin d'être sûr de l'heure qu'ils indiquent. De même, le chercheur qui mesure le temps de propogation d'un paquet IP entre deux machines en soustrayant le temps de départ de celui d'arrivée (cf. RFC 2679) doit être sûr des horloges des deux machines, sinon la mesure sera fausse. Pour synchroniser des horloges, on pourrait munir chaque ordinateur connecté à Internet d'un récepteur GPS ou équivalent. Mais de tels récepteurs sont relativement chers (surtout pour les engins les moins puissants comme les PC bas de gamme ou les téléphones portables) et ne marchent pas dans toutes les circonstances (le GPS ne fonctionne bien qu'en plein air). Le mécanisme privilégié sur l'Internet est donc que seules certaines machines sont connectées à une horloge physique correcte et que les autres d'ajustent sur celles-ci, par le biais du protocole NTP, objet de ce RFC.
A priori, synchroniser une machine C sur une autre, nommée S, est simple : C demande l'heure à S et S lui donne. C'est ainsi que fonctionnait le protocole Time du RFC 868. Mais ce mécanisme a un gros défaut : il ne tient pas compte du temps de propagation dans le réseau. Lorsque C reçoit la réponse, elle n'est déjà plus correcte... La résolution d'horloge qu'on peut obtenir est donc limitée par ce temps de propagation. En outre, les algorithmes tels que celui du RFC 868 ne permettent pas de tirer profit de multiples serveurs de temps puisqu'ils ne fournissent aucun moyen de décider quel est le « meilleur » serveur.
Pour expliquer la synchronisation d'horloge, tout un vocabulaire
spécifique est nécessaire. Il n'y a pas de glossaire
dans le RFC mais des mots come delay et offset sont définis en section
2 : pour résumer, une horloge peut avoir
un écart (offset) avec le
« vrai » temps, UTC (ou bien avec une autre
horloge, si on s'intéresse juste au fait qu'elles soient
synchronisées, ce qui n'est pas le cas de NTP). Si cet écart est
inférieur à une certaine valeur, on dit que l'horloge est
correcte (accurate). Et
l'horloge peut avoir un décalage
(skew), elle peut avancer plus ou moins vite qu'une autre
(ce qui entrainera l'apparition ou l'aggravation d'un écart). Pire, la
dérive peut être variable, auquel cas on mesure la dérivée seconde du
décalage sous le nom de dérive
(drift, mais NTP ignore ce facteur). Enfin, l'horloge a une certaine
résolution (precision), la
plus petite unité de temps qu'elle peut mesurer.
Des problèmes de mesure de temps analogues sont présents dans bien
d'autres RFC notamment le RFC 2330 mais aussi
les RFC 4656 ou RFC 5481. Pour obtenir le temps d'un
autre serveur, alors que le délai de propagation est non-nul, NTP
utilise des estampilles temporelles, des valeurs
de la mesure de l'horloge, mises dans le paquet. Après plusieurs
paquets échangés, chaque serveur NTP connait le délai de propagation
avec un autre serveur (ainsi que, au bout d'un temps un peu plus long,
la gigue, la variation de ce délai, suite aux
hoquets du réseau) et peut donc déduire ce délai des temps mesurés par
son pair. Sur une machine Unix, voyons ce que cela donne avec la commande ntpq -c peers :
% ntpq -c peers
remote refid st t when poll reach delay offset jitter
==============================================================================
+relay1.nic.fr 192.134.4.11 3 u 998 1024 377 0.297 -1.554 0.163
gw.prod-ext.pri .INIT. 16 u - 1024 0 0.000 0.000 0.000
+obelix.gegeweb. 145.238.203.10 3 u 695 1024 377 5.226 0.586 1.768
-ntp.univ-poitie 224.22.30.230 3 u 498 1024 377 6.885 -4.565 0.267
*ns1.azuria.net 193.67.79.202 2 u 56 1024 377 2.739 -1.411 0.305
-rps.samk.be 193.190.198.10 3 u 984 1024 377 5.293 5.930 0.317
Lorsque plusieurs serveurs NTP sont accessibles, NTP sélectionne le meilleur (en tenant compte de divers paramètres comme justement la gigue). Il n'y a pas de vote entre serveurs, NTP est une dictature où le meilleur serveur a toujours raison.
Comme norme, NTP est très stable, et n'avait pas bougé entre cette
version 3 et la version 4, apparue dix-huit ans plus tard dans le RFC 5905. La version 2 était décrite dans le RFC 1119 et les différences (aucune n'est essentielle) entre les
deux versions sont décrites dans l'annexe D. La version 3 a surtout
amélioré les divers algorithmes de traitement des données, sans
changer le modèle, et en changeant à peine le protocole. (La première
version de NTP était dans le RFC 958.) NTP n'était pas le
premier protocole de synchronisation d'horloge, loin de là. Il a été
précédé par daytime (RFC 867) ou
time
(RFC 868), ainsi que par des options d'ICMP comme celle
du RFC 781. Il y a également eu des mises en œuvre non
normalisées comme le démon
timed sur Berkeley Unix. NTP a aussi été inspiré par
le protocole DTS, partie du système DCE mais,
contrairement à DTS, il n'impose pas que toutes les machines
participantes dépendent du même administrateur. Enfin, il y a eu
d'innombrables projets de recherche sur des thèmes bien plus ambitieux
comme la détermination de la justesse ou de la fausseté d'une horloge,
problèmes que NTP n'essaie pas de traiter. Voir la section 1.1 pour
plus de détails sur ces autres techniques. Enfin, la version 4 de NTP,
on l'a dit, a été publiée en juin 2010 dans le RFC 5905, sans qu'elle change fondamentalement les principes du
protocole.
Le problème de la synchronisation d'horloges est très complexe et plein de détails difficiles. Le RFC 1305 est donc un des plus gros RFC qui soit (plus de cent pages). En outre, l'abondance des formules mathématiques, rares dans les RFC mais nécessaires ici à cause des calculs d'erreur, fait que notre RFC n'est pas uniquement disponible en texte brut. S'il y a bien une version dans ce format, l'auteur prévient qu'il est recommandé de lire la version PDF, disponible au même endroit. Elle est la seule à disposer des équations mais aussi de la pagination. Enfin, le caractère plus « scientifique » de ce RFC fait que la section 7, les références, est spécialement longue et évoque plus un article de physique qu'une norme TCP/IP. Le lecteur pressé a sans doute intérêt à lire plutôt l'article de David Mills (l'auteur du RFC), Internet Time Synchronization: the Network Time Protocol qui reprend le plan du RFC mais en omettant les détails (attention, cet article ne décrit que la version 2 de NTP mais les différences ne sont pas vitales). Autrement, la page Web dudit auteur, propose plein d'informations sur NTP.
La section 2 décrit le modèle utilisé. NTP considère que certaines machines ont l'information correcte (par exemple parce qu'elles l'ont obtenu d'une horloge sûre) et que le seul problème est de transmettre cette information aux autres machines. NTP ne s'essaie pas à déterminer si les serveurs ont raison ou tort, il leur fait confiance, il n'existe pas de système de vote, NTP n'est pas une démocratie. Certaines machines ont raison et les autres s'alignent.
Communiquant avec un serveur, un client NTP détermine l'écart (clock offset) avec ce serveur, le RTT (roundtrip delay) et la dispersion, qui est l'écart maximal avec l'autre horloge.
Pour cette communication, il existe plusieurs mécanismes (section 2.1), le plus courant étant un mécanisme client/serveur où le client NTP demande au serveur le temps. Celui-ci répond et l'information contenue dans le paquet permettra au client de déterminer les valeurs ci-dessus, notamment l'écart. En fait, NTP est plus compliqué que cela car il existe plusieurs niveaux de serveurs et chaque client utilise plusieurs serveurs, pour se prémunir contre une panne. La proximité d'un serveur avec une « vraie » horloge est mesurée par un nombre, la strate (section 2.2), qui vaut 1 lorsque le serveur est directement connecté à l'horloge et N+1 lorsque le serveur est coordonné avec un serveur de strate N.
Le serveur calcule ensuite (par une variante de l'algorithme de Bellman-Ford), le chemin le plus court (en utilisant comme métrique le nombre d'étapes et la strate), et c'est par celui-ci que sera transmise la valeur correcte de l'horloge (je le répète, NTP ne fait pas de pondération entre les serveurs possibles, sauf dans le cas particulier décrit dans l'annexe F, une nouveauté de la version 3 de NTP).
La section 3 décrit le protocole. La plus importante information transportée par NTP est évidemment le temps, exprimé sous forme d'un doublet. La première partie du doublet est un nombre sur 32 bits qui indique le nombre entier de secondes depuis le 1er janvier 1900 (section 3.1). La seconde est la partie fractionnaire de cette même valeur. Cela assure donc une précision d'environ 200 picosecondes. Comme tout le fonctionnement de NTP dépend de la précision de ces estampilles temporelles, le RFC recommande que leur écriture dans les paquets soit, autant que possible, fait dans les couches les plus basses, par exemple juste au dessus du pilote de la carte réseau.
32 bits n'est pas énorme et la valeur maximale sera atteinte en 2036. Les programmes devront donc s'adapter et faire preuve d'intelligence en considérant qu'un nombre de secondes très faible signifie « un peu après 2036 » et pas « un peu après 1900 ». Plus drôle, comme la valeur zéro est spéciale (elle signifie que le temps n'est pas connu), pendant 200 picosecondes, au moment de la transition, NTP ne marchera plus.
Pour son bon fonctionnement, NTP dépend de certaines variables, décrites en section 3.2. Il y par exemple l'adresse IP du pair mais aussi :
L'identifiant du type d'horloge est indiqué dans la sortie de
ntpq -c peers si le pair est de strate 1, ou bien
par la commande ntptrace sous le nom
de refid. Par exemple, ici,
clock.xmission.com est synchronisé au GPS :
% ntptrace localhost: stratum 3, offset 0.000175, synch distance 0.072555 tock.slicehost.net: stratum 2, offset 0.000658, synch distance 0.057252 clock.xmission.com: stratum 1, offset 0.000010, synch distance 0.000274, refid 'GPS'
NTP peut fonctionner selon plusieurs modes (section 3.3), en client ou en serveur
mais aussi en mode diffusion (un serveur qui
envoie ses données que quelqu'un écoute ou pas). Ainsi, avec le
programme ntpd (voir http://support.ntp.org/) d'Unix, si on
configure dans /etc/ntp.conf :
broadcast 224.0.0.1
(où l'adresse est celle de diffusion) ntpd va diffuser ses informations à tout le réseau local. Si on met :
broadcastclient
il écoutera passivement les annonces des serveurs qui diffusent. Si enfin, on écrit :
server ntp1.example.net server ntp2.example.net
il cherchera activement à se connecter aux serveurs
ntp1.example.net et
ntp2.example.net pour obtenir d'eux des
informations sur l'heure qu'il est. Les deux serveurs établiront alors
une association entre eux.
NTP peut se défendre contre un pair qui enverrait des informations aberrantes mais il ne contient pas de système de vote qui pourrait protéger contre des pairs malveillants. Même avec un tel système, si tous les pairs participaient d'un commun accord à l'attaque, NTP serait alors trompé. Il faut donc s'assurer que les pairs sont bien ceux qu'on croit. La section 3.6 (et l'annexe C) décrit les contrôles d'accès qu'on peu utiliser. En pratique, cette sécurité est peu pratiquée ; bien que fausser l'horloge d'une machine puisse avoir de sérieuses conséquences pour la sécurité (journaux avec une heure fausse, par exemple), les attaques sur NTP semblent rares. La principale protection reste le filtrage au niveau du pare-feu.
La section 4 décrit les algorithmes de correction qui permettent de réparer dans une certaine mesure les erreurs des horloges, ou bien celles introduites par la propagation dans le réseau. NTP peut aussi bien filtrer les mesures d'une horloge donnée (en ne gardant que les meilleures) que garder les bonnes horloges parmi l'ensemble des pairs accessibles. C'est une des parties les plus mathématiques du RFC, et qui justifie de lire la version PDF.
La précision obtenue avec NTP dépend évidemment de la précision de l'horloge locale. La section 5 décrit la conception d'une horloge telle qu'utilisée dans le système Fuzzball et permettant d'atteindre les objectifs de NTP.
Le format effectif des paquets apparait dans l'annexe A. Les paquets NTP sont transportés sur UDP, port 123. Chaque message indique le mode de l'émetteur (par exemple client, serveur ou autre), les différentes estampilles temporelles (heure de réception du paquet précédent Receive Timestamp, heure d'émission de celui-ci Transmit Timestamp, etc), précision de l'horloge locale, etc. Les estampilles temporelles sont indiquées dans le format à 64 bits décrit plus haut. Leur usage est décrit en section 3.4. Du fait que chaque paquet contienne toutes les estampilles nécessaires, les paquets sont auto-suffisants. Il n'est pas nécessaire qu'ils arrivent dans l'ordre, ni qu'ils soient tous délivrés (d'où le choix d'UDP comme protocole de transport).
Pour observer NTP en action, on peut utiliser tcpdump :
# tcpdump -vvv udp and port 123
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
17:11:46.950459 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 76) munzer.bortzmeyer.org.ntp > tock.slicehost.net.ntp: [udp sum ok] NTPv4, length 48
Client, Leap indicator: (0), Stratum 3, poll 10s, precision -20
Root Delay: 0.037567, Root dispersion: 0.082321, Reference-ID: tock.slicehost.net
Reference Timestamp: 3448017458.952901899 (2009/04/06 16:37:38)
Originator Timestamp: 3448018483.951783001 (2009/04/06 16:54:43)
Receive Timestamp: 3448018483.951863646 (2009/04/06 16:54:43)
Transmit Timestamp: 3448019506.950407564 (2009/04/06 17:11:46)
Originator - Receive Timestamp: +0.000080633
Originator - Transmit Timestamp: +1022.998624563
17:11:46.950946 IP (tos 0x10, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 76) tock.slicehost.net.ntp > munzer.bortzmeyer.org.ntp: [udp sum ok] NTPv4, length 48
Server, Leap indicator: (0), Stratum 2, poll 10s, precision -20
Root Delay: 0.036941, Root dispersion: 0.012893, Reference-ID: clock.xmission.com
Reference Timestamp: 3448019415.234667003 (2009/04/06 17:10:15)
Originator Timestamp: 3448019506.950407564 (2009/04/06 17:11:46)
Receive Timestamp: 3448019506.951188027 (2009/04/06 17:11:46)
Transmit Timestamp: 3448019506.951214015 (2009/04/06 17:11:46)
Originator - Receive Timestamp: +0.000780425
Originator - Transmit Timestamp: +0.000806425
On voit ici que munzer.bortzmeyer.org, machine
chez Slicehost a contacté le
serveur de temps, tock.slicehost.net (le second
serveur NTP de cet hébergeur se nomme
tick.slicehost.net) en indiquant que le paquet
était émis (Transmit Timestamp à
3448019506.950407564 (soit le six avril 2009 vers
17:11:46). tock.slicehost.net répond, renvoie
cette estampille dans le champ Originator
Timestamp, indique qu'il l'a reçue à 3448019506.951188027,
soit 780 microsecondes plus tard et qu'il a répondu à
3448019506.951214015, 26 microsecondes après la réception. munzer.bortzmeyer.org, en
regardant à quelle heure il a reçu le paquet, peut en déduire le
délai d'acheminement et le décalage des deux horloges. Si le serveur venait de démarrer, toutes les estampilles sont à zéro, sauf celle de transmission :
22:39:26.203121 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 76) munzer.bortzmeyer.org.ntp > tick.slicehost.net.ntp: [udp sum ok] NTPv4, length 48
Client, Leap indicator: clock unsynchronized (192), Stratum 0, poll 6s, precision -20
Root Delay: 0.000000, Root dispersion: 0.000000, Reference-ID: (unspec)
Reference Timestamp: 0.000000000
Originator Timestamp: 0.000000000
Receive Timestamp: 0.000000000
Transmit Timestamp: 3448384766.203066617 (2009/04/10 22:39:26)
Originator - Receive Timestamp: 0.000000000
Originator - Transmit Timestamp: 3448384766.203066617 (2009/04/10 22:39:26)
L'annexe E contient des passionnants détails sur les calculs de temps. Par exemple, l'annexe E.3 est consacrée à un exposé plus détaillé des divers services de synchronisation d'horloges publics, par exemples ceux du NIST, le LORAN ou le DCF77 allemand. Notez que, à l'époque de la publication du RFC, le GPS était encore en cours de déploiement.
L'annexe E.4 parle de l'organisation du temps, les calculs calendaires. (Je me permets de placer ici une petite publicité pour le livre de Reingold & Dershowitz Calendrical calculations.)
L'annexe G, chargée en mathématiques et en physique, décrit la
modélisation des horloges. En G.1.2, l'informaticien intéressé par
Unix trouvera un exposé très détaillé de
l'application de ce modèle aux horloges Unix. Les appels système
settimeofday() et
adjtime() permettent de modifier
l'horloge système, brutalement dans le premier cas et progressivement
dans le second (celui utilisé par NTP). adjtime()
prend bien soit que l'horloge ne recule jamais (si elle est en avance,
on la ralentit, mais on ne la fait pas aller en arrière).
L'annexe H est une analyse fouillée des causes d'erreurs dans la synchronisation d'horloges, aussi bien celles dues à l'horloge elle-même que celles dues à la propagation des messages dans le réseau. Ces dernières erreurs sont difficiles à caractériser car elles sont tout sauf aléatoires. (En effet, elles dépendent surtout de la taille des files d'attente dans les routeurs, puisque le temps de propagation, lui, est peu variable, cf. H.4. Les variations de taille de ces files sont assez chaotiques.)
L'annexe I plaira aux programmeurs car elle est la seule qui contient du code source, en C, mettant en œuvre certains des algorithmes décrits dans le RFC.
La mise en œuvre la plus courante de NTP, sur Unix, est celle
du serveur ntpd. Il se configure
dans le fichier /etc/ntp.conf et la documentation
complète figure en ligne sur http://doc.ntp.org/. La commande ntpdate permet une mise à jour sommaire, sans faire tourner de serveur :
# ntpdate pool.ntp.org 23 Feb 01:34:10 ntpdate[3335]: step time server 192.83.249.31 offset 2.155783 sec
Mais pour une meilleure précision, il faut un serveur tournant en
permanence (autrement, il existe une version simplifiée de NTP,
SNTP,
décrite dans le RFC 4330). Voici par exemple une station de
travail ordinaire, synchronisée au serveur NTP de son réseau,
ntp.example.org :
server ntp.example.org server 127.127.1.0 fudge 127.127.1.0 stratum 13
Les deux dernières lignes sont là pour dire à ntpd que l'horloge locale est raisonnablement stable et qu'on peut la considérer comme de strate 13. Comme on ne veut pas forcément que tout l'Internet aille ensuite noyer cette machine sous le trafic NTP et, pire, changer son horloge, on restreint souvent les possibilités de NTP à certaines actions. Par exemple :
# Exchange time with everybody, but don't allow configuration. restrict default kod notrap nomodify nopeer noquery # Local users may interrogate the ntp server more closely. restrict 127.0.0.1 nomodify
Une fois cette machine synchronisée, les commandes
ntpq et
ntptrace permettront de regarder
l'état de NTP :
% ntptrace localhost: stratum 3, offset 0.000116, synch distance 0.015000 fuzzer.example.org: stratum 2, offset 0.000149, synch distance 0.009868 192.0.2.77: timed out, nothing received ***Request timed out
Ici, le serveur de strate 1, 192.0.2.77 n'accepte pas des interrogation directes
de la part des stations, il ne répond donc pas à ntptrace.
On peut avoir plus de détails sur les pairs avec
ntpq, par exemple :
ntpq> peers
remote refid st t when poll reach delay offset jitter
==============================================================================
*fuzzer.ex 192.0.2.176 2 u 50 64 377 0.304 0.107 0.064
LOCAL(0) .LOCL. 13 l 1 64 377 0.000 0.000 0.001
ntpq> clocklist
assID=0 status=0000 clk_okay, last_clk_okay,
device="Undisciplined local clock", timecode=, poll=33834, noreply=0,
badformat=0, baddata=0, fudgetime1=0.000, stratum=13, refid=76.79.67.76,
flags=0
qui permet de voir le délai de la communication avec le serveur de strate 2 (ce délai est logiquement de zéro avec l'horloge locale, de strate 13). On peut aussi voir qu'il y a eu association :
ntpq> associations ind assID status conf reach auth condition last_event cnt =========================================================== 1 16199 9614 yes yes none sys.peer reachable 1 2 16200 9014 yes yes none reject reachable 1 ntpq> pstatus 16199 assID=16199 status=9614 reach, conf, sel_sys.peer, 1 event, event_reach, srcadr=fuzzer.example.org, srcport=123, dstadr=192.0.2.1, dstport=123, leap=00, stratum=2, precision=-20, rootdelay=1.999, rootdispersion=7.858, refid=192.0.2.176, reach=377, unreach=0, hmode=3, pmode=4, hpoll=6, ppoll=6, flash=00 ok, keyid=0, ttl=0, offset=0.116, delay=0.305, dispersion=3.077, jitter=0.015, reftime=cd848978.4d74dea3 Mon, Apr 6 2009 16:00:24.302, org=cd848a03.2ce4faea Mon, Apr 6 2009 16:02:43.175, rec=cd848a03.2ce6b9ee Mon, Apr 6 2009 16:02:43.175, xmt=cd848a03.2cd129e9 Mon, Apr 6 2009 16:02:43.175, filtdelay= 0.31 0.32 0.32 0.32 0.32 0.31 0.37 0.34, filtoffset= 0.13 0.13 0.13 0.13 0.13 0.12 0.15 0.12, filtdisp= 0.00 0.99 1.94 2.93 3.90 4.88 5.85 6.80
Ici, il n'y avait qu'une seule vraie association, de numéro 16199, avec le serveur NTP de strate 2.
Et sur un routeur Cisco ? Configurer NTP en client est simplement :
Router#config terminal Enter configuration commands, one per line. End with CNTL/Z. Router(config)#ntp server 129.237.32.2 Router(config)#^Z
Le configurer en serveur pour d'autres machines, ici en strate 10 par défaut :
Router#config terminal Enter configuration commands, one per line. End with CNTL/Z. Router(config)#ntp master 10 Router(config)#^Z
On peut alors vérifier l'état de NTP :
Router#show ntp status
Clock is synchronized, stratum 3, reference is 128.249.2.2
nominal freq is 250.0000 Hz, actual freq is 249.9961 Hz, precision is 2**16
reference time is BF454660.7CCA9683 (22:37:36.487 EDT Sat Sep 8 2001)
clock offset is 4.3323 msec, root delay is 136.28 msec
root dispersion is 37.69 msec, peer dispersion is 1.14 msec
Router#show ntp associations
address ref clock st when poll reach delay offset disp
*~128.249.2.2 192.5.41.40 2 4 64 377 76.9 5.49 0.4
-~130.218.100.5 198.72.72.10 3 33 128 377 7.1 13.13 0.6
+~129.237.32.2 192.43.244.18 2 16 64 377 44.8 3.05 0.9
+~128.118.25.3 128.118.25.12 2 48 64 377 39.7 5.50 1.4
* master (synced), # master (unsynced), + selected, - candidate, ~ configured
Tout le monde n'a pas forcément un serveur NTP chez lui, ni un
fournisseur qui lui en procure un de qualité. Il est donc pratique de
faire appel à des serveurs publics. Pour cela, le projet
pool.ntp.org
enregistre dans le DNS l'adresse IP des volontaires qui participent au
service ntp.pool.org. Il suffit au client de
mettre dans sa configuration :
server pool.ntp.org server pool.ntp.org server pool.ntp.org server pool.ntp.org
pour se synchroniser à quatre serveurs, pris au hasard parmi les volontaires. Notez bien que le fait de répéter la même ligne quatre fois n'est pas une erreur. Chacune de ces lignes va déclencher une requête DNS qui donnera à chaque fois une liste d'adresses IP dans un ordre différent :
% dig +short A pool.ntp.org 91.208.102.2 195.83.66.158 81.19.16.225 87.98.147.31 88.191.77.246 % dig +short A pool.ntp.org 88.191.77.246 91.208.102.2 195.83.66.158 81.19.16.225 87.98.147.31 % dig +short A pool.ntp.org 87.98.147.31 88.191.77.246 91.208.102.2 195.83.66.158 81.19.16.225
Pour être sûr d'avoir des adresses différentes, il suffit de préfixer les noms par un chiffre :
server 1.pool.ntp.org server 2.pool.ntp.org server 3.pool.ntp.org server 4.pool.ntp.org
Vu avec ntpq, on pourra avoir, par exemple :
% ntpq
ntpq> peers
remote refid st t when poll reach delay offset jitter
==============================================================================
ks34176.kimsufi 193.52.184.106 2 u 25d 1024 0 1.116 -4.039 0.000
*ns1.azuria.net 193.67.79.202 2 u 116 256 377 1.412 -1.931 0.647
+mail1.vetienne. 129.240.64.3 3 u 208 256 377 1.657 -18.063 3.348
+ntp1.adviseo.ne 209.81.9.7 2 u 114 256 377 1.001 -3.440 1.622
ntpq>
où des machines d'hébergeurs très différents sont utilisées, NTP
choisissant le meilleur (atteignable, proche, faible gigue, etc).
Bien sûr, pool.ntp.org n'offre aucune sécurité,
puisque rien ne dit qu'un méchant ne s'est pas glissé dans le lot dans
le but de perturber vos horloges. Mais c'est un service gratuit,
fourni par la communauté et
globalement de très bonne qualité. À noter que ceux qui réalisent un système d'xploitation peuvent demander un sous-domaine, pour y mettre par défaut leur machine. C'est ce que fait, par exemple, Debian et une machine Debian sera configurée par défaut avec quelque chose du genre :
server 0.debian.pool.ntp.org server 1.debian.pool.ntp.org server 2.debian.pool.ntp.org server 3.debian.pool.ntp.org
Date de publication du RFC : Mars 1991
Auteur(s) du RFC : Keith McCloghrie (Hughes, LAN Systems), Marshall T. Rose (Performance Systems International)
Chemin des normes
Première rédaction de cet article le 29 Novembre 2007
Un des RFC les plus anciens encore en service, la normalisation de la célèbre MIB-II, la base des données qui peuvent être récoltées avec le protocole de gestion de réseaux SNMP.
La MIB-II est la plus connue et la base de toutes les autres
MIB (elle succède à la MIB-I, décrite dans le RFC 1156). Elle décrit un modèle de données, pas un
protocole. Ces données sont accessibles par les différentes versions du
protocole SNMP, elle donne accès à sept groupes
d'informations, comme System ou
IP. Ce RFC est donc surtout composé d'une longue
liste de variables (objets), selon les principes communs à toutes les
MIB, décrits dans le RFC 1155.
Physiquement, une MIB est (section 4) une description en
langage ASN.1 des données présentes, avec leur
syntaxe, une
indication de leur identificateur (l'OID), une
description en langue naturelle, etc. Les commandes comme
snmpget affichent par défaut les noms des variables mais
on peut afficher les OID avec l'option
-On. Les OID de MIB-II démarrent à
1.3.6.1.2.1. Par exemple, la définition de la
variable ifNumber (nombre d'interfaces réseaux de
la machine) est :
ifNumber OBJECT-TYPE
SYNTAX INTEGER
ACCESS read-only
STATUS mandatory
DESCRIPTION
"The number of network interfaces (regardless of
their current state) present on this system."
::= { interfaces 1 }
Son OID étant { interfaces 1 } et celui de
interfaces, défini un peu plus haut, étant
{ mib-2 2 }, on voit que l'OID de
ifNumber est
1.3.6.1.2.1.2.1.0 (le zéro final est une valeur
nécessaire pour les scalaires,
avec SNMP). snmpget peut donc la récupérer :
% snmpget [options] myrouter 1.3.6.1.2.1.2.1.0 IF-MIB::ifNumber.0 = INTEGER: 2
Si la variable est un tableau, c'est un peu plus compliqué, il faut
ajouter à l'OID un index. Par exemple, les interfaces ont une variable
ifOperStatus qui indique si elles fonctionnent ou
pas (ifAdminStatus indique l'état
désiré de l'interface,
ifOperStatus son état réel ; la comparaison des
deux est donc un bon moyen de savoir si toutes les interfaces
fonctionnent comme prévu). Cete variable est définie dans notre RFC ainsi :
ifOperStatus OBJECT-TYPE
SYNTAX INTEGER {
up(1), -- ready to pass packets
down(2),
testing(3) -- in some test mode
}
ACCESS read-only
STATUS mandatory
DESCRIPTION
"The current operational state of the interface.
The testing(3) state indicates that no operational
packets can be passed."
::= { ifEntry 8 }
% snmpget [options] myrouter 1.3.6.1.2.1.2.2.1.8.1 IF-MIB::ifOperStatus.1 = INTEGER: up(1)
Voici enfin, affichée par snmpwalk, une partie de la MIB-II d'un
commutateur réseau de bas de gamme. D'abord, le
groupe System (section 3.4), qui décrit l'engin lui-même, par
exemple sa description :
SNMPv2-MIB::sysDescr.0 = STRING: 24-Port Managed 10/100 Switch w/WebView SNMPv2-MIB::sysLocation.0 = STRING: UVA ...
puis le groupe Interfaces qui décrit les
interfaces de l'engin :
IF-MIB::ifNumber.0 = INTEGER: 37 ... IF-MIB::ifDescr.1 = STRING: Ethernet Interface ... IF-MIB::ifType.1 = INTEGER: ethernetCsmacd(6) ... IF-MIB::ifMtu.1 = INTEGER: 1500 ... IF-MIB::ifOperStatus.1 = INTEGER: up(1) ... IF-MIB::ifInOctets.1 = Counter32: 188864
Ce dernier compteur, ifInOctets est un exemple
des variables que récoltent les programmes de surveillance de réseau
comme le célèbre MRTG ou comme le plus récent
Munin.
Les groupes ultérieurs comme IP, ou
TCP sont moins pertinents pour un commutateur,
car ils ne comptent que les paquets qui lui sont directement adressés.
Date de publication du RFC : Novembre 1990
Auteur(s) du RFC : Jeffrey Mogul (Digital Equipment Corporation (DEC) , Western Research Laboratory), Steve Deering (Xerox Palo Alto Research Center)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 20 Mai 2007
Ce RFC fut le premier à proposer une méthode pour déterminer la MTU disponible entre deux nœuds de l'Internet.
Une telle détermination sert à beaucoup de choses mais notamment à éviter la fragmentation en envoyant des paquets qui pourront arriver à destination « tels quels ». La fragmentation réduisant le débit, il est souhaitable de l'éviter dès le début. On peut lire à ce sujet Raising the Internet MTU qui décrit en détail pourquoi il serait bon d'augmenter les MTU. (Et, pour un point de vue plus sceptique, l'excellent article de Simon Leinen).
En attendant, qu'elle que soit la MTU, il est préférable de la déterminer dès la source des paquets, plutôt que de compter sur les routeurs ultérieurs pour fragmenter (en IPv6, c'est même obligatoire, les routeurs n'ayant pas le droit de fragmenter).
L'algorithme proposé par notre RFC est le suivant : envoyer des paquets avec le bit DF (Don't fragment) mis et voir si on reçoit des paquets ICMP Datagram too big qui contiennent en général la MTU maximale du lien suivant. Voici, vu par tcpdump, un de ces paquets ICMP, indiquant que le lien suivant ne peut faire passer que 1492 octets d'un coup :
11:10:23.474673 IP 172.19.1.1 > 172.19.1.2: icmp 556: 192.134.4.69 unreachable - need to frag (mtu 1492)
On recommence avec la nouvelle taille jusqu'à ce que le paquet atteigne sa destination. On apprend ainsi la MTU maximale du lien (c'est la plus petite MTU de tous les liens intermédiaires) et on peut ensuite utiliser des paquets de la taille optimale.
Sur le papier, la méthode est imparable. Mais, en pratique, il est fréquent qu'elle ne marche pas. Beaucoup de sites, en effet, filtrent stupidement tous les paquets ICMP et la machine qui tente de faire de la Path MTU discovery n'aura jamais de réponse.
Aujourd'hui, on doit donc plutôt utiliser des bricolages comme le
MSS clamping qui consiste à modifier sauvagement la
MSS des paquets TCP. Le clamping est décrit par exemple en http://www.netbsd.org/Documentation/network/pppoe/#clamping,
pour NetBSD. Avec
Linux, on peut utiliser la technique décrite en
http://www.linux.com/howtos/Adv-Routing-HOWTO/lartc.cookbook.mtu-mss.shtml ou bien l'option -m du programme pppoe. Par exemple, pour ma connexion ADSL, mon fichier /etc/ppp/peers/monFAI contient pppoe -I eth1 -T 80 -m 1412 pour « clamper » le MSS de TCP à 1412 octets.
Le MSS clamping ne fonctionne qu'avec TCP. Une
autre solution, sur un réseau local qui ne peut pas faire sortir des
paquets de 1500 octets (par exemple car il est connecté à Internet
avec PPPoE) est de changer la MTU sur toutes les
machines du réseau (commande ifconfig sur
Unix).
Mais une autre approche est possible depuis peu : le RFC 4821 décrit un moyen de découvrir la MTU maximale sans dépendre des paquets ICMP. Il reste donc à voir s'il sera largement déployé.
Date de publication du RFC : Mai 1990
Auteur(s) du RFC : Marshall T. Rose (Performance Systems International, Inc.), Keith McCloghrie (Hughes LAN Systems, The Wollongong Group)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 18 Février 2010
Ce RFC a été pendant longtemps la référence pour la description d'informations gérées sur un réseau. Le SMI est le cadre général, dans ce cadre on écrit des MIB, on les interroge avec SNMP (RFC 1157) et voilà la gestion de l'Internet. Aujourd'hui, la dernière norme sur le SMI est la version 2, décrite dans le RFC 2578 mais notre RFC 1155 est toujours en statut standard (numéro 16) et toujours d'actualité puisque toutes les MIB n'ont pas été mises à jour (c'est le cas de la MIB-II, la MIB de base, normalisée dans le RFC 1213, même si elle a connu des évolutions comme celle du RFC 2863).
Notre RFC décrit donc le SMI, le cadre de base de la description d'informations qu'on gère, typiquement avec SNMP (à l'époque où a été fait notre RFC, il était encore obligatoire de citer CMIP, le concurrent ISO qui n'a jamais connu de déploiement significatif). Il y a longtemps que la ligne officielle de l'IAB est que tout protocole Internet soit gérable, et aie donc une MIB, écrite selon les règles du SMI (section 1).
La section 2 donne les principes du SMI : séparation de la description des objets et du protocole d'accès (c'était nécessaire à l'époque, pour les raisons politiciennes qu'explique bien l'un des auteurs du RFC 1155, Marshall Rose, dans son livre The Simple Book), et utilisation d'un sous-ensemble de ASN.1 pour décrire les classes d'objets gérés.
Un autre principe important, est celui de la simplicité. Bien qu'on puisse se demander s'il est vraiment atteint, il faut se rappeler que les propositions concurrentes, à l'époque, étaient bien pires. Le RFC note avec modestie qu'on ne sait pas encore bien maitriser la gestion des réseaux et qu'il faut donc éviter de tout figer par des normes trop strictes (et, effectivement, en 2010, la question est toujours ouverte, comme le montre le RFC 5706). De même, le SMI se veut extensible, car tout ne peut pas être prévu à l'avance
Et, pour ceux qui s'intéressent à l'histoire, outre l'excellent livre de Rose déjà cité, il y a les RFC 1052 et RFC 1109.
Avec la section 3, on en arrive au concret : qu'est-ce qu'une MIB
et qu'est-ce qu'on met dedans ? La MIB, écrite en
ASN.1, rassemble des objets qui ont tous un
nom, plus exactement un OBJECT
IDENTIFIER (OID, section 3.1). Ce nom est une suite de chiffres, alloués
hiérarchiquement (ce qui garantit l'unicité). Certains de ces chiffres
ont aussi parfois une étiquette en lettres. Ainsi, le nœud 1 est
étiquetté iso et géré par
l'ISO. Tous les objets Internet sont sous le
sous-arbre 1.3.6.1 (3 étant alloué par l'ISO à d'autres organisations et
6 étant le DoD qui financait le projet, 1
revenant à l'IAB). En
ASN.1, cela se dit :
internet OBJECT IDENTIFIER ::= { iso(1) org(3) dod(6) 1 }
et les objets officiels sont sous le sous-arbre 1.3.6.1.2. La MIB-II
du RFC 1213 est ainsi 1.3.6.1.2.1. Pour prendre
un exemple d'objet, ifOperStatus, l'état effectif
d'une interface réseau (par exemple une carte
Ethernet) est { ifEntry 8
}, c'est-à-dire 1.3.6.1.2.1.2.2.1.8
puisque ifEntry était
1.3.6.1.2.1.2.2.1 (il faut se rappeler qu'une MIB
est arborescente). Chaque interface réseau recevra ensuite un
OBJECT IDENTIFIER à elle,
1.3.6.1.2.1.2.2.1.8.1,
1.3.6.1.2.1.2.2.1.8.1, etc. Voici un exemple vu
avec snmpwalk (-O n lui dit
d'afficher les OID, pas les étiquettes), sur une machine qui a quatre
interfaces réseaux dont deux fonctionnent :
% snmpwalk -v 1 -O n -c tressecret 192.0.2.68 1.3.6.1.2.1.2.2.1.8 .1.3.6.1.2.1.2.2.1.8.1 = INTEGER: up(1) .1.3.6.1.2.1.2.2.1.8.2 = INTEGER: up(1) .1.3.6.1.2.1.2.2.1.8.3 = INTEGER: down(2) .1.3.6.1.2.1.2.2.1.8.4 = INTEGER: down(2)
Sans -O n, on aurait eu :
% snmpwalk -v 1 -c tressecret 192.0.2.68 1.3.6.1.2.1.2.2.1.8 IF-MIB::ifOperStatus.1 = INTEGER: up(1) IF-MIB::ifOperStatus.2 = INTEGER: up(1) IF-MIB::ifOperStatus.3 = INTEGER: down(2) IF-MIB::ifOperStatus.4 = INTEGER: down(2)
Si 1.3.6.1.2 désigne les objets « officiels »,
1.3.6.1.3 (section 3.1.3 du RFC) est pour les
expérimentations et 1.3.6.1.4 pour les objets
privés et 1.3.6.1.4.1 pour les objets spécifiques à une entreprise (section 3.1.4 du RFC). Par
exemple, si Netaktiv a
obtenu
le numéro 9319, ses objets seront sous 1.3.6.1.4.1.9319.
L'objet a aussi une syntaxe (section 3., par exemple
INTEGER, OCTET STRING,
OBJECT IDENTIFIER ou NULL. C'est un
sous-ensemble d'ASN.1 qui est utilisé pour bâtir des définitions à
partir de ces types primitifs, en les organisant en séquences ou en
tables (section
3.2.2). Par exemple, l'état d'une
interface réseau, ifOperStatus, déjà cité, est
défini par le RFC 1213 comme
INTEGER. Voici la définition complète :
ifOperStatus OBJECT-TYPE
SYNTAX INTEGER {
up(1), -- ready to pass packets
down(2),
testing(3) -- in some test mode
}
ACCESS read-only
STATUS mandatory
DESCRIPTION
"The current operational state of the interface.
The testing(3) state indicates that no operational
packets can be passed."
::= { ifEntry 8 }
Notre RFC définit aussi des types à partir de ces types primitifs, types qui pourront être utilisés par toutes les MIB. C'est le cas de :
IpAddress (section 3.2.3.2), une OCTET
STRING de quatre octets (IPv6
n'était pas encore inventé),Counter (section 3.2.3.3), un entier
positif sur 32
bits, croissant de manière monotone modulu sa valeur maximale. Si 32 bits semblaient à l'époque permettre des valeurs énormes, c'est
aujourd'hui bien trop petit. Pour une interface Ethernet
10G, le Counter
ifInOctets peut atteindre sa valeur maximale en
seulement trois secondes !Gauge (section 3.2.3.4) qui, contrairement
à Counter, peut monter et descendre.Un objet a enfin un encodage sur le câble (section 3.3) car ASN.1 ne spécifie pas comment les objets doivent être sérialisés en bits. Le SMI utilise BER.
La section 4 donne les informations qui doivent être indiquées lors
de la définition d'une classe d'objets (comme
ifOperStatus plus haut) : OID, bien sûr mais
aussi accès (lecture seule ou bien aussi écriture), description en
langage naturel, etc (la syntaxe formelle est en section 4.3). Cette section est mieux
résumée par un exemple, ici tirée d'une expérience avortée, le RFC 1414 :
identOpSys OBJECT-TYPE
SYNTAX OCTET STRING (SIZE(0..40))
ACCESS read-only
STATUS mandatory
DESCRIPTION
"Indicates the type of operating system in use.
In addition to identifying an operating system,
each assignment made for this purpose also
(implicitly) identifies the textual format and
maximum size of the corresponding identUserid and
identMisc objects.
The legal values for the `indentOpSys' strings
are those listed in the SYSTEM NAMES section of
the most recent edition of the ASSIGNED NUMBERS
RFC [8]."
::= { identEntry 2 }
Toutes les définitions de ce RFC, en ASN.1, sont rassemblées dans la section 6.
Tiens, Google m'a retrouvé le premier
programme significatif que j'avais fait avec SNMP, en 1993 : http://www.cpan.org/scripts/netstuff/addresses.on.the.LAN.info. Ne
me demandez pas les sources, ils semblent avoir été perdus.
Date de publication du RFC : Février 1990
Auteur(s) du RFC : Van Jacobson (Lawrence Berkeley Laboratory)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 26 Septembre 2010
Ce RFC n'est sans doute plus utilisé nulle part aujourd'hui mais, pendant des années, presque toutes les connexions à l'Internet depuis la maison (et, souvent, depuis le bureau), passaient par un lent modem, ce qui justifiait des efforts important pour comprimer les paquets, notamment (et c'était le but de de ce RFC), les en-têtes IP et TCP en profitant des diverses redondances qu'ils contiennent. La « compression Van Jacobson » (on voyait parfois dans les documentations « VJ compression »), documentée dans ce RFC, était un outil indispensable si on voulait pouvoir utiliser son modem de manière satisfaisante.
Contrairement à beaucoup de RFC de la grande époque, il est long
(49 pages) car il y a beaucoup de détails techniques à spécifier (et
il y a du code C à la fin). Comme plusieurs RFC
de ce temps, il existe également en version
PostScript, en http://www.rfc-editor.org/rfc/rfc1144.ps. Cette version est
plus jolie et est donc recommandée pour la lecture de ce document
difficile. Elle a en outre l'avantage de permettre l'inclusion de
graphiques, comme la figure 8 qui indique le débit réel en fonction de
la MTU.
La section 1 du RFC rappelle le contexte... de l'époque (1990). Des ordinateurs chez les particuliers (enfin, chez les plus riches), un Internet qui, certes, ne figurait pas sur l'écran radar des décideurs et des journalistes (surtout en France où l'Internet était mal vu et où il n'y en avait que pour le Minitel qui, contrairement aux techniques comme SLIP (RFC 1055) utilisées pour l'Internet sur modems, avait un débit asymétrique), des modems allant de 300 b/s (modems acoustiques) à 19 200 b/s (le record - non normalisé - de la norme V.32). Il existait avant ce RFC d'autres techniques de compression d'en-têtes (RFC 914) mais celle-ci était plus performante. À noter que le protocole « Van Jacobson » est spécifique à TCP, car il dépend du format d'en-tête de TCP, et de plusieurs fonctions de TCP, comme la réémission des paquets perdus, qui a permis de mettre aucune fonction de correction d'erreur. (Le RFC 2508 a proposé une méthode pour les autres protocoles de transport.)
Quel était le problème lorsqu'on se connectait à l'Internet via un modem, en utilisant des protocoles comme SLIP ? (PPP sera normalisé quelques mois plus tard, dans le RFC 1172, mais mettra très longtemps à être déployé.) Le problème, expliqué dans la section 2 du RFC, est que des applications interactives (telnet, à l'époque) et des applications transférant des données en bloc (NNTP, SMTP et FTP à l'époque) coexistent sur le câble et que les premières, qui exigent un bon temps de réponse, souffrent de la taille excessive des en-têtes (excessive par rapport au contenu « utile »). Si on se fixe un objectif (raisonnable pour une application interactive) de 100 à 200 ms de délai, on voit qu'un paquet TCP complet, avec ses en-têtes, est trop gros (sur le format des en-têtes, cf. RFC 791, section 3.1, pour IP et RFC 793, section 3.1, pour TCP). Le paquet fait 41 octets pour un seul caractère transmis (et autant pour l'écho effectué par le shell distant), ce qui nécessiterait 4 kb/s pour être transmis en moins de 200 ms. Même pour un modem de ce débit, si un transfert de données est en cours en même temps, les paquets de telnet peuvent avoir besoin d'attendre que la ligne soit libérée. Cela interdit de faire des paquets de données trop gros (ils bloqueraient la ligne pendant plus de 200 ms) et donc la taille relative des en-têtes est aussi un problème pour eux. Le cahier du charge du RFC était donc de permettre de faire du telnet sur des modems à 300 b/s. Un humain tapant environ cinq caractères par seconde impose au maximum cinq octets d'en-tête, ce qui permettrait de réduire la taille des paquets de transfert de données et donc de résoudre deux problèmes d'un coup.
Le protocole lui-même figure en section 3. Il n'est pas évident de comprimer les en-têtes IP et TCP. Contrairement aux protocoles OSI, chaque champ a une utilité et ne peut pas être simplement omis. En revanche, certains de ces champs sont constants au cours d'une même connexion TCP et certains évoluent de manière prédictible. Si les deux parties de la connexion gardent en mémoire l'état de celle-ci, il leur suffit de transmettre avec chaque paquet l'identificateur de la connexion et les champs qui ont changé de façon imprévue. Tout le reste peut être reconstitué localement. C'est sur cette observation que repose l'algorithme Van Jacobson. Après, il ne reste plus qu'à identifier un par un, pour chaque champ, s'il est constant, s'il change de manière prévisible, ou bien s'il peut être déduit de l'information données par d'autres couches (par exemple, le champ Total Length de l'en-tête IP est souvent doublé par une fonction de la couche 2 qui indique la même information). Comme exemple de champ qui change de manière prédictible, on peut citer les numéros de séquence TCP, qui s'incrémentent avec le nombre d'octets envoyés. À noter que toutes les informations vont du compresseur vers le décompresseur : il n'y a pas de rétroaction dans le protocole VJ.
Les détails pratiques figurent en section 3.2. Par exemple, 3.2.2 indique le format du paquet comprimé, 3.2.3 les actions du compresseur et 3.2.4 le mécanisme que doit suivre le décompresseur. Ce dernier doit appliquer aveuglément son algorithme, il ne peut pas demander confirmation ou éclaircissements au compresseur. Il existe quatre types de paquets :
TYPE_ERROR : la couche 2 indique que le
paquet a été mal reçu. Le décompresseur le jette et compte sur le TCP
à l'autre bout pour réémettre.TYPE_IP : un paquet IP
non-TCP, non modifié. L'algorithme VJ ne les comprime pas et le décompresseur n'a
donc rien à faire.UNCOMPRESSED_TCP (identifié par le champ
« Protocole » de IP, normalement à 6 - pour TCP - et qui est ici l'index d'une connexion) : la connexion TCP en
question vient juste de commencer ou bien un problème s'est produit,
nécessitant une remise à zéro de l'état du compresseur. En recevant ce
paquet, le décompresseur doit mettre à jour son état, enregistrer
l'index de la connexion et les valeurs des en-têtes.
COMPRESSED_TCP et le décompresseur a alors le
plus de travail à faire, puisqu'il doit reconstituer le paquet TCP
complet (en
regardant les valeurs qui avait été stockées pour cet index)
qu'il passera au TCP local.Tout cela, c'est très joli, si tout se passe bien. Mais s'il y a une erreur ? C'est fréquent avec les modems... La section 4 couvre ce problème. D'abord, il faut détecter l'erreur. Le principe de la compression étant de supprimer la redondance, la détection d'erreur, typiquement basée sur une information redondante, devient difficile. N'importe quel bruit aléatoire sur la ligne peut être « décompressé » en un paquet TCP/IP valide. La somme de contrôle, trop courte, n'est pas une protection suffisante : sur une ligne à 9 600 b/s, un parasite de 400 µs (ce qui est très court) va corrompre 16 bits, ce que la somme de contrôle va probablement rater. Le protocole VJ dépend donc essentiellement de la détection d'erreur de la couche 2. Un autre cas où un protocole fondé sur une rétroaction du décompresseur vers le compresseur ne marcherait pas est le cas où le paquet serait totalement détruit : le décompresseur ne peut alors même pas savoir qu'il y a eu un problème. Dans ce cas, c'est TCP qui détectera l'erreur, en ne recevant pas d'accusé de réception.
Une fois l'erreur détectée par le décompresseur, comment la
rattraper (section 4.2) ? Le compresseur a
la responsabilité d'envoyer un paquet
UNCOMPRESSED_TCP pour signaler au décompresseur
qu'il doit se resynchroniser. Comment le compresseur sait-il, lui,
qu'un paquet est mal arrivé, ou pas arrivé du tout ? Il observe
simplement les paquets TCP : si le numéro de séquence n'augmente pas
(à part quelques cas spéciaux que le compresseur doit reconnaitre),
c'est qu'il y a retransmission, et que des paquets ont été perdus. Le
compresseur sait alors qu'il doit envoyer un paquet non comprimé. Le
recevant, le décompresseur saura qu'il y a eu un problème et
commencera un contexte neuf.
Le protocole VJ permet-il de configurer certains de ses paramètres ? Comme l'explique la section 5, il n'y en a pas beaucoup, car il n'y a pas de moyen de les transmettre entre les deux parties. Les deux paramètres possibles sont « compression activée ou pas » et nombre de contextes (de flux TCP simultanés) à conserver. Le premier paramètre (activer ou pas la compression VJ) ne se négocie pas, il doit donc être configuré de manière identique des deux côtés. À l'époque, c'était une source d'ennuis fréquents, qui se terminait souvent par « on va essayer avec et sans VJ et on verra bien lequel marche ». Le second paramètre est fixé à 16, avec juste une exception pour le changer si le protocole de couche 2,5 fournit un moyen pour cela (SLIP n'en fournit pas).
Quels sont les résultats obtenus effectivement par la compression VJ ? La section 5.3, très détaillée, fait la comparaison entre la compression VJ et une compression générique (Lempel-Ziv) appliquée à tout le paquet. Pour du trafic interactif (telnet), VJ l'emporte d'un facteur 3. Pour du trafic de données (FTP), c'est le contraire. La section 6 revient sur les performances du compresseur et mesure le temps pris sur les machines typiques de l'époque (Sun 3/60 ou DECstation 3100). La plupart des machines récentes (pour l'époque !) arrivaient à comprimer et à décomprimer à 64 kb/s (ce qui permettait même d'utiliser la compression VJ pour le RNIS).
Pour les programmeurs en C, l'annexe A
fournit une mise en œuvre complète de l'algorithme, documentée
très en détail (avec même un petit réglement de compte contre les
machines qui osaient être petit-boutiennes
comme le Vax). Elle était
distribuée à l'époque dans CSLIP (mise en œuvre de SLIP avec
compression). Une copie
complète du code se trouve en ftp://ftp.ee.lbl.gov/cslip.tar.Z, à l'endroit exact indiqué
par le RFC il y a vingt ans ! Bel existence de persistence d'URL !
(Par contre, l'adresse IP, indiquée dans le
RFC, a changé, bon exemple du fait que les noms de
domaine fournissent de la
permanence et pas de la convivialité.)
Avec PPP, la compression VJ peut être négociée en toute sécurité (cf. RFC 1332, section 4). En revanche, SLIP n'ayant pas de mécanisme de négociation. L'annexe B suggère donc une méthode pour détecter automatiquement, à l'une des extrêmités d'une liaison SLIP, si l'autre extrêmité est en train de comprimer avec l'algorithme VJ. Cela permet, par exemple, d'avoir un « serveur » SLIP qui s'adapte automatiquement à des clients différents.
Aujourd'hui, l'algorithme VJ n'est plus utilisé. Des techniques plus perfectionnées l'ont remplacé, notamment ROHC (RFC 5795). Mais, pendant de nombreuses années, la plupart des connexions à la maison, ou dans des sites éloignées qui n'avaient pas d'autre liaison que le vieux réseau téléphonique, passaient par cet algorithme.
Et merci à Ludovic Rousseau, Pierre-Yves Lochou et Laurent Chemla pour m'avoir aidé lors de mes débuts avec la compression VJ !
Date de publication du RFC : Octobre 1989
Auteur(s) du RFC : Robert Braden (University of Southern California (USC), Information Sciences Institute)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 5 Décembre 2007
À une époque, il semblait encore possible de résumer dans un RFC tout ce que devait savoir le développeur de services réseaux. Ce n'est évidemment plus le cas, néanmoins, ce RFC, qui synthétise les règles que doivent respecter les machines non-routeuses reste utile, certaines des règles qu'il pose étant toujours d'actualité.
Un problème classique de l'implémenteur est le nombre de RFC à lire, et le risque de ne plus pouvoir distinguer les choses importantes des détails, au milieu de toutes ces normes. D'où l'idée de résumer les « choses importantes » dans des RFC de synthèse comme le RFC 1812 pour les routeurs ou comme deux RFC, le RFC 1122 et le nôtre, qui couvrent les machines non-routeuses (host en anglais, parfois traduit par terminal, qui est un terme que je trouve trop marqué par l'époque des mainframes et du Minitel). Le RFC 1122 couvre les couches basses et le 1123 les couches hautes. C'est un des plus vieux RFC encore en service. À l'époque (1989), les médias et les experts officiels n'avaient pas encore découvert l'Internet mais celui-ci était déjà suffisamment complexe pour que la section 1.2.1 s'inquiète de l'« énorme croissance de l'Internet » et des problèmes qu'elle pose.
Comme le note la section 1, de tels RFC de synthèse sont normalement inutiles. « Une mise en œuvre de bonne foi, faite en lisant soigneusement les RFC, ainsi qu'en suivant les activités de la communauté technique et des bons principes d'ingéniérie, ne devrait se différencier des demandes de ce RFC que de manière mineure. » Mais la pratique ne suivant pas toujours la théorie, et des mises en œuvre des protocoles Internet s'étant avérées très boguées, la réalisation d'un RFC de rappel a semblé une bonne idée. En revanche, la mise à jour régulière de ce RFC, promise en section 1, ne s'est jamais concrétisée, même s'il y a eu des mises à jour partielles, comme les RFC 1349 ou RFC 2181.
La partie la plus souvent citée de notre RFC est certainement la section 2.1 Host names and numbers, qui normalise la syntaxe pour les noms de machines sur Internet. Cette syntaxe est limitée à LDH (Letters - Digits - Hyphen) c'est-à-dire un sous-ensemble d'ASCII limité aux lettres de A à Z, aux chiffres et au tiret. Contrairement à ce qu'on lit souvent sous la plume d'ignorants, cette limite n'a rien à voir avec le DNS, qui était une invention récente à l'époque de notre RFC. Cette limite plonge au contraire ses racines dans des normes plus anciennes, comme le RFC 952 qui était même encore plus strict (le nom ne pouvait pas commencer par un chiffre). Ainsi, les règles pour les noms de machines ne sont pas les mêmes que pour un nom de domaine. C'est pour cela qu'il a fallu développer IDN (RFC 3490), pas à cause d'une soi-disant limite du DNS.
La section 1.2.2 rappelle un de ces « bons principes d'ingéniérie », la fameuse phrase « Soyez prudents dans ce que vous envoyez et ouverts dans ce que vous recevez » (« Be liberal in what you accept, and conservative in what you send », déjà présente dans le RFC 791).
Voyons maintenant les autres parties, moins célèbres, de ce RFC.
Sur certains points, les changements dans l'Internet ont été positifs. C'est ainsi que la section 1.2.4 déplorait que l'auto-configuration des machines connectés était toujours aussi utopique, alors que depuis, notamment grâce à DHCP (RFC 2131), elle est devenue une réalité.
Par contre, d'autres fonctions, sur lesquelles on fondait beaucoup d'espoirs, n'ont jamais vraiment pris. Ainsi, la section 2.4 mentionne les TOS d'IPv4, que peu d'applications utilisent et que beaucoup de routeurs ou de coupe-feux bloquent. (Petite publicité personnelle : echoping permet de définir ces valeurs TOS, avec l'option -P.)
La section 3 est consacrée au protocole telnet, qui devrait logiquement être abandonné aujourd'hui, remplacé par SSH.
La section 4 concerne le transfert de fichiers, qui à l'époque se faisait uniquement avec FTP. Il est toujours utilisé aujourd'hui, mais HTTP (RFC 2616) et SCP ont diminué son importance.
La section 5 parle du courrier électronique mais on ne recommande pas sa lecture, les normes et, encore plus, la réalité ayant beaucoup évolué depuis (les textes à jour sont les RFC 2821 et RFC 2822).
La section 6.1 détaille les interactions avec les systèmes de
résolution de noms. Elle n'est pas limitée au DNS, loin de là, la section 6.1.3.8
expliquant la possibilité d'utiliser également un fichier local
(/etc/hosts sur Unix) et
de configurer quel mécanisme de résolution est utilisé
(/etc/host.conf sur Unix).
La 6.1.4, elle, mentionne les listes de domaines dans lesquels
chercher un nom (fonction mise en œuvre avec la directive
search dans le
/etc/resolv.conf des machines Unix). La
publication du RFC en 1989 n'a pas empêché
Verisign de déposer un brevet en 2003 (6,560,634)
sur cette fonction. Et l'office états-unien
des brevets
l'a accepté (les offices des brevets acceptent tout et n'importe quoi ; ils n'ont ni la
compétence, ni l'envie de chercher des précédents, puisque leurs
revenus dépendent des dépôts).
La section 6.2 concerne la gestion des machines, à une époque où le protocole SNMP était très récent.
Date de publication du RFC : Octobre 1989
Auteur(s) du RFC : Robert Braden (University of Southern California (USC)/ Information Sciences Institute (ISI))
Chemin des normes
Première rédaction de cet article le 2 Juillet 2009
Compagnon du RFC 1123, ce document normalise ce que toute machine terminale (host, par opposition à routeur) connectée à l'Internet devrait savoir. Le RFC 1123 fixait les règles des « couches hautes » (notamment la couche application), notre RFC s'attaque aux « couches basses », notamment réseau et transport).
Le résultat est un document épais (116 pages), décrivant en détail tout ce qu'IP et TCP doivent faire sur une machine terminale (les routeurs sont, eux, traités dans le RFC 1812). La section 1.4 note que les discussions sur ce RFC avaient duré dix-huit mois et généré trois méga-octets de courrier, ce qui était considérable à l'époque mais est moins qu'un document MS-Word d'une page d'aujourd'hui.
Ce RFC n'avait pas pour but de changer les normes existantes (comme le RFC 791 pour IPv4 ou RFC 793 pour TCP) mais de les résumer et les préciser. Comme le note la section 1, « une mise en œuvre de bonne foi des protocoles TCP/IP, faite en lisant les normes, ne doit différer de ce RFC 1122 que par des détails ».
Aujourd'hui, plusieurs de ses sections sont bien dépassées mais il reste la norme officielle, personne n'a eu le courage de mettre ce travail à jour.
Il n'est donc pas possible de résumer tout le RFC et j'ai donc sélectionné arbitrairement quelques points qui me semblaient intéressants.
La section 1.1 rappelle l'architecture de l'Internet et la section 1.1.1 revient sur la notion de machine terminale (host dans le RFC). La section 1.1.2 note notamment que :
La section 1.2 pose les grands principes comme le célébrissime Principe de Robustesse (section 1.2.2), « Soyez tolérant pour ce que vous recevez et exigeant pour ce que vous envoyez », principe qu'on trouve dans plusieurs autres RFC. Ainsi, un programmeur doit résister à la tentation d'exploiter les cas spécifiques d'une norme, pour éviter de perturber les autres implémentations.
La section 1.2.4 détaille la configuration des machines terminales. Elle se faisait entièrement à la main à l'époque. Aujourd'hui, avec la disponibilité fréquente de DHCP (RFC 2131), il vaut mieux oublier cette section et lire le dernier document sur la configuration, le RFC 5505.
Ensuite, le RFC suit le modèle en couches (section 1.3.1), ainsi que le vocabulaire spécifique de chaque couche pour désigner une unité de transmission de données sur le réseau (frame pour la couche 2, packet ou datagram - selon que la fragmentation aie eu lieu ou pas - pour la couche 3, message - segment pour TCP - pour la couche 4).
La section 2 concerne donc la couche de même rang. C'est ici que se trouve ARP (section 2.3.2, qui insiste que l'expiration des entrées du cache ARP est obligatoire, ce qui n'était pas assez clair dans le RFC 826). C'est aussi dans cette section (en 2.3.3) que l'on rappelle que l'encapsulation normale des paquets IP sur Ethernet est celle du RFC 894, où le troisième champ de l'en-tête Ethernet est le type du protocole de couche 3 (0x800 pour IPv4) pas celle, bien plus complexe, du RFC 1042, où la longueur de la trame se trouve à cet endroit.
Évidemment, la section 3, consacrée à la couche équivalente, est bien plus longue. Elle porte aussi son âge, par exemple en consacrant une section 3.2.1.3 aux classes d'adresse, supprimées depuis.
Parmi les nombreux points abordés, le choix du
TTL à mettre dans les paquets (section
3.2.1.7). Une machine terminale ne doit pas émettre un paquet avec un
TTL déjà à zéro. La mise en œuvre d'IP doit permettre aux
applications de fixer
le TTL (sur une machine Posix, cela se fait
normalement avec setsockopt(), voir
« Tester quels bits de l'en-tête IP on
peut changer »).
Mais il y a aussi des exigences du RFC qui ne sont plus du tout suivies aujourd'hui. La section 3.2.1.8 obligeait toute mise en œuvre d'IP à permettre le routage par la source alors que, pour des raisons de sécurité, quasiment plus aucun routeur ne l'accepte.
ICMP (RFC 792) faisant conceptuellement partie de la couche 3, il a droit à une sous-section de la section 3. Elle rappelle par exemple qu'un paquet ICMP d'erreur ne doit jamais être envoyé lorsque le paquet original était lui-même un paquet ICMP d'erreur, pour éviter les boucles. (On lit souvent cette règle énoncée comme « Un paquet ICMP ne doit jamais être envoyé en réponse à un paquet ICMP », ce qui est complètement faux, voir par exemple ping avec les ICMP echo, revus en section 3.2.2.6.)
Parmi les autres sujets abordés, la détection d'un routeur mort, qui ne transmet plus les paquets. Comme les machines terminales n'ont pas (ou plus) de protocole de routage (comme, par exemple, RIP), comment savent-elles que le routeur, en panne, est devenu un trou noir ? La méthode recommandée est, formellement, une violation du modèle en couches, mais c'est la seule qui marche dans tous les cas : les couches hautes doivent informer IP qu'elles ne reçoivent plus rien. (La section 3.3.1.4 est une passionnante discussion des autres options possibles. À lire par tout ingénieur qui s'intéresse aux réseaux.)
Le multihoming, la connexion d'une machine (ou
d'un réseau) à plusieurs réseaux, a toujours été un problème difficile
pour IP. La section 3.3.4 tente de fixer certaines règles. Par
exemple, lors d'une réponse, l'adresse IP source de la réponse doit
être l'adresse IP de destination où a été envoyée la question. Ou
encore, une application cliente doit avoir la possibilité de choisir son
adresse IP source (directive BindAddress de
OpenSSH ou bien
tcp_outgoing_address de
Squid). Et que faire en l'absence de telles
directives ? C'est l'objet de la section 3.3.4.3 qui demande de
privilégier, si possible, une adresse source située dans le même
réseau physique que l'adresse de destination (notez que le RFC 3684 a depuis fourni une solution plus générale à cette
question de sélection d'adresse source, pour le protocole
IPv6). Par exemple, une machine choisira comme
adresse IP source 127.0.0.1 si elle doit
contacter localhost et son adresse globale si
elle doit contacter une autre machine.
Au sommet de la couche
3 se trouve l'interface avec la couche 4. La section 3.4 détaille les services
que doit rendre cette interface. Par exemple, la couche 3
doit fournir un moyen de fixer (pour un paquet
émis) et d'interroger (pour un paquet reçu) des paramètres comme le
TTL ou le TOS (depuis
rebaptisé DSCP par le RFC 2474). Cette section
est rédigée sous forme d'une API virtuelle (les
API de programmation réseau réelles ont suivi un autre modèle, mais
fournissent les mêmes services, cf. le livre de Stevens). Cette API comporte
des méthodes comme SEND(src, dst, prot, TOS,
TTL, BufPTR, len, Id, DF, opt) (envoi d'un paquet en fixant
chaque paramètre).
Finalement, un tableau synthétique, en section 3.5, résume tout ce que doit implémenter le programmeur qui réalise une mise en œuvre d'IP.
La couche 4 est ensuite traitée dans la section 4. Suivant le modèle en sablier, une machine connectée à Internet a un grand choix de couches 2 et de supports physiques, une seule couche 3, IP, et à nouveau un choix en couche 4. À l'époque de notre RFC, il n'y avait qu'UDP (RFC 768) et TCP (RFC 793). Depuis, plusieurs autres ont rejoint ces deux pionniers.
Parmi les exigences pour UDP, le RFC cite une forte recommandation d'activer la somme de contrôle (section 4.1.3.4). Celle-ci est en effet facultative en UDP et plusieurs protocoles ont souffert d'avoir cru qu'ils pouvaient s'en passer (notamment NFS et le DNS pour lequel la version 1 de Zonecheck testait que cette somme de contrôle était bien activée).
TCP est bien plus riche et fait donc l'option d'une section nettement plus longue, la 4.2. À l'époque comme aujourd'hui, il est le protocole de transport le plus utilisé.
Le RFC commence (section 4.2.2) par une discussions sur le rôle des ports, en rappelant que la seule distinction normalisée entre les ports est celle entre ceux inférieurs à 255 (services normalisés) et les autres. La distinction entre les ports privilégiés (inférieurs à 1024) et les autres n'est pas normalisée, en pratique, elle est spécifique à Unix. Le RFC ne s'oppose pas à cette distinction mais note à juste titre qu'elle ne vaut pas grand'chose en matière de sécurité puisque rien ne dit que la machine avec qui on correspond applique les mêmes règles. En outre, depuis la publication du RFC 1122, la vaste diffusion des ordinateurs fait qu'un éventuel attaquant a probablement sa propre machine, sur laquelle il est root. La très relative protection sur laquelle comptaient rlogin (en vérifiant que le port source était 513) et le DNS (qui utilisait à une époque lointaine un port source fixe, 53), ne vaut donc plus rien.
Il y a plein d'autres détails intéressants à couvrir comme l'option PUSH (section 4.2.2.2) dont le RFC rappelle qu'elle ne fournit pas un marquer de fin de message mais qu'elle indique juste un souhait que les données soient transmises « le plus vite possible » (TCP attend normalement un peu pour voir si d'autres données n'arrivent pas, cette optimisation, l'algorithme de Nagle est à nouveau discutée en section 4.2.3.4).
Finalement, un tableau synthétique, en section 4.2.5, résume tout ce que doit implémenter le programmeur qui réalise une mise en œuvre de TCP.
Date de publication du RFC : Juin 1988
Auteur(s) du RFC : J. Romkey
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 18 Mars 2010
Pendant de nombreuses années, le protocole SLIP a été le plus répandu pour l'accès à l'Internet en dehors du réseau local, par exemple via un modem et le RTC. Même si ce RFC se qualifie modestement de « non-norme », il n'en a pas moins été la seule description officielle de SLIP pendant ces années.
Pourtant, SLIP était bien plus ancien que ce
RFC. Il a commencé dans les années 1980, dans la mise en œuvre
3com/Unet de TCP/IP. Le terme de « protocole »
est d'ailleurs exagéré pour parler de SLIP : c'est uniquement un
format de paquet sur une ligne
série. Aucune négociation, aucun mécanisme pour distribuer
des informations comme les adresses
IP. Mais, en contrepartie, la programmation de SLIP est
triviale (il y a même un exemple de code en C à la fin du RFC) et il a donc
existé un très grand nombre d'implémentations (aujourd'hui, par
exemple, celle du noyau Linux est toujours dans
drivers/net/slip*).
C'est en 1984, des années avant ce RFC 1055 que Rick Adams a ajouté SLIP à Berkeley Unix et que ce mécanisme a décollé.
Aujourd'hui, l'époque des modems à 1200 b/s, mentionnés par le RFC, semble bien loin et SLIP n'a plus qu'un intérêt historique. Le RFC accuse nettement son âge, notamment lorsqu'il indique (sans donner d'URL, qui n'existaient pas à l'époque) un serveur FTP anonyme pour récupérer le code (ledit serveur n'existe plus), et qu'il ajoute des instructions sur l'utilisation de shar (une horreur en terme de sécurité, inimaginable aujourd'hui).
Donc, en quoi consistait ce « protocole » ? SLIP définissait deux
caractères spéciaux, END (valeur 192) et
ESC (valeur 219, rien à voir avec le
ESC de ASCII). Le
END indique la fin du paquet. Si un vrai
caractère END (ou ESC) doit
être envoyé, on envoie à la place ESC + 220 (ou
ESC + 221). Difficile de faire plus simple. Pour
copier le noyau Linux :
#define END 0300 /* indicates end of frame */
#define ESC 0333 /* indicates byte stuffing */
#define ESC_END 0334 /* ESC ESC_END means END 'data' */
#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
...
while (len-- > 0) {
switch (c = *s++) {
case END:
*ptr++ = ESC;
*ptr++ = ESC_END;
break;
case ESC:
*ptr++ = ESC;
*ptr++ = ESC_ESC;
break;
default:
*ptr++ = c;
break;
}
}
*ptr++ = END;
Il y a quand même quelques petites subtilités. Par exemple, le RFC
recommande d'envoyer également un END
avant le paquet, pour vider tous les caractères
parasites qui seraient en attente (eh oui, les modems n'étaient pas
fiables et tout le monde n'avait pas activé V.42). D'autre part, comme SLIP ne
définissait pas de MTU, le RFC recommande de se
limiter à 1006 octets, taille historique.
Dès le début, les limites de SLIP étaient bien connues et sont listées dans le RFC :
Bref, SLIP était un vrai protocole Internet : simple, qui marche et qui rend service pendant que les comités sont toujours à discuter d'un protocole meilleur.
Dans le monde Internet, SLIP a été largement remplacé par PPP (qui n'existait pas encore à l'époque du RFC 1055).
Date de publication du RFC : Novembre 1987
Auteur(s) du RFC : P. Mockapetris (USC/ISI)
Chemin des normes
Première rédaction de cet article le 15 Octobre 2006
Couturé de cicatrices, ce RFC qui a été amendé par pas moins de vingt-six autres RFC tient toujours. "1035" est toujours la norme du DNS, un protocole sur lequel repose la quasi-totalité des applications de l'Internet. Le DNS est un des plus grands succès de l'Internet (qui se souvient aujourd'hui du ridicule X.500 ?) et notre RFC est donc une lecture indispensable.
Qui osera reprendre ces vingt-huit (avec le RFC 1034 et le 1035) documents et les consolider en un jeu de normes cohérent et à jour ? Sans doute personne, vue l'ampleur de la tâche. En attendant cette très hypothétique synthèse, prévenons tout de suite les lecteurs : lire le 1035 seul peut entrainer des problèmes.
Si son compagnon, le RFC 1034 pose les principes de base du DNS, la structure arborescente des données et le principe client-serveur du protocole, notre RFC descend, lui, dans les détails très concrets et spécifie, dans sa section 3, le format des données (resource records, les enregistrements du DNS) et dans sa section 4 celui des messages échangés entre clients et serveurs. Ces messages sont composés de plusieurs parties (la partie "Question", la partie "Réponse", la partie "Autorité", qui indique les serveurs faisant autorité pour la zone) et le résultat de la commande dig montre ces différentes sections.
Revenant sur le RFC 1034 (la séparation entre les deux RFC n'est pas toujours très logique et on est quasiment toujours obligé de lire les deux), notre RFC revient ensuite sur le format des fichiers de zone et sur l'algorithme utilisé par les logiciels.
En guise de conclusion, rappelons un avertissement : vue l'importance du DNS aujourd'hui, vue la quantité d'expérience accumulée depuis que ce protocole existe, vu le nombre de RFC qui contribuent à décrire le DNS, l'implémenteur de ce protocole ou le simple curieux qui voudrait apprendre ne doivent pas de contenter des deux RFC fondateurs mais doivent être prêts à avaler de nombreux autres textes.
Date de publication du RFC : Novembre 1987
Auteur(s) du RFC : Paul Mockapetris (ISI)
Chemin des normes
Première rédaction de cet article le 30 Août 2006
Ce RFC, très ancien, mais jamais remplacé, est toujours la norme officielle du DNS. Modifié, complété, corrigé, par des dizaines de RFC suivants, il reste, avec son compagnon RFC 1035, l'un des plus anciens RFC encore en service.
Il est très intéressant de lire aujourd'hui le RFC qui normalise le DNS. Tout l'Internet dépend fortement du DNS. Mais à l'époque, le DNS n'était qu'une méthode de nommage parmi d'autres. Il l'a finalement emporté et notre RFC ne semble pas ridicule presque vingt ans après. Le DNS a passé le test du temps et le RFC qui le définit reste une excellente source d'information.
Le DNS a été normalisé dans deux RFC : notre 1034 décrit les concepts (mais descend néanmoins beaucoup dans les détails, par exemple sur l'algorithme utilisé) et le RFC 1035 complète avec tout ce que l'implémenteur doit savoir.
Mais, depuis, de très nombreux RFC ont modifié le DNS : supprimant des options (comme IQUERY, les recherches par contenu, jamais réellement déployées et supprimées par le RFC 3425), ajoutant des services comme DNSSEC, ou expliquant tout ce qui n'était pas clair (comme le font les RFC 2181 ou bien le RFC 4592 sur les fameux jokers). Il serait appréciable qu'une âme courageuse s'attache à consolider toutes ces rustines successives en une série de RFC modernes, comme cela a été fait pour le courrier électronique avec les RFC 2821 et RFC 2822. Mais une telle tâche n'a pas encore trouvé de volontaire. Ce serait un véritable travail d'Hercule, vu le nombre de RFC à digérer et le nombre de gens à convaincre, vu aussi le caractère très spécifique d'un service dont dépend presque tout l'Internet.
Parmi les archaïsmes du RFC 1034, notons qu'il spécifie un format de fichiers pour les serveurs de noms, format que lisent des logiciels comme BIND ou NSD, et qu'affiche une commande comme dig :
@ IN SOA bortzmeyer.netaktiv.com. hostmaster.bortzmeyer.org. (
2006071901
7200
3600
604800
43200 )
IN NS ns1.bortzmeyer.org.
IN NS ns1.generic-nic.net.
IN MX 0 bortzmeyer.netaktiv.com.
. Aujourd'hui, l'IETF évite en général de normaliser les formats de fichiers des clients ou des serveurs, préférant se concentrer sur ce qui passe sur le réseau (on the wire est une expression qui revient souvent à l'IETF). En effet, la normalisation de ce format, quoique utile pour la communication entre humains, ou la rédaction de cours sur le DNS, n'est pas nécessaire à l'interopérabilité des implémentations.
RFC des différentes séries : 0 1000 2000 3000 4000 5000 6000