Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Ève

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. (Au passage, si vous les voulez présentés en italien...)

Le public visé n'est pas le gourou mais l'honnête ingénieur ou l'étudiant.


RFC 868: Time Protocol

Date de publication du RFC : Mai 1983
Auteur(s) du RFC : J. Postel (University of Southern California (USC)/Information Sciences Institute), K. Harrenstien (SRI International)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 3 septembre 2010
Dernière mise à jour le 4 septembre 2010


Bon exemple d'une ère révolue, où les RFC pouvaient faire deux pages (copyright et autre boilerplate compris), et spécifier un protocole qui s'implémentait en quinze minutes. Celui-ci décrit le protocole Time, qui permettait de récupérer l'heure d'une machine distante.

Le but était de pouvoir synchroniser plus ou moins les horloges, en interrogeant celle d'une machine distante. Certes, la précision d'une telle mesure est faible (car on ne connait pas le temps de retour de l'information, celle-ci est donc déjà dépassée lorsqu'elle arrive) mais cela convenait, à cette époque où NTP était loin dans le futur (NTP est aujourd'hui normalisé dans le RFC 5905).

Difficile de faire plus simple que ce protocole Time. Comme beaucoup de protocole de cette époque (finger, whois, ...), il a un numéro de port réservé, 37. Il suffit de se connecter à la machine distante, sur ce port (en TCP ou en UDP) et on récupère un entier de 32 bits (le RFC ne prend pas la peine de préciser s'il est gros-boutien ou petit-boutien... ; ni d'ailleurs si l'entier est signé ou non) qui indique le nombre de secondes écoulées depuis le 1er janvier 1900 à zéro heure (UTC, même si le RFC utilise encore le vieux terme anglo-saxon-centriste de GMT ; à l'époque, les étrangers restaient à leur place et ne réclamaient pas un temps « universel »). Au fait, pourquoi 1900, époque où les ordinateurs n'existaient pas, plutôt que 1970 qui aurait été plus logique ? Mystère. Les commentaires dans le source d'OpenBSD sont amusants :

/*
 * Return a machine readable date and time, in the form of the
 * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
 * returns the number of seconds since midnight, Jan 1, 1970,
 * we must add 2208988800 seconds to this figure to make up for
 * some seventy years Bell Labs was asleep.
 */
u_int32_t
machtime(void)
{
        struct timeval tv;

        if (gettimeofday(&tv, NULL) < 0)
                return (0L);

        return (htonl((u_int32_t)tv.tv_sec + 2208988800UL));
}

Si vous êtes fort en calcul, vous avez déjà vu que 32 bits permettront d'aller jusqu'en 2036 (cette valeur de la date limite indique d'ailleurs que les auteurs du RFC pensaient à des entiers non signés, malgré le curieux exemple d'une valeur négative que donne le RFC à un moment). Après, il faudra se résigner à abandonner complètement ce protocole.

En attendant, il existe des mises en œuvre de ce RFC pour tous les Unix, typiquement en passant par inetd. Le service est en général coupé par défaut, car il n'a plus guère d'utilité pratique aujourd'hui. Sur une Debian, on trouve dans /etc/inetd.conf :

#time           stream  tcp     nowait  root    internal
#time           dgram   udp     wait    root    internal

et on peut activer le service en décommentant la ligne time et en rechargeant inetd.

Côté client, le protocole est binaire (son frère, DayTime, normalisé dans le RFC 867, est, lui, en mode texte lisible par un humain) donc telnet n'est pas très utile. Voici un petit programme client en Go qui se connecte à un serveur Time et indique l'heure qu'il y a sur cette machine distante :

% ./time-rfc-868 foo.bar.example
Time at foo.bar.example:37 is 3492608823 (which is Sat Sep  4 17:07:03 UTC 2010)

Le source est en time-rfc-868.go. Merci à Kim-Minh Kaplan pour son déboguage. On peut mettre des bogues dans un programme aussi court.

Pour revenir aux entiers signés ou non, le RFC donne un exemple de valeur négative, qui n'est pas compatible avec les autres données du document. Cela a fait l'objet d'un rapport de bogue.


Téléchargez le RFC 868


L'article seul

RFC 867: Daytime Protocol

Date de publication du RFC : Mai 1983
Auteur(s) du RFC : J. Postel (University of Southern California (USC)/Information Sciences Institute)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 10 juillet 2012


Voici un RFC qui bat des records de concision. Il spécifie un protocole trivial, permettant d'obtenir l'heure d'une machine distante, et le fait en un seul paragraphe.

Le protocole daytime n'a plus un grand intérêt pratique aujourd'hui mais il a été longtemps un des outils de déboguage les plus utilisés, pour vérifier la synchronisation temporelle d'une machine distante. Difficile de faire plus simple : le client daytime se connecte en TCP sur le port 13 et n'envoie rien. Le serveur envoie une ligne qui donne la date et l'heure chez lui.

Conçu pour être utilisé par des humains, le format de daytime n'est pas spécifié : n'importe quoi de lisible, en pur ASCII, conviendra (au contraire du protocole du RFC 868, conçu pour les machines, ou bien de normes ultérieures comme le RFC 3339).

Voici un exemple d'utilisation, avec telnet en client :

% telnet $REMOTESERVER daytime
Trying 192.168.2.26...
Connected to $REMOTESERVER.
Escape character is '^]'.
Tue, 10 Jul 2012 20:07:45 GMT
Connection closed by foreign host.

On trouve des serveurs daytime un peu partout, en général inclus dans les mises en œuvre d'inetd. Le serveur utilisé pour le test ci-dessus est en Node.js et son code est simplement :

var net = require('net');
 
net.createServer(function (stream) {
    var now = new Date();
    stream.write(now.toUTCString());
    stream.end('\r\n');
}).listen(13);

Il se lance avec :

# node daytime.js

On a vu que telnet suffit comme client daytime mais, sinon, n'importe quel programme qui se connecte au port 13 suffit (il existe, par exemple, un client daytime en C dans le contrib d'echoping, daytime.c).


Téléchargez le RFC 867


L'article seul

RFC 0862: Echo Protocol

Date de publication du RFC : Mai 1983
Auteur(s) du RFC : J. Postel (University of Southern California/Information Sciences Institute)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 7 décembre 2007


Heureuse époque où un RFC pouvait tenir sur une seule page. Celui-ci normalise le protocole echo, utile surtout pour le déboguage.

echo sert à déboguer des serveurs réseaux. Son principe est de renvoyer les données transmises par le client en TCP ou en UDP. Les requêtes ICMP du même nom ne suffisent pas car, sur une machine Unix, elles sont typiquement traitées par le noyau et une machine peut donc répondre à ping et être néanmoins incapable de faire fonctionner des applications, par exemple parce qu'elle swappe trop. Un protocole de test de la couche 7 était donc nécessaire.

Du côté du serveur, echo est typiquement mis en œuvre par inetd mais on peut aussi en trouver une curieuse implémentation dans Emacs ou bien mon implémentation en Python, pour ceux qui veulent voir un exemple d'utilisation de la bibliothèque SocketServer. Une autre implémentation, en Go, illustrant bien les possibilités de ce langage, est NoNewContent.

Comme echo est un protocole très simple, les programmes de test réseau l'utilisent souvent. Par exemple, GnuTLS affiche un sample TLS 1.0 echo server dans sa documentation.

Du côté du client, echo se retrouve par exemple dans echoping, à qui il doit son nom (echo était le premier protocole utilisé par echoping).

Le protocole echo est en général désactivé depuis une alerte de sécurité. Il est à noter que echo n'est dangereux qu'en UDP (et encore, il ne permet pas d'amplification de l'attaque) ou bien combiné avec d'autres protocoles comme chargen (RFC 864). Mais le résultat de cette alerte a été la désactivation quasi-systématique de cet utile protocole (à une époque, il était activé par défaut sur toute machine Unix et sur les routeurs Cisco).


Téléchargez le RFC 0862


L'article seul

RFC 826: Ethernet Address Resolution Protocol

Date de publication du RFC : Novembre 1982
Auteur(s) du RFC : David C. Plummer (Symbolics, Inc.)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 15 mars 2007


Ce très vieux protocole permet à une machine connectée à un réseau local Ethernet de trouver l'adresse MAC d'une machine voisine à qui elle veut parler.

Lorsqu'une machine veut écrire à une autre machine située sur le même lien et qu'elle ne connait que son adresse IP, son adresse de couche 3, comment fait-elle pour avoir l'adresse MAC, l'adresse de couche 2 qu'il faut mettre dans l'en-tête de la trame Ethernet ? Elle utilise ARP.

Le principe de ce protocole est très simple : on diffuse la demande à tout le réseau local et la machine qui se reconnait répond. Vu avec tcpdump -e -n arp, cela donne :

00:11:43:e7:bc:de > 00:01:96:96:dc:60, ethertype ARP (0x0806): arp who-has 192.134.7.254 tell 192.134.7.249
00:01:96:96:dc:60 > 00:11:43:e7:bc:de, ethertype ARP (0x0806): arp reply 192.134.7.254 is-at 00:01:96:96:dc:60

Pour éviter de faire des requêtes ARP à chaque paquet IP qu'on doit envoyer, la machine garde un cache des tables ARP et, comme tous les caches, il crée parfois des problèmes lorsqu'on change une carte Ethernet et qu'on oublie que la nouvelle adresse ne va pas être vue immédiatement par tous.

La table ARP peut être affichée, sur une machine Unix avec arp -a -n :

% arp -a -n
? (192.134.7.248) at 00:04:76:A2:58:73 [ether] on eth0
? (192.134.7.249) at <incomplete> on eth0
? (192.134.7.254) at 00:01:96:96:DC:60 [ether] on eth0

« incomplete » désignant une machine qui n'a pas répondu aux requêtes ARP, sans doute parce qu'elle était éteinte.

Comme beaucoup d'autres protocoles conçus uniquement pour le réseau local et pour ne pas demander de configuration, ARP n'offre aucune sécurité. Comme le dit notre RFC, « The world is a jungle in general, and the networking game contributes many animals. ».


Téléchargez le RFC 826


L'article seul

RFC 793: Transmission Control Protocol

Date de publication du RFC : Septembre 1981
Auteur(s) du RFC : Jon Postel (University of Southern California (USC)/Information Sciences Institute)
Chemin des normes
Première rédaction de cet article le 29 septembre 2006
Dernière mise à jour le 3 mars 2008


Vingt-cinq ans ce mois-ci que le protocole TCP est le protocole de transport le plus répandu de l'Internet. Presque toutes les applications l'utilisent, à commencer par le Web.

Spécifier complètement un protocole de transport n'est pas trivial. Contrairement à IP, décrit dans le RFC 791, TCP a un état et chaque paquet doit donc être traité dans le contexte de cet état. Si la machine à états de TCP est relativement simple, il faut quand même 64 pages au RFC pour décrire tous les détails.

L'aventure de TCP est loin d'être finie : le passage à IPv6 ne l'affectera que peu, et, si le RFC 7414 liste de nombreux RFC qui améliorent ou corrigent la spécification initiale, notre RFC d'un quart de siècle est toujours d'actualité.

La machine à états de TCP : tcp

Voici un paquet TCP tel que vu par Wireshark (lancé en mode texte avec tshark -V) lors de l'établissement d'une connexion. Le format du paquet TCP est décrit dans la section 3.1 de notre RFC. On note la notion de port (ici le port 7 pour le protocole echo du RFC 862) ; IP ne permettant que d'identifier qu'une machine, les ports servent à distinguer plusieurs processus sur une machine. On y voir le bit de contrôle SYN (SYNchronize, demande d'établissement de connexion).

Transmission Control Protocol, Src Port: 36682 (36682), Dst Port: 7 (7), Seq: 0, Ack: 0, Len: 0
    Source port: 36682 (36682)
    Destination port: 7 (7)
    Sequence number: 0    (relative sequence number)
    Header length: 40 bytes
    Flags: 0x0002 (SYN)
        0... .... = Congestion Window Reduced (CWR): Not set
        .0.. .... = ECN-Echo: Not set
        ..0. .... = Urgent: Not set
        ...0 .... = Acknowledgment: Not set
        .... 0... = Push: Not set
        .... .0.. = Reset: Not set
        .... ..1. = Syn: Set
        .... ...0 = Fin: Not set
    Window size: 5840
    Checksum: 0xa57b (correct)
    Options: (20 bytes)
        Maximum segment size: 1460 bytes
        SACK permitted
        Time stamp: tsval 48358541, tsecr 0
        NOP
        Window scale: 0 (multiply by 1)

On note surtout l'important numéro de séquence. TCP gère des flux d'octets numérotés et les accusés de réception indiquent un numéro de séquence, pas un paquet. Ce numéro est affiché comme zéro par Wireshark mais c'est un numéro relatif. Dans la réalité, sur le câble, ce numéro est initialisé à une valeur tirée au hasard (il est important de la tirer au hasard pour limiter les risques qu'une session TCP soit détournée par un attaquant). tcpdump, lui, affiche la valeur absolue pour les paquets SYN, la valeur qui passe sur le câble. Il affiche une valeur relative ensuite. Si on préfère avoir tout le temps la valeur absolue, l'option -S est faite pour cela. Voici un exemple d'ouverture de connexion (vers le serveur Subversion de CNP3) avec les options par défaut :

09:18:08.880944 IP6 2001:67c:2219:8::6:69.59834 > 2001:6a8:3080:1::4.443: Flags [S], seq 4131334602, win 14400, options [mss 1440,sackOK,TS val 876788145 ecr 0,nop,wscale 4], length 0
09:18:08.908511 IP6 2001:6a8:3080:1::4.443 > 2001:67c:2219:8::6:69.59834: Flags [S.], seq 3086055825, ack 4131334603, win 5712, options [mss 1440,sackOK,TS val 81172037 ecr 876788145,nop,wscale 7], length 0
09:18:08.908534 IP6 2001:67c:2219:8::6:69.59834 > 2001:6a8:3080:1::4.443: Flags [.], ack 1, win 900, options [nop ,nop,TS val 876788152 ecr 81172037], length 0

Dans le troisième paquet, l'accusé de réception de l'initiateur de la connexion, tcpdump a affiché qu'on accusait réception, et que le prochain octet attendu était le 1 (pas encore envoyé, puisque les numéros de séquence indiquent l'octet suivant). Avec -S :

09:18:08.880944 IP6 2001:67c:2219:8::6:69.59834 > 2001:6a8:3080:1::4.443: Flags [S], seq 4131334602, win 14400, options [mss 1440,sackOK,TS val 876788145 ecr 0,nop,wscale 4], length 0
09:18:08.908511 IP6 2001:6a8:3080:1::4.443 > 2001:67c:2219:8::6:69.59834: Flags [S.], seq 3086055825, ack 4131334603, win 5712, options [mss 1440,sackOK,TS val 81172037 ecr 876788145,nop,wscale 7], length 0
09:18:08.908534 IP6 2001:67c:2219:8::6:69.59834 > 2001:6a8:3080:1::4.443: Flags [.], ack 3086055826, win 900, options [nop,nop,TS val 876788152 ecr 81172037], length 0

Les deux premières lignes sont inchangées, mais on voit désormais que le troisième paquet contenait en fait un accusé de réception attendant l'octet 3086055826 (puisque le numéro de séquence initial choisi par 2001:6a8:3080:1::4 était 3086055825).

À la fin de l'en-tête TCP, Wireshark montre les options, un champ de taille variable qui contient différentes valeurs, encodées selon un schéma compliqué (l'option peut faire un seul octet ou bien être composée d'un triplet Type-Longueur-Valeur). On y trouve ici la MSS (ici 1460 octets), définie dans notre RFC, et des options qui ont été ajoutées ultérieurement, comme SACK (Selective ACKnowledgment, RFC 2018), ou bien Window scale, RFC 7323.

On peut noter que les options de TCP, étant une famille qui s'agrandit régulièrement, posent parfois des problèmes à des coupe-feux mal conçus (probablement la majorité), qui jettent sans scrupule les paquets contenant des options qu'ils ignorent. Ainsi, il est fréquent que les petits « routeurs » installés par les FAI chez leurs clients, aient des problèmes avec certaines options TCP. À l'heure où j'écris ce texte, le window scaling, pourtant normalisé il y a seize ans, ne passe pas les routeurs d'Alice/Tiscali (sur Linux, il faut mettre la variable sysctl net.ipv4.tcp_default_win_scale à 0). Et le SACK ne passe pas chez Noos (il faut mettre net.inet.tcp.sack.enable à 0 sur une FreeBSD).


Téléchargez le RFC 793


L'article seul

RFC 792: Internet Control Message Protocol

Date de publication du RFC : Septembre 1981
Auteur(s) du RFC : J. Postel (University of Southern California (USC)/Information Sciences Institute)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 4 janvier 2008


Protocole auxiliaire d'IP depuis le début, ICMP est toujours un des protocoles essentiels de l'Internet. Sa version pour IPv4 est normalisé dans ce RFC.

Un très vieux RFC que notre RFC 792. À l'époque, on parlait encore du Catenet (le terme Internet n'était pas universellement adopté), les RFC étaient très courts, sans table des matières et sans sections numérotées, et la fameuse section Sécurité n'était pas obligatoire (alors qu'elle aurait été intéressante pour ICMP, protocole non connecté, sans aucune authentification, même faible).

ICMP est une partie intégrante d'IP (RFC 791). Même s'il est situé dans une couche au dessus (les paquets ICMP sont encapsulés dans l'IP), la mise en œuvre d'ICMP est obligatoire pour toute machine IP. IPv6 a d'ailleurs repris exactement le même modèle dans le RFC 4443.

À quoi sert ICMP ? À signaler les problèmes et à obtenir quelques informations sur les autres machines.

Un paquet ICMP comporte un champ de huit bits, le Message Type et notre RFC liste, par exemple, les types suivants :

  • Destination Unreachable, par lequel un routeur peut signaler à la machine source que la destination n'est pas joignable.
  • Time Exceeded, par lequel un routeur signale que le temps maximum de séjour dans le réseau (en fait, un nombre de routeurs traversés) est dépassé. C'est ce type qu'utilise traceroute, qui envoie des paquets avec un TTL de 1, puis 2, puis 3, et déduit des ICMP Time Exceeded reçus qu'on a atteint le routeur n° 1, 2, 3, etc.
  • Echo, qui permet de réclamer une réponse (qui sera un paquet ICMP de type Echo Reply). Ce mécanisme est surtout utilisé par la commande ping. C'est aussi un exemple d'un cas où un paquet ICMP ne sert pas qu'à signaler des erreurs. On notera que le RFC comporte d'ailleurs une bogue (souvent répétée depuis) en affirmant qu'on n'envoie jamais un paquet ICMP en réponse à un paquet ICMP. C'est faux (Echo est un bon exemple), et la formulation correcte est qu'on n'envoie jamais un paquet ICMP en réponse à un paquet ICMP d'erreur.
  • Source Quench, qui permettait de dire à la source de ralentir son débit. Il n'est plus utilisé car il serait trop facile de s'en servir pour un déni de service (RFC 1812, section 4.3.3.3). Le RFC 6633 officialise l'abandon de ce type.
  • Timestamp, qui permet de demander à une autre machine l'heure (qui arrivera dans un Timestamp Reply). Il n'a jamais été très utilisé, en comparaison de protocoles comme daytime (RFC 867) ou time (RFC 868) ou bien sûr comme NTP (RFC 1305).

D'autres types ont été depuis rajoutés dans le registre IANA.

Destination Unreachable nécessite de donner d'avantage d'informations (beaucoup de choses peuvent aller mal !) et les paquets de ce type ont donc un champ Code de huit bits dont voici certaines valeurs possibles :

  • Network Unreachable, lorsque le routeur n'a pas de route vers ce réseau.
  • Host Unreachable lorsqu'une machine ne répond pas. Ce code est typiquement utilisé par le dernier routeur, lorsque la machine de destination ne répond pas aux requêtes ARP.
  • Fragmentation needed and DF set est utilisé lorsque le paquet a une taille supérieure à la MTU du lien et que le bit DF (Do not fragment) est mis dans l'en-tête IP. C'est l'utilisation de ces paquets ICMP qui permet la découverte de la MTU du chemin (RFC 1191).

traceroute affiche ces codes lorsque la réponse n'est pas Time exceeded, avec des lettres suivies d'un point d'exclamation (pour citer la documentation, !H, !N, or !P (host, network or protocol unreachable), !S (source route failed), !F (fragmentation needed), !X (communication administratively prohibited), [...] or !<num> (ICMP unreachable code <num>)

ICMP a évolué par la suite, notamment par la possibilité d'inclure des messages structurés dans les paquets (RFC 4884).

Un des plus gros problèmes que rencontre ICMP aujourd'hui, est que beaucoup de coupe-feux administrés par des ignorants bloquent la totalité des paquets ICMP. Cette erreur vient en général d'une mauvaise compréhension des problèmes de sécurité (comme le ping of death, mal nommé puisqu'il n'est pas spécifique à ping, ou à ICMP). Le résultat est que certains protocoles comme la découverte de la MTU du chemin fonctionnent mal (cf. RFC 4821).


Téléchargez le RFC 792


L'article seul

RFC 791: Internet Protocol

Date de publication du RFC : Septembre 1981
Auteur(s) du RFC : Jon Postel (University of Southern California (USC)/Information Sciences Institute)
Chemin des normes
Première rédaction de cet article le 29 septembre 2006
Dernière mise à jour le 18 février 2008


Vingt-cinq ans ce mois-ci, un quart de siècle que le protocole IP, dans sa version 4, sert de soubassement à tout l'Internet.

Voici donc le RFC, écrit par Jon Postel lui-même, qui décrit IP. Ses concepts, le routage, l'adressage , le format de paquets.

Le RFC explique très clairement la place d'IP : il ne fournit presque aucun service « de bout en bout », il se contente d'acheminer des datagrammes.

L'adressage est traité en quelques paragraphes, CIDR n'existait pas encore, et notre RFC parle donc de « classes » d'adresses, qui seront supprimées en 1993. Le routage est décrit très succinctement.

Le format des paquets (section 3.1) occupe finalement l'essentiel du RFC mais la section 3.2, consacrée à la discussion des détails du protocole, est très instructive, notamment sur la difficile question de la fragmentation des paquets.

Il n'existe pas de langage standard pour décrire un format de paquets donc notre RFC, comme tous les autres, utilise dans sa section 3.1, de l'art ASCII. Voici l'en-tête d'un paquet IP :

    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version|  IHL  |Type of Service|          Total Length         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Identification        |Flags|      Fragment Offset    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Time to Live |    Protocol   |         Header Checksum       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Source Address                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Destination Address                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

La version vaut toujours 4 pour IPv4. Beaucoup de décodeurs comme tcpdump affichent simplement « IP » tout court, lorsqu'il s'agit d'IPv4. Voici ce qu'affiche tcpdump avec l'option -vvv :


21:59:43.111985 IP (tos 0x8, ttl  64, id 16854, offset 0, flags [DF], length: 60) 172.19.1.1.35890 > 172.19.1.2.7: S [tcp sum ok] 720694724:720694724(0) win 5840 <mss 1460,sackOK,timestamp 10464274 0,nop,wscale 0>

Le ToS (Type of Service, voir plus loin) vaut ici 8 (en hexadécimal), le TTL (Time to Live, en dépit de son nom, c'est le nombre maximum de routeurs qu'on peut traverser avant que le paquet ne soit abandonné) vaut 64, l'identificateur du fragment vaut ici 16854 et l'option (flag) DF (Don't Fragment) est à « vrai » (c'est la découverte de MTU du RFC 1191). Attention, l'ordre d'affichage n'est pas celui du paquet.

tshark, donne d'avantage de détails que tcpdump, d'une manière qui respecte bien le modèle en couches :

#  tshark -V -n 
...
Frame 1 (74 bytes on wire, 74 bytes captured)
    Arrival Time: Feb 18, 2008 22:04:15.826000000
...
Internet Protocol, Src Addr: 172.19.1.1 (172.19.1.1), Dst Addr: 172.19.1.2 (172.19.1.2)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x08 (DSCP 0x02: Unknown DSCP; ECN: 0x00)
        0000 10.. = Differentiated Services Codepoint: Unknown (0x02)
        .... ..0. = ECN-Capable Transport (ECT): 0
        .... ...0 = ECN-CE: 0
    Total Length: 60
    Identification: 0xeeec (61164)
    Flags: 0x04 (Don't Fragment)
        0... = Reserved bit: Not set
        .1.. = Don't fragment: Set
        ..0. = More fragments: Not set
    Fragment offset: 0
    Time to live: 64
    Protocol: TCP (0x06)
    Header checksum: 0xf19d (correct)
    Source: 172.19.1.1 (172.19.1.1)
    Destination: 172.19.1.2 (172.19.1.2)

On note que tshark a affiché le champ ToS sous le nom de DSCP, suivant l'évolution qui a eu lieu dans le RFC 2474, qui a complètement changé la sémantique de ce champ et son nom. Normalement, on ne devrait plus parler de ToS, même si ce terme reste fréquent.

Comment changer ce champ ? Un programme comme echoping permet, avec ses options -p et -P, de donner une valeur à ce champ. Le paquet ci-dessus a été généré par un echoping -P 0x08 172.19.1.2.

On notera enfin que c'est ce RFC 791 qui a défini, dans son annexe B, la notion d'ordre des octets sur le réseau. IP est gros boutien, le bit le plus significatif doit être envoyé en premier.


Téléchargez le RFC 791


L'article seul

RFC 768: User Datagram Protocol

Date de publication du RFC : Août 1980
Auteur(s) du RFC : J. Postel (University of Southern California (USC)/Information Sciences Institute)
Chemin des normes
Première rédaction de cet article le 8 janvier 2009


Le protocole IP, situé dans la couche 3, fournit un service de datagrammes où presque rien n'est garanti. Les datagrammes peuvent arriver dans le désordre, être dupliqués ou, plus couramment, ne pas arriver du tout. IP ne fournit pas non plus de mécanisme permettant d'identifier un processus particulier sur la machine de destination. Quasiment toutes les applications utilisent un protocole de transport au dessus d'IP. TCP (RFC 793) est le plus connu. Il fournit, lui, fiabilité de la transmission mais au prix de délais parfois importants. En effet, tout octet devant être acheminé à bon port, TCP doit souvent attendre les retardataires... ou demander leur rééxpédition. De plus, le fonctionnement de TCP nécessite l'établissement préalable d'une connexion et cela prend du temps (trois trajets sont nécessaires, donc la latence est parfois importante).

Il existe des applications pour qui cette stricte sémantique est excessive ou, plus exactement, pour lesquels on n'a pas envie de payer son prix. Ainsi, si on transmet un flux vidéo avec RTSP (RFC 7826), et qu'un paquet de données se perd, on préfère en général afficher à l'écran un petit carré noir plutôt que de geler l'affichage en attendant une retransmission.

UDP fournit donc un service minimum, peu coûteux. Si l'application n'a pas besoin de fiabilité, UDP lui permet un débit maximum. Si elle a besoin d'une sémantique plus forte, elle doit la mettre en œuvre elle-même.

Un autre service important fourni par TCP ou ses homologues comme SCTP est le contrôle de congestion. Une application qui utilise UDP bêtement, en envoyant autant de données qu'elle le peut, risque de saturer le réseau, au détriment d'autres applications plus raisonnables. Si on utilise UDP pour des données en quantité importante, on doit assurer ce contrôle de congestion soi-même (RFC 3714, RFC 5348 et RFC 8085).

UDP n'apporte donc presque rien par rapport à IP seul. Son principal ajout est la notion de ports. Le paquet UDP indique deux nombres, le port de source et le port de destination, qui, avec les adresses IP, servent à identifier les deux processus qui communiquent. L'application a typiquement indiqué le port souhaité en appelant bind.

Le RFC est ultra-court, seulement trois pages, reflet d'une époque où les protocoles étaient spécifiés avec quelques grands principes plutôt qu'avec un luxe de détails, qui évoque désormais plutôt des textes juridiques. Les RFC d'il y a vingt-huit ans ne ressemblent guère à ceux d'aujourd'hui... Mais il faut aussi noter que la taille du RFC est le reflet de la simplicité d'UDP. Le RFC se contente essentiellement de spécifier le format (simple) de l'en-tête des paquets UDP. Si on analyse UDP avec pcap, il suffit (page 1 du RFC), pour le décoder, de :

/* UDP header */
struct sniff_udp {
	uint16_t        sport;	/* source port */
	uint16_t        dport;	/* destination port */
	uint16_t        udp_length;
	uint16_t        udp_sum;	/* checksum */
};
...	
const struct sniff_dns *dns;
...
udp = (struct sniff_udp *) (packet + SIZE_ETHERNET + size_ip);
source_port = ntohs(udp->sport);
dest_port = ntohs(udp->dport);
...		

Quels protocoles d'application utilisent UDP ? Le plus connu est le DNS, dont l'essentiel du trafic se fait en UDP. Le mode principal du DNS, « une requête / une réponse », chacune tenant souvent dans un paquet, correspond en effet bien à UDP. Au moment de la sortie de notre RFC 768, l'un des principaux utilisateurs d'UDP était d'ailleurs un ancêtre du DNS, Internet Name Service (IEN 116). Mais il y a aussi NTP (RFC 5905) et, depuis moins longtemps, les protocoles « multimédia » comme RTP (RFC 3550) qui ont typiquement des grandes quantités de données à faire passer, sans exigence qu'elles arrivent toutes (une trame vidéo en retard n'a plus aucun intérêt). Aujourd'hui, les protocoles de transmission de contenu multimédia (par exemple SIP, RFC 3261 pour la téléphonie sur IP) utilisent en général TCP pour le canal de contrôle et UDP pour les données, pour lesquelles l'acheminement de tous les paquets n'est pas vital.

On peut bien sûr utiliser aussi UDP pour les transferts de fichiers, qui ont besoin d'être parfaitement fiables. Cela suppose de gérer, au dessus d'UDP (qui n'assure pas ce service), un mécanisme permettant de s'assurer que tout a été bien transmis. C'est ce que fait le client BitTorrent de référence depuis fin 2008, une décision qui a suscité pas mal de remous (souvent exagérés).

Vu avec tcpdump, commande tcpdump -vvv -n udp, voici d'ailleurs un exemple de paquet UDP, en l'occurrence pour le DNS (une question et une réponse) :

16:03:11.436076 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 78) 192.134.7.248.15301 > 199.6.1.30.53: [bad udp cksum eaea!] 31425% [1au] Type32769? doleh.com.dlv.isc.org. ar: . OPT UDPsize=4096 OK (50)
16:03:11.451313 IP (tos 0x0, ttl 54, id 0, offset 0, flags [DF], proto UDP (17), length 775) 199.6.1.30.53 > 192.134.7.248.15301: 31425 NXDomain*- q: Type32769? doleh.com.dlv.isc.org. 0/6/1 ns: dlv.isc.org. SOA[|domain]

Les champs spécifiques d'UDP (protocole 17) sont le champ Longueur et les ports (ici, 53 et 15301).

UDP a aujourd'hui plusieurs camarades / concurrents dans la catégorie « protocole de transport sans connexion et non fiable ». C'est le cas de DCCP (RFC 4340). Il a aussi des ajouts ou des variantes comme DTLS (RFC 5238) pour la sécurité ou UDP-Lite (RFC 3828) pour encore moins de vérifications.

Et pour le programmeur ? Utiliser UDP n'est pas plus difficile que d'utiliser TCP, sauf si on veut assurer les mêmes services que TCP et qu'on met en œuvre la fiabilité des transferts. Sinon, un client UDP a « juste » à créer les prises avec l'option SOCK_DGRAM (au lieu de SOCK_STREAM), à appeler bind pour obtenir un port et à envoyer les paquets, par exemple avec sendto.

Un intéressant article historique de David Reed décrit l'histoire d'UDP.


Téléchargez le RFC 768


L'article seul

RFC 608: Host names on-line

Date de publication du RFC : Janvier 1974
Auteur(s) du RFC : M. D. Kudlick (Stanford Research Institute - Augmentation Research Center)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 10 décembre 2007
Dernière mise à jour le 8 janvier 2008


Deuxième RFC (après le RFC 606) à avoir proposé de mettre la liste de toutes les machines d'Arpanet en ligne, à une époque où le DNS était encore très loin dans le futur.

Avant le DNS, le RFC 606 suggérait de résoudre le problème lancinant de la mise à jour des fichiers hosts (carnets d'adresses de machines) en mettant en ligne, accessible à tous, un fichier de toutes les machines connues sur Arpanet, avec leurs adresses (c'était avant IPv4 et les adresses tenaient sur un octet). Notre RFC était l'acceptation officielle de ce projet par le NIC, projet qui allait devenir HOSTS.TXT, le fichier de référence d'Arpanet.

HOSTS.TXT durera de nombreuses années, recopié plus ou moins régulièrement par les machines d'Arpanet. Au bout d'un moment, sa taille croissante et la charge qu'impliquait son transfert, la difficulté de maintenir un fichier central de toutes les machines, et le fait que les copies locales n'étaient jamais à jour a mené au développement d'un système décentralisé et dynamique, le DNS, qui a fait disparaitre HOSTS.TXT. (Sur l'histoire du DNS, voir mon article « Quelques éléments d'histoire... ».)

Retrouver des versions anciennes de ce fichier a été un travail amusant. En commençant par les plus récentes, Geoffroy Rivat me signale qu'on peut récupérer une version de 1994, soit bien après que le DNS aie tout remplacé (et qu'on soit passé à IPv4). Noel Chiappa, lui, m'a indiqué une version encore plus ancienne, mais toujours en IPv4.

Il signale aussi une curieuse curieuse archive au format ITS, qu'on peut assez bien lire avec un éditeur normal et qui contient apparemment une copie du HOSTS.TXT de 1983 ! En voici un extrait :

HOST MIT-LISPM-9,	CHAOS 3074,USER,LISPM,LISPM,[CADR-9,CADR9,LM9]
HOST MIT-LISPM-TEST,	CHAOS 3024,USER,LISPM,LISPM,[CADR-TEST,LMTEST,TEST]
HOST MIT-MACEWAN,	LCS 12/120,SERVER,UNIX,VAX,[MACEWAN]
HOST MIT-MARIE,		CHAOS 7500,SERVER,VMS,VAX,[MARIE,MIT-LNS]
HOST MIT-MC,		[3/44,CHAOS 1440],SERVER,ITS,PDP10,[MC,MITMC]

Une autre copie des fichiers de cette époque se trouve en http://saildart.org/prog/NET/index.html. Voir par exemple un HOSTS.TXT de 1983 en http://saildart.org/prog/NET/HST_NET/.html/000071?70,37120.

Enfin, la version la plus ancienne a été extraite par Elizabeth Feinler, directrice du NIC à l'époque, et que je remercie beaucoup pour ses efforts. Une fois retrouvée une copie papier de 1974 (apparemment incomplète), Liz Borchardt et Dana Chrisler, du Computer History Musem, ont numérisé ce document. Les adresses étaient encore codées sur un seul octet... Une copie plus récente (1982, à l'époque du RFC 810, qu'elle avait écrit) montre des adresses IPv4, sur quatre octets.

On notera avec amusement dans ce RFC que le NIC utilisait à l'époque un programme pour transformer sa base de données en fichier HOSTS.TXT. Aujourd'hui, vingt-trois ans après, l'IANA n'a pas encore rattrapé cette étape et maintient toujours ses registres dans des fichiers texte, « à la main », avec les inévitables erreurs que ce processus archaïque entraine.


Téléchargez le RFC 608


L'article seul

RFC 606: Host names on-line

Date de publication du RFC : Décembre 1973
Auteur(s) du RFC : L. Peter Deutsch (Xerox Palo Alto Research Center (PARC), MAXC)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 5 octobre 2006


Ce RFC est le premier à proposer que la liste des machines de l'Arpanet soit mise en ligne, le futur HOSTS.TXT.

Avant notre RFC, plusieurs RFC (le premier étant le RFC 226) donnaient la liste exhaustive des machines de l'Arpanet, l'ancêtre de l'Internet. Ce mécanisme de distribution était lent, peu fiable et la liste, non structurée, n'était pas analysable par un programme. Notre RFC va donc proposer que la liste soit mise en ligne, dans un fichier central, écrit dans un format défini formellement. Ce sera le futur fichier HOSTS.TXT, décidé dans le RFC 608 et qui restera en vigueur jusqu'au déploiement du DNS.


Téléchargez le RFC 606


L'article seul

RFC 229: Standard host names

Date de publication du RFC : Septembre 1971
Auteur(s) du RFC : Jon Postel (University California Los Angeles (UCLA), Computer Science Department, Network Measurement Center (NMC))
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 24 octobre 2006


Un des tous premiers RFC à tenter d'organiser le nommage sur Arpanet, trente-cinq ans avant le SMSI.

Le premier a apparemment été le RFC 226. Mais notre RFC a deux avantages : il a été écrit par Jon Postel et il est le premier à avoir nommé une machine "SEX", des dizaines d'années avant le fiasco de .xxx, retiré sur pression des bigots (bon, je plaisante un peu, ce "SEX" faisait référence au Sigma EXperimental operating system).

Autrement, la liste est très proche de celle du RFC 226, mais plus détaillée. À l'époque, c'était le seul moyen dont disposait Arpanet, le futur Internet, pour permettre d'adresser une machine par son nom. Le DNS était encore très loin.


Téléchargez le RFC 229


L'article seul

RFC 226: Standardization of host mnemonics

Date de publication du RFC : Septembre 1971
Auteur(s) du RFC : Peggy Karp (MITRE)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 5 octobre 2006


Nostalgie des vieux RFC écrits tout en majuscules et avec une date non compatible avec l'an 2000... Notre RFC est le premier à formaliser la notion de nom de machine, douze ans avant l'invention du DNS.

Aucun mécanisme de résolution n'est envisagé (même pas un simple fichier de correspondances comme le futur HOSTS.TXT, des RFC 606 et RFC 608, qui connaitra une grande popularité avant que le DNS ne le remplace) mais il y a une table des noms officiels et de l'adresse correspondante (stockée sur huit bits).

Voici l'intégralité de cette table, qui constitue donc tout l'Arpanet, l'ancêtre de l'Internet de l'époque :

            HOST #             DESIGNATOR
              1                  UCLA
             65                  UCLA36
              2                  SRIARC
             66                  SRIAI
              3                  UCSB
              4                  UTAH
              6                  MULTCS
             70                  MITDM
              7                  RAND
              8                  SDC
              9                  HARV
             10                  LNCTX2
             74                  LNC360
             11                  STAN
             12                  ILL
             69                  BBN
            133                  BBNB
            144                  AMES
            145                  MITRE
            158                  TIP

Le RFC 229 écrit, lui, par Jon Postel, et plus complet ne surviendra qu'après. Au début des années 1970, plusieurs RFC prétendront être la liste complète de toutes les machines de l'Arpanet.

Merci à Olivier Ricou pour avoir déniché ce document.


Téléchargez le RFC 226


L'article seul

RFC 20: ASCII format for network interchange

Date de publication du RFC : Octobre 1969
Auteur(s) du RFC : Vint Cerf (University California Los Angeles (UCLA))
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 2 février 2007
Dernière mise à jour le 30 mars 2008


Un RFC venu du fond des âges, qui explique l'usage du code ASCII sur les réseaux.

C'était il y a bien longtemps. ASCII avait été inventé sept ans auparavant mais son usage n'allait toujours pas de soi et il avait des concurrents. Le monde civilisé ne parlait qu'anglais et personne n'aurait imaginé que les sinophones ou les arabophones allaient un jour demander à pouvoir utiliser leur écriture sur Internet.

En quelques pages, tout était réglé : ASCII devenait le codage standard de caractères sur Arpanet.

La convention que les deux caractères CR (Carriage Return) et LF (Line Feed) soient utilisés pour une fin de ligne n'est même pas explicite dans ce RFC. Elle n'est venue que plus tard.

À noter que l'IETF a désormais un RFC équivalent sur Unicode, le RFC 5198, qui renforce la pratique de l'usage d'Unicode encodé en UTF-8 (pratique encouragée par le RFC 2277).


Téléchargez le RFC 20


L'article seul

RFC 3: Documentation conventions

Date de publication du RFC : Avril 1969
Auteur(s) du RFC : Steve Crocker (University California Los Angeles (UCLA))
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 16 décembre 2012


Membre de la prestigieuse série des tous premiers RFC, publiés en même temps en 1969, ce RFC 3 expose le fonctionnement des RFC et pose donc le principe de l'ouverture des débats.

Il est ultra-court, comme l'étaient la plupart des RFC à l'époque. Mais son contenu est dense. Les deux points essentiels, qui pèseront lourdement dans le futur Internet, sont :

  • Discussion libre et ouverte des idées, sans considérer les documents écrits comme étant sacrés (le sigle de RFC, Request For Comments, appel à commentaires, vient de là).
  • Encouragement à publier sans se demander pendant des années si le texte est parfait.

Depuis, bien des électrons ont circulé dans les câbles. Les RFC ne sont plus des « appels à commentaires » mais des documents figés, qui ne changent pas après leur publication. Et celle-ci requiert de long et parfois pénibles débats. Mais l'idée que les idées doivent l'emporter par leur valeur et pas par un argument d'autorité reste.

La lecture de la liste des membres du Network Working Group (le futur IETF) dans ce RFC est instructive : essentiellement des étudiants, dont aucun ne pouvait imposer ses idées par ses titres et ses diplômes. Le concept de RFC vient de là.

Comme son titre l'indique, ce document contient aussi des conventions, comme le fait de numéroter les RFC (Bill Duvall était le premier RFC Editor, chargé de gérer ces numéros) et comme la longueur minimale d'un RFC (lisez le texte pour la connaître).

Merci à Laurent Chemla pour m'avoir signalé ce RFC dans un article récent.


Téléchargez le RFC 3


L'article seul

RFC 1: Host Software

Date de publication du RFC : Avril 1969
Auteur(s) du RFC : Steve Crocker (University California Los Angeles (UCLA))
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 10 juillet 2009


Un document historique, le premier des RFC. Cette série de documents, qui forme l'ossature de la normalisation de l'Internet a désormais un peu plus de quarante ans. L'auteur de ce RFC 1, Steve Crocker, a d'ailleurs publié un excellent article dans le New York Times pour célébrer cet anniversaire, How the Internet Got Its Rules, révélant que le RFC 1 avait été écrit dans une salle de bains.

Évidemment, le temps a passé. Techniquement, le RFC 1 n'a plus beaucoup d'utilité. Mais, outre son rang dans la série, il reste une lecture fascinante pour l'ingénieur, le souvenir d'une époque où une bande d'universitaires mettaient en place les fondations de ce qui allait devenir l'Internet.

Pour l'anecdote, notons que le dernier RFC écrit par Steve Crocker, le RFC 4986 sur DNSSEC, a été publié en août 2007, trente-huit ans après le premier. (Ne pas confondre avec les RFC, plus récents, de son frère Dave Crocker).

Le prédécesseur de l'Internet, l'Arpanet, existait déjà lorsque le RFC a été écrit. Suivant une tradition courante sur l'Internet, la documentation suit le déploiement. Ce réseau était composé de deux sortes de machines bien distinctes, les IMP (on dirait aujourd'hui les routeurs) et les machines terminales, les hosts. Les IMP étant fermés et contrôlés par une entreprise privée, BB&N, les étudiants comme Crocker étaient laissés avec le host software. Le RFC 1, contrairement aux RFC récents, méritait bien son nom d'« Appel à commentaires ». Il contient autant de questions que de réponses.

Donc, à l'époque, les données circulaient dans des messages (les termes comme paquet n'existaient pas encore). L'en-tête de ces messages faisait seulement 16 bits dont cinq (!) étaient réservés à l'adresse de destination. Il ne pouvait donc y avoir que 32 machines sur le premier Arpanet (IPv4 passera à 32 bits en 1981 et IPv6 à 128 en 1995). Parmi les autres champs de l'en-tête, un bit Trace qui indiquait à l'IMP d'envoyer une copie du message au Network Measurement Center, pour déboguage...

Plus étonnant, l'en-tête comporte un champ nommé Link qui indique une connexion entre deux machines. Ces connexions n'étaient pas établies ou coupées à la demande mais fixes. (Le fait que les ressources soient allouées statiquement était courant dans les systèmes d'exploitation de l'époque.) Les connexions étaient au nombre de 32, maximum, et le RFC se demande à juste titre pourquoi le champ Link fait huit bits (il semble que personne ne se souvienne de la raison).

Après cette description très sommaire du logiciel, le RFC liste les usages prévus, et les exigences que doit suivre ce logiciel. Ainsi, le principal usage envisagé est la connexion à distance (dans le style du futur telnet).

La question de la latence du réseau revient souvent dans le RFC. Avec le temps que prend un message pour aller et venir (environ une seconde à l'époque), des problèmes comme l'écho des caractères tapés localement allaient être pénibles.

Si certains problèmes ont disparu avec le temps (ou bien ont diminué d'acuité comme la question de la latence), d'autres restent d'actualité. Ainsi, le RFC 1 insiste sur le fait que la machine doit mettre en œuvre de la correction d'erreurs, même si BB&N jure que l'IMP le fait déjà (« nous les croyons mais nous vérifions »). Une question qui préfigure les futurs débats sur le principe de bout en bout.

Si les connexions entre machines sont permanentes, à bord de chaque machine, les programmes n'ont pas d'accès au lien avant de l'avoir demandé explicitement. Chaque système d'exploitation d'une machine Arpanet doit donc fournir des fonctions de gestion de la connexion (et, bien sûr, d'envoi et de réception des données via la connexion). La fonction doit indiquer si la connexion sera plutôt utilisée pour l'accès à distance ou plutôt pour le transfert de fichiers (auquel cas la gestion des tampons est différente et il n'y a pas d'échappement des caractères de contrôle).

L'accès à distance étant de loin la principale application envisagée, et le problème étant très riche, une section entière du RFC discute des besoins particuliers de ce service. Par exemple, compte-tenu des problèmes de latence, le RFC recommande que la gestion de certains caractères comme le caractère de suppression soit effectuée localement. Mais le RFC allait plus loin en proposant un langage entier de description des terminaux, nommé DEL.


Téléchargez le RFC 1


L'article seul

RFC des différentes séries : 0  1000  2000  3000  4000  5000  6000  7000  8000