Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

Ce blog n'a d'autre prétention que de me permettre de mettre à la disposition de tous des petits textes que j'écris. On y parle surtout d'informatique mais d'autres sujets apparaissent parfois.


Lire des paquets capturés sur le réseau en C

Première rédaction de cet article le 23 décembre 2008


Il y a des tas de raisons de vouloir lire soi-même les paquets capturés sur le réseau. Cela peut être par curiosité, par souci de sécurité (ou pour pirater !) ou bien pour faire des statistiques. Pour un rapide coup d'œil, on utilise en général tcpdump, pour un examen interactif détaillé, l'excellent Wireshark mais, pour des études à long terme, il vaut mieux programmer et développer un programme d'analyse spécifique, ce que je fais ici en langage C.

Souvent les articles sur la question parlent ensemble de la capture des paquets et de leur analyse. Ici, je ne mentionne que l'analyse, supposant que la capture a été faite par d'autres moyens, par exemple tcpdump -w FICHIER ou bien pcapdump.

L'outil d'analyse le plus fréquent pour les programmeurs C est libpcap. Il existe un excellent tutoriel d'introduction.

Je commence par un programme trivial, qui lit un fichier au format pcap, capturé par un des outils cités dans « Capturer les paquets qui passent sur le réseau », et qui décode suffisamment d'IPv4 pour afficher le protocole de transport utilisé. L'essentiel du programme est :

/* Ouvrir le fichier pcap */
handle = pcap_open_offline(filename, errbuf);
/* Parcourir le fichier */
while (1) {
    packet = pcap_next(handle, &header);
    /* Décoder l'en-tête Ethernet en convertissant le packet en une
    struct */
    ethernet = (struct sniff_ethernet *) (packet);
    /* Si c'est de l'IPv4 */
    if (ntohs(ethernet->ether_type) == IPv4_ETHERTYPE) {
          /* Décoder IPv4 : convertir le paquet en une struct. Ne pas
	  oublier de décaler de SIZE_ETHERNET octets */
          ip = (struct sniff_ip *) (packet + SIZE_ETHERNET);
          /* Afficher */
          printf ("Paquet IPv4 avec le protocole %d\n", ip->ip_p);

Notons bien qu'il faut utiliser ntohs pour convertir le paquet dans la bonne boutianité. Le code complet du programme est disponible en readfile-ipv4.c. On peut le compiler sur Unix avec :

cc -o readfile -lpcap readfile.c

(Si libpcap est bien présente. Sur une Debian, il aura fallu installer le paquetage libpcap-dev.)

On note qu'il a fallu faire le décodage soi-même, en travaillant au niveaux des bits de l'en-tête du paquet IP. Cela nécessite donc de connaitre le protocole décodé. Pour IPv4, il faut donc lire le RFC 791, section 3.1.

Et pour IPv6 ? Le format est décrit dans le RFC 2460, section 3. Traduisons-le en C :

/* IPv6 header. RFC 2460, section3. 
   Reading /usr/include/netinet/ip6.h is interesting */
struct sniff_ip {
	uint32_t         ip_vtcfl;	  /* version then traffic class
	                                     and flow label */
	uint16_t         ip_len;	  /* payload length */
	uint8_t          ip_nxt;	  /* next header (protocol) */
	uint8_t          ip_hopl;	  /* hop limit (ttl) */
	struct in6_addr  ip_src, ip_dst;  /* source and dest address */
};

Il suffit ensuite de « plaquer » cette définition sur le paquet :

if (ntohs(ethernet->ether_type) == IPv6_ETHERTYPE) {
	ip = (struct sniff_ip *) (packet + SIZE_ETHERNET);

et hop, on a un paquet IPv6 à analyser. On peut par exemple lire ip->ip_nxt qui contient le type du prochain en-tête (en général, la couche transport, mais attention, avec IPv6, d'autres en-têtes intermédiaires peuvent être présents). Le programme complet est en readfile-ipv6.c.

Si on veut décoder des protocoles de plus haut niveau, c'est souvent plus complexe. Prenons le DNS comme exemple. Le format est décrit dans le RFC 1035, section 4.1. Il peut se traduire en :

struct sniff_dns {
	/* RFC 1035, section 4.1.1 */
	uint16_t         query_id;
	uint16_t         codes;
	uint16_t         qdcount, ancount, nscount, arcount;
};

(Cela ne contient que l'en-tête DNS, il existe également des champs ultérieurs pour stocker la requête, la réponse, etc.)

Les codes sont des bits ou des groupes de bits et, pour y accéder, il faut faire de l'arithmétique de bits. Je définis des macros pour cela :

#define DNS_QR(dns)		((ntohs(dns->codes) & 0x8000) >> 15)
#define DNS_OPCODE(dns)	((ntohs(dns->codes) >> 11) & 0x000F)
#define DNS_RCODE(dns)	(ntohs(dns->codes) & 0x000F)

Ainsi, DNS_QR va extraire le bit 15, qui indique si le paquet est une requête ou bien une réponse (on masque avec une valeur où seul ce bit est à 1, 0x8000, puis on décale vers la droite). Une fois le paquet décodé :

if (source_port == DNS_PORT || dest_port == DNS_PORT) {
     dns = (struct sniff_dns *) (packet + SIZE_ETHERNET + 
                                        size_ip + SIZE_UDP);

on peut utiliser ces macros pour afficher le contenu du paquet, par exemple :

DNS_QR(dns) == 0 ? "Query" : "Response"

Le code complet figure en readfile-ipv6-dns.c.

Les programmeurs Python peuvent regarder mon article équivalent pour Python.


L'article seul

RFC 4995: The RObust Header Compression (ROHC) Framework

Date de publication du RFC : Juillet 2007
Auteur(s) du RFC : L-E. Jonsson (Optand), G. Pelletier (Ericsson), K. Sandlund (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF rohc
Première rédaction de cet article le 22 décembre 2008
Dernière mise à jour le 30 mars 2010


Quels que soient les progrès des technologies, il n'y a jamais assez de capacité. Même aujourd'hui, les vieux modems restent en service (y compris dans un pays riche, mais étendu, comme les États-Unis) et certaines technologies récentes offrent une capacité limitée (par exemple sur les téléphones mobiles). Il est donc utile de pouvoir comprimer les données et aussi les en-têtes des paquets émis, qui sont souvent très redondants, ouvrant ainsi de bonnes perspectives pour la compression. Plusieurs mécanismes de compression ont été inventés et le projet ROHC (Robust Header Compression) a été créé pour mettre de l'ordre dans ces mécanismes, en développant un cadre commun. Ce RFC spécifie ce cadre.

La section 1 du RFC, l'introduction, donne quelques chiffres sur les gains qu'on peut tirer de la compression. Par exemple, si on utilise RTP (RFC 3550) pour transporter de la voix sur IP, il faudra transporter les 40 octets de l'en-tête (en IPv6), les 12 octets de l'en-tête UDP et les 8 octets de l'en-tête RTP (sans compter les en-têtes de la couche liaison). Ainsi, un paquet de données de 20 octets (une taille courante en voix sur IP) pourrait nécessiter 60 octets d'en-têtes TCP/IP.

Le RFC originel sur ROHC était le RFC 3095 qui incluait à la fois le cadre général et les profils de compression pour certains protocoles (un profil est un protocole de compression donné, adapté à un certain protocole). Une réforme générale de ROHC a eu lieu et il est désormais normalisé dans plusieurs RFC, notre RFC 4995, à l'origine, pour le cadre général, les RFC 4996 et RFC 5225 pour des profils pour, respectivement, TCP et les protocoles sans connexion comme IP ou UDP, le RFC 4997 pour le langage formel de définition des compressions, etc. (Le RFC 3095 n'est pas officiellement abandonné puisque le protocole est le même, il est juste mieux décrit.) Depuis, le RFC 5795 est sorti, remplaçant notre RFC 4995 en corrigeant quelques bogues.

La section 3 du RFC décrit les bases de la compression. Le principe est que le compresseur ne transmette pas certaines informations, car elles n'ont pas changé, ou bien peuvent être déduites automatiquement. Cela implique que le décompresseur puisse se souvenir de l'état de la compression, ce que ROHC nomme le contexte (la section 2.2 décrit toute la terminologie). Le maintien de ce contexte, même en présence de perturbations sur le réseau, est le principal défi de la compression. Sur des liens de mauvaise qualité (par exemple avec beaucoup de pertes), les mécanismes de compression pré-ROHC se comportaient plutôt mal (voir aussi la section 1).

Naturellement, rien n'est gratuit : le gain en capacité du réseau sera obtenu au détriment de la puissance de calcul, puisque compression et décompression nécessitent des calculs. La vitesse des processeurs des téléphones portables augmentant plus vite que leur capacité réseau, le choix de la compression semble raisonnable.

La section 3.2 rappelle l'histoire de la compression. Le premier grand travail dans le monde TCP/IP avait été la compression des en-têtes TCP par Van Jacobson en 1990 (RFC 1144), dont tous les utilisateurs de SLIP dans les années 1980 et 90 se souviennent (« Tu es sûr d'avoir activé la compression VJ ? »).

La section 4 décrit de manière relativement informelle le fonctionnement de ROHC, notamment (section 4.1), les différentes classes de changement dans les en-têtes, qui permettent leur prédiction par le décompresseur. Ainsi, la classe STATIC décrit les informations qui ne changent pas pendant la durée du flux de données (le numéro de version IP par exemple), la classe INFERRED étant composée des en-têtes qui peuvent se déduire ou se calculer à partir d'autres informations (comme la taille du paquet).

La vraie définition de ROHC est en section 5. C'est là qu'on trouve, par exemple, la description du mécanisme de rétroaction (section 5.2.4) qui permet au décompresseur de tenir le compresseur au courant du succès (ou de l'échec) de son travail. Autre exemple (section 5.1.2), chaque canal de communication ROHC a, parmi ses paramètres, un identificateur du profil utilisé (la liste des identificateurs possibles est dans un registre IANA, voir également la section 8). La section 5.4 normalise ainsi le profil d'identificateur 0x0000, le profil qui ne fait rien (en oubliant une partie, ce qui a été corrigé dans le RFC 5795), les profils « actifs » étant définis dans d'autres RFC.

Des déploiements de ROHC sont déjà faits dans les téléphones portables. Il existe une implémentation libre, RObust Header Compression (ROHC) library (merci à Didier Barvaux pour cela), tirée d'une plus ancienne bibliothèque. La section 6 du RFC 3095 contient une excellent section sur les problèmes concrets de mise en œuvre de ROHC (section qui ne semble pas avoir été reprises dans les RFC plus récents).


Téléchargez le RFC 4995


L'article seul

Lire des paquets capturés sur le réseau en Python

Première rédaction de cet article le 17 décembre 2008


Il y a des tas de raisons de vouloir lire soi-même les paquets capturés sur le réseau. Cela peut être par curiosité, par souci de sécurité ou bien pour faire des statistiques. Pour un rapide coup d'œil, on utilise en général tcpdump, pour un examen interactif détaillé, l'excellent Wireshark mais, pour des études à long terme, il vaut mieux programmer et développer un programme d'analyse spécifique.

Souvent les articles sur la question parlent ensemble de la capture des paquets et de leur analyse. Ici, je ne mentionne que l'analyse, supposant que la capture a été faite par d'autres moyens, par exemple tcpdump -w FICHIER ou bien pcapdump.

L'outil d'analyse le plus fréquent pour les programmeurs C est libpcap (dont je parle dans « .Lire des paquets capturés sur le réseau en C »). Et en Python ? Il existe plusieurs interfaces à la libpcap, notamment pylibpcap et pcapy. pcapy semble de plus haut niveau et c'est celle que j'utilise.

pcapy peut faire la capture et la lecture des fichiers au format pcap. Ses capacités d'analyse sont limitées, on utilise en général la bibliothèque impacket, des mêmes auteurs, ou bien carrément scapy.

Voici un programme simple de lecture d'un fichier pcap, tel que produit par tcpdump :

import pcapy

reader = pcapy.open_offline("mydata.pcap")

while True:
    try:
        (header, payload) = reader.next()
        print "Got a packet of length %d" % header.getlen()
    except pcapy.PcapError:
        break

Il ne semble pas y avoir de moyen de détecter la fin du fichier à part en récupérant l'erreur très générique PcapError.

payload est juste une chaîne non décodée d'octets, représentés en caractères. Si je veux l'analyser, je peux le faire « à la main » avec les fonctions de manipulation binaire de Python. Cela nécessite évidemment de lire les différentes normes pour connaître le format des paquets :


import pcapy

reader = pcapy.open_offline("mydata.pcap")

while True:
    try:
        (header, payload) = reader.next()
        # Ethernet type is two-bytes long and starts at 12 (before, you
        # have the MAC addresses)
        if payload[12:14] == '\x86\xDD': # 0x86DD is the Ethernet type for IPv6
            ip_payload = payload[14:]
            ip_version = (ord(ip_payload[0]) & 0xf0) >> 4
            if (ip_version != 6):
                raise Exception("Packet has ethernet type of IPv6 but internal IP version is %d" % ip_version)
            next_header = ord(ip_payload[6]) # RFC 2460, section 3 to know the offset
            print "Next header (probably the transport protocol) is %d" % next_header
    except pcapy.PcapError:
        break

Ici, on teste le type indiqué dans l'en-tête Ethernet pour ne garder que 0x86DD (IPv6). On saute les quatorze premiers octets (la taille de l'en-tête Ethernet) pour récupérer le paquet IPv6 que l'on décode en suivant le RFC 2460. Le numéro de version fait moins d'un octet, d'où les manipulations de bits avec & et >>.

Mais il peut être plus simple d'utiliser la bibliothèque impacket, conçue pour faciliter le décodage :

import pcapy
import impacket.ImpactDecoder as Decoders

reader = pcapy.open_offline("mydata.pcap")
decoder = Decoders.EthDecoder()

while True:
    try:
        (header, payload) = reader.next()
        result = decoder.decode(payload)
        # https://www.iana.org/assignments/ethernet-numbers
        if result.get_ether_type() == 0x86DD: # IPv6
            print "Got an IPv6 packet of length %d" % header.getlen()
    except pcapy.PcapError:
        break

Ici, plus besoin de connaître la structure de l'en-tête Ethernet, on peut utiliser get_ether_type() au lieu de payload[12:14].

Cela va permettre de s'attaquer à des protocoles de plus haut niveau, souvent plus complexes à décoder. Commençons par UDP :

import pcapy
import impacket.ImpactDecoder as Decoders
import impacket.ImpactPacket as Packets

reader = pcapy.open_offline("mydata.pcap")
eth_decoder = Decoders.EthDecoder()
ip_decoder = Decoders.IPDecoder()
udp_decoder = Decoders.UDPDecoder()

while True:
    try:
        (header, payload) = reader.next()
        ethernet = eth_decoder.decode(payload)
        if ethernet.get_ether_type() == Packets.IP.ethertype:
            ip = ip_decoder.decode(payload[ethernet.get_header_size():])
            if ip.get_ip_p() == Packets.UDP.protocol: 
                udp = udp_decoder.decode(
                    payload[ethernet.get_header_size()+ip.get_header_size():])
                print "IPv4 UDP packet %s:%d->%s:%d" % (ip.get_ip_src(),
                                                        udp.get_uh_sport(),
                                                        ip.get_ip_dst(),
                                                        udp.get_uh_dport())
    except pcapy.PcapError:
        break

Ce programme affiche les paquets UDP sur IPv4 en indiquant les adresses et ports de source et de destination. On note qu'il n'y a pas eu besoin de lire le RFC 768, tout est pris en charge par Impacket (y compris le problème, que j'ai soigneusement évité dans l'exemple du décodage manuel, de l'ordre des octets dans les champs multi-octets). Il faut juste penser, à chaque fois qu'on grimpe d'une couche, à se décaler dans le paquet (du résultat de get_header_size() sur la couche précédente).

Pour le décodage de l'en-tête IP, Impacket ne dispose malheureusement que d'un décodeur IPv4. Pour IPv6, il faut l'écrire soi-même, peut-être plutôt en utilisant Scapy. Ce sera pour un autre article.


L'article seul

Capturer les paquets qui passent sur le réseau

Première rédaction de cet article le 17 décembre 2008
Dernière mise à jour le 27 mars 2009


Lire les paquets qui passent sur le réseau est une activité indispensable pour l'étudiant qui apprend les réseaux informatiques, pour l'administrateur système qui débogue un problème, pour le chercheur qui rassemble des statistiques ou simplement pour le curieux qui veut s'instruire. Mais avant de pouvoir les lire et les analyser, il faut les capturer. Quels sont les outils disponibles ?

Tout le monde connait et utilise tcpdump, qui permet à la fois de capturer et de décoder les paquets. Pour un coup d'œil rapide, c'est parfait. Mais pour des études plus lourdes, il est souvent recommandé de séparer la capture des données (qui doit pouvoir tourner longtemps, sans trop charger la machine) de leur analyse (souvent très consommatrice en ressources et qui peut parfaitement être faite hors-ligne). Cet article se focalise sur les outils de capture, l'analyse étant faite ailleurs, avec un programme d'exploration comme Wireshark ou bien avec un programme qu'on a développé soi-même, par exemple en Python.

Un bon logiciel de capture doit pouvoir :

  • Tourner longtemps, tout en écrivant dans des fichiers, de préférence en sachant passer d'un fichier à l'autre lorsque les fichiers de capture deviennent trop gros, ou bien à l'issue d'un certain délai.
  • Pouvoir filtrer les événements intéressants, de façon à ne pas stocker n'importe quoi sur le disque. À cette fin, tous les logiciels de capture disposent d'un mini-langage permettant de dire quels sont les « événements intéressants ». La puissance expressive de ce langage est un des principaux critères qui distinguent ces logiciels.
  • Ne pas trop charger la machine (c'est une autre raison pour laquelle le filtrage est important mais attention, il peut lui-même consommer beaucoup de ressources), au cas où elle fasse tourner des services de production, et afin d'éviter de perdre des paquets (ce que font les logiciels de capture lorsqu'ils n'arrivent plus à suivre).

Presque tous les logiciels de capture enregistrement au format « pcap », celui de la libpcap.

Voyons les logiciels possibles. L'ancêtre tcpdump, très connu de tous les administrateurs réseaux, reste parfaitement utilisable pour cette tâche. Son option -w permet d'enregistrer les événements, qui pourront ensuite être lus par tout logiciel capable de lire du pcap (y compris tcpdump lui-même, avec l'option -r).

% tcpdump -i eth2 -w mydata.pcap
tcpdump: listening on eth2, link-type EN10MB (Ethernet), capture size 96 bytes
[Control-C]
41 packets captured
41 packets received by filter
0 packets dropped by kernel

Et mydata.pcap peut être analysé ensuite à loisir. tcpdump dispose de nombreuses options qui peuvent être utiles pour la capture comme -c (s'arrêter après un nombre donné de paquets) ou -C (donne une taille maximale au fichier), même si elles sont moins perfectionnées que celles des logiciels récents.

tcpdump dispose d'un langage de filtrage, nommé BPF et qui permet d'exprimer des choses simples comme « uniquement les paquets venant de 192.0.2.3 » ou « uniquement les paquets à destination du port 80 » ou encore « uniquement les paquets à destination de 2001:db8:1::deca:fbad, et venant du port 53 ». Voici cette dernière :

% tcpdump -i eth2 -w mydata.pcap \
            dst host 2001:db8:1::deca:fbad and \
            src port 53

L'analyseur Wireshark a des mécanismes de décodage des paquets bien plus riches que ceux de tcpdump. Il vient avec un programme en ligne de commande, tshark qui peut être utilisé pour la capture :

 
% tshark -i eth2  -w mydata.pcap 
Capturing on eth2
340 
[Control-C]

Notez l'affichage en temps réel du nombre de paquets capturés, bien pratique. Ses options de capture sont plus perfectionnées que celles de tcpdump, par exemple -a permet de stopper celle-ci après qu'un temps donné se soit écoulé. En mode « plusieurs fichiers », les noms des fichiers sont plus parlants qu'avec tcpdump, etc.

tshark dispose d'un langage de filtrage plus perfectionné, documenté dans Display Filter Reference. Par exemple, si on regarde les requêtes DNS, tshark peut filtrer avec des règles comme « uniquement les réponses ». Mais attention, il ne s'agit que de filtre d'affichage, le langage des filtres de capture est bien plus sommaire, c'est le même que celui de tcpdump (on peut trouver plein d'exemples sur le site de Wireshark). La raison de cette limitation est probablement que la capture doit aller vite, sans nécessiter de copier des paquets depuis le noyau et que le langage BPF, lui, peut tourner entièrement dans le noyau.

Pour des options de capture encore plus riches, on peut regarder pcapdump. Il fait partie d'un groupe de programmes utilisant pcap, développés spécialement pour Debian, mais qui peuvent être compilés sur d'autres systèmes. Par exemple, sur Gentoo, il faut installer la bibliothèque Judy (emerge judy) puis simplement utiliser make pour compiler. Ensuite, on copie les exécutables (dans src/) à la main.

Les forces de pcapdump, un logiciel spécialisé dans la capture, sont notamment ses capacités de tourner en démon (l'option n'est pas évidente à trouver, c'est -P, par exemple pcapdump -P /var/run/pcapdump.opid -C $(pwd)/dns.pcapdump), de changer de fichier sur plusieurs critères, de nommer les fichiers de capture selon un modèle qu'on choisit, d'échantilloner en n'enregistrant qu'un paquer sur N, etc. Il peut aussi lire ces options dans un fichier de configuration, dont voici un exemple qui lit les paquets DNS (port 53) et change de fichier tous les jours :

device=eth0
bpf="udp and port 53"
interval=86400
snaplen=512
promisc=0
filefmt=/var/tmp/pcapdump/eth0.%Y%m%d.%H%M.%S.pcap
mode=0600
owner=smith
group=root

Si on veut des filtres de capture très sophistiqués (tous les logiciels précédents se limitent au langage BPF), il faut les programmer soi-même ou bien utiliser un logiciel spécialisé comme dnscap. Ce programme dispose de filtres de capture spécifiques au DNS, par exemple on peut sélectionner uniquement les réponses et seulement celles qui sont négatives (NXDOMAIN, ce domaine n'existe pas).

dnscap n'a pas de documentation en ligne, tout est dans la page de manuel incluse dans la distribution. Sa compilation n'est pas toujours évidente. Sur Gentoo ou Debian, il faut ajouter dans le Makefile :

PORTLIBS= /usr/lib/libresolv.a
BINDLIB=-lbind9

Voici un exemple d'utilisation de dnscap, pour ne capturer que les paquets de réponses (-sr), et seulement si la réponse est négative (nom de domaine inexistant, -ex) et juste si la question concernait le domaine sources.org :

% dnscap -x 'sources\.org' -i eth0 -sr -g -ex 

Comme pcapdump, il permet de changer automatiquement de fichier de capture en cours de route (par exemple avec -t 86400 pour tourner tous les jours), ce qui le rend utilisable pour des études sur le long terme.

Contrairement aux filtres BPF, le filtrage fait par dnscap est effectué dans l'espace utilisateur, pas dans le noyau. Il a donc fallu copier le paquet dans ledit espace et effectuer des opérations parfois complexes avant de décider de le garder ou pas. Les capacités de capture peuvent donc s'en ressentir.

Une fois les paquets capturés, il existe plusieurs programmes tout faits pour afficher des informations sur ces captures ou pour les modifier. Par exemple, Wireshark est livré avec deux utilitaires en ligne de commande très pratiques. editcap permet de sélectionner une partie d'une capture, en indiquant les numéros d'ordre des paquets qu'on veut garder :

% editcap -r large.pcap small.pcap 1-1000
Add_Selected: 1-1000
Inclusive ... 1, 1000

gardera les mille premiers paquets du fichier large.pcap. capinfos permet d'obtenir des informations sur un fichier de trace :

% capinfos small.pcap 
...
File encapsulation: Ethernet
Number of packets: 1000 
File size: 210439 bytes
Data size: 371542 bytes
Capture duration: 23.338821 seconds
Start time: Mon Mar  2 21:41:57 2009
End time: Mon Mar  2 21:42:21 2009
...

Et si on développe un programme soi-même ? C'est assez facile, dans plusieurs langages de programmation. On peut ainsi choisir les critères de capture à volonté mais il faut prendre garde aux performances : beaucoup de paquets peuvent arriver en très peu de temps.

En langage C, libpcap, maintenue par les responsables de tcpdump, est une solution très répandue, très bien documentée, et qui marche bien. Écrire un programme de capture est assez simple.

Voici un exemple du squelette d'un tel programme (montrant la capture mais pas l'écriture sur disque), sniff-only.c. Il se compile, par exemple, avec :

% gcc -Wall -o sniff -lpcap sniff-only.c

Un bon article d'introduction à la libpcap, et à la définition de filtres de capture est Programming with Libpcap - Sniffing the network from our own application.

Pour la programmation en C, une alternative à pcap est ncap, que je n'ai pas testé. Il semble que son format de stockage soit incompatible avec pcap.

Il existe d'autres programmes de capture que je n'ai pas testés :

  • Grok
  • dumpcap qui, comme tshark, fait partie de Wireshark.

L'article seul

Recherche en plein texte avec PostgreSQL

Première rédaction de cet article le 11 décembre 2008


Traditionnellement, les SGBD ne traitaient que des données simples et courtes, comme le nom d'un employé ou son salaire. Les recherches portaient donc sur la totalité du champ. Désormais, il est de plus en plus fréquent de voir un SGBD utilisé pour stocker des textes relativement longs (des articles d'un blog, par exemple) et la recherche dans ces textes devient très longue et peu pratique. Elle nécessite l'indexation et des outils de recherche spécialisés. Qu'en est-il sur PostgreSQL ?

Pendant longtemps, le moteur de recherche plein texte de PostgreSQL était tsearch2. Distribué dans le répertoire contrib/ de PostgreSQL, il devait être installé séparément (ou via un paquetage du système d'exploitation considéré, par exemple databases/postgresql82-tsearch2 sur NetBSD). Désormais, depuis la version 8.3, il est intégré complètement à PostgreSQL, et pourvu d'une excellente documentation, très détaillée.

Le principe est de couper le texte en élements lexicaux, puis en lexèmes, qui sont des versions normalisées des éléments lexicaux. Cela se fait avec la fonction to_tsvector :

essais=> SELECT to_tsvector('les gros chats mangent les rats maigres');
                       to_tsvector                        
----------------------------------------------------------
 'le':1,5 'rat':6 'chat':3 'gros':2 'maigr':7 'mangent':4
(1 row)

Ici, elle a analysé la phrase, trouvé six mots (dont un répété) et réduit (normalisé) ceux qu'elles pouvaient. Ce processus dépend de la langue et donne parfois des résultats surprenants (« mangent » n'a pas été normalisé en « manger »).

On cherche ensuite dans ces éléments lexicaux avec la fonction de correspondance, @@. Elle prend comme paramètres un vecteur (tsvector) comme celui ci-dessus et une requête, créée avec to_tsquery :

essais=> SELECT to_tsquery('chat|rat');
   to_tsquery   
----------------
 'chat' | 'rat'
(1 row)

Le langage des requêtes (vous avez sans doute déjà deviné que | veut dire OU) est évidemment documenté.

En combinant requête, vecteur de mots et opérateur de correspondance, on peut faire une recherche complète :

essais=> SELECT to_tsvector('les gros chats mangent les rats maigres')
                        @@ to_tsquery('chat|rat');
 ?column? 
----------
 t
(1 row)

essais=> SELECT to_tsvector('on ne parle pas de ces animaux ici') 
                        @@ to_tsquery('chat|rat');
 ?column? 
----------
 f
(1 row)

On a trouvé un résultat dans le premier cas et zéro dans le second.

Bien sûr, taper de telles requêtes à la main est plutôt pénible, on a donc intérêt à créer ses propres fonctions.

L'analyse d'une phrase en mots et la normalisation de ces derniers dépend de la langue. Il y a un paramètre à to_tsvector et to_tsquery qui indique une configuration ('french' par défaut, sur mon site). Voyons quelles configurations a une installation typique de PostgreSQL 8.3 (ici, le paquetage Debian) :

essais=> \dF
               List of text search configurations
   Schema   |    Name    |              Description              
------------+------------+---------------------------------------
...
 pg_catalog | finnish    | configuration for finnish language
 pg_catalog | french     | configuration for french language
 pg_catalog | german     | configuration for german language
...

essais=> show default_text_search_config;
 default_text_search_config 
----------------------------
 pg_catalog.french
(1 row)

Prenons maintenant un exemple réel, un moteur de recherche dans la liste des RFC. On commence par créer la base :

-- Un RFC a un numéro, un titre et le corps, du texte brut
CREATE TABLE Rfcs (id SERIAL,
   inserted TIMESTAMP default now(),
   num INTEGER,
   title TEXT,
   body TEXT);

-- Créer son propre type facilite l'utilisation de la fonction search()
CREATE TYPE Results AS (num INTEGER, title TEXT, 
                        body TEXT, rank REAL);

-- Les RFC sont en anglais donc on utilise systématiquement la
-- configuration 'english'
CREATE FUNCTION search (TEXT) RETURNS SETOF Results AS
   'SELECT num, title, 
           body, ts_rank_cd(to_tsvector(''english'', title || body), 
                            to_tsquery(''english'',$1)) 
      FROM Rfcs	
         WHERE to_tsvector(''english'', title || body) @@ to_tsquery(''english'',$1) 
         ORDER BY ts_rank_cd(to_tsvector(''english'', title || body), 
                             to_tsquery(''english'',$1)) DESC;' 
  LANGUAGE SQL;

La fonction search() appelle une fonction ts_rank_cd qui calcule la pertinence d'un texte par rapport à une requête. Il faut aussi remarquer la concaténation des champs (title || body) qui indique qu'on cherche dans les deux colonnes. Testons search() :

essais=> SELECT num,title,rank FROM search('dnssec') ORDER BY rank DESC;
 num  |                         title                      | rank 
------+----------------------------------------------------+------
 4035 | Protocol Modifications for the DNS Security ...    | 10.1
 3130 | Notes from the State-Of-The-Technology: DNSSEC     |  7.4
 4641 | DNSSEC Operational Practices                       |  7.1
...

La recherche peut être plus compliquée, par exemple si on cherche les RFC qui parlent de DNSSEC et LDAP (notons que les pertinences sont bien plus faibles) :

essais=> SELECT num,title,rank FROM search('dnssec & ldap') ORDER BY rank DESC;
 num  |                     title                     |    rank     
------+-----------------------------------------------+-------------
 5000 | Internet Official Protocol Standards          |    0.111842
 4238 | Voice Message Routing Service                 |    0.0170405
 4513 | LDAP: Authentication Methods and Security ... |    0.00547112
...

Chercher dans la totalité de la base à chaque fois peut être assez long. Les moteurs de recherche emploient typiquement l'indexation pour accélerer la recherche. PostgreSQL dispose de plusieurs types d'index. Pour favoriser le temps de recherche (au détriment du temps d'indexation), j'utilise les index GIN :

CREATE INDEX rfcs_idx ON Rfcs USING gin(to_tsvector('english', title || body));

Avec ces index, les recherches sont bien plus rapides. En effet, sans index, il faut balayer toute la table comme l'indique EXPLAIN :

essais=> EXPLAIN SELECT id,num FROM Rfcs   WHERE to_tsvector('english', title || body)  @@ to_tsquery('dnssec');
                                    QUERY PLAN                                     
-----------------------------------------------------------------------------------
 Seq Scan on rfcs  (cost=0.00..186.11 rows=5 width=8)
   Filter: (to_tsvector('english'::regconfig, body) @@ to_tsquery('dnssec'::text))
(2 rows)

(Seq Scan est sequential scan.) Avec l'index, la recherche se fait d'abord dans l'index :

essais=> EXPLAIN SELECT id,num FROM Rfcs   WHERE to_tsvector('english', title || body)  @@ to_tsquery('dnssec');
                                         QUERY PLAN                                          
---------------------------------------------------------------------------------------------
 Bitmap Heap Scan on rfcs  (cost=40.70..57.34 rows=5 width=8)
   Recheck Cond: (to_tsvector('english'::regconfig, body) @@ to_tsquery('dnssec'::text))
   ->  Bitmap Index Scan on rfcs_idx  (cost=0.00..40.70 rows=5 width=0)
         Index Cond: (to_tsvector('english'::regconfig, body) @@ to_tsquery('dnssec'::text))
(4 rows)

Le programme qui prend l'ensemble des RFC et les met dans la base est index-rfcs.py. Un autre exemple pratique est le moteur de recherche de mon blog, documenté dans « Mise en œuvre du moteur de recherche de ce blog.

Sur le même sujet et dans la même langue, on peut lire le très détaillé « Recherche plein texte avec PostgreSQL 8.3 ».


L'article seul

RFC 5398: AS Number Reservation for Documentation Use

Date de publication du RFC : Décembre 2008
Auteur(s) du RFC : G. Huston
Pour information
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 11 décembre 2008


De même qu'il existe des adresses IP et des noms de domaine réservés à la documentation, les numéros d'AS de 64496 à 64511 et de 65536 à 65551 sont désormais réservés pour les auteurs des documentations sur le routage.

Écrire un cours sur le routage (comme mon cours BGP) nécessite de choisir les numéros d'AS qui apparaitront. Prendre des numéros existants est risqués car il y aura toujours un distrait pour copier-coller les configurations de routeurs qu'il a lu dans le cours, créant ainsi des problèmes avec l'AS qui a ce numéro.

Le même problème existe pour les adresses IP (d'où la réservation de 192.0.2.0/24, 198.51.100.0/24 et 203.0.113.0/24, dans le RFC 5737 ou de 2001:DB8::/32 dans le RFC 3849) ou pour les noms de domaine (pour lesquels .example a été réservé par le RFC 2606).

Comme le rappelle la section 1, même les numéros privés (pour les AS, de 64512 à 65534) ne conviennent pas puisqu'ils sont utilisés en production dans certains réseaux. C'est donc logiquement que notre RFC réserve deux plages de seize numéros d'AS pour la documentation : de 64496 à 64511 pour les AS sur deux octets et de 65536 à 65551 pour les AS sur quatre octets (ces derniers ayant été introduits par le RFC 4893, depuis remplacé par le RFC 6793).


Téléchargez le RFC 5398


L'article seul

RFC 5388: Information Model and XML Data Model for Traceroute Measurements

Date de publication du RFC : Décembre 2008
Auteur(s) du RFC : S. Niccolini (NEC), S. Tartarelli (NEC), J. Quittek (NEC), T. Dietz (NEC), M. Swany (UDel)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 11 décembre 2008


Le programme traceroute est un des piliers de l'Internet. Cet outil de débogage a servi à des dizaines de milliers d'administrateurs réseaux, lors de difficiles sessions de recherche de panne ou de divers problèmes. Né de la nécessité, il n'a jamais eu de modèle de données formel, ni de norme de présentation des résultats. C'est désormais fait avec ce nouveau document.

Cette normalisation permet notamment de stocker les résultats d'un traceroute et de les comparer de manière automatique à un autre (il existe déjà de tels programmes de comparaison, par exemple sous forme d'un moniteur pour le logiciel de surveillance réseau mon, mais tous ne comparent que la sortie texte de traceroute et peuvent donc être perturbés par des changements purement de présentation). La section 1 détaille ce cahier des charges.

La section 3 rappelle le principe de fonctionnement de traceroute : envoyer des paquets UDP (certaines versions peuvent utiliser TCP ou ICMP ; l'annexe A contient une très intéressante description des différentes versions de traceroute) à une machine distante, en mettant délibérement des valeurs trop basses au TTL (ou Hop Count) des paquets IP. Les routeurs qui, après la décrémentation de ce champ, trouveront zéro, signaleront leur existence en envoyant un paquet ICMP TIME_EXCEEDED (RFC 792).

La section 4 liste ensuite les résultats qu'on obtient avec traceroute. Selon la version de ce dernier, on peut trouver :

Enfin, la section 5 définit le modèle de données utilisé pour créer le fichier XML de résultats. 5.1 contient les types de données. Certains sont tirés des schémas du W3C comme Boolean ou DateTime, d'autres tirés d'autres RFC (par exemple le RFC 4001 pour InetAddress, les adresses IP), d'autres enfin définis ici. La section 5.2 donne la liste de tous les élements XML utilisés comme ProbeRoundTripTime (section 5.2.3.8) qui contient le RTT en millisecondes. On peut donc écrire :


<ProbeRoundTripTime>
   <roundTripTime>13</roundTripTime>
</ProbeRoundTripTime>

Cet élement ProbeRoundTripTime peut, alternativement, contenir un élément roundTripTimeNotAvailable.

La section 6 explique le choix de XML, notamment parce que les fichiers XML sont lisibles par un humain et parce qu'il existe un grand nombre d'outils existants. Cette section explique aussi pourquoi des modèles de données proches comme la MIB du RFC 4560 (également discutée en annexe C) ou l'encodage d'IPFIX dans le RFC 7011 n'ont pas été utilisés.

Enfin, une longue section 7 contient le schéma lui-même, défini avec le langage W3C Schema. L'élément ProbeRoundTripTime cité plus haut est ainsi défini comme le choix entre un entier ou la valeur roundTripTimeNotAvailable :


    <xs:element name="ProbeRoundTripTime"
                                 type="_roundTripTime">
    </xs:element>

    <xs:complexType name="_roundTripTime">
       <xs:choice>
  
       <xs:element name="roundTripTime">
           <xs:simpleType>
             <xs:restriction base="xs:unsignedInt"/>
           </xs:simpleType>
         </xs:element>

         <xs:element name="roundTripTimeNotAvailable">
           <xs:complexType/>
         </xs:element>

       </xs:choice>
     </xs:complexType>

Je ne connais pas encore d'implémentation « officielle » de traceroute qui produise ces fichiers XML. Si vous en écrivez une, attention aux caractères spéciaux (speciaux pour XML comme & ou <) dans les noms de machines : rien ne vous garantit qu'une requête DNS inverse ne va pas vous renvoyer des noms avec de tels caractères. Comme toujours quand un programme produit du XML, il ne doit pas se contenter de mettre des <balise> un peu partout, il doit aussi veiller à ces caractères spéciaux.

Il existe à ma connaissance une mise en œuvre expérimentale de traceroute qui produit du XML à ce format (dérivée du traceroute de NANOG). Elle est assez sommaire mais elle marche. traceroute-nanog-xml.c.

Il nécessite libxml2. Pour le compiler, sur GNU/Linux :

cc -DXML -lresolv  $(xml2-config --cflags) $(xml2-config --libs) \
             traceroute-nanog-xml.c -o traceroute-nanog-xml

Sur FreeBSD, même chose sans le -lresolv. Ensuite, on ne lance avec l'option -X pour produire du XML.

Une fois produits, les fichiers XML peuvent être vérifiés, par exemple avec xmllint :

% xmllint --noout --schema traceroute.xsd traceroute.xml
traceroute.xml validates

Voici des exemples de résultats stockés dans ce format, un exemple pris dans le RFC (annexe D) et un autre exemple, produit par mon programme.


Téléchargez le RFC 5388


L'article seul

RFC 5396: Textual Representation of AS Numbers

Date de publication du RFC : Décembre 2008
Auteur(s) du RFC : G. Huston (APNIC, G. Michaelson (APNIC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 10 décembre 2008


Après de très longs débats, ce RFC normalise enfin un format pour représenter les numéros de systèmes autonomes de 32 bits. Ils seront affichés dans la notation ASPLAIN, c'est-à-dire sans séparateur interne, par exemple 101234.

Depuis que le RFC 4893, en mai 2007, avait normalisé les numéros de systèmes autonomes sur quatre octets (donc potentiellement supérieurs à 65536), le débat faisait rage, dans la communauté des opérateurs Internet, sur la meilleure représentation textuelle à leur donner. Deux solutions s'affrontaient pour écrire le numéro 101234 : celle qui l'a emportée, nommée ASPLAIN, où le numéro était écrit sans séparateur interne, et une première solution, ASDOT, où on écrivait le numéro en deux parties séparées par un point, ici 1.35698 (1 * 65536 + 35698). La méthode ASPLAIN convenait mieux aux programmes, ASDOT était préféré par les humains.

Il y avait aussi une méthode ASDOT+ où même les numéros inférieurs à 65536 étaient écrits en deux parties, 20768 se notant 0.20768. ASDOT avait semblé avoir le vent en poupe d'abord, mais avait échoué devant l'IESG.

La crainte des adversaires d'ASDOT était que beaucoup de programmes écrits pour gérer les routeurs (car un gros opérateurs ayant des centaines de Juniper ou de Cisco n'édite évidemment pas les centaines de configurations depuis une interface Web, il a un programme pour cela), des gros scripts Perl ou équivalent, n'aient pas été prévus pour des points au milieu d'un numéro d'AS... Pour prendre un exemple cité par Philip Smith :

Well, here is a regexp from a router I have with IOS-XR, just to show how the . notation impacts regexp work:

as-path-set 4byte-asn
   ios-regex '_2\.0_.*_[0-9]+\.[0-9]+_',
   ios-regex '_5\.1_',
end-set

This basically says:

  • "from AS2.0 accept prefixes with 32-bit ASNs in the AS path"
  • "from AS5.1 accept just prefixes originated by AS5.1"

I'm sure some ISPs around here must have similar 16-bit ASN regexps in use at the moment. To handle 32-bit ASNs, they'll need to convert all these to escape the "." as I did above...

Voir aussi http://www.swissix.ch/asn32/doku.php pour d'autres débats sur la question.

Notre RFC 5396 tranche donc en faveur d'ASPLAIN. C'est ce format qui sera utilisé dans la configuration des routeurs, dans les discussions sur les listes de diffusion d'opérateurs comme NANOG, ou dans les IRR par exemple au RIPE-NCC (qui avait failli développer sa propre politique, vue la difficulté de l'IETF à décider). Comme le note la section 3 du RFC, cette notation a l'avantage de refléter l'absence de structure interne du routage BGP (la notation ASDOT pouvait faire croire à une hiérarchie).


Téléchargez le RFC 5396


L'article seul

Thunderbird et la cryptographie, des options pas toujours évidentes

Première rédaction de cet article le 6 décembre 2008


Le MUA Thunderbird permet d'utiliser la cryptographie pour protéger le relevé ou l'envoi du courrier. Mais trouver la bonne option n'est pas facile !

Une fois des serveurs de messagerie configurés pour utiliser le protocole de cryptographie TLS (pour Postfix, voir « Configurer Postfix avec TLS »), il reste à configurer les clients.

Thunderbird est un des plus utilisés. Logiciel libre, à interface graphique, il dispose de nombreuses fonctions, notamment de filtrage des spams par algorithme bayésien. Il dispose également du protocole TLS. Mais il n'est pas évident de choisir l'option à activer, notamment en raison d'un nommage bizarre des protocoles.

Sans Secure connections - Thunderbird, je ne serai jamais arrivé à le configurer en mode « 100 % crypto » (pour IMAP et SMTP). Cela relativise l'argument comme quoi les interfaces graphiques sont forcément simples. Le problème est qu'il est trivial de trouver quoi faire pour activer "TLS" (on clique sur un bouton) mais moins évident de savoir s'il faut choisir "TLS", "TLS, if available" ou "SSL". SSL et TLS sont pourtant la même chose (SSL est l'ancien nom du protocole qui est devenu TLS et est aujourd'hui normalisé dans le RFC 5246).

Les options "TLS" et "TLS, if available" font presque la même chose, et qui est en fait du STARTTLS (commencer en clair puis basculer en chiffré s'il est disponible). La seule différence est que "TLS" tout court impose que STARTTLS soit possible et coupe la communication si cette sécurité n'est pas posisble.

C'est l'option "SSL", très mal nommée, qui permet de faire du TLS directement (sans STARTTLS).

Donc, en SMTP : il faut configurer "TLS" (qui veut dire en fait STARTTLS) et le port 587, le port de soumission du courrier (RFC 6409).

En IMAP, avec la configuration par défaut du serveur IMAP Courier (deux ports, un pour le clair et un pour le chiffré), il faut "SSL" et ne pas cocher "secure authentication" (qui désigne un défi/réponse, mais c'est déjà assez sûr avec TLS) et il faut un certificat correct, le certificat auto-signé généré par Courier par défaut ne marche pas (mais le certificat de ma CA privée fonctionne).

(Courier peut aussi être configuré pour faire du STARTTLS dans IMAP.)

Merci à Erwan David pour ses explications.


L'article seul

Ne jamais avoir de listes noires statiques

Première rédaction de cet article le 6 décembre 2008


Quand on arrive dans un nouvel emploi d'ingénieur système & réseaux, ou bien lorsqu'on fait un petit audit d'un site existant, on tombe souvent sur des listes noires, en général d'adresses IP refusées. Ces listes ont typiquement été créées suite à un incident de sécurité et, malheureusement, sont souvent statiques, c'est-à-dire jamais mises à jour. En général, la date où a été créée une entrée donnée n'est jamais indiquée. Au bout d'un certain temps, ces listes deviennent donc plus dangereuses qu'utiles.

Il ne faut jamais utiliser une telle liste sans avoir une procédure (de préférence automatique, et surveillée, pas un cron que tout le monde a oublié) de mise à jour. Autrement, c'est votre successeur, dans deux ans, qui tombera sur le problème.

Ainsi, l'excellent site Cymru fournit tout ce qu'il faut pour cela. Leurs listes noires de bogons, par exemple, peuvent être automatiquement mises à jour via BGP, le DNS, etc.

Comme, malgré de tels services, la plupart des listes de bogons sont laissées à elles-mêmes, jamais mises à jour, le malheureux qui récupère des adresses dans un préfixe qui vient d'être alloué va souffrir. Certains ont même menacé l'ARIN ou d'autres RIR de procès, pour leur avoir « vendu » des adresses IP inutilisables.

Idem pour les listes noires liées au spam ou d'autres problèmes de sécurité. Si une adresse IP a une fois servi à spammer, elle est gâtée pour toujours. Cela a même mené à une proposition d'évaluation de la valeur des adresses IP selon leur historique.

Certaines de ces listes statiques sont parfois redistribuées et des ignorants les utilisent sans connaitre leurs limites.

Faites le test dans votre organisation : pour chaque liste de bogons, pour chaque liste noire, ou équivalent, existe t-il une procédure documentée de mise à jour ? Si non, supprimez cette liste d'urgence.

Le message attaché est un exemple ultra-classique des problèmes des listes de bogons pas à jour, tels qu'ils sont vus par les opérateurs. De tels messages sont très fréquents (ici, sur la liste SANOG, le groupe des opérateurs réseau d'Asie du Sud) et dureront tant que les gens continueront à utiliser ces listes noires statiques.

Date: Sat, 15 Sep 2007 05:13:48 -0400 (EDT)
From: Sri <jaadhoo@yahoo.com>
Subject: [SANOG] 99/8 IP Block (was Bogons)
To: sanog@sanog.org

Hello all,
I am Sri from Rogers Cable Inc. ISP in Canada. We have IP block
99.x.x.x assigned to our customers. Which happened to be bogons block
in the past and was given to ARIN in Oct 2006. As we have recently
started using this block, we are getting complaints from our customers
who are unable to surf some web sites. After investigation we found
that there are still some prefix lists/acls blocks this IP block.

We got the following blocks:

99.224.0.0/12
99.240.0.0/13
99.248.0.0/14
99.252.0.0/16
99.253.128.0/19

  Here are the few pingable ips 99.246.224.1 & 99.244.192.1
  
Please update your bogons list.

If anyone has any questions, or I can provide any additional
information which anyone may require, please feel free to email me
directly or call our TAC @ 416.935.5700.

Thanks in advance for your support,

Sri


-- 
This is the SANOG (http://www.sanog.org/) mailing list.

L'article seul

Authentifier des serveurs Internet avec X.509 lorsqu'ils ont la même adresse IP

Première rédaction de cet article le 4 décembre 2008
Dernière mise à jour le 16 décembre 2008


On lit souvent qu'il n'est pas possible d'avoir plusieurs serveurs Internet sur la même adresse IP lorsqu'ils sont authentifiés par un certificat X.509. Il faudrait donc donner une adresse IP à chacun. Cette affirmation a des origines réalistes mais est sans doute trop stricte aujourd'hui.

Dans un protocole comme HTTPS, le nom du serveur est transmis une fois la session TLS établie. Il est donc a priori trop tard à ce moment pour choisir un autre certificat. D'où le mème « Un seul certificat par adresse IP ». (Un bon résumé du problème figure dans Name-based SSL virtual hosts: how to tackle the problem.) En fait, il est possible d'avoir une seule adresse IP et néanmoins un certificat différent par Virtual Host Apache, même si les méthodes existantes ont quelques limites.

Il existe trois méthodes pour HTTPS (toutes ne sont pas forcément applicables aux autres protocoles) :

  • La commande HTTP STARTTLS (RFC 2817) qui permet de transmettre le nom du serveur avant la négociation TLS.
  • L'extension X.509 Subject Alternative Name (RFC 5280) qui permet de mettre plusieurs noms dans un certificat. Le client sera alors content si un des noms correspond.
  • L'extension TLS Server Name Indication (SNI) (RFC 6066) qui permet au client d'indiquer le nom du serveur dans la négociation TLS.

Chacune a ses forces et ses faiblesses et des domaines où elle est meilleure que les autres.

La première, STARTTLS, normalisée dans le RFC 2817, est bien décrite par Pierre Beyssac dans « HTTP et TLS, la RFC méconnue... ». Très répandue avec des protocoles comme IMAP ou SMTP, elle a un gros inconvénient pour HTTP : il n'est pas possible d'indiquer dans l'URL que TLS est obligatoire. Un attaquant sur le chemin, ou bien un serveur mal configuré, et on retombe sur du HTTP non protégé.

Mise en œuvre dans Apache depuis la version 2.2, elle n'est présent dans aucun grand navigateur, pour les raisons expliquées par Mozilla dans la bogue #276813.

Une deuxième méthode est le certificat contenant plusieurs noms. Elle est possible grâce à l'extension X.509 Subject Alternative Name, normalisée dans le RFC 2459. Elle est décrite en détail dans mon article « Plusieurs noms dans un certificat X.509 » ou bien dans celui de Franck Davy, « Apache : Hôtes virtuels et SSL (mod_ssl) ». En anglais, on peut lire « Information about setting up the ApacheServer to serve multiple HTTPS sites using one IP address ».

Elle fonctionne avec openssl (aussi bien pour générer le certificat que pour le vérifier) mais il faut que la CA qui signe l'accepte et j'ignore si les grosses CA ayant pignon sur rue le font ou pas. C'est la méthode qui semble la plus déployée et donc celle qui apporte le moins de surprises (CAcert a fait des tests détaillés d'interopérabilité sur les variantes de cette méthode).

La troisième méthode repose sur une extension du protocole TLS et non pas du format X.509. Cette extension, Server Name Indication (SNI), est l'une de celles décrites dans le RFC 6066. Elle envoie le nom du serveur lors de la négociation TLS. Elle est bien expliquée dans l'article de Pierre Beyssac « Adieu RFC 2817, bonjour RFC 3546 ».

SNI (Server Name Indication) ne marche pas avec le module Apache mod_ssl, il faut utiliser mod_gnutls. Il y a un certificat par Virtual Host et elle ne gère donc pas le cas où un Virtual Host a plusieurs noms, avec la directive ServerAlias.

Les serveurs HTTP gérés par le département de recherche & développement de l'AFNIC sont un exemple de déploiement de deux de ces techniques. Le serveur, un Apache, utilise mod_gnutls, avec un certificat par Virtual Host, et peut donc tirer profit de la troisième méthode, SNI. Au cas où le client ne gère pas l'extension SNI, le certificat par défaut (celui qui est utilisé dans la directive <VirtualHost _default_:443>) est un certificat avec plusieurs noms.

Voici un test d'un de ces serveurs avec un logiciel en ligne de commande livré avec GnuTLS (bien entendu, TLS étant une norme - RFC 5246 -, on aurait aussi bien pu tester avec openssl) :

% gnutls-cli -p 443 --x509cafile /etc/ssl/certs/AFNIC-ReD-CA.pem \
       svn.langtag.net                           
Processed 1 CA certificate(s).
Resolving 'svn.langtag.net'...
Connecting to '2001:660:3003:3::1:4:443'...
- Certificate type: X.509
 - Got a certificate list of 1 certificates.

 - Certificate[0] info:
 # The hostname in the certificate matches 'svn.langtag.net'.
 # valid since: Thu Dec  4 10:21:30 CET 2008
 # expires at: Wed Aug 31 11:21:30 CEST 2011
 # fingerprint: F5:78:88:D7:EF:CA:38:92:F3:40:B9:67:D4:B6:48:E6
 # Subject's DN: C=FR,ST=Ile-de-France,L=Saint-Quentin-en-Yvelines,O=AFNIC,OU=R&D,CN=www.generic-nic.net,EMAIL=webmaster@generic-nic.net
 # Issuer's DN: C=FR,ST=Ile-de-France,L=Saint-Quentin-en-Yvelines,O=AFNIC,OU=ReD,CN=AFNIC Research and Development,EMAIL=pki@generic-nic.net


- Peer's certificate is trusted
...

Voilà, tout va bien. Si on est inquiet, on peut vérifier l'empreinte du certificat (ici F5:78:88:D7:EF:CA:38:92:F3:40:B9:67:D4:B6:48:E6). Attention, gnutls-cli affiche l'empreinte MD5 alors que, par défaut, openssl x509 -fingerprint montre l'empreinte SHA-1. Il faut donc, pour regarder le certificat, taper openssl x509 -fingerprint -md5 -in /ou/est/le/certificat.pem.

Vishaal Golam me signale qu'il existe une quatrième méthode, avec des restrictions. Mettre un joker dans le certificat, par exemple *.example.net. Ainsi, tout logiciel client qui accepte les jokers (c'est la grande majorité mais attention, avec des sémantiques différentes car ce point n'est pas vraiment normalisé, cf. RFC 2818, section 3.1) acceptera ce certificat pour www.example.net, svn.example.net, etc. Il faut juste que la CA, l'autorité de certification, accepte ces jokers, qui diminuent ses revenus (je ne sais pas quels CA les acceptent mais, par exemple, Thawte le fait). Et la méthode ne marche que pour des noms qui ont un domaine en commun (ici example.net).

Merci à Pierre Beyssac, Mario Victor-Oscar, Yves Rutschle, Kim-Minh Kaplan et Benoit Deuffic pour des informations stimulantes et utiles.


L'article seul

RFC 5375: IPv6 Unicast Address Assignment Considerations

Date de publication du RFC : Décembre 2008
Auteur(s) du RFC : G. Van de Velde, C. Popoviciu (Cisco), T. Chown (University of Southampton), O. Bonness, C. Hahn (T-Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 4 décembre 2008


Voici un RFC qui s'adresse à l'administrateur système plutôt qu'au développeur. Il s'agit d'expliquer deux ou trois choses sur l'affectation des adresses IPv6 aux machines du réseau local, afin d'aider à la création d'un plan d'adressage.

Les principes de base de l'adressage IP sont décrits dans le RFC 4291. Une adresse est composée de deux parties, celle qui identifie le réseau et celle qui identifie l'interface de la machine, l'interface ID.

La section 1 du RFC rappelle les principales différences avec IPv4 :

  • Il est plus courant d'avoir plusieurs adresses par machine,
  • La taille de l'espace d'adressage fait qu'il n'est typiquement pas nécessaire de faire des économies.

La section 2 s'attaque ensuite à l'adressage de la partie réseau (le préfixe), que ce soit pour les adresses uniques mondialement (section 2.1) ou bien pour les adresses de site du RFC 4193 (section 2.2). Le gros morceau est en 2.4, qui détaille les bénéfices qu'on peut tirer du vaste espace d'adressage IPv6. Des schémas d'adressage « créatifs », par exemple où le préfixe est dérivé du numéro du VLAN sont désormais possibles. La croissance future du réseau peut être permise en laissant des trous dans l'allocation comme l'explique un excellent document, le RFC 3531.

La taille des préfixes est à étudier : le RFC 3177 posait comme principe l'affectation d'un /48 à chaque site, quel que soit sa taille, notamment pour éviter les problèmes en cas de rénumérotation. Mais la section 2.4.2 parle des problèmes d'économie d'adresses v6 (cf. RFC 3194). Et le RFC 6177 ne fait plus de recommandation unique.

La section 3 est dédiée à la question de la taille du préfixe d'un lien donné. Contrairement à IPv4 où on dispose d'une liberté complète, IPv6 suppose un préfixe de lien de /64 (RFC 4291, section 2.5.4). Choisir une autre valeur est théoriquement possible, mais casserait plusieurs protocoles importants comme SEND ou comme les adresses temporaires du RFC 8981. Pire, cela pourrait limiter le déploiement de futurs protocoles qui auraient eux-aussi besoin de 64 bits pour les adresses des machines. (Voir aussi l'annexe B.1 et B.2 ; on y trouve une exception pour les liens point-à-point entre deux routeurs, où un /126 est acceptable, mais pas un /127.)

Ensuite, les adresses des machines sur le lien peuvent être attribuées par plusieurs méthodes (section 4) :

  • Auto-configuration sans état (RFC 4862), section 4.1
  • Adresses anti-traçage du RFC 8981, section 4.2
  • Adresses attribuées manuellement, section 4.3. Dans ce cas, il faut veuiller à ce que les adresses n'entrent pas en conflit avec des adresses bien connues, comme par exemple l'adresse « tout à zéro » qui identifie normalement les routeurs du lien (annexe B.2.5.1). Il faut également veiller à ce que le bit 'u' de l'adresse, le 71ème bit, soit à 0 et le bit 'g', le 72ème, également. En pratique, à l'heure actuelle, se tromper sur ces deux bits n'a pas de conséquences mais cela pourrait en avoir dans le futur (cf. annexe B.2.4). Donc, 2001:DB8:CAFE:1::1 est correct (les deux bits sont à zéro) mais pas 2001:DB8:CAFE:1:0200::1 (le bit 'u' est à un, dans le groupe 0200).

Deux études de cas concrètes, en annexe A, rendent ce RFC un peu plus facile à lire.


Téléchargez le RFC 5375


L'article seul

RFC 3982: IRIS: A Domain Registry (dreg) Type for the Internet Registry Information Service (IRIS)

Date de publication du RFC : Janvier 2005
Auteur(s) du RFC : A. Newton (Verisign), M. Sanz (DENIC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF crisp
Première rédaction de cet article le 3 décembre 2008


Le protocole IRIS d'accès aux informations dites « sociales » qui sont stockées dans un registre, par exemple un registre d'adresses IP, est défini indépendemment du schéma des données stockées. Il faut donc le compléter, pour chaque registre, par un schéma indiquant comment sont structurées les données. Notre RFC le fait pour les registres de noms de domaine.

Comme tous les schémas IRIS, ce document utilise le langage W3C Schema pour spécifier les éléments XML qui peuvent être présents dans les requêtes au serveur IRIS et dans ses réponses. Le schéma a reçu le nom de DREG (Domain Registry). La section 3 liste en langue naturelle les éléments possibles de DREG, la section 4 contenant le schéma formel.

Par exemple, l'élément <findDomainsByName> (section 3.1.3) permet des interogations analogues à celles de whois en interrogeant le registre sur les données liées à un domaine dont on connait le nom.

Mais il contient aussi des requêtes qui ne sont pas possibles avec tous les serveurs whois comme <findDomainsByContact> (section 3.1.2) qui permet de retrouver tous les domaines d'une personne ou d'une organisation donnée (très intrusive, cette requête ne sera probablement jamais disponible publiquement).

Et les réponses ? La section 3.2.2 décrit la forme d'un élément <domain>. Cet élément contient les informations associées à un domaine comme ses serveurs de noms, sa date de création ou son état (status). Les états possibles sont énumérés, on y trouve, par exemple, reservedDelegation (réservé mais pas publié dans le DNS, un état qui n'existe pas aujourd'hui dans .fr mais qui peut être présent dans d'autres TLD).

Il faut noter que la liste des états possibles n'est pas la même qu'avec EPP (RFC 4931), cela serait trop simple...

D'autres types d'objet peuvent être stockés par le registre et interrogés via IRIS, comme les contacts (les personnes ou organisations responsables d'un domaine), traités en section 3.2.4.

Ce schéma DREG ne semble pas encore utilisé dans aucun serveur IRIS publiquement accessible.

Emprunté à l'annexe A du RFC, voici un exemple de requête IRIS/DREG :


<?xml version="1.0"?>
<request xmlns="urn:ietf:params:xml:ns:iris1"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <searchSet>
    <lookupEntity
      registryType="urn:ietf:params:xml:ns:dreg1"
      entityClass="domain-name"
      entityName="example.com" />
  </searchSet>
</request>

et la réponse possible d'un serveur IRIS :


<?xml version="1.0"?>
<iris:response xmlns:iris="urn:ietf:params:xml:ns:iris1"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <iris:resultSet>
    <iris:answer>
      <domain xmlns="urn:ietf:params:xml:ns:dreg1"
        authority="iana.org" registryType="dreg1"
        entityClass="domain-handle" entityName="example-com-1">

        <domainName>example.com</domainName>
        <domainHandle>tcs-com-1</domainHandle>

        <nameServer iris:referentType="host" authority="iana.org"
          registryType="dreg1" entityClass="host-handle"
          entityName="research7" />
        <nameServer iris:referentType="host" authority="iana.org"
          registryType="dreg1" entityClass="host-handle"
          entityName="nsol184" />

        <technicalContact iris:referentType="contact"
          authority="iana.org" registryType="dreg1"
          entityClass="contact-handle" entityName="dbarton" />

        <status>
          <assignedAndActive denied="true" />
        </status>

        <registry iris:referentType="registrationAuthority"
          authority="com" registryType="dreg1"
          entityClass="contact-handle" entityName="VGRS" />
        <initialDelegationDateTime xsi:nil="true"/>
        <iris:seeAlso iris:referentType="ANY" authority="iana.org"
          registryType="dreg1" entityClass="local"
          entityName="notice"  />
      </domain>
    </iris:answer>
  </iris:resultSet>
</iris:response>


Téléchargez le RFC 3982


L'article seul

RFC 2026: The Internet Standards Process -- Revision 3

Date de publication du RFC : Octobre 1996
Auteur(s) du RFC : Scott O. Bradner (Harvard University)
Première rédaction de cet article le 1 décembre 2008


Comment sont développées les normes Internet ? Qui les décide ? Comment les changer ? Ce RFC repond à toutes ces questions, en décrivant le processus de normalisation dans l'Internet. Bien sûr, comme pour beaucoup de processus sociaux, la réalité est parfois très éloignée de la description...

La plupart des normes techniques qui régissent l'Internet sont écrites dans des RFC (l'inverse n'est pas vrai : beaucoup de RFC ne sont pas des normes). Ces RFC de normalisation sont développés au sein de l'IETF et on peut trouver une description des activités de l'IETF dans mon exposé IETF à JRES.

Certains RFC ne décrivent pas un protocole ou un format mais des règles à suivre lors du développement des normes et c'est le cas de ce RFC. Son introduction rappelle que toute cette activité se déroule sous la responsabilité de l'ISOC (l'IETF n'est qu'une étiquette, elle n'a pas de personnalité juridique).

La section 1 résume les grands principes : il n'existe pas de « police des normes » (section 1.1) qui ferait respecter les RFC, la conformité à ces normes est volontaire (une norme industrielle n'est pas une loi). Et les normes Internet sont censées représenter une technique qui fonctionne, qui est bien comprise et pour laquelle existent au moins deux mises en œuvre interopérables (contrairement à une légende très répandue, il n'est pas exigé qu'une de ces mises en œuvre soit libre).

Le processus d'élaboration des normes lui-même est résumé en section 1.2. Il est ouvert à tous, est pratiqué par « la communauté » (community, mot fourre-tout dans le discours politique états-unien, qui n'est jamais clairement défini et qui exprime surtout la nostalgie du petit village fermé et regroupé autour de son église) et vise à obtenir un consensus de toutes les parties prenantes. Les procédures de ce RFC doivent être honnêtes, ouvertes et objectives. (Oui, la langue de bois est très présente dans ce RFC.)

Le RFC explique bien la difficulté de la normalisation dans un monde qui évolue aussi vite que celui des réseaux informatiques. La normalisation est forcément lente, à la fois pour des raisons sociales (construire le consensus) et techniques (écrire une norme correcte est un travail difficile), alors que la technique bouge très vite.

La section 2 décrit les documents qui sont produits par le processus de normalisation. Il commence évidemment (section 2.1) par les RFC. Ces textes, bien mal nommés (RFC voulait dire Request For Comments, ce que ne reflète plus leur statut et leur stabilité ; mais le nom est resté) existent depuis très longtemps (le RFC 1 a été publié en avril 1969). Ils sont largement et gratuitement disponibles (pendant longtemps, cela a été une des spécificités de ces normes, et une des raisons du succès de TCP/IP par rapport aux technologies concurrentes). Ils sont publiés par un organisme séparé, le RFC editor. C'est lui qui définit les règles (assez archaïques) de format, le texte brut, obligatoire pour les RFC qui ont le statut de norme.

Car ce n'est pas le cas de tous les RFC. Les normes proprement dites ne sont qu'un sous-ensemble des RFC. Dans l'index, on les reconnait au texte STDnnn qui indique leur numéro dans la série des normes (STanDard ; par exemple, UDP, RFC 768 est STD0006). D'autres RFC n'ont pas ce statut et peuvent être publiés par le RFC editor seul, sans implication de l'IETF. C'est un point important, souligné par le RFC 1796 : Not All RFCs are Standard.

Mais les RFC ne naissent certainement pas tout armés ? Comment évoluent-ils et à partir de quoi ? C'est l'objet de la section 2.2, consacrée aux Internet-Drafts (on dit aussi I-D), les RFC en gestation. Un I-D n'a aucune valeur normative et notre RFC sur les normes rappelle bien qu'il est déconseillé de s'appuyer sur un I-D, par exemple pour un appel d'offres. De même, un vendeur ne devrait pas citer d'I-D dans la liste des fonctions de son produit. En effet, les I-D ne sont pas stables et peuvent changer à tout moment (en outre, même si le RFC 2026 ne le rappelle apparemment pas, n'importe qui peut écrire un I-D et le faire distribuer par l'IETF, il n'y a pas de contrôle).

La section 3 introduit une distinction qui n'a guère été utilisée entre les spécifications techniques (TS pour Technical Specifications) et les consignes d'application (AS pour Applicability Statement), qui expliquent comment appliquer les premières. Même le vocabulaire n'est pas resté et les sigles TS et AS ne semblent plus utilisés à l'IETF.

La section 4 en arrive au chemin des normes (standards track, la route que suivent les RFC vers le nirvana du statut de « norme au sens strict »). À noter que cette partie a été réformée par la suite dans le RFC 6410, qui a réduit le nombre d'étapes à deux. Les détails des anciens trois statuts sont publiés dans la section 4.1. Une fois publiée en RFC, la technique qui a été lancée sur le chemin des normes a le statut de proposition de norme (proposed standard, section 4.1.1). Si tout va bien, lorsqu'elle mûrira, et que deux mises en œuvre distinctes existeront, un nouveau RFC sera publié, avec le statut de projet de norme (draft standard, section 4.1.2). Enfin, après de longs efforts, des tests d'interopérabilité et pas mal d'actions de lobbying, un dernier RFC sera publié, avec le statut de norme au sens propre (Standard ou Internet Standard ou Full Standard, section 4.1.3). C'est par exemple ce qui est arrivé au format ABNF, proposition de norme dans le RFC 2234, projet de norme dans le RFC 4234 et désormais norme complète dans le RFC 5234 (voir la section 6.2 pour des détails, notamment de délais obligatoires). Par contre, si l'expérience montre qu'une technique a des failles et qu'il faut modifier la spécification de manière non triviale, on repart de zéro (section 6.3).

Mais il faut noter que ces trois statuts ne correspondent pas toujours à la réalité. Des techniques très employées sont restées au statut de proposition (par exemple Sieve, RFC 5228), d'autres ont le statut de norme alors qu'elles ne sont plus utilisées (comme chargen du RFC 864). Il faut donc prendre ce classement avec prudence. (Je me souviens d'une réunion où une juriste d'un gros FAI, assez ignorante de tout ce qui concerne la normalisation, avait défendu leur politique de filtrage du courrier en ergotant sur le fait que le RFC 2821 n'était que proposition de norme...) C'est entre autre pour cela que le RFC 6410 a par la suite réduit le nombre de statuts possibles à deux.

Il existe aussi de nombreux RFC qui ne sont pas du tout sur le chemin des normes (section 4.2). C'est le cas des RFC « expérimentaux » (section 4.2.1), statut normalement réservé aux protocoles pas vraiment mûrs et sur lesquels il n'existe pas encore de consensus sur leur inocuité. Ce statut peut aussi être attribué pour des raisons politiques, comme ce fut le cas avec le RFC 4408, bloqué par la volonté de certains gros acteurs.

Le statut « pour information » (section 4.2.2) est notamment celui de tous les RFC qui ne décrivent pas un protocole ou un format mais rendent compte d'une expérience, ou formulent un cahier des charges, ou expliquent les raisons de certains choix. Pour éviter les collisions avec le travail de normalisation à proprement parler, l'IESG a son mot à dire sur ces RFC, pour pouvoir soulever d'éventuelles objections (section 4.2.3).

Enfin, le statut « historique » (section 4.2.4) revient aux RFC qui ont été officiellement considérés comme dépassés par les évolutions techniques et l'expérience acquise. C'est ainsi que, par exemple, le protocole whois++ qui devait remplacer whois, avait été normalisé dans le RFC 1913 qui, n'ayant jamais connu de déploiements significatifs, a été reclassé historique...

À noter que, de même que l'avancement d'une technique sur le chemin des normes nécessite une action délibérée de certains, le reclassement en « historique » demande que quelqu'un fasse le travail de documentation des raisons du reclassement. C'est pour cela que beaucoup de RFC sont simplement tombés en désuétude, sans même que quelqu'un se donne la peine de les faire formellement reclassifier (comme le RFC 1256).

Un statut particulier a droit à une section à lui : BCP (Best Current Practices, « Bonnes pratiques actuelles », section 5). Ces documents ne normalisent pas une technique mais une façon de l'utiliser « correctement ». Ils reçoivent également un numéro commençant par BCP. C'est ainsi que le RFC 2827, sur le filtrage des paquets trichant sur l'adresse source, est également BCP0038 et que le RFC 5226, sur la gestion des registres IANA est aussi le BCP0026. Un autre usage des BCP est de garder un pointeur vers la version actuelle de la norme. En effet, les RFC ne sont jamais modifiés mais remplacés. Si on se réfère à un RFC, on court donc le risque de pointer un jour vers un texte obsolète et il est donc recommandé d'utiliser plutôt le numéro de BCP. Par exemple, BCP0047 désignera toujours le RFC actuel sur les étiquettes de langue (actuellement le RFC 5646).

Le processus d'avancement des normes est décrit complètement en section 6. Je rappelle qu'il n'est pas automatique. Une norme n'avance pas toute seule mais seulement parce qu'un groupe de gens trouvait important de la faire avancer... et a su convaincre l'IESG (section 6.1.2).

L'IETF étant une organisation humaine et le fait de travailler sur des normes techniques ne supprimant pas les passions et les intérêts matériels, les conflits sont fréquents. Il n'est donc pas étonnant qu'il existe une section, la 6.5, sur les conflits et leur résolution. Elle détaille un mécanisme d'escalades successives. D'abord, faire appel aux présidents du groupe de travail considéré, puis au directeur de zone (une zone chapeautant plusieurs groupes), puis à l'IESG puis à l'IAB, ultime arbitre.

Il n'y a pas que l'IETF dans le monde et certaines normes très importantes sur Internet sont issues d'autres organisations (par exemple, HTML vient du W3C, Ethernet de l'IEEE et X.509 de l'UIT). La section 7 décrit donc l'interaction avec les autres SDO. Certaines normes sont qualifiées d'« ouvertes » et d'autres de « autres » mais sans que ces termes soient définis avec précision. Les normes « ouvertes » (ce terme a traditionnellement été utilisé à l'IETF de manière très laxiste, intégrant même des normes comme celles de l'ISO, qui ne sont pas publiquement accessibles) peuvent être référencées par les RFC. Les « autres » sont typiquement découragées mais peuvent être utilisées si nécessaire (section 7.1.2).

Le processus de développement des normes à l'IETF a toujours été ouvert, et les discussions elles-mêmes sont enregistrées et archivées (contrairement à l'ISO où tout, même les votes, est secret). La section 8 décrit les obligations de conservation que s'impose l'IETF.

Ce RFC 2026, dérivé du RFC 1602, lui même issu du RFC 1310, est assez ancien et c'est une autre raison pour laquelle il ne reflète pas toujours bien le processus actuel. Il a parfois été mis à jour (par exemple, sur la question des droits de propriété intellectuelle, qui était traitée en section 10, mais qui est maintenant du ressort des RFC 8721 et RFC 5378) mais de manière incomplète.


Téléchargez le RFC 2026


L'article seul

Tester son courrier électronique avec des auto-répondeurs

Première rédaction de cet article le 30 novembre 2008
Dernière mise à jour le 2 octobre 2023


Une fois qu'on a bien transpiré et configuré proprement son serveur de messagerie, comment vérifier s'il marche ? En écrivant un message ? Cela ne teste que la moitié du trajet, il serait bien d'avoir aussi une réponse... Si on a des copains patients, on peut leur écrire et solliciter une réponse mais c'est assez abusif. Il vaut mieux compter sur un programme qui répondra à chaque fois, sans se lasser, et qui pourra en prime vous indiquer à quoi ressemblait le message entrant. Quelles sont les adresses qui correspondent à un tel programme ?

Voici une liste partielle. Si vous en connaissez d'autres, n'hésitez pas à me prévenir.

  • echo@nic.fr (Accessible en IPv6 et accepte TLS.)
  • ping@stamper.itconsult.co.uk (analyse SPF et DKIM, et indique le résultat ; en revanche, il ne renvoie qu'une partie du message original ; par ailleurs, cette organisation héberge l'excellent service Stamper.)
  • check-auth@verifier.port25.com
  • ping@zici.fr (mais seulement IPv4, et sans TLS), il y a une documentation et le code.
  • test@doesnotwork.eu (IPv6 seulement, à n'utiliser que si vous pouvez envoyer et recevoir du courrier en IPv6, il teste réception et envoi, et vous envoie donc deux confirmations.)
  • ping@tools.mxtoolbox.com (la réponse est en deux parties, texte et HTML et la partie texte est du n'importe quoi, il faut regarder la partie HTML, ou passer par le site Web ; sinon, tests SPF, DKIM et DMARC).
  • Le réflecteur RFC 8255 permet de tester les messages multilingues du RFC 8255. Lisez son mode d'emploi pour en savoir plus.
  • https://www.mail-tester.com/ qui n'est pas vraiment un répondeur : on regarde une page Web qui vous indique une adresse (à usage unique) à laquelle on écrit et qui vous affiche ensuite le résultat de l'analyse (y compris SPF et DKIM).
  • À peu près la même chose avec https://www.mailgenius.com/, https://aboutmy.email/ ou avec https://scanmy.email/.
  • Un service analogue est MECSA, qui vous envoie un message auquel vous répondez et qui vous présentera alors divers diagnostics, notamment de sécurité. (À interpréter avec prudence, comme d'habitude.)
  • Le service de Glock (compte nécessaire) vous permet de tester la livraison de votre message auprès d'un certaine nombres d'hébergeurs de courrier.

Certains pratiquent le greylisting (RFC 6647) donc soyez patient : la réponse n'arrivera pas tout de suite, c'est du courrier électronique, pas de la messagerie instantanée.

Tous renvoient également le message tel qu'ils l'ont reçu, ce qui permet de vérifier que tous les détails du courrier sortant sont corrects, par exemple les en-têtes Received:. Par exemple, voici le champ Received: qu'avait le message en rentrant dans le serveur de messagerie de generic-nic.net :

Received: from mail.bortzmeyer.org (bortzmeyer-1-pt.tunnel.tserv10.par1.ipv6.he.net[IPv6:2001:470:1f12:420::2])
        by mail.generic-nic.net (Postfix) with ESMTP id 42B2A9345C2
        for <echo@generic-nic.net>; Sun, 30 Nov 2008 19:26:58 +0100 (CET)

On y voit (la syntaxe complète de Received: est décrite dans le RFC 5322, section 3.6.7) le nom qu'a annoncé l'expéditeur dans la commande EHLO, ici mail.bortzmeyer.org, l'adresse IP dudit expéditeur, ici 2001:470:1f12:420::2 et le nom obtenu à partir de cette adresse IP par résolution inverse dans le DNS, ici bortzmeyer-1-pt.tunnel.tserv10.par1.ipv6.he.net.

Une mention spéciale mérite d'être faite pour check-auth@verifier.port25.com. Outre le simple test d'écho du courrier, il fait en outre une série de tests liés à la lutte anti-spam (présence dans les principales listes noires, score SpamAssassin, etc) ce qui peut être pratique si vos messages ne sont pas délivrés et que vous soupçonnez les logiciels anti-spam d'en être responsables. Voici le genre de rapport qu'envoie ce service :

==========================================================
Summary of Results
==========================================================
SPF check:          permerror
DomainKeys check:   neutral
DKIM check:         neutral
SpamAssassin check: ham
...
[Pour SPF, ici en erreur, les enregistrements SPF et l'identité testée 
sont affichés mais aucune explication détaillée n'est fournie.]
...
SpamAssassin v3.2.5 (2008-06-10)

Result:         ham  (2.0 points, 5.0 required)

 pts rule name              description
---- ---------------------- --------------------------------------------------
-0.2 BAYES_40               BODY: Bayesian spam probability is 20 to 40%
                            [score: 0.3813]
 2.2 TVD_SPACE_RATIO        BODY: TVD_SPACE_RATIO

Autre mention, les auto-répondeurs de test des adresses internationalisées en http://idn.icann.org/E-mail_test.

Enfin, si vous voulez monter un tel service chez vous, compatible avec le RFC 3834, voici le script procmail qui est derrière echo@generic-nic.net. Il est configuré ainsi dans /etc/aliases :

echo: "|/usr/bin/procmail /etc/procmailrcs/echo"

et /etc/procmailrcs/echo contient :

VERBOSE=off
LOGFILE=/var/tmp/echo.log
MYDOMAIN=YOUR-DOMAIN-NAME-HERE.example
LOOP_TAG=echo@$MYDOMAIN

# Read RFC 3834! Option -t of formail must not be used and Auto-Submitted 
# must be present.
:0Hhb
* !^FROM_DAEMON
* $!^X-Loop: $LOOP_TAG
| (tempfile=`mktemp`; cat - > $tempfile; cat $tempfile | \
     formail -r -k -A'Precedence: junk' \
        -A'Auto-Submitted: auto-replied' \
        -A'MIME-Version: 1.0' \
        -A'Content-type: text/plain; charset=US-ASCII' \
        -A"X-Loop: $LOOP_TAG" \
        -A"From: postmaster@$MYDOMAIN (Echo automatic service)" ; \
	cat /local/lib/echo-reply; \
        echo ""; echo "Your original message:"; echo ""; \
        cat $tempfile; rm $tempfile) \
      | $SENDMAIL -t


L'article seul

DSSSL, le langage de transformation de SGML

Première rédaction de cet article le 27 novembre 2008


Le langage DSSSL (Document Style Semantics and Specification Language) est aujourd'hui bien oublié. Il était le langage favori de transformation de SGML. Comme j'ai utilisé ce langage pendant des années, il est temps de documenter un peu avant qu'il ne disparaisse complètement.


L'article complet

RFC 5395: Domain Name System (DNS) IANA Considerations

Date de publication du RFC : Novembre 2008
Auteur(s) du RFC : Donald E. Eastlake 3rd (Motorola)
Première rédaction de cet article le 27 novembre 2008
Dernière mise à jour le 5 janvier 2009


Un RFC un peu bureaucratique, pour détailler les mécanismes utilisés pour l'enregistrement dans les registres de l'IANA des paramètres liés au DNS. Il a depuis été remplacé par le RFC 6195 (qui à son tour a été remplacé par le RFC 6895).

Un certain nombre de paramètres, dans le DNS, sont enregistrés à l'IANA, afin de s'assurer d'une interprétation identique partout. C'est ainsi que l'IANA gère un registre des paramètres DNS où on trouve, entre autres, les types d'enregistrement (A, codé 1, pour une adresse IPv4, AAAA, codé 28, pour une adresse IPv6, LOC, codé 29, pour les positions géographiques du RFC 1876, etc). Cet espace n'étant pas de taille infinie, il faut y enregistrer de nouveaux paramètres avec prudence, selon les règles qui étaient expliquées dans le RFC 2929, que notre RFC modifie.

En effet, les règles du RFC 2929 étaient bien trop strictes à l'usage. Notamment, le processus d'enregistrement d'un nouveau type d'enregistrement était tellement pénible que beaucoup de protocoles (comme SPF à ses débuts) préféraient utiliser le fourre-tout TXT pour y mettre leurs enregistrements. Ce goulet d'étranglement était souvent cité comme un exemple typique des blocages liés à l'IETF.

Notre RFC assouplit donc les règles d'enregistrement des types de ressources DNS (les autres règles sont peu changées). Avant, il y avait deux solutions (voir le RFC 5226 pour plus d'explications), IETF Review (ex-IETF Consensus), un processus long et incertain imposant un RFC sur le chemin des normes, approuvé par l'IESG, ou Specification required, qui impose l'écriture d'une norme (pas forcément un RFC) « stable et permanente ».

Le nouveau système est plus léger (section 3.1.1) : il suffit désormais de remplir un formulaire décrivant le nouveau type d'enregistrement, de le soumettre sur la liste namedroppers@ops.ietf.org et d'attendre le jugement d'un expert, désigné parmi les noms fournis par l'IESG, qui décidera, sur la base du formulaire soumis, d'allouer ou pas la requête. Un tel processus est utilisé pour d'autres enregistrements à l'IANA, par exemple pour les nouvelles étiquettes de langue.

Le nouveau processus a été testé pour la première fois pour le type d'enregistrement ZS (Zone Status) qui a été accepté, sous un autre nom, NINFO, et figure désormais dans le registre IANA.

Notre RFC a depuis été remplacé par le RFC 6195, qui ne change que des points de détail (puis par le RFC 6895).


Téléchargez le RFC 5395


L'article seul

Déboguer les zones DNS signées avec DNSSEC

Première rédaction de cet article le 26 novembre 2008
Dernière mise à jour le 10 juin 2009


La sécurité est un aller et retour permanent entre trop et pas assez. Trop de sécurité et on ne peut plus rien faire, pas assez et les ennuis nous tombent dessus. Le DNS n'échappe pas à cette dialectique fondamentale. Pour se protéger de l'empoisonnement des résolveurs DNS, on pense à déployer DNSSEC. Oui, mais qui va déboguer les innombrables problèmes que cela va causer et comment ?

La vulnérabilité du DNS aux empoisonnements avec des données fausses est bien connue depuis longtemps (voir par exemple le RFC 3833). Elle est particulièrement prise en compte depuis la révélation de la faille Kaminsky. Pour faire face à cette vulnérabilité, un certain nombre d'experts prônent le déploiement d'une technique de signature cryptographique, DNSSEC, normalisée dans les RFC 4033, RFC 4034 et RFC 4035.

Il existe une longue expérience de déploiement de la cryptographie sur l'Internet et l'une des leçons apprises est que des ennuis se produisent inévitablement. Bogues dans les logiciels et erreurs de procédures de la part des humains font que la cryptographie fonctionne souvent comme une serrure : elle gêne les méchants mais elle peut aussi bloquer les gentils. Normalement, le DNS est très résistant aux erreurs de configuration : il faut vraiment le faire exprès pour rendre une zone complètement inatteignable. Avec DNSSEC, on perd cette robustesse : une erreur et la zone, quoique atteignable, ne sera pas validée et les résolveurs refuseront de transmettre les données. Il est donc crucial d'apprendre à déboguer DNSSEC.

Commençons par un cas banal à l'heure actuelle. On a un résolveur DNS qui valide avec DNSSEC (dans BIND, cela se fait avec l'option dnssec-validatation yes;) et, un matin, une zone DNS n'est plus accessible. Le résolveur, interrogé avec dig dit juste Server failure :


% dig +dnssec SOA example.net

; <<>> DiG 9.5.0-P2 <<>> +dnssec @dnssec SOA example.net
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 31180
                                       ^^^^^^^^
                                       Ici
...

Si on a accès aux journaux de ce résolveur et s'il est configuré en mode suffisamment bavard, on pourra y trouver des détails sur la cause du problème. Mais il faut noter que les résolveurs Unbound et (surtout) BIND ont en commun que les messages ainsi journalisés sont peu compréhensibles, et nécessitent souvent la lecture des RFC pour être décodés.

À l'autre extrémité du spectre de la complexité, une solution entièrement cliquodromesque est le vérificateur du registre de .se, http://dnscheck.iis.se/. Si la zone est disponible publiquement, il peut l'analyser en détail et produire des diagnostics compréhensibles par exemple :

DNSSEC signature expired: RRSIG(example.net/IN/DNSKEY/8850)
Expired signatures will be ignored by validating resolvers.

Cet outil est également distribué, sous une licence libre, pour ceux qui veulent le faire tourner chez eux. Un autre excellent outil de vérification du DNS, Zonecheck, peut faire des tests DNSSEC depuis sa version 3.

Et entre les deux ? Si on est prêt à utiliser quelques outils Unix mais qu'on n'a pas accès au journal du résolveur, ou bien qu'on ne comprend rien à ses messages ? Mark Andrews, responsable de la version actuelle de BIND, aime dire qu'on peut « déboguer DNSSEC uniquement avec dig et date ». Est-ce vrai ?

Voyons ce qu'on peut obtenir avec dig. Par défaut, la plupart des résolveurs validateurs ne distribuent aucune donnée lorsque la signature est invalide. Cela rend difficile le débogage aussi faut-il demander gentiment au résolveur d'envoyer quand même les données invalides, avec l'option +cd :

% dig +dnssec +cd SOA example.net
...
;; ANSWER SECTION:
example.net.            86400   IN      SOA     ns1.example.net. hostmaster.example.net. 2008102101 3600 900 3600000 900
example.net.            86400   IN      RRSIG   SOA 5 2 86400 20081120064157 20081021064157 8850 example.net. QWzZD+N2Y3qCoosWI7T/x3Rlqr06bZXyZhDv6h/L7PxxPXedV63gTz+b q5Rw8p/46rqkBa+YTwAH/050iZMfrKDQALh+0aLI1CJpRaiAUPyXN/hf Dc5kapJmgIW9eSD17hmbKz8Qp29WriqefPTToll4MC1TtBJm1M7QSE2e Y6Q=

Le premier enregistrement, le SOA est ce que nous avions demandé, le second, RRSIG est la signature cryptographique. La majorité est du binaire, que je ne chercherai pas à lire mais certaines données sont en clair, notamment le key ID (ici 8850) et les dates de validité de la signature.

En effet, pour empêcher un attaquant de « rejouer » de vieux enregistrements, les RRSIG ont une date de début et une date de fin de validité. (La période de validité est de un mois, par défaut, si on signe avec l'outil dnssec-signzone de BIND.) dig affiche cette date dans un format quasiment lisible, décrit par les section 3.2 et 3.1.5 du RFC 4034 : YYYYMMDDHHmmSS en UTC. Ici, la date de fin de validité est 20081120064157, donc le 20 novembre 2008 à 06h41 UTC. Comme nous sommes le 26 novembre, pas besoin de chercher plus loin : la signature a expiré. (Pour afficher la date du jour au format identique à celui de dig, sur un Unix qui a GNU date comme Debian, on peut faire date -u +%Y%m%d%H%M%S.)

En effet, puisque les signatures ont une durée de vie limitée, il faut re-signer la zone périodiquement. Les futures version de BIND le feront automatiquement. Mais, en attendant, il faut mettre dans son crontab quelque chose comme :

dnssec-signzone -N increment example.net

À noter qu'il existe aussi des appliances DNSSEC comme celle de Secure64 qui, normalement, vous dispensent de cette tâche.

Mais, pour l'instant, il faut bien dire que la signature expirée est la cause la plus fréquente de problèmes DNSSEC. Tellement qu'elle vaut la peine d'une surveillance spécifique. Par exemple, le script check-sig vérifie un nom de domaine et affiche un message d'erreur si sa signature est expirée ou bien si elle le sera bientôt (sept jours par défaut) :

% check-sig example.net
% 

% check-sig SOA example.net
Name example.net has an expired signature (20081120064157)
%

% check-sig example.org
Name example.org has a signature that will expire in less than 7 days (20081201224442)
%

Il peut donc être mis dans une crontab pour donner l'alarme lorsqu'une signature risque d'expirer. (Merci à Erwan David, Thomas Parmelan, Pierre Beyssac, Phil Regnauld et tlhackque pour sa mise au point.)

Et la cause suivante, en nombre d'erreurs ? Probablement les incohérences dans la délégation. DNSSEC repose, comme le DNS, sur un modèle hiérarchique. Une racine délègue à des zones qui délèguent à des sous-zones et ainsi de suite. Chacune de ces délégations, matérialisées par un enregistrement DS (RFC 4034, section 5), est évidemment signée. La principale différence avec le DNS est que la racine de signature peut être différente de la racine tout court, grâce à DLV (RFC 5074, technique désormais abandonnée). Ainsi, à l'heure actuelle, la plupart des zones signées sont délégués depuis le registre DLV de l'ISC, ce qui n'est plus le cas depuis. (Cf. RFC 8749.)

Or, des problèmes peuvent survenir lors des délégations puisque elles impliquent deux organisations différentes. Par exemple, un administrateur de zone décide de signer car c'est à la mode puis arrête de le faire mais oublie qu'un enregistrement DLV pointe vers lui (et donc garantit que la zone devrait être signée). Ou bien l'administrateur modifie sa clé et oublie de prévenir la zone au-dessus. De telles contradictions entre la zone parente et la zone fille sont fréquentes dans le DNS d'aujourd'hui mais, avec DNSSEC, elles ne pardonnent pas.

Supposons donc que la zone example.net ne fonctionne pas : nous ne récupérons que le Server Failure. Regardons sa clé (l'option +multi rend l'affichage des clés plus agréable) :

% dig +dnssec +cd +multi DNSKEY example.net
...
;; ANSWER SECTION:
example.net.              366 IN DNSKEY 257 3 5 (
                                AwEAAc4x/KbNECb+dpDDBSvyxfTlvUxXyC3EAqCnXDp4
                                +IxjfmwCm1QfB/VIMfqQ2bSsEu51BPk/38dBG01COvE5
                                tYit/Ux8gIuDgZiJx+ldZ9OAJ3Lnm7v/q5+gy2LSzW46
                                p6U45WHmGnDZ4c3uhzcfooXmQsW4UmIw+zDc2ePADy3M
                                bkr3Srll3XDny1OHoW6Ch4o8qC+ezzRDSEnhrtpon+r9
                                4sqXF50k6OLaqCRB3q9iaGUgviTVfZWJIlvZOwvxxpbH
                                SDd6QThM/CZBzcx/8JHAwP7MJcUQYS8XvBwRdaAfVDuE
                                FjUj6IF+vgn8PI1ipQUrF8L0OAHf1dHBou1XjuE=
                                ) ; key id = 17398

Sa clé est la 17398. Est-elle bien chez le parent ? On demande à celui-ci :

% dig @addr-server-parent +dnssec +cd +multi DS example.net.
...
;; ANSWER SECTION:
example.net.              1800 IN DS 6732 5 1 (
                                BBDDDD272C4D81EF941C722CEF79A848B543502D )

Oui, il y a bien un enregistrement DS mais pour une autre clé, la 6732. La chaîne de confiance est cassée là. Sans doute un changement de clé effectué sans prévenir le parent.

Attention, il est courant d'avoir plusieurs clés et il faut donc les regarder toutes.

Avec DLV, même principe. Ma zone sources.org est signée et enregistrée dans DLV à l'ISC, ce qu'on peut voir avec :

% dig @ns-ext.isc.org +multi DLV sources.org.dlv.isc.org
...
;; ANSWER SECTION:
sources.org.dlv.isc.org. 3600 IN DLV 22107 5 2 (
                                AF12A23DFBCDB5609DCEC2C2FBD3CD65AEEFE49CBE07
                                51C65C71C983986B7DE5 )
sources.org.dlv.isc.org. 3600 IN DLV 14347 3 1 (
                                31FF6986A07DAC3642C18606FC992F6ED403A873 )
sources.org.dlv.isc.org. 3600 IN DLV 14347 3 2 (
                                0D5D5B209264BBA5EDAEC9B95843901073BF27F01702
                                B144FFC1389D747DAB7F )
sources.org.dlv.isc.org. 3600 IN DLV 22107 5 1 (
                                EA78D532118A6C2B3C95447A7E520FF3B16FE775 )

Il y a deux clés, les 14347 et 22107, utilisant deux algorithmes différents, d'où les quatre DLV. Ici, tout va donc bien.

Et si la recherche d'une clé dans la zone ne donnait rien ? C'est que la zone n'est pas signée. Actuellement, c'est l'écrasante majorité. Sauf s'il existe une délégation DNSSEC depuis le parent (la zone serait alors invalide), ces zones ne doivent pas être refusées, sauf extrême paranoïa. Si elles déclenchent un Server Failure, c'est qu'il y a une raison non-DNSSEC à cela.

On peut tester ces techniques avec la zone test.dnssec-tools.org où se trouvent de nombreux enregistrements DNSSEC cassés volontairement. Par exemple, futuredate-A.newzsk-ns.test.dnssec-tools.org a une date des signatures valide seulement dans le futur... Même chose avec un autre domaine cassé exprès, dnssec-failed.org.

Bien sûr, un million d'autres choses peuvent tomber en panne. Par exemple, DNSSEC dépend d'EDNS0, puisque les réponses DNSSEC sont typiquement plus grosses. L'expérience prouve qu'un certain nombre de pare-feux bogués interceptent les paquets avec EDNS0 ou bien qu'un certain nombre d'administrateurs incompétents configurent leur pare-feu pour rejeter les paquets DNS de taille supérieur à 512 octets. Il faut donc également être prêt à déboguer la configuration réseau.

On trouve de nombreuses indications pratiques sur le débogage de DNSSEC dans le DNSSEC HOWTO, a tutorial in disguise ou bien dans les transparents DNSSEC in 6 minutes. Merci à Mohsen Souissi pour le débogage du texte et à Mark Andrews pour ses exemples de déboguage sur la liste bind-users.


L'article seul

Que sont les dinosaures devenus ?

Première rédaction de cet article le 25 novembre 2008


Sur mon site Web se trouvaient il y a très longtemps des jolies photos de dinosaures numérisées à partir d'un vieux livre. N'étant pas sûr de la situation légale de ces photos, j'ai préféré les retirer.

Ce qui est curieux, c'est que les adresses Web ne meurent jamais. Des années après, ces photos, qui étaient très populaires et bien référencées (et on parle d'une époque où Google n'existait pas) continuent à être demandées à leur ancienne adresse, http://www.internatif.org/bortzmeyer/dinos/. La leçon à en tirer est qu'il ne faut pas changer les adresses des ressources Web : on ne peut pas changer les milliers d'endroits où elles sont enregistrées.

Le moteur de recherche de Yahoo, par exemple, s'obstine à demander ces images. Il n'a jamais accepté qu'elles disparaissent :

72.30.87.98 - - [25/Nov/2008:09:26:47 +0100] "GET /dinos/index.fr.html HTTP/1.0" 410 457 "-" "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)" www.bortzmeyer.org

J'ai modifié la configuration d'Apache pour renvoyer le code d'erreur 410 (« Parti définitivement » alors que la classique 404 peut être temporaire ; les deux codes sont décrits respectivement dans les sections 6.5.9 et 6.5.4 du RFC 7231). Dans le .htaccess :

Redirect gone /dinos

Apache envoie alors un message d'erreur sans ambiguïté. Mais cela n'a rien changé, Yahoo continue à s'acharner.

Parfois, l'examen du champ Referer: tel qu'il est enregistré dans le journal d'Apache indique que le visiteur vient d'une page de liens comme http://www.lauriefowler.com/dinopix.html, page qui n'est plus mise à jour depuis longtemps. Le Web est d'une stabilité étonnante...

Au cas où cette inertie ne suffise pas, vous pouvez aussi utiliser le remarquable service de Internet Archive pour voir une version archivée de ces photos.


L'article seul

Vers une programmation réseau orientée vers le nom de machine

Première rédaction de cet article le 25 novembre 2008


Aujourd'hui, une des raisons pour lesquelles il est difficile de déployer de nouveaux protocoles réseaux est la dépendance des applications aux adresses IP, utilisées comme identificateurs. D'où la proposition radicale de Christian Vogt : que les machines aient une pile réseau centrée sur le nom de machine, sans accès facile à l'adresse IP, de façon à permettre de changer celle-ci, voire de changer son format ou sa sémantique.

Christian Vogt est l'auteur de plusieurs RFC sur la mobilité et un participant actif du groupe de recherche RRG de l'IRTF. C'est un chercheur très concret, toujours soucieux de proposer des solutions réalistes.

Dans son article Towards A Hostname-Oriented Network Protocol Stack for Flexible Addressing in a Dynamic Internet, Vogt propose que les applications n'aient plus accès trop facilement aux adresses IP, comme c'est le cas actuellement avec l'API de très bas niveau des prises. Il propose qu'on remplace cette API, qui lie les applications au concept d'« adresse IP comme identificateur » par une nouvelle API qui comprendrait essentiellement deux primitives :

  • ConnectToHostname(host) qui prendrait comme paramètre le nom de la machine où on veut se connecter et,
  • AcceptFromHostname() qui accepterait les connexions.

Derrière, le système d'exploitation devrait faire la résolution de nom en adresse, bien sûr, mais aussi gérer le changement d'adresse IP en cours de session, si utile à la mobilité et au multihoming, et que des protocoles comme SCTP (RFC 3286) permet.

Certaines API existantes (par exemple celles de bibliothèques comme libcurl ou comme le WSAConnectByName de Microsoft) permettent un mécanisme du genre ConnectToHostname mais qui ne gère pas le changement d'adresse en cours de session.

L'adoption d'une telle API permettrait donc de résoudre le problème du « portage » des applications de IPv4 vers IPv6, qui est une aberration en soi. Normalement, un changement de format des adresses dans la couche 3 n'aurait dû avoir aucun impact sur les applications.

Mais cette API permettrait aussi de pouvoir un jour déployer des protocoles plus avancés, où l'adresse IP n'est pas exposée, comme LISP ou HIP (RFC 9063).

Hélas, l'expérience des migrations précédentes n'incite pas à l'optimisme. Les API sont très stables, voire immobiles, et il est très difficile d'obtenir un changement des habitudes. Il suffit de voir, par exemple, qu'on trouve encore des universités où on enseigne la résolution de noms via gethostbyname(), méthode spécifique à IPv4 et abandonnée depuis le RFC 2133 il y a plus de dix ans...


L'article seul

Le Web et la version originale des documents

Première rédaction de cet article le 23 novembre 2008


Aujourd'hui, beaucoup de sites Web sont disponibles en plusieurs langues. Par exemple le site de Barcelone, http://www.barcelona.cat/, est en catalan, en espagnol et en anglais. Celui de Katmandou, http://www.kathmandu.gov.np/, est en népalais et en anglais, etc. Mais comment choisit-on sa version ? Le problème est plus compliqué qu'il n'y parait.

La norme du protocole HTTP, le RFC 2616, fournit une solution simple, la négociation de contenu (en-tête Accept-Language, RFC 2616, section 14.4). Le navigateur Web est configuré par son utilisateur avec une liste de langues préférées (par exemple, je préfère le breton, sinon le français, sinon l'anglais), il indique cette liste au serveur et le serveur envoie la page dans la langue préférée dont il dispose. Un logiciel comme Apache a ce qu'il faut pour cela. C'est très simple pour l'utilisateur, qui n'a pas à répéter son choix à chaque fois. S'il utilise un navigateur comme Konqueror, il n'aura même rien à faire, le navigateur utilisant les préférences globales de l'environnement KDE. Pour les autres navigateurs, on peut suivre l'excellente documentation de Debian.

Mais cette méthode est très peu utilisée. C'est dû en grande partie à la profonde ignorance de la plupart des webmestres : très rares sont ceux qui ont lu le RFC 2616. Mais il y a d'autres raisons : avec Apache, mettre en action cette option interfère avec d'autres options comme la sélection des formats des pages. Enfin, cette technique ne permet pas au lecteur de changer, par exemple s'il veut voir à quoi ressemblent les versions dans d'autres langues. Il faut donc toujours au moins fournir un échappement manuel. Par exemple, le site de Debian, http://www.debian.org/, traduit en des dizaines de langues, y compris le finnois et le coréen, fonctionne automatiquement avec la négociation de langue mais permet également, par des liens en bas de chaque page, de modifier ce choix.

La grande majorité des sites Web multilingues ignorent donc les préférences de langue exprimées via le navigateur. À la place, ils fournissent un mécanisme manuel où l'utilisateur doit, pour chaque site, trouver le lien permettant de sélectionner la langue, trouver sa langue (un problème difficile en soi, surtout avec les sites qui s'obstinent à utiliser de petits drapeaux) et la sélectionner.

Ce système ne tire pas profit des possibilités de HTTP et est pénible pour l'utilisateur. Souvent, en outre, le code qui le met en œuvre est bogué, comme c'est le cas sur le site de Katmandou cité plus haut. Mais il est le seul à donner un contrôle complet à l'utilisateur, sur tous les aspects du choix de langue.

En effet, le mécanisme du RFC 2616 a une grosse limite : il ne traite pas le cas où les textes sont de qualité différentes selon les langues. Ce cas est fréquent (il suffit de comparer http://www.microsoft.com/en/us/ et http://www.microsoft.com/fr/fr/) : bien que ma langue maternelle soit le français, si je demande systématiquement la version française, je me retrouve en général avec des mauvaises traductions, incomplètes et/ou dépassées. Parfois, la langue d'origine est le français et le problème est le même : la version anglaise est loin d'être équivalente.

Maintenir plusieurs versions du même site, en différentes langues, et les garder synchrones et de qualité équivalente à travers les changements et les réorganisations qu'affectent les services de communication est en effet une tâche herculéenne. Très peu d'organisations le font réellement.

Au cinéma, je ne cherche pas systématiquement des films en français, ni d'ailleurs systématiquement des films en anglais. Je préfère des films en version originale, la langue dans laquelle ils ont été faits. Pour les romans, où il n'y a pas de sous-titres, je préfère des versions originales si c'est une langue que je comprends, puis une traduction française et, s'il n'y a pas d'autre choix, une traduction anglaise.

Malheureusement, HTTP n'a pas cette notion de version originale et donc, en pratique, la sélection automatique de langue n'a que peu d'intérêt. J'ai donc cessé de l'utiliser (alors que je trouvais cette idée très astucieuse).

Voir aussi sur ce sujet l'article International Web Usability. L'entièreté du problème de choix de la langue est couvert très en détail (configuration d'Apache, pièges, moyens de les éviter) dans la section 10.5 du livre de Patrick Andries « Unicode en pratique ».

Le même problème se pose évidemment pour le courrier électronique, pour lequel une solution a été normalisée, dans le RFC 8255.


L'article seul

Le fantôme est dans le navigateur

Première rédaction de cet article le 23 novembre 2008


Une part de plus en plus importante de l'activité Internet de beaucoup d'utilisateurs se fait via un navigateur Web. Cet outil devrait donc être digne de la plus grande confiance. Loin de là.

Comme le montre l'étude de Google (Niels Provos, Dean McNamee, Panayiotis Mavrommatis, Ke Wang et Nagendra Modadugu), The Ghost In The Browser - Analysis of Web-based Malware, les navigateurs Web se font bien trop facilement infecter par le malware. Un excellent article, plein de données précises. Un article qui rappelle donc qu'il n'y a rien de ridicule à couper Javascript ou bien à naviguer derrière un relais comme Privoxy.


L'article seul

Configurer l'accès Subversion par HTTP avec Apache

Première rédaction de cet article le 22 novembre 2008


Le VCS Subversion est probablement désormais le plus utilisé des VCS centralisés, une position qui avait été longtemps tenue par CVS. Une de ses particularités est la possibilité d'accéder au dépôt Subversion par différents protocoles réseaux. Pour HTTP, le moyen le plus courant est d'utiliser Apache.

Le client Subversion désigne en effet un dépôt par un URL. Cet URL peut désigner un fichier local (il commence alors par file://, cf. RFC 8089), un accès via un compte distant atteint en SSH et il commence alors par svn+ssh:// ou bien un dépot distant accédé en HTTP, méthode la plus courante dès que le dépôt est utilisé par plusieurs utilisateurs.

Subversion utilise pour cela le protocole WebDAV, une extension à HTTP, normalisé dans le RFC 4918, plus des extensions spécifiques à Subversion. On va utiliser Apache, comme documenté en http://svnbook.red-bean.com/en/1.5/svn.serverconfig.httpd.html. Mettons qu'on veuille un dépôt accessible par l'URL https://svn.example.net/, qui permette les accès anonymes mais qui réserve certains répertoires à des utilisateurs bien identifiées (via LDAP). Apache ne demandera une authentification que pour les parties du dépôt où c'est nécessaire. La configuration va ressembler à :


# Module Apache pour WebDAV
LoadModule dav_module /usr/lib/apache2/modules/mod_dav.so
# Module Apache pour les extensions Subversion à WebDAV
LoadModule dav_svn_module /usr/lib/apache2/modules/mod_dav_svn.so
# Module Apache pour l'authentification par répertoire dans le dépôt
# (ce qu'Apache ne sait pas faire tout seul)
LoadModule authz_svn_module /usr/lib/apache2/modules/mod_authz_svn.so

# Uniquement en httpS, pour des raisons de sécurité, donc port 443
<VirtualHost *:443>
    ServerAdmin webmaster@example.net
    ServerName svn.example.net
 
    # Pour le chiffrement, on utilise GNU TLS (et pas OpenSSL)
    GnuTLSEnable  on
    GnuTLSCertificateFile /etc/ssl/certs/ssl-cert-www.example.net.pem
    GnuTLSKeyFile /etc/ssl/private/ssl-cert-www.example.net.key
    GnuTLSPriorities NORMAL:!AES-256-CBC:!DHE-RSA

 <Location />
 
  # Le dépôt
  DAV svn
  SVNPath /home/Subversion-Repository

  # Couper l'authentification ordinaire et activer celle par
  # LDAP. Naturellement, d'autres méthodes que LDAP sont
  # possibles. Voir 
  # <http://svnbook.red-bean.com/nightly/en/svn.serverconfig.httpd.html#svn.serverconfig.httpd.authz>
  AuthUserFile /dev/null
  AuthBasicProvider ldap
  AuthType Basic  
  AuthName "Example & co Subversion Repository"
  AuthLDAPURL ldap://ldap.example.net/ou=People,dc=example,dc=net?uid?sub?(objectClass=*)

  # Le fichier où se trouvent les autorisations par répertoire
  AuthzSVNAccessFile /etc/apache2/subversion-access

  # On utilise "Satisfy any" car on veut permettre les accès anonymes aussi
  Satisfy any
  require valid-user

  </Location>

</VirtualHost>

Et ce fichier /etc/apache2/subversion-access, qui stocke les autorisations, que contient-il ? Il est documenté en http://svnbook.red-bean.com/en/1.5/svn.serverconfig.pathbasedauthz.html. Le principe est qu'on définit des groupes d'utilisateurs, puis on indique des permissions (droit de lire et d'écrire) à des répertoires du dépôt. Tous les répertoires ne sont évidemment pas listées systématiquement. Lorsqu'un répertoire n'est pas indiqué, Subversion utilise les permissions du parent, puis du grand-parent, etc. L'ordre des directives dans le fichier n'est donc pas vital mais la plupart des administrateurs mettent les répertoires du plus général au plus spécifique. Voici un exemple :

# Definition des groupes d'utilisateurs 
[groups]
# La compagnie
staff = smith,jones,muller
# Des partenaires sur un projet
foobar = @staff,durand,li

# Par défaut : tout le monde peut lire, la compagnie peut lire et écrire
[/]
* = r
@staff = rw

[/Business]
# Inaccessible aux extérieurs. Comme les permissions sont normalement
# héritées du parent, il faut explicitement couper l'accès de "*" (tous).
* = 
@staff = rw

[/FooBar]
# Un projet public, sur lequel nos partenaires travaillent
* = r
@foobar = rw

[/Secret]
# Projet très réservé
* =
smith = rw

À noter qu'il n'existe apparemment pas de moyen simple pour donner des droits à tous, sauf aux anonymes. Il faut lister tous les authentifiés explicitement (* inclus les anonymes).

Voici un accès à ce répertoire par un utilisateur anonyme, qui utilise le client Subversion en ligne de commande :

% svn co https://svn.example.net/
...
A    svn.example.net/FooBar/src/main.d
...
Checked out revision 7979.

Si, maintenant, je vais dans un des répertoires qui demandent une authentification :

% cd svn.example.net/FooBar/src
% emacs util.d
% svn add util.d
A         util.d
% svn commit
Authentication realm: <https://svn.example.net:443> Example & co Subversion Repository
Password for 'smith': 
Adding         FooBar/src/util.d
Transmitting file data .
Committed revision 7980.

Apache demandera l'authentification, puisque l'anonyme n'a pas le droit d'écrire dans ce répertoire (notez que le client Subversion a affiché le domaine d'authentification, tel que configuré par AuthName).

L'un des inconvénients de l'utilisation d'Apache et de WebDAV est qu'il n'y a pas de rapport simple entre les actions Subversion (checkout, commit, etc) et les requêtes HTTP. L'examen du journal d'Apache n'est donc pas très utile. Un simple commit va produire une dizaine de requêtes dont :

88.189.152.187 - smith [22/Nov/2008:18:40:56 +0100] "PUT //!svn/wrk/8f2454bd-4a5c-0410-af3f-ad2595489424/FooBar/src/util.d HTTP/1.1" 204 - "-" "SVN/1.4.4 (r25188) neon/0.26.3" svn.example.net
88.189.152.187 - smith [22/Nov/2008:18:40:56 +0100] "MERGE /FooBar HTTP/1.1" 200 709 "-" "SVN/1.4.4 (r25188) neon/0.26.3" svn.example.net
88.189.152.187 - smith [22/Nov/2008:18:40:56 +0100] "DELETE /!svn/act/8f2454bd-4a5c-0410-af3f-ad2595489424 HTTP/1.1" 204 - "-" "SVN/1.4.4 (r25188) neon/0.26.3" svn.example.net

L'article seul

Connecter un serveur dédié à IPv6 avec un tunnel manuel

Première rédaction de cet article le 20 novembre 2008
Dernière mise à jour le 25 novembre 2009


Il existe beaucoup de façons de connecter une machine ou un réseau qui n'a pas d'IPv6 natif au monde IPv6. Je présente ici le tunnel manuel, que j'ai utilisé pour qu'une de mes machines soit joignable en IPv6.

L'épuisement proche des adresses IPv4 rend nécessaire de pousser les feux du déploiement d'IPv6. La machine utilisée pour cet article est hébergée chez Slicehost, qui ne fournit pas de connectivité IPv6. Mais on peut quand même le faire via un tunnel.

Je me suis créé un compte chez Hurricane Electric, qui est présent à Chicago, à douze milli-secondes de ma machine.

Ma nouvelle adresse IP est donc 2001:470:1f10:3aa::2. Je crée un fichier de démarrage pour Gentoo :

start() {
        ebegin "Starting IPv6 connection through Hurricane Electric"
        (
             modprobe ipv6
             ifconfig sit0 up
             ifconfig sit0 inet6 tunnel ::209.51.181.2
             ifconfig sit1 up
             ifconfig sit1 inet6 add 2001:470:1f10:3aa::2/64
             route -A inet6 add ::/0 dev sit1
        )
        eend $?
}

Sur une Debian, avec /etc/network/interfaces, ce serait (pour le cas d'une machine ayant un autre point d'attachement) :

auto 6in4
iface 6in4 inet6 v4tunnel 
   # Le POP d'Hurricane Electric au Panap
   endpoint 216.66.84.42
   address 2001:470:1f12:420::2
   netmask 64
   # "gateway" n'a pas l'air de marcher ?
   up route -A inet6 add ::/0 dev 6in4

Si on a un pare-feu, il faut penser à laisser passer les paquets IPv6 encapsulés dans IPv4 (protocole 41). Avec Shorewall, cela se fait dans /etc/shorewall/tunnels :

# Hurricane Electric in Chicago
6to4     net    209.51.181.2

Et tout fonctionne :

% traceroute6 2001:470:1f10:3aa::2
 ...
 9  10gigabitethernet1-4.core1.ams1.he.net (2001:470:0:47::1)  17.663 ms  17.468 ms  17.376 ms
10  10gigabitethernet1-4.core1.lon1.he.net (2001:470:0:3f::1)  18.894 ms  19.454 ms  18.78 ms
11  10gigabitethernet2-3.core1.nyc4.he.net (2001:470:0:3e::1)  87.946 ms  89.41 ms  87.904 ms
12  10gigabitethernet1-2.core1.chi1.he.net (2001:470:0:4e::1)  115.003 ms  112.809 ms  112.441 ms
13  1g-bge0.tserv9.chi1.ipv6.he.net (2001:470:0:6e::2)  112.213 ms  111.927 ms  112.223 ms
14  bortzmeyer-1-pt.tunnel.tserv9.chi1.ipv6.he.net (2001:470:1f10:3aa::2)  118.001 ms  118.153 ms  118.031 ms

J'ai donc modifié la zone bortzmeyer.org pour ajouter un enregistrement AAAA pour la machine en question. Je peux maintenant me vanter de ma certification IPv6.

À noter que la création du compte chez Hurricane Electric ne s'est pas passé toute seule : il y avait une bogue dans le formulaire HE, j'écris et une heure après la bogue est réparée. Ça change des boîtes françaises !

Hurricane Electric fournit aussi un /64 routé, 2001:470:1f11:3aa::/64 dans mon cas, et on peut donc configurer sa machine pour gérer ces adresses. Sur Gentoo :

route -A inet6 add 2001:470:1f11:3aa::/64 dev eth0
ifconfig eth0 add 2001:470:1f11:3aa::bad:dcaf

Sur Debian :

iface eth0 inet6 static
   address 2001:470:1f13:420::bad:dcaf
   netmask 64

Je n'ai pas pu utiliser le tunnel broker de Renater car il a aussi une bogue dans son formulaire, qui refuse mon inscription.

Une autre possibilité aurait été Sixxs mais l'inscription et la création du tunnel sont effectués manuellement et j'étais trop impatient.


L'article seul

Évaluer la valeur d'une adresse IP

Première rédaction de cet article le 18 novembre 2008


Voici une nouvelle avancée du marché dans un monde qui ne le connaissait pas : une proposition pour un service de rating des adresses IP.

Pour les noms de domaine, cela se fait depuis longtemps (voir le fameux sex.com ou bien ce que fait Sedo). Mais cela n'était pas encore le cas pour les adresses IP, alors qu'elles feront très probablement bientôt l'objet d'un marché.

Mais pourquoi certaines adresses IP valent-elles moins que d'autres ? C'est parce qu'elles sont « gâtées », par exemple parce qu'elles avaient été utilisées par des spammeurs. Une fois que cela est fait, impossible de sortir des listes noires (voir, par exemple, « Go Daddy blocks links to EC2 »).

Cela casse la légende entretenue par les RIR comme quoi toutes les adresses IP se valent...


L'article seul

RFC 5405: Unicast UDP Usage Guidelines for Application Designers

Date de publication du RFC : Novembre 2008
Auteur(s) du RFC : L. Eggert (Nokia), G. Fairhurst (University of Aberdeen)
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 18 novembre 2008


La grande majorité des applications Internet tourne sur le protocole de transport TCP. Mais son concurrent UDP, normalisé dans le RFC 768, prend de l'importance avec le multimédia et les jeux en ligne pour lesquels il est souvent bien adapté. Mais, contrairement à TCP, UDP ne fournit aucun mécanisme de contrôle de la congestion. C'est donc aux applications de fournir ce contrôle, suivant les règles expliquées par ce RFC. (Il a depuis été remplacé par le RFC 8085.)

UDP est apprécié pour certaines applications car il est simple et léger et le fait qu'il ne garantisse pas l'acheminement de la totalité des paquets n'est pas forcément un problème dans les applications multimédia : si on perd quelques secondes d'une communication téléphonique RTP, il vaut mieux passer à la suite que de perdre du temps à la retransmettre comme le ferait TCP. Mais UDP ne fournit pas non plus de contrôle de la congestion. C'est pourtant nécessaire (RFC 2914 et RFC 7567), à la fois pour assurer que le réseau continue à être utilisable et également pour assurer une certaine équité entre les différents flux de données, pour éviter qu'une seule application gourmande ne monopolise le réseau pour elle.

UDP ne le faisant pas, il faut bien que l'application le fasse et, pour cela, qu'elle mette en œuvre les conseils de ce RFC. (Notre RFC contient également des conseils pour d'autres aspects de l'utilisation d'UDP que le contrôle de congestion : mais c'est le plus important.)

Le gros du RFC est dans la section 3 qui détaille ces conseils (la section 5 contient un excellent résumé sous forme d'un tableau des conseils à suivre). Le premier est qu'il vaut peut-être mieux ne pas utiliser UDP. Beaucoup de développeurs d'applications pensent à UDP en premier parce qu'il est simple et facile à comprendre et qu'il est « plus rapide que TCP ». Mais, rapidement, ces développeurs se rendent compte qu'ils ont besoin de telle fonction de TCP, puis de telle autre, ils les mettent en œuvre dans leur application et arrivent à une sorte de TCP en moins bien, davantage bogué et pas plus rapide. Notre RFC conseille donc d'abord de penser aux autres protocoles de transport comme TCP (RFC 793), DCCP (RFC 4340) ou SCTP (RFC 4960). Ces protocoles sont d'autant plus intéressants qu'ils ont souvent fait l'objet de réglages soigneux depuis de nombreuses années et qu'il est donc difficile à un nouveau programme de faire mieux. D'autant plus qu'il existe souvent des réglages spécifiques pour les adapter à un usage donné. Par exemple, on peut dire à TCP de donner la priorité à la latence (paramètre TCP_NODELAY de setsockopt) ou bien au débit.

Si on ne suit pas ces sages conseils, et qu'on tient à se servir d'UDP, que doit-on faire pour l'utiliser intelligemment ? La section 3.1 couvre le gros morceau, le contrôle de congestion. Celui-ci doit être pris en compte dès la conception de l'application. Si cette dernière fait de gros transferts de données (section 3.1.1, c'est le cas de RTP, RFC 3550), elle doit mettre en œuvre TFRC, tel que spécifié dans le RFC 5348, donc faire à peu près le même travail que TCP. Et ce mécanisme doit être activé par défaut.

Si l'application transmet peu de données (section 3.1.2), elle doit quand même faire attention et le RFC demande pas plus d'un datagramme par RTT, où le RTT est un cycle aller-retour avec la machine distante (calculé selon le RFC 2988 ; si le calcul n'est pas possible, le RFC demande une durée de trois secondes). L'application doit également détecter les pertes de paquet pour ralentir son rythme si ces pertes - signe de congestion - sont trop fréquentes.

Le cas où l'application est un tunnel au dessus d'UDP est également couvert (section 3.1.3).

En suivant toutes ces règles, l'application gère proprement la congestion. Et le reste ? La section 3.2 fournit des pistes sur la gestion de la taille des paquets (rester en dessous de la MTU, utiliser la découverte de MTU spécifiée dans des RFC comme le RFC 4821, etc). La 3.3 explique la question de la fiabilité : par défaut, UDP ne retransmet pas les paquets perdus. Si c'est nécessaire, c'est l'application qui doit le faire. Elle doit aussi gérer l'eventuelle duplication des paquets (qu'UDP n'empêche pas). Le RFC note que les retards des paquets peuvent être très importants (jusqu'à deux minutes, normalise le RFC) et que l'application doit donc gérer le cas où un paquet arrive alors qu'elle croyait la session finie depuis longtemps.

La section 3.4 précise l'utilisation des sommes de contrôle (facultatives pour UDP sur IPv4 mais qui devraient être utilisées systématiquement). Si une somme de contrôle pour tout le paquet semble excessive, et qu'on veut protéger uniquement les en-têtes de l'application, une bonne alternative est UDP-Lite (RFC 3828), décrit dans la section 3.4.1.

Beaucoup de parcours sur l'Internet sont encombrés de « middleboxes », ces engins intermédiaires qui assurent diverses fonctions (NAT, coupe-feu, etc) et qui sont souvent de médiocre qualité logicielle, bricolages programmés par un inconnu et jamais testés. La section 3.5 spécifie les règles que devraient suivre les applications UDP pour passer au travers sans trop de heurts. Notamment, beaucoup de ces « middleboxes » doivent maintenir un état par flux qui les traverse. En TCP, il est relativement facile de détecter le début et la fin d'un flux en observant les paquets d'établissement et de destruction de la connexion. En UDP, ces paquets n'ont pas d'équivalent et la détection d'un flux repose en général sur des heuristiques. L'engin peut donc se tromper et mettre fin à un flux qui n'était en fait pas terminé. Si le DNS s'en tire en général (c'est un simple protocole requête-réponse, avec en général moins de deux secondes entre l'une et l'autre), d'autres protocoles basés sur UDP pourraient avoir de mauvaises surprises. Elles doivent donc se préparer à de soudaines interruptions de la communication, si le timeout d'un engin intermédiaire a expiré alors qu'il y avait encore des paquets à envoyer. (La solution des keepalives est déconseillée par le RFC car elle consomme de la capacité du réseau et ne dispense pas de gérer les coupures, qui se produiront de toute façon.)

La section 3.6 fera le bonheur des programmeurs qui y trouveront des conseils pour mettre en œuvre les principes de ce RFC, via l'API des prises (sockets, RFC 3493). Elle est largement documentée mais en général plutôt pour TCP que pour UDP, d'où l'intérêt du résumé qu'offre ce RFC, qui ne dispense évidemment pas de lire le Stevens. Par exemple, en l'absence de mécanisme de TIME_WAIT (la prise reste à attendre d'éventuels paquets retardés, même après sa fermeture par l'application), une application UDP peut ouvrir une prise... et recevoir immédiatement des paquets qu'elle n'avait pas prévus, qui viennent d'une exécution précédente.

Le protocole ICMP fournit une aide utile, que les applications UDP peuvent utiliser (section 3.7). Mais attention, certains messages ICMP peuvent refléter des erreurs temporaires (absence de route, par exemple) et ne devraient pas entraîner de mesures trop drastiques.

Après tous ces conseils, la section 4 est dédiée aux questions de sécurité. Comme TCP ou SCTP, UDP ne fournit en soi aucun mécanisme d'intégrité des données ou de confidentialité. Pire, il ne fournit même pas d'authentification de l'adresse IP source (authentification fournie, avec TCP, par le fait que, pour établir la connexion, il faut recevoir les réponses de l'autre). L'application doit-elle mettre en œvre la sécurité seule ? Le RFC conseille plutôt de s'appuyer sur des protocoles existants comme IPsec (RFC 4301) ou DTLS (RFC 6347). En effet, encore plus que les protocoles de gestion de la congestion, ceux en charge de la sécurité sont très complexes et il est facile de se tromper. Il vaut donc mieux s'appuyer sur un système existant plutôt que d'avoir l'hubris et de croire qu'on peut faire mieux que ces protocoles ciselés depuis des années.

Pour authentifier, il existe non seulement IPsec et DTLS mais également d'autres mécanismes dans des cas particuliers. Par exemple, si les deux machines doivent être sur le même lien (un cas assez courant), on peut utiliser GTSM (RFC 3682) pour s'en assurer.

Voilà, un rappel, ce RFC n'est plus d'actualité, il a été remplacé par le RFC 8085.


Téléchargez le RFC 5405


L'article seul

Épuisement des adresses IPv4

Première rédaction de cet article le 16 novembre 2008
Dernière mise à jour le 20 juin 2014


Depuis plus de deux ans, cet article avait été automatiquement mis à jour pour suivre l'allocation des adresses IPv4 et le temps qui restait avant leur épuisement. Eh bien, c'est désormais fait, il ne reste plus de préfixes IPv4 libres à l'IANA.

Les chiffres et dates contenus dans cet article étaient automatiquement mises à jour à partir de la liste officielle des allocations. Le nombre d'adresses IPv4 étant une ressource finie et non renouvelable, l'épuisement futur ne faisait aucun doute (même si quelques négationnistes arrivaient à nier ce fait). La dernière adresse IPv4 ayant été allouée par l'IANA, il faut, ou bien arrêter toute croissance de l'Internet, ou bien passer à IPv6, comme cela aurait dû être fait depuis longtemps. Une autre « solution » sera d'accepter un Internet limité, où les clients résidentiels, puis les petites entreprises et les associations, n'auront plus d'adresses IP publique du tout et devront passer des bricolages comme le NAT, qui limitent le nombre de services auxquels ils auront accès (par exemple le pair-à-pair).

Il reste certes un tout petit peu de temps avant que l'épuisement des adresses v4 ne touche tout le monde. Les RIR ont reçu des préfixes de l'IANA qui n'ont pas été épuisés tout de suite. Chaque RIR avait encore un à deux ans de réserve, avant de ne plus pouvoir rien donner aux FAI. Le premier à tomber à cours a été l'APNIC, le 15 avril 2011. Le RIPE-NCC a suivi le 14 septembre 2012 puis se furent ARIN en avril 2014 et LacNIC en juin 2014. Aujourd'hui, seul AfriNIC a encore sa réserve normale d'adresses IPv4. Notez que chaque RIR garde en réserve un /8 spécial, pour être attribué selon une politique très restrictive (c'est donc déjà le cas de tous les RIR sauf un). Ensuite, ce seront les FAI qui ne pourront plus rien donner aux clients. Bref, on peut avoir l'illusion que la pénurie n'existe pas encore vraiment mais il faut pour cela fermer très fort les yeux et avoir un optimisme en béton.

Pour faire des statistiques sur ce nouvel épuisement (celui des réserves des RIR), je manque de temps mais on peut regarder :


L'article seul

RFC 5387: Problem and Applicability Statement for Better Than Nothing Security (BTNS)

Date de publication du RFC : Novembre 2008
Auteur(s) du RFC : J. Touch (USC/ISI), D. Black (EMC), Y. Wang (Microsoft)
Pour information
Réalisé dans le cadre du groupe de travail IETF btns
Première rédaction de cet article le 15 novembre 2008


En matière de sécurité, le mieux peut être l'ennemi du bien. Un protocole très exigeant peut, en partie à cause de ces exigences, ne pas être déployé et laisser donc l'Internet aussi vulnérable qu'avant. C'est en partie ce qui est arrivé à IPsec et a justifié le travail sur le mécanisme « Mieux que rien » qui fait l'objet de plusieurs RFC dont notre RFC 5387 qui décrit les motivations et le domaine d'application de ce nouveau mécanisme ou dont le RFC 5386 qui normalise le nouveau protocole.

C'est une banalité que de dire que l'Internet n'est pas sûr. N'importe qui peut envoyer un paquet avec une fausse adresse IP, il est très facile d'écouter ce qui passe sur le réseau et il est facile de s'insérer dans une session déjà commencée. On peut se demander pourquoi le problème n'a pas encore été traité. Il l'a été, pourtant. Par exemple, IETF a depuis 1998 un protocole, IPsec (actuellement RFC 4301), qui permet de sécuriser n'importe quelle connexion Internet contre l'écoute ou la modification, en utilisant la cryptographie. IPsec est exigeant : pour établir une SA (Security Association, association de sécurité entre deux machines, qui leur permettra de communiquer en toute sécurité), il faut s'authentifier, ce qui veut dire un secret partagé (un mot de passe) ou bien une signature reconnue par une autorité commune. Si IPsec peut utiliser plusieurs identités dans sa base , les adresses IP, noms de domaine et bien d'autres, toutes doivent être authentifiées (voir aussi la section 2.1). C'est lourd et compliqué et cela a pesé sérieusement dans le peu de déploiement d'IPsec (section 1 du RFC).

Alors, faut-il supprimer l'obligation d'authentification ? Après tout, si IPsec est utilisé entre deux pairs BitTorrent, quel besoin ont-ils de s'authentifier ? La plupart du temps, les pairs acceptent de servir n'importe quelle autre machine. Même chose pour un serveur Web public. Mais ce n'est pas si simple (section 1.1) car l'authentification sert aussi à empêcher les attaques de « l'Homme au Milieu », un attaquant situé entre les deux machines et qui se fait passer pour leur correspondant. Si un tel intermédiaire est présent, la cryptographie ne servira à rien puisque les clés utilisées sont connues du méchant.

C'est pourtant la voie que suit (avec prudence) le nouveau protocole BTNS (Better Than Nothing Security ou « Mieux vaut un peu de sécurité que pas de sécurité du tout - ce qui arrive si on impose des contraintes trop élevées. »).

Ainsi, le protocole telnet était bien connue pour son extrême vulnérabilité, puisque les mots de passe passaient en clair, mais, pendant longtemps, les seules solutions proposées étaient horriblement compliquées comme Kerberos (RFC 1411 pour un telnet « kerberisé »). Elles n'avaient donc jamais été déployées sérieusement avant la sortie de SSH en 1995. SSH, lui, remplacera telnet en quelques années, bien que certains experts en sécurité aient froncé le sourcil lors de son lancement en l'estimant insuffisamment blindé.

Une des solutions qu'utilise BTNS pour limiter les risques est de dépendre d'une authentification faite dans les couches hautes (IPsec travaille dans la couche 3). La section 1.3 décrit comment de tels mécanismes rendent BTNS moins dangereux qu'il n'en a l'air.

On peut se demander quel est l'intérêt de BTNS si un protocole comme TLS s'occupe de toute la sécurité. Mais BTNS est IPsec, donc protège également contre certaines attaques dans les couches basses, contre lesquelles TLS ne peut rien. Ainsi, un paquet TCP RST (Reset, qui va couper la connexion) imité peut couper une session TLS, puisque TLS n'authentifie et ne protège que la couche application. Une telle attaque, pratiquée par exemple par Comcast contre ses propres clients ou par la censure chinoise contre ses citoyens (voir aussi la section 2.2.1), ne marcherait pas avec BTNS.

Les sections 2 et 3 du RFC décrivent plus en détail le problème que BTNS résout et la manière dont il le résoud (en permettant les connexions non authentifiées). La section 4, elle, revient sur le domaine d'application de BTNS. BTNS n'a pas d'intérêt pour les connexions très sécurisées, par exemple entre deux organisations qui veulent établir entre elles un VPN aussi solide que possible. Pour celles-ci, le IPsec actuel est une bonne approche. Mais BTNS est utile si :

  • Un serveur public veut accepter tous les clients mais souhaite protéger les connexions après leur établissement,
  • Un serveur sait authentifier ses clients après l'établissement de la connexion.

La section 4.1 explique les bénéfices de BTNS dans ce cas (pas d'infrastructure d'authentification à gérer) et la 4.2 ses faiblesses (le risque d'établir la connexion avec un imposteur).

Enfin, la section 5 analyse plus complètement les questions de sécurité parfois subtiles qui naissent de ce tournant dans IPsec. BTNS protège la connexion établie, mais pas l'établissement. Il est donc proche des autres protocoles TOFU (Trust On First Use ou, plus méchamment, leap of faith, « acte de foi ») comme SSH. Contrairement à SSH, BTNS ne se souvient pas forcément des clés précédemment présentées, et ne peut donc pas détecter l'arrivée d'un imposteur (cf. section 5.7).

BTNS est donc vulnérable aux attaques de l'homme au milieu (section 5.3) mais aussi à certaines attaques DoS comme tout protocole de cryptographie. En effet (section 5.4), une machine qui établit une connexion IPsec avec vous (ce qui est plus facile avec BTNS puisqu'il n'y a plus d'authentification) peut vous faire exécuter des calculs de cryptographie assez coûteux.

À l'heure actuelle, je ne connais pas d'implémentation de BTNS dans les grands projets IPsec comme Openswan.


Téléchargez le RFC 5387


L'article seul

RFC 5386: Better-Than-Nothing-Security: An Unauthenticated Mode of IPsec

Date de publication du RFC : Novembre 2008
Auteur(s) du RFC : N. Williams (Sun), M. Richardson (SSW)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF btns
Première rédaction de cet article le 15 novembre 2008


Le protocole BTNS (Better Than Nothing Security), expliqué dans le RFC 5387, est normalisé dans ce RFC 5386. Il permet d'utiliser IPsec sans authentification des autres machines, ce qui pourrait simplifier son déploiement.

BTNS ne change pas le protocole IPsec (RFC 4301), ni les protocoles associés comme IKE (RFC 4306). Sur le câble, ce sont les mêmes paquets qui passent, les changements se concentrant sur les machines terminales, dans la PAD (Peer Authentication Database, section 4.4.3 du RFC 4301) et la SPD (Security Policy Database, section 4.4.1 du RFC 4301).

Ce RFC reste assez court car il ne normalise pas encore toutes les idées prévues dans le RFC 5387 comme par exemple la liaison entre une SA (Security Association) IPsec et une connexion dans les couches hautes (cf. section 4.1) ou comme la mémoire des SA précédentes, pour n'avoir à faire confiance à un inconnu que la première fois (cf. section 4.2, qui propose un futur mécanisme analogue à celui de SSH).

La section 2 décrit BTNS par rapport à l'IPsec traditionnel. Le principal changement est que, après l'examen de toutes les entrées de la PAD, une implémentation de BTNS peut simplement accepter un pair uniquement pour sa clé publique, ou même pour n'importe quelle clé (cas où on accepte les connexions de tout le monde).

La section 3 décrit quelques exemples de scénarios avec BTNS. Ainsi, 3.3 décrit un serveur NFS qui veut protéger le trafic NFS avec IPsec, tout en acceptant n'importe quel client NFS (accepter au niveau IPsec : les couches hautes peuvent toujours imposer une authentification). La PAD (Peer Authentication Database) ressemblera à :

         Rule Remote ID        IDs allowed  SPD Search by
         ---- ---------        -----------  -------------
          1   PUBLICKEY:any    ANY          by-IP

(Une seule règle, accepter tout le monde. Une telle règle n'était pas possible en IPsec avant BTNS.) Et la SPD (Security Policy Database) pourra être :

        Rule Local Remote Next Layer BTNS  Action
               addr  addr   Protocol   ok
         ---- ----- ------ ---------- ----  -----------------------
          1    [C]    ANY      ANY      yes  PROTECT(ESP,transport,
                     with                               integr+conf)
                     port
                     2049

          2    [C]    ANY      ANY      N/A  BYPASS

(Utilisation IPsec, avec protection ESP pour le port 2049 (NFS) et ne pas toucher aux autres applications.)

La section 4 revient sur les problèmes de sécurité déjà étudiées dans la section 5 du RFC 5387. BTNS est notamment vulnérable aux attaques d'un attaquant situé au milieu.


Téléchargez le RFC 5386


L'article seul

Plusieurs noms dans un certificat X.509

Première rédaction de cet article le 14 novembre 2008


X.509 est l'énorme usine à gaz qui permet au secrétaire général de l'ITU de se vanter de la contribution de son organisation à l'Internet. Un de ses principes est que le client, par exemple HTTP, est censé vérifier que le nom dans le certificat présenté par le serveur coïncide avec le nom demandé par le client. Et si le serveur a plusieurs noms ?

Ne demandons pas à l'ITU d'avoir prévu un cas aussi simple que celui où une machine est connue par plusieurs noms, comme par exemple www.example.org et www.example.net. Il faut pour cela utiliser des extensions à X.509 telles les Subject Alternative Name du RFC 5280. Ces extensions sont correctement gérées par certains logiciels tels que OpenSSL mais pas forcément par toutes les autorités de certification.

Comment mettre de tels noms supplémentaires dans une demande de signature (CSR pour Certificate Signing Request) ? Avec OpenSSL, il faut éditer openssl.cnf pour y ajouter ces noms (je ne trouve pas de moyen de les indiquer en ligne de commande, ou de faire qu'OpenSSL les demande interactivement :

x509_extensions = v3_req   
...
[ v3_req ]
...
subjectAltName          = @alt_names

[alt_names]
# www.example.net sera donné interactivement
DNS.1   = www.example.org

Et il faut vérifier que la CSR est correcte :

% openssl req -text -in www.example.org.csr
...
           X509v3 Subject Alternative Name: 
                DNS:www.example.org
...

La CA qui signe doit elle-même gérer ces extensions. Si elle utilise OpenSSL, elle doit s'assurer d'avoir dans son openssl.cnf :

copy_extensions = copy

Rien de cela n'est spécifique à HTTP. Par exemple, si on protège ses connexions POP avec TLS, un MUA comme Thunderbird vérifie les noms et proteste si sa configuration lui dit de se connecter à mail.example.org alors que le certificat X.509 ne contient que mail.example.net. L'utilisation de noms supplémentaires résout le problème, Thunderbird ne râle plus.

Une autre solution à ce problème est possible pour les protocoles qui ne commencent pas TLS tout de suite, qui envoient une requête STARTTLS et qui transmettent le nom du serveur (pour permettre à celui-ci de déterminer le certificat à utiliser). C'est le cas de HTTP (RFC 2817) comme le rappelle Pierre Beyssac dans un article qui cite les mises en œuvre possibles (mod_gnutls le gère apparemment).

Pour les protocoles comme POP ou IMAP (RFC 2595), qui ne transmettent pas le nom du serveur, je pense que cette autre solution ne marche pas. Une approche possible serait la Server Name Indication des extensions TLS normalisées dans le RFC 6066, section 3 (merci à Mathieu Arnold pour l'idée). Cette technique permet de transmettre le nom du serveur dans le premier message TLS et fournit donc une solution générale (là encore, elle est mise en œuvre dans GnuTLS). Voir Adieu RFC 2817, bonjour RFC 3546 pour un exemple de mise en œuvre.


L'article seul

Fiche de lecture : Blackwater

Auteur(s) du livre : Jeremy Scahill
Éditeur : Nation books
978-1-84668-652-8
Publié en 2008
Première rédaction de cet article le 12 novembre 2008


Autrefois, les sociétés de mercenaires, qui louaient leurs services aux États pour des coups tordus divers, notamment en Afrique, étaient de petites sociétés européennes ou sud-africaines, comme Sandline ou Executive Outcomes. Pas de bureaux connus, peu de frais de fonctionnement, pas de paperasses, pas de scrupules excessifs. En France, avec Bob Denard, on avait même des organisations complètement informelles, juste un groupe de brutes qui se connaissaient bien et pouvaient répondre à un coup de téléphone en cinq minutes. Mais les États-Unis sont rentrés sur ce marché et ils l'ont sérieusement professionnalisé. La plus importante société de mercernariat privée au monde, Blackwater, marque l'entrée du mercenariat dans l'ère corporate : bataillons d'avocats, service de propagande (pardon, de « communication ») étoffé, et activités de lobbying et de marketing intenses.

Le journaliste Jeremy Scahill a enquêté pendant des annnées sur Blackwater et en a sorti ce livre, la référence sur le monde des « sociétés militaires privées » (il s'agit de la seconde édition). Suivant la mode idéologique du moment, développement de la sous-traitance et réduction du rôle du service public, ces sociétés s'attaquent à ce qui semblait le dernier bastion de la puissance publique, la violence armée. En Irak, il y a déjà davantage de mercenaires que de soldats réguliers. Et cela devrait continuer puisque, comme le dit franchement le PDG de Blackwater, « Quand vous voulez envoyer un colis, vous ne faites pas confiance à la Poste, vous le passer à FedEx. C'est pareil pour les questions de sécurité. ».

Si, au début, les tâches des mercenaires (appelés « sous-traitants civils » désormais) se limitaient à des missions peu glorieuses de gardiennage, désormais, ils sont parfois engagés dans des combats, jusqu'à commander des troupes régulières. S'ils se limitaient aux terres lointaines et exotiques, ils sont maintenant également utilisés sur le sol national, comme à la Nouvelle-Orléans après Katrina.

Scahill décrit en détail ce monde, les budgets considérables dont il dispose, les liens étroits entretenus avec le gouvernement de Washington, la façon dont il s'est rendu indispensable au fur et à mesure du dégraissage de l'armée régulière. Blackwater réussit à payer ses hommes bien plus chers que l'armée (mais sans retraite et sans aucun avantage social), tout en se prétendant moins cher qu'elle (mais les budgets sont tellement opaques qu'il est difficile de savoir ce qu'il en est).

Dans des pays comme l'Irak, les « sous-traitants » opèrent dans la plus totale impunité. N'étant pas aux États-Unis, ils ne sont pas soumis aux lois de ce pays. N'étant pas des militaires d'active, ils ne sont pas soumis aux lois militaires ; si indulgentes soient-elles pour les tortionnaires d'Abou Ghraib, il faut noter que plusieurs soldats ont été poursuivis devant la justice militaire pour des crimes contre des civils irakiens, ce qui n'a jamais été le cas des mercenaires, même après des massacres comme celui de la place Nisour.

La puissance de cette armée privée (qui dispose même désormais de son aviation) est d'autant plus inquiétante que ses dirigeants ont un autre but dans la vie que de gagner de l'argent. Tous professent un christianisme intégriste et guerrier, et voient leur rôle comme une composante d'une croisade. Peut-être y a t-il une part de marketing dans cette attitude. Ce serait encore le moins effrayant.

Ce ne serait pas la seule contradiction de Blackwater : les lois du capitalisme sont rudes et la concurrence (DynCorp, Triple Canopy) est très présente. Après avoir clamé bien fort son patriotisme et son chauvinisme, Blackwater a fini par embaucher des chiliens et des salvadoriens car ils coûtent moins cher que les états-uniens et leur famille ne risque pas de faire un procès s'ils meurent en Afghanistan.

Peu d'hommes politiques aux États-Unis se risquent à regarder de près ce que fait le Pentagone avec les mercenaires. Scahill épingle ainsi l'inactivité de Clinton au Sénat et note qu'Obama a été plus inquisiteur... mais aussi que le recours au mercenariat est tellement présent partout qu'il sera difficile au nouveau président de revenir en arrière.

Un excellent livre, donc, sur ce monde dangereux et fermé. Il a été composé à partir d'articles parus dans la presse et il y a donc souvent des redites (parfois mot pour mot) mais c'est un reproche mineur, l'important est d'avoir des informations soigneusement vérifiées et à jour sur ce milieu.


L'article seul

RFC 5378: Rights Contributors provide to the IETF Trust

Date de publication du RFC : Novembre 2008
Auteur(s) du RFC : S. Bradner (Harvard University), Jorge Contreras (WilmerHale)
Réalisé dans le cadre du groupe de travail IETF ipr
Première rédaction de cet article le 11 novembre 2008


Pendant longtemps, l'IETF a vécu avec l'illusion qu'elle était une organisation purement technique, vouée uniquement à produire les meilleures normes possibles, sans considération pour les questions « vulgaires » comme le droit. Désormais, l'IETF est rattrapée par la judiciarisation croissante de la société, surtout aux ÉUA, où se trouve la majorité des structures formelles qui comptent pour l'IETF (notamment l'ISOC, l'IETF elle-même restant informelle et non enregistrée). Avec l'enthousiasme des néophytes, une partie de l'IETF s'est donc engagée dans la voie d'un travail sur les questions de propriété intellectuelle (un terme d'ailleurs très contestable, puisque mêlant des choses aussi différentes que le droit d'auteur, les brevets et le droit des marques). Ce RFC décrit les « droits entrants », c'est-à-dire ceux dont l'IETF a besoin, et qui doivent lui être accordés par les participants aux travaux et notamment par les auteurs de RFC (la convention de Berne faisant que les auteurs ont automatiquement certains droits sur leur œuvre).

Si des notions de « propriété intellectuelle » apparaissaient déjà dans le RFC 2026 en octobre 1996, le premier RFC fournissant un cadre complet à ces questions a été le RFC 3667 en février 2004, remplacé par le RFC 3978 puis par notre RFC 5378. Le principal changement (section 10) est la séparation plus claire entre les droits « entrants » (ce que le contributeur donne à l'IETF) et les droits « sortants » (ce que l'IETF donne aux utilisateurs), décrits dans le RFC 8721.

Ce dernier RFC, écrit par un « grand ancien » de l'IETF (dont l'activité récente est essentiellement consacrée aux questions de propriété intellectuelle) et un avocat (qui, logiquement, pousse toujours l'IETF vers davantage de judiciarisation), est donc la version actuelle de la politique de l'IETF. Il détaille les droits que les contributeurs (participants au processus IETF) doivent transmettre à l'IETF trust, l'organisme (largement indépendant de l'IETF et étroitement contrôlé par l'ISOC et CNRI) qui est censé administrer la propriété intellectuelle de l'IETF (voir RFC 4748).

L'IETF trust ne peut en effet pas donner aux utilisateurs des RFC des droits qu'il n'a pas lui-même reçu. Pour pouvoir distribuer un RFC, le traduire, ou en extraire des parties, les droits automatiquement donnés par l'auteur (comme le droit de citation ou comme le fair use) ne suffisent pas. Il faut que les auteurs donnent explicitement davantage de droits.

La section 5 décrit les droits en question. 5.3 porte sur les droits donnés à l'IETF trust : droits de publication (évidemment), de traduction, d'utilisation des marques que contient le document, etc. 5.5 explique que ces droits n'impliquent pas de licence d'utilisation des technologies présentées dans le RFC (l'IETF, contrairement au W3C ou, dans certains cas, à OASIS, accepte de normaliser des technologies brevetées).

Pour que tout le monde puisse connaître ses droits, la section 6 explique le mécanisme de publication de ceux-ci par le biais d'un boilerplate, officiellement appelé legend. Ce boilerplate, un texte légal attaché à chaque RFC, ne figure pas dans notre RFC 5378. En effet, l'évolution des lois états-uniennes, les changements d'interprétation, peuvent nécessiter une évolution du texte, alors qu'un RFC n'est pas facile à changer. L'IETF trust reçoit donc un quasi-chèque en blanc pour rédiger le texte en question et le tenir à jour sur son site Web (c'est le second grand changement par rapport au RFC 3978).

La section 3 du RFC explique le raisonnement derrière les choix effectués (on peut aussi consulter la FAQ du trust). Par exemple, 3.3 explique que l'auteur doit donner le droit de faire certaines modifications (derivative works) car l'IETF doit pouvoir faire évoluer le RFC suivant l'évolution de la technologie. Elle explique aussi pourquoi cette règle peut comporter des exceptions, par exemple lorsque l'IETF re-publie sous forme de RFC une norme d'une autre organisation.

Comme le travail a été plutôt bâclé, un gros problème n'est survenu que plus tard lorsque des auteurs se sont aperçus que le nouveau texte interdisait de réutiliser du texte d'anciens RFC... La chasse aux auteurs de ces anciens RFC a donc commencé, pour les convaincre d'abandonner leurs droits (voir l'article IETF Shoots Itself in the Foot).


Téléchargez le RFC 5378


L'article seul

RFC 5377: Advice to the Trustees of the IETF Trust on Rights to be Granted in IETF Documents

Date de publication du RFC : Novembre 2008
Auteur(s) du RFC : J. Halpern (Self)
Pour information
Réalisé dans le cadre du groupe de travail IETF ipr
Première rédaction de cet article le 11 novembre 2008


Une fois les droits de publication, et de modification, offerts par le(s) auteur(s) d'un RFC à l'IETF trust, quels droits ce dernier va t-il transmettre aux lecteurs d'un RFC ? Le RFC 5378 spécifiait les droits « entrants » à l'IETF trust, et notre RFC 5377 spécifie les droits sortants : que puis-je faire avec un RFC ? Ai-je le droit de le lire ? De le redistribuer ? De le traduire ? (Il a depuis été remplacé par le RFC 8721.)

Pendant longtemps, l'IETF avait été réputée plus généreuse que les autres SDO car ses RFC étaient distribués librement (alors que l'ISO ou l'ITU faisaient payer une somme considérable, qui n'était même pas justifiée par les frais de distribution puisque ces dinosaures interdisaient la reproduction et la redistribution). Mais les temps ont changé : d'autres SDO ont suivi ce chemin, à commencer par le W3C, certaines organisations traditionnelles se sont ouvertes, comme l'ITU. L'IETF est désormais dans la moyenne, plus ouverte que l'ISO mais beaucoup moins que le W3C ou OASIS.

Compte-tenu de cette tendance à l'ouverture, et du développement du logiciel libre, accompagné d'un mouvement en faveur de formats ouverts, l'IETF devait donc libéraliser sa politique de licence, qui était spécifiée dans le RFC 3978. Celle-ci spécifiait notamment que les RFC étaient distribués et redistribués librement mais que toute modification était interdite. Ce problème n'était pas purement théorique : du texte issu de RFC se retrouve souvent verbatim dans des documentations de logiciel ou dans des manuels en ligne comme la page getaddrinfo (RFC 3493) sur beaucoup d'Unix. Le texte du RFC n'étant pas modifiable, ce logiciel devenait non libre. Pire, les RFC comportent souvent du code (définitions des MIB, exemples de code, schémas XML, implémentation du protocole, etc) et celui-ci n'était pas non plus modifiable et ne pouvait donc pas être inséré dans un logiciel libre !

Il était donc nécessaire de libéraliser. Mais une partie de la « vieille garde » de l'IETF s'est opposé à toute évolution et ce RFC 5377 ne représente donc finalement qu'une libéralisation très modérée. La principale innovation par rapport au RFC 3978 est la séparation du RFC entre code et texte, avec des règles différentes, plus ouvertes pour le code.

La section 1 du RFC rappelle un point important : c'est désormais l'IETF trust qui décide. Le RFC 5377, publié par l'IETF, n'est qu'indicatif et ne fixe que des grands principes. Le texte exact de la licence des RFC est écrit par l'IETF trust (http://trustee.ietf.org/license-info/ et il existe aussi une FAQ sur ces textes.) La section 2 revient d'ailleurs sur les raisons de ce choix (pouvoir s'adapter aux changements légaux aux ÉUA, pays de l'IETF trust et de l'ISOC).

On pourra trouver ce texte standard, ce boilerplate, sur le site du Trust.

La section 2 du RFC décrit les buts que suit l'IETF en publiant des RFC (cf. RFC 3935). Clairement, l'élaboration d'une licence doit se faire en gardant ces buts à l'esprit : faire fonctionner l'Internet le mieux possible.

La section 3 explique l'articulation de ce RFC avec le RFC 5378 : les droits sortants (ceux que l'IETF trust accorde aux utilisateurs) doivent être inférieurs ou égaux aux droits entrants (ceux que l'auteur a accordé à l'IETF trust). Autrement dit, l'IETF ne peut pas donner de droits qu'elle n'a pas. Si l'auteur d'un RFC interdit toute modification à son texte, le RFC publié ne permettra pas de modifications (et ne pourra d'ailleurs pas être publié sur le chemin des normes).

La section 4 s'attaque aux droits que l'IETF trust devrait donner aux utilisateurs :

  • Droit de publier et de republier (section 4.1), une très ancienne politique de l'IETF,
  • Droit (évidemment) d'implémenter la technique décrite dans le RFC (section 4.3). C'est ici qu'apparait la distinction entre code et texte. Par un mécanisme non spécifié dans le RFC (cela a été choisi par la suite comme une liste publiée par l'IETF trust), le code sera marqué spécialement et l'implémenteur aura davantage de droits sur le code, notamment le droit de modification. Cela ne résout pas, et de loin, tous les problèmes. Par exemple, cela ne permet pas de modifier du texte d'un RFC qui est inclus dans la documentation d'un logiciel.
  • Droit de modifier le texte ? Non, ce droit est exclu par la section 4.4. La montagne a donc accouché d'une souris : si ce RFC représente une libéralisation, elle reste très modérée et limitée au code.

Les discussions sur le groupe de travail IPR ont été longues et passionnées. Elles opposaient surtout la vieille garde IETF, attachée à ne rien changer et effrayée par les changements survenus avec le développement du logiciel libre, mais aussi du Web (avec ses mashups, son Wikipédia et autres preuves de l'importance du droit de modification) aux partisans du logiciel libre comme Simon Joseffson ou Lawrence Rosen. Notons que Joseffson a écrit quatre RFC, comportant souvent du code. Je cite ce point car un des arguments les plus vicieux d'un débat qui en a compté beaucoup était que les partisans d'une libéralisation n'avaient jamais écrit de RFC et donc devaient se taire !

Pourquoi donc cet acharnement à refuser les modifications ? La raison la plus souvent invoquée était le désir d'éviter l'apparition de « RFC non officiels », incompatibles avec les « vrais », qui pourraient semer la confusion. Ainsi, un « méchant » pourrait créer un document mettant à jour le RFC 5321 en remplaçant EHLO par GDAY. Outre que cette « attaque » reste très théorique, plusieurs participants ont fait remarquer que les nouvelles règles ne l'empêchent pas et que la seule protection contre ce genre de problèmes serait dans le droit des marques, par exemple en faisant déposer la marque RFC pour empêcher le document du méchant de se présenter comme RFC. Or, ce point n'a jamais été considéré...

Notons enfin que beaucoup de participants à l'IETF n'ont pas du tout suivi ce qui se passait dans ce petit groupe, en général par manque d'intérêt pour les questions politiques et juridiques.


Téléchargez le RFC 5377


L'article seul

Spectacle Le Mur

Première rédaction de cet article le 10 novembre 2008


En août 2008, à Morlaix, lors du Festival des Arts de la Rue, j'ai assisté au spectacle « Le Mur » de la compagnie 1 Watt.

C'est une extraordinaire spectacle, délirant, sur la construction d'un mur par deux voisins qui ne savent pas pourquoi ils le construisent. Les mouvements des acteurs sont fabuleux (par exemple le balayage du sol avec le dos).

La question reste ouverte : « Qu'est-ce qui vous anime ? », demandent-ils plusieurs fois aux spectacteurs ? « Le sexe ? Le pouvoir ? Le poulet ? »


L'article seul

Un portage d'un site Web Mason vers Apache 2

Première rédaction de cet article le 10 novembre 2008


J'ai passé une bonne partie de la journée à porter un site Web Mason vers une nouvelle machine. Comme la première avait Apache 1 et mod_perl 1 et que la seconde machine avait les versions 2, cela n'a pas été tout seul.

J'utilisais pas mal Mason à un époque. C'est un environnement de développement en Perl pour faire des sites Web dynamiques. Il est utilisé notamment pour amazon.com. Il s'appuie sur l'intégration de Perl dans Apache, mod_perl.

On trouve pas mal de récits d'expérience d'une telle migration sur le Web. Curieusement, tout le monde n'a pas eu les mêmes bogues et ce n'est pas la même solution qui marche pour tous. Voici donc les deux points qui ont été les plus bloquants pour moi.

J'avais un fichier index dans chaque répertoire et une directive DirectoryIndex index dans la configuration d'Apache. En Apache 1, cela marchait mais, en Apache 2, la directive DirectoryIndex semble complètement ignorée dans un répertoire géré par Mason. Résultat, lorsque le client HTTP demandait un URL qui se terminait par un répertoire, pas un fichier, le serveur renvoyait un code 404 et notait dans son journal [error] [client 192.134.4.69] Attempt to serve directory: /var/www/www.generic-nic.net/dyn/whois/.

La solution qui a marché pour moi est de chercher le fichier index via une règle de réécriture Apache :

RewriteEngine on
RewriteRule ^(.*)/$ $1/index

Cette règle dit que si l'URL se termine par /, on ajoute index à la fin. Ce n'est rien, mais j'ai dû essayer pas mal de fausses solutions avant, souvent très complexes.

Le second problème concernait l'appel d'une méthode dans les fichiers Mason. Pour donner un titre aux pages, le site utilisait une technique Mason très classique :


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>        
<title>Generic NIC: <& SELF:title &></title>

<& SELF:title &> signifiait qu'on appelle la méthode title. Celle-ci est définie dans chaque page :


<%method title>Technical details on the domain information</%method>

Mais cette technique ne marche plus avec mod_perl 2, la méthode n'est plus dans l'espace SELF mais dans REQUEST. Il faut donc réécrire le fichier qui contient l'en-tête HTML ainsi :


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>        
<title>Generic NIC: <& REQUEST:title &></title>


L'article seul

Pourquoi les RFC sont-ils encore en texte brut ?

Première rédaction de cet article le 7 novembre 2008


Les RFC, documents qui incluent les normes de l'Internet, sont publiés en texte brut, sans aucune fioriture ou marquage. Pourquoi un tel conservatisme ?

Le RFC 2223, le RFC qui normalisait les RFC (il a été remplacé depuis par le RFC 7322), précise que le seul format faisant autorité est la version en texte seul, encodée en ASCII. Malgré de nombreuses tentatives, il n'a pas encore été possible de faire évoluer cette règle. Il y a des bonnes et des mauvaises raisons à cela. (Depuis la parution de cet article, le texte brut est en voie d'abandon, cf. le RFC 7990.)

Le premier RFC, le RFC 1, a été publié en avril 1969. À l'époque, même le jeu de caractères ASCII était une nouveauté. Bien sûr, ce RFC n'a plus d'utilité de nos jours. Mais plusieurs RFC très anciens restent des normes en vigueur. Même si on écarte le RFC 20 qui normalise le texte en ASCII, le plus ancien RFC encore en service semble être le RFC 768, qui normalise UDP, et qui date d'août 1980, il y a vingt-huit ans.

Cela nous donne la première explication : la permanence. Une norme, surtout celles utilisées par un réseau aussi essentiel que l'Internet, doit pouvoir être encore lisible des années après, longtemps après que les tendances en matière de format aient changé. Si le RFC 768 avait été écrit avec le traitement de textes à la mode chez les managers de l'époque, il ne serait plus lisible aujourd'hui. Le format « texte brut » (RFC 3676) est le seul qui aie traversé cette époque.

Mais il y a d'autres critères : l'accessibilité en est un. Tout le monde, quelle que soit la plate-forme informatique utilisée, peut lire et écrire du texte brut. Cela garantit la participation maximale. Si, au lieu de distribuer les RFC en texte brut, on utilisait le format privé d'un éditeur de logiciels états-unien particulier (au hasard, Microsoft Word puisque beaucoup de blaireaux envoient systématiquement leurs documents dans ce format, sans s'être demandé si leurs destinataires pouvaient le lire), les RFC cesseraient d'être universels. Le texte brut est le PGCD des formats.

Il présente également un intérêt pour le programmeur : écrire un programme qui cherche dans les RFC ne nécessite pas de lire des spécifications compliquées d'abord (comme c'est le cas avec l'ultra-difficile PDF, pour lequel il existe très peu de mises en œuvre distinctes). Un simple grep (ou outil équivalent) suffit.

Mais le texte brut en ASCII n'a t-il pas également des limites ? Bien sûr. Il rend difficile de représenter les noms des auteurs, s'ils sont chinois, allemands ou arabes (par exemple Martin Dürst qui, dans le RFC 3987 doit expliquer comment écrire proprement son nom ou Bill de hÓra dans le RFC 5023 ce dont son co-auteur s'est plaint). Il rend pénible les exemples Unicode comme dans les RFC 3490 ou RFC 5198. Il ne permet pas de représenter les formules mathématiques, même relativement simples, comme celles des RFC 5905 ou RFC 5348. Il ne permet pas d'inclure des images autres que l'art ASCII encore que ce point soit discutable : la plupart des images contenues dans les RFC sont des diagrammes assez formels, qui seraient mieux représentés dans un langage spécialisé comme Cosmogol. L'ASCII ne permet même pas de mettre en évidence un mot en l'indiquant en gras ; pire, il semble que le RFC editor refuse les conventions ASCII courantes qui consistent à entourer le mot de * ou de _. Ainsi, distinguer une variable d'un litéral dans une spécification est souvent problématique (alors qu'un format comme Docbook le fait trivialement avec l'élément <replaceable>). Avec l'ASCII pur, il faut deviner que, lorsqu'une norme parle de http://example.com/, que http est un litéral et example.com une variable, juste un exemple.

Face à ces limites, les tentatives de faire évoluer la règle du RFC 2223 n'ont pas manquées. Ainsi, le RFC 7749 propose un format XML. XML est une norme ouverte, présente depuis suffisamment d'années pour qu'on puisse avoir confiance dans sa stabilité. Si les outils d'édition sont un peu rudes, ce n'est normalement pas un problème pour les auteurs de RFC, qui sont tous des techniciens pointus. Hélas, ce format n'a jamais été adopté officiellement, en partie à cause de l'opposition virulente de Microsoft, en partie par simple conservatisme. Le RFC editor (une organisation séparée de l'IETF, sur laquelle l'IETF n'a pas de pouvoir) est en effet très conservateur. C'est dans son travail (qui est de rendre les normes accessibles à tous pendant très longtemps) mais la déformation professionnelle devient parfois excessive. (Depuis, la sortie du RFC 7990 a marqué le début de la fin pour le texte brut.)

À la rigueur, serait-il possible d'autoriser au moins le jeu de caractères Unicode (après tout, « texte brut » n'implique pas forcément ASCII) ? C'est ce qui a été proposé de nombreuses fois, par exemple dans l'Internet-Draft draft-hoffman-utf8-rfcs, actuellement en cours de discussion. Mais le RFC editor continue à s'y opposer. (Les partisans d'Unicode ont finalement eu gain de cause avec le RFC 7997.)


L'article seul

Obsolescence des ordinateurs

Première rédaction de cet article le 6 novembre 2008


Comme la question de l'« obsolescence programmée » des ordinateurs est souvent mentionnée lors de discussions sur le développement durable, j'ai fait deux petites expériences avec des « vieux » ordinateurs, pour voir s'ils pouvaient encore servir pour le travail quotidien.

J'ai d'abord sorti de mon placard un vieux portable Compaq Armada 1570. Je l'avais acquis en 1999 (d'occasion : il a en fait quelques années de plus). Il a un processeur Pentium 200 Mhz, 32 Mo de mémoire et (quand même) plus d'un giga-octet de disque dur. J'ai utilisé le logiciel qu'il avait à l'époque, Debian et les paquetages de ce temps.

Ce qui marche très bien sur cet appareil :

  • un SGBD relationnel complet, PostgreSQL (bien plus riche que, par exemple, MySQL).
  • des langages de programmation dits « de script », pourtant généralement considérés comme lents et gourmands, comme Python ou Perl.
  • L'éditeur emacs, longtemps réputé lent et lourd (Eight Megabytes And Constantly Swapping, ce qui fait rire aujourd'hui quand on voit la taille qu'occupent les traitements de texte modernes).
  • le formateur LaTeX, souvent présenté comme gourmand (mais infiniment moins qu'OpenOffice). On peut donc écrire des textes sophistiqués.

Ce qui nécessite des adaptations :

  • le Web est utilisable via le navigateur lynx. Le seul navigateur graphique qui marche de manière acceptable est Dillo. Konqueror tourne mais swappe (manque de mémoire).
  • le courrier est utilisable via le logiciel client mutt.

Ce que je n'ai même pas essayé :

  • l'audio.
  • la vidéo.

Notons que la matériel fonctionne aussi bien qu'au premier jour, sauf la batterie, qui ne se charge plus.

Souvent, une certaine adaptation de l'utilisateur est nécessaire. Ainsi, l'éditeur Emacs et le SGBD PostgreSQL tournent bien tous les deux, mais séparément. Si on passe de l'un à l'autre très vite, le swapping devient insupportable. Il faut donc adapter son style de travail, taper plus longtemps dans l'éditeur avant de tester ses programmes, etc.

Une autre expérience a porté sur un portable bien plus récent, un Dell Inspiron 7500, acheté (d'occasion) en juillet 2005. 256 Mo de mémoire, un Pentium de 400 Mhz. Contrairement au premier, il a été testé avec un système d'exploitation actuel, le dernier Ubuntu.

En plus des applications qui marchent bien sur le plus vieux des PC, il peut en outre exécuter Firefox, OpenOffice et bien d'autres applications modernes. La taille des applications modernes fait qu'il n'est pas plus rapide que son ancêtre. Mais il peut quand même faire tourner les services actuels. Il reste trop lent pour la vidéo (Youtube défile à deux images par seconde) mais ce n'est pas un problème pour la bureautique.

La conclusion est mixte : on peut travailler avec ces ordinateurs, bien sûr. Des millions de gens l'ont fait et s'en trouvaient très bien. Mais cela peut nécessiter des logiciels différents de ceux d'aujourd'hui (trop gaspilleurs) et des comportements différents de la part de l'utilisateur (ce qui est, après tout, souvent le cas en matière de développement durable).


L'article seul

RFC 2047: MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text

Date de publication du RFC : Novembre 1996
Auteur(s) du RFC : Keith Moore (University of Tennessee)
Chemin des normes
Première rédaction de cet article le 2 novembre 2008


La série de RFC sur MIME, qui a introduit les caractères composés (et les écritures non-latines), ainsi que les objets multimédia, dans le monde du courrier électronique, comprend, entre autres, ce RFC qui normalise une méthode pour mettre des caractères non-ASCII dans les en-têtes du courrier, ces métadonnées situées avant le corps du message et structurées en nom: valeur.

Normalement, le courrier, tel qu'il était normalisé par le RFC 822 (aujourd'hui RFC 5322), ne permettait que le jeu de caractères ASCII dans les en-têtes. C'est ainsi qu'il fallait écrire :


From: Stephane Bortzmeyer <bortzmeyer@sources.org>
Subject: Du cafe bien fort !

au lieu de la forme correcte en français :


From: Stéphane Bortzmeyer <bortzmeyer@sources.org>
Subject: Du café bien fort !

Notre RFC 2047 vise tout simplement à fournir une solution à ce problème, en encodant les caractères non-ASCII, en Quoted-Printable ou en Base64. Les en-têtes ci-dessus apparaitront donc sur le réseau comme :


From: =?iso-8859-1?q?St=E9phane?= Bortzmeyer <bortzmeyer@sources.org>
Subject: Du =?iso-8859-1?q?caf=E9?= bien fort !

Ainsi, le message pourra passer à travers toute l'infrastructure du courrier qui n'accepte que l'ASCII. Ce sera au MUA de les remettre sous une forme lisible (voir par exemple mon article Décoder les en-têtes du courrier électronique).

L'approche de notre RFC est donc conservatrice : on ne demande pas à tous les logiciels sur le trajet de connaître MIME, autrement ce dernier n'aurait jamais été déployé. (MIME n'utilise même pas, par prudence, certaines fonctions du RFC 822 qui auraient pu aider mais qui sont trop souvent boguées, cf. section 1.) Aujourd'hui où l'infrastructure du courrier est très différente, une méthode plus radicale pourrait être réaliste et c'est l'approche du bien plus récent RFC 6532.

La section 2 du RFC donne la grammaire exacte : un terme encodé est précédé de =? suivi de l'encodage des caractères. (Pour le corps du message, tel que normalisé dans le RFC 2045, l'encodage est indiqué dans un en-tête, Content-Type. Pour les en-têtes eux-mêmes, il a fallu trouver une autre solution.) Puis on trouve le surencodage appliqué par MIME, Q pour Quoted-Printable et B pour Base64 puis le terme lui-même, ainsi encodé. Le tout est terminé par un ?=. Voici le résultat, produit par un programme Python avec le module email :


% python
>>> from email.header import Header
>>> h = Header('niçoise', 'iso-8859-1')
>>> print h
=?iso-8859-1?q?ni=E7oise?=

Notons que l'encodage utilisé est appelé charset (jeu de caractères) par MIME, ce qui n'est pas vraiment le terme correct (« utf-8 » est un encodage, le jeu de caractères est Unicode). La section 3 normalise ce paramètre, pour lequel les valeurs standard de MIME sont utilisées.

La section 4 décrit en détail les surencodages possibles, Quoted-Printable et Base64. Le premier (RFC 2045) convient mieux lorsque le texte comprend des caractères latins, avec quelques caractèrs composés. Le second (RFC 4648) est préférable si le texte est composé de caractères non-latins. La section 4.2 détaille quelques spécificités de Quoted-Printable et notamment l'utilisation du _ à la place de l'espace comme dans :


% python
>>> from email.header import Header
>>> h = Header("réveillés dans une Citroën niçoise", "ISO-8859-1")
>>> print h
=?iso-8859-1?q?r=E9veill=E9s_dans_une_Citro=EBn_ni=E7oise?=

Pour le même genre de tâches, les programmeurs Perl peuvent utiliser Encode::MIME::Header.


Téléchargez le RFC 2047


L'article seul

Configurer un serveur relais pour accéder à des sites Web filtrés

Première rédaction de cet article le 1 novembre 2008
Dernière mise à jour le 3 novembre 2008


Il arrive que certains sites Web soient filtrés et interdits d'accès, soit par l'État (cas de Dubaï), soit par une entreprise qui ne veut pas laisser ses employés aller sur certains sites. Une technique courante pour contourner ces filtres est le relais HTTP.

Avant de voir comment en configurer un, un sérieux avertissement. Les gens qui filtrent n'aiment pas qu'on contourne leurs filtres. Si le filtrage est le fait de l'État, le contourner peut être illégal et vous valoir de gros ennuis, notamment dans des pays comme la Chine ou la Tunisie. Si le filtrage est le fait de votre patron, celui-ci a pu indiquer dans le réglement intérieur ou bien à un endroit similaire que les tentatives de contournement étaient également interdites et pouvaient vous valoir un licenciement. Donc, soyez prévenu...

Il existe plein de façons de configurer un relais HTTP et plein de logiciels pour cela. Je ne vais pas me lancer dans la comparaison détaillée de toutes ces méthodes, simplement indiquer comment je l'ai fait pour moi.

Il faut d'abord une machine, le relais, allumée en permanence et connectée à Internet, proxy.bortzmeyer.org dans les exemples qui suivent. Aujourd'hui, de telles machines se trouvent pour moins de dix € par mois.

J'ai choisi le logiciel Apache, qui était déjà installé sur la machine. Il faut qu'il inclue l'option de relayage (proxy) ce qui, sur ma Gentoo, est le cas si, dans /etc/make.conf, on a dans la définition de APACHE2_MODULES les modules proxy proxy_ajp proxy_balancer proxy_connect proxy_http (avant de compiler Apache, bien sûr).

Il faut ensuite configurer Apache en relais. Pour simplifier, je mets les directives nécessaires dans un fichier de Virtual Host, ici /etc/apache2/vhosts.d/proxy.conf :


<IfDefine PROXY>
Listen [::1]:8080
<VirtualHost [::1]:8080>
ProxyRequests On
<Proxy *> # Do not delete!
Order Deny,Allow
Deny from all
Allow from ::1
</Proxy>
</VirtualHost>
</IfDefine>

Ici, on dit à Apache, si la variable PROXY est définie (sur une Gentoo, c'est dans /etc/conf.d/apache2), il doit écouter sur le port 8080 et autoriser le relais.

Attention, les lignes qui suivent (celles qui commencent par <Proxy *>) restreignent l'usage du relais à la machine locale et elles sont indispensables sinon votre relais est un relais ouvert (n'importe qui peut l'utiliser) et les méchants détectent en quelques heures un relais ouvert - c'est ce qui m'est arrivé - et l'exploitent pour cacher leurs traces.

Rechargez Apache et, pour tester si tout va bien, depuis la machine Apache, par exemple avec curl :

% curl -v --proxy localhost:80 http://www.ras.eu.org/ > /dev/null
...
< HTTP/1.1 200 OK
< Date: Sat, 01 Nov 2008 12:36:03 GMT
< Server: Apache
...

Ici, tout s'est bien passé. Depuis une autre machine, testez que l'accès est refusé :

% curl -v --proxy proxy.bortzmeyer.org:80 http://www.ras.eu.org/ > /dev/null 
...
< HTTP/1.1 403 Forbidden

(On a testé le port 80 car, précaution supplémentaire, le Virtual Host Apache qui fait le relais n'écoute que sur l'adresse locale ::1.) La documentation d'Apache insiste bien sur la nécessité de ne pas ouvrir complètement le relais (Controlling access to your proxy).

Mais, si le relais n'est accessible que depuis la machine relais elle-même, comment l'utiliser depuis ma machine située derrière le filtre ? Comme on souhaite en plus que le fait que l'accès au relais soit discret (rappelez vous les avertissements au début), on va chiffrer la communication. L'idéal serait que les clients HTTP puissent accéder au relais avec TLS. Mais, apparemment, ni Firefox, ni Opera, ni wget ne savent le faire. Donc, on va créer un tunnel ssh depuis la machine de l'utilisateur, vers le relais :

% ssh -f -N -v -L localhost:6666:\[::1\]:8080 proxy.bortzmeyer.org

(si on trouve cette commande trop longue à taper à chaque fois, on peut utiliser un alias, ou bien la mettre automatiquement en route à la connexion, par exemple dans le fichier ~/.xsession ; on peut aussi utiliser autossh). Cette commande fait suivre tout message envoyé au port 6666 de la machine locale vers le relais, puis au port 8080 de ce dernier (notez l'utilisation de la syntaxe du RFC 2732, [::1]:8080, pour distinguer l'adresse IP du numéro de port). -f fait s'exécuter la commande de manière non-interactive.

Il ne reste plus alors qu'à dire au navigateur Web d'utiliser http://localhost:6666/ comme relais. Ici, avec curl et la variable d'environnement http_proxy :

% export http_proxy=http://localhost:6666/
% curl -v http://www.ras.eu.org/ > /dev/null

Avec Firefox, il est sans doute préférable d'utiliser l'extension FoxyProxy, qui permet de jongler facilement avec les différentes options pour les relais.

Merci à Pascal Courtois, Thomas Quinot et Bertrand Petit pour leur aide.

Il existe une alternative à la solution « tunnel SSH + logiciel relais HTTP » présentée ici (avec Apache comme logiciel relais). Cette solution m'a été proposée par Samuel Tardieu, Ollivier Robert, Yannick Palanque ou Eon Knight : elle consiste en un tunnel SSH plus le protocole Socks pour éviter d'installer un relais explicite derrière le tunnel. On lance le tunnel SSH avec l'option -D pour relayer le Socks :

% ssh -f -N -v -D localhost:6667 proxy.bortzmeyer.org

et on peut alors dire aux navigateurs Web d'utiliser le relais Socks localhost:6667. Par exemple, avec curl :

curl -v --socks5 localhost:6667 http://www.ras.eu.org/

Mais attention : tous les logiciels ne parlent pas forcément le Socks. curl ou Firefox le font, mais ni wget, ni lynx. Même chose pour les bibliothèques d'accès au Web comme httplib qui nécessitent du code supplémentaire pour utiliser Socks :

proxy = socks.socksocket()
proxy.setproxy(socks.PROXY_TYPE_SOCKS5, 'localhost', 6667)
conn = httplib.HTTPConnection("www.ras.eu.org", 80)
conn.sock = proxy

On peut certes utiliser une bibliothèque comme tsocks pour « socksifier » les applications non-Socks mais ma solution avec Apache me paraît plus claire.

Au fait, petit avertissement à propos de Socks et Firefox (merci à Yannick Palanque). Par défaut, Firefox fait la résolution DNS en local (cf. réglage network.proxy.socks_remote_dns). Il faut y penser si on veut rester discret en utilisant un tunnel SSH.


L'article seul

KCM, gérer des clés cryptographiques sans autorité de certification

Première rédaction de cet article le 28 octobre 2008


Dans tout système utilisant la cryptographie, la gestion des clés est la principale plaie. La cryptographie garantit qu'un tiers ne pourra pas modifier, ni même écouter la communication mais comment savoir si l'interlocuteur auquel on parle n'est pas justement celui dont on veut se protéger ? Dans le monde physique, on reconnait sa voix et son visage, mais une clé cryptographique n'a pas de voix. Le mécanisme KCM (Key Continuity Management) s'attaque à ce problème.

Prenons pour simplifier le cas du courrier électronique. Pour authentifier un message et pour s'assurer de sa confidentialité, on le chiffre avec la clé publique du destinataire. Mais comment savoir si c'est la bonne ? Les deux normes les plus répandues de chiffrement du courrier, PGP (RFC 3156 et RFC 4880) ou S/MIME (RFC 3850) utilisent deux approches opposées.

PGP utilise des clés qui sont signées par qui le veut, souvent à l'occasion de sessions de signature. Si une clé a été signée par quelqu'un à qui on fait confiance, on l'utilise. Sinon, on prend un risque, celui d'utiliser une clé qui est peut-être celle d'un imposteur. C'est donc à l'utilisateur de prendre des décisions de sécurité (« La clé de Jeanne est signée par Paul, et celle de Paul par moi. Mais Paul signe t-il après des vérifications sérieuses ? ») Le mécanisme est simple, ne nécessite pas d'autorité de certification centrale et marche bien... au sein de petites communautés solides. Il n'a jamais fonctionné pour l'ensemble de l'Internet.

S/MIME, au contraire, repose sur X.509 et dépend donc d'autorités de certification qui signent les messages. L'utilisateur n'a plus de décisions à prendre. Mais ces autorités de certification sont chères, complexes et il n'est pas évident qu'elles fournissent effectivement une bonne sécurité.

En se tournant vers d'autres protocoles, on peut trouver d'autres idées. Ainsi, SSH (RFC 4251) utilise par défaut un mécanisme dit TOFU pour « Trust On First Use ». Les clés des machines auxquelles on se connecte ne sont quasiment jamais vérifiées lors de la première connexion mais elles sont stockées dans le fichier ~/.ssh/known_hosts et, si elles changent par la suite, SSH interrompt la connexion. Si on a la chance que le méchant ne soit pas en train de mener un détournement du DNS ou de BGP juste au moment de la première connexion, on peut être tranquille pour la suite. (Le terme plus formel pour TODU est « leap of faith » qu'on trouve souvent dans la littérature sur la sécurité des réseaux. On parle aussi du mécanisme « bébé-oie » par allusion au fait que l'oie sortie de l'œuf considère le premier être vu comme sa mère) Ce mécanisme de TOFU a des limites (et il existe des projets pour l'améliorer comme Perspectives) mais marche « suffisamment bien » pour l'instant.

Peut-on l'étendre au courrier ? Oui, répondent Simson Garfinkel et Robert Miller dans leur article Johnny 2: A User Test of Key Continuity Management with S/MIME and Outlook Express. L'idée de base est simple : à chaque configuration d'une nouvelle identité de courrier, le logiciel crée automatiquement une nouvelle paire de clés et envoie la clé publique avec le message. Au premier message reçu de cette adresse, il faudra décider si on l'accepte ou pas mais, ensuite, la clé est conservée et, si elle change, cela indique probablement qu'un usurpateur tente d'utiliser cette adresse, sans avoir la bonne clé.

Le mécanisme a été testé lors d'une experiénce nommé « Johnny 2 » (ainsi nommée en référence au célèbre article « Why can't Johnny encrypt? » qui concluait que les problèmes d'utilisabilité étaient au cœur des difficultés de déploiement de la cryptographie). Le résultat est très positif, montrant que les utilisateurs se débrouillent bien avec les différents cas de figure (premier message d'un correspondant, message suivant, message d'un usurpateur).


L'article seul

Exposé DNSwitness à la réunion RIPE de Dubaï

Première rédaction de cet article le 28 octobre 2008


Le 28 octobre, à Dubaï, j'ai eu le plaisir de faire un exposé lors de RIPE 57, l'une des réunions RIPE, réunions rassemblant les acteurs de l'Internet européen (comme vous pouvez le voir, l'Europe du RIPE s'étend assez loin...) L'exposé portait sur DNSwitness, le logiciel de mesures des données DNS que j'ai développé à l'AFNIC. Cet exposé a été fait au sein du groupe de travail DNS.

Voici les documents produits à cette occasion :


L'article seul

Le budget de l'IETF et le coût d'un RFC

Première rédaction de cet article le 27 octobre 2008


Combien coûte le travail de normalisation ? Ce travail implique en général plusieurs acteurs, donc les coûts sont difficiles à calculer. Mais certaines SDO sont suffisamment ouvertes pour publier un budget détaillé, donc, on peut savoir, par exemple, combien chaque RFC a coûté à l'IETF.

Les RFC sont écrits par des volontaires de diverses sociétés et organisations. Attention, j'ai écrit « volontaire », pas « bénévole ». La plupart sont en effet payés par leur société pour ce travail, et cela n'apparait pas dans le budget. Ce qui y apparait, ce sont les dépenses directes de l'IETF, comme les versements effectués au RFC editor, une fonction séparée de l'IETF, actuellement exercée par l'ISI.

Quel est le budget de l'IETF ? Il est surveillé par l'IAOC, un organisme créé par le RFC 4071. L'IAOC publie toutes les informations utiles sur son site Web. On y trouve par exemple le budget 2007 ou celui (pas encore exécuté) de 2008.

Les montants ne sont pas négligeables pour une organisation fondée sur le volontariat. Pour 2007, on trouve pas moins de 744 500 dollars pour le RFC editor.

Comme il y a eu 321 RFC publiés en 2007 (cf. http://www.rfc-editor.org/rfc.html), cela ferait 2 300 dollars par RFC, uniquement pour le travail du RFC editor, sans compter celui des auteurs, relecteurs, etc...


L'article seul

Censure à Dubaï

Première rédaction de cet article le 27 octobre 2008


Plusieurs pays filtrent le contenu diffusé sur le Web et ne laissent pas leurs citoyens y accéder. On connait le cas de la Chine, de la Tunisie, de l'Arabie Saoudite. Mais cela arrive aussi dans des pays moins souvent cités comme les Émirats arabes unis.

Voici, depuis Dubaï, ce qu'on obtient si on essaie d'accéder à un site interdit : uae-web-blocked.jpg

La redirection du port 80 est faite automatiquement, donc on ne peut pas la contourner sur sa machine locale (on peut bien sûr utiliser un relais à soi, accessible en HTTPS quelque part ; par contre, Tor ne marche pas.)

Notons que tout n'est pas si noir aux Émirats : au moins, on est prévenus franchement (il semble qu'en Tunisie, le filtre est hypocrite : il ne répond pas, faisant ainsi croire à une erreur réseau.).

(Tiens, c'est amusant, Bruce Schneier blogue sur le même sujet une semaine après.)


L'article seul

Portabilité des données d'un site Web ?

Première rédaction de cet article le 25 octobre 2008


Aujourd'hui, un grand nombre de sites Web sont techniquement gérés par un CMS ou un moteur de blog. Cela présente bien des avantages, notamment la séparation du contenu (placé dans la base de données) et de la présentation. Mais cela pose le problème de la portabilité des données. Si j'ai passé trois ans à remplir mon blog avec Wordpress, puis-je passer sur Dotclear ? Si j'ai tout mis dans SPIP, que se passe t-il si je migre vers un site à base de Drupal ?

Avec les premiers sites Web, faits en HTML (à la main ou via un logiciel d'édition HTML comme nvu), c'était simple, HTML étant un format standard et ouvert, la portabilité des pages était automatiquement assuré. Mais HTML souffre d'autres inconvénients, notamment parce que la structure de la page (titre, menu, case pour le moteur de recherche, etc) et son contenu (spécifique à chaque page) sont mélangés. Si on veut mettre à gauche le menu qui était à droite, on n'a pas de solution simple, il faut reprendre toutes les pages. Donc, il est logique que des outils comme les CMS ou les moteurs de blog se soient imposés. Mais, à l'occasion, on a perdu la portabilité. Désormais, changer de logiciel devient difficile. Dans tous les cas, les gabarits sont perdus, parfois les informations sur les auteurs (qui peut écrire, qui peut modifier) mais peut-on au moins récupérer le contenu, ces articles qu'on a passé tant de temps à taper ? A priori, cela ne marchera pas : le schéma de la base de données est différent et le langage dans lequel sont décrites les données est également différent.

Cela a mené à la prise de conscience du problème de la portabilité des données, sous-ensemble du problème général de la préservation des ressources numériques. À l'heure actuelle, les utilisateurs sont, trop souvent, prisonniers d'un logiciel particulier car en changer signifierait la perte d'un contenu significatif.

Commençons par les langages. La plupart des CMS ou moteurs de blog n'utilisent pas du tout HTML mais un langage de formatage spécifique. Quels langages existent ? Textile, par exemple (Textpattern l'utilise), le langage de MediaWiki, rendu populaire par Wikipédia, des nouveaux formats normalisés comme Atom (RFC 4287), etc. Il n'y a rien qu'on puisse appeler « standard » dans ce domaine. Rien que dans le monde du wiki, il existe de nombreux langages différents. Heureusement, ces langages sont en général plutôt simples, ce qui facilite l'écriture de programmes de conversion.

Ensuite, il y a la structure des données dans la base, différente d'un logiciel à l'autre, souvent mal documentée et toujours changeante.

Y a t-il des programmes tout faits ? Oui, souvent, dès que le format qu'on veut importer est utilisé par un logiciel populaire. Par exemple, Wordpress dispose d'importeurs pour beaucoup de ses concurrents. On peut les trouver sous l'onglet Import de l'interface d'administration. On peut lire de nombreux récits d'importation de données... plus ou moins réussies. Wordpress lui-même dit prudemment que ces importeurs permettent de récupérer « la plupart » des informations associées aux articles de l'ancien blog.

En sens inverse, l'importance de Wordpress fait que beaucoup de moteurs de blog ont un moyen d'importer du Wordpress. Par exemple, pour Textpattern, on peut voir http://forum.textpattern.com/viewtopic.php?id=23243 qui explique que Click on administration->import, enter the database-information for the wordpress installation and click button. That will import the content.. De tels programmes d'importation ad hoc doivent être écrits pour chaque couple de CMS entre lesquels on veut échanger des données et il n'est donc pas étonnant qu'ils soient fragiles et ne respectent pas toujours toutes les données.

Et cela laisse ouvert le cas des logiciels « rares », pour lesquels de tels programmes ne sont pas disponibles.

Plusieurs personnes ont donc réfléchi à ce problème de portabilité des données. Ainsi, la création, en janvier 2008, du consortium DataPortability.org par quelques acteurs de poids comme LinkedIn, Six Apart ou Flickr a suscité beaucoup d'intérêt (mais il semble qu'il n'y ai pas encore grand'chose de produit).

Quelques conseils pratiques, pour finir :

  • Avant d'écrire des milliers de pages ou d'articles, demandez-vous comment vous les récupérerez en cas de changement de logiciel ?
  • Si un programme de conversion semble disponible, testez-le d'abord, de preférence sur des données réelles. Beaucoup de ces programmes de conversion sont très sommaires et ne gèrent pas certains cas.

J'ai rassemblé quelques ressources Web sur ce thème en http://del.icio.us/bortzmeyer/dataportability.


L'article seul

RFC 5389: Session Traversal Utilities for (NAT) (STUN)

Date de publication du RFC : Octobre 2008
Auteur(s) du RFC : J. Rosenberg (Cisco), R. Mahy (Plantronics), P. Matthews (Avaya), D. Wing (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 25 octobre 2008


Le NAT a toujours été une des plaies de l'Internet, entre autres parce qu'il perturbe les applications qui veulent transmettre une référence à leur adresse IP. STUN, décrit dans ce RFC, est un des protocoles qui permet de limiter les dégâts. (Ce RCF a depuis été remplacé par le RFC 8489, qui est désormais la norme STUN.)

Pour plusieurs raisons, dont le manque d'adresses IPv4, de nombreuses machines sont connectées à l'Internet derrière un routeur qui fait du NAT. Leur adresse étant alors privée, elles ne peuvent pas la transmettre à l'extérieur, ce qui est une gêne considérable pour tous les protocoles qui reposent sur la référence à des adresses IP, comme SIP. SIP lui-même (RFC 3261) marche à travers le NAT mais les données audio ou vidéo transmises (typiquement par RTP) le sont à une adresse IP que l'appelant donne à l'appelé et, si cette adresse est privée, le flux multi-média n'arrivera jamais.

La bonne solution serait de déployer IPv6, qui fournit des adresses en quantité illimitée, ou à la rigueur de permettre un meilleur contrôle du routeur NAT avec MIDCOM (RFC 3303) mais, en attendant, STUN est une solution simple et qui marche souvent. STUN avait à l'origine été normalisé dans le RFC 3489, que ce RFC met à jour, avec des changements assez importants, mais qui n'empêchent pas la compatibilité des anciens clients avec les nouveaux serveurs (ou réciproquement, sauf si le client utilise les nouvelles possibilités, comme la possibilité de fonctionner sur TCP et plus seulement UDP).

STUN s'inscrit donc dans la catégorie des protocoles de « réparation » du NAT, catégorie décrite dans le RFC 3424.

STUN résout partiellement le problème des NAT de la manière suivante : un serveur STUN doit être installé quelque part sur l'Internet public (il existe des serveurs STUN publics) et reçoit des demandes envoyées en UDP (ou TCP, voir la description de cette nouveauté en section 7.2.2) au port 3478. Le serveur STUN peut alors connaitre l'adresse publique, celle mise par le routeur NAT et, en répondant au client, il pourra informer celui-ci « Voilà à quoi tes paquets ressemblent, vus de l'extérieur ». stun

Le nom du serveur STUN est typiquement configuré dans le client, puis le serveur recherché dans le DNS via les enregistrements SRV (RFC 2782), comme détaillé dans la section 9. (Le client Unix en ligne de commande ne connait pas encore les SRV.)

Le principe est simple, mais le RFC est plus compliqué que cela, notamment en raison des problèmes de sécurité (la section 16 du RFC est très détaillée sur ce point). Par exemple, le client STUN doit en fait commencer par une connexion TCP pour obtenir un mot de passe temporaire. (d'autres méthodes d'authenfication sont possibles.)

Un autre problème est qu'il y a en fait plusieurs sortes de NAT (voir par exemple le RFC 2663). Par exemple, certains routeurs NAT (Symmetric NAT pour le RFC 3489) n'attribuent pas l'adresse externe uniquement en fonction de la source mais aussi en fonction de la destination. Ceux-ci ne fonctionnent pas avec STUN, qui a besoin de NAT cone, c'est-à-dire où les paquets d'une même machine auront toujours la même adresse IP externe.

Voici une démonstration d'un client STUN qui, en se connectant à un serveur STUN public va apprendre son adresse IP publique :

% ifconfig -a
hme0: [...] inet 172.19.1.2
(Adresse privée, probablement NATée...)

% ./client  stun.ekiga.net -v |& more
STUN client version 0.96
...
MappedAddress = 213.41.181.9:32143
(Voici mon adresse telle que vue de l'extérieur, à noter que ce RFC,
contrairement à son prédécesseur la nomme désormais ReflexiveAddress)
...

Une fois l'adresse extérieure détectée, tout n'est pas terminé car rien n'indique, par exemple, que les paquets vont effectivement passer. C'est pour cela que la section 14 insiste que STUN n'est qu'un outil, devant s'insérer dans une solution plus gobale, comme ICE (pas encore normalisé). À lui seul, STUN ne permet pas la traversée de tous les NAT. La section 14 décrit en détail ce concept d'utilisation de STUN et les règles que doivent suivre les protocoles qui utilisent STUN.

La section 6 décrit le format des paquets. Un paquet STUN doit comprendre l'indication d'une méthode, qui indique le genre de services que désire le client. Notre RFC 5389 ne décrit qu'une seule méthode, Binding, qui permet d'obtenir son adresse IP extérieure mais TURN (RFC 5766), par exemple, en définit d'autres. Après la méthode et un identificateur de transaction (qui sert au serveur STUN à séparer ses clients), suivent les attributs, encodés en TLV (la liste des attributs figure en section 15). Les numéros des attributs sont compris entre 0x0000 et 0x7FFF s'ils doivent être reconnus par le serveur (autrement, la requête est rejetée) et entre 0x8000 et 0xFFFF si leur compréhension est facultative (cette notion d'attributs obligatoires ou facultatifs facilite les évolutions ultérieures du protocole). Une partie de l'identificateur de transaction de la version précédente de STUN a été transformé en magic cookie, une valeur fixe (0x2112A442) qui sert à reconnaitre les agents STUN conformes à la nouvelle version.

Les sections 2, 12 et 19 décrivent en détail les changements par rapport à la norme précédente, le RFC 3489, notamment le fait que STUN (qui a changé de nom au passage, en gardant le même sigle) n'est plus présenté comme une solution complète mais comme un outil pour une solution plus générale (qui doit, notamment, tester que la connectivité fonctionne, comme le fait ICE). Même la découverte du comportement du NAT est désormais effectuée par des protocoles plus riches comme celui du RFC 5780. Parmi les autres changements, il faut noter que STUN encode désormais les adresses IP (par un simple XOR, section 15.2) pour les masquer, empêchant ainsi des stupides routeurs NAT de les réécrire (oui, certains routeurs NAT, profitant de l'absence de mécanisme de responsabilité pour le logiciel embarqué, examinaient toutes les données transitant par eux pour réécrire les adresses IP afin d'y mettre l'adresse publique ; le RFC parle poliment de misguided attempt at providing a generic ALG function mais le terme correct est « débilité monstrueuse »). Notez enfin que le RFC actuel sur STUN est, depuis février 2020, le RFC 8489.


Téléchargez le RFC 5389


L'article seul

La racine DNS ORSN se termine officiellement

Première rédaction de cet article le 24 octobre 2008


C'est par un message de Paul Vixie sur la liste dns-operations que la majorité des acteurs du DNS ont appris l'arrêt officiel de la racine ORSN (Open Root Server Network).

ORSN était de très loin la plus sérieuse des racines alternatives, ces groupes de serveurs de noms qui font concurrence aux serveurs racines « officiels ». La plupart de ces racines alternatives sont créées et maintenues par de complets zozos, voire par des escrocs purs et simples. ORSN était une des rares qui géraient le même espace de nommage que la racine gérée par le gouvernement US, espace auquel elle se contentait d'ajouter des innovations techniques (comme IPv6, pour lequel il a fallu attendre des années pour que l'ICANN le mette dans la racine officielle). ORSN était géré par plusieurs opérateurs sérieux.

Si mettre en route une racine alternative est trivial (n'importe quel étudiant en informatique avec trois PC peut le faire), la faire fonctionner régulièrement pendant des années, en surveillant que tout se passe bien, est beaucoup moins simple. ORSN avait souvent eu de sérieux problèmes mais, cette fois, ses responsables ont eu au moins la franchise de reconnaître qu'ils ne pouvaient plus assurer. ORSN est donc officiellement arrêtée, ne laissant pas d'autre racine utilisable que l'officielle.

(Depuis, ORSN est apparemment reparti, en juin 2013.)


L'article seul

Générer une version statique d'un site Web

Première rédaction de cet article le 24 octobre 2008


On a souvent besoin de générer une version statique d'un site Web, c'est-à-dire de simples pages HTML, utilisables sans logiciel derrière, juste avec un serveur de fichiers, voire pas de serveur du tout, par exemple lorsque la version statique a été mise sur un CD-ROM. Mais comment faire avec les outils existants ?

Ces versions statiques sont très pratiques lorsqu'on veut pouvoir transformer un gros site Web nécessitant pour fonctionner un ensemble complexe de programmes en Java, en PHP ou autre, sans compter le SGBD qui l'accompagne. Cette transformation en site statique permet de consulter par la suite le site sur n'importe quelle plate-forme, même non connectée à l'Internet (ou bien mal connectée, un cas fréquent). france.fr aurait dû utiliser un tel mécanisme (puisque son contenu, quoique géré par des techniques dynamiques - Drupal - était entièrement statique), celà lui aurait épargné le ridicule.

Un autre cas qui m'a servi était celui où le moteur du site, un CMS, était bien vieux, plus maintenu, rempli de failles de sécurité et où personne n'avait le temps et l'envie de le mettre à jour. Le transformer en version statique a permis de continuer à le publier, même si on ne pouvait plus changer le contenu (http://www.web1901.org/). Cela avait l'avantage de supprimer beaucoup de risques de sécurité notamment les spam dans les commentaires.

Maintenant, comment faire pour produire cette version statique ? Si on a accès aux « cuisines », à la base de données où tout est stocké (ce qui est le cas des sites qu'on contrôle entièrement mais aussi de sites très ouverts comme Wikipédia), alors, il faut écrire un petit programme de conversion en HTML.

Si non, on peut toujours utiliser un client HTTP doté de la capacité de récupérer les pages, mais aussi de les modifier pour les adapter à cette nouvelle tâche. Il en existe deux en logiciel libre, wget et httrack.

Pour wget, l'utilisation de base est :

wget  --mirror --no-parent --convert-links http://www.LESITE.fr/

Le --convert-links est indispensable si certains liens sont absolus. Il faut alors les convertir en liens relatifs. Cette commande laisse un ensemble de fichiers HTML dans un répertoire nommé www.LESITE.fr, ensemble qu'on peut copier sur un CD-ROM ou une clé USB, archiver, etc.

Si le site est d'accès restreint, pas de problème :

wget --http-user MOI --http-passwd MONSECRET \
        --mirror --no-parent --convert-links  http://www.LESITE.fr/

wget a une limite que je trouve très gênante : si certains URL comportaient des ?, il laisse des fichiers avec un point d'interrogation dans le nom. Un navigateur comme Konqueror ne peut alors pas suivre les liens locaux (même sur Unix, il faut utiliser l'option --restrict-file-names=windows pour résoudre cela). Cela illustre l'importance de tester le résultat, surtout si on s'apprête à le graver sur un support stable.

Mais le vrai problème est que wget ne renomme pas les fichier en un nom finissant par .html. En local, le navigateur Web ne dispose pas de l'information donnée par le protocole HTTP et permettant de connaître le type du fichier récupéré. L'extension est donc indispensable (lynx avec -force_html ne résout pas le problème car cette option n'agit que sur le premier fichier auquel on accède).

Le deuxième logiciel utilisable, et qui n'a pas ce défaut, est httrack. Si wget a beaucoup d'options (lisez son manuel en ligne), httrack en a une quantité astronomique. Mais on utilisation de base est aussi simple :

httrack http://www.LESITE.fr/

En outre, son affichage pendant l'exécution est bien plus agréable.

httrack réécrit les URL « dynamiques » en URL simples : index.html?art=55 devient ainsi quelque chose comme index6d76.html. De tels fichiers sont bien plus facilement manipulables en local.

Les fichiers de httrack ne marchent toujours pas avec lynx (car les liens dans les fichiers ne sont pas toujours modifiés) mais c'est bon avec Konqueror qui gère intelligement les points d'interrogation. Ceci dit, l'option -%q0 règle cela et j'utilise donc désormais httrack pour ces tâches.

Pour un autre article sur le même sujet, on peut consulter http://blog2doc.over-blog.com/article-1387761.html.


L'article seul

RFC 5358: Preventing Use of Recursive Nameservers in Reflector Attacks

Date de publication du RFC : Octobre 2008
Auteur(s) du RFC : J. Damas (ISC), F. Neves (registro.br)
Première rédaction de cet article le 20 octobre 2008


L'ampleur des attaques DoS menées avec l'aide de serveurs DNS récursifs ouverts a mené à ce RFC qui résume les bonnes pratiques : un serveur DNS ne doit pas être récursif pour le monde entier.

L'accroissement du nombre d'attaques début 2006 a provoqué une prise de conscience, qui s'est manifesté par de nombreux avertissements aux administrateurs réseaux (comme celui de l'AFNIC). La vitesse de publication d'un RFC étant ce qu'elle est, c'est seulement maintenant qu'un RFC met par écrit cette règle simple (le RFC est très court). Un serveur DNS ne doit être récursif que pour ses clients connus, pas pour tout l'Internet.

En effet, s'il est récursif ouvert, il peut servir de base à une attaque par amplification. Il n'y a aujourd'hui aucune raison technique légitime de laisser un serveur récursif ouvert (vous pouvez tester le vôtre avec l'interface Web de the Measurement Factory et trouver des informations sur la configuration de votre logiciel dans le document, malheureusement ancien, Securing an Internet Name Server).

La section 4 détaille les configurations qui peuvent limiter l'accès à la récursion : par exemple, pour un boîtier SOHO qui sert également de résolveur DNS, discriminer selon l'interface (n'accepter les requêtes DNS que si elles viennent du réseau local). Ou bien, pour les machines en déplacement (un des arguments les plus souvent présentés par ceux qui voulaient maintenir la récursion ouverte à tous), utiliser un résolveur local à la machine, ou bien monter un VPN avec un résolveur de confiance.

À noter que notre RFC parle également beaucoup de BCP 38 (actuellement le RFC 2827) comme étant la « vraie » solution au problème. Mais c'est exagéré : BCP 38 ne résoud pas tous les problèmes, notamment les attaques entres clients d'un même opérateur.

Une technique non mentionnée par le RFC est de limiter le trafic du résolveur.


Téléchargez le RFC 5358


L'article seul

RFC 5382: NAT Behavioral Requirements for TCP

Date de publication du RFC : Octobre 2008
Auteur(s) du RFC : S. Guha (Cornell U.), K. Biswas (Cisco), B. Ford (MIT), S. Sivakumar (Cisco), P. Srisuresh
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 17 octobre 2008


Comme son compagnon, le RFC 4787, qui concerne UDP, ce RFC décrit les règles que doit suivre un routeur NAT pour être utilisable sans trop de problèmes par les applications TCP.

La lecture préalable du RFC 4787 est recommandée, car il fixe le vocabulaire et les principes généraux. Notre RFC les complète ensuite pour le cas de TCP.

TCP a beaucoup évolué depuis le début (cf. le RFC 7414 pour une bonne description de cette évolution) mais le mécanisme de connexion initial, le fameux « Three-Way handshake », n'a pas changé, des tentatives comme T/TCP (cf. RFC 1644) ayant échoué. C'est cette connexion initiale qui est le plus gênée par le NAT.

Les exigences de notre RFC pour un routeur NAT sont principalement :

  • Indépendance par rapport à la destination : la table de correspondance entre un port et un couple (adresse IP, port) ne doit dépendre que de la source,
  • Le routeur doit accepter la totalité de la machine à états de TCP (décrite dans le RFC 793) et notamment, ce que beaucoup de routeurs NAT ne font pas, l'ouverture simultanée (où deux machines tentent une connexion TCP à peu près en même temps),
  • Les éventuels délais avant qu'une session TCP « inactive » soit coupée doivent être d'au moins deux heures (aujourd'hui, il est courant que des routeurs NAT suppriment une connexion de leur table au bout de quelques minutes, car leurs concepteurs n'ont pensé qu'aux sessions HTTP, jamais à SSH, où il est courant qu'une session dure des jours et n'envoie pas de paquets tout le temps).

Depuis la sortie de ce RFC, le RFC 7857 a apporté quelques compléments.


Téléchargez le RFC 5382


L'article seul

Normalisation synthétique du DNS : un nouvel échec

Première rédaction de cet article le 16 octobre 2008


Le DNS est très compliqué pour les implémenteurs, car il existe de nombreux RFC, qui se mettent partiellement à jour. Les deux RFC de départ, le RFC 1034 et RFC 1035, sont, selon les critères actuels, plutôt mal écrits, et ils sont précisés, modifiés, etc, par bien d'autres RFC, mais qui ne les rendent pas obsolètes pour autant. Écrire une mise en œuvre correcte du DNS aujourd'hui nécessite de lire beaucoup de documents.

Régulièrement, un groupe de participants à l'IETF se dit que c'est intolérable, qu'il faut faire quelque chose, et décident, soit de réécrire les RFC 1034 et RFC 1035 en propre, en intégrant les mises à jour, soit, pour les moins courageux, d'écrire un RFC de guide parmi les RFC, sur le modèle de ce qu'est le RFC 7414 pour TCP.

La dernière tentative de produire un document qui détaille les RFC sur DNS, leur importance, et leurs relations, suivait cette seconde méthode. Elle se nommait DNS profile. Cette fois, j'étais un des participants au projet. Il vient d'échouer et d'être officiellement abandonné le 15 octobre.

Comme les projets précédents, il a échoué par manque de temps (la faille Kaminsky est tombée en plein milieu du projet), manque d'intérêt, manque de financement (le travail à l'IETF est fondé sur le volontariat). Le DNS restera donc en l'état.


L'article seul

RFC 3879: Deprecating Site Local Addresses

Date de publication du RFC : Septembre 2004
Auteur(s) du RFC : C. Huitema (Microsoft), B. Carpenter (IBM)
Chemin des normes
Première rédaction de cet article le 14 octobre 2008


L'IETF n'a jamais apprécié les identificateurs à portée purement locale, comme le TLD .local ou comme les adresses IP privées du RFC 1918. Ces identificateurs locaux, dont la signification est spécifique à un site donné, soulèvent plusieurs problèmes, par exemple une question pratique : que faire si deux organisations fusionnent et qu'elles utilisent toutes les deux de tels identificateurs, qui sont en collision ?

Les RFC successifs sur l'adressage IPv6 prévoyaient des identificateurs « site-local », spécifiques à un site, dans le préfixe FEC0::/10 (RFC 3513, section 2.5.6, ce RFC ayant depuis été remplacé par le RFC 4291). Toute organisation pouvait piocher librement dans ces adresses, tout en faisant attention à ne pas les laisser sortir de son site. Cela a permis à beaucoup d'organisations de commencer à expérimenter avec IPv6.

Mais ces identificateurs posaient des problèmes, en général communs avec tous les problèmes des identificateurs locaux. La section 2 du RFC les détaille :

  • Si des applications se passent des adresses IP, comme le font FTP ou SIP, elles doivent connaitre les frontières de site pour savoir si elles peuvent passer des adresses privées (section 2.2).
  • Commes les domaines privées, les adresses IP privées tendent à « fuir », à être transmises en dehors du site (par exemple dans les en-têtes Received: du courrier électronique ou via des requêtes DNS comme celles qu'absorbe l'AS112). Comme elles perdent toute signification en dehors du site d'origine, cela sème la confusion (section 2.3).
  • Elles nécessitent un traitement spécial par les routeurs (section 2.4).
  • Selon le RFC 3879, le concept de « site » lui-même n'est pas clairement défini (section 2.5). Est-ce une entité administrative unique ? Un site géographique unique ? Un AS ? Je dois avouer que cette section est la moins convaincante de tous et qu'elle donne l'impression que les auteurs ont voulu charger la barque. Puisque les adresses « site-local » sont spécifiques à un site, rien n'empêchait chaque site d'avoir sa propre définition.

Du point de vue pratique, pour l'opérateur d'un réseau, ces inconvénients pouvaient sembler légers et, de toute façon, un mécanisme de remplacement était nécessaire. C'est au développement de ce mécanisme que s'attaque la section 3 qui réclame un mécanisme alternatif assurant l'unicité des adresses « locales ». Cela ne supprimera pas, par exemple, les fuites, mais cela les rendra plus facile à déboguer. Ce mécanisme, les ULA (Unique Local Addresses) a finalement été créé par le RFC 4193.

Un détail important : la section 5, consacrée à la sécurité, rappelle que, contrairement à ce que croient beaucoup d'administrateurs réseaux débutants, le fait d'avoir des adresses privées n'offre à peu près aucune protection (par exemple parce que des techniques comme le changement DNS permettent d'attaquer de l'intérieur). La bonne technique est l'emploi de filtres et elle s'applique aux adresses privées comme aux publiques.

Il ne faut cependant pas considérer que les identificateurs locaux sont systématiquement une mauvaise idée. Ils sont nécessaires lorsque l'obtention d'identificateurs globaux, valables partout, est difficile ou coûteuse. C'est le cas des adresses IPv4 privées du RFC 1918 : vue la pénurie d'adresses IPv4 et les obstacles financiers et bureaucratiques à franchir pour en obtenir, il est logique d'utiliser ces adresses privées. C'était également le cas à l'époque pour les adresses IPv6 privées. Pendant longtemps, il était complètement impossible d'en obtenir (par diplomatie, pour éviter de vexer les RIR, le RFC 3879 évite de rappeler cet épisode). Il est donc déplorable que ce RFC aie été publié avant que son successeur, le RFC 4193, soit prêt. Désormais, les ULA de ce RFC fournissent une meilleure solution, qui évite notamment les collisions entre deux sites qui fusionneraient. On peut donc enterrer FEC0::/10 sans remords.


Téléchargez le RFC 3879


L'article seul

La licence restrictive de Broadcom surprend les utilisateurs Linux des serveurs Dell

Première rédaction de cet article le 13 octobre 2008


Depuis longtemps, la difficulté à obtenir les spécifications des périphériques d'ordinateurs comme les cartes Ethernet handicape sérieusement les développeurs (et donc les utilisateurs) de logiciel libre. Si beaucoup de choses (Wifi, cartes graphiques, notamment 3D, ACPI) fonctionnent si mal sur Linux ou sur FreeBSD, ce n'est pas à cause de la paresse ou de l'incompétence de leurs développeurs, mais à cause de la volonté délibérée des fabriquants de ne pas aider, notamment en ne communiquant pas les spécifications, ou bien en ne le faisant qu'en échange d'un NDA très restrictif. Parfois, ces fabricants fournissent un pilote ou une partie de pilote (le firmware) mais pas toujours sous une licence libre. (Les firmwares ne sont fréquemment livrés qu'en binaire.) Et parfois, la licence change...

C'est ce qui vient d'arriver aux utilisateurs des serveurs Dell Poweredge comme le 2950 ou le 2970, équipés d'une carte Ethernet Broadcom détectée par Linux comme Broadcom NetXtreme II BCM5708 1000Base-T (B2) PCI-X 64-bit 133MHz. Cette carte fonctionnait sans problèmes avec les noyaux Linux jusqu'au 2.6.23, avec le module bnx2. Sur un Dell Poweredge 2970, sous Debian lenny (version actuellement en test), je mets à jour le noyau, je redémarre et plus de réseau !

La licence n'est en effet plus libre : comme bien d'autres, Debian n'acceptait de tels ajouts au noyau que temporairement et a fini par durcir sa position. Il faut désormais, pour que le pilote Linux fonctionne, charger un blob binaire (et, apparemment, penser à faire un update-initramfs -u). Plusieurs utilisateurs en ont fait l'expérience. Sur Debian, ce firmware est disponible dans les dépôts de logiciel non-libre, sous le nom de firmware-bnx2. Sa licence est en /usr/share/doc/firmware-bnx2/copyright.

Son installation a nécessité pour moi une clé USB puisqu'il n'y avait plus de réseau. Il vaut donc mieux, si on est le malheureux propriétaire de telles machines, penser à le faire avant le prochain redémarrage... Et penser à le faire remarquer à Dell, qui utilise de tels composants dans ses machines.

Un bon article en français sur la gestion du firmware sur Debian est « Firmwares manquants dans Debian ? Apprenez à gérer le problème ».


L'article seul

Les Japonais aussi pètent parfois les plombs

Première rédaction de cet article le 13 octobre 2008


Personne en Europe ne comprend vraiment le Japon, c'est une banalité. Mais tout espoir n'est pas perdu, pense Keiko Ichiguchi, auteure de mangas, résidente à Bologne depuis des années et qui a décidé de faire un modeste effort pour expliquer le Japon aux européens. Ce petit livre, la suite de « Pourquoi les Japonais ont les yeux bridés », illustré par l'auteure, fait partie de ce projet.

Notre Japonaise Bolonaise s'est donc lancé dans des explications : est-ce que les japonais gardent toujours leur calme ? (Non, mais les manifestations de la colère ne sont pas les mêmes qu'en Europe.) Pourquoi les héros du Shinsengumi sont-ils si populaires ? Existe t-il des gros mots en japonais ? (Oui, mais pas beaucoup.) Les adolescentes japonaises sont-elles bizarres ? (Oui, d'après l'auteure, une quadragénaire.)

Le tout oscille entre article de Marie-Claire, cours d'histoire (la révolution Meiji est traitée en trois chapitres), plaidoyer antiraciste (dans le chapitre « Je suis une extra-communautaire ») compensé par des bouffées de nationalisme (« Je suis une Japonaise dangereuse  »).

C'est léger, cela fait réfléchir et c'est édité chez Kana (Dargaux/Lombard).


L'article seul

Trouver si un domaine a des jokers

Première rédaction de cet article le 10 octobre 2008


Le DNS permet à un domaine d'avoir des jokers, des enregistrements qui feront que le serveur DNS répondra systématiquement à tous les noms de domaine, qu'ils « existent » ou pas. Comment tester, sans accès aux données entrées, si un domaine a de tels jokers ?

Les jokers (wildcards) sont un des points les plus contestés du DNS. Certains TLD les utilisent de façon à rabattre du trafic (essentiellement des fautes de frappe) vers un serveur de publicité (c'est ce que fait aujourd'hui .tk ou ce qu'à fait, avec beaucoup plus de publicité, .com, dans l'affaire connue - bien à tort - sous le nom de Sitefinder ; le registre de .fr, s'est par contre engagé à ne pas le faire).

Pire, certains FAI peu scrupuleux utilisent une technique similaire sur les résolveurs DNS qu'ils mettent à la disposition de leurs clients, malgré l'avertissement du RFC 4924 (voir aussi le communiqué de l'AFNIC).

Comment détecter qu'il y a des jokers ? En lisant le RFC 1034, cela semble simple. Les jokers sont représentés par le caractère * et, si on veut tester example.org, on fait une requête DNS pour *.example.org et on voit si le domaine existe ou pas (attention à échapper le caractère * pour le shell Unix) :


% dig ANY \*.example.org
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 48646
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

Le NXDOMAIN (No Such Domain) indique que le domaine n'existe pas et qu'il n'y a donc pas de jokers. Avec .tk, par contre :


% dig ANY \*.tk         
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63123
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 7, ADDITIONAL: 1
...
;; ANSWER SECTION:
*.tk.                   86400   IN      MX      20 MX-HOST.DOT.tk.

Ici, le domaine existe : .tk a bien des jokers.

Mais le monde est plus compliqué que cela : on trouve des domaines qui ne répondent pas pour * mais qui ont quand même des jokers, et aussi le contraire. Il faut donc utiliser un algorithme plus perfectionné. Voici celui que j'ai développé (avec l'aide de Joe Abley et de plusieurs autres) :

  • Envoyer une requête pour *.DOMAINE.example,
  • Envoyer trois requêtes pour des noms choisis aléatoirement dans DOMAINE.example,
  • Vérifier que les réponses coïncident.

Notez qu'aucun algorithme de recherche de jokers n'est parfait. Celui-ci a des faux négatifs (par exemple si la malchance fait que les noms choisis au hasard existent réellement) et des faux positifs (par exemple si les serveurs DNS ont des réponses variées - plusieurs serveurs avec des adresses IP différentes à chaque requête).

Le code de mise en œuvre en Python, utilisant dnspython, est disponible. Voici quelques tests :


% python DNSwildcards.py fr
fr does not have A wildcards
% python DNSwildcards.py -t TXT fr
fr does not have TXT wildcards

% python DNSwildcards.py tk       
tk has A wildcards (['193.33.61.2', '195.20.32.103', '209.172.59.196', '217.119.57.22'])

% python DNSwildcards.py elastoplast.fr
elastoplast.fr has wildcards but no data for type A
% python DNSwildcards.py -t MX elastoplast.fr 
elastoplast.fr has MX wildcards ([<DNS IN MX rdata: 10 mail1.beiersdorf.com.>, <DNS IN MX rdata: 50 mail2.beiersdorf.com.>])

Et, si on indique explicitement le résolveur (ici, celui d'OpenDNS, un service de résolution qui renvoie de fausses réponses avec de la publicité) :


# Avec le résolveur standard, cela marche
% python DNSwildcards.py bortzmeyer.org                  
bortzmeyer.org does not have A wildcards

# Avec OpenDNS, on récupère toujours l'adresse du serveur de publicités
% python DNSwildcards.py -r 208.67.222.222 bortzmeyer.org
bortzmeyer.org has A wildcards (['208.69.34.132'])


L'article seul

RFC 5357: A Two-way Active Measurement Protocol (TWAMP)

Date de publication du RFC : Octobre 2008
Auteur(s) du RFC : K. Hedayat (Brix Networks), R. Krzanowski (Verizon), A. Morton (AT&T Labs), K. Yum (Juniper Networks), J. Babiarz (Nortel Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 7 octobre 2008


Aujourd'hui, l'administrateur réseau qui teste ses problèmes de performance utilise en général ping pour mesurer le RTT, le temps d'aller-retour avec la machine visée. Demain, utilisera t-il un programme nommé twping et le vieux ping sera t-il dépassé ? C'est en tout cas ce que visent les auteurs de ce protocole de mesure de RTT. (ping restera utile pour les tests de bon fonctionnement.)

ping, qui repose sur l'envoi de paquets ICMP echo request et echo reply (cf. RFC 792) a en effet des limites, décrites dans le RFC 2681, section 2.6 : notamment, il est difficile de savoir si les paquets ICMP ont été traités rapidement ou pas par la machine qui répond (un routeur Cisco renvoie la réponse très lentement, car elle doit passer par le processeur généraliste du routeur). En outre, il n'est pas possible de réserver l'usage de ces paquets echo à certains, sauf à filtrer par adresse IP (TWAMP, lui, permet l'authentification).

TWAMP (Two-way Active Measurement Protocol) hérite directement d'OWAMP (One-way Active Measurement Protocol, RFC 4656). Il reprend beaucoup de ses concepts, notamment la séparation en deux protocoles, celui de contrôle et celui de test. Notre RFC 5357 est d'ailleurs largement écrit sous forme de différences entre OWAMP et TWAMP, on ne peut donc pas implémenter ce dernier sans avoir lu le RFC 4656.

TWAMP met donc en œuvre la métrique décrite dans le RFC 2681 pour les mesures bidirectionnelles. Ces mesures ont l'avantage de ne pas dépendre de la présence d'une horloge correcte sur les deux machines et l'inconvénient de ne pas pouvoir séparer les contributions du trajet aller et du trajet retour. Un des deux est peut-être bien plus lent que l'autre mais les mesures bidirectionnelles ne pourront pas le détecter.

Comme l'explique la section 1.2, un système TWAMP peut comprendre jusqu'à quatre machines mais on peut supposer que, la plupart du temps, il n'y en aura que deux, la Control-Client/Session-Sender et la Server/Session-Reflector. Le programme sera lancé sur la première, qui émettra les paquets qui seront renvoyés par la seconde, permettant de calculer le RTT.

La section 2 décrit le protocole : le Control-Client établit une connexion avec le Server sur le port 862, ils se mettent d'accord sur le test, puis le Session-Sender envoie les paquets au Session-Reflector.

La section 3 décrit le protocole de contrôle, très proche de celui d'OWAMP. La section 4 est consacrée au protocole de test, dont la différence avec son prédécesseur est plus marquée, puisqu'il faut désormais renvoyer les paquets reçus. La procédure exacte suivie par le Reflector est décrite en 4.2. Le réflecteur renvoie la date d'arrivée, celle d'émission de la réponse et d'autres informations (section 4.2.1). Comme la réponse contient le TTL tel qu'il était à l'arrivée, une implémentation de TWAMP doit pouvoir accéder aux en-têtes IP, ce qui n'est pas pas toujours simple. Comme avec OWAMP, le diable est dans les détails et l'implémentation doit être faite très soigneusement pour limiter les erreurs et imprécisions.

TWAMP a depuis, bénéficié d'extensions au protocole de base, décrites dans le RFC 6038.

À noter que ce RFC est, je crois, le premier RFC qui normalise la prononciation du sigle du protocole (section 1.3) : « ti-ouampe ».

Il n'existe pas actuellement de mise en œuvre de TWAMP en logiciel libre. Compte-tenu de la proximité du protocole avec OWAMP, le meilleur moyen d'en écrire une serait sans doute de partir du programme owamp.

Pour une critique vigoureuse de ce RFC (pas du protocole, mais de la rédaction du RFC), voir « How NOT to Write a Protocol Specification », de Dustin D. Trammell.


Téléchargez le RFC 5357


L'article seul

RFC 3406: Uniform Resource Names (URN) Namespace Definition Mechanisms

Date de publication du RFC : Octobre 2002
Auteur(s) du RFC : L. Daigle (Thinking Cat), D. van Gulik (Web Weaving), R. Iannella (IPR Systems), P. Faltstrom (Cisco)
Première rédaction de cet article le 1 octobre 2008


Le RFC 2141 définissait une syntaxe pour les URN, un membre de la grande famille des URI. Dans cette syntaxe, immédiatement après la chaîne de caractères urn:, on trouve l'espace de noms (namespace), une chaîne de caractères qui identifie le domaine d'une autorité d'enregistrement. Notre RFC 3406 expliquait les procédures de création d'un nouvel espace de noms dans le registre des espaces de noms que tient l'IANA. Ces deux anciens RFC ont dépuis été remplacés par le RFC 8141.

Comme expliqué dans la section 1, ce mécanisme d'espaces de noms suppose que, dans chaque espace, il existe une autorité d'enregistrement qui accepte (ou refuse) les enregistrements et que, d'autre part, il existe une autorité qui enregistre les espaces de noms (en l'occurrence l'IANA). Tout le RFC 3406 est consacré aux procédures de cette dernière autorité et aux mécanismes pour enregistrer un identificateur d'espace de noms (NID pour namespace identifier). (La résolution des URN en autres identificateurs n'est par contre pas couverte.) Des exemples d'autorité d'enregistrement dans un espace de noms donné sont le gouvernement néo-zélandais (RFC 4350) ou l'OGC (RFC 5165).

La section 2 du RFC détaille ensuite ce qu'est un espace de noms (un ensemble d'identificateurs uniques géré, c'est-à-dire que tous les noms syntaxiquements corrects n'en font pas partie, uniquement ceux qui ont été enregistrés). Par exemple, les ISBN forment un tel espace (dont l'utilisation dans des URN a fait l'objet du RFC 3187). À l'intérieur d'un espace de noms, les règles d'enregistrement et le travail quotidien du registre ne sont pas gérés par l'IETF ou l'IANA mais par l'autorité d'enregistrement de cet espace.

La section 3 introduit les différents types d'espaces de noms. Il y a des espaces expérimentaux (section 3.1), qui ne nécessitent pas d'enregistrement auprès de l'IANA, et qui se reconnaissent à leur NID commençant par x- (leur usage est désomais découragé, cf. RFC 6963). Il y a les espaces informels (section 3.2), dont le NID commence par urn- et est composé de chiffres et les espaces formels (section 3.3) dont le NID est composé de lettres et qui, contrairement aux informels, sont censés fournir un bénéfice aux utilisateurs de l'Internet (les espaces informels ont le droit d'être réservés à une communauté déconnectée). Contrairement encore aux informels, l'enregistrement des espaces formels doit faire l'objet d'une spécification écrite, typiquement un RFC.

Un des principes des URN est la durabilité : un URN devrait être stable dans le temps. Mais cette stabilité dépend essentiellement de facteurs non-techniques, comme la permanence dans le temps du registre (une organisation privée et fermée comme l'IDF est, par exemple, typiquement un mauvais choix pour assurer la permanence). Toutefois, si on ne peut pas garantir la stabilité d'un espace de noms, on connait en revanche des facteurs qui diminuent la probabilité de permanence et l'IETF peut donc analyser les spécifications à la recherche de tels facteurs (c'est une variante du problème très riche mais bien connu de la stabilité des identificateurs).

Enfin, avec la section 4, on arrive au processus d'enregistrement lui-même. Il faut en effet un peu de bureaucratie pour s'assurer que le NID est bien enregistré et que le registre des NID soit lui-même stable. Les procédures sont différentes selon le type d'espace de noms. Les expérimentaux (section 4.1) ne sont pas enregistrés du tout. Les informels (section 4.2) ont leur propre registre, avec un processus d'enregistrement léger, mais très peu utilisé.

Le gros morceau est constitué des espaces de noms formels (section 4.3). Cette fois, le processus d'enregistrement est plus complexe, un RFC est nécessaire, mais on obtient un « vrai » NID comme MPEG (RFC 3614), OASIS (RFC 3621) ou 3gpp (RFC 5279).

Le formulaire d'enregistrement complet est disponible dans l'annexe A du RFC. Bon courage aux futurs enregistreurs. N'oubliez pas de lire tout le RFC.

Notre RFC succède au RFC 2611, les changements étant détaillés dans l'annexe C. Ils incluent une meilleure formalisation des différents types d'espace (expérimental, informel et formel) et une description plus détaillée des formalités d'enregistrement. Depuis, il a lui-même été remplacé par le RFC 8141.


Téléchargez le RFC 3406


L'article seul

RFC 5322: Internet Message Format

Date de publication du RFC : Octobre 2008
Auteur(s) du RFC : P. Resnick (Qualcomm)
Chemin des normes
Première rédaction de cet article le 1 octobre 2008


Vieux de désormais trente et une années (la première norme était le RFC 724 en mai 1977), le format des messages électroniques vient donc de recevoir une nouvelle spécification. Pas de grands changements mais beaucoup de petites erreurs corrigées, elle marque l'avancée de la norme au statut de « projet de norme ».

Le courrier électronique d'Internet repose sur deux piliers : un protocole d'échange des messages, SMTP, normalisé dans le RFC 5321 et un format des messages, que traite notre RFC 5322. Les deux sont relativement indépendants, notamment dans le sens où on peut transporter des messages sur d'autres protocoles que SMTP, comme par exemple UUCP. Autre exemple, les adresses traitées par les deux RFC sont différentes (même si leur syntaxe est la même), SMTP gérant l'enveloppe du message et le format gérant son contenu (section 1). Cela justifie deux RFC séparés.

Que contient le RFC 5322 qui vient de remplacer le RFC 2822 ? Moins qu'on ne pourrait le croire. Des pans énormes de l'utilisation du courrier sont en dehors de ce RFC comme l'important format MIME (RFC 2045) ou comme les extensions d'internationalisation (RFC 6532).

Il reste donc un RFC sur l'envoi de messages textuels en ASCII. Mais, sans même prendre en compte des extensions comme MIME, c'est déjà assez complexe. La section 2 définit les règles lexicales des messages. Les messages sont découpés en lignes composées ce caractères. Le nombre maximal de caractères par ligne est de 998 caractères (section 2.1.1, qui recommande d'accepter également des longueurs plus grandes, mais sans générer soi-même de lignes plus longues).

La section 2.2 définit les en-têtes qui composent le début du message. Un message au format RFC 5322 ressemble, sur le câble, à :


Date: Tue, 9 Sep 2008 09:33:17 +0200
To: ubuntu-fr@lists.ubuntu.com
Message-ID: <20080909073317.GA23390@sources.org>
Subject: [Son] Silence complet sur mon ESS ES1978 Maestro 2E
From: Stephane Bortzmeyer <stephane@sources.org>

Le son, avec Linux, c'est vraiment p=E9nible.

J'ai un Dell Inspiron 7500 dont le son ne marche pas du tout. Silence
complet.

...

Le début, avant la ligne vide, est composé de cinq en-têtes (il y en a bien d'autres, non affichés ici. Avec mutt, c'est la commande h qui permet d'afficher tous les en-têtes). Chaque en-tête a un nom, suivi du deux-points et d'un corps. Si les premiers MUA affichaient directement les noms des différents champs, cela ne se fait plus guère aujourd'hui. En général, ce que voit l'utilisateur est bien différent de ce qui passe sur le câble, notamment à des fins de localisation (afficher « Objet » et pas « Subject », par exemple). Le corps du champ peut être non structuré (section 2.2.1, on y met ce qu'on veut, c'est le cas du champ Subject:) ou bien structuré (section 2.2.2, il obéit à une mini-grammaire spécialisée, c'est le cas de Date: ou de From:). Les champs peuvent être très longs et il est donc prévu (section 2.2.3) de pouvoir les plier sur plusieurs lignes. C'est un des points les plus souvent oubliés des auteurs d'analyseurs de ce format. Il faut donc rappeler qu'on ne peut pas utiliser d'outil orienté ligne comme grep sur un message électronique. (Une solution est d'utiliser l'excellente commande formail, dans le paquetage procmail, avec son option -c qui replie les lignes.)

Enfin, il y a le corps du message, après les en-têtes. Précédé d'une ligne vide, ce corps n'a pratiquement pas de structure dans notre RFC 5322 (section 2.3) mais d'autres normes comme MIME (RFC 2045) se chargent de combler ce manque et permettent, par exemple, de transporter plusieurs fichiers, y compris binaires, dans un seul message.

La section 3 décrit la syntaxe d'un message. La grammaire est très riche et très complexe. Pire, en raison de l'ancienneté de ce format, un grand nombre de productions grammaticales sont désormais abandonnées mais doivent toujours être reconnues par un analyseur, au cas où un logiciel les génère encore. Elles ont un nom commençant par obs- pour qu'on puisse les reconnaitre plus facilement. (La section 4 décrit cette grammaire abandonnée plus en détail. On y trouve, par exemple, un format pour les années sur deux chiffres, non compatible avec l'an 2000.)

Parmi les subtilités de cette grammaire :

  • La syntaxe des dates, dans le champ (structuré) du même nom (section 3.3). Elle est très souvent violée : en pratique, on voit des dates de toutes les formes, même lorsque le logiciel est un programme payant et cher. Un exemple correct est Date: Tue, 30 Sep 2008 11:49:07 +0200 (le format du courrier est bien plus ancien que la norme ISO 8601). Ce champ est décrit en 3.6.1.
  • Les adresses (section 3.4). C'est, encore plus que les dates, un des aspects les plus mal compris du courrier. Le Web abonde de programmes écrits dans des langages qui encouragent l'approximation (comme PHP ou Javascript) et qui refusent des adresses parfaitement légales. À leur décharge, il faut dire que la grammaire de la section 3.4.1 n'est pas triviale ! Un exemple d'adresse (on les utilise notamment dans les champs From: et To:) est stephane+blog@bortzmeyer.org. On notera que des normes comme NAI (RFC 7542) ou bien XMPP (RFC 7622) utilisent une syntaxe proche.

Enfin, la section 3.6 décrit tous les en-têtes. Citons entre autres :

  • L'expéditeur, From:, Sender: et Reply-To:, section 3.6.2.
  • Les destinataires, To: et Cc: (ceux qui reçoivent une copie), section 3.6.3.
  • Message-ID:, section 3.6.4, un champ structuré qui contient un identificateur unique du message, par exemple <17b4fdcd0809290041i4323797al964ccf5a344b1c47@mail.gmail.com>.
  • Subject:, section 3.6.5, qui indique l'objet du message et n'est pas structuré. Pour qu'il puisse contenir autre chose que des caractères ASCII, il faut utiliser l'encodage du RFC 2047 (ou le plus récent RFC 6532).
  • Received:, section 3.6.7, qui sert à indiquer par quels relais est passé un message. Par exemple, Received: from rv-out-0708.google.com (rv-out-0708.google.com [209.85.198.250]) by mx1.nic.fr (Postfix) with ESMTP id 98D821714088 for <bortzmeyer@nic.fr>; Mon, 29 Sep 2008 09:41:22 +0200 (CEST). C'est un excellent outil de débogage pour l'administrateur réseau.

La liste des en-têtes n'est pas figée, on la trouve dans un registre IANA (créé à l'origine par le RFC 4021) décrit en section 6.

Notre RFC 5322 remplace le RFC 2822, par rapport auquel il y a peu de changements. Le RFC 2822 remplaçait le RFC 822 qui est resté en service très longtemps, accompagnant l'essor du courrier électronique, et qui a été tellement influent que son numéro sert souvent à désigner le format (comme dans l'ancien module Python rfc822, remplacé depuis par email). L'annexe B donne la liste des changements par rapport au RFC 2822, essentiellement des corrections de bogues.


Téléchargez le RFC 5322


L'article seul

RFC 5321: Simple Mail Transfer Protocol

Date de publication du RFC : Octobre 2008
Auteur(s) du RFC : J. Klensin
Chemin des normes
Première rédaction de cet article le 1 octobre 2008


Ce RFC normalise la version actuelle de SMTP, le protocole de transfert de courrier électronique qui est un des grands succès de l'Internet et toujours une de ses applications les plus populaires, malgré les attaques des spammeurs et la concurrence des blogs et de la messagerie instantanée.

Ce protocole a été successivement normalisé par les RFC 788 (qui avait lui-même été précédé par des RFC décrivant des protocoles qui étaient très proches de SMTP), RFC 821, RFC 2821 et désormais notre RFC 5321. Le RFC 788 datant de novembre 1981, SMTP a donc vingt-sept ans.

Parmi ses caractéristiques principales, on trouve la simplicité, qui lui vaut son nom (écrire un client SMTP est simple), le fait qu'il permette le relayage du courrier par des serveurs intermédiaires et le fait qu'il ne spécifie que le transport du message, pas son contenu, qui fait l'objet du RFC 5322.

Il est intéressant de noter que, s'il a gagné en fonctions, SMTP en a aussi perdu dans certains cas. C'est ensuite que les fonctions de messagerie instantanée (voir annexe F.6) ont disparu avec le RFC 2821, le routage par la source également (annexe F.2) ou que la simple soumission du courrier par le logiciel client est désormais traitée par le RFC 6409, le SMTP complet étant réservé aux communications entre serveurs de messagerie.

La section 2 du RFC traite en détail du modèle de fonctionnement de SMTP. Le principe est que l'émetteur trouve le serveur distant (en général grâce aux enregistrements MX du DNS) puis ouvre une connexion TCP avec ce serveur distant, connexion sur laquelle on transmet l'adresse de l'expéditeur, celle du destinataire et le message (ces deux adresses forment donc ce qu'on appelle l'enveloppe, qui ne fait pas partie du message ; elles ne sont pas forcément identiques aux adresses qu'on trouve dans les champs From: et To: du message). (L'annexe B revient également sur certains aspects de la séparation entre l'enveloppe et le message. Ainsi, faire suivre un message en se fiant aux en-têtes To: du message, au lieu d'utiliser l'enveloppe, va très probablement produire des boucles sans fin.)

Le serveur distant n'est pas forcément la destination finale, il peut être un simple relais (un relais utilise SMTP des deux côtés) ou une passerelle (la passerelle parle SMTP d'un côté mais utilise un autre protocole, par exemple un protocole privé, de l'autre côté, cf. section 2.3.10).

En théorie (et la section 2.1 insiste sur ce point), le serveur qui a accepté un message doit le délivrer ou bien prévenir l'expéditeur. Aujourd'hui, avec la prolifération du spam et des joe jobs, ce principe n'est plus tenable et cette partie du RFC est donc celle qui est la plus ignorée. Une discussion sur ce point figure dans le RFC, aux sections 6.1, 6.2 et 7.8, qui admettent que « In today's world, [...] those principles may not be practical. » en rappelant toutefois qu'il faut être prudent, contrairement à beaucoup d'opérateurs de serveurs de messagerie qui jettent de nombreux messages sans garder de trace, ce qui jette un sérieux doute sur la fiabilité du service de courrier.

SMTP est simple, mais extensible. La section 2.2 résume le modèle d'extensibilité de SMTP, qui avait été intégré à partir du RFC 2821. Il repose sur une nouvelle commande pour s'annoncer au serveur distant, EHLO, qui remplace l'ancien HELO, et qui permet d'annoncer les extensions que l'ou ou l'autre MTA accepte. La section 2.2.1 insiste toutefois sur le fait que l'une des forces de SMTP est sa simplicité et qu'il ne faut donc peut-être pas trop le charger d'extensions, si elles ne sont pas clairement utiles.

La (longue) section 2.3 est consacrée à la terminologie. Elle rappelle notamment la distinction entre enveloppe et message, signalée plus haut. C'est ainsi que la définition des en-têtes du message comme Subject: ou bien Date: est laissée au RFC 5322, alors que celle du corps du message est du domaine de MIME (RFC 2045).

C'est également dans cette section de terminologie que sont définis des termes comme MTA ou MUA même si le RFC note (section 2.3.3) que, dans ce monde peu organisé, il ne faut pas toujours prendre les mots trop sérieusement.

La section suivante, 2.4, couvre les principes de base de la syntaxe SMTP, comme le fait que les commandes sont du texte, pas du binaire, qu'elles sont insensibles à la casse, et que les réponses à ces commandes sont des nombres de trois chiffres, conçus pour être interprétés par un programme (par exemple, 500 signifie « Erreur de syntaxe »).

Place ensuite, en section 3, aux procédures SMTP. Le cœur du protocole est là, notamment dans la section 3.3 qui explique l'enchaînement des commandes. Quatre sont particulièrement importantes, EHLO pour se connecter (section 4.1.1.1), MAIL FROM pour indiquer l'expéditeur (section 4.1.1.2), RCPT TO pour le destinataire (section 4.1.1.3) et DATA pour envoyer le message (section 4.1.1.4).

Voici un exemple d'une session SMTP, telle que l'affiche, pour nous aider au débogage, le client SMTP msmtp, lorsqu'il est lancé par echo TEST | msmtp --from=foobar@example.org --debug stephane@bortzmeyer.org (les lignes préfixées par <-- sont envoyées par le serveur SMTP de réception, celles commençant par --> par celui d'émission) :


<-- 220 relay1.nic.fr ESMTP Postfix
--> EHLO bortzmeyer.nic.fr
<-- 250-relay1.nic.fr
<-- 250-PIPELINING
<-- 250-SIZE 10240000
<-- 250-VRFY
<-- 250-ETRN
<-- 250-ENHANCEDSTATUSCODES
<-- 250-8BITMIME
<-- 250 DSN
--> MAIL FROM:<foobar@example.org>
--> RCPT TO:<stephane@bortzmeyer.org>
--> DATA
<-- 250 2.1.0 Ok
<-- 250 2.1.5 Ok
<-- 354 End data with <CR><LF>.<CR><LF>
--> TEST
--> .
<-- 250 2.0.0 Ok: queued as 92859A1D95D
--> QUIT
<-- 221 2.0.0 Bye

On voit, et c'est une des caractéristiques importantes de SMTP, que l'émetteur peut indiquer ce qu'il veut comme expéditeur. Cela permet les usurpations d'identité mais il n'est pas évident de résoudre ce problème de sécurité sans supprimer en même temps bien des usages utiles du courrier. Si le serveur SMTP initial peut à la rigueur authentifier ses clients, les serveurs suivants n'ont guère le choix, sinon de tout accepter.

Et voici ce qu'affiche un programme Python qui utilise la bibliothèque smtplib. Notons que les commandes de la bibliotèque portent le nom des commandes SMTP. Ici, on n'utilise que la commande de bienvenue initiale, EHLO :


% python
...
>>> import smtplib
>>> s = smtplib.SMTP("mail.example.org")
>>> s.set_debuglevel(True)
>>> s.ehlo("mail.foobar.example")
send: 'ehlo mail.foobar.example\r\n'
reply: '250-horcrux\r\n'
reply: '250-VRFY\r\n'
reply: '250-ETRN\r\n'
reply: '250-STARTTLS\r\n'
reply: '250-ENHANCEDSTATUSCODES\r\n'
reply: '250-8BITMIME\r\n'
reply: retcode (250); Msg: mail.example.org
VRFY
ETRN
STARTTLS
ENHANCEDSTATUSCODES
8BITMIME
(250, 'mail.example.org\nVRFY\nETRN\nSTARTTLS\nENHANCEDSTATUSCODES\n8BITMIME')

On trouve d'ailleurs des mises en œuvre de SMTP pour tous les langages de programmation, pour Emacs Lisp, pour Haskell...

En théorie, le serveur SMTP ne devrait pas du tout toucher au message qu'il convoie. Mais il existe quelques exceptions. Par exemple, la section 3.7.2 couvre le cas des en-têtes Received: dans le message (également discutés en section 4.4). Très utiles au débogage, ceux-ci doivent être ajoutés par chaque serveur SMTP qui a relayé le message. Pour le premier exemple ci-dessus, l'en-tête Received: ressemblera à :


Received: from bortzmeyer.nic.fr (batilda.nic.fr [192.134.4.69])
        by relay1.nic.fr (Postfix) with ESMTP id 92859A1D95D
        for <stephane@bortzmeyer.org>; Sun, 28 Sep 2008 03:56:11 +0200 (CEST)

Enfin, la section 4.1 décrit une par une toutes les commandes SMTP et leur syntaxe. La section 4.2 décrit, elle, les réponses. Composées de trois chiffres, le premier indique si la réponse est positive, négative ou incomplète (ainsi, 2xy indique que le serveur qui répond est satisfait, 5xy qu'il ne l'est pas et 4xy qu'il y a eu un problème temporaire). Le second chiffre, lui, indique le genre de la réponse : x0z pour ce qui concerne la syntaxe, x2z pour le réseau, etc. On peut donc en déduire que 421 signifie un problème temporaire avec le réseau, forçant à fermer la connexion (section 3.8).

Tout cela est bien beau, mais cela ne fait que spécifier le dialogue avec un serveur distant qu'on a déjà trouvé. Et comment le trouver ? Si je suis un MTA et que je veux transmettre un message envoyé à postmaster@gmail.com, comment est-ce que je trouve l'adresse du ou des serveurs responsables de gmail.com ? Si on refaisait SMTP en partant de zéro aujourd'hui, j'utiliserai sans doute les enregistrements SRV du RFC 2782. Mais le courrier électronique a été normalisé longtemps avant ce RFC et il utilise donc une sorte d'enregistrements SRV spécifique, les enregistrements MX. Le MTA regarde donc dans le DNS les MX de gmail.com :

% dig MX gmail.com.
gmail.com.		3600	IN	MX	5 gmail-smtp-in.l.google.com.
gmail.com.		3600	IN	MX	10 alt1.gmail-smtp-in.l.google.com.
...

et sait donc qu'il doit contacter gmail-smtp-in.l.google.com. La section 5 du RFC est consacrée à ce mécanisme.

Que faire s'il n'y a pas d'enregistrement MX ? La question a toujours été chaudement discutée chez les passionnés de SMTP, mais particulièrement lors de la rédaction de ce RFC 5321. En effet, l'ancienne règle (section 5 du RFC 2821) était qu'on utilisait, s'il était présent, un enregistrement A (une adresse IPv4), qualifié de « MX implicite ». Ce mécanisme est très critiqué : les domaines ont souvent un enregistrement A pour le Web (afin de pouvoir taper http://example.net/ et pas seulement http://www.example.net/) et la machine qu'il indique n'a pas forcément de serveur de courrier. En outre, que faut-il faire s'il n'y a pas d'enregistrement A mais un AAAA (une adresse IPv6) ? Notre RFC s'éloigne donc du RFC 2821 ici et décide de garder l'ancienne convention du MX implicite (au nom de la continuité), en l'étendant à IPv6 (voir la discussion en section 5.2). Les termes de « A RR » (A resource record, enregistrement de type A) ont ainsi disparus au profit de address RR qui regroupe A et AAAA.

On note qu'il n'existe pas de moyen normalisé de dire « Je ne veux pas recevoir de courrier » ; ne pas avoir de MX ne suffit pas, en raison de la règle maintenue d'un MX implicite ; la méthode la plus courante, mais non standard, est de publier un MX délibérement invalide, pointant par exemple vers . (la racine) ou vers localhost.

Notons que la section 5 précise qu'un émetteur SMTP doit essayer d'envoyer à toutes les adresses IP, pas uniquement à tous les MX (un serveur peut avoir plusieurs adresses).

La section 6 est consacrée aux problèmes et à tout ce qui peut aller mal. Par exemple, la sous-section 6.4 parle des rapports avec les implémentations qui violent la norme. Elles sont très nombreuses (historiquement, Lotus Notes semble avoir la médaille des problèmes). Depuis que le courrier existe, il y a des polémiques entre les « éradicateurs » qui demandent que les serveurs SMTP refusent de compenser ces violations et stoppent tout dialogue avec les logiciels trop bogués et les « conciliateurs » qui, après avoir fait trois génuflexions vers la statue de Jon Postel et cité son « principe de robustesse » (« Be conservative in what you send and liberal in what you accept »), demandent qu'on essaie malgré tout de parler avec les programmes ratés. Le problème est d'autant plus difficile que tous les développeurs ne sont pas égaux : on peut difficilement refuser de parler aux serveurs de messagerie d'AOL, quelles que soient les curieuses pratiques qu'ils utilisent. Même chose avec des logiciels très répandus comme Microsoft Exchange.

Une autre partie du problème est que certains MUA ont des capacités limitées et qu'on ne peut pas trop exiger d'eux. Ainsi, les serveurs SMTP ont pris l'habitude de réparer les messages, en rectifiant par exemple les champs Date: invalides (une bogue très fréquente). Ces réparations devraient, dit le RFC, être limitées aux clients locaux, que l'on connait, et ne pas s'étendre aux machines d'autres domaines. Cette approche est cohérente avec le RFC 6409 (qui sépare la soumission d'un message depuis un MUA vers le premier MTA, de l'envoi d'un message entre MTA) mais avec certains logiciels, comme Postfix, elle ne peut pas être configurée.

Toute aussi brûlante est la question de la sécurité du courrier électronique, qui fait l'objet de la section 7. D'abord (section 7.1), il y a le problème de l'authentification : un serveur SMTP peut toujours prétendre que le courrier vient de pape@nic.va, il n'y a aucun moyen de vérifier. (De très nombreux projets ont visé à traiter ce problème, voir par exemple les RFC 7208 et RFC 6376 mais il est bien plus compliqué qu'il n'en a l'air, notamment parce qu'il n'existe pas de système d'identité international et reconnu.) Le RFC recommande donc d'authentifier ses messages, par exemple avec le RFC 4880.

La section 7.9, elle, couvre les questions opérationnelles liées à la sécurité. Par exemple, certains fournisseurs de courrier (notamment AOL, qui s'en vante bruyamment), refusent le courrier de certains sites, sur des critères décidés unilatéralement et sans prévenir leurs propres utilisateurs. D'une certaine façon, c'est compréhensible, puisque l'ampleur du spam nécessite des mesures souvent radicales. Mais cela peut, si on poursuit cette logique, mener à un système de courrier qui serait réservé à un oligopole de quelques fournisseurs qui s'acceptent entre eux (le projet du MAAWG).

C'est la même section qui mentionne les relais ouverts, en des termes étonnamment prudents (la pratique générale est de les supprimer). Comme autre exemple de code Python pour faire du SMTP, voici un programme pour tester si un serveur est un relais ouvert.

Ce RFC ne marque guère de changements par rapport à son prédécesseur, le RFC 2821. Le but principal était de le faire avancer sur le chemin des normes, vers son nouveau statut de « Projet de norme ». Les changements ? Eh bien, le principal étant l'extension du « MX implicite » à IPv6.

Ce RFC a été longtemps retardé par une amusante et exaspérante « querelle des exemples » et a même fait l'objet d'un appel contre l'obstruction de l'IESG. Celle-ci estimait en effet que le RFC aurait dû utiliser, pour ses exemples, uniquement les noms de domaines du RFC 2606, malgré le fait que le RFC 2821 aie déjà utilisé des noms comme isi.edu (l'université de Jon Postel) ou generic.com depuis des années.

Des propositions d'architectures radicalement nouvelles, en général fondées sur un modèle où le récepteur « tire », comme avec Atom, plutôt que sur le modèle traditionnel du courrier où l'expéditeur « pousse » ont déjà été faites, par exemple par Dan Bernstein ou par Wietse Venema mais n'ont jamais débouché sur des protocoles finalisés, et encore moins sur des implémentations. Ces propositions visent en général à traiter le problème du spam en forçant l'expéditeur à garder le message chez lui, jusqu'au moment de la récupération par le destinataire. Cela résoudrait la question du stockage du spam, mais pas du tout celle de son traitement puisqu'il faut bien notifier le destinataire qu'il a un message, et qu'il doit bien le récupérer pour décider si c'est du spam ou pas.


Téléchargez le RFC 5321


L'article seul

RFC 5352: Aggregate Server Access Protocol (ASAP)

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : R. Stewart, Q. Xie, M. Stillman (Nokia), M. Tuexen (Muenster University of Applied Sciences)
Expérimental
Réalisé dans le cadre du groupe de travail IETF rserpool
Première rédaction de cet article le 30 septembre 2008


Membre de la famille Rserpool (décrite dans le RFC 5351, ASAP (Aggregate Server Access Protocol) est le protocole de communication entre un client (le PU, pour Pool User) et le serveur ENRP (RFC 5353), ainsi qu'entre un élément du groupe de serveurs d'application (le PE pour Pool Element) et le serveur ENRP. ASAP permet aux PE de s'enregistrer auprès du serveur ENRP et aux PU de trouver l'adresse d'un PE avec lequel ils vont travailler.

Le groupe de serveurs de l'application, le pool, est identifié par un handle nommé PH (pool handle). ASAP permettra de résoudre cet handle en une ou plusieurs adresses IP. Le fait d'interposer cet intermédiaire entre le client et le serveur de l'application permet d'assurer des fonctions de répartition de charge ou de résistance aux pannes. Comme le rappelle la section 1.3, un handle n'a qu'une signification locale à une organisation, il ne prétend pas être unique pour tout l'Internet.

Les deux fonctions essentielles d'ASAP sont donc :

  • Pour un PE, un des serveurs de l'application, de signaler sa disponibilité (message ASAP_REGISTRATION, section 2.2.1),
  • Pour un PU, un client final, de trouver l'adresse IP d'un ou plusieurs serveurs du groupe, afin de le contacter (message ASAP_HANDLE_RESOLUTION, section 2.2.5).

ENRP, quant à lui (RFC 5353), est utilisé entre les serveurs ENRP, pour assurer leur synchronisation.

Une façon simple de décrire ce que fournit ASAP est de lire la section 6 qui décrit, en pseudo-code, les primitives d'ASAP. Par exemple, l'enregistrement d'un serveur dans le groupe est (section 6.1) :

         
Format: registration.request(poolHandle,
                             User Transport parameter(s))

La section 2 détaille le format des messages que portera ASAP. Le format de base est défini dans le RFC 5354. Ainsi, ASAP_REGISTRATION (section 2.2.1) porte le handle du groupe que le PE veut rejoindre. La réponse, ASAP_REGISTRATION_RESPONSE (section 2.2.3) comprendra un champ Reject qui, mis à 1, indiquera l'échec éventuel (un 0 signifiant le succès).

L'autre message important est ASAP_HANDLE_RESOLUTION (section 2.2.5) et sa réponse, ASAP_HANDLE_RESOLUTION_RESPONSE. Le premier permet de résoudre un handle en une adresse IP (ou une liste d'adresses IP, pour donner du choix au client, et lui permettre d'essayer d'autres serveurs en cas de défaillance, voir par exemple la section 6.8.1 et le RFC 5356).

Le principal protocole de transport utilisé par ASAP (sections 2.1 et 5) n'est pas TCP mais SCTP (RFC 4960), entre autres parce qu'il fournit déjà une certaine résistance aux pannes (plusieurs adresses IP peuvent être utilisées pour la même association). Le port par défaut est 3863 (3864 avec TLS). Notons qu'ASAP n'est pas purement requête-réponse : le serveur ENRP peut envoyer des messages non sollicités, par exemple si un pool change.

Il existe une implémentation d'ASAP en logiciel libre dans rsplib.


Téléchargez le RFC 5352


L'article seul

RFC 5351: An Overview of Reliable Server Pooling Protocols

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : P. Lei (Cisco), L. Ong (Ciena), M. Tuexen (Muenster University of Applied Sciences) , T. Dreibholz (University of Duisburg-Essen)
Pour information
Réalisé dans le cadre du groupe de travail IETF rserpool
Première rédaction de cet article le 30 septembre 2008


Il existe de très nombreux cas où une application cliente peut utiliser plusieurs serveurs parmi un groupe (le pool). L'idée de la suite de protocoles Reliable Server Pooling ( RSerPool) est de fournir un moyen standard de faire ce choix. Ce RFC explique les concepts de base de ce protocole, normalisé dans d'autres RFC.

La section 1 du RFC résume les raisons pour lesquelles on veut disposer d'un groupe, un pool, de serveurs plutôt que d'un serveur unique, par exemple, pour atteindre des objectifs de haute disponibilité ou de répartition de charge. Les nouveaux protocoles devront fournir notamment les services suivants :

  • indépendance par rapport à l'application,
  • liaison directe entre le client et le serveur, sans machine intermédiaire,
  • séparation des fonctions de disponibilité et de changement en cas de panne, des fonctions propres à l'application.

Comment sont structurés les protocoles de la famille RSerPool ? (Le cahier des charges était le RFC 3237 et prévoyait un protocole relativement léger, interne à un domaine administratif, moins ambitieux, donc, que les grilles.) Le groupe (pool) a un identificateur, le PH (Pool Handle). Les serveurs du groupe se nomment les PE (Pool Element). Chaque PE s'enregistre auprès d'un serveur ENRP (Endpoint haNdlespace Redundancy Protocol) en utilisant le protocole ASAP (Aggregate Server Access Protocol), décrit dans le RFC 5352. Le client se nomme, lui, le PU (Pool User). Il utilise également ASAP pour parler au serveur ENRP, obtenant ainsi la correspondance entre le PH et l'adresse IP du serveur effectif. Le PU parlera ensuite directement au PE, utilisant un protocole spécifique à l'application. Enfin, le serveur ENRP peut se synchroniser avec d'autres serveurs ENRP (RFC 5353) pour fournir également un service à haute disponibilité.

Ces protocoles sont décrits dans différents RFC, le RFC 5352 pour ASAP, le RFC 5353 pour ENRP, le RFC 5354 pour le format des paramètres, le RFC 5356 pour les politiques de sélection des serveurs et le RFC 5355 pour l'analyse des risques de sécurité.

La section 2 décrit ASAP (Aggregate Server Access Protocol), le protocole de communication entre le PU et le serveur ENRP, ainsi qu'entre ce dernier et les PE, les membres du groupe. ASAP est normalisé dans le RFC 5352. Il permet aux PE de s'enregistrer auprès du serveur ENRP (section 2.2) et au PU d'obtenir l'adresse d'un membre du groupe (section 2.3). Dès qu'un PE s'enregistre sous un identificateur de groupe (un PH), ce groupe existe et, lorsque le dernier PE se désenregistre, le groupe disparait (section 2.1).

Comme la communication entre le PU, le client et le PE, le serveur, est directe (ce qui permet au protocole d'être indépendant de l'application), il n'y a pas d'état et il peut donc être difficile de passer d'un PE à un autre en cas de panne, le nouveau PE ne se souvenant pas du contexte de l'application. La famille de protocoles RSerPool fournit donc quelques mécanismes limités pour conserver un état (section 2.5). Ainsi, la section 2.5.1 permet un système de petits gâteaux, envoyés par le PE au PU et que celui-ci doit renvoyer lorsqu'il change de PE, permettant ainsi de garder trace de l'état de l'application.

La section 3 décrit ENRP, Endpoint haNdlespace Redundancy Protocol, le protocole de communication entre les serveurs ENRP. Ce protocole, normalisé dans le RFC 5353, permet aux serveurs ENRP d'un domaine de se synchroniser et de garder trace des PE enregistrés dans tel ou tel groupe.

La section 4, enfin, donne des exemples d'usage de la famille RSerPool. L'exemple de la section 4.1 est relativement simple, RSerPool y est utilisé pour sélectionner un serveur. La résolution d'un PH en adresse IP d'un serveur est donc le seul service invoqué. Cette section décrit les modifications nécessaires au code source de l'application :

  • Spécifier un PH (identificateur de groupe) au lieu d'un nom (ou d'une adresse IP),
  • Au lieu d'utiliser la fonction classique de résolution de nom, getaddrinfo, utiliser une fonction RSerPool de résolution,

À noter qu'il n'existe pas d'API standard pour les protocoles de la famille RSerPool. À noter également que, dans un exemple aussi simple, RSerPool n'était pas forcément nécessaire, les enregistrements DNS SRV du RFC 2782 auraient suffi.

L'exemple de la section 4.2 est plus complexe, faisant appel à toutes les fonctions de RSerPool, y compris pour la transmission de données entre le client, le PU et le serveur, le PE.

Il existe au moins une mise en œuvre de RSerPool. Elle est disponible en http://tdrwww.iem.uni-due.de/dreibholz/rserpool/. Elle est décrite dans la thèse Reliable Server Pooling -- Evaluation, Optimization and Extension of a Novel IETF Architecture. La page de l'auteur contient beaucoup d'autres informations sur la famille Rserpool.


Téléchargez le RFC 5351


L'article seul

RFC 5353: Endpoint Handlespace Redundancy Protocol (ENRP)

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : Q. Xie, R. Stewart, M. Stillman (Nokia), M. Tuexen (Muenster Univ. of Applied Sciences), A. Silverton (Motorola)
Expérimental
Réalisé dans le cadre du groupe de travail IETF rserpool
Première rédaction de cet article le 30 septembre 2008


Complétant la série des RFC sur la famille de protocoles Rserpool, famille dont le cahier des charges était le RFC 3237, ce document normalise le protocole ENRP (Endpoint Handlespace Redundancy Protocol) qui est le protocole utilisé entre les serveurs qui font la traduction des identifiants, les handles, en adresses IP.

Rappelons brièvement le fonctionnement de Rserpool (le RFC 5351 fournit une description plus détaillée) : un client, le PU (Pool User) veut accéder aux services fournis par un groupe (pool) de serveurs d'application, les PE (Pool Elements). Le client ne connait que l'identifiant du groupe, le PH (Pool Handle). Pour le traduire en adresses IP, le client utilise le protocole ASAP (RFC 5352) pour demander aux serveurs ENRP cette traduction. Les PE utilisent également ASAP pour s'enregistrer auprès des serveurs ENRP. Et comment les serveurs ENRP se synchronisent-ils ? Avec le protocole ENRP de notre RFC 5353. Grâce à lui, les serveurs ENRP forment un registre distribué et résistant aux pannes.

Notons qu'ENRP n'est conçu que pour fonctionner au sein d'un même domaine administratif, où toutes les machines sont configurées par la même équipe et peuvent donc, après authentification forte, se faire confiance (la section 6 détaille ces exigences de sécurité et impose TLS avec authentification réciproque). La conception d'un tel protocole pour l'Internet entier est encore un défi.

C'est la section 3 qui décrit le fonctionnement du protocole. Au démarrage, un serveur ENRP doit (section 3.2) générer son identifiant ENRP (un entier de 32 bits), trouver un mentor, le pair qui lui donnera les autres informations (la section 3.2.21 explique comment), obtenir la liste de ses pairs (et la garder à jour, cf. section 3.4) puis les tenir au courant des enregistrements/départs de PE (section 3.3) qu'il voit (chaque PE ne parle qu'à un serveur ENRP, son home server).

La section 3.5 détaille la procédure plus compliquée de remplacement (take over), qui permet à un pair de remplacer un pair en panne et de signaler aux PE (via le protocole ASAP) qu'ils doivent changer leur serveur ENRP.

La section 2 du RFC décrit les messages ENRP (s'appuyant sur la base fournie par le RFC 5354). Par exemple, ENRP_PRESENCE (section 2.1) permet à un serveur ENRP d'annoncer à un de ses pairs ENRP qu'il est toujours là. ENRP_HANDLE_TABLE_REQUEST (section 2.2) est utilisé lorsqu'un pair ENRP rejoint les autres et réclame une copie complète de la table des handles et des adresses IP associées. ENRP_HANDLE_UPDATE (section 2.4) servira ensuite aux mises à jour, au fur et à mesure que des PE s'enregistreront ou bien partiront.

ENRP_LIST_REQUEST (section 2.5) est également utilisé à l'initialisation d'un pair ENRP : il lui permet de demander une liste des pairs ENRP actuellement actifs.

Il existe au moins une mise en œuvre d'ENRP dans http://tdrwww.iem.uni-due.de/dreibholz/rserpool/.


Téléchargez le RFC 5353


L'article seul

ISO 5218, une norme indispensable

Première rédaction de cet article le 28 septembre 2008


L'ISO ne laisse rien au hasard et aux choix individuels. Comme son nom l'indique, elle normalise. C'est ainsi qu'il existe une norme « Représentation des sexes humains », la 5218.

Le texte est une des très rares normes ISO à être publiquement disponible, en http://standards.iso.org/ittf/PubliclyAvailableStandards/c036266_ISO_IEC_5218_2004(E_F).zip. Il fait 24 pages serrées, qui, en retirant les avertissements juridiques et le délayage, se résument à :

Data elements  Code
Not known      0 (zero)
Male           1 (one)
Female         2 (two)
Not applicable 9 (nine)

Donc, on sait désormais que les hommes sont représentés par Un et les femmes par Deux (convention qui avait déjà été adoptée dans des systèmes comme le NIR).

Notons quand même cet avertissement, qui prouve que l'ISO pense à tout : No significance is to be placed upon the fact that "Male" is coded "1" and "Female" is coded "2". This standard was developed based upon predominant practices of the countries involved and does not convey any meaning of importance, ranking or any other basis that could imply discrimination. .

Et pour ceux qui ont aimé, voici une discussion surréaliste sur la liste PostgreSQL, sur le même sujet (comment représenter le genre dans une base de données) : http://www.mail-archive.com/pgsql-general@postgresql.org/msg89107.html. La proposition que j'ai préférée était celle d'utiliser 1 pour les hommes et 0 pour les femmes, méthode qui a l'avantage d'être auto-documentée (regardez la forme du chiffre, si vous n'avez pas compris). Et, bien sûr, si on utilise une base de données qui accepte l'Unicode, on peut mettre directement les caractères U+2642 (♂) et U+2640 (♀)...


L'article seul

Geoff Huston et le futur marché des adresses IPv4

Première rédaction de cet article le 26 septembre 2008


Geoff Huston est l'auteur de nombreuses études sur l'épuisement prochain des adresses IPv4. Ces études ont contribué à la prise de conscience du fait qu'il ne restait plus que deux ou trois ans avant l'allocation de la dernière adresse. Dans un article récemment publié, The Changing Foundation of the Internet: Confronting IPv4 Address Exhaustion, Huston se demande ce qui se passera après.

Huston commence par revenir sur l'état actuel de la transition vers IPv6 : elle est à peine commencée. L'épuisement des adresses IPv4 ne peut donc plus désormais être évitée. Même si tout le monde s'affolait enfin et déployait IPv6 en urgence, il serait trop tard.

À propos de cette transition, d'ailleurs, l'auteur tord le coup à la légende comme quoi l'IETF aurait été insouciante en ne prévoyant pas de plan de déploiement d'IPv6. Il y en avait bien un : le dual stack où, pendant la transition, chaque machine aurait eu deux adresses, une v4 et une v6. Il était décrit à l'origine dans le RFC 1933 en avril 1996, il y a douze ans (aujourd'hui, RFC 4213, section 2). Mais il n'a pas marché.

Huston analyse ensuite les raisons de cet échec, largement dû à la dérégulation qui a créé un marché très atomisé où aucune décision collective n'était possible « A more likely explanation for the current situation is an inability of a highly competitive deregulated industry to be in a position to factor in longer term requirements into short term business logistics. ».

Bref, nous sommes maintenant proches du mur et n'avons plus le temps de freiner. Que se passera t-il ensuite ? Huston considère qu'il y aura forcément un marché des adresses IP. « A more likely scenario is that addresses will change hands in exchange for money. ». Il ne fait pas preuve d'un grand enthousiasme pour cette solution (au contraire de certains adorateurs du marché comme Milton Mueller dans Scarcity in IP addresses: IPv4 Address Transfer Markets and the Regional Internet Address Registries) mais il la pense inévitable.

Et il appelle à l'organiser « The corollary of this approach is the use of markets to perform the address distribution function, creating a natural pricing function based on levels of address supply and demand. ».

Joli article qui part d'un échec du marché pour arriver à la conclusion qu'il faut créer un nouveau marché...

Un autre article très détaillé sur le sujet, et assez partagé sur la question du marché, est Running on Empty: the challenge of managing Internet addresses de Lehr, Vest et Lear. Sinon, on peut noter dans le dernier numéro des Enjeux / Les Échos un dossier « Pénuries », où on trouve, outre le pétrole, l'eau et l'uranium... les adresses IP (avec, chose étonnante, uniquement des informations exactes). Ça, c'est un signe des temps.


L'article seul

Stack Overflow, un site de Q&A pour programmeurs

Première rédaction de cet article le 26 septembre 2008
Dernière mise à jour le 5 juin 2009


Joel Spolsky a annoncé le 15 septembre le lancement de Stack Overflow, un très intéressant site Web de questions & réponses pour programmeurs, avec système de réputation.

À l'usage, Stack Overflow s'avère très riche en information de qualité. Le principe est que toute personne qui veut écrire doit s'authentifier (les simples lecteurs peuvent être anonymes) et que les actions de cette personne (poser une question, proposer une réponse) lui vaudront petit à petit une réputation, déterminée par les votes des autres utilisateurs. Stack Overflow rejoint donc la grande famille des réseaux sociaux.

Les réponses aux questions sont classées, non pas dans l'ordre chronologique comme sur un blog mais dans l'ordre décroissant des votes, ce qui permet à l'information la plus reconnue d'émerger hors du bruit.

Pour ceux que ça intéresse, ma réputation est aujourd'hui de 2169 ce qui me permet, par exemple, d'éditer les messages des autres, ou de voter contre une contribution (il faut une réputation de 15 pour voter pour).

Stack Overflow permet d'afficher sa réputation sur son site, pour frimer. Je n'ai pas encore osé le faire sur l'ensemble de mon blog (non, en fait, la vraie raison est qu'il y a une mauvaise interaction entre l'HTML de Stack Overflow et celui de mon blog).

Comment se fait l'authentification ? Il faut s'enregistrer ? Non, pas du tout, la seule authentification utilisée est OpenID (donc, http://www.bortzmeyer.org/ pour moi). Une excellente idée qui permet d'éviter de se créer encore un compte de plus.

Parmi les questions, on note que les langages couramment utilisées sur Windows comme Java ou Visual Basic se taillent la part du lion. Pour le programmeur Unix, lire les questions sur la page d'accueil n'est donc pas passionnant mais Stack Overflow permet d'étiquetter les questions et chercher ensuite selon ces étiquettes. Ainsi, http://stackoverflow.com/questions/tagged/elisp donnera accès aux questions sur Emacs Lisp et http://stackoverflow.com/questions/tagged/haskell aux questions sur Haskell.

Stack Overflow contient déjà énormément d'informations de qualité, ce qui semble indiquer que le système fonctionne. Quelques bons exemples, sur des questions assez pratiques :

Et sur des questions plus conceptuelles, moins susceptibles de recevoir une réponse simple et univoque :

Les données de Stack Overflow sont désormais publiques, ce qui permet en outre de lancer plein d'analyses sur le fonctionnement du site.

Stack Overflow a désormais un site frère pour l'administration systèmes et réseaux, Server Fault.

Le meilleur article sur Stack Overflow est « Anthropology: The Art of Building a Successful Social Site ». À lire absolument pour voir tout ce qui fait la réussite de Stack Overflow.


L'article seul

RFC 2681: A Round-trip Delay Metric for IPPM

Date de publication du RFC : Septembre 1999
Auteur(s) du RFC : Guy Almes (Advanced Network & Services, Inc.), Sunil Kalidindi (Advanced Network & Services, Inc.), Matthew J. Zekauskas (Advanced Network & Services, Inc.)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 25 septembre 2008


Les mesures de performances sur l'Internet sont un sujet passionnant mais complexe. Comme il faut bien commencer par définir précisement ce qu'on mesure, ce RFC ne spécifie pas un protocole mais uniquement une métrique, une grandeur qu'on veut mesurer et qui doit faire l'objet d'une définition rigoureuse. Cette métrique est le temps d'aller-retour (RTT) d'un paquet IP.

Cette mesure du RTT est connue grâce à l'outil ping. Mais ping a, entre autres défauts, celui de ne pas reposer sur une métrique rigoureuse, ce qui rend souvent difficile de savoir ce qu'il mesure exactement. Notre RFC s'attache donc à une définition précise d'une telle métrique. Il s'appuie pour cela sur le cadre et les définitions du RFC 2330, et suit de près le RFC 2679, qui décrivait une telle métrique pour les allers simples.

La section 1.1 du RFC commence par expliquer pourquoi une telle métrique est utile : notamment parce que certaines applications, notamment les plus interactives, fonctionnent mal si le RTT est trop élevé, que sa valeur minimale donne une idée des caractéristiques intrinsèques du lien et que des augmentations de ce RTT peuvent indiquer une congestion du lien. Elle est donc pertinente dans beaucoup de cas.

Mais pourquoi, continue cette section 1.1, mesurer le temps d'aller-retour et pas seulement celui d'aller simple comme le fait le RFC 2679 ? En effet, le RTT a plusieurs défauts : en cas de routage asymétrique, le temps de parcours aller peut être très différent du temps retour (et le RTT ne permet pas de voir cette différence). Même chose si des mécanismes divers (par exemple l'asymétrie des débits en ADSL) font qu'une direction a des caractéristiques très différentes d'une autre. C'est vrai, mais le RTT a aussi des avantages, notamment le fait qu'il est beaucoup plus facile à mesurer que l'aller simple, puisqu'il ne nécessite pas que les horloges des deux machines soient synchronisées (c'est sur ce principe que fonctionne ping).

Les lecteurs étant désormais convaincus de l'intérêt de cette métrique, la section 2 passe donc à sa définition : baptisée du nom scientifique de Type-P-Round-trip-delay, le temps d'aller-retour a pour paramètre les adresses IP de la source et de la destination, le temps T de la mesure, pour unité la seconde et pour définition (section 2.4) le délai entre la mise du premier bit de la question sur le câble et la réception du dernier bit de la réponse. Type-P signifie simplement qu'il peut dépendre du type du paquet (par exemple TCP vs. UDP, ou bien le numéro de port, tout ce qui fait qu'un routeur peut traiter ce paquet rapidement ou pas). Ainsi, les mesures de ping ont pour Type-P « ICMP avec des paquets echo ». Ce terme de Type-P est défini dans la section 13 du RFC 2330.

Cette définition est donc très simple sur le papier. En pratique, elle pose quelques problèmes, signalés par la section 2.5 : le temps T de la mesure dépend, lui, d'une bonne synchronisation des horloges, la définition n'indique pas à partir de quand on renonce à attendre un paquet perdu (le résultat de la mesure est alors indéfini), etc.

Ce n'est pas tout : même lorsque la métrique est parfaite, les ordinateurs sont des machines physiques ayant plein de limitations, qui limitent la précision de la mesure. Il est symptomatique du mauvais état de la métrologie sur Internet qu'on voit souvent citer des résultats sans indiquer les marges d'erreur ou d'incertitude. La section 2.7 cite certaines de leurs causes :

  • Les faiblesses des horloges (section 2.7.1) sont à prendre en compte. Si la mesure du RTT ne nécessite pas de synchronisation de celles-ci (sauf pour déterminer le temps T de la mesure), elle demande par contre un peu de stabilité. Une dérive (skew) très forte ou, plus probable, un changement brusque de l'heure par l'opérateur ou par un logiciel peut fausser un résultat. De même, la résolution des horloges peut être trop mauvaise pour la rapidité des réseaux modernes.
  • La définition du RTT est lié au concept de « mise sur le câble » des bits (section 2.7.2). Un programme typique n'a pas accès à l'information sur l'instant exact où le bit est envoyé. Le temps qu'il mesure est celui de la machine, pas celui de la carte réseau. (Mon programme echoping, qui mesure le RTT, n'essaie même pas de déterminer ce wire time, je ne pense pas qu'il existe une méthode portable sur Unix pour cela.)
  • Le temps de réaction de la machine visée est souvent difficile à prédire (section 2.7.3). Les routeurs Cisco, par exemple, ne génèrent pas la réponse aux paquets ICMP echo sur la carte (fast path) mais dans leur processeur généraliste, bien plus lent. Avec de telles machines, le temps mesuré par ping est largement dominé par le temps de réponse du routeur et pas par le réseau proprement dit. Sur une machine Unix, ICMP est mis en œuvre dans le noyau, ce qui fournit certaines garanties, notamment que le swapping n'interviendra pas. Mais cela ne garantit pas, par exemple, qu'une surcharge du processeur de la machine ne va pas ajouter un délai inattendu. Si le Type-P est TCP avec le port 80, comme HTTP est typiquement mis en œuvre en mode utilisateur, les incertitudes sont bien plus grandes (swapping, temps de réponse de l'application - par exemple Apache, ...)

Une fois ces problèmes surmontés, il faut indiquer à l'utilisateur le résultat des mesures. C'est l'objet de la section 2.8 qui insiste sur la nécessité de transmettre au dit utilisateur toutes les informations permettant d'interpréter les données : le Type-P (pour echoping, il faut utiliser l'option -v et encore, l'affichage du Type-P n'est pas vraiment clair), la façon dont une réponse en retard est considérée comme perdue, les résultats de l'étalonnage et le chemin suivi par les paquets (à noter que cette information n'est en général pas accessible au programme de mesure, à part éventuellement l'interface réseau de sortie).

Une fois cette première métrique établie, le RFC, dans sa section 3, définit un échantillonage de cette mesure, selon une distribution de Poisson. Cette seconde métrique, définie de 3.1 à 3.4, a deux paramètres supplémentaires, le temps de fin de la mesure et le taux d'envoi des paquets (le lambda de la distribution de Poisson).

La section 3.5 discute du choix du paramètre lambda, en citant le RFC 2330. En gros, comme il s'agit d'une mesure active, plus lambda est élevé et plus la mesure est précise, mais plus on a perturbé le réseau avec tous ces paquets de test.

Munis de cette deuxième métrique, le RFC cite quelques statistiques intéressantes (section 4) qui peuvent être obtenues :

  • Le Xème centile (section 4.1), c'est-à-dire la valeur du RTT pour laquelle X % des mesures tombent en dessous. Ainsi, le 90ème centile est la valeur du RTT telle que 90 % des mesures donnaient une RTT plus faible. Le 50ème centile est presque équivalent à la médiane, décrite en section 4.2.
  • Le délai d'aller-retour minimum (section 4.3) qui reflète le cas idéal (réseau peu ou pas chargé, machine distante peu ou pas chargée et qui répond donc aux mieux de ses capacités).

Enfin, la section 5 est consacrée aux questions de sécurité. Comme toutes les mesures actives, celles du RTT doivent garder à l'esprit la nécessité de ne pas surcharger le réseau (ne pas utiliser l'option -f de ping). Mais ce point concerne la sécurité du réseau vis-à-vis des mesures. Il y a aussi un problème de sécurité des mesures vis-à-vis du réseau. En effet, les équipements sur le trajet peuvent fausser la mesure en retardant ou en donnant la priorité à certaines paquets. En cas de mesure d'un réseau franchement hostile, il peut être nécessaire de recourir à des techniques cryptographiques pour préserver l'intégrité des mesures.

Un protocole utilisant cette métrique a été normalisé, TWAMP (RFC 5357).


Téléchargez le RFC 2681


L'article seul

RFC 5348: TCP Friendly Rate Control (TFRC): Protocol Specification

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : M. Handley, S. Floyd (ICIR), J. Padhye (Microsoft), J. Widmer (University of Mannheim)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dccp
Première rédaction de cet article le 25 septembre 2008


Tout protocole sur Internet doit gérer la congestion et réagir proprement à celle-ci, sans aggraver le problème par un comportement égoïste. Si ce protocole fonctionne sur TCP, c'est fait automatiquement pour lui. Mais s'il fonctionne sur des protocoles sans notion de connexion, comme UDP, c'est plus complexe. Ce RFC spécifie un mécanisme que les protocoles peuvent utiliser pour assurer un contrôle de congestion compatible avec celui de TCP. Il s'applique aussi bien aux protocoles de la couche transport comme DCCP qu'aux protocoles de la couche application, si la couche transport ne fournit pas de contrôle de congestion.

Il est difficile de demander à chaque application de faire ce contrôle, qui est très complexe. Celles utilisant TCP ou bien DCCP (RFC 4340) voient ce contrôle fait automatiquement pour elles. Le protocole de notre RFC 5348, TFRC, peut être utilisé par DCCP, son principal client (RFC 4342), ou bien par une application utilisant UDP (section 1 du RFC). TFRC n'est d'ailleurs pas un protocole complet, spécifié dans les moindres détails, puisque certains points dépendent du protocole qui l'utilise (le RFC 4342 donne un exemple d'utilisation de TFRC).

Le nom de TFRC vient de son désir d'être « civil » envers TCP lorsqu'un flot de données TCP et un flot de données DCCP sont en compétition sur le même câble. Normalement, chacun des deux flots doit obtenir une part à peu près égale de la capacité disponible. (Un protocole « incivil » enverrait le plus de paquets possible, sans ralentir, malgré la congestion.)

TFRC met en œuvre ses mécanismes chez le récepteur des données (sections 3, 5 et 6). Celui-ci mesure le pourcentage de données perdues et en informe l'émetteur (par des paquets décrits en section 3.2.2), qui devra alors ralentir l'envoi (pour calculer le ralentissement nécessaire, l'émetteur dispose également du RTT, qu'il a mesuré à cette occasion). L'équation exacte est donnée dans la section 3.1 et est très proche de celle dite Reno.

Le contrôle de congestion est un problème complexe, très mathématique, et qui mène facilement à des textes longs, comme ce RFC. Les nombreuses formules qu'il contient sont d'autant plus difficile à lire que, comme tout RFC, il est en texte brut.

La section 4 décrit plus en détail ce que doit faire l'émetteur, notamment s'il ne reçoit pas les paquets d'information du récepteur (l'émetteur doit alors diviser son débit par deux, mesure drastique justifiée par le fait que, si aucun paquet d'information ne passe, c'est probablement que la congestion est sévère).

Notons qu'une variante de TFRC fonctionne avec des mesures du taux de perte de paquets faites par l'émetteur et pas par le récepteur. Elle est décrite en section 7.

TFRC avait été normalisé à ses débuts dans le RFC 3448. La section 9 résume les changements, peu importants. Le principal est que, dans l'ancien RFC, l'émetteur était tenu par le taux d'envoi que lui imposait le récepteur. Si l'émetteur envoyait peu, parce qu'il n'avait pas grand'chose à dire (data limited), le récepteur lui retournait un taux d'envoi faible. Ce problème a été traité.


Téléchargez le RFC 5348


L'article seul

Remplacement automatisé de caractères en Emacs

Première rédaction de cet article le 18 septembre 2008
Dernière mise à jour le 19 septembre 2008


Un petit exercice de programmation en Emacs Lisp. Comment remplacer facilement un ensemble de caractères par un autre ?

Beaucoup de pages Web aujourd'hui utilisent tout le jeu de caractères Unicode et elles ont bien raison, le Web étant certainement un des services d'Internet le mieux « unicodisé ». Ainsi, on trouvera sur une page Web comme http://morris.blogs.nytimes.com/2008/08/11/photography-as-a-weapon/, pourtant en anglais, des caractères Unicode comme les jolis guillemets (“this information that you heard? It's wrong.”, utilisant les caractères U+0201c et U+0201d. Mais ces caractères ne sont pas présents dans ASCII ni même dans Latin-1. Comme je ne suis pas encore pas encore passé à UTF-8, ces caractères me gênent lorsque je veux copier-coller une partie d'une page Web dans, par exemple, un courrier. Emacs accepte le texte mais, à l'enregistrement, proteste que :

These default coding systems were tried to encode text
in the buffer `toto':
  (iso-latin-1 (15 . 342396) (51 . 342393) (60 . 342397) (185
  . 342393))
However, each of them encountered characters it couldn't encode:
  iso-latin-1 cannot encode these: “ ”

Comment les convertir sans procéder à un rechercher/remplacer par caractère (car il n'y a pas que les guillemets) ? Une des forces d'Emacs est d'être programmable, dans son langage dédié, un dialecte de Lisp. On peut donc écrire :

(defun to-latin1 ()
  (interactive "*")
  (goto-char (point-min))
  (replace-string "something" "other thing")
  (goto-char (point-min))
  (replace-string "some other thing" "yet another thing")
...
)

On peut alors appeler cette fonction (avec M-x to-latin1 ou bien en l'attachant à une touche) et la conversion est faite.

Bon, il reste à mettre les caractères à changer. Le moyen le plus simple est de convertir le code en chaîne. La syntaxe Emacs Lisp pour cela est :

"\x53979"

Comment ai-je trouvé le chiffre (hexadécimal) 53979 ? Emacs n'utilise pas les points de code de la norme Unicode, malheureusement. Ce code 53979 est donc spécifique à Emacs. Pour le trouver, le plus simple est donc de mettre le curseur sur le caractère problématique et de faire C-x =. Le code est alors affiché en bas dans la mini-fenêtre.

Voici donc le résultat final :

(defun to-latin1 ()
  (interactive "*")
  (goto-char (point-min))
  (replace-string "\x53979" "'")
  (goto-char (point-min))
  (replace-string "\x5397c" "\"")
  (goto-char (point-min))
  (replace-string "\x5397d" "\"")
)

Merci à Christopher J. Madsen (cjm) pour son aide sur la syntaxe.


L'article seul

RFC 5325: Licklider Transmission Protocol - Motivations

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : S. Burleigh (NASA/Jet Propulsion Laboratory), M. Ramadas (Ohio University), S. Farrell (Trinity College - Dublin)
Pour information
Première rédaction de cet article le 17 septembre 2008


Le groupe de travail de l'IRTF DTN (Delay-Tolerant Networking) continue son travail de création de protocoles de communication standards capables de fonctionner dans l'espace lointain, ou dans des milieux similaires. Après le protocole Bundle du RFC 5050, qui décrit un protocole de niveau Application pour le transfert de données, voici le protocole Licklider, de niveau Transport.

LTP (Licklider Transmission Protocol), ainsi nommé en l'honneur du pionnier de l'Internet, est donc sur le même créneau que des protocoles comme TCP, chargé de fournir un service de transport aux applications (ce que le RFC 5050 nomme un convergence layer). Il est normalisé dans le RFC 5326 et des extensions sont prévues par le RFC 5327. Notre RFC 5325, lui, expose les motivations derrière ce protocole.

Les milieux où LTP sera utilisé sont caractérisés (sections 1 et 2 du RFC) par des délais de transmission très longs (une heure pour joindre Jupiter depuis la Terre), une fiabilité faible des transmissions et le fait que celles-ci ne soient possibles que par intervalles, lorsque les deux astres ne sont pas masqués par un troisième. Le principal « client » de LTP sera donc la NASA. (Le problème général des communications spatiales avait été décrit dans le RFC 4838.)

La section 2.1 fait également remarquer que les limites de ces communications spatiales ne sont pas uniquement physiques (vitesse de la lumière) mais également économiques. Les antennes capables de communiquer avec les vaisseaux spatiaux, comme celles du DSN, sont rares et leur location coûte cher.

La même section 2.1 explique pourquoi ces caractéristiques condamnent les protocoles réseaux traditionnels : on ne peut pas attendre un accusé de réception avant de continuer à transmettre, vue la longueur du RTT ; on ne peut pas négocier des paramètres de transmission avec l'autre partie, la fenêtre de transmission est souvent trop courte pour cela ; l'évaluation du RTT par des mesures est en général impossible. LTP sera donc un protocole unidirectionnel, l'interactivité n'étant en général pas possible dans l'espace.

La section 2.2 détaille les limites de TCP ou SCTP pour ce problème. Avec une équation d'état comme celle du RFC 5348, une transmission de la Terre à Mars à seulement dix kilobits par seconde nécessiterait un taux de perte des données inférieur à 10^(-5), ce qui est irréaliste dans l'espace.

La section 3 explique les grandes lignes du protocole (il faut lire le RFC 5326 pour avoir la vraie norme). LTP transmet des blocs de données qui sont composés de deux parties, la « rouge » (ces données doivent faire l'objet d'un accusé de réception, sinon elles sont retransmises) et la « verte » (jamais retransmises). Chacune des deux parties peut être vide. Ainsi, une application de transfert de fichiers mettra typiquement toutes les données dans la partie rouge et rien dans la verte. LTP permet donc à l'application de choisir la sémantique de TCP ou bien d'UDP et ceci pour chaque bloc de données.

Vue la nature unidirectionnelle de LTP, il n'y a pas de négociation avec l'autre partie : la transmission des données se fait « en aveugle », LTP stockant les parties rouges pour pouvoir les retransmettre s'il n'y a pas d'accusé de réception. Seule la couche Liaison peut donner des indications à LTP (la section 3.1.1 détaille ces indications).

Justement, quand retransmettre ? Comme LTP ne peut pas mesurer le RTT, il doit dépendre de calculs réalisés avant la transmission (la section 3.1.3 détaille ces calculs), en se basant sur la vitesse de la lumière et les délais connus, par exemple dus à la disponibilité des antennes. Cela permet d'évaluer à partir de quand une non-réponse est le signe de données perdues. Il faudra alors retransmettre (section 3.2).


Téléchargez le RFC 5325


L'article seul

Adaptation des types Python à PostgreSQL pour psycopg

Première rédaction de cet article le 16 septembre 2008


psycopg est l'interface avec PostgreSQL la plus répandue chez les programmeurs Python. Parmi toutes ses qualités, psycopg adapte automatiquement les types Python aux types PostgreSQL. Mais cette adaptation ne fonctionne pas toujours toute seule et a parfois besoin d'un coup de main.

Avec psycopg, si j'ai créé une table en SQL avec :

 
CREATE TABLE Foobar (t TEXT, i INTEGER);

je peux écrire dans mon programme Python :

cursor.execute("INSERT INTO Foobar (t, i) VALUES (%s, %s)", 
               ["I like Python", 42])

et psycopg trouve tout seul que "I like Python" est une chaîne de caractères alors que 42 est un entier. Il quote (met entre apostrophes) donc le premier et pas le second. PostgreSQL recevra (instruction SQL affichée grâce à log_statement = 'all') :

2008-09-16 13:40:19 CEST STATEMENT:  INSERT INTO Foobar (t, i) VALUES ('I like Python', 42)

Cela marche bien dans ce cas car Python connait les types utilisés et peut donc le dire à psycopg2 :


>>> type(42)
<type 'int'>
>>> type("I like Python")
<type 'str'>

Mais si on a affaire à des types qui existent dans PostgreSQL et pas dans Python ? Le cas est fréquent car PostgreSQL dispose de nombreux types comme par exemple les points, les adresses IP ou encore les UUID (RFC 4122). Essayons avec les adresses IP. Créons la table  :

CREATE TABLE Foobar (addr INET);

puis remplissons-la :

cursor.execute("INSERT INTO Foobar (addr) VALUES (%s)", 
                            ["2001:DB8::CAFE:1"])

Ça marche, l'adresse IP 2001:db8::cafe:1 a bien été enregistrée. Python ne connait pas ce type, donc l'a traité comme une chaîne de caractères, que PostgreSQL a su analyser.

Mais si on veut mettre un tableau de telles adresses (petit détour par le DNS : il est tout à fait légal, et même fréquent, qu'à un nom de machine donnée correspondent plusieurs adresses IP) ? Là, Python, psycopg et PostgreSQL ne sont pas assez intelligents. On crée la table :

CREATE TABLE Foobar (addr INET[]);

et on tente de la peupler :


>>> cursor.execute("INSERT INTO Foobar (addr) VALUES (%s)", [["2001:DB8::CAFE:1", "192.168.25.34"]])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
psycopg2.ProgrammingError: column "addr" is of type inet[] but expression is of type text[]
LINE 1: INSERT INTO Foobar (addr) VALUES (ARRAY['2001:DB8::CAFE:1', ...
                            ^
HINT:  You will need to rewrite or cast the expression.

En effet, PostgreSQL aura reçu :

2008-09-16 13:53:01 CEST LOG:  statement: INSERT INTO Foobar (addr) VALUES (ARRAY['2001:DB8::CAFE:1', '192.168.25.34'])

alors qu'il aurait fallu envoyer INSERT INTO Foobar (addr) VALUES ('{2001:DB8::CAFE:1, 192.168.25.34}'). (Le problème serait le même pour le type UUID.)

Quelle est la bonne solution ? psycopg pourrait être plus malin et mieux connaître les types de PostgreSQL mais c'est plus compliqué que ça en a l'air. Heureusement, il existe une solution assez simple. Depuis sa version 2, psycopg permet de définir des adaptateurs soi-même, c'est-à-dire le code qui va faire la conversion d'un objet Python, au moment de l'appel à PostgreSQL. Cette technique est documentée (sommairement) dans le fichier doc/extensions.rst qui est distribué avec psycopg. (On le trouve aussi sur le Web en http://www.initd.org/svn/psycopg/psycopg2/trunk/doc/extensions.rst mais, servi avec une mauvaise indication de son type, il est difficile à lire.) Voici l'exemple que donne la documentation. Il utilise le type POINT de PostgreSQL, qui représente un point dans un espace cartésien à deux dimensions. On crée la table avec :

CREATE TABLE Atable (apoint POINT);

et on peut la peupler en SQL ainsi :

INSERT INTO Atable (apoint) VALUES ('(1, 3.14159)');

Pour que cela soit fait automatiquement depuis le programme Python utilisant psycopg2, le code est :

    from psycopg2.extensions import adapt, register_adapter, AsIs
    
    class Point(object):
        def __init__(self, x=0.0, y=0.0):
            self.x = x
            self.y = y
    
    def adapt_point(point):
        return AsIs("'(%s,%s)'" % (adapt(point.x), adapt(point.y)))
        
    register_adapter(Point, adapt_point)
    
    curs.execute("INSERT INTO atable (apoint) VALUES (%s)", 
                 (Point(1.23, 4.56),))

Et voici enfin le (tout petit) adaptateur que j'ai écrit pour le type PostgreSQL INET, qui permet de représenter des adresses IP :

from psycopg2.extensions import adapt, register_adapter, AsIs

class Inet(object):
    """ Classe pour stocker les adresses IP. Pour que psycopg puisse
    faire correctement la traduction en SQL, il faut que les objets
    soient typés. Les chaînes de caractères ne conviennent donc pas. """
  
    def __init__(self, addr):
        """ Never call it with unchecked data, there is no protection
	against injection """
        self.addr = addr

def adapt_inet(address):
    """ Adaptateur du type Python Inet vers le type PostgreSQL du même
    nom. On utilise un "cast" PostgreSQL, représenté par '::inet' """
    return AsIs("'%s'::inet" % address.addr)

register_adapter(Inet, adapt_inet)

Et on l'utilise ainsi (notez qu'il faut appeler le constructeur Inet() pour « typer » les valeurs) :

cursor.execute("INSERT INTO Foobar (addr) VALUES (%s)", 
                 [[Inet("2001:DB8::CAFE:1"), Inet("192.168.25.34")]])

Désormais, cela fonctionne. PostgreSQL reçoit :

2008-09-16 17:43:48 CEST LOG:  statement: INSERT INTO Foobar (addr) VALUES (ARRAY['2001:DB8::CAFE:1'::inet, '192.168.25.34'::inet])

et exécute bien la requête.

Merci à Chris Cogdon et Federico Di Gregorio (l'auteur de psycopg) pour leur aide sur ce sujet.


L'article seul

La fête du Cheval 2008 au Trait

Première rédaction de cet article le 16 septembre 2008


Le 14 septembre 2008, Le Trait a accueilli la seizième édition de la Fête du Cheval. Voici plusieurs photos.


L'article complet

Install Ubuntu / Linux on a Dell Inspiron 7500

First publication of this article on 15 September 2008
Last update on of 18 September 2010


I installed the operating system Ubuntu on a Dell Inspiron 7500 laptop machine. This article is to share the information that I obtained during the process.

While the basic functions are OK, there are problems. As often with laptops, even quite old machines, a lot of things do not work, or do not work out of the box.


L'article complet

RFC 5261: An Extensible Markup Language (XML) Patch Operations Framework Utilizing XML Path Language (XPath) Selectors

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : J. Urpalainen (Nokia)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF simple
Première rédaction de cet article le 11 septembre 2008


De nombreux protocoles IETF s'appuient sur XML, par exemple pour stocker de l'information de configuration. Dans ce cadre, le besoin de modifier de l'information XML sans devoir transporter le fichier entier, en communiquant juste les différences, est fréquent.

Pour le texte brut, ce besoin est couvert depuis longtemps par le format diff / patch. Jusqu'à présent, il n'existait aucune norme équivalente pour XML. Plusieurs propositions de « langages de patch » pour XML ont été faites mais ce RFC est le premier où on atteint le stade de la normalisation.

Il a été développé au sein du groupe de travail Simple, qui normalise des extensions au protocole SIP (RFC 3261) et qui en avait besoin, entre autres, pour la mise à jour de configurations stockées en XCAP (RFC 4825). Mais il est très général et applicable à tous les domaines.

Le principe de cette technique est simple. La partie du document XML à modifier est identifiée par une expression XPath. Une fois cette partie localisée, du contenu est ajouté, modifié ou retiré, selon que le fichier de modifications contienne des éléments <add>, <replace> ou <remove> (la section 4 détaille chacun de ces éléments).

L'annexe A du RFC contient de nombreux exemples, en voici quelques uns pour illustrer :


   <diff>
     <add sel="/section"><para>Nouveau paragraphe, lorem, ipsum, dolor, etc</add>
   </diff>

Ce code ci-dessus ajoute un nouvel élément <para>. L'expression XPath pour localiser le point où l'ajouter est donnée par l'attribut sel. Ici, on ajoute le nouvel élément dans l'élément <section> de premier niveau.


 <diff>
     <replace sel="section[title='Bibliographie']">
         <bibliography>...</bibliography>
     </replace>
   </diff>

Ici, la section de titre « Bibliographie » est remplacée par un élément <bibliography>.

   
   <diff>
     <remove sel="article/section/para/text()"/>
   </diff>

Ici, le texte de l'élément <para> est supprimé.

La syntaxe complète de ce nouveau format est décrite dans la section 8, elle est exprimée en W3C Schema.

À noter qu'il existe déjà une mise en œuvre de ce format, xmlpatch. Voici un exemple d'utilisation avec un premier document toto.xml :


<article>
<abstract>Brouillon</abstract>
<section>
<title>Premier essai</title>
<para>À l'heure actuelle, on ne sait pas encore grand'chose.</para>
</section>
</article>

et sa deuxième version, totoplus.xml :


<article>
<section>
<title>Premier essai</title>
<para>Aujourd'hui, nous en savons bien plus.</para>
</section>
<section>
<title>Révélations</title>
<para>Nous avons même une seconde section.</para>
</section>
</article>

Appliquons xml_diff pour obtenir un fichier de différences, au format du RFC :

% xml_diff -f toto.xml -t totoplus.xml -o toto.xmlpatch

Ce fichier des différences contient :


<?xml version="1.0"?>
<x:changes xmlns:x="urn:xml-changes">
  <x:remove sel="*/*[1]" ws="after"/>
  <x:replace sel="*/*/*[2]/text()">Aujourd'hui, nous en savons bien plus.</x:replace>
  <x:add sel="*"><section>
<title>R&#xE9;v&#xE9;lations</title>
<para>Nous avons m&#xEA;me une seconde section.</para>
</section>
</x:add></x:changes>

Personnellement, je ne trouve pas les expressions XPath extraordinaires, elles manquent notamment de robustesse en cas de légers changements du document source. Mais elles sont correctes et on peut appliquer ce patch :

% xml_patch -f toto.xml -p toto.xmlpatch -o toto-patched.xml

et cela nous redonne un document qui a le même contenu que totoplus.xml. Attention, cela ne signifie pas qu'il soit identique au bit près (par exemple, les caractères UTF-8 de l'original ont été remplacés par des entités numériques XML) mais que son contenu informationnel (l'infoset XML) est le même.

Au passage, vous remarquerez que l'élement XML qui englobe les éléments patch n'est pas défini par le RFC. <diff> (dans les exemples du RFC) ou bien <changes> (dans l'exemple avec xml_patch) sont des choix arbitraires. Cela été fait ultérieurement dans le RFC 7351.


Téléchargez le RFC 5261


L'article seul

La sécurité de BGP et l'importance des réactions rapides

Première rédaction de cet article le 10 septembre 2008


Des problèmes récents comme l'attaque involontaire de Pakistan Telecom contre Youtube ou comme la polémique autour des annonces de l'ancienne adresse d'un serveur racine du DNS ont ravivé l'intérêt pour les problèmes de sécurité de BGP. L'annonce en août 2008 d'un nouveau moyen pour limiter le risque d'être détecté lorsqu'on fait des fausses annonces BGP a encore renforcé l'inquiétude. Certains se posent donc la question : pourquoi ne « sécurise » t-on pas BGP ? Pourquoi n'importe quel incompétent à Pakistan Telecom peut-il détourner l'accès à un service vital et stratégique comme Youtube ?

La réponse à cette question est parfois « parce que l'Internet a été conçu par des étudiants hippies et irresponsables qui ne pensaient pas à la sécurité ; aujourd'hui que l'Internet est une ressource critique, il faudrait prendre la sécurité de BGP plus au sérieux ». Cette position laisse entendre qu'on pourrait sécuriser BGP pour peu qu'on le veuille vraiment. Mais c'est trop simpliste. Voyons pourquoi.

BGP, normalisé dans le RFC 4271, fonctionne entre pairs, des routeurs qui ont été configurés pour échanger de l'information sur les routes disponibles. Chaque routeur peut accepter et refuser les routes annoncées par son pair, selon des critères choisis unilatéralement, et ils ne s'en privent pas (le RFC 5291 fournit un mécanisme - facultatif - pour informer son pair). Les deux pairs étant en général proches physiquement, souvent sur un câble dédié, la sécurité du canal BGP n'est guère en cause (on peut l'améliorer avec IPsec mais la plupart des opérateurs préfèrent la solution du RFC 2385, qui sera peut-être remplacée dans le futur par celle du RFC 5925). Le problème n'est pas d'authentifier le pair voisin, le problème est d'authentifier ce qu'il raconte ! Sachant que les annonces BGP sont transmises de routeur en routeur, comment garantir une chaîne de confiance depuis le premier ? En d'autres termes, si mon voisin m'annonce qu'il a entendu qu'il y avait une route vers 192.0.2.0/24, et qu'il le sait parce que lui-même l'a entendu d'un de ses voisins, comment savoir si cette route est authentique, d'autant que ce terme même n'est pas clairement défini (cf. RFC 5123) ?

Alors, comment authentifier des annonces BGP ? Les propositions actuelles, comme Secure BGP ou soBGP, actuellement discutées au sein du groupe de travail SIDR de l'IETF ne sont pas nouvelles. Elles visent à mettre au point un mécanisme de signature cryptographique des annnonces BGP. Le RIR qui attribue un préfixe IP signera cette attribution, permettant à l'opérateur qui a reçu le préfixe de signer ses annonces. Les RFC normalisant cette technique ont été publiés début 2012.

La principale difficulté commune à tous ces mécanismes est que la hiérarchie d'attribution des adresses IP (de l'IANA vers les RIR puis vers les LIR) ne correspond pas très bien au maillage BGP, qui, lui, n'est pas hiérarchique. Le client final annonce sa route (s'il fait du BGP lui-même) ou bien la fait annoncer par qui il veut, sans que le LIR par qui il a obtenu l'adresse n'approuve ou même soit au courant. Et c'est sans même parler des adresses PI, qui ne sont pas liées à un LIR. Changer ce mécanisme est certainement possible, mais cela change le modèle de fonctionnement de l'Internet. Et cela donnerait un plus grand pouvoir aux opérateurs puisque seules les annonces approuvées par eux pourront être faites.

Bien sûr, les annonces qui sont faites sont normalement annoncées dans les IRR. Mais les IRR publics sont souvent de piètre qualité. Certains sont assez à jour, par exemple celui du RIPE-NCC mais ce n'est pas le cas de tous (parfois tout simplement parce que les procédures de mise à jour sont trop strictes). Certaines entreprises ont leur propre IRR, tâche assez lourde. Il n'est donc pas étonnant que le filtrage des annonces BGP sur la base des IRR (n'accepter que les routes qui sont publiées dans un IRR) aie eu assez peu de succès : comme l'ont montré beaucoup d'études et d'expériences douloureuses, ce filtrage rencontre beaucoup de faux positifs (des routes légitimes refusées) et également des faux négatifs (routes illégitimes acceptées quand même). Il faut aussi se rappeler que, dans le cas du « détournement » du serveur racine L, l'annonce « anormale » était bien faite par le titulaire du préfixe...

Alors, n'y a t-il pas d'espoir pour la sécurité et la stabilité de l'Internet ? Notons d'abord que, bien que triviales en pratique et très connues, les vulnérabilités de BGP n'ont pas eu pour conséquence des attaques nombreuses. Une des raisons est que tout le monde voit l'attaque et peut réagir et tomber sur le dos du responsable. Jusqu'à l'annonce de Kapela & Pilosov, ces « attaques » (souvent en fait, des erreurs) étaient détectées et corrigées très vite. C'est un point important de la sécurité de l'Internet : celui-ci n'a pas la sécurité d'un bloc de béton, passif et n'étant protégé que par sa résistance aveugle. L'Internet est plutôt un organisme vivant : très vulnérable, mais aussi très réactif, doté d'un système immunitaire particulièrement efficace, puisque ses leucocytes sont intelligents...

L'Internet peut ainsi réagir à une large gamme d'attaques, y compris des attaques pas encore inventées. Lors de l'attaque contre Youtube, la détection, l'identification du responsable et la correction avaient été faites en quelques heures.

C'est pour cela que, jusqu'à présent, les armes les plus efficaces contre les détournements BGP ont été des systèmes d'alerte comme MyASN ou bien IAR. Ces systèmes fonctionnent aussi lors d'attaques du style Kapela & Pilosov. En effet, le détournement de Youtube avait été noté car plus personne ne pouvait travailler, sans ce service indispensable. Si l'attaquant avait utilisé les techniques mises au point par Kapela et Pilosov, il aurait pu échapper à la détection, mais pas si Youtube avait utilisé MyASN (ils utilisent probablement un tel service).

Un peu plus lointain, d'autres systèmes sont actuellement mis au point pour donner du temps aux administrateurs réseaux en cas de détournement, évitant ainsi d'avoir une perturbation, même de durée limitée. C'est ainsi que Pretty Good BGP ralentit délibérement la propagation de nouvelles routes (considérées suspectes par défaut) pendant 24 heures. Ainsi, une équipe réactive pourra arrêter le détournement avant qu'il ne soit accepté par les routeurs. (Une mise en œuvre de Pretty Good BGP est disponible pour Quagga.)


L'article seul

Les normes du courrier électronique enfin entièrement internationalisées

Première rédaction de cet article le 7 septembre 2008
Dernière mise à jour le 12 mars 2013


Parmi les protocoles utilisés sur Internet, presque tous sont internationalisés depuis longtemps. Le dernier gros manque concernait les adresses de courrier électronique, obligées de s'en tenir à stephane@internet-en-cooperation.fr alors qu'on voudrait pouvoir écrire à stéphane@internet-en-coopération.fr. Désormais, nous avons une solution normalisée, Internationalized Email, dont les spécifications viennent d'accéder au statut de norme IETF.

Bien sûr, pour l'exemple ci-dessus, n'utilisant que l'alphabet latin, le gain n'est pas évident. Mais il l'est beaucoup plus si vous voulez écrire votre adresse avec l'écriture arabe ou chinoise.

Le contenu des courriers était internationalisé depuis longtemps, au moins depuis MIME (RFC 1341 à l'origine, en juin 1992). Mais les adresses ne l'étaient pas encore. Une solution était en développement depuis longtemps à l'IETF, sous le nom d'EAI (Email Addresses Internationalization) et avait été publiée à l'origine en 2008, avec un statut « expérimental ». Elle est désormais, après une histoire complexe, entièrement normalisée.

Il y a deux parties à l'adresse (décrites dans le RFC 5322) : la partie locale, à gauche du @ et le nom de domaine à droite. Si ce nom de domaine, depuis la sortie du RFC 3490, en mars 2003, peut s'écrire en Unicode (norme IDN), le courrier exigeait toujours un nom de domaine en ASCII donc un message de non-délivrance, par exemple, allait affichait la forme Punycode du nom. Ce n'était pas une vraie internationalisation.

La nouvelle norme, qui réalise enfin cette internationalisation, est spécifiée dans les RFC suivants :

  • RFC 6530, Overview and Framework for Internationalized Email décrit le cadre général. Si on ne lit qu'un seul RFC de la série, c'est celui-là.
  • RFC 6531, SMTP extension for internationalized email address, qui indique les modifications de SMTP pour utiliser le courrier aux adresses Unicode.
  • RFC 6532, Internationalized Email Headers, qui décrit l'utilisation d'UTF-8 dans les en-têtes du courrier électronique où, jusqu'à présent, seul ASCII était autorisé.
  • RFC 6533, Internationalized Delivery Status and Disposition Notifications, qui précise le format des accusés de réception et des avis de remise et de non-remise.
  • Le cas des listes de diffusion est traité dans le RFC 6783.
  • Et des RFC pour les protocoles permettant la récupération locale du courrier, c'est-à-dire POP (RFC 6856) et IMAP (RFC 6855), ainsi que deux RFC (RFC 6857 et RFC 6858) décrivant un algorithme pour se « replier » au cas où, à la lecture d'un message reçu, il faille transmettre un message internationaisé à un vieux logiciel ne comprenant pas la nouvelle norme.

Il existe plusieurs mises en œuvre d'EAI, dont l'interopérabilité a été testée en juillet 2008 lors d'une session commune aux NIC chinois, coréens, japonais et taïwanais.

Je ne les ai pas encore déployées sur mes serveurs donc inutile d'écrire à stéphane@bortzmeyer.org, cela ne marchera pas. (Si vous voulez tester, des auto-répondeurs utilisant ces adresses sont disponibles.) Pire, en général, le message sera massacré par les divers intervenants (encodé en Quoted-Printable ou transformé en stphane@bortzmeyer.org ou Dieu sait quoi) avant même d'arriver à mon serveur. Merci à André Sintzoff pour ses tests.

L'expérience avec la syntaxe actuelle des adresses, ignorée par bien des programmeurs amateurs, donne à penser qu'il ne sera hélas pas possible de si tôt d'utiliser une telle adresse dans les formulaires.

Le principal protocole de la famille TCP/IP qui ne soit pas complètement internationalisé est donc désormais FTP qui dispose de deux types de transfert de données, « texte » et « binaire » où « texte » ne concerne que l'ASCII (ou, à la rigueur, les jeux ISO 8859). Un travail est en cours pour étendre FTP afin de pouvoir utiliser le texte Unicode du RFC 5198.


L'article seul

RFC 5336: SMTP extension for internationalized email address

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : J. Yao (CNNIC), W. Mao (CNNIC)
Expérimental
Première rédaction de cet article le 7 septembre 2008


Dans la grande série des RFC décrivant les adresses de courrier internationalisées, ce document traite des modifications au protocole SMTP. Il a été remplacé quatre ans après par le RFC 6531 et n'est donc plus une lecture indispensable.

Plusieurs RFC composent la nouvelle norme EAI ou « Email Addresses Internationalized » (cf. RFC 4952, remplacé depuis par le RFC 6530). Les deux principaux concernent le format des messages (RFC 5335) et le dialogue entre deux serveurs de messagerie, suivant le protocole SMTP. Ce dernier cas est couvert dans notre RFC 5336.

Les adresses de courrier en Unicode ne sont pas en effet compatibles avec le SMTP « brut ». Ainsi, la commande RCPT TO qui permet d'indiquer le destinataire, ne prend en paramètre que de l'ASCII. Il faut donc étendre SMTP (actuellement normalisé en RFC 5321) pour permettre de l'UTF-8 en paramètre de commandes comme MAIL FROM et RCPT TO. Cette extension se signale avec l'option UTF8SMTP, dont l'usage permet de vérifier que le MTA situé en face comprend bien la nouvelle norme (sections 1 et 2 du RFC). Si ce n'est pas le cas, une adresse en ASCII facultative peut être utilisée.

La section 3 forme le gros du RFC en spécifiant rigoureusement le nouveau protocole. Voyons d'abord un exemple de dialogue SMTP avec la nouvelle extension (C est le client - l'appelant - et S le serveur - l'appelé) :


S: 220 mail.example.org ESMTP Foobar (Debian/GNU)
C: EHLO mail.iloveunicode.example 
S: 250-mail.example.org
 250-ENHANCEDSTATUSCODES
 250-8BITMIME
 250-UTF8SMTP
 250 DSN
C: MAIL FROM:<stéphane@internet-en-coopération.fr> ALT-ADDRESS=bortzmeyer@afnic.fr
S: 250 2.1.0 Ok
C: RCPT TO: <françoise@comptabilité.example.org>
S: 250 2.1.5 Ok

Notez les deux adresses, chacune comprenant des caractères non-ASCII, à gauche et à droite du @.

Les serveurs qui mettent en œuvre l'extension UTF8SMTP doivent également accepter la très ancienne extension 8BITMIME (RFC 1652) qui permet, depuis belle lurette, de ne pas se limiter à l'ASCII dans le contenu des messages, sans pour autant nécessiter des encodages comme Quoted-Printable (en dépit d'une légende tenace).

La section 3.1 présente la nouvelle extension, UTF8SMTP. Les extensions SMTP sont définies par le RFC 5321, section 2.2. Un MTA peut annoncer qu'il accepte UTF8SMTP, permettant à son pair, s'il l'accepte également, d'utiliser des adresses UTF-8. C'est également cette section qui définit ce que doit faire un MTA lorsqu'il tente de transmettre un message internationalisé à un ancien MTA qui ne gère pas cette extension. Quatre solutions sont possibles, la plus fréquente sera sans doute d'utiliser le mécanisme de repli (downgrade).

La section 3.3 décrit la nouvelle syntaxe pour les adresses. L'ancienne était limitée à ASCII mais très permissive (bien qu'on trouve, notamment derrière les formulaires Web, énormément de logiciels de « vérification » bogués). En gros, la syntaxe est qu'une adresse est formée de deux parties, la partie locale et le nom de domaine, tous les deux séparés par l'arobase. La nouveauté est que les deux parties peuvent désormais être en Unicode, avec peu de restrictions sur la partie locale (le nom de domaine étant soumis aux restrictions du RFC 3490).

Une adresse alternative tout en ASCII peut être fournie par le paramètre ALT-ADDRESS. C'est l'objet des sections 3.4 et 3.5. Elle doit s'utiliser conjointement à une modification du message (qui peut contenir des en-têtes en UTF-8) et l'ensemble du processus s'appelle le repli (downgrade). Sa spécification est publiée dans le RFC 5504. (Dans l'exemple de dialogue SMTP plus haut, seul l'expéditeur avait une adresse alternative.)

Il y a plein d'autres détails dans cette section, comme celui (section 3.7.1) que le paramètre de la commande EHLO (un nom de machine) doit être encodé en Punycode puisque, à ce stade, on ne sait pas encore si UTF8SMTP est accepté ou pas.

Je n'ai pas encore testé avec mes Postfix, ni vérifié quels étaient les plans des auteurs de ce logiciel vis-à-vis de cette extension de SMTP.


Téléchargez le RFC 5336


L'article seul

RFC 5337: Internationalized Delivery Status and Disposition Notifications

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : C. Newman (Sun), A. Melnikov (Isode)
Expérimental
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 7 septembre 2008


Dans l'ensemble des RFC sur l'internationalisation des adresses de courrier électronique, ce document traite le cas des accusés de réception et avis de non-remise (DSN pour Delivery Status Notification). Il est le prédécesseur du RFC 6533, la norme actuelle.

Puisque les RFC 5336 et RFC 5335 permettent désormais d'utiliser des adresses de courrier électroniques internationalisées, c'est-à-dire utilisant tout le jeu de caractères Unicode, il faut prévoir le cas où les courriers provoquent l'envoi d'avis de remise ou de non-remise (DSN pour Delivery Status Notification, RFC 3461 et RFC 3464) et d'accusés de réception (MDN, pour Message Disposition Notification, RFC 8098). C'est l'objet de ce RFC, qui met à jour les anciens documents qui limitaient ces accusés et avis au jeu ASCII.

Le format des DSN dans le RFC 3464 parle de « types d'adresse ». Les adresses en UTF-8 du RFC 5335 sont un nouveau type d'adresses. Si le serveur SMTP accepte l'extension UTF8SMTP du RFC 5336 et l'extension DSN du RFC 3461, il doit permettre d'utiliser ce type dans le paramètre ORCPT (Original Recipient, section 4.2 du RFC 3461). Si le serveur n'accepte pas UTF8SMTP, l'adresse à utiliser dans les DSN doit être encodée en 7bits, selon les règles exposées dans cette section 3 (et non pas selon les règles du RFC 5137, paru trop tard). Par exemple, stéphane@bortzmeyer.org peut s'écrire st\x{E9}phane@bortzmeyer.org. (La section 3 détaille plus complètement le traitement des adresses UTF-8.)

Une fois réglé le problème de la représentation des adresses, la section 4 traite les DSN en UTF-8. Les DSN traditionnels étaient composés d'un objet MIME de type multipart/report comportant trois objets décrivant le problème (un objet conçu pour être lu par un humain, un message/delivery-status et le message originel, message/rfc822). Pour le courrier internationalisé, de nouveaux types ont été créés :

  • message/global-delivery-status qui, contrairement à son prédécesseur message/delivery-status, accepte l'UTF-8 et permet donc de placer directement les adresses UTF-8, sans encodage en ASCII. En outre, il dispose d'un nouveau champ, Localized-Diagnostic, qui permet de stocker des messages lisibles par un humain. La langue de ces messages est indiquée par une étiquette de langue (RFC 4646).
  • message/global qui remplace message/rfc822 (dont le nom, hommage au vieux RFC 822, était de toute façon dépassé). À noter que le terme global (mondial) utilisé pour noter ce type avait fait l'objet de vives discussions et même d'un vote. Cet objet permet de transporter le message original (si on ne transporte que les en-têtes, on utilise message/global-headers.

On peut noter que la norme MIME (RFC 2046) interdisait l'usage de l'option Content-Transfer-Encoding pour les objets de type message/* mais cette règle a été assouplie par le RFC 5335.

La section 5 traite des MDN (Message Disposition NOtificatin, RFC 3798). Ils ne sont pas très différents des DSN et ont un format très proche, avec un type MIME message/global-disposition-notification.

La section 6 traite des registres IANA. Le type « UTF-8 » est ajouté au registre des types d'adresses (section 6.1), et les nouveaux types MIME comme message/global sont ajoutés au registre des types MIME (sections 6.3 à 6.5).

Enfin, la section 7 est dédiée aux questions de sécurité. Outre les problèmes de sécurité classiques des DSN et des MDN (non authentifiés, ils permettent de faire croire qu'un message a échoué, alors qu'il a bien été délivré, ou le contraire), le RFC nous prévient que des DSN ou des MDN délibérement incorrects peuvent être envoyés par un attaquant dans l'espoir de profiter d'erreur dans la programmation des analyseurs, par exemple pour déclencher un débordement de tampon. Le risque est plus important s'il y a beaucoup d'encodage, le décodage pouvant faire varier la taille des données.


Téléchargez le RFC 5337


L'article seul

RFC 5335: Internationalized Email Headers

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : Y. Abel (TWNIC)
Expérimental
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 7 septembre 2008


Dans l'ensemble des RFC qui décrivent les adresses de courrier électronique internationalisées (c'est-à-dire pouvant utiliser tout le répertoire Unicode), celui-ci se consacre au nouveau format des en-têtes, mettant donc à jour le fameux RFC 2822 (en toute rigueur, il n'est mis à jour que par ceux qui participent à l'expérience, cf. section 1.2 du RFC). Il a été remplacé par la suite par le RFC 6532.

Désormais, on peut, si on participe à l'« expérience » (tel est son statut officiel) EAI (Email Address Internationalization), avoir dans un message un en-tête comme :

From: Stéphane Bortzmeyer <stéphane@sources.org>

Oui, avec du vrai UTF-8, y compris dans l'adresse proprement dite, pas seulement dans les commentaires, et encore, à condition de les surencoder selon le RFC 2047 comme c'était le cas avant.

L'éditeur du RFC travaille à TWNIC, le registre chinois de .tw. Les chinois ont, fort logiquement, été particulièrement actifs dans tout le processus EAI. Celui-ci visait à terminer l'internationalisation du courrier électronique, qui avait passé une étape décisive en novembre 1996, avec la sortie du RFC 2045 sur MIME. Mais cette norme MIME n'internationalisait que le corps des messages. EAI permet désormais d'internationaliser également les en-têtes comme From: ou Received: (mais pas, par exemple, Date: ou Message-ID:, qui resteront en ASCII pur, cf. section 4.3 ; Date:, par exemple, est censé être analysé par le MUA et présenté ensuite à l'utilisateur dans sa langue).

EAI comprend plusieurs RFC, par exemple à l'époque le RFC 4952 définit le cadre général, le RFC 5336, l'utilisation des adresses Unicode dans SMTP (avec l'extension UTF8SMTP), des futurs RFC qui traiteront le cas de POP ou IMAP et notre RFC 5335, qui se concentre sur le format des messages. Tous ont été remplacés en 2012 par la nouvelle série, autour du RFC 6530.

Concrètement, que change donc ce RFC ? La section 4 détaille ce qui est modifié :

  • La grammaire ABNF qui décrit les en-têtes est changée (sections 4.1 et 4.3) pour accepter des caractères UTF-8, de préférence normalisés en NFC (cf. RFC 5198). Déjà très complexe, cette grammaire devient ainsi réellement difficile.
  • La syntaxe des adresses (telles qu'on les trouve dans des en-têtes comme From: ou To:) est modifiée pour accepter UTF-8. Pour les sites qui utilisent une adresse électronique comme identificateur, comme le fait Amazon.com, ce sera un intéressant défi !
  • Un nouveau type MIME est créé, message/global, pour permettre d'identifier un message EAI (section 4.6).

Parmi les conséquences pratiques de ce changement, il faut noter que les programmeurs qui écrivent des logiciels traitant le courrier doivent désormais gérer Unicode, même s'ils se contentent d'analyser les en-têtes... L'époque du courrier traité avec des scripts shell est bien passée.

La section 5 liste également quelques conséquences pour la sécurité comme le fait qu'un mécanisme d'authentification devra être prêt à gérer plusieurs adresses pour la même personne (car, pendant un certain temps, plusieurs utilisateurs auront à la fois une adresse en Unicode et une en ASCII pur).


Téléchargez le RFC 5335


L'article seul

Combien de fils d'exécution ?

Première rédaction de cet article le 4 septembre 2008


Je viens de commencer un programme comportant plusieurs fils d'éxcution (threads). Lorsqu'on découpe un programme en fils, il y a une décision à prendre concernant le nombre de fils ; beaucoup de fils permet un parallélisme maximal mais implique aussi un surtravail dû à la communication avec ces fils. Peu de fils fait que du travail peut rester bloqué car le fil en est toujours au travail précédent. La valeur optimale dépend évidemment du problème précis.

Ici, il s'agissait d'un projet AFNIC d'interrogation des zones DNS sous .fr pour en déduire des informations, par exemple sur le niveau de déploiement de IPv6 ou bien de DNSSEC (projet DNSwitness). Les requêtes DNS aux serveurs de noms peuvent être très lentes, surtout si un ou plusieurs serveurs de la zone sont en panne, et qu'on doit attendre l'expiration du délai de garde. Avec un programme séquentiel, quelques pourcents de zones vraiment cassées peuvent retarder considérablement tout le programme. D'où l'idée de parallèliser.

.fr compte actuellement environ 1 200 000 zones déléguées. Faut-il 1 200 000 fils d'exécution ? Ou bien seulement 10 ? Ou entre les deux ? On peut toujours spéculer a priori sur le chiffre idéal. Il dépend de beaucoup de facteurs (matériel utilisé, efficacité de l'ordonnanceur utilisé, ici celui de Python, nombre de communications nécessaires avec les fils, etc). Notons que, le programme étant écrit en Python, où l'interpréteur lui-même n'est pas parallèle, une machine multiprocesseur n'est pas forcément utile.

Le mieux est de mesurer plutôt que d'essayer d'imaginer. Je fais un programme qui lit le fichier de zone de .fr, je crée N tâches Python et je confie à chacune 1 200 000 / N zones à interroger (chaque tâche doit évidemment aussi signaler à la tâche maîtresse le résultat de ses interrogations). L'interrogation se fait avec l'excellent module DNS Python, en ne parlant pas directement aux serveurs de noms mais en étant derrière un résolveur/cache Unbound (donc, attention, le cache peut influencer les mesures, c'est pour cela qu'elles ont été faites deux fois).

Avec seulement cent tâches (N = 100), le programme ne peut faire qu'environ cent zones par seconde. Je l'ai interrompu avant la fin. Avec 1000 tâches, on arrive à 480 zones par seconde. Et avec 10 000 tâches, on atteint 550 zones par seconde.

Cela illustre l'efficacité de l'ordonnanceur Python : il vaut mieux utiliser « beaucoup » de tâches.

Ne prenez pas le résultat au pied de la lettre pour vos programmes. Ce qui compte ici est la méthode (mesurer au lieu de supposer ; l'informatique est une science expérimentale). Le résultat, lui, dépend de beaucoup de facteurs.

Les tests ont été faits avec Python 2.5.2 sur une machine Debian lenny avec le noyau Linux 2.6.22. L'ordinateur était un Dell Poweredge avec huit gigaoctets de RAM et quatre processeurs AMD Opteron.


L'article seul

RFC 5334: Ogg Media Types

Date de publication du RFC : Septembre 2008
Auteur(s) du RFC : I. Goncalves (Xiph), S. Pfeiffer (Xiph), C. Montgomery (Xiph)
Chemin des normes
Première rédaction de cet article le 4 septembre 2008


Ce court RFC documente les types « MIME » (RFC 2045) à utiliser pour le format de fichiers multimédia Ogg, changeant sérieusement les anciens types du RFC 3534.

Dans un monde du multimédia dominé par des formats fermés comme WMF ou partiellement ouverts comme Flash (sans compter les innombrables et futiles brevets sur ces formats), Ogg, format maintenu par la fondation Xiph et décrit dans le RFC 3533, reste le principal format ouvert. Comme beaucoup de formats multimédia (par exemple AVI), Ogg ne permet que de créer des containers, des ensembles de flux de données, dont chacun a son propre format. Ainsi, un film stocké dans un container Ogg contiendra en général deux flux, un vidéo (typiquement au format Theora) pour l'image et un audio (typiquement au format Vorbis) pour le son. D'autres containers Ogg peuvent contenir plus de deux flux de données temporelles.

Cette façon de stocker les données complique un peu la définition d'un type de données pour étiqueter les containers Ogg, lorsqu'ils sont distribués par courrier électronique ou bien envoyés via le protocole HTTP. Le RFC originel, le RFC 3534, définissait un type unique, application/ogg. Le problème était qu'un container Ogg ne contenant que du son au format Vorbis se trouvait étiqueté avec le type très général application/ alors que le type audio/ aurait certainement mieux convenu. Notre RFC introduit donc deux nouveaux sous-types de video/ et audio/, soit video/ogg et audio/ogg, et redéfinit le type application/ogg.

La section 2 du RFC rappelle les changements depuis le RFC 3534, la principale étant ces deux nouveaux types.

La section 4 décrit les problèmes de compatibilité qui pourraient surgir avec les anciennes applications. Elle pose le principe que du contenu purement audio devrait être marqué avec le nouveau type audio/ogg (même chose pour la vidéo), réservant l'usage de application/ogg aux contenus plus complexes (par exemple dans le secteur scientifique, où ils sont plus fréquents que dans le monde du multimédia). Pour ces contenus, notre RFC impose l'extension Ogg Skeleton pour identifier les différents flux contenus. Elle décrit aussi l'utilisation du paramètre codecs qui permet de préciser le format des flux inclus, et donc le codec à utiliser. Ainsi, un flux Speex dans un fichier Ogg pourra être identifié par audio/ogg; codecs=speex. La section 5 du RFC précise davantage les relations entre les trois types désormais normalisés, du plus général, application/ogg au plus spécifique, audio/ogg.

La section 10 contient la « paperasse » nécessaire à l'enregistrement des trois types dans le registre IANA des types. La section 10.1 enregistre application/ogg, recommandant l'extension de fichier .ogx (.ogg étant souvent utilisé uniquement pour l'audio).

10.2 définit video/ogg (extension .ogv) et 10.3 audio/ogg, qui garde l'extension « historique » .ogg.

Ogg dispose d'une mise en œuvre de référence, sous une licence libre, la libogg (section 8 du RFC, sur l'interopérabilité).

Notons enfin une section 7 du RFC consacrée à la sécurité et qui donne quelques avertissements utiles : si Ogg en lui-même n'est qu'un format et ne pose pas de problème de sécurité en soi, certains contenus d'un fichier Ogg peuvent être exécutables et poser alors de redoutables problèmes de sécurité comme l'ont montré les nombreuses alertes de sécurité qui concernaient Flash. Ces contenus ne devraient pas être exécutés sans une validation (par exemple une signature électronique, service non fourni actuellement par Ogg lui-même mais qui peut être utilisé sur les flux transportés dans un container).

D'autre part, les contenus multimédia sont souvent de grande taille et des attaques par déni de service indirect sont toujours possibles, par exemple en envoyant une image qui, après décompression, sera ridiculement grande, ou un flux audio avec un rythme d'échantillonage impossible à suivre. Les programmes qui lisent les fichiers multimédia doivent donc être prudents.


Téléchargez le RFC 5334


L'article seul

Premiers jours d'utilisation du Neo Freerunner avec Openmoko

Première rédaction de cet article le 3 septembre 2008


J'ai reçu en rentrant de vacances mon Neo Freerunner, un téléphone portable équipé de la plate-forme logicielle Openmoko. Ce téléphone entièrement libre, matériel et logiciel, tiendra t-il ses promesses ?

Le monde de la téléphonie mobile est aujourd'hui dominé par des engins totalement fermés dont le plus extrême est sans doute l'iPhone d'Apple. Ces appareils font tourner un système d'exploitation complètement privateur mais, surtout, ils ne permettent pas toujours de faire tourner dessus les applications qu'on veut. C'est ainsi que la machine favorite des ignorants, l'iPhone, refuse les applications non approuvées par Apple et ne permet d'utiliser qu'un seul opérateur de téléphone mobile. (Cf. Problems of typical "closed" phones. Autres articles sur l'iPhone : Apple interdit aux développeurs d'applications refusées de publier ce refus et Apple censure à sa guise les contenus qui lui déplaisent.)

Ces appareils sont donc bien plus fermés qu'un PC avec MS-Windows. Au moins, Steve Ballmer ne m'empêche pas de faire tourner n'importe quel logiciel, par exemple Firefox et Open Office sur son système « fermé » ! Il est curieux de voir des gens critiquer vertement le géant états-unien du logiciel et se précipiter ensuite chez le petit Satan pour acheter très cher un engin dont le degré de fermeture ferait envie à Microsoft.

Il n'est donc pas étonnant qu'un gros effort marketing soit en cours pour nous convaincre que l'avenir de l'accès à Internet est dans la téléphonie mobile : l'Internet est un symbole d'ouverture et le refermer est une priorité pour beaucoup.

Pourtant, la téléphonie mobile n'est pas forcément synonyme de fermeture. Il existe plusieurs plate-formes qui sont relativement ouvertes (comme le fameux Android de Google) et surtout un système totalement ouvert, Openmoko. Avec Openmoko, non seulement le téléphone ne fait tourner que du logiciel libre mais, en outre, la partie matérielle repose également sur des composants dont les schémas sont publiés et réutilisables pour d'autres fabricants (pour des raisons légales, la partie GSM n'est pas dans ce cas). C'est donc un projet très (trop ?) ambitieux ; il offrirait plus de liberté que mon PC/Debian de la maison, où seul le logiciel est libre.

Il existe aujourd'hui un téléphone construit pour Openmoko, le Neo Freerunner. Il est distribué en France par Bearstech.

Son noyau est un Linux mais ce n'est pas cela qui compte : la Freebox a un Linux aussi et elle est extrêmement fermée. Par contre, la séquence de boot avec les messages du noyau de 0,4 mm de hauteur vaut le coup d'œil.

Qu'en est-il après quelques jours d'essais ? Si le matériel est très soigné (vous pouvez lire un excellent récit illustré du déballage et de la mise en route), le logiciel n'est pas à la hauteur. D'abord, il faut bien comprendre que l'état actuel d'Openmoko est franchement beta, voire alpha. Il n'est pas utilisable par des simples utilisateurs, et n'a pas vraiment d'intérêt même pour des geeks, si ces derniers ne sont pas des développeurs pour cette plate-forme. Quelques exemples : la partie GPS est très difficile à faire marcher, la dernière version officielle, Om 2008.8, ne permet pas de téléphoner sans un insupportable écho, l'application de gestion des contacts (stockés sur la carte SIM) n'a pas de fonction de recherche, le clavier virtuel a une touche d'effacement très complexe (les problèmes d'ergonomie sont fréquents sur Openmoko), etc.

Surtout, le logiciel est très peu stable : les Freerunner sont livrés avec une image, Om 2007.2, qui n'est plus maintenue et que personne n'utilise. Le nouvel utilisateur doit donc commencer par en flasher une nouvelle. Il existe plusieurs images possibles, radicalement différentes (Qtopia, FSO, Debian, Om) et il est donc difficile de partager des expériences. La seule documentation d'usage concerne Om 2007.2 (Om 2008.8 est complètement différent). Le seul fait de signaler une bogue est un travail difficile.

Bref, le projet est intéressant mais encore peu avancé. Si j'apprécie de pouvoir me connecter avec ssh sur mon téléphone pour y taper ls, cela ne suffit pas encore pour remplacer mon téléphone ordinaire. Enfin, cela permet de frimer :

root@om-gta02:~# uname -a
Linux om-gta02 2.6.24 #1 PREEMPT Thu Apr 24 08:23:36 CST 2008 armv4tl unknown

root@om-gta02:~# traceroute www.google.com
traceroute: warning: www.google.com has multiple addresses; using 74.125.39.104
traceroute to www.l.google.com (74.125.39.104), 30 hops max, 38 byte packets
 1  192.168.0.200 (192.168.0.200)  0.871 ms  3.278 ms  1.697 ms
 2  192.168.2.254 (192.168.2.254)  5.235 ms  4.121 ms  4.520 ms
 3  88.189.152.254 (88.189.152.254)  37.890 ms  35.868 ms  49.363 ms
 4  78.254.1.62 (78.254.1.62)  36.765 ms  37.107 ms  39.220 ms
 5  seg75-1.v902.intf.nra.proxad.net (78.254.255.37)  37.450 ms  36.687 ms  37.085 ms
 6  inv75-1-v900.intf.nra.proxad.net (78.254.255.33)  35.948 ms  37.212 ms  37.182 ms
...

Bien sûr, il faut voir où sont les responsabilités : le monde de la téléphonie est corporatiste et ultra-fermé. Les licences pour des puces 3G coûtent des millions de dollars (sans compter le coût de fabrication de la puce elle-même) et ne sont données qu'en échange de NDA léonins. Même chose pour le monde du multimédia, où des entreprises prédatrices ont acquis de nombreux brevets logiciels et harcèlent ceux qui utilisent les formats (peut-être) couverts par ces brevets.

J'espère que l'argent que j'ai dépensé sera utile pour les futurs développements mais je n'ai pas actuellement davantage de temps à y consacrer.


L'article seul

Install Ubuntu / Linux on a Packard Bell EasyNote MX37

First publication of this article on 30 August 2008
Last update on of 16 September 2010


I installed the operating system Ubuntu on a Packard-Bell EasyNote MX37 laptop machine. This article is to share the information that I obtained during the process.

While the basic functions are OK, there are problems. As often with laptops, especially very recent machines, a lot of things do not work, or do not work out of the box.


L'article complet

Produire des données uniquement en tapant sur le clavier

Première rédaction de cet article le 28 août 2008


Question idiote du jour : quelle quantité de données peut produire un être humain tapant sur un clavier ?

Un être humain normal tape environ 1 à 2 caractères par seconde (à noter que les professionnels mesurent plutôt en mots/minute ; vous pouvez tester votre propre vitesse avec l'excellent http://www.lecturel.com/clavier/mots-par-minute.php ; mais il s'agit alors de la vitesse de frappe brute alors qu'on considère ici qu'on écrit des textes originaux, pour lesquels il faut réfléchir). Si on prend deux caractères par seconde et s'il tape de 20 ans à la mort, 40 heures par semaine (sans RTT, ni vacances, le rêve du MEDEF), cet humain (ou plutôt ce surhomme pour avoir une telle productivité) produira dans sa vie (en moyenne 81 ans en France) presque un milliard de caractères. Supposant que ces textes soient encodés en Latin-1, où chaque caractère occupe un octet, cela fera un giga-octet seulement. Soit même pas la taille d'une clé USB moderne. Une vie entière de frappe sur un petit machin qui tient au creux de la main...

Si on multiplie par le nombre d'humains qui aient jamais vécu sur Terre (environ cent milliards selon Arthur Clarke dans un passage célèbre de 2001), on n'arrive encore qu'à cent exa-octets, ce qui dépasse la taille d'un seul très gros disque dur d'aujourd'hui, mais reste probablement un faible nombre par rapport à la capacité totale de tous les disques durs de la planète (tiens, qui la connait ?).

Même si ces données étaient stockés en UTF-32, un encodage d'Unicode parfois critiqué (bien à tort) pour la place qu'il utilise (quatre octets pour tout caractère), on n'aurait que quatre cents exa-octets.

Conclusion : s'il n'y avait pas de machines comme les caméscopes numériques ou le LHC pour produire rapidement d'énormes quantités de données, les fabricants de disques durs seraient au chômage...


L'article seul

La faille de sécurité BGP de 2008

Première rédaction de cet article le 28 août 2008


Des failles de sécurité sur Internet, il y en a. Des failles concernant le protocole de routage BGP, il y en a. Que dire de particulier sur celle annoncé à Defcon en août 2008 ?

Notons d'abord la mise en scène. Comme le disait un participant de Nanog : « I think they saw the DNS people getting their 10 minutes of fame and wanted their own :) ». La sécurité informatique est un métier, comme le show-business : il faut faire parler de soi. Ce n'est pas par hasard que les exposés à Defcon commencent toujours par « cette faille est particulièrement sérieuse ». On n'a jamais vu un chercheur en sécurité débuter avec « C'est une petite vulnérabilité sans intérêt. ». Prendre conscience de cela aide à mettre cette annonce dans son contexte.

Ensuite, la faille de sécurité en question est-elle réellement nouvelle ? Non et oui. Non, car elle ne contient que des éléments déjà bien connus comme les limites du modèle de sécurité de BGP (BGP est normalisé dans le RFC 4271 et le RFC 4274 fournit une bonne analyse du protocole), qui avait par exemple été bien illustrées par l'attaque de Pakistan Telecom contre YouTube. Oui parce qu'une combinaison intelligente de techniques connues est en soi une nouveauté. Ce qu'ont présenté Anton Kapela & Alex Pilosov à Defcon est une réelle percée.

En quoi consiste t-elle ? Le socle sur lequel elle s'appuie est le fait que n'importe quel routeur BGP de la planète (donc, en pratique, n'importe quel opérateur, ou craqueur ayant piraté un opérateur), peut annoncer la route qu'il veut et elle se propagera, dans certaines conditions, à tous les autres routeurs BGP du monde, faisant ainsi converger le trafic vers les routeurs choisis par l'attaquant. Par exemple, si je veux récupérer le trafic de Paypal, j'observe que leur annonce BGP est pour le préfixe 66.211.160.0/19, j'annonce 66.211.168.0/24 (un préfixe plus spécifique, pour être sûr qu'il se propage et qu'il soit utilisé, tout en couvrant quand même les adresses IP de www.paypal.fr) et hop, je récupère les paquets destinés à Paypal.

Mais, évidemment, ça se voit : la grande ouverture de l'Internet, qui fait sa vulnérabilité, est aussi sa principale ligne de défense, la base de son système immunitaire. N'importe qui peut utiliser un looking glass et voir qui est l'attaquant. Il y a même des services d'alerte automatique bâtis sur ce principe (commme MyASN ou bien Renesys Route Intelligence). Et, surtout, tout le trafic étant dévié, le service normal s'arrête et tout le monde peut faire un traceroute pour voir à cause de qui. Grâce à cela, l'attaque de Pakistan Telecom avait tourné court.

La première innovation de Kapela & Pilosov était donc de bloquer les méthodes de détection les plus simples en acheminant le trafic détourné vers son destinataire légitime. Si l'attaquant ne veut pas réaliser une DoS mais simplement espionner le trafic, cela lui permet d'être plus discret (cela porte le doux nom, emprunté à l'électricité, de BGP shunt). Cela ne stoppe pas les alarmes des systèmes comme MyASN mais cela empêche la détection immédiate. Il est probable que la majorité des sites qui sont ainsi attaqués ne se rendent compte de rien (tout le monde n'est pas abonné à MyASN).

La redirection est délicate à réussir : il faut que tout l'Internet achemine le trafic de la victime vers l'attaquant sauf les réseaux qui sont sur le chemin de retour choisi, de façon à ce que le trafic puisse revenir à son destinataire légitime. Kapela & Pilosov utilise pour cela l'AS prepending en mettant dans le chemin d'AS de l'annonce BGP des valeurs qui assureront le rejet de la route de retour pour tous... sauf pour les routeurs du chemin de retour que les attaquants ont choisi.

La deuxième innovation de nos deux chercheurs est de modifier le TTL dans les paquets IP qu'ils voient passer, pour rendre encore plus difficile la détection par la victime.

Faut-il s'inquiéter ? Oui. Même s'il n'y a rien de révolutionnaire dans cette attaque, on peut dire qu'elle démocratise le détournement BGP, comme l'attaque Kaminsky démocratisait les empoisonnements de caches DNS.

Que peut-on faire ? D'abord, le site normal, qui n'est pas opérateur. Il ne peut pas faire grand'chose pour empêcher le shunt mais il peut se protéger en utilisant systématiquement des mécanismes de sécurisation de bout en bout, notamment la cryptographie (par exemple SSH et jamais telnet). Ainsi, même détourné, le trafic révèlera nettement moins de chose. Mais c'est essentiellement aux opérateurs d'agir. Si on a son propre numéro d'AS, il est recommandé de s'inscrire aux mécanismes d'alarme cités plus haut. Si on est opérateur ou auteur de logiciel BGP, on peut vérifier ses règles de filtrage, se demander s'il ne serait pas une bonné idée d'utiliser un IRR (sans se faire d'illusions : la qualité des données qu'on y trouve est loin d'être parfaite) ou espérer le déploiement de technologies de sécurisation de BGP comme RPKI+ROA, Secure BGP et soBGP (celles-ci ont du mal à décoller, non pas qu'elles soient trop compliquées mais parce qu'elles ont en commun de nécessiter la création d'une nouvelle infrastructure de confiance, avec ce que cela suppose de problèmes organisationnels et politiques. Le RFC 5123 en explique certains.)

L'article qui a fait le plus de bruit est Revealed: The Internet's Biggest Security Hole. C'est un article très sensationnaliste, une de ses plus grosses erreurs est de reprendre le discours standard : Those protocols were largely developed in the 1970s with the assumption that every node on the then-nascent network would be trustworthy. En fait, les concepteurs de l'Internet à l'époque (au fait, BGP est bien plus récent que « les années 70 ») étaient bien conscients de ces problèmes mais, même si on repartait de zéro, on ne pourrait pas les résoudre facilement (il n'existe pas d'État policier mondial qui pourrait attribuer des « licences d'opérateur » et des certificats X.509 afférents pour pouvoir signer les annonces BGP). Le second article de Wired, More on BGP Attacks -- Updated est bien meilleur, surtout pour les détails techniques. Mais le mieux est de lire les transparents originaux des deux découvreurs de la faille (également sur le site de Defcon).

Sur BGP, on peut aussi lire mon cours pratique.


L'article seul

RFC 4941: Privacy Extensions for Stateless Address Autoconfiguration in IPv6

Date de publication du RFC : Septembre 2007
Auteur(s) du RFC : T. Narten (IBM), R. Draves (Microsoft), S. Krishnan (Ericsson)
Chemin des normes
Première rédaction de cet article le 26 août 2008
Dernière mise à jour le 18 décembre 2008


Une des particularités d'IPv6 est de disposer d'un mécanisme, l'autoconfiguration sans état qui permet à une machine de se fabriquer une adresse IP globale sans serveur DHCP. Ce mécanisme crée typiquement l'adresse IP à partir de l'adresse MAC de la machine et une même machine a donc toujours le même identifiant (les 64 bits les plus à droite de l'adresse IPv6), même si elle change de réseau et donc de préfixe. Il est donc possible de « suivre à la trace » une machine, ce qui peut poser des problèmes de protection de la vie privée. Notre RFC fournit une solution, sous forme d'un mécanisme de création d'adresses temporaires, partiellement aléatoires. (Elle a depuis été assez sérieusement révisée et améliorée dans le RFC 8981.)

L'autoconfiguration sans état, normalisée dans le RFC 4862 est souvent présentée comme un des gros avantages d'IPv6. Sans nécessiter de serveur central (contrairement à DHCP), ce mécanisme permet à chaque machine d'obtenir une adresse globale (IPv4, via le protocole du RFC 3927, ne permet que des adresses purement locales) et unique. Cela se fait en concaténant un préfixe (par exemple 2001:db8:32:aa12::), annoncé par le routeur, à un identifiant d'interface (par exemple 213:e8ff:fe69:590d, l'identifiant de mon PC portable - les machines individuelles, non partagées, comme les PDA sont particulièrement sensibles puisque la connaissance de la machine implique celle de son maître), typiquement dérivé de l'adresse MAC.

Partir de l'adresse MAC présente des avantages (quasiment toute machine en a une, et, comme elle est unique, l'unicité de l'adresse IPv6 est obtenue facilement) mais aussi un inconvénient : comme l'identifiant d'interface est toujours le même, cela permet de reconnaître une machine, même lorsqu'elle change de réseau. Dès qu'on voit une machine XXXX:213:e8ff:fe69:590d (où XXXX est le préfixe), on sait que c'est mon PC.

La solution initiale de ce problème avait été introduite par le RFC 3041, que notre RFC 4941 met à jour.

Les sections 1.2 et 2 du RFC décrivent le problème plus en détail. Elles notent entre autre que le problème n'est pas aussi crucial que l'avaient prétendu certains (une véritable campagne anti-IPv6 avait été montée à une époque par des gens mal informés). En effet, il existe bien d'autres façons, parfois plus faciles, de suivre une machine à la trace, par exemple par les fameux petits gâteaux de HTTP mais aussi par des moyens de plus haute technologie comme les caractéristiques matérielles de l'ordinateur, que l'on peut observer sur le réseau. Parmi les autres méthodes, notons aussi que si on utilise les adresses temporaires de notre RFC 4941 mais qu'on configure sa machine pour mettre dynamiquement à jour un serveur DNS avec cette adresse, le nom de domaine suffirait alors à suivre l'utilisateur à la trace !

La section 2.2, consacrée à la situation actuelle avec IPv4, fait d'ailleurs remarquer que la situation n'est pas parfaite avec IPv4 non plus, et que certains articles qui sonnaient l'alarme contre les dangers de IPv6 étaient donc vraiment peu informés. Aujourd'hui, en pratique, beaucoup de machines ont une adresse IPv4 qui change peu ou pas et elles sont donc plus vulnérables au « pistage » (sauf si elles changent de réseau souvent) que les machines IPv6 utilisant ce RFC 4941.

La section 2.4 commence à discuter des solutions possibles. DHCPv6 (RFC 3315, notamment la section 12) serait évidemment une solution, mais qui nécessite l'administration d'un serveur. L'idéal serait une solution qui permette, puisque IPv6 facilite l'existence de plusieurs adresses IP par machine, d'avoir une adresse stable pour les connexions entrantes et une adresse temporaire, non liée à l'adresse MAC, pour les connexions sortantes, celles qui « trahissent » la machine. C'est ce que propose notre RFC, en générant les adresses temporaires selon un mécanisme pseudo-aléatoire.

Enfin, la section 3 décrit le mécanisme de protection lui-même. Il y a deux cas, celui où on dispose d'un mécanisme de stockage des données, par exemple une mémoire Flash et celui où l'appareil, trop simple, n'a pas un tel mécanisme.

Le premier cas est détaillé dans la section 3.2.1 : on stocke une « valeur historique » à chaque génération d'une adresse. On utilise la valeur précédente, on la concatène à l'identifiant d'interface et on passe le tout à travers MD5. Les 64 premiers bits du résumé MD5 formeront le suffixe de l'adresse IPv6. La faiblesse cryptographique de MD5 n'est pas un problème, on ne cherche pas ici à résister à une attaque, juste à condenser un nombre aléatoire. Il n'est pas nécessaire que toutes les machines utilisent la même fonction de hachage et l'usage d'autres algorithmes que MD5 est donc autorisé.

La section 3.2.2 traite des cas où un dispositif de stockage n'existe pas et recommande alors l'usage d'une source réellement aléatoire, selon le RFC 4086.

Une fois l'adresse temporaire générée (les détails sont dans la section 3.3), il faut la renouveler de temps en temps (sections 3.4 et 3.5, cette dernière expliquant pourquoi renouveler une fois par jour est plus que suffisant). L'ancienne adresse peut rester active pour les connexions en cours mais plus pour de nouvelles connexions.

Maintenant que l'algorithme est spécifié, la section 4 du RFC reprend de la hauteur et examine les conséquences de l'utilisation des adresses temporaires. C'est l'occasion de rappeler un principe de base de la sécurité : il n'y a pas de solution idéale, seulement des compromis. Si les adresses temporaires protègent davantage contre le « flicage », elles ont aussi des inconvénients comme de rendre le débogage des réseaux plus difficile. Par exemple, si on note un comportement bizarre associé à certaines adresses IP, il sera plus difficile de savoir s'il s'agit d'une seule machine ou de plusieurs.

L'utilisation des adresses temporaires peut également poser des problèmes avec certaines pratiques prétendument de sécurité comme le fait, pour un serveur, de refuser les connexions depuis une machine sans enregistrement DNS inverse (un nom correspondant à l'adresse, via un enregistrement PTR). Cette technique est assez ridicule mais néanmoins largement utilisée.

Un autre conflit se produira, note la section 7, si des mécanismes de validation des adresses IP source sont en place dans le réseau. Il peut en effet être difficile de distinguer une machine qui génère des adresses IP temporaires pour se protéger contre les indiscrets d'une machine qui se fabrique de fausses adresses IP source pour mener une attaque.

Quelles sont les différences entre le RFC originel, le RFC 3041 et celui-ci ? Peu importantes, elles sont résumées dans la section 8. Les principales sont des demandes plus fortes sur la configurabilité de l'usage des adresses temporaires, l'acceptation explicite d'autres fonctions de hachage que MD5 et surtout le fait que le réglage standard par défaut doit désormais être de couper l'usage des adresses IP temporaires. En revanche, les changements ont été davantage prononcés avec la mise à jour suivante de cette technique, dans le RFC 8981.

Sur MS-Windows, ce mécanisme semble avoir été implémenté depuis Vista.

Sur Linux, notre RFC est mis en œuvre depuis longtemps (c'est l'option CONFIG_IPV6_PRIVACY de compilation du noyau), mais désactivé par défaut, comme demandé par le RFC (section 3.6). Le paramètre sysctl qui contrôle ce protocole est net.ipv6.conf.XXX.use_tempaddr où XXX est le nom de l'interface réseau, par exemple eth0. En mettant dans le fichier /etc/sysctl.conf :

# Adresses temporaires du RFC 4941
net.ipv6.conf.default.use_tempaddr = 2

On met en service les adresses temporaires, non « pistables » pour toutes les interfaces (c'est le sens de la valeur default). Il y a plusieurs pièges, très bien expliqués par Pascal Hambourg : au moment où le sysctl.conf est lu, le module noyau ipv6 n'est pas forcément chargé. Et certaines interfaces ont pu être configurées avant, alors que default ne s'applique qu'aux futures interfaces. Pour s'assurer que les réglages soient bien pris en compte, il vaut mieux faire en sorte que le module ipv6 soit chargé tout de suite (sur Debian, le mettre dans /etc/modules) et que les interfaces fixes aient leur propre réglage. Par exemple, sur Debian, on peut mettre dans /etc/network/interfaces :

iface eth2 inet dhcp
   pre-up sysctl -w net.ipv6.conf.eth2.use_tempaddr=2

Ou alors il faut nommer explicitement ses interfaces :

net.ipv6.conf.eth0.use_tempaddr = 2

Le comportement du noyau Linux face à ces options est souvent surprenant. Voir par exemple la bogue #11655. Notez aussi qu'ifconfig n'affiche pas quelles adresses sont les temporaires (mais ip addr show le fait).

Notons que l'adresse « pistable » est toujours présente mais vient s'y ajouter une adresse temporaire choisie au hasard. Selon les règles du RFC 6724, rappelées dans la section 3.1 de notre RFC, c'est cette adresse temporaire qui sera choisie, en théorie, pour les connexions sortantes. Avec Linux, il faut pour cela que use_tempaddr vale plus que un (sinon, l'adresse temporaire est bien configurée mais pas utilisée par défaut). ifconfig affichera donc :

wlan0     Link encap:Ethernet  HWaddr 00:13:e8:69:59:0d  
...
          inet6 addr: 2001:db8:32:aa12:615a:c7ba:73fb:e2b7/64 Scope:Global
          inet6 addr: 2001:db8:32:aa12:213:e8ff:fe69:590d/64 Scope:Global

puis, au démarrage suivant, l'adresse temporaire (la première ci-dessus) changera :

wlan0     Link encap:Ethernet  HWaddr 00:13:e8:69:59:0d
...
          inet6 addr: 2001:db8:32:aa12:48a9:bf44:5167:463e/64 Scope:Global
          inet6 addr: 2001:db8:32:aa12:213:e8ff:fe69:590d/64 Scope:Global

Sur NetBSD, il n'y a qu'une seule variable syscvtl pour toutes les interfaces. Il suffit donc de mettre dans /etc/sysctl.conf :

net.inet6.ip6.use_tempaddr=1

Par contre, je n'ai pas trouvé comment faire que l'adresse temporaire soit utilisée par défaut. Sur FreeBSD, je n'ai pas essayé, mais je suppose que les variables sysctl au nom bien parlant net.inet6.ip6.use_tempaddr et net.inet6.ip6.prefer_tempaddr sont là pour cela.

Ceux qui veulent configurer ce service sur une machine Linux peuvent aussi lire Stateless Network Auto Configuration With IPv6 ou IPv6 privacy extensions on Linux. Sur les autres systèms, je suggère Enabling Privacy Enhanced Addresses for IPv6.


Téléchargez le RFC 4941


L'article seul

Représentation sous forme texte de ce qui passe sur le réseau

Première rédaction de cet article le 25 août 2008
Dernière mise à jour le 18 mai 2020


Dans beaucoup de protocoles réseau, ce qui passe « sur le câble » est dans un format binaire incompréhensible pour un humain. Il est souvent utile de pouvoir le représenter sous forme texte, par exemple lorsque des programmes comme tcpdump le décodent. C'est encore mieux si ce format texte est normalisé, cela permet la communication facile entre humains. Regardons quelques exemples surtout empruntés à la famille TCP/IP. Ce sera l'occasion de voir que la syntaxe des adresses IPv4 n'a jamais été normalisée...


L'article complet

RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2

Date de publication du RFC : Août 2008
Auteur(s) du RFC : Tim Dierks (Independant), Eric Rescorla (Network Resonance)
Chemin des normes
Première rédaction de cet article le 24 août 2008


Le protocole de cryptographie TLS, autrefois nommé SSL, est un des protocoles de l'IETF les plus utilisés. À chaque seconde, des milliers de connexions TCP, en général HTTP, sont protégées contre l'écoute, et même parfois authentifiées par TLS. Ce RFC met à jour l'ancienne norme, le RFC 4346. (Depuis, la version 1.3, très différente, a été normalisée dans le RFC 8446.)

Aujourd'hui, plus personne n'aurait l'idée de faire circuler un mot de passe en clair sur le réseau, car il serait très facile à capturer (par exemple avec un programme comme dSniff). TLS fournit la confidentialité à une connexion TCP. (TLS peut aussi fonctionner avec d'autres protocoles de transport comme SCTP - RFC 3436 ou bien UDP - RFC 6347.)

L'authentification par mot de passe a par ailleurs des défauts, notamment que le mot de passe soit réutilisable. Si l'utilisateur a été victime d'un faux serveur, par exemple par suite d'un hameçonnage, il donne son mot de passe et le méchant qui contrôle le faux serveur peut l'utiliser sur le vrai site. Pour traiter ce problème, TLS fournit une solution d'authentification reposant sur les certificats X.509 ou bien sur les clés OpenPGP (RFC 5081). TLS permet aussi bien au client d'authentifier le serveur qu'au serveur d'authentifier le client (cette deuxième possibilité est à l'heure actuelle peu utilisée).

Les certificats X.509 sont composés de la partie publique d'une clé asymétrique et de métadonnées, comme la date d'expiration. Ils sont signés par une CA, qui a elle-même un certificat signé par une CA et ainsi de suite jusqu'à arriver aux CA racines installés dans le logiciel. La plupart du temps, l'utilisateur n'a jamais examiné ces certificats des CA racine et n'a aucune idée de leur fiabilité. C'est l'un des gros points faibles de l'authentification par TLS / X.509.

TLS n'est pas une solution miracle, il n'en existe pas en sécurité informatique. Par exemple, TLS ne protège pas dans les cas suivants :

  • Si un programme espion tourne sur la machine de l'utilisateur (ce qui est le cas de beaucoup, peut-être la plupart des machines MS-Windows),
  • Si le serveur est méchant ou mal protégé. Par exemple, un numéro de Carte Bleue transmis par TLS n'est protégé que pendant le voyage ! Si le serveur à l'autre bout stocke ces numéros et se fait pirater, TLS n'y pourra rien.

Passons maintenant au RFC proprement dit. Il fait plus de cent pages et pourtant de nombreux points n'y sont pas, comme la définition des algorithmes cryptographiques utilisés. La sécurité est un domaine compliqué, d'autant plus qu'une petite erreur peut annuler toute la sécurité de même que l'oubli de fermer à clé peut rendre inutile une lourde porte blindée.

TLS est composé de deux parties (section 1 du RFC), le Record Protocol, protocole de bas niveau qui transmet des messages en les chiffrant pour la confidentialité et l'intégrité et le Handshake protocol, bâti sur le premier, et qui se charge entre autres de négocier les paramètres de la session.

En effet, TLS fonctionne en négociant au début un algorithme de chiffrement ainsi qu'une clé cryptographique de cet algorithme pour la session. Le Record protocol va ensuite chiffrer les messages avec cette clé.

La section 4 du RFC détaille le langage de présentation. L'IETF n'a pas de langage unique de spécification, chaque RFC utilise des outils différents pour décrire ses protocoles ou algorithmes. TLS crée donc le sien, proche du C. Par exemple la section 4.4 décrit les nombres, tous créés à partir d'un type unit8, qui stocke un octet. La section 4.5 décrit les types énumérés comme enum { null, rc4, 3des, aes } BulkCipherAlgorithm; (le type qui sert à définir les valeurs de l'algorithme de cryptographie symétrique).

La section 6 décrit en détail le Record protocol. C'est un protocole qui va effectuer le chiffrement, mais aussi la compression, la fragmentation, etc.

La section 7 couvre le protocole de négociation (Handshake protocol). C'est le protocole qui permet l'authentification du serveur par le client (ou, plus rarement, le contraire) et la sélection des options, par exemple l'algorithme de chiffrement utilisé. L'authentification se fait en général en présentant un certificat X.509, certificat signé par un tiers de confiance (RFC 5280, en pratique, le tiers « de confiance » est une des CA installées par défaut avec le logiciel, dont personne ne sait pourquoi elles ont été choisies). Voici par exemple le résultat de ce protocole, tel qu'affiché par la commande gnutls-cli (qui est livrée avec GnuTLS) :

% gnutls-cli -d 9 www.example.org
Connecting to '192.0.2.20:443'...
...
|<3>| HSK[80708e8]: Selected cipher suite: DHE_RSA_AES_256_CBC_SHA

Le chiffrement AES en mode CBC a été choisi. gnutls-cli permet de voir le passage de tous les messages TLS de ce protocole, tels qu'ils sont décrits dans la section 7.4 :

      enum {
          hello_request(0), client_hello(1), server_hello(2),
          certificate(11), server_key_exchange (12),
          certificate_request(13), server_hello_done(14),
          certificate_verify(15), client_key_exchange(16),
          finished(20), (255)
      } HandshakeType;

Comme précisé dans la section 7.3, ce protocole de négociation a aussi ses propres vulnérabilités. Au démarrage, il n'y a évidemment pas d'algorithme de chiffrement ou de clé de session sélectionnés. Comme le précise la section 7.4.1, TLS démarre donc sans chiffrement. Un attaquant actif, capable de modifier les paquets IP, peut changer la liste des algorithmes acceptés, avant que le chiffrement ne soit actif, de façon à sélectionner un algorithme faible. (Le remède est de refaire la négociation une fois le chiffrement activé.)

Comme souvent avec TLS, le protocole est extensible. La section 7.4.1.4 décrit par exemple les extensions à l'annonce que font les machines TLS, possibilité qui est utilisée dans le RFC 5081 pour ajouter les clés OpenPGP aux certificats X.509. (Les extensions existantes étaient initialement décrites dans le RFC 4366 et sont désormais dans le RFC 6066. Le registre complet des extensions est maintenu à l'IANA.)

La section 9 indique l'algorithme de chiffrement obligatoire, RSA avec AES. Il est nécessaire de définir un algorithme obligatoire, autrement, deux mises en œuvre légales de TLS pourraient être incompatibles si les deux ensembles d'algorithmes n'avaient aucun élément en commun.

Par rapport à son prédécesseur, le RFC 4346, qui normalisait TLS 1.1, les changements sont de peu d'importance (la liste figure en section 1.2). Un client TLS 1.2 peut interagir avec un serveur 1.1 et réciproquement (voir l'annexe E pour les détails.) Il s'agit en général de clarifications ou bien du changement de statut de certains algorithmes cryptographiques. En effet, la cryptographie bouge et certains algorithmes, qui paraissaient solides à une époque, sont vulnérables aux attaques modernes (c'est par exemple ce qui est arrivé à MD5 et SHA1). C'est pour cela que l'algorithme « RSA avec AES » fait désormais partie des algorithmes obligatoires et que par contre IDEA et DES sont partis.

Contrairement à IPsec (RFC 4301), TLS fonctionne entre la couche de transport et les applications. Il n'est donc pas invisible aux applications, qui doivent être explicitement programmées pour l'utiliser. Pour cela, il n'existe malheureusement pas d'API standard. OpenSSL, l'implémentation la plus populaire de TLS, a la sienne, son concurrent GnuTLS en a une autre, etc. (GnuTLS dispose d'une couche d'émulation de OpenSSL mais elle est incomplète.)

Un programme comme echoping qui peut utiliser aussi bien OpenSSL que GnuTLS, doit donc recourir aux services du préprocesseur C, par exemple :

#ifdef OPENSSL
        ...
        SSL_set_fd(sslh, sockfd);
        if (SSL_connect(sslh) == -1)
#endif
#ifdef GNUTLS
...
        gnutls_transport_set_ptr(session, 
                                 (gnutls_transport_ptr) (long) sockfd);
        tls_result = gnutls_handshake(session);
...
#ifdef OPENSSL
        if ((rc = SSL_write(sslh, sendline, n)) != n) {
...
#ifdef GNUTLS
        if ((rc = gnutls_record_send(session, 
                                     sendline, strlen (sendline))) != n) {
...

Une autre solution pour une application qui veut faire du TLS sans se fatiguer est de compter sur le fait que TLS est indépendant du protocole utilisé par l'application et qu'on peut donc simplement créer un tunnel TLS, par exemple avec stunnel. Ainsi, on n'a même pas besoin de modifier le source de l'application.

Le déploiement de protocoles est toujours lent dans l'Internet. TLS 1.2, décrit dans ce RFC, ne s'est retrouvé dans le navigateur Firefox que cinq ans après.


Téléchargez le RFC 5246


L'article seul

RFC 5291: Outbound Route Filtering Capability for BGP-4

Date de publication du RFC : Août 2008
Auteur(s) du RFC : E. Chen (Cisco Systems), Y. Rekhter (Juniper Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 24 août 2008


Quand deux routeurs BGP échangent des routes, il est fréquent que certaines soient refusées par le routeur récepteur, par exemple parce qu'ils les estime invalides ou parce qu'elles ne correspondent pas à ses politiques de routage (section 2 du RFC). C'est donc un gaspillage que de les envoyer et ce nouveau RFC permet au routeur récepteur de signaler à l'avance à son pair BGP quelles routes il n'acceptera pas.

BGP, normalisé dans le RFC 4271 est le protocole d'échange de routes dans l'Internet. Pratiqué surtout entre organisations distinctes, il permet de faire du routage politique, cest-à-dire de rejeter certaines routes en fonction de la politique de chaque organisation. Pour cela, les routeurs BGP mettent typiquement en œuvre des filtres sur les routes reçues. Avec notre RFC, ces filtres peuvent être transmis au routeur pair sous le nom d'ORF (Outbound Route Filters) que le pair appliquera sur le jeu de routes qu'il allait annoncer, supprimant de ce jeu les routes qui ne conviennent pas à son pair.

La section 3 détaille ce qu'est un ORF. C'est un tuple composé de :

  • l'AFI/SAFI (qui permet notamment d'indiquer si la route concerne IPv4 ou bien IPv6), termes définis dans le RFC 4760.
  • le type d'ORF, qui sera enregistré dans un registre IANA (pas encore peuplé, cf. section 7).
  • l'action à effectuer sur cet ORF, typiquement ADD (l'ajouter à la liste) ou REMOVE (le supprimer).
  • la politique à appliquer aux routes qui corrspondent à ce critère (PERMIT ou DENY).
  • Et la valeur, dont le contenu dépend de l'AFI/SAFI, c'est typiquement un préfixe réseau.

La section 4 explique ensuite comment encoder les ORF et les transmettre dans une session BGP. Les sections 5 et 6 précisent que le routeur qui gère les ORF doit l'annoncer (cf. RFC 5492) par la capacité BGP n° 3 Outbound Route Filtering Capability.


Téléchargez le RFC 5291


L'article seul

Comment fonctionne la faille DNS « Kaminsky » ?

Première rédaction de cet article le 31 juillet 2008


La faille de sécurité DNS découverte par Dan Kaminsky à l'hiver 2007-2008 et annoncée le 8 juillet 2008 n'a pas encore été officiellement publiée en détail. Cela doit être fait le 8 août à la conférence BlackHat à Las Vegas. Mais, l'Internet étant ce qu'il est, il n'est pas étonnant que cette date n'aie pas été tenue et que les informations aient été publiées avant l'annonce officielle. Trois exploitations de la faille ont déjà été publiées. Plusieurs articles publics ont déjà repris en détail ces informations (voir par exemple, en français, l'article de Sid. On peut donc désormais expliquer en quoi cette faille consiste.

Je tiens d'abord à rappeler que des tas de bêtises ont été écrites sur l'Internet (et plus encore dans la presse papier ou à la télévision) sur cette faille. Ne vous fiez pas à des messages arrogants d'ignorants complets qui écrivent dans les commentaires d'un blog « La faille est une faiblesse du générateur aléatoire de BIND » ou bien « C'est une faille classique et il n'y a rien de nouveau ».

Plaçons un peu de contexte : le DNS fonctionne typiquement sur UDP (il peut aussi utiliser TCP et l'utilisation de ce protocole règlerait complètement la faille Kaminsky mais beaucoup de serveurs de noms sont incorrectement configurés et refusent les accès TCP). UDP n'a pas la notion de connexion et l'adresse IP de la machine avec laquelle on parle n'est donc pas du tout authentifée (avec TCP, elle est vérifiée par le processus de connexion, le 3-way handshake - section 3.4 du RFC 793 -, ainsi que par les numéros de séquence, qui doivent démarrer d'un nombre imprévisible). Lorsqu'un résolveur (le serveur de noms qui pose une question) interroge le serveur faisant autorité (le serveur de noms qui connait la réponse), il ne peut pas savoir si la réponse vient bien du serveur faisant autorité, elle peut venir d'un méchant qui a usurpé l'adresse IP de celui-ci, et répondu avant lui. Si le méchant peut donc deviner quant une requête va être émise (il existe des techniques pour cela, la plus simple étant de la générer soi-même, si le résolveur est un récursif ouvert, ou bien si on dispose d'un zombie autorisé à y accéder), cet attaquant peut envoyer une fausse réponse (en bombardant le vrai serveur en même temps, le méchant peut le ralentir pour augmenter les chances de gagner la course).

S'il n'y avait que cela, le DNS serait trivial à abuser. Mais quelques protections existent : la plus importante est que la requête DNS contient un nombre, le Query ID (QID, parfois appelé Transaction ID, TXID). Il est décrit dans la section 4.1.1 du RFC 1035. Le résolveur n'accepte une réponse que si elle contient un Query ID identique à celui qu'il a lui-même envoyé. La réponse doit également correspondre à une question actuellement en suspens et être reçue sur le port UDP d'où venait la question. (Il y a très longtemps, les implémentations du DNS étaient naïves et acceptaient à peu près n'importe quoi, ce qui est fini depuis belle lurette.) Malheureusement, le Query ID ne fait que 16 bits de long, ce qui est suffisant pour démêler des questions distinctes mais pas assez pour sécuriser la transaction. Envoyer 2^16 soit 65 536 réponses fausses pour qu'au moins une soit acceptée ne prend pas assez de temps, avec l'Internet rapide d'aujourd'hui. (Une vraie solution à la faille Kaminsky et à toutes les failles de la même famille serait de passer le Query ID à 128 bits. Mais cela serait un changement du DNS incompatible.)

Cette faiblesse du DNS est connu depuis très longtemps. Par exemple, en 1995, Paul Vixie écrivait « With only 16 bits worth of query ID and 16 bits worth of UDP port number, it's hard not to be predictable. A determined attacker can try all the numbers in a very short time and can use patterns derived from examination of the freely available BIND code. Even if we had a white noise generator to help randomize our numbers, it's just too easy to try them all. ». Ce risque (et d'autres) a été documenté par exemple dans le RFC 3833 en 2004. Il n'y a en effet rien de nouveau ici, mais la faille Kaminsky permet d'exploiter cette vulnérabilité avec bien plus d'efficacité qu'une attaque par force brute.

Jusqu'à présent, en effet, cette protection avait quand même suffit, à condition que le Query ID soit réellement aléatoire (suivant les recommandations du RFC 4086). Des problèmes étaient survenus avec le serveur DNS de Microsoft (qui n'utilisait que 14 des 16 bits du Query ID) ou avec BIND (générateur aléatoire bogué, faille CVE-2007-2926). Mais ils étaient facilement solubles en mettant à jour le logiciel bogué.

Fin 2007, la situation était donc d'une faiblesse connue (16 bits ne sont pas suffisants) mais peu exploitée car l'attaque n'était pas pratique. Typiquement, si on voulait empoisonner le cache d'un résolveur pour le nom www.example.com, il fallait d'abord attendre l'expiration de l'enregistrement stocké (si on a accès au résolveur, c'est facile, puisque le TTL est publié), faire en sorte qu'une question sur www.example.com soit générée (là encore, c'est beaucoup plus facile si on a accès au résolveur) et, pendant les quelques dizaines de millisecondes avant que les serveurs faisant autorité répondent, envoyer une bouffée de fausses réponses, en comptant qu'une corresponde. Même aidé par le paradoxe de l'anniversaire, cela ratait plus souvent que cela ne réussissait.

La menace se rapprochait toutefois suffisamment pour avoir poussé l'IETF à s'intéresser au travail de Bert Hubert sur la résistance aux faux. Ce travail est actuellement documenté dans l'Internet-Draft Measures for making DNS more resilient against forged answers. Ce document, pas encore approuvé, contient de très intéressants calculs quantitatifs sur l'attaque exposée ci-dessus, évaluant ses chances de succès (trop élevées, hélas) et proposant des mesures pour rendre l'attaque plus difficile, mesures dont la principale est la SPR (Source Port Randomisation, le fait de rendre le port UDP source imprévisible, le faisant ainsi venir au secours du Query ID). Ce travail avançait cahin-caha lorsque la nouvelle de la faille Kaminsky a commencé à circuler en février 2008.

Cette faille est très simple dans son principe. Elle repose sur la faiblesse expliquée ci-dessus (les 16 bits du Query ID ne représentent pas suffisamment d'entropie). Mais elle la rend facilement exploitable. Avant Kaminsky, toutes les attaques reposaient sur une question portant sur le nom qu'on voulait détourner. Si on voulait empoisonner le cache avec une fausse valeur pour www.example.com, on faisait poser au résolveur la question « Quelle est l'adresse IP de www.example.com ? » et on glissait une fausse réponse. Le problème de cette méthode est qu'on n'a droit qu'un un essai : même s'il reçoit plusieurs questions identiques de ses clients, le résolveur n'en envoie qu'une seule et il faut donc deviner le Query ID de cette unique question. Pire, si on rate son coup, la bonne réponse, celle qui vient du serveur faisant autorité, va être mise dans le cache du résolveur et, si le TTL a une valeur raisonnable, l'attaquant ne pourra pas réessayer avant plusieurs heures ou même jours.

Dan Kaminsky a innové essentiellement sur un point : si on veut fausser www.example.com, on va demander au résolveur des informations sur quelquechoseNNN.example.com où NNN est un nombre qui varie à chaque requête. Ainsi, le résolveur devra envoyer autant de requêtes que de noms de domaine différents, augmentant énormément les chances de l'attaquant, surtout s'il est aidé par le paradoxe de l'anniversaire. Notez que, le nom de la zone (ici example.com) doit être le même, pour que les requêtes aillent toutes au même serveur faisant autorité mais aussi pour passer les contrôles du paragraphe suivant.

Bon, maintenant, l'attaquant, au lieu de n'avoir qu'une seule chance, en a des milliers et l'attaque devient bien plus facile. Mais quel intérêt pour lui d'arriver à mettre une fausse réponse pour quelquechose5447.example.com dans le cache du résolveur ? C'était www.example.com qui l'intéressait ! C'est la deuxième innovation de Kaminsky. Dans la fausse réponse, l'attaquant glisse non seulement un enregistrement pour quelquechoseNNN.example.com (qui n'est pas obligatoire, on peut aussi répondre sans section Answer) mais également des enregistrements pour www.example.com dans les autres sections comme Additional. Les tests qu'effectuent les résolveurs ne suffiront pas à le rejeter puisque ce nom est dans le bailliage (les résolveurs rejettent les noms dits « hors-bailliage », les noms qui sont dans une autre zone que la zone du nom cherché, justement pour limiter les risques d'empoisonnement).

Si jamais le résolveur devenait davantage paranoïaque, il suffirait d'ailleurs de glisser de faux enregistrements NS (Name Server) et une fausse colle dans la section Authority, que le résolveur ne peut pas ignorer. C'est ce que fait une des exploitations, et voici la réponse DNS fausse, telle que vue par Wireshark. Ici, on a tenté de tricher sur l'adresse IP de www.example.com, un domaine dont les serveurs faisant autorité sont à l'IANA (ici, 193.0.0.236). On tente d'empoisonner le cache avec l'adresse 192.0.2.1 :

...
    Source: 193.0.0.236 (193.0.0.236)
    Destination: 192.0.2.253 (192.0.2.253)
User Datagram Protocol, Src Port: 53 (53), Dst Port: 49186 (49186)
    Source port: 53 (53)
    Destination port: 49186 (49186)
    Length: 175
    Checksum: 0x98a1 [correct]
        [Good Checksum: True]
        [Bad Checksum: False]
Domain Name System (response)
    Transaction ID: 0x0001
    Flags: 0x8400 (Standard query response, No error)
        1... .... .... .... = Response: Message is a response
        .000 0... .... .... = Opcode: Standard query (0)
        .... .1.. .... .... = Authoritative: Server is an authority for domain
        .... ..0. .... .... = Truncated: Message is not truncated
        .... ...0 .... .... = Recursion desired: Don't do query recursively
        .... .... 0... .... = Recursion available: Server can't do recursive queries
        .... .... .0.. .... = Z: reserved (0)
        .... .... ..0. .... = Answer authenticated: Answer/authority portion was not authenticated by the server
        .... .... .... 0000 = Reply code: No error (0)
    Questions: 1
    Answer RRs: 1
    Authority RRs: 1
    Additional RRs: 1
    Queries
        deb623f600000009.example.com: type A, class IN
            Name: deb623f600000009.example.com
            Type: A (Host address)
            Class: IN (0x0001)
    Answers
        deb623f600000009.example.com: type A, class IN, addr 1.1.1.1
            Name: deb623f600000009.example.com
            Type: A (Host address)
            Class: IN (0x0001)
            Time to live: 1 day
            Data length: 4
            Addr: 1.1.1.1
    Authoritative nameservers
        example.com: type NS, class IN, ns www.example.com
            Name: example.com
            Type: NS (Authoritative name server)
            Class: IN (0x0001)
            Time to live: 1 day
            Data length: 20
            Name server: www.example.com
    Additional records
        www.example.com: type A, class IN, addr 192.0.2.1
            Name: www.example.com
            Type: A (Host address)
            Class: IN (0x0001)
            Time to live: 1 day
            Data length: 4
            Addr: 192.0.2.1

L'attaque Kaminsky est donc bien nouvelle. Elle passe d'une méthode laborieuse et ayant de faibles chances de succès à une méthode qui marche à presque tous les coups et en très peu de temps (moins de dix minutes avec les exploitations publiées, beaucoup moins avec certaines non publiées).

Voici pourquoi il est donc urgent de mettre à jour, si ce n'est pas encore fait, les résolveurs DNS dont vous avez la responsabilité. À part PowerDNS et Unbound, qui le mettaient déjà en œuvre, cette mise à jour installe la SPR (rendre le port source aléatoire) sur les résolveurs. On passe ainsi de seulement 16 bits d'entropie (le Query ID) à 32 (le Query ID plus le port source, qui est également sur 16 bits). Cela retarde le moment où l'attaque sera efficace, en attendant des mesures plus radicales.


L'article seul

Y aura t-il un groupe de travail ALTO à l'IETF ?

Première rédaction de cet article le 31 juillet 2008
Dernière mise à jour le 14 novembre 2008


À la réunion IETF 72 de Dublin, la création du groupe de travail nommé ALTO pour Application Layer Traffic Optimisation n'est pas allée de soi et ne semble pas garantie.

À quoi sert ALTO ? La majorité du trafic sur Internet est aujourd'hui consacrée aux services pair-à-pair. Ces services remettent en cause bien des suppositions sur lesquelles avait été architecturé le réseau. Ils consomment autant de trafic montant que de descendant (contrairement à des systèmes asymétriques comme le Minitel ou l'ADSL), ils sont bavards, et imprévisibles. Il n'est donc pas étonnant que ces services se retrouvent souvent dans les médias comme à l'occasion du piratage des sessions BitTorrent par Comcast.

Tous ces points sont résumés dans l'expression du problème, l'Internet-Draft, draft-marocco-alto-problem-statement. À l'atelier P2P infrastructure workshop de l'IETF le 29 mai 2008 à Boston (dont le compte-rendu figure dans le RFC 5594), plusieurs mesures ont été étudiées, par exemple de meilleurs systèmes de contrôle de la congestion, mais aussi des mesures visant à améliorer la localité, mesures qui mènent à ALTO.

En effet, contrairement au client/serveur, pour lequel on cherche à accéder à une machine (et on ne peut optimiser que le chemin qui y mène), le pair-à-pair concerne l'accès à une ressource. On peut alors chercher un exemplaire de cette ressource qui soit plus proche. ALTO peut donc se résumer à « Quand on est à Dublin, télécharger le fichier à partir d'un pair à Londres plutôt qu'à Tokyo ».

Les machines terminales, celles des utilisateurs, ne sont pas forcément les mieux placées pour sélectionner les « meilleurs » pairs (notons que la définition de « meilleur » est un des sujets les plus chauds dans les discussions sur ALTO). Par exemple, elles n'ont aucune idée des coûts, de quels liens sont du transit cher et desquels sont du peering gratuit. ALTO repose donc sur un système d'« oracle » où le pair demande au serveur ALTO (l'oracle) de lui indiquer les meilleures solutions. Le futur protocole conçu par le futur groupe ALTO ne gérera que l'interface entre le client ALTO (le pair) et le serveur ALTO (l'oracle). Comment l'oracle prend sa décision est hors-sujet pour ALTO. L'oracle a pu utiliser les ICS, Meridian, un flux BGP ou un ensemble de préférences configurées manuellement, par exemple par le FAI.

Ça, c'était le principe. Maintenant, il y a les difficultés pratiques. Par exemple :

  • Est-ce que l'oracle doit donner des informations sur la topologie du réseau ou bien juste indiquer quel(s) pair(s) choisir ? Les opérateurs ne sont pas très chauds pour la première solution, car ils ne souhaitent pas distribuer d'informations sur leur réseau.
  • Comment le client ALTO trouve t-il l'oracle ?
  • Et la question qui ravira les fans de Matrix : le client peut-il faire confiance à l'oracle ? La question n'est pas purement théorique vu le nombre de FAI qui mentent délibérement à leurs clients (par exemple en réécrivant les réponses DNS).

Une fois le problème posé, quelles sont les solutions actuelles ? (Elles sont décrites dans un Internet-Draft, draft-hilt-alto-survey.) Il y a en gros deux catégories :

  • Les cas où c'est l'application qui cherche le meilleur pair, par exemple par des ping brutaux vers un ensemble de pairs potentiels (ce qui consomme beaucoup de ressources et ne supporte pas le passage à l'échelle) ou bien par des techniques plus intelligentes comme les ICS.
  • Les cas où c'est le réseau qui décide, ce qui est l'idée de base du projet P4P (une expérience P4P a été décrite dans le RFC 5632). ALTO fonctionnera ainsi, l'oracle pouvant utiliser des techniques comme ICS pour récupérer l'information qu'il servira à ses clients.

Naturellement, une des principales motivations pour ALTO est financière, d'où l'amusant exposé de Henning Schulzrinne (par ailleurs auteur de SIP) à Dublin à propos de l'économie de l'Internet. Compte-tenu du caractère fongible qu'à aujourd'hui la capacité des accès Internet, on peut calculer, par exemple, que l'envoi du contenu d'un DVD coûte aujourd'hui 1,05 $ US, uniquement en bande passante. Schulzrinne suggérait de signaler ces coûts à l'utilisateur par exemple « Do you want to watch the movie now (4$) or wait until night (2.5$)? ».

Enfin, le dernier document important dans l'état actuel du développement d'ALTO est le cahier des charges (Internet-Draft draft-kiesel-alto-reqs) que Sebastian Kiesel a présenté à Dublin. ALTO doit, selon ce document :

  • Se concentrer sur le protocole entre le client ALTO et le serveur ALTO (les mécanismes, par exemple, de synchronisation des informations entre serveurs ALTO étant ainsi exclus),
  • Ne pas mettre tous ses œufs dans le même panier. ALTO ne va pas résoudre tous les problèmes seuls et il est également nécessaire de réagir proprement à la congestion... et de se débrouiller correctement si, pour une raison ou une autre, ALTO n'est pas disponible.

La question délicate des informations que le client ALTO envoie au serveur ALTO n'est pas réglée. Il serait intéressant pour le serveur, afin de prendre une meilleure décision, que le client donne le plus de détails possibles (« Je compte télécharger le dernier album de Carla Bruni, au format zip, soit 631 méga-octets ») mais cela soulève évidemment bien des questions liées à la protection de la vie privée. La plupart des clients ne voudraient pas avouer le nom des ressources qu'ils téléchargent. Même la simple indication de la taille de la ressource pourrait donner trop d'indications à un oracle indiscret.

Il n'existe pas encore de documents sur le protocole lui-même.

C'est dans ce contexte que s'est tenu la réunion de l'IETF à Dublin le 29 juillet. Cette réunion avait le titre de BoF (Birds of a Feather, réunion informelle) puisque le groupe de travail n'est pas encore constitué. Ce fut un grand succès, avec plus de 150 personnes et un agenda chargé. Après les exposés résumés ci-dessus, une importante discussion porta sur la future charte du futur groupe de travail. Plusieurs questions ne posaient pas réellement de problème comme le fait que les questions de légalité du contenu seraient jugées hors-sujet. Les serveurs ALTO ne serviront donc pas à mettre en œuvre les desiderata de Sony ou d'Universal.

Une discussion très technique sur les caches suscita plus d'intérêt mais, gloalement, aucune objection à la charte ou au groupe de travail n'a été soulevée pendant la réunion.

C'est pourquoi ce fut une surprise pour beaucoup de voir une opposition apparaître au moment du « hum ». Le hum est une institution IETF, permettant d'indiquer une préférence, de manière non publique. Il consiste simplement à faire du bruit sans ouvrir la bouche. Le « hum » montra une salle partagée moitié-moitié. Il n'y a donc pas de consensus.

Quel était le problème ? Lisa Dusseault, Area Director (directrice de l'activité Applications à l'IETF), demanda si le problème était jugé inintéressant ? Insoluble ? Ou bien que la solution proposée risquait d'être dangereuse ?

Contrastant avec le silence pendant la réunion (timidité ?), la liste de diffusion ALTO a vu une longue discussion s'ensuivre. Une des objections les plus fréquentes était que les intérêts des utilisateurs et des FAI étaient différents, voire opposés, et qu'il n'y avait aucune chance qu'un oracle géré par le FAI puisse donner des réponses utiles aux utilisateurs.

Une objection plus technique était que le projet de charte ne restreignait pas assez l'ensemble des questions qui pouvaient être posées à l'oracle.

Enfin, encore plus politique, certains craignaient que, une fois déployés, les oracles deviennent plus ou moins obligatoires et qu'il ne soit plus possible à un pair d'un réseau pair-à-pair de ne pas obéir aux « suggestions » de l'oracle...

Finalement, l'IESG a approuvé la création du groupe le 12 novembre, avec une charte modifiée, qui cadre mieux ce que ALTO pourra faire ou ne pas faire, et un calendrier qui prévoit que l'essentiel du travail devra être terminé fin 2009. Le premier RFC a déjà été publié, le RFC 5693.


L'article seul

RFC 5283: LDP Extension for Inter-Area Label Switched Paths (LSPs)

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : B. Decraene (France Telecom), JL. Le Roux (France Telecom), I. Meinei (Juniper)
Chemin des normes
Première rédaction de cet article le 27 juillet 2008


Le protocole MPLS de commutation de paquets selon une étiquette (label) utilise souvent LDP comme mécanisme d'attribution des étiquettes. LDP ne fonctionnait bien qu'à l'intérieur d'une même zone du système autonome et ce nouveau RFC étend LDP pour le cas où on dispose de plusieurs zones.

La section 1 du RFC explique la motivation pour cette modification : un certain nombre d'opérateurs ont tiré profit du caractère hiérarchique de protocoles de routage internes comme OSPF ou IS-IS pour créer plusieurs zones (areas) dans leur système autonome. Ce découpage en zones (section 3 du RFC 2328) permet de gérer des très grands systèmes autonomes, en évitant que chaque routeur connaisse tout le réseau.

Mais, sur les réseaux MPLS utilisant LDP, pour qu'un routeur qui reçoit une correspondance entre une étiquette MPLS et une FEC (Forwarding Equivalent Class, section 2.1 du RFC 3031) la prenne en compte, la norme LDP (section 3.5.7.1 du RFC 5036) impose que la table de routage du routeur possède une entrée qui corresponde exactement cette FEC. Par exemple pour monter un tunnel MPLS, le routeur MPLS doit avoir dans sa table une route avec une correspondance exacte avec le point de sortie du tunnel, c'est-à-dire en IPv4 le préfixe en /32 ; avoir une route en /24 qui couvrirait ce /32 ne suffit pas.

En pratique, sur les réseaux MPLS utilisant LDP et qui ont un IGP multi-zones, monter des tunnels vers ou depuis des routeurs appartenant à d'autres zones nécessitait donc des bricolages comme l'annonce des adresses (préfixes en /32 ou bien /128 en IPv6) dans tous les sens entre tout plein de zones en passant aussi par la zone qui sert d'épine dorsale, ce qui est très lourd à gérer et rend l'intérêt des zones douteux. Elles avaient justement été conçues pour éviter de transporter des détails internes à une zone, en agrégeant les annonces de préfixes...

La section 4 du RFC détaille le problème, notamment dans le cas de tunnels (RFC 4364, RFC 4761 et RFC 4762). La section 6 fournit des exemples, avec de jolis dessins.

La section 5 présente la solution. Notre RFC 5283 permet donc désormais de faire accepter à LDP des associations étiquette/FEC pour lesquelles le LSR (le routeur MPLS) aurait des routes moins spécifiques, par exemple parce qu'elles ont été agrégées. C'est donc simplement l'application de la traditionnelle règle IP de la « meilleure correspondance » (longest match) à la sélection d'une étiquette MPLS.

L'ancienne règle continue à s'appliquer par défaut (le RFC impose que la nouvelle extension ne soit pas activée automatiquement). En effet, si on arrête de publier les préfixes les plus spécifiques, il faut que tous les routeurs MPLS de la zone acceptent l'extension. Elle est donc déployable de manière progressive (section 7.1) mais à condition de faire attention.

Merci à Sarah Tharan pour ses explications détaillées sur cette extension.


Téléchargez le RFC 5283


L'article seul

RFC 5279: A Uniform Resource Name (URN) Namespace for the 3rd Generation Partnership Project (3GPP)

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : A. Monrad, S. Loreto (Ericsson)
Pour information
Première rédaction de cet article le 26 juillet 2008


3GPP dispose désormais d'une famille d'URN, identifiée par le NID (Namespace IDentifier) 3gpp.

3GPP est un groupe de normalisation privé, composé de fournisseurs de systèmes de téléphonie mobile (section 1). Ses activités nécessitent des identificateurs stables et 3GPP a choisi les URN (RFC 8141).

La description complète de leurs URN apparait dans la section 2 du RFC et est également documentée en ligne en http://www.3gpp.org/tb/Other/URN/URN.htm.

La section 3 donne quelques exemples de ces nouveaux URN comme urn:3gpp:featurephones ou bien urn:3gpp:acme.foo-serv (cette seconde URN utilisant un système hiérarchique, non documenté dans le RFC, où « acme » est un opérateur et « foo-serv » un de ses services).


Téléchargez le RFC 5279


L'article seul

RFC 5290: Comments on the Usefulness of Simple Best-Effort Traffic

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : S. Floyd, M. Allman (ICIR/ICSI)
Pour information
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 25 juillet 2008


L'Internet a toujours fonctionné sur le principe du « fais au mieux » (best effort), c'est-à-dire que les applications qui l'utilisent n'ont aucune garantie sur les caractéristiques quantitatives du réseau qui sera à leur disposition. Le débit, par exemple, ne peut pas être connu à l'avance ; lorsqu'on commence un transfert de fichiers, on ne sait pas quand il se terminera. Ce principe a assuré le succès de l'Internet, par rapport à des réseaux concurrents qui se vantaient de leurs « garanties de qualité de service » et qui, en conséquence, offraient un service moyen nettement inférieur. Mais il est contesté par certains qui voudraient la possibilité de garantir une « qualité de service » (QoS pour « Quality of Service ») dans le réseau. Ce nouveau RFC ne tranche pas sur la question de savoir si la QoS est une bonne idée ou pas, il rappelle uniquement l'intérêt qu'il y a à disposer d'un mécanisme équivalent au « fais au mieux », une offre très efficace et qui correspond à beaucoup d'usages.

À l'époque où l'Internet avait du mal à s'imposer face aux réseaux prônés par les gens des télécommunications, appuyés par les gouvernements, un des reproches qui lui étaient le plus souvent fait était de ne pas garantir de « qualité de service » (QoS). Avant un appel téléphonique avec SIP, en effet, on ne peut pas savoir quel sera la capacité disponible, quel sera le RTT ou quelle sera la gigue. On peut les mesurer mais rien ne garantit que ces grandeurs resteront constantes pendant l'appel. Cela peut gêner certaines applications. C'est pour cela que des mécanismes visant à gérer la QoS ont été développés sur Internet comme intserv (RFC 1633) ou bien diffserv (RFC 2475). En pratique, ces mécanismes ont été très peu déployés, ce qui relativise la soi-disant demande de QoS. En général, il est moins coûteux d'augmenter le débit des tuyaux que de déployer ces mécanismes complexes. Mais certains vont plus loin et réclament le déploiement généralisé de QoS dans Internet, au point de ne plus garder de service « fais au mieux ». C'est là qu'intervient notre RFC 5290.

Sa thèse de base est que le socle de l'Internet doit rester un service « fais au mieux » (quitte à ajouter quelques mécanismes de QoS par dessus). Ce service est défini comme « tout ce qui ne bénéficie pas d'un service différencié » (section 1). Un moyen simple d'assurer ce service est l'« équité entre les flux » (flow-rate fairness).

La section 2 expose les propriétés de ce service simple best effort. En 2.1, les auteurs listent les forces de ce service :

  • Il ne demande pas trop d'efforts de la part de l'infrastructure réseau : les routeurs, par exemple, ont ainsi le minimum de travail. Ce service libère ainsi des ressources pour, par exemple, augmenter la capacité (les réseaux télécoms traditionnels passaient tellement de temps à gérer la QoS que leur débit total était sérieusement réduit).
  • Il ne demande pas trop de mécanismes économiques entre les opérateurs. Une des principales raisons du très faible déploiement de diffserv est qu'il nécessite des mécanismes de compensation entre opérateurs. Autrement, tout le monde enverrait ses paquets avec la classe la plus favorisée ! Ces compensations sont complexes et nécessitent des accords entre opérateurs qui vont plus loin que les mécanismes actuels entre opérateurs, ou entre un opérateur et son client.
  • Et, surtout, ce service « fais au mieux » est utile dans le monde réel. Il marche, pour une grande variété d'applications, et il propulse l'Internet depuis trente ans, malgré les affirmations (qu'on trouve par exemple dans la quasi-totalité des ouvrages universitaires sur les réseaux informatiques publiés en France) comme quoi un réseau sans QoS ne servait à rien.

Évidemment, tout n'est jamais uniformément rose. Le service « fais au mieux » a aussi des limites, que détaille la section 2.2. D'abord, certains utilisateurs veulent de la QoS et sont prêts à payer pour cela (section 2.2.1). Il ne faut pas les en priver mais cette demande soulève des questions très diverses. Par exemple, l'ensemble des ressources réservées pour les services « à garantie » ne doit pas mener à l'épuisement des ressources pour le service de base, autrement les riches utilisateurs pourraient s'approprier tout le réseau pour eux. Il existe une abondante littérature (le RFC donne quelques références) sur l'économie de l'Internet, la légitimité et l'efficacité de faire payer de manière différenciée, etc. Ensuite, les services avec QoS peuvent interférer avec la « transparence du réseau ». En effet, il n'est pas difficile d'imaginer des cas où, pour certaines applications, celui qui ne paierait pas le surcoût de la QoS serait, en pratique, exclu du réseau. Mais le débat est loin d'être clos sur la question de savoir quel niveau de QoS reste compatible avec cette transparence du réseau. (Le RFC 2990 donne des éléments de départ sur l'architecture de QoS.)

Une autre faiblesse du « fais au mieux » est sa sensibilité aux incivilités (section 2.2.2). Si un certain nombre d'utilisateurs ne jouent pas le jeu, le réseau peut s'effondrer puisqu'il n'y a pas de limites à l'allocation de ressources. Dans cette optique, les services différenciés ne seraient pas tant un moyen de « donner plus à ceux qui paient plus » qu'un mécanisme de contrôle de la congestion, même en présence d'implémentations « agressives » de TCP/IP, qui ne respecteraient pas les règles énoncées dans le RFC 2914.

Enfin, la dernière faiblesse (section 2.2.3) est le cas de « pics » de trafic brutaux (suite à une DoS ou tout simplement en cas de grand succès d'un site Web), pour lesquels le mécanisme « fais au mieux » mène en général à ce que personne ne soit servi...

Après ce tour des forces et faiblesses du mécanisme « fais au mieux », le RFC aborde, dans la section 3, le concept d'« équité entre les flux ». L'idée est que cette équité ne serait certes pas parfaite, mais assurerait un service « fais au mieux » qui soit convenable pour tout le monde. Notre RFC paraphrase Winston Churchill en disant que l'équité entre les flux est le plus mauvais des services, à l'exception de tous les autres.

En effet (section 3.1), cette équité serait relativement facile à mettre en œuvre (pour TCP, qui forme la grande majorité du trafic actuel, elle est déjà implémentée dans ses algorithmes), elle ne nécessite pas de calculs de facturation complexes, elle marche aujourd'hui et elle satisfait une notion sommaire, mais raisonnable, de la « justice » puisque chaque flot aura une part de la capacité du réseau.

Elle a par contre des limitations (section 3.2). Elle est difficile à faire respecter (section 3.2.1). En effet, dans l'Internet actuel, son respect dépend des machines aux extrémités du réseau, machines qui sont sous le contrôle d'un utilisateur qui peut être un méchant égoïste. Changer ce système pour que les routeurs fassent le contrôle serait un changement considérable d'architecture. Et, après tout, l'Internet s'en est passé jusqu'à présent.

Une deuxième question est qu'il n'existe pas de définition claire et consensuelle de ce qu'est l'équité entre les flux. Tout le monde est pour l'équité, c'est lorsqu'on essaie de la définir que les ennuis commencent (section 3.2.2). D'abord, « flux » (flow) n'est pas bien défini (cf. RFC 2309, RFC 2914, RFC 3124 et bien d'autres). Est-ce par connexion ? (Un concept qui n'existe pas pour tous les protocoles, par exemple UDP.) Ou bien pour tout trafic entre deux machines ? Ou bien, à une granularité intermédiaire, faut-il mettre toutes les connexions TCP démarrées par le même navigateur Web ou bien le même client BitTorrent dans le même flux ? Et l'équité doit-elle se mesurer en nombre de paquets ou en octets/seconde ? (Les protocoles interactifs comme SSH préféreraient certainement la première solution.) Et que faire avec les protocoles où le trafic tend à être très irrégulier ? Faut-il une équité « en moyenne » ? Si oui, sur quelle période ? Bref, si l'objectif politique est clair, le traduire en chiffres précis semble très difficile.

La section 4 du RFC 5290 s'attaque à un problème sur lesquels bien des protocoles se sont brisés : le déploiement. Pour reprendre l'exemple traditionnel du fax, celui qui a acheté le premier fax a fait preuve d'une confiance aveugle dans le succès de la technologie. Son fax ne lui servait à rien. Ce n'est qu'une fois qu'un nombre suffisant d'acheteurs s'en sont procuré un que son achat avait un sens. De même, une bonne partie des difficultés d'IPv6 s'explique par cet effet « œuf et poule ». Les premiers à déployer IPv6 n'ont aucun intérêt à le faire (ils ne pourront communiquer avec personne). Résultat, le déploiement ne se fait pas.

Et pour la QoS ? C'est le même problème : déployer un réel système de QoS sur l'Internet nécessiterait des actions par un certain nombre d'acteurs différents et ceux-ci ne voient pas de motivation à le faire. Voici pourquoi presque tous les déploiements actuels de QoS sont restés limités à une seule organisation.

Enfin, la section 5 décrit le travail qui a été fait, à l'IETF et ailleurs, sur ce problème. L'histoire de la qualité de service sur l'Internet est vieille, on trouve déjà une discussion dans le RFC 896, mais aussi, plus tard, dans le RFC 2212 et RFC 2475. Le RFC 2309 traite du cas où certains flux ne jouent pas le jeu et tentent d'occuper toute la capacité disponible et le RFC 3714 de la notion d'équité. La référence reste le RFC 2914 sur les principes de contrôle de congestion sur l'Internet.

La section 5.2 contient plusieurs autres références sur le travail fait à l'extérieur de l'IETF comme les articles Flow Rate Fairness: Dismantling a Religion ou Pricing the Internet.


Téléchargez le RFC 5290


L'article seul

RFC 5218: What Makes For a Successful Protocol?

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : D. Thaler (IAB), B. Aboba (IAB)
Pour information
Première rédaction de cet article le 25 juillet 2008


Qu'est-ce qui fait qu'un protocole a du succès ou pas ? Pourquoi certains restent-ils dans une petite niche alors que d'autres accèdent à la domination mondiale ? Et y a t-il des leçons à tirer de ces succès et de ces échecs, pour améliorer les prochains protocoles ? C'est à ces questions que s'attaque le dernier RFC de l'IAB, « qu'est-ce qui fait un succès ? ».

Il n'y a évidemment pas de réponse simple et univoque. Le RFC 5218 ne tente bien sûr pas de trouver une recette simple qui garantirait le succès. Il liste plutôt des facteurs qui jouent un rôle, essayant d'évaluer l'importance de ce rôle. La moitié du RFC est constituée d'études de cas où plusieurs protocoles sont étudiés du point de vue de ces facteurs.

Ce qui est sûr, c'est que la qualité technique du protocole n'est qu'un des facteurs, et pas le plus important.

Au sein des protocoles IETF, pourquoi Diameter (RFC 3588, puis RFC 6733) n'a t-il jamais remplacé Radius (RFC 2865) ? Pourquoi SNMP v1 (RFC 1157) continue t-il à être tant utilisé ? Et, bien sûr, même s'il est très peu cité dans le RFC, pourquoi IPv6 (RFC 2460) n'a t-il pas remplacé IPv4 (RFC 791) ? Pourtant, à chaque fois, le protocole présenté comme « le successeur » avait bénéficié d'un marketing vigoureux.

Entre protocoles IETF et protocoles d'autres origines, pourquoi IP a t-il écrasé IPX, qui était probablement techniquement supérieur, ou bien OSI, qui bénéficiait d'un soutien politicien et bureaucratique marqué ?

La section 1.1 du RFC commence par tenter de définir ce qui fait le succès. BGP (RFC 4271) est un succès, bien qu'il ne soit installé que sur un petit nombre de machines et qu'il ne soit utilisé directement que par une petite minorité de personnes. DHCP (RFC 2131) est un autre exemple d'un succès qui ne se voit pas forcément, puisqu'il n'est utilisé qu'à l'interieur d'un site (DHCP est un « protocole TCP/IP » mais pas vraiment un « protocole Internet »). Même chose pour OSPF (RFC 2328). En revanche, les protocoles célèbres, utilisés à travers l'Internet, sont des succès incontestables comme HTTP (RFC 2616), SIP (RFC 3261) ou le DNS (RFC 1034).

La section 1.2 essaie de quantifier cette question en parlant des deux dimensions du succès : les usages et l'échelle. Un protocole est conçu pour certains usages. Le succès signifie souvent qu'il est utilisé pour d'autres usages. Un protocole est prévu pour une certaine échelle d'utilisation et le succès va souvent le conduire à la dépasser largement (par exemple, il y a bien plus de machines connectées à l'Internet que n'en prévoyaient ses concepteurs, même dans leurs rêves les plus fous). Le RFC invente même le concept de « succès fou » (wild success) pour désigner les protocoles qui, comme IPv4, ont dépassé toutes les espérances.

HTTP (section 1.2.1) est un exemple encore meilleur d'un succès fou. Il a dépassé les usages prévus (puisqu'on se sert de HTTP en dehors du Web, par exemple pour REST et XML-RPC, voire pour traverser les coupe-feux et « tunneler » le trafic). L'ampleur de son déploiement a aussi largement dépassé les ambitions initiales de Tim Berners-Lee !

Plus complexe, toujours en section 1.2.1, est le cas d'ARP (RFC 826). En ampleur du déploiement, c'est un grand succès. Mais ses usages ont été réduits : conçu pour fonctionner sur n'importe quel type de réseau local, il n'a jamais été déployé que sur Ethernet.

Alors, est-ce souhaitable pour un concepteur de protocole de voir son bébé devenir un « succès fou » ? Ce n'est pas évident, comme le note la section 1.3. Avoir un succès fou a des conséquences, certaines bonnes et d'autres mauvaises. Par exemple, le succès peut entraîner le protocole aux limites de ses capacités quantitatives, « problème » que connait actuellement IPv4, dont les quatre milliards d'adresses possibles ne sont plus suffisantes. (À l'époque de sa conception, le modèle dominant était « un ordinateur par organisation ». Il est passé ensuite à « un ordinateur par département » puis « un ordinateur par personne » et le modèle actuel de plusieurs ordinateurs par personne est une des causes de l'épuisement des adresses IPv4.)

De même, le succès peut aggraver ou révéler des problèmes de sécurité : le protocole qui réussit va attirer l'attention des craqueurs.

Et l'échec ? Symétrique du succès, c'est le sort de certains protocoles. La section 1.3 essaie de l'analyser. D'abord, il ne faut pas forcément être pressé. Au début, un protocole n'a aucun déploiement et aucune implémentation. Ce n'est qu'avec le temps qu'on peut dire que le protocole a réussi ou échoué. HTTP a mis plusieurs années à décoller, par exemple. IPv4 est resté le protocole d'un petit réseau inconnu des décideurs et des journalistes pendant de nombreuses années.

Les protocoles réseaux ont un problème particulier à surmonter, celui de l'œuf et la poule (un terme que critique notre RFC, d'ailleurs). En effet, le réseau ne sert à rien si on est tout seul. Si j'invente un protocole de courrier électronique supérieur à SMTP (avec l'expérience qu'on a aujourd'hui, ce n'est pas très difficile), ce protocole, si réussi soit-il, ne servira à rien puisque j'en serai le seul utilisateur et que je ne pourrai donc envoyer du courrier à personne. Le cercle vicieux s'enclenche facilement : personne n'a déployé le nouveau protocole donc les auteurs de logiciels ne se pressent pas pour l'intégrer dans leurs programmes donc les utilisateurs ne s'en servent pas, donc il n'y a pas de déploiement, etc. Tout le monde aurait intérêt à ce que le nouveau protocole réussisse mais les premiers convertis supporteraient tous les coûts. En l'absence d'une autorité centrale qui pourrait ordonner le déploiement du nouveau protocole, bien des propositions de réforme ont ainsi été victimes de ce que les économistes appellent un échec du marché.

Quelles sont les méthodes pour faire face au problème de l'œuf et de la poule ? La section 1.3 en cite plusieurs :

  • Résoudre un problème immédiat et brûlant, ce qu'a fait, par exemple, le NAT (RFC 3022).
  • Fournir un « service qui tue » (killer app), comme l'ont fait les services de distribution de fichiers en pair-à-pair, service tellement utile que les utilisateurs sont prêts à faire des efforts, par exemple à reconfigurer leur routeur.
  • Être invisible, c'est-à-dire ne nécessiter aucun changement.
  • Réduire les ambitions, en diminuant les usages prévus, ce qui rend le succès plus facile. C'est ainsi que la diffusion restreinte (multicast) sur tout l'Internet, telle qu'envisagée à l'origine, a été un échec mais cette même diffusion restreinte est largement pratiquée sur les réseaux locaux.
  • Obtenir une aide ou une directive gouvernementale. La question est chaudement disputée, les adorateurs du marché aimant prétendre que l'Internet s'est créé tout seul, par le seul jeu non régulé des forces du marché. Rien n'est plus faux, l'Internet et son prédécesseur Arpanet ont vécu pendant quinze ans aux crochets de l'état états-unien. Mais l'intervention de l'État (à part sous une dictature extrême du genre Ivan le Terrible) ne marche pas toujours, les acteurs gardant leur liberté. Le RFC cite l'intervention du gouvernement japonais en faveur d'IPv6 mais, si cette aide a permis à Kame de faire un travail très intéressant sur IPv6, ce protocole reste minoritaire au Japon comme ailleurs. De même, les protocoles OSI ont nettement perdu face à TCP/IP malgré un soutien gouvernemental très obtus (par exemple en France). Et, dans un domaine différent de celui des réseaux, le langage de programmation Ada ne s'est pas imposé, en dépit d'une consigne officielle de n'utiliser que lui pour tous les programmes de l'armée états-unienne (le plus gros consommateur de logiciels du monde).

La section 2 explore les différentes causes de succès, en précisant bien qu'aucun succès n'a réuni toutes ces causes. 2.1 se spécialise dans les raisons du succès « de base », 2.2 dans celles du succès fou.

D'abord, le protocole doit évidemment avoir un intérêt et cet intérêt doit compenser les coûts (section 2.1.1). Si les coûts liés au matériel sont les plus visibles, ils ne sont pas forcément les plus importants. Ainsi, tout protocole qui nécessite de re-former les utilisateurs a un travail plus difficile pour s'imposer car le coût de cette formation est non-trivial. Les coûts liés à l'invalidation des anciens calculs économiques sont également à prendre en compte : si un FAI fonde son modèle économique sur des connexions Internet intermittentes, un protocole qui permet d'être connecté tout le temps comme l'ADSL, va remettre en cause ce modèle (de façon significative, mais étonnante pour un RFC, le paragraphe sur l'économie est le plus long de la section).

Et quels sont les bénéfices possibles ? Résoudre un problème lancinant (DHCP a ainsi mis fin au cauchemar des administrateurs réseaux courant de machine en machine pour faire un changement), permettre des choses qu'on ne faisait pas avant, ou rendre simplement plus efficace les choses qu'on faisait déjà (de tels protocoles sont souvent plus simple à déployer car ils ne remettent pas en cause les usages). Si le coût initial est élevé, le protocole peut avoir du mal à s'imposer, même si les bénéfices futurs sont prometteurs.

En outre, coûts et bénéfices ne sont pas équitablement répartis. Les techniques de NAT sont très coûteuses pour les développeurs d'applications, qui doivent coder des contournements compliqués mais apportent des bénéfices aux FAI, qui font des économies d'adresses IP. Tout dépend donc de qui décide. Le RFC note donc que le succès d'un protocole vient souvent de « l'alignement des coûts et des bénéfices », c'est-à-dire du fait que les bénéfices viennent à ceux qui supportent les coûts initiaux (même si, comme dans le cas du NAT, les coûts finaux sont payés par d'autres).

Ensuite, pour être un succès, le protocole a tout intérêt à être déployable petit à petit (section 2.1.2). En effet, le dernier flag day (tout l'Internet change de protocole le jour J à l'heure H) a eu lieu en janvier 1983 lors du déploiement d'IPv4 (et du passage à TCP/IP). Aujourd'hui, il est complètement impossible de changer tout l'Internet d'un coup et le nouveau protocole doit donc pouvoir s'intégrer à l'Internet existant (le grand drame d'IPv6 vient de là).

D'autres causes de succès non technique sont la disponibilité du code en logiciel libre ou quasi-libre (sections 2.1.3 et 2.1.4), le fait que le protocole soit ouvert (section 2.1.5) et maintenu par une SDO selon un processus ouvert (section 2.1.6, qui est un peu un plaidoyer pro domo pour l'IETF). Le succès d'IPv4 contre IPX ou OSI (ce dernier cas n'est pas cité par le RFC mais est encore plus net) tient largement à ces points. TCP/IP a gagné en bonne partie par sa disponibilité dans les Unix de Berkeley.

Le fait que la norme soit « ouverte » joue un rôle important, ce qui explique aussi la vigueur des débats dans le groupe de travail IPR de l'IETF. Les RFC ne sont pas les normes les plus ouvertes du monde, par exemple leur licence (RFC 5378) limite les usages qui peuvent en être faits...

Et la technique, alors, elle ne joue aucun rôle ? Un peu quand même, argumente la section 2.1.7, qui explique qu'un protocole bien conçu a davantage de chances.

Mais le succès est une chose et le succès fou en est une autre. Qu'est-ce qui cause un succès fou ? L'extensibilité et l'absence de limites aident (sections 2.2.1 et 2.2.2). DECnet était limité par construction à 65 536 machines, ce qui garantissait son échec à terme, même s'il avait connu de bons débuts.

L'un des points où il y a la plus grosse différence entre le succès et le succès fou concerne la sécurité (section 2.2.3). Au début, il n'est pas nécessaire qu'un protocole soit sûr (ce point est développé également en section 3). Compte-tenu des divers coûts associés à la sécurité, notamment les difficultés d'usage, faire l'impasse sur la sécurité est en général un bon moyen de réussir au début. Mais, lorsque le protocole devient très répandu, les craqueurs se précipitent dessus et cherchent à le subvertir. C'est alors que les impasses qui avaient été faites sur la sécurité peuvent se payer cher. Néanmoins, foncer d'abord et réfléchir ensuite à la sécurité semble être une bonne stratégie (les protocoles qui intègrent la sécurité dès le début ne sont souvent jamais déployés et donc jamais attaqués).

Notons que l'annexe A, qui représente la moitié du RFC, décline ces analyses pour une série d'étude de cas. C'est ainsi que sont examinés :

  • Protocoles Web (HTTP et HTML) contre Gopher (section A.1). La qualité technique n'a guère joué (HTML à cette époque était très pauvre et, contrairement à ce que dit le RFC, n'avait même pas les formulaires). Mais le déploiement était simple et apportait des bénéfices immédiats.
  • IPv4 contre IPX (section A.2). Il existait d'innombrables protocoles réseaux à l'époque. Tout administrateur réseau devait en gérer plusieurs. Aucun des protocoles concurrents n'était déployable progressivement mais la base installée était faible. Certains de ces protocoles avaient des limites fondamentales (comme AppleTalk) qui leur interdisaient d'être le protocole d'un réseau mondial. IPX n'avait pas ces défauts et avait bien des avantages techniques sur IPv4 (comme l'auto-configuration, alors que DHCP n'existait pas encore). Mais la grande force d'IPv4 était la disponibilité d'une mise en œuvre libre, dans BSD (financée par des fonds publics). Même chose pour la disponibilité d'une norme.
  • SSH (section A.3). Ce protocole (RFC 4251) a remplacé telnet et rlogin en très peu de temps. Très simple à installer et à utiliser (beaucoup l'ont adopté uniquement pour la redirection des sessions X11, un énorme progrès à l'époque), ne nécessitant pas d'infrastructure centrale (contrairement aux solutions à base de Kerberos), SSH, malgré un statut légal peu clair au début, s'est vite imposé. Les puristes de la sécurité avaient pourtant critiqué cette simplicité (bien que beaucoup de solutions de sécurité aient échoué en raison de la grande complexité qu'elles imposaient aux utilisateurs). Le modèle TOFU (Trust On First Use) de SSH leur semblait une hérésie. Mais l'alternative était du telnet avec zéro sécurité. (Aujourd'hui, des techniques comme Perspectives tentent d'améliorer le système TOFU.)
  • Diffusion restreinte (multicast) entre domaines distincts (section A.4). C'est cette fois un échec qui est analysé. Le multicast (RFC 5110) a souvent été présenté comme indispensable aux services multimédia sur Internet mais la réalité est qu'il n'a jamais connu d'utilisation significative. Pourquoi ? Il manquait de la plupart des facteurs de succès. Il n'est pas évident qu'il répondait à un problème réel (la diffusion est utile si tout le monde regarde la même chaîne de télévision en même temps, comme dans les années 60, mais elle ne sert à rien pour la VoD). Il nécessite des grands changements dans tous les routeurs du chemin. Bref, les coûts étaient importants et les bénéfices peu clairs.
  • WAP (section A.5) est un autre échec, qui avait pourtant bénéficié d'un marketing très lourd et peu subtil, composé essentiellement d'affirmations tonitruantes comme quoi « 90 % des accès au Web se feraient en WAP dans cinq ans » et autre fumage de moquette de consultant. Coincé entre le classique HTTP et le plus perfectionné I-Mode, WAP n'apportait rien de précis. Très fermé (licences à acheter, normes non accessibles, évolution pilotée par une organisation où le coût d'adhésion était de 27 000 $), WAP n'est pas allé loin. Il est amusant a posteriori de compter le nombre d'articles sur WAP qui étaient parus dans la presse pour décideurs, alors qu'il n'avait connu aucun déploiement, par rapport au nombre d'articles qu'avait eu IP alors que l'Internet était déjà massivement utilisé.
  • La lutte du protocole IETF Radius (RFC 2865) contre le protocole de Cisco Tacacs (section A.7) est un autre cas où la disponibilité d'une norme ouverte et sans entraves a été le facteur dominant. Tacacs a évolué par la suite, une implémentation libre est apparue, ainsi qu'une norme (RFC 1492) mais c'était trop tard.
  • Plus douloureux est le succès du NAT (section A.8). Apportant un bénéfice immédiat à celui qui le déploie (le IP masquerading de Linux, première mise en œuvre répandue du NAT, avait été un succès foudroyant et avait beaucoup contribué au décollage de Linux), le NAT, propulsé par la pénurie d'adresses IPv4, s'est répandu partout, en dépit de l'opposition vigoureuse de l'IETF. Le fait qu'il apportait un bénéfice à court terme et qu'il était déployable sur un site sans aucune coordination avec les autres lui ont permis de progresser très vite.

La section 3 sert de conclusion au RFC. Elle estime que les facteurs de succès les plus importants sont le fait que le protocole apporte un avantage réel et le fait qu'il puisse être déployé progressivement, sans flag day.

Les qualités techniques du protocole sont secondaires et le RFC note, à juste titre, que beaucoup de protocoles ayant connu un succès fou ne passeraient pas l'examen de l'IESG aujourd'hui...

La conclusion finale est donc que l'examen par l'IETF des nouveaux protocoles devrait donc inclure l'étude des facteurs de succès.

Enfin, je note que l'IAB n'a guère mentionné des cas où l'échec est plus gênant pour l'IETF comme le peu de déploiement d'IPv6...


Téléchargez le RFC 5218


L'article seul

Fiche de lecture : Honni soit qui mal y pense

Auteur(s) du livre : Henriette Walter
Éditeur : Laffont
978-2-253-15444-0
Publié en 2001
Première rédaction de cet article le 25 juillet 2008


Aujourd'hui, on tend souvent à opposer l'anglais et le français, par exemple dans les réunions francophones où on discute de l'inquiétante montée de l'anglais dans le monde. Mais les deux langues ont en fait une importante histoire en commun, se sont mutuellement influencées, et la connaissance de leurs relations tumultueuses, par exemple par la lecture du livre d'Henriette Walter, peut aider à mieux les comprendre toutes les deux.

Henriette Walter nous entraîne à travers quatorze ou quinze siècles d'histoire commune. Le lecteur devra réviser pour suivre les bouleversements historiques qui font que, par exemple, la cour d'Angleterre parlait français au XIème siècle (et le roi d'Angleterre était donc incapable de comprendre ses sujets) mais l'avait abandonné au XVème. Deux langues proches géographiquement, dont les locuteurs ont beaucoup commercé, beaucoup échangé d'idées et se sont beaucoup fait la guerre. Cela crée des liens et les échanges ont été innombrables entre les deux langues, dans le vocabulaire et dans la grammaire. Et bien d'autres langues ont participé à l'évolution du français et de l'anglais comme l'italien ou les langues scandinaves.

Le livre est rempli d'informations éclairantes à ce sujet. Je ne savais pas que challenge, un mot symbole du franglais était à l'origine un mot français (qui s'écrivait « chalenge »), apporté par les Normands, disparu en France entre-temps et revenu ensuite via les États-Unis. Ni que l'on peut dire computer pour ordinateur, le mot était français, voulait dire « calculer » et venait en droite ligne du latin (ceci dit, un ordinateur ne sert pas qu'à calculer, mais aussi à écrire et à diffuser ce texte...).

Outre son côté ludique, ses nombreuses anecdotes historiques et ses tests (« Quels sont les noms d'animaux qui sont identiques en anglais et en français, comme condor, alligator, lion ou python ? »), ce livre est également très pratique pour chercher un mot particulier, grâce à un excellent index.

Un chapitre très intéressant concerne les langues de la science. Mais c'est là où j'ai trouvé les deux plus grosses erreurs du livre : Henriette Walter affirme que « client-serveur » est un calque, c'est-à-dire un mot formé selon les règles de grammaire d'une autre langue, ici l'anglais, puisque, dit-elle, le déterminant précède le déterminé. Mais l'explication est fausse, « client-serveur » ne veut pas dire « le serveur du client » mais exprime une relation entre deux parties.

De même, Henriette Walter affirme que « attracteur étrange » est « mystérieux » et prétend que le mot strange de l'anglais strange attractor aurait du être traduit par « étranger » alors que n'importe quel livre de physique lui aurait montré que les attracteurs étranges sont bien... étranges.

Passons sur ces deux erreurs, le livre en contient sûrement d'autres mais c'est inévitable vue l'ampleur du sujet et la difficulté à retrouver les racines de tous ces mots.


L'article seul

RFC 5340: OSPF for IPv6

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : R. Coltun (Acoustra Productions), D. Ferguson (Juniper Networks), J. Moy (Sycamore Networks), A. Lindem (Redback Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ospf
Première rédaction de cet article le 24 juillet 2008


Le protocole de routage OSPF, normalisé dans le RFC 2328 est, à l'origine, très lié à IPv4. Le déploiement d'IPv6 nécessitait une adaptation d'OSPF et c'est ainsi que la version 3 d'OSPF (le RFC 2328 décrivait la version 2) est sortie, baptisée « OSPF pour IPv6 ».

Le premier RFC sur cette nouvelle version d'OSPF était le RFC 2740 que notre RFC 5340 met à jour. Comme son prédécesseur, ce RFC est écrit sous forme d'une liste de différences avec OSPF v2 (la version pour IPv4) et il faut donc lire également le RFC 2328 si on veut tout comprendre. Dur travail car la seule liste des différences fait 111 pages, mais il est vrai qu'OSPF n'est pas un protocole simple. En tout cas, je présente ce RFC comme il est écrit, sans reprendre ce que disait déjà le RFC 2328.

OSPF v3, la version pour IPv6, reprend les concepts habituels d'OSPF, comme l'inondation des LSA, l'élection des routeurs sur l'Ethernet, etc. Mais il n'est pas compatible avec OSPF v2, en raison du changement de format des paquets (section 2.7). Un site « double-pile » (IPv4 et IPv6) doit donc faire tourner les deux protocoles en parallèle (certains sites ont préféré adopter IS-IS pour n'avoir qu'un seul protocole).

Reprenant les concepts et le vocabulaire d'OSPF v2, le RFC a parfois eu des problèmes avec certains concepts qui avaient des noms différents entre IPv4 et IPv6. La section 1.2, de terminologie, détaille ces pièges.

La section 2 résume le RFC, puisqu'elle explique les différences entre OSPF v2 et OSPF v3. La plus grosse différence est le fait que tout ce qui est spécifique des adresses IP a été retiré des paquets généraux et mis dans des LSA spécifiques du protocole considéré (section 2.2). OSPF v3 est ainsi plutôt « multi-protocole » que purement IPv6 et il aurait pu être utilisé pour IPv4. Mais, en pratique, cela n'a jamais été fait et OSPF v3 ne sert qu'à IPv6. Peut-être les extensions à OSPFv3 qu'a finalement apporté le RFC 5838, en avril 2010, décoinceront enfin les choses.

Ainsi, les paquets Hello d'OSPF v2 indiquaient le masque de sous-réseau utilisé, ce qui n'est plus le cas en OSPF v3. De même, les identificateurs comme le Router ID ne sont plus des adresses, ce sont simplement des nombres de 32 bits, qu'on écrit avec la syntaxe habituelle des adresses IPv4.

Parmi les autres différences, on peut noter qu'OSPF v3 travaille par lien réseau et plus par sous-réseau IP (section 2.1), qu'on peut faire tourner plusieurs incarnations d'OSPF sur le même lien, différenciées par leur Instance ID (section 2.4) et que les voisins sont identifiés par une adresses « locale au lien » (section 2.5) comme fe80::207:cbff:fec3:8323 ce qui, à mon avis, ne facilite pas le débogage (peu d'administrateurs réseaux connaissent par cœur les adresses locales au lien de leurs routeurs).

L'authentification des routeurs voisins a disparu du RFC (section 2.6), puisqu'on est censé désormais utiliser IPsec (via le RFC 4302). L'idée était que tout le monde utiliserait IPsec, de toute façon, d'autant plus qu'il était censé être obligatoirement intégré dans IPv6 ce qui, en pratique, n'a pas été le cas. L'idée de se reposer entièrement sur IPsec a été abandonnée avec la sortie du RFC 6506, qui prévoit un mécanisme d'authentification pour OPSFv3.

La section 3 décrit les différences entre l'ancien RFC, le RFC 2740 et celui-ci. Normalement, anciennes et nouvelles implémentations d'OSPF v3 interopèrent. Parmi les changements, l'abandon de MOSPF (section 3.2), le service de multicast (RFC 1584), jamais réellement utilisé. Ou bien l'abandon des adresses IPv6 « locales au site » (section 3.7), suivant le RFC 3879.

La section 4 est ensuite consacrée aux « conseils aux implémenteurs », c'est-à-dire tout ce qu'il faut savoir pour créer une belle mise en œuvre d'OSPF v3. Elle détaille les changements dans les structures de données que doit maintenir le routeur (section 4.1), le traitement des paquets (section 4.2), les nouveaux LSA (comme le Link LSA de la section 4.4.3.8) et les changements des anciens (section 4.4), etc.

La section 5 est consacrée à la sécurité. Elle revient sur l'authentification des routeurs, qui doit désormais se faire avec IPsec, comme détaillé dans le RFC 4552 (idée abandonnée avec le RFC 6506). Elle note aussi que l'authentification des routeurs ne suffit certainement pas à éliminer tous les problèmes de sécurité du routage, comme le détaille le RFC 4593.

L'annexe A détaille le format des paquets, les B et C les paramètres qui gouvernent le comportement d'OSPF.

Des exemples de configuration concrète d'un routeur OSPF v3 se trouvent dans mon cours OSPF. Par exemple, on peut voir les adjacences IPv6 sur un des routeurs :

# show ipv6 ospf6 neighbor
 RouterID         State/Duration    DR              BDR             I/F[State]
 192.134.7.241     Full/00:01:42    192.134.7.245   192.134.7.241   eth0[DR]
 10.4.200.2        Full/00:00:01    0.0.0.0         0.0.0.0         eth1[DR]

où on note que les routeurs sont identifiés par un Router ID, qui a la forme d'une adresse IPv4.


Téléchargez le RFC 5340


L'article seul

Pourquoi le domaine de tête ".local" n'est pas une bonne idée

Première rédaction de cet article le 19 juillet 2008


Sur beaucoup de sites, les ressources réseaux internes ont des noms situées sous le pseudo-TLD .local. Ce TLD (domaine de tête) n'avait pas été enregistré à cet usage et son utilisation peut apporter des mauvaises surprises.

Il vaut mieux en effet utiliser un vrai nom de domaine par exemple grandeentreprise.fr ou petiteassociation.org. Si on veut séparer les ressources locales, purement internes, local.grandeentreprise.fr ou monsite.petiteassociation.org (qui tirent profit du caractère hiérarchique du DNS) conviennent également. À une époque lointaine, un nom de domaine en .com était gratuit (oui, la réservation de renault.com m'avait coûté 0 €).

Puis obtenir un nom de domaine était devenu très cher ou bien soumis à de pénible restrictions bureaucratiques. Mais le prix a été nettement abaissé par des acteurs comme Gandi et les règles d'enregistrement se sont souvent assouplies. Aujourd'hui il est raisonnable de supposer que tout le monde a un nom de domaine, et peut l'utiliser pour ses ressources internes comme pour les externes.

Mais, au fait, pourquoi .local est-il une mauvaise idée ? D'abord, parce qu'il n'était nullement garanti. Ce n'est qu'en février 2013 qu'il a été inclus dans le nouveau registre des TLD spéciaux. Le RFC 2606 réserve quelques TLD à des fins de test ou de documentation et .local n'en fait pas partie.

Mais le problème de fond est que .local n'est pas unique puisque des tas d'entreprises l'utilisent. Que se passera t-il en cas de fusion ou d'acquisition ? Si un utilisateur de .local absorbe un autre utilisateur, les conflits de noms seront fréquents (Et le cas s'est souvent produit.)

Ce n'est pas parce que ces ressources ne sont pas accessibles de l'Internet qu'il faut leur donner un nom qui n'est pas unique.

Certes, des géants états-uniens du logiciel comme Microsoft (avec son système Active Directory) ou bien Apple (avec Bonjour), utilisent ce pseudo-TLD. Mais ils ne sont pas des exemples à suivre. Cette utilisation montre simplement leur peu d'intérêt de la normalisation et leur tendance au « Je fais ce que je veux et tant pis pour l'opinion des autres ». Lors de la discussion du RFC 4795 sur LLMNR, Apple avait même tenté d'obtenir la réservation de .local avec comme seul argument « Nous nous en sommes servis unilatéralement, désormais l'IETF doit approuver ce choix. » Cela a finalement été fait dans les RFC 6761 et RFC 6762.


L'article seul

Les registres IANA désormais en XML

Première rédaction de cet article le 18 juillet 2008


Le 14 juillet, l'IANA a annoncé que les registres qu'elle maintenait seraient désormais en XML et a produit les premiers registres convertis au nouveau format. L'annonce met fin à une étonnante tradition de l'Internet, le fait que les registres des numéros affectés aux différents protocoles étaient simplement maintenus sous forme de fichiers texte.

On connait surtout le rôle politicien que joue l'IANA, un service de l'ICANN, dans la maintenance du fichier de zone de la racine DNS. Mais ce rôle ne doit pas faire oublier que l'IANA est également chargée, pour le compte de l'IETF, de la maintenance d'un grand nombre de registres plus techniques, pour stocker les informations sur les nombres qui doivent être unique pour que l'Internet fonctionne. Par exemple, les numéros de ports TCP ou UDP (80 pour HTTP, 25 pour SMTP, etc) sont stockés dans un tel registre à l'IANA. Ce rôle est formalisé dans le RFC 2860 et la partie IETF du travail dans le RFC 5226.

Pendant presque toute son existence, l'IANA a géré ses registres d'une manière très simple. Chaque registre était un fichier texte édité à la main par Jon Postel. Cela marchait mais, aujourd'hui, un tel système semble bien dépassé. Il ne permet notamment pas d'analyser facilement les registres (qui sont, à quelques exceptions près, non structurés) et il ne permet pas de présenter ces registres sous d'autres formats, par exemple HTML. L'IANA était consciente du problème depuis longtemps mais n'a bougé qu'avec beaucoup de précautions. En effet, son rôle est d'être conservatrice. Les registres doivent rester accessibles pendant des dizaines d'années et les convertir dans le dernier format à la mode, uniquement pour devoir en changer six mois plus tard, ne serait pas une bonne façon de les gérer. En outre, il fallait évidemment que ces registres soient décrits dans un format ouvert. Le processus a donc été long (et, contrairement à ce qu'on lit parfois sur le fonctionnement ouvert de l'Internet, très secret et conduit uniquement par un petit groupe non public). XML était le candidat évident pour le format des données.

Désormais, le train du changement est sur les rails et les premiers registres ont été convertis et officiellement annoncés.

Prenons un exemple, le registre des paramètres d'AAA, utilisé par exemple par le RFC 3588. Le registre texte traditionnel est https://www.iana.org/assignments/aaa-parameters (qui existe toujours, jusqu'au basculement prévu cette année vers une version texte produite automatiquement à partir de la version XML). La nouvelle version faisant autorité est https://www.iana.org/assignments/aaa-parameters/aaa-parameters.xml. À partir de cette version, on peut produire automatiquement, par exemple, une version HTML.

Outre les données, on trouve à l'IANA les outils de conversion, par exemple le script XSLT de conversion en XHTML, https://www.iana.org/assignments/aaa-parameters/aaa-parameters.xsl.

Le maintien de données cohérentes dans les registres nécessitait évidemment la définition d'un schéma de données XML. Il est écrit en RelaxNG (je recommande le livre d'Eric ven der Vlist sur ce langage). Le schéma du registre AAA est en https://www.iana.org/assignments/aaa-parameters/aaa-parameters.rng. Convertie en syntaxe « compacte », voici ce schéma. On note qu'il inclus un schéma plus général, applicable à tous les registres, https://www.iana.org/assignments/_support/iana-registry.rng (dont voici la version en syntaxe compacte).

Armé de ces schémas, on peut vérifier que le registre est bien correct :

% rnv aaa-parameters.rnc aaa-parameters.xml
aaa-parameters.xml

ou bien, avec xmllint :

% xmllint --noout --relaxng aaa-parameters.rng aaa-parameters.xml 
aaa-parameters.xml validates

L'IANA va désormais travailler à convertir tous les registres et à développer de nouveaux services que permet ce format, par exemple des mécanismes permettant de suivre les changements dans un registre, sans doute grâce à un système de syndication, où les flux de syndication pourront être produits automatiquement.

On notera que certains registres, ayant déjà un format structuré, ne seront pas convertis en XML. C'est le cas par exemple du registre des langues du RFC 4646.


L'article seul

RFC 5220: Problem Statement for Default Address Selection in Multi-Prefix Environments: Operational Issues of RFC 3484 Default Rules

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : A. Matsumoto, T. Fujisaki (NTT), R. Hiromi (Intec Netcore), K. Kanayama (INTEC Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 18 juillet 2008


Lorsqu'un système connecté à Internet a plusieurs adresses IP, la question de savoir laquelle utiliser comme source se pose. Si ce système dispose d'adresses IP de familles différentes, par exemple IPv4 et IPv6, la question de la sélection de l'adresse de destination peut également survenir. Le RFC 3484 décrivait un mécanisme pour cette sélection, mais qui a posé des problèmes en pratique, problèmes que décrit notre RFC.

Le RFC 3484 est par exemple mis en œuvre dans le système GAI (à noter que ce système est très peu documenté) de la GNU libc (utilisée dans des systèmes comme Gentoo ou Debian). Ce système se configure via le fichier /etc/gai.conf et permet d'avoir des politiques comme « Privilégier systématiquement les adresses IPv6 » ou bien « Préferer IPv4 sauf pour tels préfixes ». C'est l'expérience avec des systèmes analogues (sur FreeBSD, c'est /etc/ip6addrctl.conf, cf. la documentation ; Solaris a un mécanisme proche) qui a donné naissance au travail actuel sur le successeur du RFC 3484, travail dont notre RFC 5220 décrit les motivations et dont le RFC 5221 donne le cahier des charges pour le prochain mécanisme. Le successeur a finalement été le RFC 6724, en septembre 2012.

La section 2 forme l'essentiel de notre RFC, en listant successivement plusieurs cas concrets et les solutions - ou l'absence de solution - que leur apporte le RFC 3484. La section 2.1.1, par exemple, analyse le cas où il y a deux routeurs sur le même lien. La sélection du premier routeur à utiliser ne dépendant typiquement pas de l'adresse IP source, un site connecté à deux FAI va avoir des problèmes puisque les paquets pourront être envoyés au « mauvais » routeur, celui connecté à un autre FAI que celui qui a attribué l'adresse source choisie (le cas de la section 2.1.2 est similaire et montre un FAI qui met en œuvre le RFC 2317, éliminant ainsi les paquets IP malchanceux).

La section 2.1.3 décrit par contre un cas qui peut être résolu par le RFC 3484, contrairement aux deux précédents. La machine y est connectée à l'Internet via un FAI et à un réseau privé, utilisant par exemple des adresses IP locales (RFC 4193). Dans ce cas, il suffit de donner la priorité aux adresses globales. Si le préfixe global est 2001:db8:1000::/48 et que le préfixe du réseau privé est 2001:db8:8000::/48, les règles suivantes dans gai.conf donneront le résultat attendu :

# Tout l'Internet
precedence  ::/0          40
# Le réseau privé, à n'utiliser que si le destinataire est dans ce réseau privé,
# grâce à la règle "longest matching rule" du RFC 3484, section 5,
# règle 8. On lui met une précédence plus faible.
precedence 2001:db8:8000::/48    20

La section 2.1.4 décrit un cas similaire.

La section 2.1.5 décrit le cas où le site change son préfixe (cf. RFC 4192) et où les machines doivent, pendant la transition, utiliser la bonne adresse source. Ce problème se résout également dans le cadre du RFC 3484. Mais il faut noter que, le RFC en question ne spécifiant pas de mécanisme d'auto-configuration, cela nécessitera d'aller éditer le gai.conf (ou équivalent) sur toutes les machines du site, ce qui rendra le renumérotage très pénible !

La section 2.1.7 étudie le cas des adresses « vie privée » du RFC 4941. Ces adresses ayant des propriétés spécifiques, il serait préférable de choisir ou non leur utilisation par service et pas globalement et le RFC 3484 ne permet pas cela (le RFC 5014 fournit une solution possible).

La section 2.2 couvre le cas de la sélection de l'adresse destination. Par exemple, 2.2.1 étudie le cas très courant où un site est connecté nativement en IPv4 mais, compte tenu du manque de FAI IPv6, utilise un tunnel lent et peu fiable pour se connecter en IPv6. La table par défaut du RFC 3484, section 2.1, prioritise IPv6, ce qui n'est pas une bonne idée dans ce cas. Il est donc préférable de pouvoir choisir IPv4, ce qui se fait par exemple avec la ligne suivante dans /etc/gai.conf :

# Always prefer IPv4
precedence ::ffff:0:0/96  100

::ffff:0:0 désigne les adresses IPv4 mappées (section 2.5.5.2 du RFC 4291). Ce cas ne nécessite donc pas de modification du RFC 3484. 2.2.2 est un cas similaire où il n'y a pas de connectivité Internet IPv6 du tout mais où le réseau local offre IPv6.


Téléchargez le RFC 5220


L'article seul

RFC 5221: Requirements for address selection mechanisms

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : A. Matsumoto, T. Fujisaki (NTT), R. Hiromi (Intec NetCore), K. Kanayama (INTEC Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 16 juillet 2008


L'ancien modèle d'IP prévoyait seulement une adresse IP par interface réseau donc, pour la plupart des machines, une seule adresse IP tout court. Le choix de l'adresse IP à utiliser lorsque cette machine initiait une communication avec une autre machine était donc trivial. Mais ce modèle a changé, notamment avec l'arrivée d'IPv6, où la multiplicité des adresses devient la règle. Quelles adresses source et destination utiliser, dans ces conditions ? Le RFC 3484 exposait un mécanisme, qui a prouvé quelques limitations, menant à la conception d'un système amélioré dont notre RFC 5221 est le cahier des charges et le RFC 6724 la réalisation.

Le système du RFC 3484 a été mis en œuvre dans plusieurs systèmes d'exploitations. Par exemple, ceux utilisant la GNU libc disposent de la méthode de ce RFC et, en prime, ont /etc/gai.conf à leur disposition pour configurer manuellement le choix des adresses. Mais ce mécanisme n'est pas parfait et le RFC 5220 décrit les problèmes qu'il pose.

Le nouveau mécanisme va tenter de traiter ces problèmes, tout en gardant la possibilité d'un mécanisme totalement automatique (section 1).

La section 2 liste les onze exigences du nouveau système (je ne les cite pas toutes ci-dessous). Par exemple, 2.2 pose comme principe qu'il ne doit pas rendre la machine plus pénible à utiliser : le processus de sélection ne doit pas être long et il ne doit pas imposer une action manuelle. 2.5 exige que le mécanisme puisse être spécifique à chaque application, permettant à Firefox d'utiliser des règles différentes de celles de Thunderbird (via par exemple une API qui reste à définir). 2.7 insiste sur la nécessité pour l'administrateur système de pouvoir contrôler ce mécanisme, depuis un point central (comme /etc/gai.conf sur Debian ou Gentoo).

La sélection d'adresses IP source et destination a évidemment un impact sur la sélection du premier routeur à utiliser et ce point faisait l'objet du RFC 4191, et désormais de la section 2.8 de notre RFC.

Comme il n'est pas question de réécrire toutes les applications, le mécanisme envisagé doit évidemment être compatible avec l'API socket du RFC 3493 (section 2.9). Et, toujours sur la question de compatibilité, ce mécanisme doit marcher avec celui du RFC 3484.


Téléchargez le RFC 5221


L'article seul

RFC 2181: Clarifications to the DNS Specification

Date de publication du RFC : Juillet 1997
Auteur(s) du RFC : Robert Elz (Computer Science), Randy Bush (RGnet, Inc.)
Chemin des normes
Première rédaction de cet article le 14 juillet 2008


Le DNS est à la fois un des protocoles de base de l'Internet, dont presque toutes les transactions dépendent, et un des protocoles les plus mal spécifiés. Les RFC de référence, les RFC 1034 et RFC 1035, sont toujours en service mais, écrits il y a plus de vingt ans, ils accusent leur âge. Ils sont souvent ambigus et ont été mis à jour par de nombreux RFC ultérieurs. Ainsi, celui qui développe une nouvelle mise en œuvre du DNS doit lire plusieurs RFC successifs. L'un des plus importants est notre RFC 2181 qui avait clarifié plusieurs points particulièrement importants de la norme originelle.

On ne peut rien faire avec le DNS si on ne lit pas ce RFC 2181. Il est une sorte de FAQ des erreurs les plus souvent commises en lisant trop vite les RFC 1034 et RFC 1035. Mais il corrige aussi ces RFC, qui comportaient parfois de réelles erreurs (sections 1, 2 et 3).

Les consignes de notre RFC 2181 sont très variées.

Ainsi, la section 4 rappelle que le serveur DNS doit répondre depuis l'adresse IP à laquelle la question a été posée (pour un serveur qui a plusieurs adresses). La section 4.2 pose le même principe pour le numéro de port.

La section 5 introduit un concept nouveau, celui de RRSet (Resource Record Set ou « ensemble d'enregistrements de données »). Ce concept n'existait pas dans les RFC 1034 et RFC 1035. Un RRSet est un ensemble d'enregistrements DNS pour le même nom de domaine, et le même type. Ainsi, ce groupe forme un RRSet :

foobar.example.com.    IN    AAAA      2001:DB8:123:456::1
foobar.example.com.    IN    AAAA      2001:DB8:CAFE:645::1:2

mais pas celui-ci :

foobar.example.com.    IN    AAAA      2001:DB8:123:456::1
baz.example.com.       IN    AAAA      2001:DB8:CAFE:645::1:2

(car le nom est différent) ni celui-ci :

foobar.example.com.    IN    AAAA      2001:DB8:123:456::1
foobar.example.com.    IN    A         192.0.2.34

(car le type est différent).

Le RFC impose ensuite (section 5.1) que les enregistrements d'un RRSet soient tous envoyés dans une réponse (ou bien que le bit TC - indiquant la troncation - soit positionné, ce que détaille la section 9). Pas question de n'envoyer qu'une partie d'un RRSet. Il impose également que les différents enregistrements d'un RRSet aient le même TTL (section 5.2). Il existe également des règles pour DNSSEC (section 5.3) mais elles concernent l'ancienne version de DNSSEC, qui a depuis été remplacée par DNSSEC-bis (RFC 4033 et suivants).

De même qu'un serveur ne peut pas n'envoyer qu'une partie des enregistrements d'un RRSet, il ne doit pas fusionner un RRSet reçu en réponse avec des données du même RRSet qui seraient dans son cache (section 5.4). Le reste de la section 5.4 est d'ailleurs consacré à la nécessaire paranoïa d'un serveur de noms récursif. En effet, le RFC 2181 lui impose de ne pas accepter aveuglément n'importe quelle donnée mais de juger de la confiance qu'on peut lui accorder (section 5.4.1). Ainsi, les données présentes dans la section additional d'une réponse DNS sont moins fiables que celles de la section answer. Le déploiement de notre RFC a ainsi résolu un gros problème de sécurité du DNS : les serveurs de noms récursifs avalaient tout le contenu de la réponse, sans juger de sa valeur, et étaient donc faciles à empoisonner avec de fausses données. Ainsi, avant le RFC 2181, un serveur qui demandait les enregistrements de type A pour www.example.org et qui recevait une réponse :

;; QUESTION SECTION:
;www.example.org.                            IN      A

;; ANSWER SECTION:
www.example.org.                       IN   A    192.0.2.1

;; ADDITIONAL SECTION:
www.google.example.                       IN   A   192.0.2.178

acceptait l'enregistrement A dans la section additionnelle, bien que cet enregistrement n'aie aucun rapport avec la question posée et ne fasse pas autorité.

La section 6 du RFC traite des frontières de zones DNS (zone cuts). L'arbre des noms de domaine est découpé en zones (RFC 1034, section 2.4 et 4.2), chaque zone étant traditionnellement décrite dans un fichier de zone spécifique. Pour connecter une zone parente à la fille, la parente ajoute des enregistrements de type NS. Il faut se rappeller que les frontières de zone ne se voient pas dans le nom de domaine. Est-ce que org.uk est géré par la même organisation que co.uk ? Vous ne pouvez pas le savoir juste en regardant ces noms. D'autre part, les zones ne correspondent pas forcément à des frontières organisationnelles. Pendant longtemps, nom.fr était dans une zone différente de fr alors que les deux domaines étaient gérés par le même organisme, l'AFNIC. En sens inverse, le futur domaine .tel n'aura qu'une seule zone, tout en permettant aux utilisateurs de mettre leurs propres données.

Bref, la zone est une notion complexe. Notre RFC rappelle juste que les données de délégation (les enregistrements NS) ne font pas autorité dans la zone parente (section 6.1). En dehors des enregistrements indispensables à la délégation (NS et peut-être A et AAAA de colle), les serveurs ne doivent pas envoyer de données qui sont au delà d'une frontière de zone.

La section 8 corrige légèrement la définition du TTL qui se trouve section 3.6 du RFC 1034 en imposant que ce soit un entier non signé.

La section 10 s'attaque à des question plus délicates car plus visibles par l'utilisateur humain, les questions de nommage. Au contraire des règles des sections précédentes, qui ne seront guère vues que par les programmeurs qui écrivent des serveurs de noms, les règles des sections 10 et 11 concernent tous les gérants de zones DNS.

D'abord, un rappel en début de section 10 : dire que telle machine « a pour nom de domaine gandalf.example.net » est un net abus de langage. Une machine n'a pas un nom qui serait le « vrai » ou l'« authentique ». Il faut plutôt dire que des tas de noms dans le DNS peuvent pointer sur une machine donnée. Ainsi, il n'y a aucune obligation d'avoir un seul enregistrement de type PTR (section 10.2) pour une adresse IP donnée.

La section 10.1 clarifie les enregistrements de type CNAME. Leur noms peut être trompeur car il veut dire Canonical Name (« nom canonique ») alors que le CNAME sert plutôt à enregistrer des alias (section 10.1.1). Si le DNS contient :

www.example.org.    IN    CNAME    www.example.net.

il ne faut pas dire que www.example.org est le CNAME de www.example.net mais plutôt qu'il est l'alias de www.example.net ou, plus rigoureusement, qu'il existe un enregistrement de type CNAME dont le nom est www.example.org.

La section 10.2 rappelle qu'on peut avoir plusieurs enregistrements de type PTR et surtout qu'un PTR peut mener à un alias, et pas directement au nom de domaine désiré. Cette propriété est d'ailleurs à la base de la délégation sans classe de in-addr.arpa décrite dans le RFC 2317.

Par contre, les enregistrements NS et MX ne peuvent pas mener à un alias (section 10.3). Un logiciel comme Zonecheck teste d'ailleurs cela.

Enfin, la section 11 est peut-être la plus ignorée de tout le RFC. Consacrée à la syntaxe des noms de domaines, elle rappelle (c'est juste un rappel, les RFC 1034 et RFC 1035 étaient déjà clairs à ce sujet) qu'un nom de domaine peut prendre n'importe quelle valeur binaire. Si vous entendez quelqu'un dire que « le DNS est limité aux caractères ASCII » ou bien « le DNS est limité aux lettres, chiffres et tiret », vous pouvez être sûr que la personne en question est profondément ignorante du DNS. Le DNS a toujours permis de stocker n'importe quels caractères, même non-ASCII et, s'il a fallu inventer les IDN du RFC 3490, c'est pour de tout autres raisons.

La section 11 souligne juste que les applications qui utilisent le DNS peuvent avoir des restrictions. Ainsi, avant les IRI du RFC 3987, les adresses du Web étaient en effet limitées à ASCII.


Téléchargez le RFC 2181


L'article seul

RFC 5211: An Internet Transition Plan

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : J. Curran
Pour information
Première rédaction de cet article le 13 juillet 2008


Il y a déjà eu des tas de plans pour réaliser la transition depuis l'actuel IPv4 vers le futur protocole IPv6. Ce très court RFC, qui est une contribution individuelle, expose sommairement un tel plan, dont rien ne garantit qu'il sera davantage suivi que les autres.

Comment passer d'un Internet très majoritairement IPv4 à un Internet où IPv6 représenterait l'essentiel des adresses et du trafic, ne laissant que des îlots attardés avec l'ancien protocole ? Le problème est d'autant plus difficile que les premiers à migrer n'ont aucun intérêt à le faire puisqu'ils ne peuvent joindre personne en IPv6 ; aujourd'hui, il n'y a pratiquement aucun « gros » site Web accessible en IPv6, et ce n'est pas différent pour les autres services. Il y a peu de chances que les seules lois du marché suffisent à effectuer ce changement (voir aussi le RFC 1669).

Notre RFC décrit un plan possible, en notant bien qu'il n'est pas obligatoire. J'ajoute qu'il ne semble pas plus réaliste que les autres, qu'on trouve par exemple dans les RFC 3750 ou RFC 4057. Il part d'une prémisse optimiste, que les acteurs voudront la connectivité IPv6 pour elle-même.

L'idée est de décrire la transition en plusieurs étapes (section 2). Trois étapes sont prévues, chacune permettant de tirer d'avantage de bénéfices de la transition. Dans l'étape de Préparation (section 2.1, prévue pour durer jusqu'en décembre 2009, c'est-à-dire quasiment demain), on dote certains serveurs accessibles de l'extérieur de capacités IPv6 (sans forcément mettre IPv6 sur tous les réseaux locaux). Pour limiter les risques, ces serveurs sont accessibles avec un nom spécial, comme expliqué en section 2.1.1 (c'est ce que fait Google en ce moment où son service phare, le moteur de recherche, est accessible sous le nom http://ipv6.google.com). Notons que la grande majorité des organisations connectées à Internet n'a toujours pas commencé cette étape, prévue pour se terminer dans un an et demi. Notons aussi que cette étape ne permet pas encore d'abandonner IPv4, toute machine devant rester « double-pile » (v4 et v6).

Dans la seconde étape (section 2.2), prévue de janvier 2010 à décembre 2011, tous les serveurs ont IPv6, et on déploie IPv6 sur les réseaux internes. Idéalement, à la fin de cette étape, un accès Internet en IPv6 seul serait possible. Notons que, même si ce calendrier était respecté, il suffirait à peine à éviter l'épuisement des adresses IPv4, qui devrait survenir en 2011.

Enfin, la troisième étape (section 2.3), prévue à partir de janvier 2012, sera consacrée au démantèlement progressif des services IPv4 et à la stabilisation des services IPv6.

Évidemment, ce calendrier devrait être suivi, vu l'approche de la date où la dernière adresse IPv4 sera allouée. Mais le sera t-il ? Compte-tenu de l'actuelle situation de déni de la réalité, c'est peu probable.

Un mot en passant : ce blog n'est pas accessible en IPv6, le fournisseur d'hébergement actuel ne le proposant pas. Un tunnel existe mais il est bien trop lent et surtout trop peu fiable pour que j'annonce une adresse IPv6 dans le DNS.


Téléchargez le RFC 5211


L'article seul

L'accessibilité des sites Web, ce n'est pas uniquement pour les handicapés !

Première rédaction de cet article le 12 juillet 2008


L'accessibilité des sites Web est un sujet à la mode. De nombreux articles sont publiés, de nombreuses réunions ou colloques se tiennent, de nombreux débats ont lieu. Mais la plupart des sites Web restent très peu accessibles. Est-ce parce qu'on restreint trop souvent les utilisateurs de l'accessibilité aux handicapés ?

Le discours sur l'accessibilité est en général du type « Il faut qu'un aveugle puisse voir le site Web, il en a le droit comme les autres ». Ce discours est largement repris et jamais contesté ouvertement (personne n'osera dire, même s'il le pense, « Les aveugles nous embêtent, tant pis pour eux, je ne vais pas laisser cette minorité de perdants affadir le design de mon beau site Web tout en Flash qui bouge »). Mais ce discours a peu d'effet : la très grande majorité des sites Web ne sont pas accessibles à tous. Mise en page et contenu mélangés (par exemple par l'utilisation de tableaux (<table> HTML), contenus entièrement en Flash, profusion d'images sans texte alternatif (ou avec un attribut alt alors que l'image ne sert qu'à la décoration, ce qui est tout aussi absurde), fonctionnement impossible sans Javascript, pas de structuration des données (qui permettrait de les reprendre facilement)...

Les sites Web commerciaux, réalisés par des professionnels, ne sont pas les meilleurs, loin de là. Comme il existe bien plus de sites Web que d'auteurs Web compétents, les sites sont réalisés par des gens dont la compétence n'est pas en écriture Web mais en graphisme ou en programmation, des disciplines utiles mais différentes, et qui ne rendent pas forcément sensibles à la structuration des sites Web.

Pourquoi les sites Web ne sont-ils pas plus accessibles aujourd'hui qu'avant ? Est-ce par manque de documentation ? Non, des documents comme la référence, le Web Content Accessibility Guidelines du W3C sont souvent cités. En français, l'excellent site d'Alsacréations contient également plein d'informations utiles si le webmestre a décidé de rendre le site Web accessible.

Peut-être est-ce parce que le discours dominant réduit l'accessibilité à une préoccupation pour une minorité. On demande aux auteurs de sites Web d'être généreux, de penser aux plus faibles (une pensée très démodée dans la France de Sarkozy), alors que ces auteurs ont déjà beaucoup de travail pour boucler le projet Web à temps et que prendre en compte les besoins de 2 ou 3 % des utilisateurs ne se justifie pas financièrement.

Mais c'est un raisonnement discutable. Quittons un peu l'accessibilité numérique et voyons comment se pose le problème pour l'accessibilité physique, par exemple des bâtiments. Si on rend un bâtiment accessible à tous, par exemple en installant des rampes d'accès, des ascenseurs larges, on ne rend pas service qu'à la minorité qui est en fauteuil roulant. On aide aussi les gens chargés de paquets, les femmes avec des bébés et les jeunes cadres dynamiques qui se sont claqués un muscle au squash.

En d'autres termes, les dépenses entraînées par l'accessibilité profitent à tous et pas seulement aux handicapés qu'on essaie de culpabiliser en leur annonçant les dépenses qu'on a fait « pour eux ».

C'est la même chose avec l'accessibilité numérique. Si on rend un site Web accessible à tous, cela ne servira pas qu'aux aveugles. On aidera également les économiquement faibles qui ont un vieux navigateur sans possibilités sophistiquées, les frimeurs riches qui ont un téléphone portable avec accès EDGE (le plus cher des téléphones portables a un écran et un processeur dont les capacités sont inférieures à celles du moindre PC), les moteurs de recherche qui n'ont en général pas de capacité Javascript ou Flash, etc.

Terminons en citant le site Web de Renaissance Numérique qui dit fort justement : « Les standards d'accessibilité séparent le contenu et le contenant. Il est ainsi plus facile de maintenir un site et de le mettre à jour. Une meilleure organisation du contenu permet également de fournir un service de meilleur qualité et mieux ciblé. » et « La conformité aux standards permet de concevoir facilement des interfaces utilisateurs en fonction des supports et de leurs usages. Nous ne pouvons pas proposer la même interface sur un écran de téléphone mobile que sur un PC portable à écran 11' ou un PC de bureau avec un grand écran. »


L'article seul

Vulnérabilité du DNS rendant l'empoisonnement plus facile

Première rédaction de cet article le 9 juillet 2008
Dernière mise à jour le 22 juillet 2008


Le 8 juillet, l'avis VU#800113 du CERT a révélé publiquement une faille du protocole DNS. Cette faille permet un empoisonnement relativement facile des caches DNS.

On peut trouver un bon résumé dans l'article Fixes Released for Massive Internet Security Issue. L'attaque a été découverte par Dan Kaminsky et repose sur une vulnérabilité classique du DNS. Le résolveur DNS (serveur récursif) accepte en effet une réponse si la question posée, le Query ID (RFC 1035, section 4.1.1) et le port UDP où arrive la réponse coïncident avec une question en attente. Mais Kaminsky a découvert un mécanisme pour envoyer une fausse réponse ayant de très bonnes chances d'être acceptée. (Le mécanisme détaillé est expliqué dans un autre article.) Indépendamment de cette attaque spécifique, il faut noter que la vulnérabilité est connue depuis longtemps (voir par exemple l'article DNS and BIND Security Issues de Paul Vixie qui dit With only 16 bits worth of query ID and 16 bits worth of UDP port number, it's hard not to be predictable. A determined attacker can try all the numbers in a very short time and can use patterns derived from examination of the freely available BIND code. Even if we had a white noise generator to help randomize our numbers, it's just too easy to try them all.) C'est pour cela que certains résolveurs ne sont pas vulnérables (ils mettaient en œuvre des mécanismes de défense depuis longtemps).

Depuis le site Web de l'auteur de la découverte, on peut tester la vulnérabilité de son résolveur. Mais ledit site Web est très chargé et le code Javascript bogué. Si on veut tester via le Web, il faut mieux utiliser https://www.dns-oarc.net/oarc/services/dnsentropy. Si on préfère tester en local, une bonne solution est le script de Michael C. Toren :

%  perl noclicky-1.00.pl 192.0.2.225
Looking up zqq0wi2odh5x.toorrr.com against 192.0.2.225
Fetching http://209.200.168.66/fprint/zqq0wi2odh5x
Requests seen for zqq0wi2odh5x.toorrr.com:
  192.0.2.225:32769 TXID=2234
  192.0.2.225:32769 TXID=22512
  192.0.2.225:32769 TXID=17521
  192.0.2.225:32769 TXID=32880
  192.0.2.225:32769 TXID=40914
Your nameserver appears vulnerable; all requests came from the same port.

Aïe, cette machine est vulnérable.

Et une autre solution pour tester la vulnérabilité de son serveur récursif, ne nécessitant que le traditionnel dig, est de demander à porttest.dns-oarc.net :

%  dig +short porttest.dns-oarc.net TXT
z.y.x.w.v.u.t.s.r.q.p.o.n.m.l.k.j.i.h.g.f.e.d.c.b.a.pt.dns-oarc.net.
"192.0.2.248 is POOR: 26 queries in 4.5 seconds from 1 ports with std dev 0.00                 "

On voit que cette machine est vulnérable : toutes les requêtes DNS sont émises depuis le même port.

Enfin, deux autres outils plus graphiques, entièrement via le Web, et que je recommande, DNS ENtropy, de l'OARC et le test de GRC.

Les logiciels peuvent diminuer leur vulnérabilité en utilisant un port source UDP aléatoire. C'est ce que font toutes les mises à jour qui viennent d'être publiées (voir par exemple communiqué de l'ISC). Le seul fait de choisir le Query ID au hasard est nécessaire mais pas suffisant (il ne fait que 16 bits de large). Certains résolveurs comme PowerDNS ou bien Unbound avaient déjà ce mécanisme et n'étaient donc pas vulnérables (pour Unbound, voir leur analyse complète et aussi celle de PowerDNS).

Attention : il ne suffit pas de faire la mise à jour du logiciel, encore faut-il tester que la configuration du serveur de noms ne force pas l'usage d'un port unique. C'est par exemple un problème possible avec BIND si le fichier named.conf contient une ligne du genre query-source port 53;. Cette ligne, qui force l'usage d'un port unique annule tout l'effet du patch correctif ! (Et c'est détecté par les tests ci-dessus.)

Les systèmes comme Debian ou Gentoo ont très vite intégré les patches et la mise à jour normale suffit donc.

On peut noter que ce patch peut perturber certains coupe-feux, qui s'étonneraient des réponses arrivant à un grand nombre de ports. Par exemple, il semble que Zone Alarm sur Windows XP proteste et qu'il faille passer son niveau de sécurité à Medium si la machine fait tourner un BIND sécurisé (voir http://www.pcinpact.com/actu/news/44747-zonealarm-windows-dns-internet-probleme.htm et http://www.zdnet.fr/actualites/informatique/0,39040745,39382271,00.htm.

Comme le rappelle le communiqué de l'ISC cité plus haut, la solution idéale est de passer à DNSSEC (RFC 4033, RFC 4034 et RFC 4035). Mais c'est une opération très lourde, nécessitant des mise à jour des logiciels, l'action des registres, celle des gérants de résolveurs, etc. Et DNSSEC apporte ses propres vulnérabilités et la complication de gestion qui est associé aux systèmes utilisant la cryptographie. Réclamer son déploiement est donc assez yakafokon.


L'article seul

RFC 5250: The OSPF Opaque LSA Option

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : Lou Berger (LabN), Igor Bryskin (Adva), Alex Zinin (Alcatel)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ospf
Première rédaction de cet article le 4 juillet 2008


Le protocole de routage OSPF fonctionne en distribuant de l'information sur les interfaces du routeur, informations qui sont transmises par inondation à tous les routeurs de la zone. Cette information est structurée en LSA (Link State Advertisement) et ces LSA appartiennent à différents types, les premiers ayant été décrits dans le RFC 2328. Comme tous les routeurs de la même zone (area) doivent comprendre tous ces types, ajouter un nouveau type de LSA n'est pas facile. D'où l'idée, qui avait fait l'objet du RFC 2370, de créer un type « opaque » qui pourrait stocker de l'information spécifique à une application, sans que les routeurs aient besoin de connaitre autre chose que le fait qu'il soit opaque. C'est l'objet de notre RFC, qui remplace le 2370.

Ainsi, il sera plus facile d'étendre OSPF, comme l'avaient fait les RFC 3623 ou RFC 3630. Il suffit désormais d'enregistrer un « type de LSA opaque » auprès de l'IANA. Les routeurs qui ne connaissent pas ce type passeront les LSA sans les comprendre et sans être affectés. Le RFC 5250 ne spécifie d'ailleurs pas comment utiliser les LSA opaques, cela dépend complètement de l'application envisagée (section 2).

La section 3 décrit en détail ces nouveaux LSA. Il en existe de trois types :

  • Le type OSPF 9 est réservé aux LSA opaques locaux à un segment de réseau et ne sont pas transmis aux routeurs qui sont sur d'autres segments,
  • Le type OSPF 10 sert aux LSA opaques locaux à une zone OSPF,
  • Et le type 11 est pour les LSA opaques diffusés dans tout un AS (à l'exception des zones « terminales » par exemple les NSSA du RFC 3101).

Le LSA opaque est composé d'un en-tête LSA normal (section 12.1 du RFC 2328) suivi de 32 bits d'information qui sont divisés en un sous-type de 8 bits (le registre IANA les nomme opaque LSA option types) et 24 bits pour les informations spécifiques à l'application. Ainsi, le sous-type 1 désigne l'application traffic engineering du RFC 3630, alors que le 4 est la router information du RFC 4970. Le reste du LSA contient les données (de longueur variable, voir l'annexe A.2).

La section 3.1 gouverne la diffusion de ces LSA opaques, par inondation (section 13 du RFC 2328). Un routeur sait que son voisin OSPF est capable de gérer des LSA opaques en regardant le bit O (comme Opaque, valeur 0x40) lu dans les paquets Database Description que les deux routeurs s'échangent.

Justement, la section 4 décrit les changements dans les structures de données du protocole. En raison de l'option O citée plus haut, la description d'un voisin OSPF doit avoir un champ de plus pour stocker cette information sur les capacités du voisin.

La section 5 est la grosse nouveauté par rapport au RFC 2370, qui avait normalisé le protocole à l'origine. Elle décrit la diffusion des LSA opaques entre différentes zones OSPF. Enfin, la section 7 décrit les questions de compatibilité avec les vieux routeurs qui ne mettent pas en œuvre les LSA opaques (ils les ignorent, et ne peuvent donc pas les transmettre à leurs voisins).

La plupart des mises en œuvre d'OSPF supportent ces LSA opaques. Avec Quagga, il faut s'assurer que le logiciel a été configuré avant la compilation avec --enable-opaque-lsa. Il suffit ensuite de mettre ospf opaque-lsa dans le fichier de configuration OSPF. IOS et JunOS disposent également de ces LSA opaques.


Téléchargez le RFC 5250


L'article seul

RFC 5227: IPv4 Address Conflict Detection

Date de publication du RFC : Juillet 2008
Auteur(s) du RFC : Stuart Cheshire (Apple)
Chemin des normes
Première rédaction de cet article le 4 juillet 2008


Ce RFC est entièrement consacré à un problème qui a causé des cheveux blancs à beaucoup d'administrateurs de réseaux informatiques : la détection d'une duplication d'adresses IP.

Que la duplication soit un phénomène normal (cas des réseaux non gérés, ceux dont personne ne s'occupe, où il n'y a pas de liste des adresses allouées), le résultat d'une erreur humaine, ou une incivilité (« Je prends une adresse IP au hasard, on verra bien »), elle est quasiment impossible à empêcher. Une machine peut toujours émettre avec l'adresse qu'elle veut, le protocole ARP (RFC 826) ne peut fournir aucune sécurité (section 6 du RFC). Peut-on au moins la détecter ? C'est ce que propose notre RFC, après avoir expliqué (section 1) pourquoi le mécanisme proposé par le RFC 2131 n'est pas suffisant (cette section 1, comme souvent avec Stuart Cheshire, tourne d'ailleurs souvent au réglement de comptes, comme lorsque l'auteur souligne que Mac OS avait déjà résolu le problème en 1998).

Le nouveau protocole, ACD, repose sur ARP. La section 1.2 commence en listant les nouveautés. Le principe d'ACD est d'utiliser ARP, non pas pour poser sincèrement la question « Qui utilise telle adresse IP ? » mais pour détecter ceux qui répondraient à une requête pour l'adresse IP de la machine émettrice. Comme le note la section 1.2, de telles questions « orientées » sont courantes dans la vie. Si on demande au café « Est-ce que cette table est libre ? » c'est en général avec l'intention de s'y asseoir si elle l'est. De même, avec ACD, la machine qui veut vérifier l'unicité de son adresse IP, mettons 192.0.2.48 va demander à tout le monde « Qui utilise 192.0.2.48 ? » et confirmer cette adresse si personne ne réagit. ACD est utilisable sur tout réseau où ARP fonctionne.

La section 2 est la description détaillée du protocole. Lors du démarrage ou redémarrage d'une interface réseau, la machine ACD envoie une requête ARP pour sa propre adresse, avec sa propre adresse MAC comme adresse MAC source et 0.0.0.0 comme adresse IP source (section 2.1.1 : cette surprenante précaution est nécessaire pour éviter de polluer les caches ARP si quelqu'un utilise déjà cette adresse).

Après une attente suffisante (les détails se trouvent dans le RFC), si personne n'a répondu, la machine considère qu'il n'y a pas de duplication d'adresse et envoie une deuxième requête ARP, cette fois-ci avec son adresse IP en source, pour prévenir qu'elle va désormais utiliser cette adresse.

La réponse ARP est normalement acheminée en unicast mais la section 2.6 explique qu'ACD peut aussi utiliser la diffusion générale.

Et si ça va mal ? Si quelqu'un utilise cette adresse ? La section 2.4 couvre ce cas, en notant également que la détection de conflit doit être continue, puisqu'une autre machine peut arriver à tout moment en voulant utiliser la même adresse. La section détaille donc le concept de « défendre son adresse », comment et dans quelles conditions.

La section 3 contient l'explication d'un choix de conception qui fut très discuté, l'utilisation, pour tester la duplication, de requêtes ARP au lieu de réponses ARP, a priori plus adaptées. La principale raison est la crainte que certaines implémentations ne gèrent pas correctement des réponses qui n'ont été précédées d'aucune requête. Notons aussi qu'il est malheureusement rare dans les RFC de voir une discussion des choix alternatifs : la spécification est en général annoncée telle quelle, sans justification des choix, contrairement à ce que fait ce RFC.

La section 4, historique, rappelle l'ancienne technique des « ARP gratuits » (au sens de « meurtres gratuits »), qui avait été proposée par Stevens dans son TCP/IP illustrated et explique en quoi ACD est préférable (l'ARP gratuit est l'équivalent de crier « Je vais prendre cette table » sans vérifier si elle est déjà occupée).


Téléchargez le RFC 5227


L'article seul

RFC 2460: Internet Protocol, Version 6 (IPv6) Specification

Date de publication du RFC : Décembre 1998
Auteur(s) du RFC : Stephen E. Deering (Cisco Systems, Inc.), Robert M. Hinden (Nokia)
Chemin des normes
Première rédaction de cet article le 1 juillet 2008


Si IPv4 est normalisé dans un seul document, le RFC 791, le candidat à sa succession IPv6 est décrit de manière plus modulaire, dans plusieurs RFC dont notre RFC 2460, essentiellement consacré au format des paquets. Il a depuis été remplacé par le RFC 8200.

Remplaçant le premier RFC sur le format des paquets IPv6, le RFC 1883, notre RFC 2460 est resté stable pendant dix-huit ans, alors que la plupart des RFC sur IPv6 ont connu des révisions ; les autres RFC importants pour IPv6 sont le RFC 4291 sur l'adressage - certainement le moins stable -, le RFC 4861 sur le protocole de découverte des voisins, le RFC 4862 sur l'autoconfiguration des adresses et le RFC 4443 sur ICMP.

À l'heure actuelle, le déploiement de ce RFC est très limité : peu de paquets IPv6 circulent sur Internet et il est loin d'avoir succédé à IPv4. Le fait d'avoir un numéro de version plus élevé ne suffit pas ! Notre RFC 2460 présente sans hésiter IPv6 comme le successeur d'IPv4, ce qui reste pour l'instant un vœu pieux.

IPv6 reprend largement le modèle qui a fait le succès d'IPv4 : un protocole de datagrammes, un routage jusqu'au prochain saut (peu ou pas de routage de bout en bout), des datagrammes acheminés « au mieux possible », un en-tête de paquet simple et où les champs sont de taille fixe. La section 1 du RFC résume les différences entre les formats de paquets IPv4 et IPv6.

La plus spectaculaire des différences est bien sûr l'augmentation de la taille des adresses. Toujours fixe (contrairement à des concurrents où les adresses étaient de tailles variables), cette taille passe de 32 à 128 bits. Le maximum théorique d'adresses (en supposant une allocation parfaite) passe donc de quatre milliards (ce qui ne permet même pas d'allouer une adresse à chaque personne sur Terre) à plus de 10^40, un nombre qui défie l'imagination.

Compte-tenu de l'épuisement rapide des adresses IPv4, cette augmentation est à elle seule une bonne raison de migrer vers IPv6. Elle reflète les changements de paradigme successifs en informatique, de « un ordinateur par entreprise » au début des années 70, lorsque IPv4 a été conçu, à « un ordinateur par département » au cours des années 80 puis à « un ordinateur par personne » avec l'explosion de la micro-informatique et à « plusieurs ordinateurs par personne » de nos jours lorsque le cadre dynamique et branché se promène avec davantage d'appareils électroniques sur lui que n'en portait James Bond dans ses premiers films. Les quatre milliards d'adresses d'IPv4 sont donc aujourd'hui bien insuffisantes.

Mais ce changement de format des adresses est également la faiblesse d'IPv6 : il ne permet en effet pas à des machines v4 et v6 de communiquer directement et les premiers adopteurs du nouveau protocole ne peuvent donc pas parler aux anciens, ce qui a puissamment freiné le déploiement d'IPv6.

Les autres changements apportés par IPv6 sont moins connus mais semblaient à l'époque justifier le nouveau protocole :

  • Le format de l'en-tête est simplifié, facilitant la tâche des routeurs (en pratique, IPv4 garde son avantage, la complexité de son format étant compensée par l'expérience des développeurs et la quantité de main d'œuvre qui a travaillé à optimiser les routeurs IPv4).
  • Les options sont à la fois plus libres, notamment en taille, et moins contraignantes à gérer pour les routeurs,
  • Les services d'authentification et de confidentialité ont été inclus (cet argument est souvent cité en faveur d'IPv6 mais il est largement bidon, IPv4 ayant désormais les mêmes capacités, et elles n'ont pas souvent été intégrées dans les implémentations IPv6).

La section 3 détaille le format du nouvel en-tête de paquet.

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version| Traffic Class |           Flow Label                  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Payload Length        |  Next Header  |   Hop Limit   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                                                               +
   |                                                               |
   +                         Source Address                        +
   |                                                               |
   +                                                               +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                                                               +
   |                                                               |
   +                      Destination Address                      +
   |                                                               |
   +                                                               +
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Contrairement aux paquets IPv4, il n'y a pas de champ « Options » de taille variable. Le champ « Version » contient évidemment le numéro 6 (il y a eu des protocoles ayant reçu le numéro 5 ou 7 mais ils n'ont jamais été déployés). Le champ DSCP, ex-TOS, d'IPv4 est remplacé par les champs Traffic class et Flow label qui semblent très peu utilisés en pratique (sections 6 et 7 du RFC, ainsi que l'annexe A ; le flow label a été ensuite mieux normalisé dans le RFC 6437).

Le champ Next header indique le type de l'en-tête suivant. La plupart du temps, c'est l'en-tête d'un protocole de transport comme TCP (numéro 6) ou DCCP (numéro 33), dont les numéros sont stockés dans un registre IANA. Mais cela peut être aussi un en-tête d'extension de la couche réseau par exemple 44 pour les fragments (ces numéros sont stockés dans le même registre IANA). Notez que, depuis, le RFC 6564 a modifié les règles pour les futurs en-têtes, imposant un format commun. (Pour analyser les paquets IPv6, voir mon article « Analyser les en-têtes IPv6 avec pcap ».)

Vu avec tshark, la version texte de l'analyseur Wireshark, et son option -V, voici un paquet IPv6 contenant lui-même du TCP :

Internet Protocol Version 6
    0110 .... = Version: 6
        [0110 .... = This field makes the filter "ip.version == 6" possible: 6]
    .... 0000 0000 .... .... .... .... .... = Traffic class: 0x00000000
    .... .... .... 0000 0000 0000 0000 0000 = Flowlabel: 0x00000000
    Payload length: 40
    Next header: TCP (0x06)
    Hop limit: 64
    Source: 2a01:e35:8bd9:8bb0:21e:8cff:fe76:29b6 (2a01:e35:8bd9:8bb0:21e:8cff:fe76:29b6)
    Destination: 2a01:e35:8bd9:8bb0:21c:23ff:fe00:6b7f (2a01:e35:8bd9:8bb0:21c:23ff:fe00:6b7f)

La section 4 présente les en-têtes d'extension. Grande nouveauté d'IPv6, ils sont situés entre l'en-tête IP normal et l'en-tête de la couche transport. La plupart d'entre eux sont ignorés par les routeurs situés sur le trajet et traités seulement à l'arrivée (alors qu'un routeur IPv4 devait, en théorie, toujours examiner les options). Notre RFC normalise certaines de ces extensions, mais d'autres peuvent être ajoutées par des RFC ultérieurs comme par exemple le RFC 3775 qui normalise le Mobility Header (numéro 135, section 6.1 du RFC).

C'est ainsi que la section 4.3 décrit l'en-tête d'extension « Hop-by-hop », une de celles qui doivent être examinées par tous les routeurs sur le trajet. Elle contient des options (décrites en section 4.2), qui sont stockées sous forme de tuples TLV. Le type de chaque option indique, dans ses deux premiers bits, si l'option peut être ignorée ou non.

Le symétrique de cet en-tête est le « Destination », section 4.6, qui stocke, de la même façon, les options qui ne doivent être traitées que par le destinataire. (Pour mettre un tel en-tête dans vos paquets, voir mon article.)

La section 4.4 décrit l'en-tête « Routing » qui permet d'indiquer la route qu'on souhaite voir le paquet prendre, ou bien d'enregistrer la route effectivement suivie. Notons qu'un champ, le « Routing Type », indique le type de routage souhaité et que sa valeur 0 ne doit plus être utilisée : en raison de problèmes de sécurité serieux, le Type 0 Routing Header a été abandonné dans le RFC 5095.

La section 4.5 décrit l'en-tête « Fragment » qui permet de représenter des paquets IP qui, trop longs, ont été fragmentés par l'émetteur (contrairement à IPv4, les routeurs IPv6 n'ont pas le droit de fragmenter).

La section 5 décrit les questions liées à la taille des paquets. IPv6 impose une MTU minimale de 1280 octets et, en théorie, une machine qu n'enverrait que des paquets de cette taille (ou plus petits) n'aurait jamais de problème. Au delà, on doit utiliser la découverte de la MTU du chemin, spécifiée dans le RFC 1981 mais dont le moins qu'on puisse dire est qu'elle n'est pas très fiable (cf. RFC 4821).

Les différences avec le RFC 1883 sont décrites après la bibliographie. Elles sont en général de peu d'importance. Par exemple, la MTU minimale passe à 1280 octets (après des débats enfiévrés, à une époque où LocalTalk était une technologie assez courante, le RFC 1883 utilisait 576 octets). Outre changement, la possibilité d'envoyer des très grands paquets, les jumbograms, a disparu du RFC de base et figure désormais dans un RFC dédié, le RFC 2675. Le RFC 8200, qui a remplacé notre RFC, n'a pas apporté de changements cruciaux.


Téléchargez le RFC 2460


L'article seul

RFC 5248: A Registry for SMTP Enhanced Mail System Status Codes

Date de publication du RFC : Juin 2008
Auteur(s) du RFC : T. Hansen (AT&T Laboratories), J. Klensin
Première rédaction de cet article le 1 juillet 2008


Le protocole SMTP de transport du courrier électronique, normalisé dans le RFC 5321, prévoit depuis le RFC 3463 des codes d'erreur à trois nombres très détaillés. Mais il n'existait pas de registre de ces codes et des doublons commençaient à apparaître. Ce RFC spécifie donc un registre des codes de retour SMTP, où tout le monde pourra vérifier que 4.3.1 signifie « Mail system full ».

Parmi les scénarios que résolvent ces codes de retour figure celui de l'internationalisation. SMTP est asynchrone et indirect. L'expéditeur du message n'a pas de contact direct avec les serveurs SMTP sur le trajet. Cela rend donc difficile des problèmes comme celui de la génération de messages d'erreur dans la langue de l'expéditeur. Actuellement, le serveur SMTP typique génère des messages d'erreur dans sa langue à lui (en général de l'anglais), pas dans celle de l'expéditeur qui va le recevoir. Plusieurs approches complémentaires ont été tentées pour résoudre ce problème, celle permise par notre RFC 5248 étant d'envoyer un code de statut numérique, que le MUA de l'expéditeur aura la charge de traduire. Ainsi, recevant « 5.2.2 - User's mailbox is too large - over ten gigabytes », le MUA pourra afficher « Pas assez de place dans la boîte aux lettres du destinataire » (et ignorer les détails en anglais).

Les codes SMTP (RFC 5321, section 4.2.1) originaux, dits « de base » sont composés de trois chiffres écrits sans séparateur (par exemple 554 pour Transaction failed). Les codes « améliorés » du RFC 3463 comportent, eux, trois nombres, la classe (2 : tout va bien, 4 : erreur temporaire, 5 : erreur définitive, etc), le second le sujet (6 : problème avec le contenu du message, 7 : problème avec la politique de sécurité, etc) et le troisième le détail. Ils s'écrivent avec un point comme séparateur. Ainsi, 5.5.2 signifie « Commande non reconnue » (erreur de classe 5, permanente, puisque le serveur SMTP ne va pas spontanément accepter de nouvelles commandes, erreur de sujet 5, problème de protocole). Dans cette session SMTP, on voit le code de base, 502 et le code amélioré 5.5.2 :

% telnet MYSERVER smtp
220 myserver.example.com ESMTP Postfix (Ubuntu)
XMPA <me@foobarfr>
502 5.5.2 Error: command not recognized

Dans ce cas précis, le gain apporté par les codes améliorés est faible, le code de base était déjà suffisamment spécifique. Mais, dans le futur, des codes améliorés supplémentaires pourront être enregistrés (comme ce fut le cas pour ceux du RFC 7372). Ainsi, il n'y a pas actuellement de code pour le greylisting (RFC 6647, notamment la section 5)) et les serveurs SMTP renvoient donc un code générique :

RCPT TO:<foobar@langtag.net>
450 4.7.1 <foobar@langtag.net>: Recipient address rejected: Greylisted by greyfix 0.3.2,\
    try again in 3480 seconds.\
    See http://projects.puremagic.com/greylisting/ for more information.

Un futur RFC pourra donc créer un code pour cette utile technique anti-spam.

Notre RFC demande donc à l'IANA (section 2) de créer un registre, le SMTP Enhanced Status Codes, précisant les codes et leur signification.

Ce registre, dit la section 2.3, sera rempli, en suivant les règles du RFC 5226, selon la règle « Specification required » qui impose l'existence d'un texte écrit (pas forcément un RFC). La section 2.4 décrit les valeurs initiales contenues dans ce registre.


Téléchargez le RFC 5248


L'article seul

Pourquoi avoir développé IDNA au lieu d'utiliser directement l'Unicode dans le DNS ?

Première rédaction de cet article le 29 juin 2008


On voit souvent des questions du genre « Pourquoi la norme actuelle sur les noms de domaine internationalisés, IDNA (RFC 5890), utilise t-elle un encodage en ASCII (le Punycode du RFC 3492), plutôt que d'utiliser directement Unicode dans le DNS ? ». Cet article tente de répondre à cette question.

Actuellement, la norme pour les noms de domaine internationaux, IDNA (pour Internationalized Domain Names in Applications), prévoit que le nom de domaine en Unicode, par exemple Ὅμηρος.gr, va être traduit dans un sous-ensemble d'ASCII, ici en xn--sxajkhl1633b.gr (le TLD grec n'est pas encore traduit). C'est ce nom en ASCII qui sera mis dans les fichiers de zone et qui circulera entre serveurs DNS. Pourquoi avoir introduit ce système ? Pourquoi ne pas avoir permis directement l'Unicode dans le DNS ?

On lit parfois que c'est parce que le DNS ne permettrait qu'ASCII. C'est totalement faux. Celui qui écrit ça montre qu'il ne connait pas le sujet. Le DNS a en effet toujours permis n'importe quel contenu, bien au delà d'ASCII. Le RFC 2181, dans sa section 11, a bien enfoncé le clou en rappelant que tout caractère est légal dans le DNS.

Le premier problème à l'utilisation d'Unicode ne vient pas du DNS mais des applications qui gèrent des noms de machines et pour lesquelles la règle (RFC 1123, section 2.1) est en effet bien plus restrictive. Cette règle est connue sous le nom de LDH (pour Letters-Digits-Hyphen, cette règle limite en effet les noms de machine aux lettres, chiffres et au tiret).

Comme on enregistre en général un nom de domaine pour y mettre des noms de machine, la plupart des registres ont intégré cette règle et ne permettent que des noms de domaines LDH. Par exemple, les règles d'enregistrement dans ".fr" disent « Sont admis à titre de noms de domaine les termes alphanumériques constitués de lettres de l'alphabet français [sic] A à Z et de chiffres de 0 à 9 et du tiret - ». Mais c'est une politique des registres, pas une limitation du DNS.

Changer cette règle nécessiterait de modifier beaucoup de logiciels, tous ceux qui manipulent des noms de machine.

Mais il existe un second problème, plus subtil. Le DNS ne permet pas de recherches floues. Soit le nom correspond parfaitement à un nom dans la base, soit le serveur renvoie le code NXDOMAIN (No Such Domain). Comme c'est un peu dur pour les utilisateurs, une canonicalisation (ou normalisation) est prévue, actuellement uniquement l'insensibilité à la casse. Cette canonicalisation rend le DNS un peu plus agréable à l'utilisateur, qui serait certainement dérouté s'il fallait taper exactement le bon caractère, et que CHOCOLAT.fr soit différent de chocolat.fr.

Elle suffit pour ASCII. Pour Unicode, elle ne serait pas réaliste car Unicode offre d'autres possibilités. Ainsi, « thé » peut s'écrire en Unicode avec trois caractères, U+0074, U+0068, et U+00E9 (le dernier identifiant le « e avec accent aigu ») ou bien avec quatre, U+0074, U+0068, U+0065, et U+0301, le dernier étant l'accent aigu combinant. Pour la plupart des lecteurs, ces deux chaînes de caractères sont « identiques ». Pour un logiciel, elles ne le sont pas. Seule une canonicalisation permet une comparaison « raisonnable » de ces deux chaînes. Ainsi, NFC, un des algorithmes standard de canonicalisation d'Unicode, ne laisserait que la première forme, celle à trois caractères.

Il faudrait donc, si on déploie un jour un hypothétique « DNSv2 » (100 % Unicode), mettre NFC (ou un de ses équivalents) dans tous les serveurs de noms... Cet algorithme est compliqué, nécessite des tables (alors que, en ASCII, on peut passer des majuscules ou minuscules sans tables, uniquement en ajoutant ou retirant 32), a des points obscurs (notamment si le caractère Unicode n'est pas affecté)... Peu d'auteurs de serveurs de noms envisagent de l'inclure dans leur code.

Cette seconde raison est la principale. Même si on choisissait une approche « table rase » et qu'on fasse DNSv2 en partant de zéro, en ignorant l'existant, il faudrait résoudre ce problème de canonicalisation (voir le RFC 5198 pour une façon de le traiter).


L'article seul

Le support de Free, une source de distractions sémantiques

Première rédaction de cet article le 29 juin 2008


Le FAI Free est réputé pour la qualité très approximative de son service : pannes fréquentes, support totalement incompétent et payant (y compris le temps d'attente, si on appelle depuis un autre réseau téléphonique, ce qui est évidemment toujours le cas lorsqu'il y a une panne), etc. Cette réputation est-elle justifiée ? Le support, en tout cas, est à la hauteur de son image.

La dernière question que j'ai posée au support par courrier électronique était : « Y a t-il un moyen de dire à la Freebox (configurée en routeur + serveur DHCP) de distribuer comme serveur DNS non pas sa propre adresse mais des adresses IP de serveur que je choisis ? » Et la réponse, qui a mis pas moins de trois jours pleins à arriver, est « Si vous désirez configurer un réseau wifi, il vous faut vous rendre dans la rubrique "Fonctionnalités Optionnelles" de l'interface personnalisée de votre compte utilisateur à l'adresse suivante (http://subscribe.free.fr/login/). Ensuite veuillez cliquez sue le lien: "internet" puis : "Configurer mon routeur Freebox" Ensuite veuillez activer le mode routeur et le mode DHCP ensuite veuillez sortir et cliquer de nouveau sur "internet" puis sur la partie guache de la page vous trouverez le lien :"Personnaliser mon reverse DNS" ou vous pouvez distribuer les adresses que vous choisissez. » D'où sort le Wifi ? Et, d'une manière générale, quel rapport avec ma question ?

On voit que la rumeur fréquente selon laquelle le support de Free serait assuré entièrement par des logiciels, type Eliza, est une pure calomnie. Un robot ne mettrait pas trois jours à répondre et lirait probablement mon message, sans inventer n'importe quoi comme ce Wifi mystérieusement apparu. La réalité est plutôt que le support est assuré par des gens incompétents, sous-payés et méprisés, et que la qualité est à l'avenant. Compte-tenu du marché de l'emploi, on se doute bien que quelqu'un qui aurait, ne serait-ce qu'un Bac+2 en informatique ne ferait pas le support de premier niveau...


L'article seul

PowerDNS permet de modifier facilement les réponses DNS

Première rédaction de cet article le 27 juin 2008


Le serveur DNS récursif PowerDNS permet, depuis la version 3.1.7, de modifier facilement les réponses DNS, par exemple pour filtrer du contenu indésirable ou bien pour transformer les réponses « Domaine inexistant » en une réponse pointant vers un site Web d'aide. C'est, je crois, le premier récurseur à permettre cela, via une interface claire et bien documentée.

Il existe une forte demande de « réécriture » des réponses DNS. Par exemple, la justice peut imposer à un FAI de filtrer tel ou tel site illégal. Ou bien un FAI peut vouloir mentir à ses clients en les dirigeant vers une page Web avec des publicités dès que ces clients font une faute de frappe et que le nom de domaine n'existe pas. Ces demandes étaient jusqu'à présent satisfaites en modifiant le source du résolveur (par exemple BIND), ou bien en programmant de zéro avec des bibliothèques comme Net::DNS en Perl.

Désormais, avec l'annonce de la version 3.1.7 de PowerDNS, cette réécriture est démocratisée. Le serveur récursif PowerDNS appelle une fonction écrite en Lua avant de renvoyer la réponse et cette fonction peut modifier ladite réponse. Changer une valeur est désormais aussi simple que d'écrire un script Lua comme :

function nxdomain  ( ip, domain, qtype )
       if qtype ~= pdns.A then return -1, {} end  --  only A records
       if not string.find(domain, "^www%.") then return -1, {} end  -- only things that start with www.
       ret={}
       ret[1]={qtype=pdns.CNAME, content="www.example.com", ttl=3602}
       ret[2]={qname="www.example.com", qtype=pdns.A, content="192.0.2.4", ttl=3602}
       return 0, ret
end

Les notes de cette version parlent de l'utilité de ce service pour des « réécritures responsables ». Mais c'est là que le bât blesse. Certes, PowerDNS n'est qu'un outil, il n'est pas responsable des mauvaises utilisations qui ne manqueront pas d'être faites. Certes, il existe des utilisations légitimes d'un tel système (comme le filtrage des publicités grâce au script en http://www.fredan.org/nomoreads_pdns-recursor.tar). Certes, si un serveur récursif est utilisé par une seule personne, elle a tout à fait le droit de modifier les réponses comme elle veut.

Mais la demande de réécriture des réponses DNS vient surtout de ceux qui veulent tromper leurs utilisateurs. Le cas le plus fréquent est celui de FAI peu scrupuleux qui renvoient, à la place du NXDOMAIN (No Such Domain, nom non trouvé) l'adresse IP d'un de leurs serveurs Web, avec la publicité qui va avec.

Ces pratiques ont été critiquées dans le RFC 4924, section 2.5.2. Mais il faudra plus qu'un RFC pour les faire cesser ! En attendant, il est dangereux de donner de tels outils à ceux qui n'hésitent pas à envoyer de fausses réponses à leurs propres clients.


L'article seul

Utiliser son câblage téléphonique existant avec une Freebox en dégroupage total

Première rédaction de cet article le 27 juin 2008


Les abonnés au FAI Free en dégroupage total bénéficient d'un service téléphonique permettant de connecter des téléphones ordinaires à une prise de la Freebox. Mais ce service est très limité, notamment parce que, par défaut, il ne permet pas de réutiliser le câblage téléphonique existant dans la maison, et impose de poser le téléphone juste à côté de la Freebox (qui n'est pas forcément située dans un endroit pratique, elle est en général là où arrive la ligne). Quelles sont les solutions ?

Dans mon appartement, j'ai déjà câblage téléphonique pré-installé et prises, qui datent du temps de France Télécom, et qui marchent. Dommage de devoir les abandonner. C'est pourtant la solution la plus souvent proposée :

  • Utilisation d'un téléphone SIP connecté en IP via le Wifi ou le CPL.
  • Pose d'une base DECT près de la Freebox et du téléphone à la distance qu'on veut (si la Freebox est dans une chambre, ce qui est mon cas, il faut penser à couper la sonnerie sur la base).

Mais pourquoi la Freebox ne peut-elle activer le câblage existant ? Garfield le Chat explique :

« Une ligne téléphonique fonctionne avec deux fils (un joli schéma et une documentation complète sont disponibles en Utilisation du filtre gigogne (livré par les Fai) en filtre de tête ainsi qu'en http://goctruc.free.fr/Telephonie/Telephonie.html).

La plupart des pré-câblages réalisés en appartement sont prévus sur 4 fils (deux lignes possibles).

Le truc est d'utiliser la paire 2 pour l'arrivée FT (initialement cablée sur la paire 1 bien sûr), brancher la Freebox sur cette paire 2 (un dédoubleur de ligne - que j'ai à la maison - suffit), et de réinjecter sur la paire 1 (qui est disponible et libre) le signal sorti de la prise RJ-11 téléphone de la Freebox.

Du coup, toutes les prises de la maison deviennent potentiellement des points d'accès à des téléphones fixes (sans besoin de filtre ADSL bien sur) ou des bases DECT auto-alimentées (c'est mieux).

Mais je privilégie quand même une bonne base DECT (Siemens) avec autant de combinés que nécessaire et tant pis pour le pré-câblage.

Il faut savoir que l'énergie qui peut être transmise par la Freebox au(x) téléphones est limitée et qu'en outre la Freebox se calibre (au redémarrage) sur le (seul) téléhpone qui est censé être branché dessus.

Attention : une erreur de câblage et pssschittt la Freebox. Le 48 volts ca ne pardonne pas. »

Bref, c'est faisable mais pas juste en claquant des doigts.

Une autre façon de décrire la même approche est donnée par un contributeur anonyme :

« Tu mets un doubleur de prise téléphonique sur chacune de tes prises T murales (c'est un gros machin un peu moche qui sépare une prise T en deux prises T).

Sur la prise 1 (principale) tu connectes l'arrivée ADSL de la Freebox, comme en direct sur la prise 2, tu réinjectes la sortie téléphonique de la Freebox, et sur chacune des prises 2 dans ta maison tu as récupéré une ligne téléphonique... »

Coyote Errant nuance : « Ce principe n'est vrai que si l'installation intérieure est câblée standard, c'est-à-dire avec au moins deux paires : à vérifier avant d'acheter les doubleurs. »

Le doubleur semble disponible aux alentours de dix euros.

Voilà, pour l'instant, je ne me suis pas encore lancé mais déjà, c'est documenté :-)

Merci à Garfield le Chat, à Christian Thomas, à Era, à Coyote Errant, à Hcx, à JKB et aux autres.


L'article seul

RFC 5210: A Source Address Validation Architecture (SAVA) Testbed and Deployment Experience

Date de publication du RFC : Juin 2008
Auteur(s) du RFC : J. Wu (Université de Tsinghua), J. Bi (Université de Tsinghua), X. Li (Université de Tsinghua), G. Ren (Université de Tsinghua), K. Xu (Université de Tsinghua), M. Williams (Juniper)
Expérimental
Première rédaction de cet article le 26 juin 2008


On le sait, l'Internet ne dispose pas de moyen de garantir l'authenticité de l'adresse IP de l'expéditeur d'un paquet. Le projet SAVA (Source Address VAlidation, il ne semble pas avoir de page Web mais il existe une liste de diffusion) vise à explorer les moyens de valider les adresses IP source. Il est actuellement à un stade très préliminaire mais une première expérience en vraie grandeur a été tentée en Chine et ce RFC la documente.

Si l'Internet n'authentifie pas les adresses IP, ce n'est pas, comme on le lit souvent, parce que ses concepteurs étaient naïfs, trop confiants dans la nature humaine, ou bien parce qu'ils étaient distraits et avaient oublié cette fonction. C'est parce que le problème est très difficile dans un réseau ouvert comme l'Internet. Si les réseaux X.25 vérifiaient les numéros des appelants, c'est simplement parce qu'il n'existait qu'un petit groupe d'opérateurs (seulement deux aux États-Unis et un seul en France) et que leurs clients devaient passer par un opérateur (pas de connexion directe). C'est aussi parce que ce petit groupe fermé d'opérateurs était uniquement situés dans les pays de l'OCDE. Dans l'Internet d'aujourd'hui, si une université thaïlandaise vérifie les adresses IP des machines de ses étudiants, par quelque moyen que ce soit, pourquoi un site gouvernemental brésilien, situé à plusieurs AS de là en tiendrait-il compte ?

(Il faut également mentionner les cas où il n'est même pas évident de savoir qui est le titulaire légitime d'une adresse, comme ce fut le cas lors du récent problème avec le serveur racine L.)

Plusieurs tentatives d'authentifier les adresses IP ont déjà eu lieu. Les documents les plus souvent cités sur ce travail sont les RFC 2827 et RFC 3704. Si tous les opérateurs appliquaient ces RFC et qu'on pouvait avoir confiance en tout le monde, le problème de l'usurpation d'adresses IP disparaitrait. Comme ce n'est pas le cas, le projet SAVA aborde le problème différemment.

SAVA est à la fois plus ambitieux (puisqu'il vise à permettre l'authentification de toute adresse IP partout dans le monde) et plus modeste, puisqu'il est bâti sur le prémisse que tout le monde n'adoptera pas SAVA (en tout cas, pas imémdiatement), et que peu d'opérateurs en déploieront immédiatement toutes les composantes et qu'il faut donc qu'il y aie des bénéfices même pour les premiers adoptants (ce qui manque au RFC 2827).

Le principe de SAVA est que chacun vérifie ce qu'il peut (il n'y a pas obligation de vérifier chaque adresse IP, une vérification du préfixe est déjà appréciable) et qu'il le communique à ceux qui le veulent. Selon les relations de confiance entre opérateurs, ces informations se propageront plus ou moins loin.

Le réseau chinois de la recherche et de l'enseignement CRNET a décidé de monter un test en grandeur nature de SAVA, dans son état actuel (SAVA n'est pas du tout normalisé, pour des raisons à la fois techniques et politiques.) Ce RFC est le compte-rendu de cette expérience. Douze sites ont participé à l'expérience, qui n'était donc pas une simple petite manipulation de laboratoire.

La section 2 du RFC résume les principes de SAVA, notamment le caractère « multi-barrières » (les vérifications peuvent se faire à divers endroits, puisqu'il n'est pas réaliste de les imposer, on aura donc toujours des cas où l'autre n'aura pas validé les adresses). Autre règle de SAVA : le fait que plusieurs mécanismes de vérification peuvent coexister. Non seulement il ne serait pas réaliste techniquement d'utiliser le même mécanisme pour un réseau Wifi et pour un réseau national, mais cette souplesse dans le choix des techniques de validation permet de maximiser le nombre de participants. SAVA se veut donc plus réaliste que les incantations habituelles « Il faudrait que tout le monde mette en œuvre le RFC 2827 ». Actuellement, dans SAVA, les vérifications peuvent se faire dans le réseau local, à l'intérieur de l'AS (c'est la seule possibilité dans le RFC 2827) ou bien entre AS. Autant que possible, SAVA réutilise des techniques existantes.

Les sections suivantes du RFC détaillent ces trois possibilités. La 2.2 explore les moyens de vérifier les adresses IP sur le réseau local, par exemple en ayant un commutateur qui interagisse avec le protocole d'allocation d'adresses IP. Aujourd'hui, le commutateur Ethernet est typiquement ignorant des allocations faites, par exemple avec DHCP et ne peut donc pas vérifier les adresses. Si ce commutateur jouait un rôle dans DHCP, il connaitrait les adresses IP qui peuvent apparaitre sur chaque port physique et pourrait les valider (cette technique se répand depuis : RFC 7513).

La section 2.3 traite la validation à l'intérieur de l'AS en recommandant simplement l'usage des techniques du RFC 2827 et RFC 3704.

Et les sections 2.4 et 2.5 traitent de la validation des adresses IP entre deux AS. 2.4 s'occupe du cas où les deux AS sont directement connectés. Dans ce cas, le problème est bien connu, chaque AS doit n'accepter de son voisin qu'un jeu limité de préfixes, enregistré dans un registre comme les IRR. Notons que l'expérience du détournement de YouTube par Pakistan Telecom a bien montré que cette pratique restait minoritaire, en partie parce que les IRR sont de qualité médiocre et en partie parce qu'elle impose un travail supplémentaire à tous. Certes, cette affaire portait sur le non-filtrage des annonces BGP et pas sur le non-filtrage des adresses IP mais rien ne permet de penser que le second filtrage sera fait plus sérieusement que le premier.

Plus délicat techniquement est le cas où les deux AS ne sont pas connectés directement. La solution préconisée par SAVA (sections 2.5 et 5.3) est alors l'utilisation d'un en-tête IPv6 spécial (l'expérience a été faite dans un environnement purement v6, ces en-têtes sont décrits dans le RFC 2460, section 4.3), le authentication tag. Signé cryptographiquement, cet en-tête permet de s'assurer que les routeurs des AS intermédiaires n'ont pas « bricolé » les adresses.

Après ces principes, la section 3 décrit l'expérience effective. La Chine a changé depuis « Tintin et le lotus bleu ». Le réseau CNG1-CERNET2, utilisé pour le test, connecte vingt-cinq sites, répartis dans tout le pays, à des débits allant jusqu'à 10 Gb/s. Il comprend plusieurs AS et est purement IPv6. L'expérience n'a utilisé qu'une moitié de ces sites, mais a mis en œuvre les trois scénarios de validation décrits en section 2. Les douze sites participants n'ont pas tous déployé ces trois scénarios, ce qui permet de tester SAVA dans le cas (réaliste) où tout le monde n'est pas au même niveau de déploiement.

La section 4 présente les résultats de l'expérience et proclame qu'elle fut un succès. Les paquets usurpateurs injectés dans le réseau, ont été tous jetés tôt ou tard. Les performances n'ont pas toujours été au rendez-vous, par exemple le routeur IPv6 routait toutes les extensions hop-by-hop en logiciel, donc à des performances catastrophiques pour des liaisons si rapides.

Cela ne veut pas dire que SAVA, tel que déployé dans le banc de test, soit parfait. La section 5 détaille ses limites et devrait être lue par tous ceux qui s'indignent bruyamment que l'Internet ne leur offre pas encore le niveau de traçabilité qu'ils réclament. D'abord, il faut noter qu'il y a belle lurette que la majorité des attaques sur Internet ne sont plus effectuées en trichant sur l'adresse IP. Les zombies ne se soucient en effet pas de déguiser leur adresse. D'autre part, même si SAVA peut commencer localement, une validation de bout en bout nécessitera en général la coordination de plusieurs AS, chose très difficile à obtenir. Enfin, la section 5 note que des techniques comme le multihoming ou la mobilité compliquent encore les choses.

Reste à savoir ce que deviendra SAVA. La section 6 propose une synthèse en affirmant que l'expérience a été un succès mais que le protocole doit être considérablement amélioré. Le cadre général et les protocoles ne sont pas encore normalisés et l'IETF n'a pas encore accepté un groupe de travail pour le faire (un groupe de travail avec une charte plus restreinte, SAVI, a été proposé mais pas encore accepté), SAVA soulevant bien des problèmes, notamment politiques. Ce n'est pas par hasard que la première expérimentation de SAVA sur le terrain aie eu lieu dans un pays gouverné par une dictature. Dans les couloirs de l'IETF, on entend souvent des protestations contre une technique qui rendrait la tâche des policiers chinois plus facile.


Téléchargez le RFC 5210


L'article seul

RFC 4013: SASLprep: Stringprep Profile for User Names and Passwords

Date de publication du RFC : Février 2005
Auteur(s) du RFC : K. Zeilenga (OpenLDAP Foundation)
Chemin des normes
Première rédaction de cet article le 20 juin 2008


Beaucoup de protocoles Internet ont besoin de comparer des noms, par exemple pour tester leur égalité avant une authentification de ce nom. Si les noms sont en Unicode, il est préférable de les normaliser avant la comparaison, pour que le résultat de celle-ci ne soit pas trop déroutant pour l'utilisateur. C'est le but de SASLprep, normalisé dans ce RFC.

Le RFC sur SASLprep est très court car SASLprep est juste un profil de stringprep (normalisé dans le RFC 3454). Stringprep était l'algorithme général de normalisation des noms à l'IETF. Il ne spécifiait pas tous les détails de la normalisation effectuée, laissant ceux-ci à des profils comme nameprep (RFC 3491, utilisé dans les IDN) ou bien notre SASLprep. Stringprep ayant depuis été abandonné (cf. RFC 7564), ce RFC 4013 a été remplacé par le nouveau mécanisme du RFC 7613.

SASLprep est conçu pour l'utilisation dans le contexte de l'authentification, notamment pour SASL (RFC 4422). L'idée est de passer les noms et les mots de passe à travers SASLprep avant toute comparaison, pour que le résultat de celle-ci corresponde aux attentes de l'utilisateur (section 1).

Le profil lui-même est décrit dans la section 2. Par exemple, SASLprep utilise la normalisation Unicode NFKC (section 2.2 de notre RFC et section 4 du RFC 3454). Ainsi, comme l'illustre les exemples de la section 3, la chaîne U+2168 (Ⅸ, chiffre romain 9) sera transformée en la chaîne « IX », qui a la même signification. Sans SASLprep, un utilisateur dont le nom comporterait ce caractère Unicode aurait du mal à se loguer ! La section 2 spécifie aussi (section 2.3) les caractères interdits par SASLprep, comme les caractères de contrôle.

On peut tester cet algorithme sur Unix avec la commande idn de la GNU libidn et son option --profile :

% echo Café | idn --quiet --stringprep --profile SASLprep
Café

% echo pi² | idn --quiet --stringprep --profile SASLprep
pi2

Dans le premier exemple, on note que SASLprep est sensible à la casse (qui n'a pas été modifiée). Dans le second exemple, l'exposant 2 dans « pi au carré » a été remplacé par un 2 ordinaire, conséquence de la normalisation NFKC. Un hypothétique mot de passe « pi² » serait donc équivalent à « pi2 ».

Une mise en œuvre de SASLprep, sous forme d'une bibliothèque utilisable depuis vos programmes, figure dans la GNU SASL Library.


Téléchargez le RFC 4013


L'article seul

RFC 5153: IPFIX Implementation Guidelines

Date de publication du RFC : Avril 2008
Auteur(s) du RFC : E. Boschi (Hitachi Europe), L. Mark (Fraunhofer FOKUS), J. Quittek, M. Stiemerling (NEC), P. Aitken (Cisco)
Pour information
Première rédaction de cet article le 18 juin 2008


Le protocole IPFIX, décrit désormais dans les RFC 7011 et RFC 7012, permet à une machine d'observation (en général un routeur) d'envoyer des résumés sur le trafic observé à une machine de récolte, qui produira ensuite de jolis camemberts. Ce RFC donne des conseils aux programmeurs qui développent des systèmes IPFIX, jusqu'à citer en section 10 une liste des erreurs de mise en œuvre les plus courantes.

C'est donc un document non-normatif (section 2 pour les détails), qui ne remplace pas les RFC qui spécifient le protocole mais qui les complète, si on développe un observateur ou un récolteur IPFIX.

Comme le rappelle la section 1.2, IPFIX fonctionne en envoyant des tuples TLV. Des gabarits (Template) décrivent les données possibles (des gabarits standards sont décrits dans le RFC 7012) et des enregistrements IPFIX (Data Record) contiennent les données elles-mêmes. Les tuples peuvent être envoyés avec plusieurs protocoles de transport, SCTP étant recommandé.

Après ces préliminaires, commencent les conseils aux implémenteurs. La section 3 discute l'implémentation des gabarits. Par exemple, l'exporteur devrait envoyer le gabarit avant les données. Mais, selon le protocole de transport utilisé, le gabarit peut arriver après et le récolteur devrait donc être patient, ne pas jeter immédiatement les données où le Template ID est inconnu (section 3.1).

Les données envoyées en IPFIX sont typiquement de grande taille et le programmeur doit donc faire attention à la taille des messages envoyés. Il ne faut pas dépasser la MTU en UDP (section 3.5).

La section 4 couvre les responsabilités de l'exporteur. Ainsi, 4.3 lui rappelle de maintenir les compteurs (par exemple le nombre de paquets d'un flot), y compris sur une longue période. S'il risque de ne pas en être capable, il doit plutôt utiliser des compteurs différentiels (Delta Counter, section 3.2.3 du RFC 7012). 4.5 se consacre aux enregistrements qui portent l'indication de l'heure et rappelle donc qu'il faut synchroniser ses horloges, par exemple avec NTP.

Ceux qui développent le logiciel du récolteur liront plutôt la section 5 qui leur rappellera, par exemple, que les identificateurs des gabarits (Template ID) ne sont uniques que par exporteur (plus rigoureusement, par observation domain) et qu'il faut donc maintenir une liste par exporteur.

La section 6 est consacrée aux problèmes de transport. Contrairement à beaucoup d'autrs protocoles IETF, où un seul protocole de transport est spécifié, afin de maximiser l'interopérabilité, IPFIX offre un grand choix : UDP, TCP et SCTP, ce dernier étant le seul obligatoire (avec son extension PR du RFC 3758). La section 6.1 justifie ce choix et rappelle quelques conséquences de l'utilisation de SCTP. Par exemple, l'extension PR (Partial Reliability) permet d'envoyer les enregistrements avec différents niveaux de fiabilité (ceux liés à la facturation nécessitant typiquement davantage de soins que ceux de simple statistique).

En revanche, la section 6.2, consacrée à UDP, explique pourquoi ce protocole est dangereux et comment limiter les risques (notamment en ne l'utilisant qu'au sein de réseaux fermés et contrôlés). Cela peut être le cas si on met à jour un système Netflow en IPFIX, puisque Netflow n'utilisait que UDP.

La section 7 est consacrée aux middleboxes, les machines intermédiaires comme les coupe-feux ou les routeurs NAT. Perturbant les flots mesurés, elles entrainent de délicats problèmes pour la mesure, par exemple la nécessité de bien choisir le point exact d'observation (section 7.2). Comme ces intermédiaires peuvent modifier certaines caractéristiques du flot comme le port, l'information transmise par IPFIX peut devenir très variable (section 7.3.3).

La section 8 est dédiée à la sécurité. IPFIX sert souvent à transporter des données sensibles et la section 8.1 rappelle qu'il peut être prudent d'utiliser DTLS ou TLS, afin d'éviter qu'un indiscret ne prenne connaissance des informations.


Téléchargez le RFC 5153


L'article seul

Perspectives, un outil pour améliorer la sécurité de SSH et des protocoles équivalents

Première rédaction de cet article le 11 juin 2008


Vous connaissez le TOFU ? Pas celui qui se mange. TOFU est un sigle qui veut dire Trust On First Use et qui désigne les applications réseau qui vérifient, via la cryptographie, que la machine à laquelle elles parlent est bien la même que la dernière fois, alors même qu'il n'y a en général pas de vérification sérieuse la première fois. SSH est l'exemple le plus connu.

À la première connexion SSH avec une machine, on reçoit un avertissement :

% slogin rebecca
The authenticity of host 'rebecca.generic-nic.net (192.134.7.252)' can't be established.
DSA key fingerprint is b8:28:72:4d:66:40:9e:40:47:55:a1:40:ad:4a:d8:30.
Are you sure you want to continue connecting (yes/no)? 

Si on répond OUI, sans vérifier l'empreinte (ce que fait quasiment tout le monde), on est connectés. Mais si le méchant s'était glissé sur le chemin à ce moment là, on est fichus.

SSH est plus efficace si le méchant arrive par la suite :

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the DSA host key has just been changed.
The fingerprint for the DSA key sent by the remote host is
b8:28:72:4d:66:40:9e:40:46:55:a1:40:ad:4a:d8:30.
Please contact your system administrator.
Add correct host key in /home/bortzmeyer/.ssh/known_hosts to get rid of this message.
Offending key in /home/bortzmeyer/.ssh/known_hosts:11
DSA host key for rebecca.generic-nic.net has changed and you have requested strict checking.
Host key verification failed.

Par défaut, SSH bloque l'accès dans ce cas. Il reste donc la faiblesse de la première connexion. Une solution possible est d'utiliser des options « fascistes » comme StrictHostKeyChecking yes et de vérifier à la main les empreintes des clés. Très peu le font, c'est bien trop contraignant. Une autre approche a été choisie par le RFC 4255, qui consiste à publier la clé SSH dans le DNS. Évidemment, cela implique que la zone soit signée par DNSSEC et que l'administrateur de la zone fasse bien son nouveau travail d'Autorité de certification.

Perspectives, présenté dans l'article Improving SSH-style Host Authentication with Multi-path Network Probing adopte une autre approche. Un réseau de machines situées un peu partout dans l'Internet se connectent aux machines qu'on leur a indiqué et, sur demande, indiquent la clé observée. Ce réseau fournit donc une redondance spatiale (les différentes machines observent depuis différents points du réseau, ce qui protège contre certaines attaques, par exemple celles utilisant BGP) et une redondance temporelle (les machines du réseau de vérification, les notaires, ont une mémoire des clés précédentes et peuvent détecter un changement).

Voyez l'article pour les détails, qui sont nombreux (il faut authentifier les notaires et qu'ils signent leurs messages, il faut pouvoir accepter plusieurs réseaux de notaires concurrents, il faut gérer le cas où, comme dans Minority Report, ils ne sont pas d'accord entre eux, etc).

Ce système ne s'applique pas qu'à SSH, il peut concerner toutes les applications de type TOFU, ce qui est souvent le cas de HTTPS.

L'équipe de Perspectives a continué le travail et le tout est désormais présenté sur leur site officiel. Des idées similaires ont été avancées pour le DNS, par exemple ConfiDNS.


L'article seul

RFC 4925: Softwire Problem Statement

Date de publication du RFC : Juillet 2007
Auteur(s) du RFC : X. Li (Cernet), S. Dawkins (Huawei), D. Ward (Cisco), A. Durand (Comcast)
Pour information
Réalisé dans le cadre du groupe de travail IETF softwire
Première rédaction de cet article le 11 juin 2008


Les réseaux informatiques typiques d'il y a vingt ans étaient multi-protocoles et ces protocoles coexistaient plus ou moins harmonieusement. Pour connecter deux réseaux via un troisième, parlant un protocole différent, on utilisait souvent des tunnels. C'est ainsi que, par exemple, IP a servi à connecter beaucoup de réseaux AppleTalk. Puis IP a tout remplacé et les réseaux sont devenus mono-protocole. Maintenant, avec l'épuisement des adresses IPv4 qui se rapproche, avec le déploiement d'îlots IPv6 qu'il faut relier entre eux, les tunnels reviennent, et avec eux beaucoup de complexité. Un groupe de travail de l'IETF, softwire (« câbles virtuels ») travaille donc à une meilleure spécification de ces tunnels. Ce RFC est la première étape publiée de leur travail.

Les idées derrière le système des « câbles virtuels » (soft wires) sont très anciennes. Par exemple, le système de « courtier en tunnels » (tunnel broker) du RFC 3053, en janvier 2001, était déjà un câble virtuel, même si le mot n'existait pas encore. Mais pourquoi avoir remplacé les tunnels par des « câbles virtuels » ? La raison principale est cosmétique : les tunnels souffrent d'une mauvais réputation, lents, compliqués, peu fiables, posant des problèmes de MTU. Comme les balayeurs sont devenus techniciens de surface, comme le surveillant général est devenu conseiller d'éducation, les tunnels sont devenus des soft wires (la section 1.1 détaille le vocabulaire et définit le câble virtuel comme un tunnel, créé sous le contrôle d'un protocole, ce qui exclut donc les tunnels manuels).

Ce premier RFC ne fait que définir le problème. D'autres documents, en cours d'élaboration à l'IETF, s'occuperont des protocoles effectifs. La section 1 introduit le problème, spécifier des câbles virtuels qui pourront être établis rapidement, mais durer longtemps, afin de connecter des réseaux IP entre eux (typiquement, des réseaux IPv6 via un réseau IPv4). Cette section introduit également la grande distinction entre les topologies « Centraliser et redistribuer  » (Hubs and Spokes) et « Maillage » (Mesh). Dans le premier cas, le réseau est organisé autour de points proéminents (les hubs) qui concentrent le trafic et le redistribuent. Dans le second, tout le monde est au même niveau.

La section 2 est consacrée au « Centraliser et redistribuer  ». Les tunnels du RFC 4213 sont un exemple typique de cette approche. Voici, extrait de cette section, un cas où une machine double pile (v4 et v6) se trouve sur un réseau local où le CPE est purement v4 (la section 2.2 décrit plus finement ce cas), et qui est connecté à un FAI purement v4. Elle va donc établir un câble virtuel avec un concentrateur de câbles virtuel (le « hub ») qui va ensuite la connecter aux réseaux v6. Seul IPv6 circulera sur ce câble virtuel. softwire-fig3 Comme précisé dans la section 2.4, le protocole du câble virtuel doit permettre la délégation d'un préfixe IPv6 fixe, même si l'adresse IPv4 du CPE change. On peut utiliser pour cela le RFC 3633. Cette exigence fait que 6to4 ne permet pas de créer de véritables câbles virtuels, puisque l'adresse IPv6 change en même temps que la v4.

Dans le mode « Centraliser et redistribuer », c'est toujours la machine double pile qui crée le câble virtuel, en se connectant au concentrateur. Elle est nommée l'initiateur (section 2.5). Le concentrateur est typiquement un routeur double pile (section 2.6). Le RFC impose que le protocole permette « des millions » d'initiateurs. Le protocole de découverte du concentrateur n'est pas spécifié. Enfin, la section 2.11 détaille les exigences de sécurité, comme la possibilité d'authentifier les initiateurs.

La section 3, elle, parle de l'architecture maillée. Dans cette architecture, un réseau uniquement IPv4 connecte des clients IPv6 entre eux en fournissant des AFBR (Address Family Border Routers) qui parlent les deux protocoles et peuvent créer des câbles virtuels entre eux. Cela ressemble donc beaucoup aux VPN, par exemple dans le RFC 4364, mais sans l'exigence de gérer plusieurs espaces d'adressage distincts.

Les câbles virtuels, en pratique, vont nécessiter d'encapsuler les paquets d'un protocole (en général IPv6) dans un autre (en général IPv4). Les sections 2.13 et 3.5 discutent de l'encapsulation en notant que toutes les techniques existantes doivent pouvoir être utilisées. Cela implique GRE (RFC 2784), MPLS (RFC 3031) ou L2TP (RFC 3931).


Téléchargez le RFC 4925


L'article seul

Envoyer text/html ou bien application/xhtml+xml ?

Première rédaction de cet article le 10 juin 2008


Ce blog est entièrement publié en XHTML, une instance de XML. Pourtant, si vous regardez les en-têtes HTTP émis par le serveur, vous verrez text/html et pas application/xhtml+xml, qui est la valeur officielle (cf. RFC 3236 ou bien XHTML Media Types).

Pas mal d'électrons ont déjà été maltraités pour écrire des pages Web expliquant que ceux qui utilisent text/html sont des crétins ignorants et que seul application/xhtml+xml est acceptable. C'est le cas par exemple du texte Sending XHTML as text/html Considered Harmful (une traduction en français existe). Ce texte est très pinailleur, mettant en avant des problèmes ponctuels, liés à des cas vraiment rares. Son quasi-unique argument c'est que avec XHTML, les auteurs feront du XML invalide sans s'en rendre compte. Ça ne s'applique pas à mon blog, où les fichiers sont tous validés. (Le cas de tels sites est traité dans l'annexe B du document, mais celle-ci ne va pas jusqu'à reconnaître que le conseil est mauvais.)

Un autre argument, celui des risques que les lecteurs copient-collent le XML dans un document HTML et aient des problèmes est vraiment ridicule. C'est comme dire « C'est mal de programmer en D car cela ressemble trop au C et les utilisateur vont le copier-coller, produisant ainsi du C incorrect ».

Mais pourquoi ne pas utiliser application/xhtml+xml quand même ? Après tout, c'est la norme. Je n'ai pas de position bien tranchée sur ce point (contrairement à Karl Dubost qui dit « N'en déplaise à de nombreuses personnes, servir des pages en application/xhtml+xml n'est plus un choix difficile »). À une époque, certains logiciels comme lynx avaient des problèmes avec application/xhtml+xml (cela semble réglé). Mais MSIE n'accepte toujours pas ce type (il propose juste d'enregistrer le fichier), ce qui élimine pas mal d'utilisateurs.

Et je regrette surtout qu'on utilise le type MIME application alors que text conviendrait bien mieux (text/* est pour tous les types qu'on peut lire avec un éditeur ordinaire, ou bien avec cat ou more, ce qui est bien le cas de XML).

Je changerais donc peut-être la configuration de mon blog un jour, mais je n'accepte pas le discours comme quoi text/html pose des problèmes, cela ne correspond pas à ce que j'observe, même avec IE. Même http://www.w3c.org/ ne le fait pas.

À noter que la question est uniquement du type MIME à annoncer. Mes pages sont toujours en XHTML et c'est très bien comme cela (l'article Laisser tomber le XHTML ? donne un autre point de vue).

Enfin, pour parler de choses pratiques, si votre site est servi par Apache, la configuration pour envoyer le type MIME officiel est :

AddType application/xhtml+xml .html

L'article seul

RFC 5256: INTERNET MESSAGE ACCESS PROTOCOL - SORT AND THREAD EXTENSIONS

Date de publication du RFC : Juin 2008
Auteur(s) du RFC : M. Crispin (Panda Programming), K. Murchison (Carnegie Mellon University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF imapext
Première rédaction de cet article le 10 juin 2008


Le protocole IMAP d'accès aux boîtes aux lettres distantes s'étoffe dans toutes les directions. Ce RFC normalise les extensions permettant au serveur IMAP de faire le tri des messages lui-même, avant de les envoyer chez le client.

Un serveur IMAP peut être simpliste, laissant le client faire l'essentiel du travail, par exemple de tri des messages pour les afficher dans l'ordre souhaité par l'utilisateur. Mais certains serveurs IMAP, par exemple ceux qui stockent les messages dans une base de données SQL peuvent aussi faire ce travail facilement et les extensions SORT et THREAD permettent à un client de demander ce tri. C'est utile pour certains clients (cf. RFC 1733) et cela garantit aux utilisateurs un tri standard.

La section 2 du RFC présente d'abord quelques termes de base. Ainsi, 2.1 explique le concept de « sujet de base ». Le sujet des messages (dans le champ Subject:) étant parfois modifié en cours de discussion (notamment par l'ajout des caractères indiquant une réponse, typiquement Re: ), le tri par sujet doit se faire sur le sujet de base, pas sur le contenu littéral du sujet. Ce sujet de base s'obtient notamment en décodant les séquences du RFC 2047 et en supprimant les Re:  ou Fwd:  initiaux. (La section 2.1 précise bien que, vue la fantaisie avec laquelle certains logiciels modifient le sujet, on n'atteindra pas 100 % de succès.)

La section 3 contient la définition formelle des deux nouvelles extensions. La nouvelle commande SORT pourra indiquer le critère de tri, parmi un ensemble pré-défini (date, expéditeur, taille, sujet, etc). Si on trie selon l'expéditeur, seulement la partie locale de l'adresse (addr-mailbox) est utilisée donc par exemple l'expéditeur de mes messages, pour ce tri, sera stephane+blog et pas stephane+blog@bortzmeyer.org et encore moins Stéphane Bortzmeyer <stephane+blog@bortzmeyer.org>. Trier sur le nom affiché, par exemple, ouvrirait des possibilités très intéressantes pour les amateurs d'internationalisation. Ainsi, la liste suivante (tel qu'elle serait triée par un tri alphabétique stupide) :

  • Bandou Mitsugoro
  • Mao Zedong
  • Mark R. Crispin
  • Nishimura Aiko
  • Pedro Castro Gomez

peut être triée de nombreuses façons. Un tri qui croirait être malin en utilisant le nom de famille donnerait :

  • Nishimura Aiko
  • Mark R. Crispin
  • Pedro Castro Gomez
  • Bandou Mitsugoro
  • Mao Zedong

alors que le tri correct, tenant compte de la position du nom de famille dans les différentes cultures, serait :

  • Bandou Mitsugoro
  • Pedro Castro Gomez
  • Mark R. Crispin
  • Mao Zedong
  • Nishimura Aiko

Les auteurs ont jugé que demander à implémenter un tel tri, internationalement correct, serait trop exiger. Le tri se fait donc seulement sur le nom de la boîte aux lettres.

Plusieurs critères peuvent être spécifiés, chacun servant de clé successive pour départager les ex-aequo. Par exemple, à la commande IMAP :

TAG145 SORT (SUBJECT FROM DATE) UTF-8 ALL

le serveur triera selon le sujet, puis selon l'expéditeur (à sujet identique), puis selon la date si les deux premiers critères donnent le même résultat.

La nouvelle commande THREAD, quant à elle, permet d'organiser les messages en fils (threads) de discussion, selon les références (la méthode normale, avec les champs References: et In-Reply-To:) ou selon le sujet (« rangement du pauvre », pour le cas où les références manquent). Notons qu'une telle méthode nécessite que les utilisateurs se servent du courrier correctement et, par exemple, ne volent pas les fils.

La section 4 décrit les réponses possibles à ces deux commandes et la section 5 donne la grammaire formelle en ABNF.

Désolé, je n'ai pas encore cherché quels serveurs IMAP mettaient en œuvre les nouvelles extensions mais elles sont apparemment largement déployées sur le terrain depuis de nombreuses années (l'extension SORT est annoncée dans la réponse CAPABILITY de beaucoup de serveurs IMAP, cf. section 7.2.1 du RFC 3501 pour cette réponse).


Téléchargez le RFC 5256


L'article seul

RFC 5255: Internet Message Access Protocol Internationalization

Date de publication du RFC : Juin 2008
Auteur(s) du RFC : Chris Newman (Sun), Arnt Gulbrandsen (Oryx), Alexey Melnikov (Isode)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF imapext
Première rédaction de cet article le 10 juin 2008


Le protocole IMAP (RFC 3501) d'accès à des boîtes aux lettres distantes a déjà quelques capacités d'internationalisation mais ce RFC en ajoute deux : la possibilité de demander des messages en diverses langues et la possibilité de demander d'autres fonctions de comparaison du texte.

La section 3 présente la première extension, LANGUAGE. Elle permet à un client IMAP de demander, en utilisant les étiquettes de langue du RFC 4646 une autre langue que celle par défaut, pour les messages du serveur, messages qui sont souvent transmis tels quels à l'utilisateur humain. Par exemple, un dialogue entre le client C: et le serveur S: (ici, le serveur parle anglais, allemand et italien) pourra être :

        C: A003 LANGUAGE
        S: * LANGUAGE (EN DE IT i-default)
        S: A003 OK Supported languages have been enumerated
...
        C: C001 LANGUAGE DE
        S: * LANGUAGE (DE)
        S: C001 OK Sprachwechsel durch LANGUAGE-Befehl ausgefuehrt

La section 4 présente la deuxième extension, qui comprend deux niveaux, I18NLEVEL=1 et I18NLEVEL=2. Cette extension permet aux fonctions de tri du RFC 5256 d'utiliser divers comparateurs (RFC 4790). Au premier niveau (section 4.3), le comparateur i;unicode-casemap (RFC 5051) est utilisé, au deuxième niveau (section 4.4), le client peut choisir un comparateur de son choix, avec la commande COMPARATOR (section 4.7).

La section 4.5 décrit un problème de compatibilité avec les mises en œuvre actuelles d'IMAP, qui n'utilisent pas toutes le même comparateur par défaut.

Enfin, le RFC note (section 5) que l'internationalisation complète du courrier nécessite également des actions en dehors d'IMAP comme les adresses de courrier internationalisées (RFC 6530).


Téléchargez le RFC 5255


L'article seul

Pas de macros en XML, hélas

Première rédaction de cet article le 9 juin 2008


Depuis des années que je fais des documents XML, je regrette l'absence d'un mécanisme de macros, permettant de mettre plusieurs éléments d'un coup.

Quelques exemples concrets pour expliquer ce qui me manque :

  • Je parle de noms de domaines dans des documents Docbook et, au lieu de <systemitem role="domainnname">fr</systemitem>, j'écrirai bien <domain>fr</domain>.
  • J'ai souvent en Docbook des énumérations qui n'ont qu'un seul paragraphe et, plutôt que de taper <listitem><para> à chaque fois, je préférai juste mettre <item>.

Les transformations XML ne résolvent pas le problème. Ce n'est pas la présentation finale que je veux changer, c'est le code XML tapé. Ainsi, si j'utilise un programme XSLT pour convertir mes « macros », comme l'éditeur XML ne les connait pas, il ne va pas pouvoir m'afficher les éléments valides (une fonction de mon éditeur XML dont je me passerais difficilement).

Les entités XML ne résolvent pas le problème parce que j'ai en général des paramètres (cf. l'exemple des noms de domaine ci-dessus). Et, de toute façon, elles ne survivent pas aux transformations XSLT.

Changer le schéma (ce qui est relativement facile avec des schémas comme Docbook) pour y introduire mes nouveaux éléments m'oblige ensuite à gérer une version locale de Docbook, et à adapter les feuilles de style alors que je veux juste définir un élément en terme d'autres éléments existants.

Les macros traditionnelles comme celles de M4 ou de cpp ne me plaisent guère car elles ne connaissent pas XML. Leur usage perturberait les éditeurs XML et, en utilisant ces macros, on risque de produire des documents invalides, voire mal formés (problème courant en C où l'usage des macros peut produire du code syntaxiquement invalide).

Je préférerai ce que les programmeurs Scheme appellent « macros hygiéniques » (« macros de transformation source à source » dans l'article de Wikipédia) mais elles ne semblent pas exister en XML ? C'est une des grosses limites de ce format. Les formats qui sont presque toujours produits par un programme comme JSON n'ont pas ce problème car ils ne cherchent pas à faciliter la vie d'un auteur humain. Mais XML est utilisé pour des textes (comme ce blog) et ce manque est donc sérieux.


L'article seul

Indiquer correctement l'encodage des fichiers envoyés par un serveur Web

Première rédaction de cet article le 9 juin 2008


Idéalement, il n'existerait qu'un seul jeu de caractères universel et un seul encodage de ce jeu et tout le monde l'adopterait et il n'y aurait pas de problème. Mais dans le monde où nous vivons, beaucoup de jeux coexistent sur Internet et encore plus d'encodages différents. Pour que les visiteurs de votre site Web voient les caractères corrects et non pas des signes cabalistiques (comme dans le fameux pastiche de Martine, « Martine écrit en UTF-8 »), il faut un peu de méthode.

Il n'y a en effet pas de truc magique, juste de la méthode. Celle que je suggère, et qui doit être suivie dans cet ordre est exposée ici.

1) Décider d'un jeu de caractères et d'un encodage pour les pages Web publiées. On prend ce qu'on veut, l'important est de s'y tenir. Pour le jeu de caractères, Unicode est le choix évident, puisqu'il permet de représenter tous les caractères. Pour des pages en français, son encodage UTF-8 est un bon choix. Mais on peut aussi utiliser ISO-8859-15 ou ISO-8859-1, l'important est de ne pas changer tout le temps.

2) Trouver comment produire les pages à cet encodage. Cela dépend du processus de publication. Si l'encodage choisi est UTF-8, si on édite les pages avec Emacs en UTF-8, il n'y a rien à faire. Si on édite les pages avec Emacs en ISO-8859-1, il fait convertir avec recode. Avec un CMS, il faut lire la documentation du CMS. Etc.

3) S'assurer que les pages contiennent l'indication correcte de l'encodage. En XML / XHTML, cela se fait dans la déclaration. Exemple: <?xml version="1.0" encoding="UTF-8" ?>. En HTML traditionnel, cela se fait via les éléments <meta>. Exemple: <meta http-equiv="content-type" content="text/html; charset=iso-8859-15" />. Il parait que MSIE ignore l'encodage XML et il peut donc être prudent de mettre le <meta> de toute façon, c'est ce que je fais sur mon blog.

4) S'assurer que le serveur HTTP envoie la bonne indication d'encodage. (Cette étape peut être facultative, ça dépend de beaucoup de choses. Dans le doute, je la fais toujours.) Cela se règle, avec Apache, grâce à AddCharset. Exemple: AddCharset UTF-8 .html. Ensuite, le validateur du W3C doit permettre de vérifier cela. On peut aussi utiliser l'excellente extension Firefox WebDeveloper (menu Information, option View Response Headers). Sinon, sur Unix, avec wget :

% wget --server-response --output-document /dev/null http://www.example.org/
  HTTP/1.1 200 OK
  Date: Tue, 13 May 2008 19:22:43 GMT
  Server: Apache/1.3.34 Ben-SSL/1.55
  X-Powered-By: PHP/4.4.8
  Connection: close
  Content-Type: text/html

Ici, aucun charset n'est indiqué dans la ligne Content-Type, ce qui est clairement mauvais. Questions :

  • Quelle est la valeur par défaut ?
  • Est-ce vraiment bien prudent de compter sur cette valeur par défaut ?

L'article seul

Tirer davantage du shell Unix avec les alias

Première rédaction de cet article le 9 juin 2008


Beaucoup d'utilisateurs du shell Unix ne se servent jamais d'alias ni de fonctions. Ils tapent et retapent de longues commandes compliquées, sans jamais consacrer une demi-journée à apprendre les possibilités avancées du shell. « Je n'ai pas le temps » est un excuse souvent entendue. Mais, s'ils calculaient le Temps Total (comme on définit désormais un Coût Total), peut-être trouveraient-ils que cette demi-journée d'apprentissage leur ferait gagner pas mal de temps pour leurs tâches futures. Lorsque je montre une commande compliquée à des utilisateurs Unix, leur réponse est souvent « Mais je ne vais pas taper un truc aussi long à chaque fois ! ». Bien sûr, c'est pour cela que les alias existent.

Les alias sont une fonction du shell qui permet de définir un équivalent court pour une commande. Si on veut simplement mettre quelques options, toujours les mêmes, certaines commandes Unix permettent de les fixer dans un fichier de configuration. Mais toutes les commandes n'ont pas cette possibilité. Et elle ne résout pas tous les problèmes. Si je veux enchaîner plusieurs commandes ? Si je veux utiliser parfois certaines options et parfois d'autres ? Je peux écrire un script, bien sûr, mais les alias sont une solution plus légère.

La définition d'un alias dépend légèrement du shell utilisé (en gros, la famille sh et la famille csh divergent). Tous les exemples qui suivent ont été testés avec zsh, un shell de la famille sh.

On définit un alias avec la commande du même nom :

% alias dir="ls -lt"

% dir               
total 4
-rw-r--r-- 1 stephane stephane 30 Jun  9 16:55 truc.c
...

Si on veut que cette définition soit permanente, on peut mettre la commande alias dans le fichier de démarrage (pour zsh, en ~/.zshrc).

Voici quelques alias que j'utilise souvent. Taper alias NOM va afficher la définition de l'alias de ce nom.

Pour voir facilement les en-têtes renvoyés par un serveur HTTP, ce qui aide souvent au débogage, faire un telnet à la main est une solution mais elle est souvent pénible. wget fournit ce service, s'il est appelé avec les bonnes options :

% alias hh
hh='wget --server-response --output-document /dev/null'

% hh http://www.example.org/
...
  HTTP/1.1 200 OK
  Date: Mon, 09 Jun 2008 15:02:40 GMT
  Server: Apache/2.2.8 (Ubuntu) mod_python/3.3.1 Python/2.5.2 PHP/5.2.4-2ubuntu5.1 with Suhosin-Patch mod_perl/2.0.3 Perl/v5.8.8
  Last-Modified: Wed, 19 Sep 2007 06:43:55 GMT
  ETag: "17c0cf-203-43a775c8b60c0"
  Content-Length: 515
  Content-Type: text/html
...

J'utilise, dans la définition de l'alias, les noms longs des options (--server-response au lieu de juste -S car l'alias est ainsi mieux documenté. Les noms courts des options sont très pratiques en interactif mais déconseillés dans un alias ou un script.

Un alias peut être composé de plusieurs commandes, reliées par un point-virgule (exécution séquentielle) ou un tube (execution séquentielle et la sortie de la première commande est l'entrée de la seconde). Ainsi, pour voir les 20 derniers fichiers chargés via mlDonkey :

 % alias lastdonkey 
lastdonkey='ls -lt /var/lib/mldonkey/ | head -n 20'

Il n'y a pas de limite au nombre de commandes utilisables. Ici, l'alias svnpurge supprime dans une copie de travail Subversion, tous les fichiers qui ne sont pas gérés par ce logiciel (attention, c'est une commande dangereuse). Elle est définie ainsi dans mon ~/.zshrc :

alias svnpurge="svn status | awk '/^\?/ {print $2}' | xargs rm -f"

Comment marche t-elle ? svn status affiche les fichiers non gérés par Subversion avec un point d'interrogation. awk les extrait et xargs appelle rm pour les détruire.

Après, si on veut des paramètres, des structures de contrôle un peu compliquées, il faut mieux passer aux fonctions.


L'article seul

Options IP interdites en pratique

Première rédaction de cet article le 7 juin 2008


Il devient de plus en plus difficile de déployer de nouvelles techniques sur l'Internet, en raison de coupe-feux excessivement zélés qui bloquent tout ce qu'ils ne connaissent pas. L'Internet s'ossifie, peut-être jusqu'au point où il faudra un nouveau réseau pour retrouver cette possibilité de déploiement de nouvelles techniques. Une étude de chercheurs de Berkeley montre ainsi que les options IP sont bloquées dans environ la moitié des cas.

Le protocole IPv4, normalisé dans le RFC 791, prévoit dans la section 3.1 du RFC l'ajout éventuel d'options dans l'en-tête du paquet IP. Ces options étaient prévues pour permettre certaines fonctions supplémentaires (le RFC 791 en normalisait quatre). En théorie, toute implémentation d'IP doit les reconnaitre.

Et en pratique ? Bien des fonctions parfaitement standards, normalisées depuis des années, comme ECN (RFC 3168) sont, en pratique, inutilisables car filtrées par beaucoup de routeurs. Un groupe de chercheurs a donc cherché ce qu'il en était des options IP et leur conclusion, publiée dans l'article IP Options are not an option est inquiétante : environ la moitié des chemins entre deux machines jettent les paquets IP ayant une option.

Comment ont-ils mesuré ? Ils sont partis du réseau PlanetLab, qui comprend de nombreuses machines un peu partout dans le monde. Entre chaque couple de machines, ils ont tenté d'envoyer des paquets IP avec et sans option (et avec diverses options) et ont compté les cas où le paquet sans option arrivait, mais pas le paquet avec option.

Leur étude approfondit ce résultat en montrant également que le paquet est en général jeté près du point de départ ou bien d'arrivée, c'est-à-dire aux franges de l'Internet, pas dans les réseaux des grands opérateurs.

À noter que, bien que IPv6 soit mentionné dans leur étude, les tests ont été effectués uniquement en IPv4. Il serait intéressant de voir ce que cela donne en v6 puisque le mécanisme d'options est complètement différent. En IPv4, tout paquet avait un champ Options, et de longueur variable, ce qui est très pénible à analyser rapidement pour les routeurs. En IPv6, les options (RFC 2460, section 4.2) sont en dehors de l'en-tête, dans une « extension d'en-tête ».

Une analyse équivalente pour TCP, pas plus optimiste, se trouve dans l'excellente étude de Google Probing the viability of TCP extensions.


L'article seul

RFC 5185: OSPF Multi-Area Adjacency

Date de publication du RFC : Mai 2008
Auteur(s) du RFC : S. Mirtorabi (Nuova), P. Psenak (Cisco), A. Lindem, A. Oswal (Redback networks)
Chemin des normes
Première rédaction de cet article le 7 juin 2008


Le protocole de routage OSPF, normalisé dans le RFC 2328 pour IPv4 et RFC 5340 pour IPv6 est toujours autant utilisé et connait régulièrement de nouveaux perfectionnements. C'est ainsi que, grâce à ce nouveau RFC, on peut désormais mettre un lien physique dans deux zones OSPF.

Dans l'OSPF classique multi-zones (les zones - areas - sont un mécanisme de découpage des grands réseaux OSPF, cf. section 3 du RFC 2328), un lien physique, par exemple un réseau Ethernet, ne peut appartenir qu'à une seule zone. C'est parfois contraignant, comme le montre l'exemple cité dans la section 1.1 de notre RFC. En effet, OSPF préférera toujours une route interne à la zone à une route inter-zones et cette règle l'empêchera parfois de choisir la meilleure route. Dans cet exemple : ospf-multi-area-adj les routeurs R1 et R2 vont communiquer via les trois liens qui se trouvent dans la zone 1 et pas par l'épine dorsale, pourtant plus rapide mais située dans une autre zone.

La section 1.2 du RFC examine donc les contournements possibles et leurs inconvénients, avant que la 1.3 ne résume la solution choisie : permettre la création d'une adjacence entre deux routeurs OSPF au dessus d'un lien appartenant à une autre zone. Cette adjacence se fera comme si les deux routeurs étaient connectés par une liaison point-à-point (section 2.7 pour les détails).

La section 2, assez courte, détaille les changements que cela nécessite dans le protocole, changements qui sont compatibles avec les implémentations existantes (la section 3 discute cette compatibilité). Ce changement est le même pour OSPF IPv4 et OSPF IPv6 (OSPFv3), comme décrit dans la section 4.

Je ne connais pas encore d'implémentations de ce RFC.


Téléchargez le RFC 5185


L'article seul

RFC 4035: Protocol Modifications for the DNS Security Extensions

Date de publication du RFC : Mars 2005
Auteur(s) du RFC : R. Arends (Telematica Institute), R. Austein (ISC), M. Larson (Verisign), D. Massey (Colorado State University), S. Rose (NIST)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 5 juin 2008


L'ensemble connu sous le nom de DNSSEC vise à authentifier les réponses des serveurs DNS en signant cryptographiquement lesdites réponses. Cet ensemble est normalisé dans plusieurs RFC dont notre RFC 4035, qui spécifie les changements dans le protocole. Ces modifications du protocole sont modérées mais indispensables pour l'authentification des données.

Ce RFC complète donc le RFC 4033 qui exposait les principes généraux de DNSSEC, ainsi que son cahier des charges, et du RFC 4034 qui décrivait les nouveaux types d'enregistrements DNS nécessaires, DS, DNSKEY, RRSIG et NSEC. Il met à jour l'ancien RFC qui couvrait tous les aspects de DNSSEC (RFC 2535). Il explique ce que doivent faire des serveurs et résolveurs DNSSEC pour permettre l'authentification. En effet, la simple utilisation des nouveaux enregistrements ne suffit pas à valider les réponses.

D'abord, la section 2 explique ce que doivent faire les programme de génération des zones (dnssec-keygen chez BIND) et de signature des zones (dnssec-signzone chez BIND). Elle parle donc du comportement « hors-ligne » du serveur, indépendamment des requêtes qu'il reçoit. La section 2.1 couvre la gestion des clés : leur partie publique doit être incluse dans la zone, dans des enregistrements DNSKEY, par exemple, ici dans .bg :

bg.   IN  DNSKEY  257 3 5 AwEAAcNsUEdXDwV5Sgr55kFzm0kCFNOL9iP8asHh1FKvDcxdJCe4mQJm l4kQ0C1CZyMwPIL3QWNP8yWcBLs2rfFeTX/lPXWDRvujLVxDCXCDvYkH Av4q3OkwDn+5pSH3DApKjVaW9K5XFFzNVTf3DRXWGzPNiWWXB35JHSo+ Iz2nYEHX4ZQumcT7z1BmQgQ91cS+wFT4FiCKrKdpPfxBFDSRgVZKPrL5 l6BFd/EK4jrbpzGM+83UxEBsqhR+K/GDk/yZC9jSm9DMOZJ7woYBhIwz q3lPpaoBBMbFLKw1FVQR4oFL1yznFkkcOOvZ5bu1G2s6lohoYz9Qlwld jwSqVg2TMXMclZzlUzGLFiMJsqwNnwfnD6mFaqjWbZXqRXLMupNYlKiu NKKs9zvnjpH5P/QjWX3Ym6owMebVTvlqbGc3lwIhk+d8gOYQzaUBf7Vk NRS3lb92zQe8DDhdyGosH7Po/rIP/QewKrcmgcExB4YpEZQ8M2EI5ddy 4bcnHCAqgjZ05b2mQyaxN3y4m3Ws85QsNQ7t9MnBXMkRkL6Zh9Zvs4k3 MQK4h0S6Jn22/kjqoBBsJYB2VYhToE/ljEt+uHjHVMWUtZ3jyfo1nY23 7cWXaYRW/2XNWXYluaOPdzJOuaDm6bBz5w+JbaY3GjEs78T7nmkn7MsK gDjDNwYf+8hrbDO3

La section 2.2 passe ensuite aux signatures. Elles doivent être mises dans des enregistrements RRSIG et il doit y en avoir un par RRset (ensemble des enregistrements de différents types pour un même nom de domaine). Cette section rappelle aussi qu'on ne signe que les enregistrements pour lesquels on fait autorité. Ainsi, les NS qui indiquent les serveurs de noms d'une zone, sont signés dans la zone fille, pas dans la zone parente qui s'en sert pour la délégation. Même chose pour la colle (adresses IP indispensables à la délégation), qui n'est pas signée.

Un des problèmes les plus difficiles de DNSSEC est la « preuve de non-existence ». Afin que les requêtes et réponses DNS puissent passer par des serveurs traditionnels (pour que le DNS continue à marcher, même sans validation), DNSSEC utilise des enregistrements DNS classiques. Prouver qu'un nom de domaine existe consiste simplement à produire une signature d'un enregistrement portant sur ce nom. Mais comment prouver qu'un nom de domaine n'existe pas, alors qu'il n'existe rien à signer ? DNSSEC résout ce problème par deux sortes d'enregistrement prouvant la non-existence, les NSEC, introduits dans le RFC 4034 et dont l'inclusion dans le fichier de zone est spécifiée en section 2.3 de notre RFC, et les NSEC3 qui ont été introduits plus tard par le RFC 5155. Les NSEC qui, à l'époque de la publication de notre RFC 4035, étaient le seul mécanisme de preuve de non-existence, ont en effet un gros défaut : ils permettent à un client DNS de récupérer indirectement toute la zone DNS.

La section 2.3 dit donc que tout nom de domaine pour lequel un enregistrement est signé doit avoir un NSEC, par exemple, ici le MX de laperouse.sources.org est signé et un NSEC annonce que le nom suivant est ludwigVII.sources.org :

laperouse.sources.org.  86400   IN MX   10 aetius.bortzmeyer.org.
                        86400   RRSIG   MX 3 3 86400 20080802035206 (
                                        20080601035206 55957 sources.org.
                                        CH+eYPc36AXc9W9sEIaUFnOLdlodKXa+9yLQ
                                        SuXYgDbmEQMufy052L0= )
                        43200   NSEC    ludwigVII.sources.org. MX RRSIG NSEC

La section 2.4 explique le placement des DS, les enregistrements qui complètent les NS dans la zone parente, afin de permettre une délégation signée depuis une zone vers sa fille. Un DS référence les clés publiques de la zone fille. Les DS ne se trouvent donc pas dans la zone déléguée. Ils sont générés par le gérant de cette zone déléguée et transmis au gérant de la zone parente, qui les inclut dans son fichier de zone et les signe. (On pourrait aussi envoyer les DNSKEY au parent pour qu'il génère les DS lui-même mais le RFC 6781, section 4.3.2, recommande plutôt d'envoyer les DS.) Ainsi, si le gérant de bortzmeyer.example signe sa zone avec BIND, dnssec-signzone va lui générer un fichier dsset-NOMDELAZONE. qui contiendra les DS qu'il transmettra au gérant de .example (par exemple en EPP selon le RFC 4310 ou bien selon une procédure qui dépend du registre). Voici le contenu de ce fichier des DS :

sources.org.            IN DS 55957 3 1 A12F149F84B34E09501C32CC9F984FB9E1ED196A
sources.org.            IN DS 55957 3 2 DFE4A96D7FCC9B3F99990861AE3B915E832B699FC9628CE0DF7BE45D DE37DFB3

La section 2.5 parle des CNAME, ces enregistrements « alias » qui permettent à un nom de domaine de pointer vers un autre. Les CNAME doivent évidemment être signés, ce qui implique de leur adjoindre un RRSIG et notre RFC 4035 adoucit donc la vieille règle (RFC 1034) selon laquelle on ne pouvait pas mettre des données avec un CNAME :

openid.sources.org.     86400   IN CNAME munzer.bortzmeyer.org.
                        86400   RRSIG   CNAME 3 3 86400 20080802035206 (
                                        20080601035206 55957 sources.org.
                                        CFhUR1j+1b684LERarhf6bmIbWHvnox6/cZT
                                        txCiMpOS5rRHBcQQHYQ= )
                        43200   NSEC    sub.sources.org. CNAME RRSIG NSEC

De même, la section 2.6 modère l'ancienne règle qui disait que, dans la zone parente, seuls des NS pouvaient être présents pour une zone fille (désormais, les DS et les NSEC sont également possibles).

La section 3 s'attaque aux serveurs de noms qui veulent distribuer des données authentifiées. Ces serveurs se voient d'abors imposer de gérer l'extension EDNS0 (RFC 2671), notamment en raison de la plus grande taille de réponse qu'elle permet (les enregistrements DNSSEC sont typiquement assez grands). Mais c'est aussi parce que EDNS0 permet aux résolveurs DNS d'indiquer qu'ils acceptent DNSSEC, selon le mécanisme du DO bit, décrit dans le RFC 3225. Pour BIND, utilisé en résolveur, on met ce bit avec l'option dnssec-validation yes; dans le fichier de configuration. Pour dig, si je donne l'option +dnssec, dig va mettre ce DO bit (bit DNSSEC OK) dans la requête, comme on le voit ici avec wireshark et son option Export (tcpdump ne permet apparemment pas de l'afficher) :


    Additional records
        <Root>: type OPT
            Name: <Root>
            Type: OPT (EDNS0 option)
            UDP payload size: 4096
            Higher bits in extended RCODE: 0x0
            EDNS0 version: 0
            Z: 0x8000
                Bit 0 (DO bit): 1 (Accepts DNSSEC security RRs)
                Bits 1-15: 0x0 (reserved)
            Data length: 0

Outre ce bit dans les requêtes, DNSSEC prévoit deux bits dans les réponses, les CD (Checking Disabled) et AD (Authentic Data).

La section 3.1 traite d'un serveur faisant autorité pour une zone. Pour que BIND gère le DNSSEC dans ce cas, il faut mettre l'option dnssec-enable yes; dans son fichier de configuration. Un tel serveur qui reçoit une requête avec le bit DO doit inclure les enregistrements DNSSEC comme les RRSIG, et fournir les NSEC si le nom n'existe pas (ou s'il existe mais sans enregistrement du type demandé). Voici un exemple avec dig et BIND :


% dig +dnssec MX sources.org
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
# La réponse a été validée, "ad" est présent
...
;; ANSWER SECTION:
sources.org.            86379   IN      MX      10 uucp.bortzmeyer.org.
sources.org.            86379   IN      RRSIG   MX 3 2 86400 20080802035206 20080601035206 55957 sources.org. CEYv0Tds6c7OSD7ZxEPmY0hQgs4ZMM5QE/8Ecmgm8Re7srtPhPEGVyg=

# Et, si le nom n'existe pas :
% dig +dnssec MX nexistepas.sources.org
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 14178
# Le nom n'existe pas, NXDOMAIN
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1
# Réponse validée grâce aux NSEC
...
;; AUTHORITY SECTION:
...
ludwigvii.sources.org.  10800   IN      NSEC    openid.sources.org. AAAA RRSIG NSEC
# Le NSEC dit qu'il n'existe rien entre ludwigvii.sources.org et openid.sources.org

L'inclusion des RRSIG (section 3.1.1) peut poser des problèmes de taille, car ils sont nettement plus gros que les enregistrements habituels. Le RFC détaille donc dans quels cas les envoyer. L'envoi des NSEC obét à des règles encore plus complexes, détaillées dans la section 3.1.3. Par exemple, s'il y a une réponse, mais qu'elle a été générée par un joker (le caractère * dans le fichier de zone), il faut envoyer les NSEC.

Après les serveurs faisant autorité de la section précédente, la section 3.2 parle des serveurs récursifs. Lorsque leur client indique son désir de faire du DNSSEC, via le bit DO, le serveur récursif doit leur envoyer les enregistrements DNSSEC et procéder à la validation, puis en indiquer le résultat via le bit AD (« ces données sont authentiques, je les ai vérifiées »). Pour BIND, c'est l'option dnssec-validation yes; qui met en route DNSSEC pour un serveur récursif.

Il y a tout un débat sur le meilleur endroit où effectuer la validation DNSSEC. Dans les applications pour qu'elles aient le plus d'informations possibles et puissent ajuster ainsi leurs messages à l'utilisateur ? Dans un résolveur situé sur la machine de l'utilisateur, la seule à laquelle il puisse vraiment faire confiance, puisque les autres machines et le réseau peuvent être sous le contrôle des méchants ? (Mais l'utilisateur de base ne va certainement pas installer et gérer BIND et il n'existe pas de serveur récursif et validateur « clés en main ».) Dans les résolveurs du FAI, qui sont déjà utilisés et configurés et qui sont gérés par des professionnels ? (Mais le FAI est parfois le premier à mentir, par exemple en dissimulant les réponses NXDOMAIN - ce domaine n'existe pas - derrière des fausses réponses menant à un serveur publicitaire qu'il contrôle.)

Ce débat n'aura pas de réponse consensuelle de si tôt (voir par exemple la section 4.9.3 du RFC). En attendant, notre RFC permet tous les modes de fonctionnement. Par exemple, si le résolveur ne veut pas que les serveurs auxquels il parle fassent de la validation, il peut leur demander avec le bit CD (section 3.2.2). S'il veut signaler à son client qu'il a validé (libre au client de le croire ou pas), il a le bit AD (section 3.2.3) pour cela.

La liste des tâches à accomplir par un résolveur continue en section 4, qui couvre tous les résolveurs, pas seulement les serveurs de noms récursifs de la section précédente. Eux aussi doivent gérer EDNS0 (section 4.1).

Si un résolveur valide les réponses avec DNSSEC, la section 4.3 donne les résultats auquel il peut parvenir :

  • Sûres (Secure) : les réponses DNS ont été vérifiées avec DNSSEC et sont correctes. Le résolveur peut alors positionner le bit AD, comme précisé dans la section 4.9.3.
  • Non sûres (Insecure) : en l'absence de clé cryptographique connue (voir le paragraphe suivant), les réponses DNS n'ont pas pu être vérifiées.
  • Invalides (Bogus) : le résolveur avait une clé mais les signatures sont fausses. Cela peut être bien sûr parce qu'un attaquant a modifié les données mais c'est souvent aussi en raison d'une erreur des gérants de la zone signée, voire du résolveur ; signatures expirées (un mois par défaut, dans BIND), décalage de l'horloge (DNSSEC implique une synchronisation des horloges), modification maladroite d'un fichier, etc. Ce genre de problèmes est très fréquent en cryptographie pratique et sera certainement une source d'amusement sans fin pour les utilisateurs de DNSSEC. Si la réponse est invalide, un serveur récursif doit - section 5.5 - retourner le code SERVFAIL (Server failure).
  • Incertaines (Indeterminate) : quelque chose a empêché le résolveur de se faire une opinion ferme.

Mais, justement, comment vérifier une signature ? Faut-il mettre dans le résolveur la clé de toutes les zones DNS du monde ? Évidemment pas. La section 4.4 parle des trust anchors (« points de départ de la confiance »), ces clés (au moins une) qui sont mises en dur dans la configuration du résolveur. À partir d'une telle clé, on peut vérifier une zone, et toutes ces sous-zones signées, en suivant les enregistrements DS, où on trouvera les clés des sous-zones. Idéalement, si la racine du DNS était signée, un seul trust anchor suffirait, la clé de la racine.

En pratique, la racine n'est pas actuellement signée. Il faut donc gérer à la main un ensemble de trust anchors (voici par exemple le fichier que j'utilise avec BIND, qui est à jour le 2008-06-04). On retrouve ces clés sur des sites tels que https://www.ripe.net/projects/disi/keys/ ou http://www.iis.se/domains/sednssec/publickey. La meilleure façon de gérer ces trust anchors est décrite dans la section 5, qui décrit par exemple les vérifications de cohérence que devrait faire un résolveur (tester que la trust anchor se retrouve bien dans la zone sous la forme d'un enregistrement DNSKEY). La section 5.1 parle notamment des « îlots de confiance » (islands of security), qui sont les zones signées sans que leur zone parente le soit (la très grande majorité, à l'heure actuelle). Par exemple, aujourd'hui, la zone .org n'est pas signée donc sources.org, qui l'est, est un « îlot de sécurité » dont les clés sont :

sources.org. IN DNSKEY 256 3 3 CKoOFAptkq5oqs8hlDf1gYDDpRPrjySc+wjBxLBbQtkXOrAUoBOrUa6I Yx83fYsA/i3BbhOXjS3K5/JlIupCszv2xTtrgIb0uivatvtO1WSySjOw R4dhfgPXdYbTAcYLYZRSiOFXxzXjnczRgqJu6tu50U7m7RK5wiIBTE6Q StNEanhez3srKtJK07iYutga/INvPxE82zVdGeBmIJpLqQ7gnCR3VaMh FtX+jO0/QHY/07vtZxNJhMucQt/oCG8rGQYVl1g8diZUtfd4iIgf2ill fBppxqc5EW3lLH1yVmu4JcHLaC4E7WiipupGd9N4APi5PzR3tuER8iua JYDHaZIwBmOm9weedHM9fUhOWYjmbEejvC8DvX6epDHVpAxgzysTapLa VBAci4a2/A/VVnrO2snUTdRzx8B8p5gnAgwl0ojXrgQRcPb0eDaFUdQx b9qLM75oM6miFeg1qsoqWNW/P1YvX/Kd2IDRcpskFE/ReYMpna40Ywj9 941/dRoDm6AMRpejsXYTlcpQRuRW54qpJuaY
sources.org. IN DNSKEY 256 3 5 AwEAAduXW4l/heiryuKxgipsGR2mIDnZxotS1Cf6+hzYROeGqPUnO2SI aQVh8s89u2hUT6I8T0C0UGVAJ2lmgTV6jEXwNyAm9wYzkZg6WnP5Nt3W eitsSBPQljAQvWsxNpp99QQrtycE4RDCtOiQS1igFPaEFPSawuvDEW8X oM2adQFa7RBXue8Xk5uxgbHorLLb3UTi7Ai1E7/J786XhlNGGJmpQJaB +qbyWG6Y81Uvnvj+CkU/hl7gRq2PE4TD2cJOZ85kia3fVUqOY6rOWK0X gylkQCV8Pjsd0LwVUfQ73/yDEpmw3ZBZDZUahWYnya2jFaidFJqfACoK ZXKMFcqkFt0=

La section 5.4 est consacrée aux NSEC, qui nécessitent des règles particulières pour leur validation.

Le reste du RFC est consacré à des exemples détaillés de zones signées, et de requêtes et réponses DNSSEC, avec leurs explications.

Si on veut tester un résolveur DNSSEC, il existe une zone prévue pour cela, test.dnssec-tools.org. Elle contient à peu près toutes les erreurs possibles. Par exemple, futuredate-A.newzsk-ns.test.dnssec-tools.org a une date de signature située dans le futur :


% dig A futuredate-A.newzsk-ns.test.dnssec-tools.org

; <<>> DiG 9.4.2 <<>> A futuredate-A.newzsk-ns.test.dnssec-tools.org
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 10278

Et, sur le serveur résolveur, le journal contiendra :

28-May-2008 14:07:59.910 dnssec: info: validating @0xa9c450: futuredate-A.newzsk-ns.test.dnssec-tools.org A: no valid signature found

Voici quelques extraits des fichiers de configuration de BIND, pour faire du DNSSEC (on peut trouver des instructions plus détaillées dans le DNSSEC HOWTO, a tutorial in disguise ou dans DNSSEC Resolver Test) :

options {

        dnssec-enable yes; // Accepte les requêtes avec le bit DO et
        // renvoie les enregistrements DNSSEC

        dnssec-validation yes; // Valide les
	// enregistrements DNSSEC reçus (le bit DO est mis
	// systématiquement par les BIND récents)
        
};

Pour le débogage, il peut être prudent de mettre le résultats des traitements DNSSEC dans un fichier séparé :


 logging {
          channel dnssec_log {             // a DNSSEC log channel
                  file "/var/tmp/bindlog/dnssec.log" size 20m;
                  print-time yes;        // timestamp the entries
                  print-category yes;    // add category name to entries
                  print-severity yes;    // add severity level to entries
                  severity debug 7;      // print debug message <=7
                          // Cela va noter *beaucoup* de messages
                          // On peut aussi mettre "severity info;" qui
			  // est nettement moins bavard.
          };

    category dnssec  { dnssec_log; };
};

Une fois que c'est fait, on peut tester le résultat avec des noms correctement signés comme sigok.verteiltesysteme.net ou délibérement mal signés comme sigfail.verteiltesysteme.net.

Pour un serveur faisant autorité, il faut générer des clés par exemple :

% dnssec-keygen -a RSASHA1 -b 2048 -n ZONE sources.org

On peut aussi générer plusieurs clés de types différents et les inclure dans la zone, par exemple, pour une clé DSA, avec dnssec-keygen -a DSA -b 1024 -n ZONE sources.org. Notons que cette commande dépend du générateur aléatoire de la machine et elle consomme beaucoup d'entropie, se bloquant dès qu'il n'y en a pas assez de disponible. Paradoxalement, il vaut donc mieux l'exécuter sur une machine chargée.

Il faut ensuite signer la zone et penser à la resigner après chaque modification (ou bien avant son expiration, selon l'évenement qui a lieu en premier). Pour simplifer le processus, on peut utiliser make avec un Makefile de ce genre :

reload: sources.org.signed foobar.example.signed
        rndc reload
        # Ou nsdc rebuild && nsdc reload pour NSD

%.signed: %
        @echo Signing requires a lot of entropy in /dev/random, do not hesitate to load the machine...
        # 5356800 seconds = two months of validity
        dnssec-signzone -e +5356800 $^

Le serveur devra alors avoir dans son fichier de configuration (named.conf pour BIND, nsd.zones pour NSD), le fichier sources.org.signed (et non pas le fichier sources.org qu'on édite et qui ne contient pas les signatures).


Téléchargez le RFC 4035


L'article seul

Fiche de lecture : Petit bréviaire des idées reçus en économie

Auteur(s) du livre : Les Éconoclastes
Éditeur : La Découverte
2-7071-4450-9
Publié en 2004
Première rédaction de cet article le 5 juin 2008


Un excellent petit livre d'économie pour tous ceux qui entendent tous les jours que « à cause de la démographie, il va falloir passer aux retraites par capitalisation » ou que « les entreprises privées sont plus efficaces que les services publics » ou encore que « il y a trop de charges sociales » et qui se demandent si c'est bien vrai, ou si c'est simplement répété suffisamment souvent pour que tout le monde y croie.

« Les Éconoclastes », pseudonyme collectif des auteurs, sont un groupe d'étudiants et de chercheurs en économie qui trouvent l'enseignement de cette discipline trop mathématique et trop éloigné des réalités. Ils abordent l'économie avec un prisme simple : « quels sont les faits connus ? ». Loin des théories purement idéologiques, ils montrent que ce ne sont pas forcément les pays ayant le plus d'impôts qui ont le plus de chômage, que le système de santé aux États-Unis est bien moins efficace qu'en France (mais beaucoup plus coûteux), que la différence entre retraite par capitalisation et retraite par répartition est bien moindre qu'on ne le dit (lors d'une retraite par capitalisation, on ne stocke pas d'or sous son matelas, on achète des produits financiers dont le rendement, comme pour les retraites par répartition, dépendra de l'état de l'économie)...

Un livre simple (quoique tous les termes ne sont pas forcément définis, il faut parfois aller faire un tour sur Wikipédia) et qui rectifie pas mal de préjugés.


L'article seul

Publication de la norme ISO 639-5

Première rédaction de cet article le 4 juin 2008
Dernière mise à jour le 25 février 2009


La norme ISO portant le numéro 639-5 vient d'être approuvée. Elle ajoute aux autres normes 639, qui portent sur la normalisation des listes de langues humaines, une liste des classifications de ces langues.

La nouvelle norme a le nom officiel de « Codes for the representation of names of languages - Part 5: Alpha-3 code for language families and groups », en français, « Codes pour la représentation des noms de langue - Partie 5: Code alpha-3 pour les familles de langues et groupes de langues ». Elle normalise des codes de trois lettres pour les familles et autres groupes de langues. Son agence de maintenance est la Bibliothèque du Congrés états-unien, comme pour ISO 639-1 et 639-2 (mais pas ISO 639-3) qui gère le site officiel.

À noter qu'ISO 639-5 est une liste de codes, pas une classification. On y trouve l'information qu'il existe une famille sdv (« Langues soudaniques orientales ») mais pas d'information sur ses membres comme le nubien.

Les classifications des langues (un sujet parfois chaudement débattu entre linguistes) restent extérieures à la norme. En revanche, la hiérarchie des familles est, elle, présente. Le fait que le manxois (code ISO 639-3 glv) est membre de la famille celtique (code ISO 639-5 cel n'est pas cité mais le fait que la famille celtique est elle même membre de l'ensemble indo-européen (code ISO 639-5 ine) est indiqué dans la liste. De même, on voit que les langues soudaniques orientales comprennent plusieurs familles, dont celle des langues nubiennes (dont fait partie le nubien cité plus haut).

La liste des codes est disponible gratuitement sur le site de l'agence de maintenance.


L'article seul

Exposé sur les politiques d'allocation d'adresses IP aux JTR

Première rédaction de cet article le 4 juin 2008


À l'occasion des JTR (Journées Techniques Réseaux) sur le thème d'IPv6, j'ai fait un exposé sur les politiques d'allocations de ressources virtuelles, notamment des adresses IP. Voici les transparents de cet exposé.


L'article seul

RFC 5194: Framework for real-time text over IP using the Session Initiation Protocol (SIP)

Date de publication du RFC : Juin 2008
Auteur(s) du RFC : A. van Wijk, G. Gybels
Pour information
Réalisé dans le cadre du groupe de travail IETF sipping
Première rédaction de cet article le 4 juin 2008


De même que le sigle VoIP désigne le transport de la voix sur IP, ToIP veut dire « Texte sur IP » et désigne le transport de texte au dessus d'IP, une technique proche de la messagerie instantanée mais néanmoins distincte. Ce RFC définit un cadre pour la mise en œuvre de ToIP sur le protocole SIP.

SIP, normalisé dans le RFC 3261, est un des grands succès de l'Internet. C'est le seul protocole ouvert permettant des services tel que la téléphonie sur IP. D'où l'idée de l'utiliser pour le ToIP. Mais qu'est-ce que le ToIP ?

La section 1 du RFC répond à cette question : au contraire de la messagerie instantanée, qui est semi-interactive (le texte n'est envoyé qu'après une action explicite de l'utilisateur), le texte-sur-IP est commplètement « temps réel », il est transmis au fur et à mesure qu'il est tapé. Il est largement utilisé par les sourds ou les personnes atteintes d'un handicap de la parole (le RFC 3351 détaille les demandes spécifiques de ces utilisateurs). Mais des utilisateurs non-handicapés apprécient également la réactivité de ce medium. Il est également utile dans certains environnements, par exemple une usine bruyante.

Étant proche de la téléphonie, il est donc logique de vouloir le réaliser avec les protocoles de signalisation SIP (RFC 3261) et de transport de données RTP (RFC 3550). RTP a déjà une norme pour le transport du texte, le RFC 4103.

Le cahier des charges proprement dit débute à la section 5 du RFC. Le ToIP doit être l'équivalent du téléphone et doit donc fournir un transport et une présentation « en temps réel », une transmission bidirectionnelle, et doit pouvoir être utilisé en même temps que d'autres médias tels que la vidéo (la norme ITU F.703 pose également ces exigences). Parmi les nombreux détails qui émaillent la section 5, on peut noter :

  • Section 5.2.2, la transmission des caractères doit être suffisamment rapide pour fonctionner avec un utilisateur qui tape vite mais également des programmes qui généreraient le texte (le RFC dit « trente caractères par seconde »).
  • Section 5.2.4, la couche présentation n'est pas oubliée lorsque le RFC demande que la signalisation aux utilisateurs humains puissent utiliser des moyens accessibles à tous (les signaux sonores ne conviennent pas aux malentendants).
  • Section 5.2.5.3, on retrouve la messagerie instantanée, avec la requête que des passerelles soient possibles entre ce service et le ToIP (une implémentation possible est décrite en 6.2.5.3).

La section 6 détaille comment le service pourrait être implémenté, avec les équipements et logiciels SIP et RTP existants. L'interconnexion avec la téléphonie classique n'est pas oubliée, puisque la section 6.2.5.1 détaille comment faire passer du texte « temps réel » sur cette téléphonie traditionnelle, selon la norme (ou plutôt la description de diverses normes) ITU V.18.

Enfin, la section 7 couvre les cas divers, comme l'accès aux services d'urgence. J'ignore s'il est actuellement réaliste d'appeler les pompiers en texte seul...


Téléchargez le RFC 5194


L'article seul

Quelles sont les arrières-pensées derrière le slogan de l'Internet mobile ?

Première rédaction de cet article le 28 mai 2008


« Le développement de l'Internet se fera sur des téléphones mobiles » est une tarte à la crème du marketing actuel. C'est donc une très bonne chose que Joi Ito s'attache à chercher les arrières-pensées derrière ce slogan.

Que dit Joi Ito dans son article Is Mobile Internet Really Such a Good Thing? ? Tout simplement que les intentions des promoteurs de cet Internet mobile ne sont pas toujours très avouables. L'Internet se caractérise par des engins ouverts (les ordinateurs) dans un réseau ouvert. Cela permet le déploiement rapide d'innovations (comme l'avait été le Web à ses débuts) et cela permet aux utilisateurs le choix et surtout le contrôle sur ce qui tourne sur leurs machines. Au contraire, l'Internet mobile, aujourd'hui, consiste surtout à déployer des engins fermés et contrôlés (comme l'iPhone), où on ne peut pas choisir les applications qui tournent dessus, et à les déployer dans un réseau fermé (comme l'offre soi-disant Internet d'Orange/3GPP où seuls les ports 80 et 443, ceux d'HTTP, sont autorisés).

Sur le même sujet (le danger de ces boîtes fermées, pratiques à utiliser, mais sur lesquelles l'utilisateur n'a aucun contrôle), le livre de Jonathan Zittrain, The Future of the Internet and How to Stop It est la référence. En français, je recommande l'excellent article de Benjamin Sonntag « Pourquoi l'Internet mobile n'est PAS Internet ? ».


L'article seul

Utiliser le client classique de BitTorrent avec screen

Première rédaction de cet article le 28 mai 2008


Les téléchargements de fichiers avec le protocole BitTorrent peuvent prendre des jours, voires des semaines. Laisser un logiciel ouvert pendant ce temps n'est pas possible pour une machine de maison ordinaire, qui est souvent éteinte. Même sur un serveur allumé en permanence, cela bloque un terminal par téléchargement, si on utilise le client traditionnel, btdownloadcurses. Il existe plusieurs solutions à ce problème, la mienne combine un des logiciels du client traditionnel, btlaunchmanycurses et le programme screen.

Une des solutions est évidemment d'utiliser un autre programme, puisqu'il existe beaucoup de clients BitTorrent, tous plus ou moins compatibles (en dépit de l'absence d'une norme écrite du protocole). Je n'ai jamais eu de succès avec Azureus (core dumped) qui, contrairement à ce que prétend le discours marketing, comme presque tous les programmes Java, ne fonctionne pas avec n'importe quel environnement Java mais uniquement avec celui de Sun (qui était non-libre jusqu'à une époque très récente). De même, bien que mlDonkey aie, en théorie, un support BitTorrent, les téléchargements ne démarrent jamais, dans mon cas (et ce logiciel semble en voie d'abandon, avec une communauté qui est devenue inactive). Quant à TorrentFlux, il nécessite un serveur Web, PHP, etc.

Retour au client BitTorrent original, écrit en Python. Il comprend de nombreux programmes différents dont un qui fait presque tout ce dont j'ai besoin : btlaunchmanycurses prend en argument un répertoire, ouvre tous les fichiers « torrent » de ce répertoire et lance simultanément les opérations. Ajouter un nouveau « torrent » à la liste est aussi simple qu'un wget dans ce répertoire (par exemple wget ftp://ftp.netbsd.org/pub/NetBSD/iso/4.0/i386cd-4.0.iso.torrent pour récupérer le CD de NetBSD).

Pour libérer le terminal et pour que btlaunchmanycurses s'exécute tranquillement en arrière plan, la meilleure solution est d'utiliser le programme screen qui permet de lancer le programme en arrière-plan, le reprendre à volonté (y compris depuis une autre machine), le détacher à nouveau, etc. Le script shell attaché fait exactement cela :


#!/bin/sh

NAME=BitTorrent
DIR=${HOME}/Downloads
BT=btlaunchmanycurses
BT_OPTIONS="--ipv6_enabled 1 --max_uploads 3 --max_upload_rate 8 --max_download_rate 85"

cd ${DIR}

# Starts "screen" detached, with a command to run
screen  -S ${NAME} -d -m ${BT} ${BT_OPTIONS} .

# The limit of this approach is that screen disappears when ${BT} is
# over. If ${BT} scrashes, you lose the error messages :-)

# The alternative would be to launch screen without a command (just -d
# -m) and then to issue a "screen -X -r ${NAME} exec ${BT} ...". But
# this is ignored, probably because a bug in screen (see
# <https://savannah.gnu.org/bugs/index.php?18882>

# Another solution (thanks to Thomas Montfort to bring it to me) is to
# use the 'zombie kr' command in ~/.screenrc.

Il ne reste plus qu'à faire en sorte que ce script, start-bittorrent, soit lancé automatiquement au démarrage de la machine. Le client BitTorrent sait reprendre les transferts interrompus. Encore faut-il le mettre en route. Pour éviter d'utiliser le compte root, on peut exploiter un service des crons modernes comme Vixie Cron qui permet de lancer une commande au moment de certains événements comme le démarrage. Ainsi, j'ai dans ma crontab :

@reboot  bin/start-bittorrent

Je dois des remerciements à Erwan Arzur pour m'avoir indiqué btlaunchmanycurses et à Erwan David pour son aide sur cron.


L'article seul

RFC 5233: Sieve Email Filtering: Subaddress Extension

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : K. Murchison (Carnegie Mellon University)
Chemin des normes
Première rédaction de cet article le 27 mai 2008


Beaucoup d'utilisateurs du courrier électronique utilisent des sous-adresses pour présenter plusieurs identités à l'extérieur. La sous-adresse est typiquement séparée du nom de la boîte aux lettres par un + (mais chacun a sa convention, il n'y a rien de standard, cf. section 1 du RFC). Ainsi, l'adresse que je publie sur ce blog, stephane+blog@bortzmeyer.org contient une sous-adresse, blog. Cette nouvelle extension du langage de filtrage de courrier Sieve permet de prendre des décisions en fonction de la sous-adresse.

Le principal intérêt pratique des sous-adresses est en effet de pouvoir filtrer automatiquement le courrier en fonction de l'identité (à noter que, par méchanceté ou par simple incompétence, un certain nombre de sites Web refusent les sous-adresses). Si j'écris sur toutes les listes du W3C avec une adresse stephane+w3c@bortzmeyer.org, je peux filtrer les réponses facilement, en procmail avec une règle comme :

:0:
* !^TO_(stephane\+w3c)@
Mail/sdo/w3c

Et avec Sieve ? Ce langage, normalisé dans le RFC 5228, permet d'exprimer des règles de filtrage de manière standard. Notre RFC 5233 l'étend avec l'extension subaddress qui permettra, dès qu'elle sera mise en œuvre par les logiciels, d'utiliser :

require ["envelope", "subaddress", "fileinto"];
      
if envelope :detail "to" "w3c" {
          fileinto "inbox.sdo.w3c";
}

Le :detail a été introduit par l'extension subaddress. Il renvoie la sous-adresse (:localpart renvoie la partie à gauche du @ et :user renvoie le nom de la boîte, sans la sous-adresse).

Cette extension subaddress avait originellement été spécifiée dans le RFC 3598, que ce nouveau RFC modifie sur des points de détail (l'annexe B détaille ce qui a changé).


Téléchargez le RFC 5233


L'article seul

Extlang ou pas extlang ?

Première rédaction de cet article le 26 mai 2008


Le groupe de travail LTRU (Language Tag Registry Update) de l'IETF est très en retard dans son projet de normalisation des futures étiquettes de langue, ces courtes chaînes de caractères qui permettent d'indiquer la langue d'un document ou de préciser la langue qu'on souhaite utiliser sur Internet. Une des raisons de ce retard est le débat sans fin sur les « extlangs », ces mécanismes permettant de représenter le concept de « macrolangue » introduit par la norme ISO 639-3. En gros, l'égyptien doit-il se noter ar-arz ou bien arz ? Et le cantonais doit-il être zh-yue ou simplement yue ?

Dans la norme actuelle, le RFC 4646, les étiquettes de langue sont formées de plusieurs sous-étiquettes, chacune identifiant la langue, l'écriture ou le pays. Les sous-étiquettes qui identifient la langue sont tirées de ISO 639-1 ou ISO 639-2, normes qui placent toutes les langues sur un pied d'égalité.

Mais le monde des langues humaines est complexe. La définition traditionnelle d'une langue est le critère de compréhension mutuelle. Si différents que puissent être les accents, le vocabulaire et l'orthographe, l'anglais d'Australie peut être compris par un irlandais (parfois avec effort). C'est donc la même langue, dont la sous-étiquette est en. De même, si proches que soient le français et le catalan, par leur origine commune, deux locuteurs de ces deux langues ne peuvent pas se comprendre. Il s'agit donc bien de deux langues distinctes, dont les sous-étiquettes sont fr et ca.

Naturellement, il existe une zone grise : le danois est-il si différent du norvégien ? L'arabe marocain du tunisien ? Le cas est d'autant plus difficile que certaines langues sont différentes à l'oral mais moins à l'écrit (c'est justement le cas de l'arabe). D'une certaine façon, il n'existe qu'une langue arabe. D'une autre, il en existe plusieurs (qui ne recoupent pas forcément exactement les frontières nationales). Parfois, l'histoire ou la politique contribuent à brouiller la perception linguistique correcte, comme dans le cas du mandarin, souvent appelé chinois par abus de langage, parce que c'est la langue de l'État chinois.

Pour tenter de modéliser ce monde très complexe et qui n'a pas été conçu rationnellement, SIL, l'organisation qui a été la principale responsable de la norme ISO 639-3 a créé un nouveau concept, celui de macrolangue. Une macrolangue est une langue unique, selon certains critères, et un groupe de langues selon d'autres. Les deux plus célèbres sont le chinois (avec la sous-étiquette zh) et l'arabe (ar). Le registre d'ISO 639-3 indique donc pour chaque langue si elle est couverte par une macrolangue. Le cantonais est ainsi « couvert » par le chinois. Notons tout de suite que les langues couvertes (parfois appelées par dérision « microlangues ») ne sont pas des dialectes, ce sont bien des langues séparées, typiquement sans mutuelle compréhensibilité.

Comment représenter les macrolangues dans le successeur du RFC 4646 ? La première idée, dont les prémisses figurent dans le RFC 4646, était d'utiliser un concept nouveau, l'Extended Language Subtag, l'extlang. Dans ce système, tel que prévu à l'origine, la première sous-étiquette identifiait la macrolangue (ou la langue tout court pour les cas - les plus fréquents - où il n'y avait pas de macrolangue) et un ou plusieurs extlangs la suivaient. Ainsi, l'arabe tunisien était ar-aeb et le zapotèque de la Sierra de Juárez était zap-zaa (zap étant la sous-étiquette de la macrolangue zapotèque).

Pour comprendre l'intérêt de ce système, il faut voir que les logiciels qui manipulent les étiquettes de langue, lorsqu'ils ne trouvent pas une langue satisfaisante, cherchent en général en supprimant les sous-étiquettes en partant de la droite, où se trouvent les sous-étiquettes les moins significatives (ce mécanisme est décrit dans le RFC 4647). Ainsi, si on demande à un système de recherche un document en az-Arab-IR (l'azéri écrit dans l'écriture arabe tel qu'il est utilisé en Iran), et qu'aucun document ne correspond à cette étiquette, le logiciel peut chercher s'il a az-Arab (en abandonnant les spécificités iraniennes) ou même az (de l'azéri, quelles que soient ses autres caractéristiques). Les extlangs collaient bien à ce modèle. Une demande de sq-als (le tosque) serait ainsi tronquée en sq (la macrolangue pour l'albanais), ce qui ne serait pas une mauvaise solution de repli.

Mais, à l'examen plus attentif des extlangs, plusieurs problèmes sont survenus. D'abord, la constation que le repli en tronquant par la droite ne donnait pas toujours des résultats corrects. Rien ne garantit que les langues couvertes par une même macrolangue sont mutuellement compréhensibles, bien au contraire. Donc, le repli « aveugle » obtenu en supprimant les sous-étiquettes en partant de la droite ne va pas être satisfaisant. Ensuite, les extlangs compliquent le modèle puisqu'ils représentent un nouveau cas à spécifier, à implémenter et à expliquer. Enfin, les extlangs peuvent porter un message erroné, celui comme quoi une langue particulière du groupe serait la langue principale. Ce message peut être souhaité (la plupart des arabophones sont très attachés à la référence à une langue arabe unique), ou pas mais il est toujours délicat, puisqu'il place les langues dans une hiérarchie. De nombreuses discussions, parfois houleuses, avaient animé le groupe de travail autour de ces problèmes.

C'est ainsi que LTRU avait, en décembre 2007, renoncé à utiliser les extlangs et changé les Internet-Drafts pour mettre en œuvre cette décision. Dans cette nouvelle version, le registre des langues gardait l'information comme quoi une langue était couverte par une macrolangue mais les étiquettes de langue étaient uniquement formées avec la langue elle-même. Le tosque était donc noté als, le zapotèque de la Sierra de Juárez zaa et le mandarin cmn.

Mais, à l'IETF, les choses ne se passent pas toujours aussi simplement. Cinq mois après ce changement, les problèmes de la nouvelle version apparaissent, souvent soulevés par des gens qui n'avaient guère contribué au travail concret, et rien dit à l'époque de l'abandon des extlangs. Dans les cas où le groupe autour d'une macrolangue comporte une langue dominante (ce qui est le cas du chinois avec le poids du mandarin, ou celui de l'arabe avec la référence qu'est l'arabe standard, mais pas du zapotèque), de nombreux documents ont déjà été étiquetés avec l'étiquette qui est devenue celle de la macrolangue. Par exemple, les ressources en mandarin ne devraient plus être notées zh comme avant mais cmn. Que faire avec les innombrables documents en mandarin qui avaient été étiquetés zh en suivant le RFC 4646 ?

Idéalement, le seul registre des langues suffirait à trouver des bonnes solutions. Mais, en fait, les décisions à prendre par le logiciel dépendent souvent de critères non linguistiques. Par exemple, si un utilisateur a configuré comme langue préférée le breton, il n'est pas déraisonnable de lui servir du texte en français. Non pas que les deux langues soient proches (la première est une langue celte et le second une langue romane) mais parce que, en pratique, presque tous les gens qui comprennent le breton comprennent également le français. Mais on ne peut pas mettre cette information (de taille importante et qui change souvent) dans le registre ! Il faudrait donc se résigner, ce qui ne semble pas facile, à ne pas avoir dans le registre d'information permettant un repli « intelligent ».

Après, là encore, un débat très chaud, le groupe LTRU a finalement fait marche arrière le 26 mai 2008, revenant aux extlangs. Cela nécessite de revenir à la précédente version des Internet-Drafts, de revoir documents et implémentations. Et sans garantie que cela ne recommence pas dans quelques mois...

Ma vue personnelle est que le système est instable : on peut bâtir un bon argumentaire pour les deux solutions (contre les extlangs, voir le texte de Mark Davis), aucune n'est parfaite, car les langues humaines n'ont pas été conçues pour faciliter la tâche de l'IETF. Il aurait fallu adopter une solution et s'y tenir mais les mécanismes de décision à l'IETF ne rendent pas cela facile.


L'article seul

RFC 5191: Protocol for Carrying Authentication for Network Access (PANA)

Date de publication du RFC : Mai 2008
Auteur(s) du RFC : D. Forsberg (Nokia), Y. Ohba (Toshiba), B. Patil (Nokia), H. Tschofenig (Siemens), A. Yegin (Samsung)
Chemin des normes
Première rédaction de cet article le 26 mai 2008


PANA est un protocole conçu pour transporter un protocole d'authentification lors d'accès à un réseau, EAP. Le RFC 5193 donne une vision de haut niveau de PANA, notre RFC 5191, quant à lui, définit en détail le protocole. Comme l'indiquent les appartenances des auteurs, PANA et EAP sont surtout utilisés dans le monde de la téléphonie mobile.

PANA est assez simple : les messages EAP (RFC 3748) sont encapsulés dans les messages PANA, qui sont transportés sur UDP. PANA ne fait pas d'authentification lui-même, il transporte juste des paquets. Les méthodes d'authenfication sont donc complètement extérieures à PANA.

La section 2 décrit la terminologie de PANA, pour laquelle il vaut mieux se référer au RFC 5193. La machine qui veut accéder au réseau (par exemple un téléphone portable) est le client PANA, le PaC. La machine avec laquelle elle parle est le serveur PANA, le PAA. Pour prendre sa décision, ce serveur va souvent parler à un serveur AAA, par exemple avec la protocole Radius (RFC 2865). Une fois l'authentification terminée, le trafic réel passera par un routeur ou autre machine d'accès, l'EP. Souvent, EP et PAA seront dans la même boîte et communiqueront via une API pana

La section 3 résume le protocole : les dialogues PANA sont composés de requêtes et de réponses, chaque message portant ou ou plusieurs AVP. Le transport utilisé est UDP, choisi pour sa simplicité de mise en œuvre.

Puis la section 4 détaille le protocole. Le PaC ou le PAA peuvent être à l'origine du dialogue. Lorsque le PaC veut s'authentifier (section 4.1), il envoie une requête PANA-Client-Initiation au PAA. Notez que le mécanisme de découverte du PANA n'est pas spécifié ici (une solution possible est décrite dans le RFC 5192). Le PAA répond alors avec une PANA-Auth-Request, qui porte la charge EAP. Un échange de messages PANA-Auth-Answer et PANA-Auth-Request suivra alors, jusqu'à ce qu'EAP aie terminé. (La liste complète des messages possibles figure dans la section 7.) Si l'authentification est un succès, le dernier message peut également contenir des consignes pour le PaC comme de reconfigurer son adresse IP. Les autres sous-sections de la section traitent de la ré-authentification en cours de session ou bien de la terminaison de la session.

La section 5 précise les règles de traitement des messages, notamment en cas de perte de paquets (UDP ne promettant pas de délivrer tous les paquets). Chaque participant au dialogue PANA doit maintenir une séquence numérotée des paquets, pour pouvoir détecter et corriger une perte. La même section explique aussi comment s'assurer de l'intégrité des messages, via un hachage cryptographique.

Le format exact des messages est normalisé dans les sections 6 et 8, qui présentent les AVP, qui sont très proches de ceux du RFC 3588.

Vu le but de PANA, transporter un protocole d'authentification, il n'est pas étonnant que la section sur la sécurité soit détaillée. Cette section 11 du RFC explique donc les mécanismes qui, de concert avec ceux d'EAP, vont permettre d'utiliser PANA même sur un réseau peu sûr.


Téléchargez le RFC 5191


L'article seul

Choix d'identificateurs pour les normes IETF

Première rédaction de cet article le 23 mai 2008


Toute SDO publie des normes qui ont besoin d'être référencées. Il faut pouvoir, de manière non ambiguë, dire « Ce compilateur Lisp est conforme à la norme ISO/IEC 13816:2007 ou bien « Ce routeur IP implémente le RFC 4970 ». L'IETF voit en ce moment une vive discussion sur l'achat d'un ISSN pour identifier la série des RFC.

Cette discussion a été lancée par Ray Pelletier, de l'IETF Trust ; sa proposition est d'acheter un numéro ISSN, pour identifier la série des RFC. La série complète, pas juste un RFC particulier, puisque le rôle d'un ISSN n'est pas de désigner un seul document. La question de la citation d'un RFC particulier reste donc ouverte (l'IETF a une norme pour cela, le RFC 2648, mais personne ne l'utilise).

Cet ISSN permettrait par exemple des références correctes aux RFC, notamment dans la littérature « académique ». L'ISSN peut s'exprimer tel quel (ISSN 0395-2037) ou bien via un URN, selon le RFC 8254 : urn:ISSN:0395-2037.

Le débat sur les identificateurs a toujours fait rage dans les communautés de bibliothécaires, de documentalistes et autres professionnels de la gestion de l'information. (Voir par exemple les articles d'Emmanuelle Bermès, de la BNF.) Le fil de discussion qui a suivi l'annonce de l'IETF Trust a donc, logiquement, cité les DOI (une très mauvaise idée), les ISBN et plusieurs autres familles d'identificateurs.

Comme l'a noté Steve Crocker, le but principal est sans doute simplement de calmer les trolls qui s'obstinent à prétendre que les normes IETF ne sont pas de vraies normes. En gros, l'ISSN pour les RFC serait l'équivalent du costard/cravate pour les humains...

Finalement, l'ISSN a été demandé et obtenu : 2070-1721.


L'article seul

Qui contrôle les serveurs racine du DNS ?

Première rédaction de cet article le 23 mai 2008


Un récent petit incident, sans conséquence pratique, la réutilisation de l'ancienne adresse IP d'un serveur racine du DNS, le serveur L.root-servers.net, a mis en évidence la question de la gestion des serveurs racine. Onze organisations gèrent un de ces treize serveurs. Qui les a désignées ? Qui les contrôle et les surveille ? Que se passe t-il s'il l'une d'elles ne rend plus un service correct ? Que se passe t-il si une organisation se porte volontaire pour remplacer l'une d'elles ?

Revenons d'abord sur ce minuscule incident. Le serveur racine L.root-servers.net, géré par l'ICANN, a changé d'adresse IP le 1 novembre 2007, passant de 198.32.64.12 à 199.7.83.42. Compte-tenu de la nature particulière des serveurs racine (toutes les résolutions DNS commencent par eux, jusqu'à ce que les caches soient peuplés), de tels changements sont difficiles à propager. Il faut mettre à jour d'innombrables fichiers de configuration un peu partout dans le monde (avec BIND, c'est typiquement dans le fichier root.hints ou db.root). Il n'est donc pas étonnant que, des mois plus tard, l'ancienne adresse reçoive encore des requêtes. (Plus bizarre est le fait qu'elle reçoive des requêtes autre que la requête initiale, dite de « priming », après laquelle le résolveur DNS, aurait dû se rendre compte de son erreur. Mais c'est une autre histoire.)

L'ancienne adresse de L venait de l'espace d'adresses allouées à ep.net. Et c'est là que commence le problème. ep.net a commencé à annoncer en BGP les adresses incluant l'ancienne adresse du serveur racine et, plus fort, un serveur DNS répondait bien à cette ancienne adresse. Ses réponses étaient apparemment correctes (identiques à celles des « vrais » serveurs racine) donc l'incident n'a eu aucune conséquence pratique. Mais pourquoi ep.net avait-il fait cela ? Avaient-ils le droit ?

Je passe sur les débats parfois assez puérils sur ce point. Bill Manning, le responsable d'ep.net, étant une personnalité controversée, il n'est pas étonnant que certaines accusations soient allées assez loin (voir par exemple le règlement de comptes de David Conrad et la réponse de CommunityDNS, qui travaillait avec Manning).

Mais la discussion a soulevé un point d'habitude pudiquement laissé dans l'ombre. Qui est responsable des serveurs racine ? Si un opérateur de serveur racine ne fait pas son travail comme attendu (Bill Manning opère un autre serveur racine, le B.root-servers.net), peut-on le virer ? À partir de quel niveau de non-service ? Et, sans citer de cas aussi dramatiques (après tout, les opérateurs actuels font plutôt bien leur travail), est-ce qu'une nouvelle organisation peut candidater et proposer de remplacer un des serveurs existants (certains, sans être clairement en panne, ne sont pas très performants) ?

La réponse à toutes ces questions est la même et elle représente un des secrets les mieux gardés de la gouvernance Internet : personne ne sait. Aucune règle, aucun contrat, n'encadre le travail des opérateurs de serveurs racine. (Une seule petite exception à cette absence de contrat, le Mutual Responsibilities Agreement entre l'ISC et l'ICANN.) Tout dépend uniquement de leur bonne volonté. Certes, elle n'a pas manqué jusqu'à présent, avec des félicitations particulières pour les opérateurs du F.root-servers.net, de loin les plus dynamiques et ceux qui se soucient le plus d'informer la communauté des utilisateurs. Mais cette bonne volonté se maintiendra t-elle dans le futur ? Est-ce acceptable qu'une ressource aussi critique pour l'Internet dépende juste de cela ?

Les onze organisations ont été désignées il y a très longtemps, parce que Jon Postel les connaissait et personne aujourd'hui n'ose remettre en cause cette désignation. Aucune organisation, et surtout pas l'ICANN, n'a de légitimité suffisante pour « virer » un serveur racine. La liste est donc, de facto, fermée et non modifiable.

Quelques autres articles sur ce sujet : plein de détails techniques sur le blog de Renesys (gâchés par un titre racoleur, voir aussi la suite et leur exposé à NANOG) et un bon résumé de Danny McPherson, qui plaide pour un contrôle accru par l'ICANN.


L'article seul

RFC 5203: Host Identity Protocol (HIP) Registration Extension

Date de publication du RFC : Avril 2008
Auteur(s) du RFC : J. Laganier (DoCoMo Euro-Labs), T. Koponen (HIIT), L. Eggert (Nokia)
Expérimental
Première rédaction de cet article le 22 mai 2008


Le protocole HIP, décrit dans le RFC 5201 est très bien adapté au cas où l'adresse IP (le localisateur) change après l'établissement d'une association. Mais cela laisse ouvert le grand problème de la connexion initiale. Comment trouver une machine HIP ? Par le mécanisme de rendez-vous du RFC 5204 ? C'est certainement une bonne solution mais, alors, comment les machines HIP sont-elles connues du serveur de rendez-vous ? C'est là que notre RFC rentre en jeu pour normaliser un mécanisme d'enregistrement auprès d'un service. (Il a depuis été remmplacé par le RFC 8003.)

Le mécanisme est très simple et le RFC court. On réutilise simplement les établissements d'associations de HIP, avec de nouveaux types de paramètres, notamment REG_INFO (pour l'hôte qui accepte d'être registrar, c'est-à-dire d'enregistrer) et REG_REQUEST (pour celui qui demande un enregistrement). Le mécanisme exact est détaillé dans la section 3 et les nouveaux paramètres dans la section 4.

HIP authentifiant les deux parties bien plus solidement que IP seul, le registrar peut alors décider s'il accepte l'enregistrement ou pas (sections 3.3 et 6).

Le rendez-vous, normalisé dans le RFC 5204 est donc une simple application de notre RFC mais d'autres pourront apparaître à l'avenir.


Téléchargez le RFC 5203


L'article seul

RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP

Date de publication du RFC : Septembre 2001
Auteur(s) du RFC : K. Ramakrishnan (TeraOptic Networks), S. Floyd (ACIRI), D. Black (EMC)
Chemin des normes
Première rédaction de cet article le 21 mai 2008


De tout temps, un des plus gros problèmes de l'Internet a été de gérer la congestion, le fait qu'il y a plus de paquets IP qui veulent passer par les tuyaux que de capacité pour les faire passer. La réponse classique d'IP à la congestion est de laisser tomber certains paquets, les protocoles de plus haut niveau étant alors censés ralentir en réponse à ces pertes. Notre RFC normalise une autre méthode : lorsque le routeur sent que la congestion est proche, il marque les paquets IP pour indiquer aux machines terminales qu'il faudrait ralentir. Une excellente page, par une des auteures du RFC, ECN (Explicit Congestion Notification) in TCP/IP décrit ce système, qui n'a malheureusement pratiquement pas connu de déploiement.

C'est le RFC 2481 qui avait proposé pour la première fois ce mécanisme (et notre RFC le remplace et passe du statut « expérimental » au statut « chemin des normes »). La méthode classique, laisser tomber des paquets, rappelée dans la section 1 du RFC, a toujours bien marché. Le réseau est traité comme une boîte noire, on y envoie des paquets et la seule signalisation reçue est le fait que certains paquets ne ressortent pas. Les protocoles de plus haut niveau, comme TCP (RFC 793) ou DCCP (RFC 4340) ralentissent alors leur débit. Mais cela fait perdre des données, juste pour envoyer une indication. D'où l'idée de prévenir avant que la congestion ne soit réellement installée, en modifiant deux bits de l'en-tête IP, pour indiquer que le routeur a du mal à suivre. Les machines terminales, si elles gèrent ECN, vont alors ralentir leur débit de manière plus efficace que si elles avaient attendu en vain un paquet (Active Queue Management, décrit dans le RFC 7567 et dans la section 4 de notre RFC 3168).

Avec la section 5, commence la description des changements effectués dans IP. Deux bits de l'en-têtes sont réservés pour ECN. Ils peuvent prendre les valeurs 01, 10 (ces deux valeurs, dites ECT, indiquant que l'expéditeur du paquet comprend ECN, l'intéressante section 20 explique pourquoi il y en a deux), 00 (pas d'ECN accepté) et 11 (dite CE, cette valeur indiquant la congestion). Ces deux bits se placent juste après le DSCP (l'ancien TOS) du RFC 2474. Si le routeur détecte que la congestion est proche, par exemple parce que ses files d'attente de sortie se remplissent, et que le paquet IP indique que l'expéditeur comprend ECN, alors le routeur peut, au lieu d'attendre la congestion, mettre un bit à 1 pour indiquer le problème au destinataire.

La section 6 du RFC décrit ensuite ce que le protocole de transport au dessus d'IP devrait faire avec les bits ECN (seul TCP est couvert dans ce RFC). 6.1 couvre TCP et modifie donc la section 3.1 du RFC 793. Deux nouveaux bits sont réservés dans l'en-tête TCP, permettant aux deux machines qui se parlent en TCP de se prévenir qu'elles comprennent ECN et, si nécessaire, d'indiquer le début de congestion, détecté en regardant les paquets IP modifiés par le routeur. Une fois ECN ainsi « négocié », les paquets IP porteront le bit ECN adapté, comme on le voit avec tcpdump :

12:04:58.525094 IP (tos 0x2,ECT(0), ttl 64, id 2069, offset 0, flags [DF], proto TCP (6), length 142) 192.134.4.97.50418 > 192.134.4.69.80: P 1:91(90) ack 1 win 46 <nop,nop,timestamp 3266115 18052032>
12:04:58.525242 IP (tos 0x0, ttl 64, id 61994, offset 0, flags [DF], proto TCP (6), length 52) 192.134.4.69.80 > 192.134.4.97.50418: ., cksum 0x1463 (correct), 1:1(0) ack 91 win 46 <nop,nop,timestamp 18052032 3266115>

ECT(0) désignant le motif 10 (« je comprends ECN »). Les paquets de pur acquittement TCP (le deuxième paquet affiché ci-dessus) ne portent pas de bits ECN.

Les sections 8 à 11 du RFC discutent de détails pratiques et d'évaluation d'ECN. Les section 18 et 19 sont consacrées au cas où une middlebox dans le réseau modifie maladroitement les bits ECN. Les sections 21 et 22 ne normalisent rien mais expliquent les choix qui ont été fait dans les en-têtes de paquets, en revenant sur les anciennes définitions de ces en-têtes.

L'Internet étant infecté de machines non gérées et non modifiables, comme certains routeurs bas de gamme (les CPE, par exemple), il est très difficile de déployer de nouveaux protocoles ou de nouveaux services. Ainsi, sept ans après sa normalisation formelle, ECN ne passe toujours pas avec certains sites, où les paquets marqués sont jetés. La section 6.1.1.1 du RFC discute ce problème (voir aussi http://www.icir.org/tbit/ecn-tbit.html).

C'est pour cela que beaucoup de systèmes d'exploitation viennent avec ECN coupé par défaut. Par exemple, sur Linux, on peut voir si ECN est accepté avec :

 % sysctl net.ipv4.tcp_ecn
net.ipv4.tcp_ecn = 0

et les développeurs discutent régulièrement de son activation par défaut. FreeBSD, lui, ne semble pas avoir de support ECN du tout ? Un guide complet de configuration pour les Cisco se trouve en http://www.cisco.com/en/US/docs/ios/12_2t/12_2t8/feature/guide/ftwrdecn.html. Pour MPLS, on peut consulter le RFC 5129. Autre lecture possible, une proposition d'activer ECN par défaut.

Depuis des années, des utilisateurs demandent un support de ECN dans echoping mais ça reste à développer. Il n'est pas évident que ECN doive être sous le contrôle des applications.


Téléchargez le RFC 3168


L'article seul

Il n'y a plus de classes d'adresses

Première rédaction de cet article le 20 mai 2008


On voit souvent des administrateurs réseaux parler de « classe B » ou de « classe C » en se référant à un groupe d'adresses IP. Ces termes sont dépassés et reflètent une réalité qui a disparu depuis longtemps. Ils ne devraient plus être employés.

Pour expliquer pourquoi, je dois faire un détour sur la façon dont fonctionne l'adressage IP, normalisé, pour IP version 4, dans le RFC 791. Les adresses IPv4 faisant 32 bits, ce protocole permet 2^32 soit plus de quatre milliards d'adresses. Pas question que les routeurs aient une route vers chacune de ces adresses. Leur mémoire n'y suffirait pas et, surtout, le rythme de changement serait trop élevé. On regroupe donc aujourd'hui les adresses contiguës en préfixes de longueur N où N est le nombre de bits qui servent à identifier le préfixe, les autres bits identifiant la machine. En IPv4 et IPv6, ce nombre de bits n'est pas fixé par le protocole, il est déterminé par l'administrateur système. On note un réseau par son préfixe, suivi d'une barre oblique et de la longueur du préfixe. Par exemple, le préfixe 192.0.2.128/25 a une longueur N de 25 bits, ces 25 bits valant 11000000 00000000 00000010 10000000, laissant 7 bits pour identifier une machine sur ce réseau. Si plusieurs routes sont possibles pour une destination donnée, le routeur prendra la plus spécifique (celle dont N est le plus grand).

A t-on toujours fait comme cela ? Non. Il y a de nombreuses années, les préfixes étaient de taille fixe, on avait uniquement le choix en des préfixes de longueur 8, baptisés « classes A », de longueur 16, les « classes B » et de longueur 24, les « classes C ». Ce système était très rigide et gaspillait considérablement les adresses (si une classe C ne suffisait pas, pas possible de prendre un /23, il fallait sauter directement à une classe B). Il a donc été abandonné au profit de l'adressage actuel, qui avait été baptisé CIDR pour Classless Inter-Domain Routing. Classless donc, « sans classe ». Ce nom dit bien ce qu'il veut dire, les classes ont disparu.

Le premier RFC sur les idées qui mèneront à CIDR a été le RFC 1338 en juin 1992. Le RFC 1467 en août 1993 faisait le point sur le déploiement de CIDR. Les RFC 1518 et RFC 1519 en septembre 1993 sont les premier à décrire CIDR sous sa forme actuelle, pendant que le RFC 1517 décrivait les motivations et les problèmes que CIDR visait à résoudre. C'est donc depuis quinze ans que les classes ont disparu ! Révisée, la norme actuelle est le RFC 4632. Comme on le voit, l'adressage actuel est très ancien. Il est très inquiétant que des enseignants ignorants donnent toujours des cours IP où les classes sont citées, sans préciser qu'elles n'ont qu'un intérêt historique.

Les classes se voient encore un peu dans certaines techniques comme le DNS où les délégations dans in-addr.arpa se font sur des frontières d'octets. Ce problème a été largement réglé par le RFC 2317.

Pendant les quelques années où la communauté Internet testait la nouvelle technique, certains termes avaient été utilisés, qui n'ont plus de raison d'être. C'est ainsi qu'on parlait de supernetting pour désigner l'agrégation de plusieurs classes en un préfixe plus général (cette technique étant la base de CIDR, elle n'a plus besoin d'un nom spécifique, même s'il faut encore apparemment dire à IOS ip classless pour qu'il l'accepte). De même, les VLSM (Variable Length Subnet Mask) ont été oubliés : le masque du réseau est désormais toujours de longueur variable.

Le successeur d'IPv4, IPv6, est, lui, parti proprement en tenant compte de l'expérience de son prédécesseur et a toujours été « sans classe ».


L'article seul

RFC 5157: IPv6 Implications for Network Scanning

Date de publication du RFC : Mars 2008
Auteur(s) du RFC : T. Chown (University of Southampton)
Pour information
Première rédaction de cet article le 20 mai 2008


Une technique classique des méchants craqueurs qui cherchent à pénétrer un gentil réseau est de balayer (to scan) l'ensemble des adresses IP à l'intérieur du réseau, pour voir lesquelles répondent et ainsi trouver des cibles. Par exemple, Slammer l'utilisait. Mais en IPv6, où le nombre d'adresses possibles est infiniment plus grand, cette tactique est-elle encore efficace ? (Notez que ce RFC a, depuis, été remplacé par le RFC 7707.)

Imaginons que le craqueur aie déterminé que le préfixe IP du réseau de sa victime est le 192.0.2.128/25. Il reste 7 bits pour les machines soit 128 victimes potentielles à interroger, ce qui ne prend que quelques secondes pour un programme comme fping. Cette technique est donc très utilisée pour avoir une liste des adresses IP utilisées... et donc des cibles possibles. Mais en IPv6, si la victime a le réseau de préfixe 2001:DB8:AF:42::/64, comment le balayer de manière efficace ? Cela fait 64 bits pour les machines donc 18446744073709551616 adresses à examiner, ce qui ne peut pas se faire en un temps raisonnable (sections 2.1 et 2.2 du RFC).

Certains en ont donc déduit que le balayage (scanning) était impossible en IPv6 et que donc, sur ce point, IPv6 offrait davantage de sécurité qu'IPv4.

Mais notre RFC montre que ce n'est pas si simple et qu'il existe d'autres méthodes que la force brute pour trouver les machines allumées (un excellent article de Steve Bellovin avait déjà déblayé ce terrain).

La section 2.3 parle par exemple de l'exploitation de conventions d'adressage. Si l'administrateur du réseau 2001:DB8:AF:42::/64 cité plus haut numérote ses machines 2001:DB8:AF:42::1, 2001:DB8:AF:42::2, 2001:DB8:AF:42::3, etc, l'attaquant n'aura à tester qu'une petite partie des adresses théoriques. Si au lieu d'adresses calculées ainsi, on utilise la traditionnelle autoconfiguration sans état d'IPv6 (RFC 4862), la connaissance du fournisseur des cartes Ethernet fournit déjà un bon moyen de sérieusement réduire l'espace de recherche.

Les sections 3 et 4 du RFC listent l'ensemble des techniques connues et que le méchant pourrait utiliser pour arriver néanmoins à balayer un réseau IPv6. La section 4 concerne les cas où l'attaquant est lui-même sur ce réseau et le problème est alors assez simple (il lui suffit d'espionner les paquets ND (Neighbor Discovery, cf. RFC 4861). La section 3 parle des cas où l'attaquant n'est pas sur le réseau. Sa tâche est alors plus difficile mais reste faisable : par exemple la section 3.3 détaille l'information qu'on peut tirer d'un transfert de zone DNS, et la 3.4 l'intérêt qu'on peut trouver à regarder les journaux d'un gros serveur, journaux où on trouvera les adresses de clients qui sont autant de cibles potentielles.

Plus moderne est l'observation des pairs dans un réseau P2P (section 3.5). La plupart des protocoles de P2P, par exemple BitTorrent, mettent en rapport direct les « offreurs » et les « preneurs » et, en offrant du contenu intéressant, on peut récolter beaucoup d'adresses IP de machines.

La section 5 passe aux recommandations et contre-mesures : utilisation d'adresses « vie privée » (RFC 8981), dont la durée de vie est limitée, utilisation d'adresses EUI-64 (RFC 4291, cf. section 5.1) mais sans l'adresse MAC (section 5.3), configuration du serveur DHCP (RFC 8415) pour ne pas attribuer les adresses séquentiellement à partir de ::1 (section 5.4), etc.

Enfin, en guise de synthèse, la section 7, qui résume le problème et les moyens de le limiter, rappelle que dissimuler les adresses IP des machines est de la Sécurité par l'obscurité : cela peut ralentir l'attaquant, mais cela ne doit certainement pas être utilisé comme unique moyen de défense, car, tôt ou tard, l'attaquant trouvera ces adresses.

Un nouveau RFC, plus détaillé, a remplacé celui-ci, le RFC 7707.


Téléchargez le RFC 5157


L'article seul

RFC 5226: Guidelines for Writing an IANA Considerations Section in RFCs

Date de publication du RFC : Mai 2008
Auteur(s) du RFC : Thomas Narten (IBM), Harald Alvestrand (Google)
Première rédaction de cet article le 20 mai 2008
Dernière mise à jour le 24 juin 2015


Un aspect peu connu du travail de normalisation est la nécessité de tenir des registres de certains paramètres, lorsque la liste de ces derniers n'est pas fixée dans un RFC. Par exemple, les algorithmes publiés dans le DNS pour IPsec ne sont pas définis de manière limitative dans le RFC 4025 mais sont enregistrés dans un registre public. Pour les RFC, ces registres sont tenus par l'IANA. Celle-ci ne décide pas quels registres elle doit tenir ni à quelle condition un nouveau paramètre peut y rentrer, elle applique les décisions contenus dans la section IANA Considerations d'un RFC. C'est cette section qui était décrite ici. Ce RFC a depuis été remplacé par le RFC 8126.

Prenons l'exemple du RFC 3315 (DHCP). Sa section 24 contient le texte This document defines several new name spaces associated with DHCPv6 and DHCPv6 options: - Message types - Status codes - DUID - Option codes IANA has established a registry of values for each of these name spaces, which are described in the remainder of this section. These name spaces will be managed by the IANA and all will be managed separately from the name spaces defined for DHCPv4.. En application de ce texte, l'IANA a créé le registre DHCPv6 and DHCPv6 options qu'on peut consulter en ligne à https://www.iana.org/assignments/dhcpv6-parameters. Et comment ajoute-t-on des entrées dans ce registre ? En suivant les règles données dans ce même RFC : New DHCP option codes are tentatively assigned after the specification for the associated option, published as an Internet Draft, has received expert review by a designated expert [11]. The final assignment of DHCP option codes is through Standards Action, as defined in RFC 2434 [11]. .

Pour aider les auteurs de RFC à écrire correctement cette section IANA Considerations, notre RFC 5226, qui succède au RFC 2434, pose quelques règles.

Les sections 1 et 2 du RFC décrivent le problème général de la gestion d'un espace de nommage (namespace). Tous ces espaces n'ont pas les mêmes caractéristiques. Certains sont très petits (le champ protocole, qui n'a que huit bits soit 256 valeurs possibles, cf. RFC 5237) et doivent donc être gérés avec prudence, certains sont hiérarchiques comme le DNS ou comme les OID et peuvent donc être délégués, certains sont immenses, et peuvent être gérés avec moins de précautions (mais nécessitent quand même des règles, comme expliqué dans la section 2).

La section 3 décrit le rôle des experts sur lesquels doit parfois s'appuyer l'IANA. Certains registres nécessitent en effet un choix technique avec l'enregistrement d'un nouveau paramètre et l'IANA n'a pas forcément les compétences nécessaires pour cette évaluation. Elle délègue alors cette tâche à un expert (designated expert). Par exemple, pour le registre des langues, défini par le RFC 4646, l'expert actuel est Michael Everson. Ce registre utilise également une autre possibilité décrite dans cette section, une liste de discussion qui sert à un examen collectif des requêtes (pour le registre des langues, cette liste est ietf-languages@iana.org). La section 3 discute des autres choix qui auraient pu être faits (par exemple un examen par le groupe de travail qui a créé le RFC, ce qui n'est pas possible, les groupes de travail IETF ayant une durée de vie limitée). Elle explique ensuite les devoirs de l'expert (comme la nécessité de répondre relativement rapidement, section 3.3, chose qui est loin d'être toujours faite).

La section 4 est consacrée à la création d'un nouveau registre. Si un RFC doit demander une telle création, il doit préciser quelle politique d'enregistrement devra suivre l'IANA. C'est une des parties les plus intéressantes du RFC, notamment sa section 4.1 qui explique les politiques possibles, par exemple :

  • Allocation hiérarchique (« Hierarchical Allocation »), où l'IANA ne délègue que les noms de plus haut niveau, laissant d'autres registres allouer les nouveaux inférieurs. C'est le cas par exemple des adresses IP.
  • Premier Arrivé, Premier Servi (« First Come First Served »), où toute requête est acceptable et est faite dans l'ordre d'arrivée. Les entrées dans le préfixe OID iso.org.dod.internet.private.enterprise sont un bon exemple (https://www.iana.org/assignments/enterprise-numbers mais attention, le registre est lourd à charger). C'est sans doute la plus « libérale » des politiques d'enregistrement.
  • Examen par un expert (« Expert review »), comme indiqué plus haut. C'est ainsi que sont gérés les plans des URI permanents du RFC 7595.
  • Spécification nécessaire (« Specification required ») où un texte écrit et stable décrivant le paramètre souhaité est nécessaire (ce texte n'est pas forcément un RFC, il y a d'ailleurs une politique « RFC required »). Les profils de ROHC (RFC 5795) sont enregistrées sous cette condition.
  • Examen par l'IETF (« IETF Review »), l'une des plus « lourdes », puisqu'il faut un RFC « officiel », qui soit passé par l'IESG ou par un groupe de travail IETF (tous les RFC ne sont pas dans ce cas, certains sont des contributions individuelles). C'est la politique des extensions TLS du RFC 6066 (cf. RFC 5246, section 12, qui utilisait encore l'ancien terme de « IETF Consensus »).
  • Action de normalisation (« Standards Action »), encore plus difficile, le RFC doit être sur le chemin des normes et donc avoir été approuvé par l'IESG. C'est le cas par exemple des types de message BGP (RFC 4271, section 4.1), en raison de la faible taille de l'espace en question (un seul octet, donc un nombre de valeurs limité) et sans doute aussi en raison de l'extrême criticité de BGP. C'est aussi la politique pour les options DHCP données en exemple plus haut.
  • Et il existe encore l'approbation par l'IESG qui est la politique de dernier recours, à utiliser en cas de cafouillage du processus.

Parmi les autres points que doit spécifier le RFC qui crée un nouveau registre, le format de celui-ci (section 4.2). À noter que l'IANA n'utilise pas d'outils pour tester ce format (les registres IANA étaient de simples fichiers texte, maintenus avec un éditeur ordinaire mais ont migré pour la plupart vers XML, depuis la publication de ce RFC) et que des erreurs de syntaxe sont parfois apparues dans des registres.

La section 5 couvre l'enregistrement de nouveaux paramètres dans un registre existant. C'est elle qui précise, entre autres, que l'IANA ne laisse normalement pas le choix de la valeur du paramètre au demandeur (mais, en pratique, l'IANA est sympa et a accepté beaucoup de demandes humoristiques comme le port TCP n° 1984 pour le logiciel Big Brother...)

Enfin, diverses questions sont traitées dans la section 6, comme la récupération de valeurs qui avaient été affectées mais qui ne le sont plus (le RFC 3942 l'avait fait mais c'est évidemment impossible dès que les paramètres en question ont une... valeur, ce qui est le cas entre autres des adresses IP).

Bien que la plupart des allocations effectuées par l'IANA ne sont guère polémiques (à l'exception des noms de domaine et des adresses IP, qui sont des sujets très chauds), notre RFC 5226 prévoit une procédure d'appel, décrite en section 7. Cela n'a pas suffit à régler quelques cas pénibles comme l'enregistrement de CARP.

Ce RFC 5226 remplace le RFC 2434 (et a lui-même été remplacé depuis par le RFC 8126). Les principaux changements sont détaillés dans la section 10. Par exemple, le terme de propagande IETF Consensus a été remplacé par le plus neutre IETF Review. (Les organisations qui parlent de leur consensus policy le font en général pour faire taire les critiques, en prétendant que tout le monde est d'accord.) Les changements sont en général de simples clarifications, le nouveau RFC étant plus directif que l'ancien. Les autres changements sont souvent l'ajout de questions nouvelles, comme la récupération de valeurs qui avaient été allouées.

Les relations entre l'IETF et l'IANA sont fixées par le MOU contenu dans le RFC 2860. À noter que tout n'est pas couvert dans ce RFC, notamment des limites aux demandes de l'IETF. Que se passerait-il par exemple si l'IETF demandait à l'IANA, qui ne facture pas ses prestations, de créer un registre de milliards d'entrées, très dynamique et donc très coûteux à maintenir ? Pour l'instant, l'IANA ne peut pas, en théorie, le refuser et la question s'est parfois posée à l'IETF de savoir si tel ou tel registre n'était pas trop demander.

Puisque l'IANA est un acteur important de l'Internet, rappelons aussi que, bien que la fonction de l'IANA soit actuellement assurée par l'ICANN, la tâche de gestion des protocoles et des registres n'a rien à voir avec les activités, essentiellement politiciennes, de l'ICANN.


Téléchargez le RFC 5226


L'article seul

screen, pour lancer de longs programmes et pouvoir les suivre

Première rédaction de cet article le 18 mai 2008


Sur une machine Unix, on a souvent envie de lancer des programmes qui durent longtemps, parfois des jours ou des semaines, et qu'on souhaite regarder de temps en temps, sans pour autant bloquer un terminal (d'autant plus qu'on travaille depuis différents postes). screen est un outil assez peu connu pour assurer cette tâche. Il permet de suivre un programme en cours d'exécution, puis de se détacher de lui tout en le laissant tourner et de se rattacher ensuite à volonté.

Si le programme est prévu pour tourner sans surveillance, directe, si c'est un démon, screen n'est pas nécessaire. Mais si on lance une grosse compilation sur sa machine Gentoo ou FreeBSD ? Si on a lancé un client BitTorrent pour télécharger des fichiers et qu'on veut voir de temps en temps où il en est ? Si c'est sur la machine de son bureau, on peut toujours laisser un xterm ouvert. Mais si c'est sur une machine dédiée hébergée chez OVH ou Slicehost ?

Avec la solution du xterm ouvert, je ne peux pas regarder dans la journée au bureau et le soir à la maison. Même chose avec des trucs comme nohup. Avec screen, par contre, je peux lancer le programme, regarder s'il tourne, me détacher du programme (screen continuera à tourner, même sans terminal, et le programme avec lui) puis plus tard me ré-attacher, depuis une toute autre machine.

Les trois commandes de base avec screen dont donc :

  • screen pour lancer une nouvelle session. On peut aussi taper screen MONPROGRAMME pour lancer le programme immédiatement (screen se terminera lorsque le programme MONPROGRAMME se terminera).
  • Control-a d (par défaut, mais c'est modifiable) pour se détacher.
  • screen -r pour reprendre une session en cours.

Personnellement, j'utilise aussi beaucoup l'option -S qui permet de donner un nom à une session screen. screen -list permet ensuite d'afficher les sessions et screen -r NOMSESSION de reprendre celle désirée :

~ % screen -S toto
[Ici, on fait un Control-a d]
[detached]
~ % screen -list
There are screens on:
        8116.toto       (Detached)
        3509.BitTorrent (Detached)
2 Sockets in /var/run/screen/S-stephane.

(screen permet aussi d'avoir plusieurs fenêtres dans une même session mais je n'utilise pas cette possibilité.)

L'un des intérets de screen est de surveiller des programmes bavards (comme une grosse compilation) et il peut donc être utile de remonter dans les messages précédemment affichés. Control-a <escape> fera passer en mode Copy et on pourra chercher en arrière avec Control-r.

screen peut se configurer, notamment via son fichier ~/.screenrc. Par exemple, certains utilisateurs d'Emacs n'apprécie pas le Control-a qui commence les commandes (dans Emacs, cette séquence permet d'aller au début de la ligne) et le reconfigurent dans .screenrc :

# Control-z, plutôt
escape ^Zz

L'excellent site dotfiles.org a une section sur des exemples de tels fichiers.

Un dernier truc amusant qu'un utilisateur m'a signalé. screen peut aussi s'attacher à un terminal physique et peut donc servir d'émulateur de terminal, de concurrent de minicom. Ici, la machine preston est accessible par une liaison série :

% screen -S preston /dev/ttyS0

NetBSD/sparc64 (preston) (console)

login: 

[Control-A d et on est détaché]

J'ai aussi écrit un article sur screen spécifique à BitTorrent. On peut trouver une excellente introduction à screen http://linuxgazette.net/147/appaiah.html ou une plus courte en http://www.mattcutts.com/blog/a-quick-tutorial-on-screen/ ou bien http://www.redhatmagazine.com/2007/09/27/a-guide-to-gnu-screen/.

Le principal concurrent de screen est tmux. Un tableau des commandes comparées donne une idée des fonctions supplémentaires de tmux (c'est vu par les gens de tmux, attention). Il existe un autre article de comparaison.


L'article seul

Fiche de lecture : Unicode 5.0 en pratique

Auteur(s) du livre : Patrick Andries
Éditeur : Dunod
978-2-10-051140-2
Publié en 2008
Première rédaction de cet article le 17 mai 2008


Unicode est un jeu de caractères permettant de représenter toutes les écritures du monde. Il serait donc logique qu'il soit documenté dans plusieurs langues mais, sauf erreur, ce livre de Patrick Andries est le premier à parler d'Unicode en français.

Le sujet est très riche et très complexe. Certaines personnes, ignorant l'ampleur du problème, disent parfois qu'Unicode est « trop complexe ». La réalité est que le monde est complexe ; Unicode choisissant de suivre les usages existants (au lieu que les usages se plient aux limites de la technique), il doit traiter d'innombrables cas et le résultat est certainement complexe, mais pas inutilement complexe. Patrick Andries connait bien Unicode pour être membre du Consortium Unicode depuis des années et pour être un promoteur de cette norme en français (son site http://hapax.qc.ca/ regorge d'informations sur Unicode). Il s'est donc attaqué à la tâche d'écrire le premier livre en français sur Unicode.

Cela suppose quelques défis, notamment de trouver des traductions correctes et compréhensibles pour certains termes. Je n'ai pas reconnu du premier coup le word joiner (U+2060) derrière le « gluon de mots » et les « seizets d'indirection » m'ont également dérouté, même si le terme est bien plus correct que l'anglais surrogates. D'une manière générale, ce livre est peut-être un peu trop difficile à lire à force de vouloir être exact et de toujours utiliser des termes corrects, en évitant raccourcis et approximations. Il parait que la langue française est bien adaptée à cela...

Le plan du livre est classique ; concepts de base sur les écritures (chapitre 1) ; les jeux de caractères (chapitre 2) ; les concepts de base d'Unicode (chapitres 3 et 4) ; grand tour d'horizon des caractères dont on dispose dans Unicode (chapitres 5 à 8) ; applications d'Unicode, notamment dans le monde des protocoles et formats Internet (chapitres 9 à 11) ; l'internationalisation de logiciels (chapitre 12, très intéressant mais dont le lien avec Unicode est ténu) ; Unicode et les polices (chapitre 13, dont je n'ai vu aucun équivalent dans les autres livres sur Unicode).

Les exemples de programmation du chapitre 12 sont presque tous empruntés à C# ou à Java, des langages plutôt « costard / cravate », qui ont souvent l'avantage d'un grand nombre de bibliothèques pour manipuler l'Unicode (par exemple via un accès facile à ICU) et le défaut d'un modèle de caractères peu Unicodien (par exemple, dans Java, les caractères en dehors du Plan Multilingue de Base ne sont pas des caractères Unicode comme les autres, contrairement à Python ou Haskell). Pour avoir une petite idée du support Unicode dans d'autres langages, on peut regarder mon article Unicode en divers langages.

De même, la plupart des exemples concrets, par exemple sur la saisie de caractères Unicode, ne concernent que MS-Windows et les utilisateurs d'Unix qui ont des difficultés avec Unicode ne trouveront pas beaucoup à se mettre sous la dent.

L'écriture même d'un tel livre est un exploit, dans un monde où les systèmes informatiques sont encore rares d'avoir un parfait support d'Unicode. Peu de logiciels permettent de composer un ouvrage avec d'innombrables exemples Unicode (LaTeX en est hélas peu capable). Le livre a été écrit avec MS-Word, puis porté sur InDesign pour l'édition finale. InDesign s'est parfois montré trop intelligent, par exemple en remplaçant des caractères qu'il pensait inadaptés par d'autres. C'est ainsi qu'un exemple discutant le guillemet anglo-saxon, " (U+0022), présente en fait un guillemet français, le « (U+00AB). Une page Web d'errata présente les erreurs recensées dans le livre.

Au final, c'est un livre que je recommande chaudement. Les programmeurs qui veulent mettre en œuvre Unicode (et pas seulement l'utiliser) trouveront plus d'informations dans le livre de Gillam mais ceux qui veulent se servir d'Unicode dans un contexte Internet/XML seront au contraire bien plus satisfaits avec le livre d'Andries (qui est plus proche, par le public visé, du livre - en anglais - de Korpela).


L'article seul

RFC 5000: Internet Official Protocol Standards

Date de publication du RFC : Mai 2008
Auteur(s) du RFC : RFC Editor
Pour information
Première rédaction de cet article le 16 mai 2008


Ce RFC, héritage d'une époque où le Web n'existait pas, était simplement un récapitulatif des normes actuelles de l'Internet, récapitulatif qui se trouve désormais en ligne en http://www.rfc-editor.org/rfcxx00.html. Mais c'est l'occasion de revenir sur les normes Internet et leur signification.

Autrefois, il n'était pas facile d'accéder à l'information en ligne, ou bien elle n'était tout simplement pas accessible et l'état de bases de données comme la base du registre IANA ou bien la liste des RFC étaient publiées sous forme de RFC. Pour la base des numéros et noms de protocoles, ce furent les RFC 317, puis le RFC 604, puis plusieurs autres jusqu'au dernier, le RFC 1700 en 1994. Après, cette information n'a plus été distribuée qu'en ligne (le RFC 3232 explique pourquoi). Mais la liste des protocoles normalisés continue à être publiée, en plus de la version en ligne, sous forme de RFC, comme notre RFC 5000, qui remplace le RFC 3700. C'est finalement le RFC 7100 qui a annoncé officiellement la fin de la publication de cette liste sous forme de RFC. Désormais, seule la version en ligne fait foi.

Que contient ce RFC 5000 ? Une liste de RFC, classés selon leur statut. Sur le chemin des normes, un RFC pouvait à l'époque avoir trois statuts, proposition de norme, projet de norme et norme complète (le nombre a été réduit à deux par le RFC 6410). Mais ces trois statuts, décrits dans le RFC 2026, sont peu significatifs. En effet, l'IETF étant fondée sur le volontariat, le passage d'un protocole d'un statut à un autre nécessite une action volontaire, pour un gain douteux (peu de gens font attention au niveau de normalisation). On voit donc des protocoles très utilisés rester au statut de proposition et des protocoles abandonnés depuis longtemps garder leur statut de norme complète. L'IETF n'a pas de ramasse-miettes pour les reclasser.

Parmi les normes complètes, on trouve évidemment IPv4 (RFC 791) et le DNS (RFC 1034 et RFC 1035) mais aussi les désormais quasiment abandonnés RARP (RFC 903) ou bien complètement abandonnés comme le serveur de citations (RFC 865) ou comme IP sur ARCnet (RFC 1201). En revanche, HTTP n'y figure pas (le RFC 2616 n'est que « projet de norme ») et SMTP y est représenté par une version dépassée, le RFC 821 (la version actuelle est dans le RFC 2821 mais qui n'est pas considéré comme « norme complète »). Tout ceci décrédibilise sérieusement le classement.

Le RFC contient également la liste des RFC de « bonnes pratiques » comme le RFC 2870 (qui était BCP 40 à l'époque, depuis remplacé par le RFC 7720) sur le fonctionnement des serveurs de noms de la racine ou comme le RFC 2277 (BCP 18) sur la politique de l'IETF concernant les jeux de caractères et les langues.

Notre RFC 5000 contient aussi des RFC expérimentaux, qui ne sont pas sur le chemin des normes. Il est exceptionnel que, une fois l'expérience terminée, elle soit documentée et que le RFC soit reclassifié en « historique » (une des exceptions est le RFC 3197 qui a documenté l'échec du RFC 1611). On y trouve par conséquent une très longue liste d'expériences assez amusantes comme le défunt RFC 1383 qui tentait de remplacer BGP par le DNS...


Téléchargez le RFC 5000


L'article seul

RFC 5193: Protocol for Carrying Authentication for Network Access (PANA) Framework

Date de publication du RFC : Mai 2008
Auteur(s) du RFC : P. Jayaraman (Net.Com), R. Lopez (Univ. of Murcia), Y. Ohba (Toshiba), M. Parthasarathy (Nokia), A. Yegin (Samsung)
Pour information
Réalisé dans le cadre du groupe de travail IETF pana
Première rédaction de cet article le 14 mai 2008


Appliquant le cahier des charges qui avait été défini dans le RFC 4058, le protocole PANA vient d'être normalisé dans le RFC 5191 et notre RFC accompagne cette spécification, pour décrire les caractéristiques de haut niveau du protocole.

PANA sert à transporter un protocole d'authentification, typiquement EAP (RFC 3748), entre une machine qui veut accéder à un réseau (la PaC, PANA Client) et une machine d'authentification, le PAA (PANA Authentication Agent). (Ces rôles sont expliqués dans la section 2 du RFC, la section 3 détaillant les différentes communications entre eux.) pana Après le succès de l'authentification, le PAA indiquera à l'EP (Enforcement Point, typiquement un routeur ou un commutateur) qu'il peut laisser passer le trafic du client, du PaC.

Ces rôles peuvent être situés sur des machines différentes ou pas. Par exemple, en ADSL, le PAA et l'EP seront typiquement situés dans le même BRAS. Le protocole PANA ne spécifie que la communication entre le PaC et le PAA.

À noter que, pour prendre sa décision, le PAA pourra être lui-même client d'un protocole d'AAA comme Radius (RFC 2865) ou Diameter (RFC 6733).

PANA a été conçu pour s'adapter à des environnements très différents, notamment du point de vue de la sécurité (section 4 du RFC). Par exemple, il peut y avoir un canal sûr entre le PaC et le PAA, avant même que PANA ne tourne ou pas. S'il existe un tel canal sûr (cas du WiFi avec WPA ou bien cas où la liaison physique entre le PaC et le PAA est considérée comme sûre), PANA est très simple. Dans le cas contraire, il est important d'utiliser des méthodes EAP résistantes à l'espionnage ou à la modification des paquets.


Téléchargez le RFC 5193


L'article seul

Fiche de lecture : L'identité numérique en question

Auteur(s) du livre : Olivier Iteanu
Éditeur : Eyrolles
978-2-212-12255-8
Publié en 2008
Première rédaction de cet article le 13 mai 2008


Aujourd'hui, les questions d'identités numériques sont partout sur Internet. Est-il légal de donner un nom qui n'est pas celui de l'état civil lorsqu'on remplit un de ces milliers de formulaires qui existent sur le Web ? Est-ce grave que les contributeurs de Wikipédia soient identifiés par des « pseudos » comme Cereales Killer ou Anthere ? Est-ce normal de devoir se souvenir de dizaines de mots de passe différents ? Pourquoi ne pas utiliser son compte Google pour tout, de ma banque en ligne aux blogs où je mets des commentaires ? Si mon avatar dans Second Life tue quelqu'un, suis-je responsable ? Toutes ces questions sont relatives au concept d'identité numérique. La notion d'identité paraissait simple dans le monde physique où beaucoup de gens (à tort selon Olivier Iteanu) l'assimilaient à la seule identité délivrée par l'État. Comment faire désormais sur les réseaux ?

Le livre répond réellement à toutes ces questions et à bien d'autres. Olivier Iteanu est un avocat, expert reconnu des aspects juridiques des NTIC et défenseur des droits des citoyens face à des dangers comme l'utilisation abusive de leurs données personnelles ou comme leur traçage excessif.

Ce livre est court et n'épuise pas la question, qui est très vaste. Mais il éclaire bien des aspects de celle-ci. Mon chapitre préféré est le 4, sur le « pseudo », où Iteanu défend l'idée que le pseudo est une identité valable, reconnue mais soumise à certaines limites (ne pas choisir un pseudo dans le but de tromper, se méfier du droit des marques).

Mais il y a aussi l'intéressante introduction du livre, sur le manque d'un service d'identité générique sur Internet, manque probablement dû (c'est une des hypothèses évoquées) au choix de la simplicité. Des projets comme OpenID tentent d'apporter une partie de la solution de ce manque.

Parmi les autres chapitres utiles, le chapitre 2 est une explication et une défense de l'anonymat, dont Iteanu pense que, bien que légal actuellement, il pourrait être mieux reconnu par la loi. Le chapitre 9 est consacré aux menaces liées à l'usurpation d'identité comme le hameçonnage et le chapitre 10 à la redoutable efficacité du moteur de recherche Google, « plus fort que le casier judiciaire » car il n'oublie rien et n'est soumis à aucun contrôle.

La conclusion du livre est un appel à maîtriser nos identités numériques, plutôt que des les voir créées, copiées et volées par des forces peu sympathiques. Cela implique, dit Iteanu, un vrai droit à l'anonymat, une meilleure définition juridique de l'identité et le déploiement de techniques d'identité décentralisées permettant à chacun de créer et de contrôler ses identités sur le réseau.

Un peu de publicité personnelle pour finir : j'ai fait un article sur OpenID à JRES, article qui place cette technique au milieu des grandes manœuvres sur l'identité numérique. OpenID pourrait être une des briques permettant de construire le système d'identité distribué dont parle Iteanu.


L'article seul

Le spectacle de Jolie Môme à la fête de Lutte Ouvrière

Première rédaction de cet article le 12 mai 2008


La Compagnie Jolie Môme a, une fois de plus, fait un remarquable spectacle à la fête annuelle de Lutte Ouvrière le 12 mai. C'était chaud, coloré, collectif (pas une vedette unique toujours mise en avant, chaque artiste a son tour) et nouveau aussi.

Parmi les chansons, un sketch/chanson très drôle sur les fermetures de maternités dans les petites villes, où le futur père et la future mère doivent conduire jusqu'à la grande ville ; une chanson NTIC sur la disparition du numéro de téléphone des renseignements, le 12 ; une nouvelle orchestration des Nouveaux Partisans de Dominique Grange, et une autre de Sans la nommer de Georges Moustaki ; une chanson très méchante (mais pas forcément injuste) sur l'écologie, dédiée à Dominique Voynet ; une chanson sur la grève des employés de McDonald's ; un hilarant « conseil aux athlètes français aux Jeux Olympiques » leur montrant comment chanter l'Internationale sur l'air de la Marseillaise au cas où ils gagneraient.

En conclusion : « Il faudra lutter plus pour gagner plus. ».


L'article seul

RFC 2328: OSPF Version 2

Date de publication du RFC : Avril 1998
Auteur(s) du RFC : John Moy (Ascend Communications)
Chemin des normes
Première rédaction de cet article le 11 mai 2008


OSPF est le protocole de routage interne de l'IETF. Si RIP est encore utilisé à certains endroits, si des protocoles non-standard, spécifiques à un fabricant de routeurs sont parfois utilisés sur des sites où l'intérêt des normes ouvertes n'a pas été compris, si son concurrent ISO 10589, IS-IS a connu quelques déploiements, OSPF est de loin le plus répandu. Ce RFC est la spécification normative d'OSPF version 2, la version pour IPv4.

Par définition, les IGP, comme OSPF, sont utilisés uniquement à l'intérieur d'un système autonome. Il est donc toujours difficile de produire des statistiques fiables directes, rien ne permettant de dire, vu de l'extérieur, quel IGP utilise une organisation. Mais il n'y a pas de doute qu'OSPF est de loin le plus répandu. Son histoire a parfois été cahotique, et vient d'une grande discussion à l'IETF pour créer un IGP moderne, discussion très chaude qui avait opposé les partisans des protocoles à vecteur de distance, comme RIP aux protocoles à état des liens, comme OSPF. (Christian Huitema, dans son excellent livre « Et Dieu créa l'Internet » décrit ce débat. Le premier article sur un protocole à états des liaisons dans l'ancien Arpanet est l'excellent An Overview of the New Routing Algorithm for the ARPANET en 1979.)

OSPF a finalement été normalisé dans le RFC 1131 en octobre 1989, qui connaitra plusieurs successeurs, les plus récents étant le RFC 2178, et son successeur, notre RFC 2328. L'annexe G décrit les différences avec le RFC 2178, aucune n'étant vitale (il s'agit bien du même protocole).

Notre RFC 2328 est un des plus longs jamais publiés par l'IETF, avec presque deux cent pages. Il n'est pas spécialement pédagogique, son but étant de permettre le développement d'implémentations compatibles du protocole. Il ne cherche pas à aider l'administrateur réseau, ni à informer le curieux de passage. La table des matières est déroutante, conçue selon une logique qui a un sens, mais pas celui du nouveau venu. Pour une explication de plus haut niveau (mais pas forcément facile) d'OSPF, on peut consulter le livre écrit par l'auteur du RFC. Pour une présentation plus orientée vers l'ingénieur en charge du réseau, on peut citer mon cours OSPF. Mais, de toute façon, OSPF est compliqué, il ne faut pas se faire d'illusions.

Quels sont les principes de base d'OSPF ? Comme décrit dans le résumé du RFC et dans la section 1, OSPF est un protocole à état des liens (link state et ce terme se retrouve partout dans le RFC). Chaque routeur diffuse par inondation ( flooding) l'état de ses interfaces réseaux et tout routeur connait donc l'état de tout le réseau, tous les routeurs ont la même information. À partir de celle-ci, chaque routeur fait tourner l'algorithme SPF pour trouver les routes à suivre. Le fait que tous les routeurs aient la même information facilite le calcul de routes sans boucles.

Le routage proprement dit se fait ensuite uniquement sur les en-têtes IP, sans encapsulation ultérieure.

Comme le système autonome a en général des connexions avec d'autres systèmes autonomes, certains des routeurs apprennent également des routes par d'autres protocoles comme BGP (RFC 4271) et OSPF permet d'importer ces routes dans la base de données, comme « routes externes ».

OSPF dispose d'un mécanisme hiérarchique, les zones (areas), qui permet de limiter la diffusion de l'information, rendant ainsi ce protocole moins sensible aux changements d'échelle. La règle « tous les routeurs ont exactement la même base de données des états des liens » doit donc être nuancée : elle n'est valable qu'à l'intérieur d'une seule zone.

Tout le vocabulaire d'OSPF est rassemblé dans la section 1.2. Comme souvent avec les documents informatiques en anglais, il n'y a pas une seule traduction en français qui fasse autorité. J'ai repris ici le vocabulaire de mon cours.

Vue la taille du protocole, il est impossible de citer toutes les sections du RFC. Seules celles qui me semblent les plus importantes sont listées ici.

La section 2 du RFC détaille la base des états de liens, le cœur d'OSPF. Sa section 2.1 précise comment sont représentés les routeurs et les réseaux. Ces derniers peuvent être point à point, à diffusion comme Ethernet, ou bien NBMA (Non-Broadcast Multiple Access, qui font l'objet de la section 2.1.1 et pour lesquels les choses sont assez complexes) comme le relais de trames. La représentation du lien dépend du type de réseau auquel le routeur est connecté.

La section 2.1.2 illustre tout ceci avec un exemple de base de données pour un réseau petit mais relativement complexe. La section 2.2 montre ensuite le résultat du SPF sur ce réseau.

La 2.3 explique la modélisation des informations externes, obtenues depuis un autre protocole. Elles sont de deux types, le type 1 pour les informations venant du système autonome (et donc dont le coût peut être comparé aux coûts OSPF) et le type 2 pour les informations extérieures, non seulement à OSPF, mais également au système autonome, et pour lesquelles le coût est toujours supérieur au coût OSPF.

La section 4 décrit le fonctionnement du protocole : chaque routeur OSPF, au démarrage, rassemble les informations sur ses propres interfaces réseau, puis apprend l'existence de ses voisins, et forme une adjacence sur chaque réseau. Il échange ensuite l'information sur l'état des liens avec le routeur adjacent (rappelons que tous les voisins ne sont pas adjacents, seuls le DR - Designated Router - et le BDR - Backup Designated Router le sont).

Cette information sur les états des liens est transmises sous forme d'unités nommés LSA (Link State Advertisement), qui sont transmis par inondation (procédure décrite en détail en section 13), jusqu'à ce que tous les routeurs de la zone aient la même information.

Plus concrète, la section 4.3 normalise le format des paquets OSPF. Celui-ci fonctionne directement sur IP, avec le numéro de protocole 89. Les champs du protocole sont de taille fixe, pour faciliter la mise en œuvre. Les détails du format sont renvoyés à l'annexe A. Le traitement des paquets figure dans la section 8.

La section 5 est dédiée aux différentes structures de données que doit manipuler le routeur OSPF. Par exemple, le Router ID est un entier de 32 bits qui identifie de manière unique un routeur du système autonome. Cet entier est en général représenté avec la même syntaxe qu'une adresse IPv4 (même pour la version d'OSPF conçue pour IPv6). D'autres structures de données sont décrites dans les sections 9 (les interfaces réseaux) ou 10 (les routeurs voisins).

La section 7 explique le protocole par lequel les routeurs OSPF d'un même segment de réseau se trouvent et s'échangent des informations. Tous les routeurs du lien envoient des paquets de type Hello à une adresse de diffusion restreinte, 224.0.0.5 (les valeurs numériques nécessaires au protocole, comme cette adresse, sont dans l'annexe A). Ici, tcpdump montre ces paquets émis par le routeur de Router ID 192.134.7.252, de la zone 0 (l'épine dorsale) :

22:29:04.906209 IP (tos 0xc0, ttl 1, id 22064, offset 0, flags [none], proto OSPF (89), length 64) 192.134.7.252 > 224.0.0.5: OSPFv2, Hello, length: 44
        Router-ID: 192.134.7.252, Backbone Area, Authentication Type: none (0)
        Options: [External]
          Hello Timer: 10s, Dead Timer 40s, Mask: 255.255.255.240, Priority: 1
          Designated Router 192.134.7.252

Sur un réseau à diffusion comme Ethernet, un routeur est élu routeur principal (Designated Router, DR, section 7.3 mais l'algorithme d'élection figure, lui, dans la section 9.4). Les adjacences ne se forment qu'avec lui et tous les échanges OSPF passent par lui (il existe aussi un routeur de secours, le BDR, Backup Designated Router, section 7.4).

La section 12 présente les paquets LSA (Link State Advertisement, ou annonces de l'état des liens), par lesquels les routeurs OSPF se tiennent au courant de leur situation. La section est très longue car il y a beaucoup d'informations possibles à transmettre !

Une fois que les routeurs ont toute l'information nécessaire, ils peuvent faire tourner l'algorithme SPF de Dijkstra et calculer ainsi les routes, selon la procédure que décrit la section 16. (RIP utilisait Bellman-Ford.)

D'autres sections couvrent des parties plus « exotiques » du protocole, moins nécessaires en première approche.

La section 3 est consacrée au découpage en zones. (Notez toutefois que seuls les plus grands réseaux OSPF en ont besoin. Dans un document plus pédagogique, les zones auraient été reléguées à la fin.) Les routeurs d'une zone ne connaissent pas la topologie interne aux autres zones, seulement le moyen de joindre un routeur ABR (Area Border Router, section 3.3) attaché à cette zone. Les zones OSPF sont forcément attachées à une zone principale, numérotée 0 (section 3.1), qui sert d'épine dorsale au réseau.

La section 14 explique le mécanisme d'expiration des LSA dans la base (ils ne restent en effet pas éternellement).

La section 15 spécifie les liens virtuels qui permettent de connecter des parties physiquement disjointes d'une zone.

Les annexes B et C contiennent les paramètres d'OSPF, les valeurs numériques qui gouvernent le comportement du routeur. L'annexe B décrit les constantes, dont la valeur est fixe, comme MaxAge, la durée de vie maximale d'un LSA (fixée à une heure). L'annexe C contient les variables, que l'on peut modifier via la configuration du routeur (attention, il est souvent nécessaire que tous les routeurs du lien, ou bien tous les routeurs de la zone, soient d'accord sur la valeur). Par exemple, avec Quagga, on peut changer Interface output cost (le « coût » d'une interface réseau) en mettant dans le fichier ospfd.conf :

interface xxx0
  ! Ligne lente, son usage est découragé
  ip ospf cost 10000

L'annexe D est consacrée à l'authentification. OSPF trouvant ses voisins par diffusion, un routeur méchant peut assez facilement s'insérer dans un réseau et diffuser de fausses informations. Sur un réseau partagé par plusieurs organisations, par exemple un point d'échange Internet, il n'est pas rare de voir passer des paquets OSPF, émis, espérons-le, suite à une erreur de configuration et pas par malveillance. Pour éviter que les adjacences ne se forment entre deux voisins, OSPF permet d'utiliser un secret partagé que doivent connaitre les routeurs.

Il existe aujourd'hui deux mises en œuvre libres d'OSPF :

mais on trouve évidemment ce protocole dans tous les routeurs, des Cisco aux Juniper en passant par les Vyatta.


Téléchargez le RFC 2328


L'article seul

Exprimer le néant dans divers langages de programmation

Première rédaction de cet article le 7 mai 2008
Dernière mise à jour le 12 mai 2008


Tous (ou presque tous ?) les langages de programmation permettent de noter une donnée qui n'existe pas, le rien, le néant. Mais chacun utilise un symbole différent.

En SQL, c'est le NULL. Ainsi, un booléen en SQL est tri-valué : vrai, faux ou NULL. Cela agace prodigieusement certains théoriciens comme Date. Voici un exemple avec une valeur égale à NULL :


tests=> CREATE TABLE Data (Name TEXT,  Ready BOOLEAN);
CREATE TABLE
tests=> INSERT INTO DATA Values ('toto', false);
INSERT 0 1
tests=> INSERT INTO DATA Values ('tata', true);
INSERT 0 1
tests=> INSERT INTO DATA (Name) Values ('truc');
INSERT 0 1

tests=> SELECT * FROM Data;
 name | ready 
------+-------
 toto | f
 tata | t
 truc | 
(3 rows)

tests=> SELECT * FROM Data WHERE Ready IS NULL;
 name | ready 
------+-------
 truc | 
(1 row)

Et un exemple illustrant bien que NULL n'est ni vrai ni faux. La troisième ligne, avec le nom truc, n'apparaitra pas :


tests=> SELECT * FROM Data WHERE Ready;
 name | ready 
------+-------
 tata | t
(1 row)

tests=> SELECT * FROM Data WHERE NOT Ready;
 name | ready 
------+-------
 toto | f
(1 row)

PHP utilise également NULL.

Python utilise None. N'importe quelle variable peut prendre la valeur None. Par contre, Python est typé, même si c'est dynamiquement typé, et on ne peut pas effectuer n'importe quelle opération sur None :


>>> 2 + None
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

Si on essaie avec des booléns, None a un comportement qui peut être déroutant : il est quelque part entre True et False.


>>> x = True and False
>>> print x
False
>>> x = True and None
>>> print x
None
>>> x = False and None
>>> print x
False
>>> x = False or None
>>> print x
None

Perl utilise undef. N'importe quelle variable peut prendre cette valeur. Contrairement à Python, toutes les combinaisons sont possibles avec undef :

 % perl                            
print 2 + undef, "\n";
2

% perl
print 2  and undef, "\n";
2

Lisp utilise traditionnellement nil, qui sert aussi à noter le booléen Faux (merci à Emmanuel Saint-James pour son aide sur Lisp). #f qui sert à noter « faux » et uniquement « faux » a été introduit par Scheme, qui a supprimé la confusion qui existait dans Lisp sur ce sujet. La liste vide () convient aussi. Voici un exemple en Common Lisp :

; Renvoie Faux donc nil
> (or (= 2 3) (= 2 1))
NIL

> (or (= 2 3) (= 2 2))
T

; La liste vide est fausse
> ()
NIL

; On peut l'utiliser avec les opérateurs booléens
> (or (= 2 3) ())
NIL

> (or (= 2 2) ())
T

Pascal désigne les pointeurs invalides par nil. Pascal est statiquement et assez fortement typé et les variables des autres types n'ont pas de valeur nil possible. Ada est très proche de Pascal sur ce point, mais utilise null au lieu de nil.

Ruby utilise également nil.

Haskell est typé et ne permet pas de valeur « nulle » sauf si on utilise la monade Maybe qui permet d'avoir une valeur Nothing. Peu de fonctions sont définies sur les variables Maybe (à part tester si elles contiennent quelque chose et, si oui, quoi).

Visual Basic a le même terme, Nothing.

C utilisait traditionnellement 0, valable aussi bien pour les entiers, les caractères et les pointeurs. Aujourd'hui, la bonne pratique est plutôt d'utiliser la macro NULL.

À noter que les langues, pas seulement les langages de programmation, peuvent avoir ce souci de noter l'inexistence. Le lojban a zo'e pour cela. Pour dire « je parle en lojban », où il faut normalement spécifier le public et le sujet avant la langue utilisée, une des méthodes est d'indiquer les arguments manquants par zo'e donc, ici mi tavla zo'e zo'e la lojban.

Merci à Bertrand Petit pour sa suggestion originale.


L'article seul

Copier un sous-arbre d'un dépôt Subversion vers un autre dépôt

Première rédaction de cet article le 7 mai 2008


Le VCS Subversion s'est largement imposé comme la référence en matière de VCS centralisé, c'est-à-dire reposant sur un dépôt unique de données. Contrairement à son prédécesseur CVS, Subversion permet, par exemple, de déplacer facilement un fichier ou un répertoire à l'intérieur du dépôt, sans perdre l'historique. Mais ce déplacement n'est pas possible entre dépôts différents. Il existe une manipulation pour le faire mais elle nécessite quelques efforts.

Pour Subversion, le monde se réduit à un dépôt à la fois. Si on a un dépôt B (https://svn.nic.fr/ReD-AFNIC/Etudes dans l'exemple ci-dessous) et qu'on souhaite y importer des fichiers venus d'un dépôt A (svn+ssh://bortzmeyer@foobar.example.com/home/bortzmeyer/AFNIC-Subversion dans l'exemple ci-dessous), en gardant leur historique (donc, sans utiliser les fonctions d'importation classiques), la simple copie ne marche pas :

% svn copy svn+ssh://bortzmeyer@foobar.example.com/home/bortzmeyer/AFNIC-Subversion \
           https://svn.nic.fr/ReD-AFNIC/Etudes
svn: Source and dest appear not to be in the same repository (src: 'svn+ssh://bortzmeyer@foobar.example.com/home/bortzmeyer/AFNIC-Subversion'; dst: ' https://svn.nic.fr/ReD-AFNIC/Etudes')

La manipulation exacte est possible mais plus complexe. Il faut :

  • Copier le dépôt A sous forme d'un fichier texte. Il faut opérer sur le serveur (on accède directement aux fichiers) avec la commande svnadmin : svnadmin dump /home/bortzmeyer/AFNIC-Subversion > svn.dump
  • Filtrer le fichier texte de dump avec la commande svndumpfilter pour ne garder que le sous-arbre qui nous intéresse. Attention, le chemin à donner en paramètre est un chemin absolu dans le dépôt (ici, on garde trois sous-arbres, anycast, EPP et dDOS-February-2007). La commande utilisée est svndumpfilter include /RD/anycast /RD/EPP /RD/dDOS-February-2007 < svn.dump > svn-filtered.dump
  • Selon l'arborescence utilisée dans l'ancien et dans le nouveau dépôt, il peut être nécessaire d'éditer le fichier de dump pour changer les noms des répertoires (les champs Node-path et, s'il y eu des copies, par exemple des branches, les champs Node-copyfrom-path). Par exemple, si le fichier dump contient Node-path: IETF/Behave/tests-socket, et qu'on charge ce fichier dans le répertoire /ReD-AFNIC, le fichier résultant sera en /ReD-AFNIC/IETF/Behave/tests-socket. Ce changement peut se faire avec la fonction de rechercher / remplacer d'un éditeur ordinaire (les fichiers de dump de Subversion sont de simples fichiers texte) ou bien avec un outil comme sed ou perl.
  • De même, il peut être nécessaire de créer le répertoire où sera accroché le sous-arbre copié. Cette création peut se faire via une copie de travail (mkdir puis svn commit) ou bien directement dans le dépôt avec svn mkdir URL.
  • Copier le fichier résultant du filtrage sur le nouveau serveur (là encore, il faut pouvoir accéder aux fichiers) avec svnadmin : svnadmin load --parent-dir /ReD-AFNIC /home/Subversion-Repository < svn-filtered.dump. L'option --parent-dir permet d'indiquer à quel endroit on accroche le sous-arbre. Cette commande peut échouer partiellement et il est donc prudent de la tenter d'abord sur une copie du dépôt.

Les deux commandes svnadmin nécessitent d'avoir les droits pour accéder aux fichiers du dépôt Subversion, en lecture pour la première étape et en écriture pour la seconde. Par exemple, si le dépôt final n'est accessible qu'en HTTP et que les données sont propriétaires de l'utilisateur sous le nom duquel tourne le serveur HTTP (cet utilisateur est www-data par défaut sur une Debian), il faudra exécuter la commande sous l'identité de www-data par exemple avec sudo : sudo -u www-data svnadmin load ....

Si svnadmin load échoue avec un message du genre :

<<< Started new transaction, based on original revision 4
svnadmin: File not found: transaction '92-1', path '/ReD-AFNIC/Etudes/two'
    * adding path : ReD-AFNIC/Etudes/two ... %

c'est qu'un répertoire manque. Il faut, comme indiqué ci-dessus, changer les noms dans le fichier de dump ou bien créer le répertoire. C'est le point le plus délicat de la manipulation.

Une fois copié l'ancien dépôt, il est prudent de faire un svn delete sur cet ancien dépôt, pour éviter de continuer à l'utiliser par accident.

Quelques avertissements, enfin :

  • Si des fusions ou d'autres opérations qui dépendent du numéro de révision sont présentes dans l'ancien dépôt, elles ne seront pas forcément copiées correctement.
  • Les numéros des révisions ne sont pas conservés (puisqu'ils sont uniques par dépôt), mais les dates le sont. Résultat, l'ordre des révisions dans le nouveau dépôt n'est plus l'ordre chronologique.

Bref, pour résumer, cette manipulation n'est pas idéale. Avec Subversion, il vaut mieux réfléchir avant de mettre les fichiers dans des dépôts séparés, copier entre dépôts restera toujours un pis-aller !

Merci beaucoup à Kevin Grover pour ses explications détaillées sur la manipulation à faire, merci aussi à Les Mikesell pour des détails utiles. Je signale aussi le court article « Moving a Folder Across SVN Repositories ».

Blair Zajac me suggère qu'on peut aussi utiliser la propriété svn:externals de Subversion pour « copier » l'ancien dépôt sans réellement le fusionner (pas tout à fait ce dont j'avais besoin mais cette technique peut être utile dans d'autres cas).

Pour tester différentes idées, j'ai écrit un script shell qui réalise cette manipulation sur des dépôts « bidons ».


L'article seul

Le marchand de café

Première rédaction de cet article le 4 mai 2008


Vous aimez le café ? Comme moi, comme les informaticiens, vous en buvez plusieurs fois par jour ? Cela vous aiguise l'esprit et vous rend plus efficace ? Alors, vous êtes comme Miguel Lienzo, le héros du roman « Le marchand de café » de David Liss.

Miguel est marchand à Amsterdam au 17ème siècle, lors d'un des moments de plus grande splendeur de la ville, où se développe le lieu de travail de Miguel, la Bourse, où se vendent les premiers contrats à terme, où les Juifs portugais comme Miguel bénéficient d'une relative liberté. La Bourse est un univers impitoyable, Miguel a des dettes, a provoqué la colère d'un homme important, et va tenter d'utiliser le café, que pratiquement aucun européen ne boit encore, pour « se refaire »...

Argent, amour, trahison, récits de voyages, navires chargés de riches cargaisons, rien ne manque à cet excellent roman de vacances.


L'article seul

Fiche de lecture : The power of ideas - Internet governance in a global multi-stakeholder environment

Auteur(s) du livre : Wolfgang Kleinwächter (éditeur)
Éditeur : Germany land of ideas
Publié en 2007
Première rédaction de cet article le 4 mai 2008


Ce livre est un recueil d'articles produits par différents acteurs de la gouvernance Internet un peu partout dans le monde. On n'y trouvera aucune unité, chacun a juste dévelopé un thème qui lui tenait à cœur (comme Latid Latif expliquant qu'IPv6 va sauver le monde). Il n'y a pas non plus grande originalité dans un livre où la plupart des auteurs avaient déjà eu de nombreuses occasions de faire connaitre leur point de vue.

Les articles sont courts et il y a peu de questions originales traitées. Le spectre des idées politiques est large, personne n'a été oublié, ce qui fait qu'un article d'Anriette Esterhuysen de l'APC, qui appelle à l'intervention publique pour s'assurer que tous les citoyens sont connectés, et qui met en garde contre les extensions des privilèges des titulaires de propriété intellectuelle est immédiatement suivi d'un article de George Sadowsky, de l'ISOC, qui explique que seul le Dieu Marché doit être autorisé à intervenir et qu'il est crucial de maintenir et d'étendre les droits déjà exorbitants dont jouissent les titulaires de propriété intellectuelle.

La plupart des articles n'apprendront rien à celui qui a déjà un peu étudié la gouvernance Internet, d'autant plus que la langue de bois est fort active (articles de Vint Cerf ou de Hamadoun Touré). Seuls quelques auteurs se sont aventurés hors de leur domaine habituel (comme Louis Pouzin qui écrit sur les identités numériques).


L'article seul

RFC 5225: RObust Header Compression Version 2 (ROHCv2): Profiles for RTP, UDP, IP, ESP and UDP Lite

Date de publication du RFC : Avril 2008
Auteur(s) du RFC : G. Pelletier, K. Sandlund (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF rohc
Première rédaction de cet article le 2 mai 2008


ROHC est un mécanisme de description des compressions possibles des en-têtes des paquets IP. Ce RFC décrit les profils de compression qui peuvent être utilisés pour un certain nombre des protocoles les plus courants (la définition de ROHC lui-même étant dans le RFC 5795, la section 3 de notre RFC fait quelques rappels).

Mettant à jour les RFC précédents, le RFC 3095, mais aussi les RFC 3843 et RFC 4019, ce RFC est l'état de l'art en ce qui concerne la compression d'en-têtes. La principale innovation est l'utilisation du langage formel ROHC-FN du RFC 4997 (la section 4.2 résume les principaux changements).

Le gros du RFC commence avec la section 5 qui expose les principes de chaque profil. Un canal ROHC relie un compresseur et un décompresseur. Le compresseur indique les changements par rapport aux prévisions, l'absence de changements signifiant au décompresseur qu'il peut appliquer la règle par défaut. Les systèmes de compression en réseau doivent toujours faire un compromis entre la robustesse (qui nécessite de la redondance, donc de ne pas trop comprimer) et l'efficacité (qui impose de supprimer toute la redondance). Voir par exemple la section 5.1.2, qui discute ce compromis.

Enfin, la section 6 contient les profils eux-mêmes, exprimés en partie en ROHC-FN. Cette section contient des fonctions de compression et les règles ROHC-FN qui les utilisent. Parmi les fonctions primitives, qui ne sont pas en ROHC-FN, la section 6.6.6 (fonction inferred_ip_v4_length) dit comment comprimer la champ Length d'IPv4. Étant déductible de la longueur du datagramme, il n'est pas indispensable et peut donc être comprimé à une taille de... zéro bits. La section 6.6.9 décrit une méthode bien plus complexe (fonction timer_based_lsb) pour les champs dont la valeur change approximativement en fonction linéaire du temps (elle nécessite donc que les horloges du compresseur et du décompresseur ne dérivent pas trop l'une par rapport à l'autre).

Un exemple en ROHC-FN est au contraire la définition de la fonction scaled_ts_lsb (qui sert pour RTP), qui s'exprime ainsi :

scaled_ts_lsb(time_stride_value, k)
{
  UNCOMPRESSED {
    timestamp [ 32 ];
  }

  COMPRESSED timerbased {
    ENFORCE(time_stride_value != 0);
    timestamp =:= timer_based_lsb(time_stride_value, k,
                                  ((2^k) / 2) - 1);
  }

  COMPRESSED regular {
    ENFORCE(time_stride_value == 0);
    timestamp =:= lsb(k, ((2^k) / 4) - 1);
  }
}

L'annexe A est une excellente étude des en-têtes de divers protocoles, avec une classification de leur comportement, selon qu'il permet la compression ou pas. C'est une lecture recommandée pour tous ceux qui s'intéressent à la compression d'en-têtes mais n'ont pas envie de relire le RFC original du protocole. Ils trouveront résumées de façon claire les caractéristiques de chaque champ de l'en-tête. Par exemple, pour IPv6 (annexe A.2) :

  • Version is STATIC-KNOWN c'est-à-dire constante pour toute la durée du flot et à une valeur « bien connue », en l'occurrence 6.
  • Hop Limit est RACH (RArely CHanging), c'est-à-dire changeant rarement (ce nombre ne bouge que lorsque les routes sont modifiées)
  • Source Address est STATIC-DEF, c'est-à-dire constant pour toute la durée du flot et pouvant d'ailleurs servir à définir le flot.

Il n'existe apparemment pas d'implémentation libre de ROHC. Mais plein de déploiements sont déjà faits dans les téléphones portables. La thèse d'Ana Minaburo contient une bonne introduction à ROHC.


Téléchargez le RFC 5225


L'article seul

État actuel du Linux Driver Project

Première rédaction de cet article le 26 avril 2008


Un rapport de Greg Kroah-Hartman publié sur lwn.net le 7 avril fait le point sur l'état du Linux Driver Project (LDP), un projet qui vise à augmenter le nombre de pilotes de périphériques pour le noyau Linux. Ce rapport est très optimiste, est-ce justifié ?

Greg Kroah-Hartman résume la situation ainsi :

  • Linux a déjà plus de pilotes que n'importe quel autre noyau dans l'histoire.
  • Il n'y a pratiquement plus de matériel non géré par Linux.
  • Le LDP a peu de travail car presque tout se fait tout seul sans lui.

Tout le monde partage t-il cette vision optimiste ? Non, comme le montre, par exemple, la discussion qui a suivi sur le site. Les remarques critiques les plus fréquentes concernent les performances et l'étendue des fonctions gérées. Par exemple, dans certains cas, le pilote Linux ne fait que du polling et délivre donc des performances inférieures au pilote Windows qui accepte les interruptions. Ou bien le pilote Linux ne gère pas telle ou telle fonction comme la 3D pour une carte graphique. Dans les deux cas, un Linuxien zélé peut dire « Ce matériel fonctionne sous Linux » alors qu'il marche moins bien que sous Windows.

Mais Greg Kroah-Hartman oublie également d'autres problèmes fréquents :

  • Le pilote est parfois moins fiable que sous Windows (le serveur X sur ma machine de bureau gèle de temps en temps complètement, avec le pilote libre de la carte nVidia NV18 GeForce4 AGP, ce qui ne semble pas arriver avec le pilote non-libre).
  • Le pilote est bien disponible dans le noyau Linux, par exemple il a été accepté dans le dépôt git d'Andrew Morton mais il n'a pas encore atteint les utilisateurs ordinaires, qui ne compilent pas eux-même leur noyau à partir d'un dépôt git, mais dépendent d'un système d'exploitation stable, pas toujours ultra-récent. Dans le monde des PC, où les changements sont très rapides, ce problème est un des plus fréquents. Sur le dernier PC que j'ai acheté neuf chez Darty, ni la carte Ethernet gigabit Realtek RTL8111/8168B PCI, ni la carte graphique Intel Q33/Q35/G33 n'étaient reconnues par une Debian stable, alors qu'un noyau Linux récent installé à la main les accepte. Mais beaucoup d'utilisateurs n'ont pas envie de faire une telle manipulation.
  • Enfin, certains pilotes sont non libres et le matériel ne fonctionne que si l'utilisateur accepte de se retrouver, comme sur Windows et sur MacOS, avec un logiciel privateur. Parfois, le logiciel se prétend libre mais charge du code non libre présent sous forme d'un gros fichier binaire.

Greg Kroah-Hartman, pour mieux appuyer sa démonstration, ne parle que du noyau proprement dit et « élimine » les cartes graphiques, une source fréquente de problèmes, car leurs pilotes sont en général dans X.Org, pas dans le noyau, et les scanneurs et imprimantes, pour la même raison.

Donc, on ne peut certainement pas dire que la situation des pilotes de périphérique avec Linux soit aussi rose que la peint cet article. Mais la faute à qui s'il y a tant de problèmes ? Il faut se rappeler que l'origine du mal n'est pas à chercher du côté des développeurs Linux comme Greg Kroah-Hartman, mais plutôt du côté des entreprises qui ne produisent pas de documentations pour leurs matériels, ou bien exigent la signature de NDA pour y avoir accès, quant elles ne refusent pas purement et simplement tout pilote libre, de peur que la lecture du source ne révèle comment fonctionne leur matériel.


L'article seul

Assurer l'authenticité des données stockée dans une DHT

Première rédaction de cet article le 22 avril 2008


Les DHT sont un moyen entièrement pair-à-pair de stocker de l'information dans le réseau. Leur force est la résistance aux attaques, leur faiblesse le fait qu'on ne puisse pas garantir l'authenticité des données stockées, puisque le mécanisme classique de « faire confiance au serveur qui fait autorité », utilisé par exemple pour le DNS, ne s'applique pas aux DHT où on ignore même sur lequel des milliers de serveurs de la DHT nos précieuses données seront stockées.

Il faut donc utiliser la cryptographie et signer les données.

Voici donc un protocole possible, suivi de son application au service OpenDHT. L'expérience prouve largement que les amateurs (et même parfois les professionnels) ne voient jamais les failles de sécurité des protocoles cryptographiques qu'ils conçoivent : les critiques sont donc les bienvenues.

Pour éviter les collisions sur le mot « clé », je ne l'utilise que pour la clé cryptographique. Je nomme « nom de l'attribut » (ou index) l'« endroit » où on veut stocker et « valeur de l'attribut » la chose qu'on veut stocker.

Chaque entité qui veut stocker des trucs dans la DHT a une clé cryptographique asymétrique. Pour un protocole comme HIP (RFC 5201), la clé serait le HI (Host Identifier).

  • Avant d'écrire, l'entité concatène la partie publique de sa clé et le nom de l'attribut.
  • Elle hache le résultat et ça donne un index de la DHT.
  • Elle écrit à l'index deux valeurs, la valeur proprement dite et une signature cryptographique.
  • L'entité qui lit connait la clé publique et connait le nom de l'attribut. Elle peut donc reproduire les deux premières étapes. Elle lit alors la donnée et et peut vérifier la signature.

Notez qu'on n'a pas dit comment on connaissait les clés publiques de ses partenaires. Le mécanisme pour cela est en dehors de ce protocole.

Les failles que je vois pour l'instant :

  • Une donnée écrite, puis supprimée peut être rejouée par un pair méchant (ou par un sniffer car je ne suis pas sûr qu'OpenDHT permette du https). Il faudrait un système d'horloge logique pour éviter cela.
  • Il doit y en avoir beaucoup d'autres !

Voici une mise en œuvre possible en Python. J'utilise la bibliothèque pyme pour signer en OpenPGP.

Le programme qui écrit la donnée, d'abord. Il s'utilise ainsi :

% python put.py -k 82AEEF63  quelquechose.example.org 192.0.2.42

La ligne ci-dessus stocke la valeur 192.0.2.42 dans la DHT, indexée par le nom quelquechose.example.org, en signant avec la clé OpenPGP 0x82AEEF63. Il fabrique les deux noms (celui composé de la clé et de l'attribut et celui qui sert à stocket la signature) :

key = Binary(sha.new(pgp_key + attribute).digest())
key_for_sig = Binary(sha.new(pgp_key + attribute + ".SIGNATURE").digest())

puis écrit dans la DHT :

proxy.put(key, bin_value, ttl, "put-authentic.py")]
proxy.put(key_for_sig, Binary(signature), ttl, "put-authentic.py")

Le programme qui lit les données vérifie les signatures. Il s'utilise ainsi :

%  python get.py -k 82AEEF63  quelquechose.example.org

À noter que rien n'empêche plusieurs écritures sur le même nom (les attributs sont multi-valués dans OpenDHT) donc le programme doit boucler sur tous les résultats obtenus. Autrement, il fait simplement l'inverse du programme d'écriture :

signatures, pm = proxy.get(key_for_sig, maxvals, pm, "get-authentic.py")
vals, pm = proxy.get(key, maxvals, pm, "get-authentic.py")

Si un méchant a essayé d'insérer de fausses données, cela se voit tout de suite (rappelons qu'on ne peut pas empêcher cette insertion, juste la détecter a posteriori) :


% python get.py -k 82AEEF63   quelquechose.example.org

Good signature from:
  uid:         OpenDHT Authenticity Test (Test only, not a real user) <stephane+opendht@sources.org>
Value is "192.0.2.42"

BAD signature from:
  uid:         OpenDHT Authenticity Test (Test only, not a real user) <stephane+opendht@sources.org>
Value is "102.0.2.42"


L'article seul

RFC 4034: Resource Records for the DNS Security Extensions

Date de publication du RFC : Mars 2005
Auteur(s) du RFC : R. Arends (Telematica), R. Austein (ISC), M. Larson (Verisign), D. Massey (Colorado State University), S. Rose (NIST)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 22 avril 2008


Complétant la série des RFC sur DNSSEC, ce RFC 4034 décrit les types d'enregistrements utilisés par ce protocole, DNSKEY, RRSIG, DS et NSEC.

DNSSEC, décrit dans les RFC 4033 et RFC 4035, permet de signer cryptographiquement les enregistrements DNS de façon à garantir leur authenticité. Pour cela, DNSSEC ne modifie pas le format des paquets DNS, mais il ajoute plusieurs types d'enregistrement nouveaux. Notre RFC fait partie de la série de RFC qui décrit DNSSEC-bis (la première version de DNSSEC, assez différente, n'ayant eu aucun succès) et il succède au RFC 2535.

La plupart des exemples ci-dessous ont été obtenus pour la zone sources.org qui est désormais signée. Vous pouvez interroger en DNSSEC ses serveurs de noms (dig NS sources.org. vous en donnera la liste).

Chacun des nouveaux types d'enregistrement va faire l'objet d'une section. La section 2 est consacrée à DNSKEY, les clés publiques des zones. Un de ces enregistrements stocke notamment l'algorithme de chiffrement utilisé et la clé. La représentation texte officielle (chaque type d'enregistrement DNS a une représentation binaire, utilisée sur le câble, et une représentation texte, utilisée par exemple dans les fichiers de zone de BIND), décrite en section 2.2, affiche la clé encodée en Base64 :

sources.org.                        86400   DNSKEY  256 3 3 (
   CL9vwM+5gCMZdycMOYJQ7lSspHDTsaZmZkDR
   l+KNx/VytmbPSfcdYmhJJHyTdGpzqXmm6qEd
   4Kpyqbd59RXv9JCVVM3MntiX/hruxbB3WsV0
   hlVej1IuWFDncJFLWhaD9UjgGm+UoqlQJGVJ
   rGZf7KvwL4iKZhr1fiDEJFD7e9cxU8dojhHp
   mmAOZLjEYKytDMB0rj8/Mnm5cVVu29UFS+0y
   jvkdbQD0EJ9FwF/8MwG4DHj6ZtFwxeNp2NCD
   6oj0kxDi5ktY0rQtSv506aAMmGBqS6tNno+g
   9KgCLZ5jk5e8fpl9Rlmd2SlVMAyf8E3C9joB
   ZqCqYX+VcooSrcvgn/4m6CTDPxK+DuE+KW5/
   NiE062MKdID7xAxiCj14Suj9K9TKL60buuFa
   gJ3qTjhS5C62uPk8U9+zHpQ0qjcb0gv3/M+l
   RcXi46g0OF17cTLy83lgU6s2ApMmaboeUbm2
   3lfCEl8B6R2BhE98mfoDNg+Xlj63X8w93LCo
   XP/c1SZivNolol/Ky6apULe3euFuwdOFfYCR
   ) ; key id = 55957

Ici, la clé 55957 utilise DSA/SHA-1 (valeur 3). Ces clés peuvent être générées, par exemple, par le programme dnssec-keygen, qui fait partie de BIND. Bien lire la liste des algorithmes utilisables pour une zone dans l'annexe A.1 sinon, on aura un message du genre a key with algorithm 'HMAC-SHA256' cannot be a zone key.

Les enregistrements RRSIG sont le cœur de DNSSEC, puisqu'ils stockent les signatures des autres enregistrements. Ce sont les RRSIG que vérifie un validateur DNSSEC. Un enregistrement RRSIG contient notamment :

  • le type de l'enregistrement couvert par la signature,
  • l'algorithme de chiffrement utilisé (la liste des algoritmes possibles à l'origine figure dans l'annexe A.1 et la liste actuelle est maintenue par l'IANA),
  • les dates de signature et d'expiration,
  • la signature elle-même.

Sous la forme texte décrite en section 3.2, voici un tel enregistrement :

laperouse.sources.org.  86400   IN MX   10 aetius.bortzmeyer.org.
                        86400   RRSIG   MX 3 3 86400 20080522104407 (
                                        20080422104407 55957 sources.org.
                                        CIxBOzsaxBexcAQQE1ukqNfBz5yDnPBVhgxr
                                        MNR7FrfM2iH/AOWoO/8= )

Ici, ce RRSIG signe un MX.

La section 4 est consacrée à NSEC, un type d'enregistrement qui va résoudre un problème délicat, la « preuve de non-existence ». En effet, DNSSEC fonctionne en joignant une signature aux enregistrements existants, ce qui permet de prouver leur existance. Mais si un nom n'existe pas et que le serveur veut renvoyer NXDOMAIN (No Such Domain) ? On ne peut pas signer un enregistrement qui n'existe pas. La solution DNSSEC est de créer des enregistrements NSEC qui sont signés et qui indiquent l'enregistrement suivant (l'ordre est défini dans la section 6, c'est simplement l'ordre des codes ASCII). Ainsi, si je demande nexistepas.example.org et que je récupère :

lulu.sources.org.    43200   IN      NSEC    patou.sources.org. AAAA RRSIG NSEC

je sais que nexistepas.sources.org n'existe pas, puique le NSEC ci-dessus me garantit qu'il n'y a rien entre lulu et patou.

Un autre type d'enregistrement permettant la « preuve de non-existence », le NSEC3, est décrit dans le RFC 5155. En effet, le NSEC a un gros inconvénient, il permet l'énumération complète de la zone, en suivant simplement les NSEC. Cette faiblesse des NSEC est une des raisons pour lesquelles DNSSEC n'a pas été d'avantage déployé.

C'est très bien de signer sa zone mais ensuite, comment les résolveurs partout dans le monde vont-ils connaitre sa clé ? Ils ont pu l'obtenir par un autre moyen et la mettre dans leur configuration (ce qu'on nomme une trust anchor). Mais un tel mécanisme ne se généralise évidemment pas à tout l'Internet. Il faut donc un seul trust anchor, la clé de la racine, et un système de délégations. Ces délégations sont mises en œuvre par les enregistrements DS, décrits en section 5. Ces enregistrements contiennent un condensat cryptographique de la clé :

sources.org.            IN DS 55957 3 1 A12F149F84B34E09501C32CC9F984FB9E1ED196A

Ici, 55957 est l'identité de la clé, 3 l'algorithme de la clé et 1 celle du condensat (SHA-1, la liste complète est maintenue par l'IANA).


Téléchargez le RFC 4034


L'article seul

RFC 5205: Host Identity Protocol (HIP) Domain Name System (DNS) Extensions

Date de publication du RFC : Avril 2008
Auteur(s) du RFC : P. Nikander (Ericsson), J. Laganier (DoCoMo)
Expérimental
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 21 avril 2008


Le protocole HIP n'avait pas encore de mécanisme pour trouver l'identificateur d'une machine distante. C'est désormais chose faite grâce à ce RFC qui permet de trouver l'identificateur dans le DNS (RFC qui a depuis été remplacé par le RFC 8005).

HIP fait partie de la famille des protocoles qui visent à séparer l'identificateur du localisateur. Les identificateurs HIP se nomment les HI (Host Identifier) et, jusqu'à présent, le seul moyen de trouver l'HI d'une autre machine était d'attendre qu'elle vous contacte, ou bien de le configurer manuellement. Désormais, avec ce RFC, on peut trouver l'HI, comme une adresse IP, dans le DNS.

Notre RFC crée donc un nouveau type d'enregistrement DNS, nommé logiquement HIP, qui stocke, en échange d'un nom de domaine, le HI, son résumé cryptographique - le HIT (Host Identifier Tag) - et les éventuels serveurs de rendez-vous, serveurs qui, dans le protocole HIP, servent d'intermédiaires facultatifs lorsqu'on veut contacter une machine distante (cf. RFC 5204).

Notre RFC permet de trouver l'identificateur à partir du nom mais pas le localisateur ; les serveurs de rendez-vous sont une solution possible pour cela ; une autre est d'utiliser les traditionnels enregistrements A et AAAA du DNS, le localisateur HIP étant une adresse IP.

Curieusement (pour moi), le HIT est donc stocké dans les données DNS, alors que celles-ci n'offrent aucune sécurité au point que le RFC exige en section 4.1 de recalculer le HIT qui vient d'être obtenu dans le DNS.

Le tout ressemble donc aux enregistrements IPSECKEY du RFC 4025, ce qui est normal, le HI étant une clé cryptographique publique.

Voici un exemple d'enregistrement HIP tel qu'il apparaitrait dans le fichier de zone de BIND. On y trouve l'algorithme cryptographique utilisé (2 = RSA), le HIT (en hexadécimal), le HI (encodé en Base64) et les éventuels serveurs de rendez-vous (ici, deux, indiqués à la fin) :

www.example.com.      IN  HIP ( 2 200100107B1A74DF365639CC39F1D578
                                AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p
9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQ
b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
                                rvs1.example.com.
                                rvs2.example.com. )

L'ensemble du RFC est assez court, ce mécanisme d'annuaire qu'est le DNS étant simple et bien connu.


Téléchargez le RFC 5205


L'article seul

RFC 5204: Host Identity Protocol (HIP) Rendezvous Extension

Date de publication du RFC : Avril 2008
Auteur(s) du RFC : J. Laganier (DoCoMo), L. Eggert (NEC)
Expérimental
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 21 avril 2008


HIP, par défaut, nécessite que l'initiateur d'une association connaisse le localisateur, l'adresse IP du répondeur. Si celui-ci bouge souvent, et qu'il n'est donc pas pratique de mettre cette adresse dans le DNS, une solution est d'utiliser le mécanisme de rendez-vous, décrit par ce RFC, où l'initiateur contacte un serveur de rendez-vous qui relaie vers le répondeur. (Ce RFC a depuis été remplacé par le RFC 8004.)

Le schéma est clairement expliqué dans la section 3 du RFC. En fonctionnement habituel de HIP, l'initiateur trouve l'identificateur et le localisateur du répondeur (typiquement, dans le DNS, cf. RFC 5205), puis le contacte directement. Si le localisateur n'est pas connu (ce qui est fréquent si le répondeur est un engin mobile, changeant souvent d'adresse IP), l'initiateur envoie le premier paquet (I1) au serveur de rendez-vous, qui le relaie au répondeur. Les autres paquets (R1, I2 et R2) seront transmis directement entre les deux machines HIP. Le mécanisme est détaillé dans la section 3.3 (il faut notamment procéder avec soin à la réécriture des adresses IP, en raison entre autre du RFC 2827).

Et comment l'initiateur trouve t-il le serveur de rendez-vous ? En général dans le DNS, via les enregistrements de type HIP. Et comment le répondeur avait-il fait connaitre au serveur de rendez-vous son adresse IP ? Via le protocole d'enregistrement du RFC 5203, comme l'explique la section 4.


Téléchargez le RFC 5204


L'article seul

RFC 5201: Host Identity Protocol

Date de publication du RFC : Avril 2008
Auteur(s) du RFC : R. Moskowitz (ICSAlabs), P. Nikander, P. Jokela (Ericsson Research NomadicLab), T. Henderson (The Boeing Company)
Expérimental
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 21 avril 2008


HIP, décrit dans ce RFC, est un protocole très ambitieux, puisqu'il vise à compléter IP en fournissant une séparation de l'identificateur et du localisateur, permettant d'améliorer la sécurité (notamment la résistance aux DoS) et de mieux gérer la mobilité et le multi-homing. La version 1, décrite dans ce RFC, a depuis été remplacée par la v2, dans le RFC 7401.

L'architecture générale de HIP est décrite dans le RFC 9063. Notre RFC normalise, lui, le protocole concret. HIP repose d'abord sur la séparation entre un nouvel identificateur, le HI (Host Identifier) et un localisateur, plus concret, qui sera simplement l'adresse IP, réduite à un rôle moins visible, sans exigence de stabilité. Par exemple, HIP permettra le changement de localisateur (d'adresse IP) en cours de connexion, sans rompre celle-ci, ce qui sera précieux pour la mobilité.

HIP est donc déployable uniquement en modifiant les machines terminales du réseau (si les coupe-feux le laissent passer), sans toucher aux routeurs. Il en existe des mises en œuvres pour FreeBSD et Linux. Le projet OpenHIP adapte également des logiciels comme Wireshark pour qu'ils aient un support HIP. InfraHIP travaille également à l'infrastructure HIP. L'article HIP Implementation for FreeBSD donne des détails intéressants sur la mise en œuvre de HIP, notamment sur les questions liées à l'API.

Si on ne veut pas lire le RFC 9063, on peut néanmoins avoir une bonne introduction à HIP en lisant les sections 1 et 2 de ce RFC. Elles expliquent le vocabulaire (par exemple, HIP, étant un protocole situé en haut de la couche 3 n'utilise pas le terme de connexion mais celui d'association), le nouvel espace de nommage et les principes du protocole.

L'espace de nommage fait l'objet de la section 3. On distingue les HI (Host Identifier), qui sont des clés publiques d'un couple clé privée / clé publique et qui sont de taille variable, et les HIT (Host Identifier Tag, décrits dans la section 3.1), qui sont un résumé cryptographique des HI. Ils sont de taille fixe (donc plus faciles à traiter), 128 bits, la taille d'une adresse IPv6. Un préfixe ORCHID (RFC 4843), le 2001:10::/28, sert à éviter toute collision avec les « vraies » adresses IPv6. Avec OpenHIP, la clé peut être générée par le programme hitgen qui fabrique un fichier XML ressemblant à ceci :


<?xml version="1.0" encoding="UTF-8"?>
<my_host_identities>
  <host_identity alg="RSA" alg_id="5" length="128" anon="no" incoming="yes" r1count="10">
    <name>horcrux-1024</name>
    <N>C6EBA2894C33A1312B38853A8ECC0D7967496237A65529807EDF23C4DA753EE88F8FBF71BE38B6910181D5B75DB075B9962326D9BB50C65121DBFD712F1B7F4E2B035953AD650EB5C96B56295FE2731B3B36E8AFED7FB5CD48B73C31A224D4CE4F097D84888EC2E3CA8F3A78939D89B7BCFC5E6DEEAF670695349BFFFE8445F1</N>
    <E>010001</E>
    <D>383A51165838DBDE872611DACC94775692D09677BE87A214954843D7181D3E2C04B0905FF9721481069909AD2C497DED78B7F4FA64CD5F517DADAE8538D89FF21B0498A72F1132545328ABD371B1BAC8ED46441D900921523B78BA55F3FC227F432F2061C92CE9665CB99C1CF425AA90CFC6345FA4E7DA43E477EAF69F86A801</D>
    <P>FF03F93454C9C2D8EC47FE8C9DBF0D82F05E13905F304A5ACA42C45E579F917B4C8CEFEF6B06AAB9BCB7A911D5514B7AEE685DA91E7CC60DDC4C37BA94A22E71</P>
    <Q>C7B0394EB5506B2B75E19E5654262E843659BB76A465C2A7AC47A430749944378E3161FF805B4C6CB037B5CB111F0EF49FF03047FB1CFC51DC0D72DEDAD64F81</Q>
    <dmp1>7426C128DEBD8EEBF2A2D004080D6F0006AF32C5FD352788B6BB3669AA0B59DE08FDE082F202755C67E25735722DB6ED650D502BA961376C34BCDA5D3739AF61</dmp1>
    <dmq1>1B97DE5361FA9AD4869586ABA7351F78658A40BD443A4B8B9FE2C66D6BAF421DEB2827C2869A17156DC444FAAA83002E0D6BC3402F12F24ADD7D7E420D3B5001</dmq1>
    <iqmp>7499A27F59CA1746F1A6E5DE832592F8ACF80B814DD511C490614C44DC92B5CD1650AC944ED5751F28846487C221E8C17E68264DFEF748B86E38EB1F238D94A9</iqmp>
    <HIT>2001:1f:cd4:7125:2427:f77c:d1b6:e15f</HIT>
    <LSI>1.182.225.95</LSI>
  </host_identity>
</my_host_identities>

Notez bien que le fait d'utiliser XML est un choix de OpenHIP, qui n'est utilisé qu'en local. Il n'est pas imposé par la norme qui, sur le câble, n'utilise que du binaire. Les éléments comme P, Q ou iqmp sont les éléments d'une clé RSA (HIP peut utiliser d'autres formats que RSA). Le HIT est représenté en utilisant la syntaxe des adresses IPv6, puisqu'il a la même taille et a été conçu pour être stocké comme une adresse par les applications.

La section 3.2 explique comment générer un HIT à partir du HI. Étant un résumé cryptographique (fait avec SHA-1), il est sûr, on ne peut pas fabriquer facilement un HI qui aurait le même HIT.

Pour signer les paquets, les deux machines utiliseront au début un échange de Diffie-Hellman.

La section 4 donne une vision générale du protocole, qui sera ensuite détaillée dans les sections ultérieures. HIP a reçu le numéro de protocole 139.

La section 4.1 décrit comment former une association entre deux machines HIP. Celle qui demande l'association est nommée l'initiateur, celle qui l'accepte le répondeur. Le protocole d'association nécessite quatre paquets. En effet, avec seulement trois paquets, comme le fait TCP (RFC 793) lors de l'établissement d'une connexion (Three-way handshake), on ne peut pas à la fois se protéger contre les DoS et permettre des options par connexion. Se protéger contre les DoS nécessite de ne pas garder d'état tant que le pair n'est pas authentifié, même faiblement. Les techniques qui permettent à TCP de ne pas garder d'état sur le « répondeur », telles que les SYN cookies du RFC 4987 sont incompatibles avec les options TCP.

Voici pourquoi les protocoles plus récents comme SCTP (RFC 3286) ou comme HIP nécessitent quatre paquets.

Dans HIP, ils sont nommés I1, R1, I2 et R2. Les paquets I sont envoyés par l'initiateur et les paquets R par le répondeur.

L'établissement d'une association se passe donc comme ceci :

  • L'initiateur envoie I1 au répondeur. Le paquet contient l'identificateur (le HIT) de l'initiateur et (optionnellement) celui du répondeur. Aucun état n'est créé chez le répondeur.
  • Le répondeur envoie R1. Ce paquet contient un puzzle cryptographique que l'initiateur devra résoudre. Il contient également les paramètres de la session Diffie-Hellman. Et ce paquet est signé.
  • L'initiateur envoie I2, qui contient la solution du puzzle. les paramètres Diffie-Hellman de l'initiateur. Ce paquet est signé.
  • Le répondeur envoie R2 pour accepter l'association. Ce paquet est signé.

Le puzzle, détaillé en section 4.1.1, est un petit problème de calcul que l'initiateur doit résoudre pour montrer qu'il est près à « payer », à faire un effort pour que l'association soit acceptée. La difficulté du puzzle peut être réglée par le répondeur. En pratique, il est très difficile d'imaginer un puzzle qui soit dissuasif contre des attaquants disposant d'un botnet entier, tout en étant soluble par des appareils simples, genre téléphone portable, ne possédant guère de puissance de calcul. (La section 4.1.1 détaille ce problème et les solutions possibles.)

La section 4.1.3 détaille l'utilisation du Diffie-Hellman.

Une des grandes forces de HIP est la possibilité de mettre à jour une association existante (section 4.2). À tout moment, pendant la session, un paquet de type UPDATE peut être envoyé pour changer certains paramètres de la session, comme les localisateurs (les adresses IP) utilisées. La signature des paquets permet de s'assurer que le paquet UPDATE est authentique.

La section 5 est longue car elle détaille le format, bit par bit, de tous les paquets échangés. Il y a huit types de paquets (section 5.3) comme I1, R1, I2, R2 ou comme UPDATE, présenté plus haut.

Enfin, la section 6 détaille le traitement des paquets, ce qu'il faut faire en les recevant, les erreurs et la façon de les gérer (règle simple : ne pas renvoyer de paquets HIP en cas d'anomalie, seulement des ICMP, et avec un débit limité, car on ne peut pas être sûr du pair s'il y a une erreur), etc.


Téléchargez le RFC 5201


L'article seul

Mon exposé à Sparkling Point sur les conséquences politiques des choix techniques

Première rédaction de cet article le 18 avril 2008


Lors de la réunion Sparkling Point du 17 avril, j'ai fait un exposé sur « Les conséquences politiques des choix techniques », suivant l'observation de Lawrence Lessig que « The code is the law » (l'architecture - d'un système technique - est la loi).

Je développe trois exemples, empruntés au monde de l'Internet, les politiques d'allocations d'adresses IP, la révision de la norme sur les noms de domaines en Unicode et les débats sur la nouvelle architecture de routage et d'adressage de l'Internet.

Les transparents de cet exposé sont visibles :


L'article seul

Persistent Personal Names for Globally Connected Mobile Devices

Première rédaction de cet article le 14 avril 2008


Il y a traditionnellement deux moyens de donner des noms à des engins connectés à un réseau (que ces engins soient des ordinateurs, des PDA, des téléphones, etc) : un système d'allocation hiérarchique comme le DNS et un système complètement local comme le NBP d'Apple ou comme le LLMNR du RFC 4795. Le premier est lourd, très chargé politiquement et administrativement et échappe aux contrôles des engins connectés. Le second ne marche que sur un réseau local et ne présente aucune sécurité (n'importe quelle machine peut dire qu'elle se nomme FileServer). Cet excellent article détaille un mécanisme qui permet des allocations locales, utilisables globalement, et sûres.

L'article Persistent Personal Names for Globally Connected Mobile Devices, de Bryan Ford, Jacob Strauss, Chris Lesniewski-Laas, Sean Rhea, Frans Kaashoek et Robert Morris (MIT) décrit leur système UIA (Unmanaged Internet Architecture). L'idée de base est de tenir compte des réseaux sociaux et du fait que les gens qui communiquent se rencontrent physiquement de temps en temps. Du fait de ce point de départ, UIA ne remplace donc pas toutes les fonctions du DNS. Le principe d'UIA est que chaque machine s'attribue un nom et que ce nom, pour être utilisable depuis une autre machine, nécessite une introduction, qui nécessite le rapprochement physique. Une fois l'identité de chaque machine apprise, elles peuvent s'éloigner, UIA maintient une correspondance entre l'identité et l'adresse IP actuelle, et diffuse cette correspondance aux autres machines connues (un tel système ne convient donc que pour des petits groupes, par pour tout l'Internet). Cette correspondance est authentifiée par cryptographie, comme dans HIP (RFC 9063).

Le système se généralise à d'autres utilisateurs, en indiquant le nom de ces autres utilisateurs. Si Bob a une machine nommée myPDA, Alice pourra, après introduction du groupe Bob, utiliser le nom myPDA.Bob.

Le protocole n'est pas purement théorique, une implémentation est disponible.


L'article seul

Les toilettes du pape

Première rédaction de cet article le 13 avril 2008


Dans ce film de César Charlone et Enrique Fernández, (El baño del papa dans la version originale), on fait beaucoup de vélo mais pas pour s'amuser comme le cadre parisien stressé qui se détend en faisant du Vélib'. Ici, on est dans la campagne uruguayenne et les cyclistes sont des contrebandiers, qui profitent des différences de prix entre l'Uruguay et le Brésil proche pour gagner quelques petits sous.

Pas de la contrebande de haute volée, avec des marchandises précieuses, encore moins d'armes ou de drogue, les héros du film transportent de l'huile, du sucre, parfois une bouteille de whisky. Il faut pédaler sur une piste difficile, parfois en pleine nature pour éviter les contrôles, il faut risquer la rencontre avec la douane qui confisque parfois les marchandises, selon son arbitraire.

Mais tout va changer, espèrent les habitants de Melo : le pape Jean-Paul II va venir faire un discours dans leur village et les voisins brésiliens ne vont pas manquer d'affluer par milliers. Tout le village se met donc au travail pour valoriser cette visite papale. La plupart créent des stands de nourriture ou de boisson, mais un des contrebandiers a une meilleure idée. Il va installer des toilettes et faire payer très cher leur usage.

Tous investissent leurs maigres économies, empruntent à la banque, vendent leur outil de travail (leur vélo) pour investir dans ce grand projet. Les quantités de nourriture achetées sont énormes, alors qu'on ne connait que la future affluence que ce que promet la télévision locale. Non seulement ils prennent des risques à se faire pâmer les propagandistes du MEDEF, qui n'ont jamais vus de tels risquophiles, mais ils travaillent comme des fous pendant des jours, dans l'espoir de gagner un peu plus.

Je ne vous dis pas la fin, mais ceux qui ont déjà vus des films latino-américains se doutent que cela se terminera moins bien que dans les films états-uniens, où l'esprit d'entreprise est toujours récompensé.


L'article seul

Mettre à jour NetBSD

Première rédaction de cet article le 13 avril 2008
Dernière mise à jour le 1 octobre 2009


Après des années passées à administrer des machines Debian où la mise à jour vers une nouvelle version du système est simple et marche à (presque) tous les coups, passer un ordinateur NetBSD de la version 3 à la version 4 est un amusant retour en arrière, comme de faire un stage dans une île déserte avec juste un briquet et un couteau.

La machine est une Sun UltraSparc 10. Elle était en NetBSD 3.1 et vient de passer en NetBSD 4 puis, avec la même méthode, en NetBSD 5. Ce que j'ai fait, sur les excellents conseils de Mark Weinem :

  • Vérifier que tout était en place pour rattraper un éventuel problème. Sauvegarde des choses importantes, test de la liaison série avec la console (une session minicom sur une autre machine Unix).
  • Récupérer tous les fichiers nécessaires en http://ftp.netbsd.org/pub/NetBSD/NetBSD-5.0.1/sparc64/binary/sets/. J'ai utilisé pour cela la commande wget --mirror --no-parent --execute robots=off http://ftp.netbsd.org/pub/NetBSD/NetBSD-5.0.1/$(uname -m)/binary/sets/. Pour le reste de la manipulation, on va supposer qu'on a tout copié dans /var/tmp/netbsd5. On se rend dans ce répertoire.
  • Décomprimer le noyau avec pax -zrf kern-GENERIC.tgz. pax est simplement un frontal aux différents formats d'archivage comme tar.
  • Copier, par précaution, l'ancien noyau du système avec mv /netbsd /netbsd.old et mettre le nouveau noyau, récupéré à l'étape précédente avec mv netbsd /netbsd. On pourra redémarrer sur l'ancien noyau, si nécessaire, avec la commande boot netbsd.old de l'invite de démarrage de la Sparc.
  • Sur la Sparc, qui utilise OpenFirmware, une autre manipulation semble nécessaire, ou bien le nouveau noyau panique (« No bootinfo information.\ This kernel requires NetBSD boot loader.\ panic: sparc64_init. »). Il faut sauvegarder l'ancien /ofwboot, puis copier le nouveau (qu'on trouve dans l'ensemble base.tgz, en ./usr/mdec/ofwboot).
  • Redémarrer. (Il est important d'installer le noyau d'abord.)
  • Lors de la récupération, on a obtenu des ensembles (sets), des fichiers d'archive contenant tout les fichiers nécessaires. etc.tzg et xetc.tgz contiennent, comme leur nom l'indique, des fichiers de configuration. On ne les installera pas directement, la machine étant déjà configurée.
  • Installer les ensembles. On va dans la racine (cd /) et on installe : for set in $(ls /var/tmp/netbsd5/*.tgz | grep -v etc | grep -v kern); do; pax -zrf $set; done.
  • postinstall check. Ce programme va vérifier que tout est bien en place. Exécuter ensuite la commande qu'indiquera postinstall.
  • On a désormais les exécutables, les bibliothèques, etc. Mais on n'a pas encore mis à jour la configuration de la machine. Pour cela, on va utiliser le programme etcupdate ainsi : etcupdate -s /var/tmp/netbsd5/etc.tgz -s /var/tmp/netbsd5/xetc.tgz. etcupdate est interactif et, pour chaque fichier de configuration pour lequel il y a une nouveauté, il demandra s'il doit garder l'ancien, installer le nouveau ou bien fusionner interactivement les deux (le système est nettement moins intelligent que son équivalent Debian, qui regarde si l'ancien fichier a été modifié localement, avant de poser la question).
  • Il ne reste plus qu'à redémarrer, sur le nouveau système.

À noter que cette opération n'a mis à jour que le système de base. Autre différence avec Debian, le système est coupé en deux, le système de base et les applications, qui se gèrent à la main, ou bien via un système comme pkgsrc.

Il existe d'autres méthodes pour mettre à jour un système NetBSD. Citons notamment la possibilité de démarrer la machine sur un CD-ROM NetBSD et de choisir l'option de mise à jour (merci à Marc Baudoin pour ses explications). Cela simplifie le processus mais ne peut pas s'effectuer à distance.

Une autre solution, pour ceux qui aiment le compilateur, est de compiler soi-même le système de base (attention, je ne l'ai pas fait moi-même, l'opération est trop lente et consomme trop de place disque, je recopie juste une documentation) :

  • cd /usr/src
  • cvs update
  • Éditer le fichier de configuration (ici, MAMACHINE) et ./build.sh -U -u kernel=MAMACHINE.
  • cp /netbsd /netbsd.old puis cp /usr/src/sys/arch/$(uname -m)/compile/obj/MAMACHINE/netbsd /netbsd
  • Redémarrer
  • cd /usr/src
  • ./build.sh -U tools
  • ./build.sh -U -u distribution

L'article seul

RFC 5165: A Uniform Resource Name (URN) namespace for the Open Geospatial Consortium (OGC)

Date de publication du RFC : Avril 2008
Auteur(s) du RFC : C. Reed (Open Geospatial Consortium)
Pour information
Première rédaction de cet article le 12 avril 2008


Régulièrement, un nouveau RFC vient enrichir la grande famille des URN (RFC 8141, qui décrit les règles d'enregistrement), ces identificateurs prévus pour être stables et pérennes. Cette fois, les URN ogc viennent s'ajouter, pour stocker les normes et schémas de l'Open Geospatial Consortium.

Ce consortium produit des normes utilisés dans le monde de la géographie comme le format GML et qui servent à communiquer des informations spatiales, utilisées dans de nombreux secteurs (sections 1 et 5 du RFC).

Les URN de l'OGC utiliseront le NID (Namespace IDentifier) ogc. Ce NID sera suivi d'un type de ressource et des coordonnées de la ressources (section 2). L'OGC mettra en place un résolveur permettant de transformer ces URN en URI, à l'adresse http://urn.opengis.net/. Le reste de la section décrit les procédures de l'OGC, notamment pour garantir l'unicité de ces URN.

Un exemple des nouveaux URN (section 3) est urn:ogc:specification:gml:doc-is(02-023r4):3.0.0 qui identifiera une version particulière de la norme GML (d'où l'utilisation de la ressource « specification »).


Téléchargez le RFC 5165


L'article seul

pgtop, pour voir les activités de PostgreSQL

Première rédaction de cet article le 10 avril 2008
Dernière mise à jour le 13 juillet 2011


Un utilitaire très pratique, pgtop, permet de voir l'activité des processus de PostgreSQL, de regarder les requêtes SQL en cours d'exécution, les statistiques, etc.

pgtop ressemble (délibérement) à la commande top d'Unix. Sur une Debian "lenny" avec PostgreSQL 8.3, j'ai testé la version (actuellement beta) 3.6.2-beta3. configure && make pour le compiler (j'ai juste dû ajouter LDFLAGS = -lcurses dans le Makefile, voilà ce que c'est que d'utiliser des versions beta). Sur une Debian "squeeze", il est désormais dans un paquetage normal (nommé ptop). Puis je le lance avec pg_top -p 5433 -d MABASE et, merveille, je vois l'activité de mon SGBD. Je vais maintenant savoir, lorsque ça rame, pourquoi ça rame.

On trouve de nombreux exemples en http://ptop.projects.postgresql.org/screenshots/.

Il y a bien d'autres façons de voir ce que son SGBD favori est en train de faire, par exemple via des requêtes SQL :

> SELECT current_query FROM pg_catalog.pg_stat_activity WHERE datname='MABASE';
...
CREATE INDEX qname_idx_DNS_Packets_1 ON DNS_Packets_1(qname);
...

Merci à Nicolas Delvaux pour ses informations.


L'article seul

Pourquoi avoir choisi l'ISO pour OpenDocument ?

Première rédaction de cet article le 10 avril 2008


L'adoption par l'ISO de la norme Open XML, proposée par Microsoft, a fait couler beaucoup d'encre, notamment en raison des manœuvres peu glorieuses qui ont permis le retournement de veste du représentant français, malgré les faiblesses techniques de la proposition (des méthodes analogues ont été utilisées dans d'autres pays). La conclusion de la plupart des observateurs, à juste titre, était que l'approbation d'une norme à l'ISO dépendait plus des qualités du lobbyiste que de celles de la norme. (Voir par exemple le communiqué de l'APRIL.) C'est juste mais, dans ce cas, pourquoi diable le monde du logiciel libre, qui avait fait approuver peu de temps auparavant OpenDocument à l'ISO a t-il choisi cet organisme ?

Il existe de nombreuses organisations de normalisation dans le monde. Les tenants du logiciel libre, y compris des grosses entreprises comme Sun ou IBM avaient choisi de porter le format OpenDocument à l'ISO et s'étaient bruyamment vantés de son approbation par cet organisme. C'était tendre la perche à Microsoft : utiliser ses moyens pour faire approuver n'importe quoi par une bureaucratie est le principal domaine de compétence du géant de Redmond. Il n'y a donc pas de quoi s'étonner du succès de la proposition Microsoft à l'ISO. À l'ISO, les participants aux groupes de travail (qui sont parfois de réels experts du domaine) ne sont pas ceux qui votent. Le vote est fait par des représentants des gouvernements, dont on ne sait pas trop bien qui les a désigné où à qui ils répondent. Il est en général impossible de savoir qui a voté quoi. Par exemple, la France a t-elle voté OUI ou NON à la norme ISO 639-3 ? Je vous laisse chercher.

Un tel système favorise les bons lobbyistes, qui ont l'oreille des gouvernements. C'est le terrain où Microsoft est fort et où le monde du logiciel libre a étrangement choisi de se rendre.

Il existe des organisations de normalisation plus ouvertes, où les experts du domaine ont un poids plus important et où les décisions sont davantage transparentes, comme le W3C, l'IETF ou OASIS. Pourquoi être allé à l'ISO ? Pourquoi découvrir seulement maintenant que l'ISO « manque de crédibilité » ? L'ISO a toujours été fermée, bureaucratique, ne rendant pas de compte au public et ne distribuant même pas ses normes sur Internet. Faire normaliser un format ouvert à l'ISO, c'est comme faire voter la déclaration des Droits de l'Homme par le parlement tunisien !


L'article seul

RFC 5147: URI Fragment Identifiers for the text/plain Media Type

Date de publication du RFC : Avril 2008
Auteur(s) du RFC : E. Wilde (UC Berkeley), M. Dürst (Aoyama Gakuin University)
Chemin des normes
Première rédaction de cet article le 10 avril 2008


Les URI disposent depuis longtemps d'un moyen de désigner une partie d'un document, par les biais des « identificateurs de fragments », précédés d'un dièse, comme par exemple http://www.example.org/foobar.html#section3. Entièrement interprétés par le client Web, ces identificateurs étaient définis seulement pour XML et HTML et notre RFC ajoute le texte brut.

La façon classique d'utiliser ces identificateurs est de modifier le document cible pour y ajouter un élément à viser, par exemple :


<p id="avertissement-sante">Fumer est dangereux pour la santé.</p>

fera qu'un navigateur pourra, lorsqu'on lui demandera http://www.example.org/document.html#avertissement-sante, aller directement à ce paragraphe. On peut aussi utiliser, au lieu d'un simple nom comme avertissement-sante, utiliser une expression XPath, si le navigateur accepte XPointer. En outre, avec XLink, on peut même pointer vers un document qu'on ne peut ou ne veut modifier, ce qui évite de devoir ajouter des attributs id ou name.

Le texte brut (normalisé dans MIME par le RFC 2046) n'étant pas, lui, structuré, on ne pouvait pas compter sur des « marques » particulières. D'où le choix de notre RFC de compter les caractères ou bien les lignes.

C'est ainsi que les URI de ce RFC ressembleront à http://library.example/2007/11/5311.txt#char=6234 (le curseur du navigateur ira sur le 6234ème caractère) ou bien http://library.example/2004/03/228.txt#line=534,580 (le navigateur affichera le texte compris entre la 534ème ligne et la 580ème).

Mais les documents accessibles sur le Web tendent à changer. De tels identificateurs de fragments sont clairement moins robustes que ceux utilisant un attribut du document XML (comme avertissement-sante plus haut), ou bien que ceux utilisant une expression XPath. Comment détecter le cas où un paragraphe a été ajouté, faussant ainsi les liens ? Cette norme permet d'ajouter à l'URI un mécanisme de contrôle d'intégrité, en indiquant la longueur ou bien la somme de contrôle MD5 (RFC 1321) du document. Si elles ne correspondent pas, le navigateur sait qu'il ne doit pas utiliser l'identificateur de fragment. Ainsi, http://www.myblog.example/2006-12/mespensees.php#line=50;length=19576,UTF-8 amènera le navigateur à compter le nombre de caractères du document et à ignorer l'identificateur de fragment s'il ne trouve pas 19576 caractères.

Notre RFC doit aussi traiter des problèmes plus subtils comme la façon de compter les fins de ligne du document (il existe plusieurs façons de les représenter, et la norme décide qu'une fin de ligne compte toujours pour un caractère).

Un autre problème subtil est la nécessité de tenir compte de l'encodage des caractères. En effet, char= compte bien le nombre de caractères, pas le nombre d'octets.

Deux implémentations existent, une dans Amaya et une en Python, incomplète mais quand même utile: TextFrag.py.

À noter aussi une présentation par un des auteurs, un amusant et intéressant article de Tim Bray, Matthew-6:9.txt#line=,1 et un intéressant texte de Karl Dubost élargissant le problème.


Téléchargez le RFC 5147


L'article seul

RFC 5123: Considerations in Validating the Path in BGP

Date de publication du RFC : Février 2008
Auteur(s) du RFC : R. White, B. Akyol (Cisco)
Pour information
Première rédaction de cet article le 8 avril 2008


La sécurité du protocole BGP, par lequel les routeurs Internet échangent l'information sur les routes existantes, est depuis longtemps un sujet de préoccupation. Actuellement, BGP (RFC 4271) n'offre quasiment aucune sécurité contre les usurpations (un routeur annonce une route qu'il n'a pas « le droit » d'annoncer, comme lors de la récente usurpation perpétrée par Pakistan Telecom). Pourquoi ne valide t-on pas les routes annoncées ? En partie parce que c'est plus compliqué que ça n'en a l'air, comme l'explique ce récent RFC.

Beaucoup de gens, étonnés qu'un technicien incompétent à Karachi puisse stopper l'activité d'un site Web stratégique et essentiel uniquement en détournant son trafic grâce à BGP, réclament des mesures drastiques et notamment la validation des routes annoncées par BGP. Certains opérateurs, rares, font une validation partielle, en général basée sur le contenu des IRR. Pourquoi cette pratique n'est-elle pas plus répandue ?

Les mécanismes existants de sécurité comme BGP-MD5 (RFC 2385) ou TCP-AO (RFC 5925) ne sécurisent que le canal de communication entre deux routeurs. Ils permettent d'être sûr de l'identité du pair BGP, mais pas de valider ce qu'il annonce. Le routeur de Pakistan Telecom était authentique, il était aussi menteur et BGP-MD5 ne protège pas le message, uniquement le canal.

Notre RFC fait donc la liste des points à vérifier lors d'une validation. Le premier (section 1.1) est évidemment de savoir si l'AS d'origine est autorisé à annoncer cette route. C'est un point crucial mais qui n'est pas le sujet de notre RFC, qui se consacre au devenir ultérieur de cette annonce. Plusieurs autres questions sont ensuite posées dans le RFC. Par exemple, la section 1.3 demande « Est-ce que l'annonce par un routeur qui n'est pas de l'AS d'origine est autorisée ? » et explique que la question est bien plus subtile qu'elle ne le semble puisqu'il y a en fait trois sous-questions derrière cette question apparemment simple :

  • L'autorisation d'annoncer une route particulière, par exemple 192.0.2.128/25 (route authorization).
  • L'autorisation d'annoncer un préfixe qui inclus la route, par exemple 192.0.2.0/24 (reachability authorization).
  • L'autorisation de faire transiter les paquets par son réseau (transit authorization).

Ces trrois autorisations, à première vue équivalentes, peuvent en fait donner des résultats différents, comme le montrent les exemples ultérieurs.

Citons uniquement un exemple, présenté en section 2.2, qui exploite le fait que la route réellement empruntée n'est pas contrôlée par la source mais par chaque AS intermédiaire. Un AS annonce à son voisin une route avec un chemin d'AS, mais, en interne, il a une route statique qui prend un autre chemin. L'annonce est-elle valide ? L'AS annonceur était autorisé à annoncer cette route (route authorization et reachability authorization) mais il est impossible de déterminer s'il y avait transit authorization puisque le chemin réellement emprunté n'apparait pas dans l'annonce.

Globalement, ce RFC fait à mon avis œuvre utile en expliquant la complexité du routage Internet. Il donne parfois un peu trop dans le pinaillage en montant en épingle des cas intéressant mais très rares. Le vrai problème de la validation des routes en BGP est plutôt l'absence d'un système de « droit d'usage » permettant de savoir qui a le droit d'annoncer telle route. Sans un tel système, les protocoles sécurisés de diffusion de routes (qui existent, et reposent sur la cryptographie) n'ont rien sur lequel se baser. (Un groupe de travail de l'IETF, RPSEC, travaille actuellement à un cahier des charges pour un routage sécurisé. Un exemple de mécanisme permettant de valider les annonces de route a été publié début 2012.)


Téléchargez le RFC 5123


L'article seul

Unicode 5.1

Première rédaction de cet article le 7 avril 2008


Le consortium Unicode vient d'annoncer la sortie de la version 5.1 de la célèbre norme de jeu de caractères. 1 624 caractères de plus, permettant à Unicode de dépasser les 100 000 caractères.

Parmi les nouveaux venus, un certain nombre de caractères arabes (notamment pour écrire le persan) ou cyrilliques, le Eszett allemand en majuscule (la précédente majuscule de ß était la chaîne SS, ce sera désormais le caractère Unicode U+1E9E, que votre navigateur ne sait probablement pas encore afficher), l'alphabet Sundanese (que je ne connaissais pas), d'autres alphabets nouveaux comme le Cham, les caractères du Mah-jong (cf. le roman « Sous les vents de Neptune » de Fred Vargas), et plein d'autres caractères rigolos comme U+2B3D, « LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE » ou U+2E2A, « TWO DOTS OVER ONE DOT PUNCTUATION ».

La majuscule du Eszett a suscité bien des controverses (cf. http://de.wikipedia.org/wiki/Versal-Eszett), certains germanophones expliquant que cette lettre n'existe pas. On peut consulter la proposition initiale en http://std.dkuug.dk/jtc1/sc2/wg2/docs/n3227.pdf, avec des exemples d'utilisation, pris par exemple sur des pierres tombales.

Le programme de conversion de la base Unicode en SQL est un excellent outil pour explorer cette nouvelle version :

ucd=> SELECT count(*) AS Total FROM Characters;                                        total  
--------
 100713
(1 row)

ucd=> SELECT To_U(codepoint) AS Codepoint, name FROM 
                Characters WHERE version = '5.1';
 codepoint |                                 name                                  
-----------+-----------------------------------------------------------------------
 U+1E9E    | LATIN CAPITAL LETTER SHARP S
 U+A66E    | CYRILLIC LETTER MULTIOCULAR O
...
 U+372     | GREEK CAPITAL LETTER ARCHAIC SAMPI
 U+373     | GREEK SMALL LETTER ARCHAIC SAMPI
...
 U+520     | CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK
 U+521     | CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK
 U+522     | CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK
 U+523     | CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK
 U+606     | ARABIC-INDIC CUBE ROOT
 U+607     | ARABIC-INDIC FOURTH ROOT
 U+608     | ARABIC RAY
...

L'article seul

Apache et le module GnuTLS

Première rédaction de cet article le 7 avril 2008
Dernière mise à jour le 4 décembre 2008


Pour faire du TLS sur un serveur HTTP Apache, la solution la plus connue est le module mod_ssl. Mais il en existe une autre, le module GnuTLS.

GnuTLS est une mise en œuvre libre du protocole TLS (ex-SSL, protocole normalisé dans le RFC 5246). Étant sous licence GPL, il peut être utilisé par des programmes GPL (alors que OpenSSL a une licence incompatible avec la GPL, ce qui a entrainé des problèmes pour plusieurs projets). GnuTLS offre également des possibilités qui sont absentes d'OpenSSL, comme la possibilité d'utiliser des clés PGP (RFC 5081) en sus des certificats X.509.

Sur une machine Debian, où tout est déjà compilé et empaqueté, l'installation du module mod_gnutls d'Apache est triviale. Un coup de aptitude install, puis ln -s ../mods-available/gnutls.load /etc/apache2/mods-enabled (Sébastien Tanguy me fait remarquer à juste titre qu'il existe une méthode de plus haut niveau, la commande a2enmod) et recharger Apache. Sa configuration peut être aussi courte que :

    GnuTLSEnable  on
    GnuTLSCertificateFile /etc/ssl/certs/ssl-cert-Example.pem
    GnuTLSKeyFile /etc/ssl/private/ssl-cert-Example.key
    GnuTLSPriorities NORMAL

Et hop, ça marche avec des clients HTTP utilisant GnuTLS comme avec ceux utilisant OpenSSL comme Konqueror.

Une des forces de GnuTLS est qu'il permet l'utilisation de l'extension de TLS SNI (Server Name Indication) qui permet de mettre plusieurs certificats différents à des Virtual Host Apache se partageant une seule adresse IP. Il suffit de mettre une directive GnuTLSCertificateFile différente par Virtual Host :


<VirtualHost _default_:443>
        # Site par défaut. Son certificat sera envoyé aux clients
	# non-SNI 
        ...
        GnuTLSCertificateFile /etc/ssl/certs/ssl-cert-DEFAULT.example.net.pem
...
<VirtualHost *:443>
        ...
        ServerName svn.example.net
        GnuTLSCertificateFile	/etc/ssl/certs/ssl-cert-svn.example.net.pem
...
<VirtualHost *:443>
        ...
        ServerName viewvc.example.net
        GnuTLSCertificateFile	/etc/ssl/certs/ssl-cert-viewvc.example.net.pem
...


L'article seul

RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core

Date de publication du RFC : Octobre 2004
Auteur(s) du RFC : Peter Saint-Andre (Jabber Software Foundation)
Chemin des normes
Première rédaction de cet article le 7 avril 2008


Jabber est le nom original, et XMPP le nom IETF d'un protocole d'échange d'informations encodées en XML, protocole surtout connu pour son utilisation dans la messagerie instantanée.

La messagerie instantanée est une application très populaire surtout chez les moins de dix ans. Elle permet d'échanger des messages sans prendre le temps de réfléchir et en général sans craindre qu'ils soient archivés (contrairement au courrier électronique où il faut réfléchir car ce que l'on écrit restera). Elle sert à de nombreux usages, discussions entre geeks, systèmes de surveillance avec notification des problèmes, etc. À l'exception du vénérable protocole IRC (décrit - insuffisamment - dans le RFC 2810 et suivants), les systèmes existants de messagerie instantanée sont tous basés sur des protocoles privés et fermés comme MSN. La normalisation qui fait le succès du courrier électronique n'a pas réussi ici.

D'où le vieux projet (RFC 2779) de développer un protocole moderne et ouvert, adapté à cette application. C'est ce qu'on fait les développeurs du protocole Jabber en 1999, projet adopté ultérieurement par l'IETF, rebaptisé XMPP en 2002 et qui était normalisé dans ce RFC (l'annexe D liste les différences entre Jabber et XMPP, la plupart liées à la sécurité et à l'internationalisation). Depuis, il a été remplacé par le RFC 6120. Notre RFC décrit un protocole généraliste, un RFC compagnon, le RFC 3921, normalise les aspects spécifiques à la messagerie instantanée.

Quels sont les principes de XMPP ? Les données sont encodées en XML (avec quelques bémols notés en section 11), dans des strophes (stanzas) qui sont des petits paquets d'information. Ces strophes sont transmises sur une connexion TCP (section 4.2) entre client et serveur, ou bien entre serveur et serveur. Les entités qui communiquent (ce ne sont pas forcément des humains, Jabber ayant été conçu pour permettre également la communication entre programmes) sont identifiées par une adresse, qui a une forme syntaxique proche de celle du courrier électronique. Par exemple, mon adresse XMPP est bortzmeyer@gmail.com.

XMPP, comme le courrier électronique, fonctionne par le connexion de serveurs, chacun chargé d'un ou plusieurs domaines. Les clients transmettent les messages aux serveurs, qui se chargent de les acheminer au serveur suivant (section 2.1 du RFC).

Les adresses (JID pour Jabber Identifier) sont décrites dans la section 3. Outre le classique nom@domaine, elles peuvent comporter une ressource, indiquée après la barre oblique (par exemple bortzmeyer@gmail.com/AFNIC).

La représentation des données en XML est décrite dans la section 4. Un flux de données, un stream, est un élément XML <stream>, qui comporte une ou plusieurs strophes, <stanza>. Il existe de nombreux types de strophes (section 9) sans compter les messages d'erreur, décrits en 4.7. Voici un exemple classique d'un échange (C étant le client et S le serveur), avec des strophes de type message :


   C:   <message from='juliet@example.com'
                 to='romeo@example.net'
                 xml:lang='en'>
   C:     <body>Art thou not Romeo, and a Montague?</body>
   C:   </message>
   S:   <message from='romeo@example.net'
                 to='juliet@example.com'
                 xml:lang='en'>
   S:     <body>Neither, fair saint, if either thee dislike.</body>
   S:   </message>

Contrairement à beaucoup d'autres protocoles de messagerie instantanée, conçus uniquement pour jouer, XMPP, étant prévu aussi pour le travail, dispose de fonctions de sécurité très riches. La section 5 précise l'utilisation de TLS et la 6 celle de SASL.

La section 9 détaille les types de strophes disponibles. Trois types sont définis dans ce RFC, <message>, <presence> et <iq>. <message>, dont la sémantique est décrite en section 9.2.1, transporte un... message, tandis que <iq> (section 9.2.3) est une interrogation (Info / Query). Ces éléments XML ont un certain nombre d'attributs par exemple l'attribut to, section 9.1.1, qui spécifie l'adresse du destinataire (romeo@example.net dans la pemière strophe de l'exemple ci-dessus). La syntaxe complète, exprimée en W3C Schema, figure dans l'annexe C.

XMPP est aujourd'hui mis en œuvre dans de nompbreux logiciels. C'est ainsi que le service de messagerie instantanée Google Talk utilise XMPP. Le client XMPP (qui est aussi un client de nombreux autres protocoles) le plus populaire sur Unix est sans doute Pidgin (ex-Gaim). Côté serveurs, le plus pittoresque (et pas le moins utilisé) est sans doute ejabberd, écrit en Erlang.

Les développeurs liront avec intérêt le livre Programming Jabber qui explique comment utiliser Jabber/XMPP dans ses propres programmes.


Téléchargez le RFC 3920


L'article seul

La zona

Première rédaction de cet article le 6 avril 2008


Ce film de Rodrigo Plá montre une zone protégée de Mexico, un terrain privé entouré de murs et de barbelés, protégé par les gadgets les plus modernes de la technologie, dans le but d'échapper à la violence permanente de la ville. Comme aux États-Unis, comme déjà en France, le « désir de ghetto » mène à inscrire dans l'espace la volonté de séparation avec les « classes dangereuses ». Si les femmes de ménage indiennes ont l'autorisation de rentrer pour leur travail, le reste de la ville, même la police, est interdite d'accès.

Trois jeunes issus des bidonvilles vont rentrer dans la zone pour un cambriolage, déchaînant la violence des résidents de la Zona qui tiennent à maintenir la stricte pureté de leur communauté. À une ou deux exceptions près, ils ne sont pas des fascistes ou des brutes sadiques, mais ils paniquent à l'idée de tout contact avec le monde extérieur.

Étonnante zone protégée où les riches se sont enfermés eux-même, étonnante île privée, où les résidents pratiquent une stricte démocratie entre eux, tout en excluant tout le reste de la population (ils tiennent une assemblée générale avant de décider d'aller à la chasse à l'homme).


L'article seul

RFC 2045: Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies

Date de publication du RFC : Novembre 1996
Auteur(s) du RFC : Ned Freed (Innosoft International, Inc.), Nathaniel S. Borenstein (First Virtual Holdings)
Chemin des normes
Première rédaction de cet article le 4 avril 2008


Autrefois, du temps des dinosaures, les internautes vivaient dans des cavernes et gravaient au silex des courriers en texte seul, sur des écorces d'arbre. En 1992, MIME a été inventé et, depuis, les humains sont civilisés et envoient du spam en HTML, des vidéos débiles et des photos ratées par courrier électronique. Notre RFC 2045 est l'actuelle norme MIME.

À l'origine du courrier électronique, la norme (aujourd'hui le RFC 5322) décrivait surtout les métadonnées, les en-têtes du message, comme From: (l'expéditeur) ou Date: (la date d'envoi). Le corps du message, lui, était laissé au seul texte brut, dans le seul jeu de caractèrs US-ASCII.

Pour transmettre du non-texte, par exemple des images de Carla Bruni, on se servait d'encodages non-standard, qui transformaient le fichier binaire en texte. C'était l'époque de uuencode (ou de Binhex pour les macounistes). Même pour le texte seul, dès qu'on dépassait les limites du jeu de caractères ASCII, donc, dès qu'on écrivait autre chose que l'anglais, on ne pouvait plus rester strictement dans les limites du RFC 822 (la norme du courrier de l'époque). Ces limites et les motivations pour MIME sont décrites dans la section 1 du RFC.

MIME a changé cela. Normalisé à l'origine dans le RFC 1341, puis dans le RFC 1521 (et suivants) et finalement dans notre RFC 2045 et ses compagnons suivants, MIME repose sur quatre piliers :

  • Un format pour le corps du message, normalisé dans le RFC 2045, format récursif, permettant d'inclure diverses parties dans un message,
  • Des encodages pour les parties binaires,
  • Une notion de type, normalisée dans le RFC 2046, permettant d'étiqueter sans ambiguïté les parties du message, notion qui a eu un grand succès et est utilisée par bien d'autres protocoles,
  • Un truc permettant de mettre des caractères non-ASCII dans les en-têtes (RFC 2047).

Pour le texte, MIME utilise la notion de character set (section 2.2). Comme l'explique une note de cette section, le terme est erroné, puisqu'il s'agit en fait, dans MIME, d'un encodage, pas simplement d'un jeu de caractères.

Avec la section 3, commence la description du format MIME lui-même. MIME ajoute quelques nouveaux en-têtes à commencer par MIME-Version (section 4) qui indique qu'il s'agit d'un message MIME. La section 5 décrit l'en-tête Content-type qui spécifie le type MIME du message ou de la partie du message. Il existe un zoo entier de ces types, conservé dans un registre à l'IANA. Le principe est que le type est composé de deux parties, le type proprement dit, qui identifie le genre de données (texte, image, son, ...) et le sous-type qui identifie le format. Ainsi, image/png est une image au format PNG, text/troff est du texte au format troff (RFC 4263). Plus complexes, les types message ou application. Le premier identifie un message MIME inclus dans un autre message MIME (par exemple lors de l'envoi d'un avis de non-réception (RFC 3461). Le second identifie des données binaires qui ne peuvent être comprises que par une application spécifique, indiquée par le sous-type. La classification MIME n'est pas toujours aussi évidente et je n'ai personnellement jamais compris pourquoi XML est en application/xml et pas text/xml. Enfin, des paramètres peuvent se trouver dans cet en-tête, par exemple pour indiquer l'encodage d'un texte (Content-Type: text/plain; charset=utf-8) ou bien pour indiquer le site où récupérer un document pointé (comme dans le programme d'exemple ci-dessous).

La section 6 introduit un autre en-tête, Content-Transfer-Encoding qui indique comment le contenu a été emballé pour passer à travers des serveurs (qui peuvent n'accepter que l'ASCII). Un Content-Transfer-Encoding: 8bit spécifie que le contenu n'a pas été modifié du tout, il faudra alors que tous les serveurs laissent passer le 8bits. À une époque très lointaine, où les mammouths étaient encore fréquents en France, certains serveurs mettaient le huitième bit à zéro ou autres horreurs ; une longue polémique, au début des années 1990, avait opposé ceux qui voulaient transmettre les textes en français en 8bits (et tant pis pour les quelques serveurs archaïques) et ceux qui préféraient l'encoder dans des systèmes comme Quoted-Printable (Content-Transfer-Encoding: quoted-printable, décrit en détail dans la section 6.7), qui étaient plutôt pires pour les MUA de l'époque, qui affichaient caf=E9 au lieu de café...

À titre d'exemple, voici un programme Python qui analyse un message MIME. Le programme n'est pas récursif, bien que cela soit souvent utile pour les messages MIME, la définition même du format étant récursive (un message peut être composé de parties qui sont elles-mêmes composées de parties, etc, cf. la note de la section 2.6). Ces messages contiennent une partie de type message/external-body qui donne des instructions d'accès à un fichier par FTP :

import email
from email.MIMEText import MIMEText
...
# We receive the message on standard input (for instance through
# procmail and its pipe action)
message = email.message_from_file(sys.stdin)
subject = message.get("subject")

# A MIME message can be single-part but we are interested only in multi-parts
if not message.is_multipart():
     raise NotForMe("Not multipart")
...
# The body of the message
parts = message.get_payload()
# Iterate over the parts of the message
for part in parts:
    if part.get_content_type() == "message/external-body":
          params = dict(part.get_params())
          if params["access-type"] == "anon-ftp":
                url = "ftp://%s/%s/%s" % (params["site"],
                                          params["directory"],
                                          params["name"])
...

À l'époque du RFC 822, écrire un programme qui analysait les messages électroniques était trivial, on pouvait travailler directement avec le texte, même un simple grep suffisait. Avec MIME, les parties multiples (section 5.1 du RFC 2046), et les encodages variés, l'utilisation de bibliothèques comme email en Python devient indispensable. Par exemple, les spammeurs encodent souvent leurs messages en Base64 (section 6.8, désormais dans le RFC 4648), afin de trompeur les analyseurs de mots-clés naïfs.

On note que ce RFC, ce qui est relativement rare, contient également d'intéressantes notes (introduites par NOTE) sur les choix effectués par les concepteurs du format MIME. Leur lecture permet de mieux comprendre ces choix.


Téléchargez le RFC 2045


L'article seul

Sélection d'articles dans un flux de syndication

Première rédaction de cet article le 3 avril 2008
Dernière mise à jour le 6 avril 2008


Ce serait bien d'avoir des sélections de mon flux de syndication (http://www.bortzmeyer.org/feed.atom) par sujet (PostgreSQL, XSLT, Python, etc). Existe t-il des services en ligne qui assurent ce genre de sélections ?

Comme je maitrise complètement le processus de production du flux, je pourrais bien sûr générer N flux selon le sujet mais cela représente du travail, alors que les critères de sélection évoluent tout le temps.

Je me demande s'il n'existe pas plutôt un service tiers de sélection à qui on donnerait l'URL du flux, un critère de sélection (mot-clé, expression rationnelle, expression XPath) et qui renverrait un URL que je pourrais donner à des sites d'agrégation comme http://planete.postgresql.fr/ ou comme http://fr.incubator.wikiblogplanet.com/, qui n'acceptent que les articles sur un certain sujet (PostgreSQL dans le premier cas, Wikipédia dans le second).

J'ai testé trois de ces services mais d'autres adresses seraient bienvenues.

Le premier est http://www.filtermyrss.com/. Il marche uniquement avec RSS, alors que mon flux est en Atom (RFC 4287). Il ne filtre que par mot-clés, pouvant apparemment porter sur certains éléments (titre uniquement, par exemple).

Puis j'ai testé http://feedrinse.com/. Il nécessite une inscription, certes gratuite mais c'est quand même pénible. Après inscription, je dois être bête, je n'ai jamais pu le faire marcher.

Le service de référence le plus souvent cité pour ce genre d'opérations est Yahoo Pipes, un mécanisme de programmation graphique, permettant de définir des traitements sur des flux d'information. Yahoo Pipes nécessite apparemment un compte Yahoo et Yahoo me refuse l'inscription (This is not a valid email address, dit-il, et mon identifiant OpenID ne suffit apparemment pas donc j'ai abandonné tout espoir d'utiliser Yahoo). Un problème analogue m'empêche de tester Fwicki qui en outre se vante stupidement de ses brevets dès la page d'accueil.

Enfin, http://re.rephrase.net/filter/ est celui que j'ai choisi. Il n'y a pas besoin d'inscription, il marche bien avec Atom. Les recherches se font par mot-clés, portant sur le texte ou sur une partie du texte (une documentation très complète est disponible). En outre, le source du service est distribué par l'auteur.

C'est donc celui que j'utilise en ce moment. Par exemple http://re.rephrase.net/filter/?feed=http%3A%2F%2Fwww.bortzmeyer.org%2Ffeed.atom&filter=title%3Apostgresql+OR+title%3ASQL sélectionne tous les articles du flux qui ont « postgresql » ou « SQL » dans leur titre.

Les caractères composés du français nécessitent un peu de bricolage. Rephrase, écrit en PHP, n'a pas de support d'Unicode et fait une recherche « bête » en comparant les octets. Si le flux de syndication est en UTF-8, il faut mettre de l'UTF-8 dans le critère de tri. Ainsi, pour chercher tous les articles parlant de Wikipédia, l'URL sera http://re.rephrase.net/filter/?feed=http%3A%2F%2Fwww.bortzmeyer.org%2Ffeed.atom&filter=wikip%C3%A9dia, puisque le caractère « é » se code par 0xC3 et 0xA9 en UTF-8.

Depuis ce choix, mon blog a été muni d'un moteur de recherche. Donc, une autre solution, à explorer, serait d'utiliser le moteur de recherche pour produire des flux Atom dynamiques, avec des requêtes comme http://www.bortzmeyer.org/search?pattern=postgresql&format=Atom. Toutefois, le moteur de recherche de ce blog ne renvoyant que les N articles les plus pertinents, ce n'est pas actuellement idéal pour faire une vue d'un flux de syndication.

Merci à Benoit Deuffic, David Larlet et Olivier Mengué pour leur aide à trouver ces services. Merci à l'auteur de Rephrase, Sam Angove, pour sa rapidité à répondre aux questions des utilisateurs.


L'article seul

RFC 5156: Special-Use IPv6 Addresses

Date de publication du RFC : Avril 2008
Auteur(s) du RFC : M. Blanchet (Viagenie)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 3 avril 2008


Un certain nombre de préfixes IPv6 ont une signification spéciale et ce RFC les documente, pour éviter aux lecteurs de devoir fouiller dans les nombreux RFC originaux. (Depuis, ce RFC a été remplacé par le registre décrit dans le RFC 6890.)

Normalement, les préfixes des réseaux IPv6 sont attribués par l'IANA aux RIR qui les allouent ensuite aux LIR (qui sont en général des FAI). Ces allocations et les affectations aux utilisateurs finaux sont enregistrées par les RIR et sont publiquement accessibles via des protocoles comme whois.

Mais certains préfixes sont spéciaux et échappent à ce mécanisme. Ils ont été réservés par tel ou tel RFC et sont donc dispersés à plusieurs endroits. Notre RFC, écrit par l'IANA, rassemble toutes ces réservations en un seul endroit. (Il existe un RFC équivalent pour IPv4, le RFC 5737.)

Voici quelques exemples de préfixes ainsi documentés :

  • 2001:DB8::/32 (section 2.6), réservé pour la documentation par le RFC 3849 (par exemple pour rédiger des manuels, sans craindre que les adresses IP d'exemple soient utilisées),
  • FE80::/10, réservé pour les adresses locales au lien par le RFC 4291,
  • 2001:20::/28, réservé pour créer des identificateurs (et non de simples adresses) sous le nom d'ORCHID (RFC 7343),
  • Et bien d'autres, énumérés dans la section 2. Par contre, on ne trouvera pas les adresses site-local, FEC0::/10, celles-ci ayant été abandonnées par le RFC 3879.

Téléchargez le RFC 5156


L'article seul

Systèmes de coordonnées pour Internet

Première rédaction de cet article le 1 avril 2008


De nombreuses applications Internet ont besoin de connaitre la « distance » entre deux machines. Par exemple, un logiciel de pair-à-pair cherche quel pair est le plus « proche » avant de lui demander un fichier. Pour cela, la méthode utilisée est en général à la fois consommatrice en ressources et peu précise. Le déploiement de mécanismes de coordonnées Internet pourrait résoudre le problème élégamment.

Aujourd'hui, la métrique la plus courante est le RTT avec l'autre machine et la méthode de mesure la plus fréquente est la force brute : on écrit à tous les partenaires potentiels et le premier à répondre est considéré comme le plus proche et sera désormais davantage utilisé. C'est par exemple ainsi que fonctionne le résolveur DNS BIND ou la plupart des logiciels de pair-à-pair. La métrique n'est pas idéale (il existe des liens Internet à fort débit mais à latence élevée). Et cela consomme beaucoup de ressources réseau (il faut émettre des octets vers chaque pair potentiel) et pour une mesure qui n'est pas forcément très précise.

Les systèmes de coordonnées Internet traitent le problème d'une manière radicale. On ne « pingue » plus les pairs potentiels mais on obtient leurs coordonnées dans un espace cartésien à N dimensions. Connaissant ces coordonnées et les siennes propres, déterminer une distance, et donc la proximité d'un futur partenaire, est triviale.

Mais comment déterminer les coordonnées d'une machine ? En testant un petit nombre de machines cibles, les amers (beacons ou lighthouses, on peut aussi traduire par phare ou balise). Contrairement à un pair quelconque, les amers sont en petit nombre (donc on consomme moins de ressources à les tester), stables, et judicieusement placés. Chaque amer a, en testant les autres amers, déterminé ses coordonnées, ce qui permettra à la machine testeuse de déterminer la sienne avec un coût plus faible et une meilleure précision.

Il existe plusieurs systèmes concurrents de coordonnées Internet. À l'heure actuelle, aucun n'est encore réellement déployé et utilisé. L'excellent exposé de Marcelo Pias, Internet Coordinate Systems Tutorial expose les principaux et les compare. Les premiers utilisaient, pour calculer les coordonnées des amers, la minimisation d'erreur par le simplex downhill, alors que les plus récents, comme ICS décrit dans Constructing Internet Coordinate System Based on Delay Measurement utilisent l'analyse en composantes principales. Voici une liste pas du tout limitative de certains de ces systèmes, outre ICS :

Le projet P4P, très à la mode actuellement, est complémentaire de ces systèmes de coordonnées. Il vise à fournir un moyen de distribuer des informations de topologie (qui est connecté à qui) et de politique (le lien de peering est préféré au lien de transit) pour que les machines puissent décider judicieusement de leurs pairs. Mais il faut noter que plusieurs présentations de P4P comme celle de Pando sont biaisées dans leur façon de décrire le pair-à-pair actuel, en prétendant que les pairs sont aujourd'hui choisis plus ou moins au hasard, alors que ce choix (qui a l'avantage de simplifier l'implémentation) n'est pas universel.

Une autre approche possible à la question de la détermination d'un pair « proche » est Meridian.


L'article seul

RFC 4934: Extensible Provisioning Protocol (EPP) Transport Over TCP

Date de publication du RFC : Mai 2007
Auteur(s) du RFC : S. Hollenbeck (Verisign)
Chemin des normes
Première rédaction de cet article le 1 avril 2008
Dernière mise à jour le 7 mai 2008


Ce court RFC spécifiait comment utiliser le protocole d'avitaillement EPP au dessus d'une simple connexion TCP. Il a été remplacé depuis par le RFC 5734.

EPP, décrit dans le RFC 4930 est à sa base uniquement un format XML pour les requêtes d'avitaillement (création, mise à jour et destruction d'objets) et leurs réponses. Ces éléments XML peuvent être transmis de différence façon (au dessus de HTTP, de BEEP, par courrier électronique, etc), et notre RFC normalise la plus commune aujourd'hui, une simple connexion TCP. Il remplace le RFC 3734, avec uniquement des modifications de détail, portant notamment sur la sécurité (section 8).

Le RFC est court car il n'y a pas grand'chose à dire, juste l'utilisation des primitives de TCP (ouverture et fermeture de connexion, section 2 du RFC), l'ordre des messages (section 3) et le fait que chaque élément EPP soit précédé d'un entier qui indique sa taille (section 4). Sans cet entier (qui joue le même rôle que l'en-tête Content-Length de HTTP), il faudrait, avec la plupart des implémentations, lire les données octet par octet (sans compter que la plupart des analyseurs XML ne savent pas analyser de manière incrémentale, il leur faut tout l'élément). En outre, sa présence permet de s'assurer que toutes les données ont été reçues (voir l'excellent article The ultimate SO_LINGER page, or: why is my tcp not reliable).

L'entier en question est fixé à 32 bits. Si on programme un client EPP en Python, l'utilisation brutale du module struct ne suffit pas forcément. En effet :

struct.pack("I", length)

force un entier (int) mais pas forcément un entier de 32 bits. Pour forcer la taille, il faut utiliser également, comme précisé dans la documentation, les opérateurs < et >, qui servent aussi à forcer la boutianité (merci à Kim-Minh Kaplan pour son aide sur ce point). Voici une démonstration (un "l" standard fait 4 octets alors que le type long de C peut faire 4 ou 8 octets) :

# Machine 32 bits :

Python 2.4.4 (#2, Apr  5 2007, 20:11:18) 
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import struct
>>> print struct.calcsize("l")
4
>>> print struct.calcsize(">l")
4
# Machine 64 bits :

Python 2.4.5 (#2, Mar 11 2008, 23:38:15) 
[GCC 4.2.3 (Debian 4.2.3-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import struct
>>> print struct.calcsize("l")
8
>>> print struct.calcsize(">l")
4

Si on a quand même un doute, on peut tester la taille obtenue mais ce code est probablement inutile (merci à David Douard pour son aide ici) :


# Get the size of C integers. We need 32 bits unsigned.
format_32 = ">I"
if struct.calcsize(format_32) < 4:
    format_32 = ">L"              
    if struct.calcsize(format_32) != 4:
        raise Exception("Cannot find a 32 bits integer")
elif struct.calcsize(format_32) > 4:
    format_32 = ">H"                
    if struct.calcsize(format_32) != 4:
        raise Exception("Cannot find a 32 bits integer")
else:
    pass
...
def int_from_net(data):
    return struct.unpack(format_32, data)[0]

def int_to_net(value):
    return struct.pack(format_32, value)

L'algorithme complet d'envoi est :

epp_as_string = ElementTree.tostring(epp, encoding="UTF-8")
# +4 for the length field itself (section 4 mandates that)
# +2 for the CRLF at the end
length = int_to_net(len(epp_as_string) + 4 + 2)
self._socket.send(length)
self._socket.send(epp_as_string + "\r\n")

et la lecture :

data = self._socket.recv(4) # RFC 4934, section 4, the length 
                            # field is 4 bytes long
length = int_from_net(data) 
data = self._socket.recv(length-4)
epp = ElementTree.fromstring(data)
if epp.tag != "{%s}epp" % EPP.NS:
     raise EPP_Exception("Not an EPP instance: %s" % epp.tag)
xml = epp[0]

Le code Python complet (qui ne met en œuvre qu'une petite partie de EPP, le but était juste de tester ce RFC 4934), utilisant la bibliothèque ElementTree, est disponible en ligne.


Téléchargez le RFC 4934


L'article seul

RFC 4122: A Universally Unique IDentifier (UUID) URN Namespace

Date de publication du RFC : Juillet 2005
Auteur(s) du RFC : Paul J. Leach (Microsoft), Michael Mealling (Refactored Networks, LLC), Rich Salz (DataPower Technology, Inc.)
Chemin des normes
Première rédaction de cet article le 1 avril 2008


Ce RFC décrit un espace de noms URN pour les UUID, une famille d'identificateurs uniques, obtenus sans registre central. Il a depuis été remplacé par le RFC 9562.

Les UUID, également connus sous le nom de GUID, sont issus à l'origine du système des Apollo, adopté ensuite dans la plate-forme DCE. Ils ont une taille fixe, 128 bits, et sont obtenus localement, à partir d'un autre identificateur unique comme l'adresse MAC ou bien en tirant au hasard, la grande taille de leur espace de nommage faisant que les collisions sont très improbables (section 2 du RFC). Ce RFC reprend la spécification de DCE de l'Open Group (ex-OSF) et ajoute la définition d'un espace de noms pour des URN (section 3). (Il existe aussi une norme ITU sur les UUID et un registre des UUID, pour ceux qui y tiennent.)

Les UUID peuvent donc convenir pour identifier une entité sur le réseau, par exemple une machine mais aussi, vu leur nombre, comme identificateur unique pour des transactions (ce qui était un de leurs usages dans DCE). En revanche, ils ne sont pas résolvables.

Sur Unix, on peut fabriquer un UUID avec la commande uuidgen, qui affiche la représentation texte standard que normalise notre RFC :

% uuidgen 
317e8ed3-1428-4ef1-9dce-505ffbcba11a
% uuidgen
ec8638fd-c93d-4c6f-9826-f3c71436443a

On trouve les UUID à de nombreux endroits en informatique, par exemple dans les logiciels Mozilla (cf. http://developer.mozilla.org/en/docs/Generating_GUIDs).

Pour l'affichage sous forme d'URN (RFC 8141), on ajoute juste l'espace uuid par exemple urn:uuid:ec8638fd-c93d-4c6f-9826-f3c71436443a.

La section 4 du RFC détaille le format interne de l'UUID (en dépit des apparences, l'UUID n'est pas plat, il a une structure). Notamment, la section 4.1.3 précise le champ Version (qui devrait plutôt s'appeler Type), puisqu'un UUID peut être généré à partir d'une estampille temporelle (version 1, option -t de uuidgen), d'une valeur aléatoire (version 4, option -r) ou d'un résumé cryptographique (version 3).

L'UUID utilise également l'adresse MAC de la machine, si elle est présente (section 4.1.6).

La section 4.2, elle, décrit le processus de génération d'un UUID à base temporelle. Idéalement, il faut utiliser une graine enregistrée sur le disque (pour éviter de générer des UID identiques) ainsi que l'instant de la génération. Mais lire sur le disque prend du temps (alors qu'on peut vouloir générer des UUID rapidement, par exemple pour identifier des transactions) et l'horloge de la machine n'a pas toujours une résolution suffisante pour éviter de lire deux fois de suite le même instant. Cette section contient donc également des avis sur la génération fiable d'UUID, par exemple (section 4.2.1.2) en gardant en mêmoire le nombre d'UUID générés, pour les ajouter à l'heure. Si on préfère des UUID créés par résumé cryptographique, la section 4.3 est là pour cela.

La section 6, consacrée à la sécurité, rappelle qu'un UUID ne doit pas être utilisé comme capacité (car il est trop facile à deviner) et qu'il ne faut pas demander à un humain de comparer deux UUID (ils se ressemblent trop pour un œil humain).

L'annexe A est une excellent mise en œuvre, en langage C, des principes décrits dans la section 4. Si on préfère utiliser Python, il existe, depuis la version 2.5, un module UUID qui offre des fonctions de génération d'UUID de différentes versions :

import uuid

myuuid = uuid.uuid1() # Version 1, Time-based UUID
otheruuid = uuid.uuid4() # Version 4, Random-based UUID
yetanotheruuid = uuid.uuid5(uuid.NAMESPACE_DNS,
                            "www.example.org")
                      # Version 5, a name hashed by SHA1
if (myuuid == otheruuid or \
    myuuid == yetanotheruuid or \
    otheruuid == yetanotheruuid):
    print "They are equal, PANIC!"

print myuuid
print otheruuid
print yetanotheruuid
    

À noter que le SGBD PostgreSQL, à partir de la version 8.3, inclus un type UUID.

essais=> CREATE TABLE Transactions (id uuid, value INT);
CREATE TABLE
essais=> INSERT INTO Transactions VALUES 
           ('74738ff5-5367-5958-9aee-98fffdcd1876', 42);
INSERT 0 1
essais=> INSERT INTO Transactions VALUES 
            ('88e6441b-5f5c-436b-8066-80dca8222abf', 6);
INSERT 0 1
essais=> INSERT INTO Transactions VALUES ('Pas correct', 3);
ERROR:  invalid input syntax for uuid: "Pas correct"
essais=> SELECT * FROM Transactions;
                  id                  | value 
--------------------------------------+-------
 74738ff5-5367-5958-9aee-98fffdcd1876 |    42
 88e6441b-5f5c-436b-8066-80dca8222abf |     6
(2 rows)

Il existe plusieurs exemples d'utilisation des UUID. Par exemple, Linux s'en sert pour identifier les disques attachés à la machine, de préférence à l'ancien système où l'ajout d'un nouveau disque pouvait changer l'ordre des numéros sur le bus et empêcher le système de trouver un disque. Un /etc/fstab typique sur Linux contient donc désormais des :

UUID=da8285a0-3a70-413d-baed-a1f48d7bf7b2       /home   ext3 defaults ...

plutôt que les anciens :

/dev/sda3       /home           ext3    defaults  

car sda3 n'est pas un identificateur stable. L'UUID, lui, est dans le système de fichiers et ne changera pas avec les changements sur le bus. On peut l'afficher avec dumpeéfs :


# dumpe2fs -h /dev/sda3
...
Filesystem UUID:          da8285a0-3a70-413d-baed-a1f48d7bf7b2
...


Téléchargez le RFC 4122


L'article seul

RFC 5128: State of Peer-to-Peer(P2P) Communication Across Network Address Translators(NATs)

Date de publication du RFC : Mars 2008
Auteur(s) du RFC : P. Srisuresh (Kazeon), B. Ford (MIT), D. Kegel (kegel.com)
Pour information
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 30 mars 2008


Pour faire face à la plaie du NAT, les applications pair-à-pair ont développé de nombreuses techniques pour pouvoir passer à travers les routeurs NAT. Ce RFC les documente.

Le groupe de travail Behave de l'IETF travaille à normaliser les techniques permettant de contourner les NAT et les nombreux problèmes qui leur sont associés. Quoique certains à l'IETF auraient préféré qu'aucun travail permettant de rendre les NAT plus supportables ne soit effectué, le consensus a finalement été qu'il valait mieux travailler à faire fonctionner les applications malgré les NAT, plutôt que de rêver supprimer ceux-ci.

Ce RFC ne normalise pas un protocole mais examine l'état de l'art, en matière de fonctionnement en présence de NAT. Il rappelle que les NAT n'apportent rien en matière de sécurité mais, comme cette technique est largement déployée, il est préférable de documenter les bricolages divers qu'utilisent les applications forcées de vivre derrière un NAT.

Il existe deux grandes catégories de techniques pare-NAT. Celles qui reposent sur une signalisation explicite de l'application au routeur NAT. La plus connue est UPNP. L'IETF a son MIDCOM (cf. RFC 4097) pour le même rôle. Ces techniques ne sont pas étudiées dans notre RFC.

Les autres techniques pare-NAT sont celles qui ne nécessitent pas forcément de communication explicite entre l'application et le routeur NAT. Chacune est détaillée dans une section de ce RFC.

La terminologie utilisée est celle du RFC 2663, pas celle des « cônes » du RFC 3489 et la section 2 est entièrement occupée à débroussailler les questions de vocabulaire.

Les techniques décrites ensuite sont :

  • Le relayage, où une machine située à l'extérieur relaie les paquets entre les deux pairs coincés derrière leur NAT. Très consommatrice de ressources pour le relais, cette technique n'est en général qu'un dernier recours pour les applications P2P. (Le protocole TURN, RFC 5766, est un exemple de cette technique.)
  • Le retournement où un des deux pairs peut demander à l'autre d'être l'initiateur de toutes les connexions. Cela n'a d'intérêt que si un des deux n'est pas derrière un NAT.
  • Le perçage, ainsi nommé parce que les applications tentent de percer un trou dans le routeur NAT pour laisser les paquets passer. Le principe est d'envoyer un paquet vers le pair, créant ainsi une entrée dans la table du routeur NAT, pour un certain port. Des paquets en sens inverse qui connaissent le port (par exemple parce qu'ils ont contacté un serveur de rendez-vous STUN) peuvent alors y écrire.
  • La prédiction de ports UDP ou TCP, très difficile, car elle repose sur des heuristiques sur le prochain numéro de port que choisira le routeur NAT pour sa table.

La section 5 résume ces techniques et les recommandations des auteurs. Le perçage est la technique la plus efficace à l'heure actuelle.

La section 6, consacrée à la sécurité, est très détaillée car les NAT crée de nombreux problèmes de sécurité.

Notre RFC contient aussi, en section 4, une bonne liste des articles sur le sujet, afin d'aider l'auteur d'applications qui veut maximiser les chances de fonctionnement dans toutes les circonstances.


Téléchargez le RFC 5128


L'article seul

RFC 5198: Unicode Format for Network Interchange

Date de publication du RFC : Mars 2008
Auteur(s) du RFC : J. Klensin, M. Padlipsky
Chemin des normes
Première rédaction de cet article le 30 mars 2008


Il ne reste plus beaucoup de normes Internet qui soient limitées à l'ASCII et elles tombent une à une. Un des problèmes rencontrés pour éliminer les dernières est que certains protocoles transmettent du texte et que « texte », à l'IETF, voulait toujours dire seulement ASCII. Voici que ce RFC introduit un nouveau type de texte, utilisant Unicode.

Pendant longtemps, plusieurs normes comme le RFC 959 sur FTP faisaient référence à des données de type texte, c'est-à-dire sans formatage, avec des lignes terminées par la séquence CRLF (Carriage Return puis Line Feed). Cette définition du texte, souvent nommé « NVT », datant du RFC 854, limitait le texte au jeu de caractères ASCII, jeu de caractères qui ne permet pas de représenter toutes les écritures du monde. Où est le problème ? peut-on se demander. Pourquoi ne pas simplement remplacer ASCII par Unicode partout dans le texte ? C'est en effet la bonne solution mais le diable est dans les détails et, Unicode étant beaucoup plus riche qu'ASCII et n'étant pas figé, traiter ces détails a pris du temps. (Et ce RFC a fait l'objet de nombreuses controverses.) Unicode a plusieurs encodages, plusieurs façons de représenter une fin de ligne et même plusieurs façons de représenter le même caractère.

Le RFC pose donc comme règles (section 2) :

  • Jeu de caractères Unicode.
  • Utilisation de l'encodage UTF-8, normalisé dans le RFC 3629.
  • Normalisation obligatoire avec le mécanisme NFC, qui combine le plus possible les caractères.
  • Utilisation de la séquence CRLF pour les sauts de ligne.

Le choix d'UTF-8 provient de sa large utilisation dans beaucoup de protocoles Internet, due en partie au fait qu'il est un sur-ensemble de l'encodage ASCII.

Le choix du CRLF comme indicateur d'une fin de ligne est également dû à sa large utilisation aujourd'hui. Bien qu'Unicode aie des caractères plus adaptés (Line separator, U+0028 et Paragraph separator, U+0029), ils sont très peu utilisés. La passionnante annexe C discute en détail ce choix.

La normalisation fait l'objet d'une section 3 détaillée. Elle est nécessaire car Unicode permet de représenter un caractère de plusieurs façons. Ainsi, U+2126, Ohm sign, Ω, a une forme canonique qui est U+03A9, Greek capital letter omega , Ω, (les symboles scientifiques ne sont normalement pas codés séparément dans Unicode et ceux qui le sont sont normalisés dans une lettre ordinaire). Cas plus connu, deux caractères peuvent se combiner par exemple U+0061 U+0300 se combinent, par le mécanisme NFC, en U+00E0 (la première séquence est faite d'un petit a et de l'accent grave combinant, la seconde est donc juste un à). L'obligation de normalisation rendra donc plus facile la comparaison des textes (la section 6 sur la sécurité note toutefois que le pare-feu prudent ne doit pas supposer que l'envoyeur respectera la norme).

La section 4 couvre un autre problème délicat, celui des versions d'Unicode. Contrairement à ASCII, qui était figé dès le début, des nouveaux caractères sont ajoutés dans Unicode régulièrement, ainsi que de nouvelles règles de normalisation. Si on ne fait pas attention, une nouvelle version d'Unicode pourrait rendre invalides (car non normalisés) des textes auparavant valables. Pour éviter cela, notre RFC interdit l'utilisation des points de code non affectés. Les politiques de stabilité du consortium Unicode garantissent que, dans ce cas, la normalisation NFC est stable (la section 5.2 discute également ce choix).

La section 5 explique quelles normes pourrait tirer profit de ce nouveau RFC. Celles qui utilisent déjà UTF-8, comme LDAP, ne sont pas concernées. Mais, outre FTP, déjà cité, cette nouvelle référence pourrait intéresser des protocoles comme whois (dont le RFC 3912 note que, en théorie, il est limité à ASCII).

Cas rare chez les RFC, il se termine par des annexes traitant d'histoire. L'excellente annexe A revient sur l'histoire tourmentée des jeux de caractères dans Internet, du RFC 20, qui imposera ASCII, au RFC 318 qui sera le premier à mentionner le « NVT » (Network Virtual Terminal). L'annexe B, elle, extrait de différents RFC, ce qui est à ce jour la définition la plus complète et la plus correcte de la norme NVT... que notre RFC remplace. Bel hommage du présent au passé.


Téléchargez le RFC 5198


L'article seul

Comptes Unix stockés sur LDAP

Première rédaction de cet article le 26 mars 2008
Dernière mise à jour le 30 novembre 2008


Si on gère de nombreux ordinateurs multi-utilisateurs, on se pose forcément la question de la centralisation des comptes, des informations sur les utilisateurs. Il est très pénible de devoir créer un compte sur N machines dès qu'un nouvel employé arrive ou de devoir se rappeler des M mots de passe précédents parce qu'on ne les a pas changé sur toutes les machines.

Il existe plusieurs solutions techniques à ce problème, et je présente ici l'utilisation de LDAP pour gérer une base centralisée de comptes, notamment pour des machines Unix.


L'article complet

Remplacer du texte en XSLT

Première rédaction de cet article le 26 mars 2008


Si on produit un format quelconque à partir de XML, par exemple du CSV ou bien du LaTeX, on est souvent confronté au cas de caractères qui, sans créer de problèmes dans le source XML, sont « spéciaux » pour le format de destination et nécessitent donc d'être protégés (to be escaped, dans la langue de J. K. Rowling). Comment le faire en XSLT ?

La technique présentée ici est largement inspirée d'un excellent article de Jenni Tennison. Les exemples ci-dessous concernent la production de LaTeX pour lequel on peut trouver une liste des caractères « spéciaux ». On définit d'abord un espace de noms XML pour les données sur ces caractères spéciaux :


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:tolatex="http://www.bortzmeyer.org/xmlns/tolatex"
...

puis on définit ces caractères et leur remplacement. On note que cette définition est complètement séparée du code qui fait le remplacement, pour faciliter la maintenance :


  <tolatex:replacements>
    <tolatex:replacement search="$">DOLLAR-TO-ESCAPE</tolatex:replacement>
    <tolatex:replacement search="\">$\backslash$</tolatex:replacement>
    <!-- Difficult circularity in escaping -->
    <tolatex:replacement search="DOLLAR-TO-ESCAPE">\$</tolatex:replacement>
    <tolatex:replacement search="#">\#</tolatex:replacement>    
    <tolatex:replacement search="%">\%</tolatex:replacement>    
    <tolatex:replacement search="_">\_</tolatex:replacement>    
...
    <tolatex:replacement search="&#xa0;">~</tolatex:replacement>
    <tolatex:replacement search="&amp;">\&amp;</tolatex:replacement>
    <tolatex:replacement search="&#x153;">\oe{}</tolatex:replacement>
    <tolatex:replacement search="&#x20ac;">\EUR{}</tolatex:replacement>
  </tolatex:replacements>

  <xsl:variable name="replacements"
    select="document('')/xsl:stylesheet/tolatex:replacements" />


Quand on rencontre du texte, le gabarit suivant est appelé. Il appelle alors replace en passant un paramètre qui est la position dans l'élément <tolatex:replacements> (au début, un) :


  <xsl:template name="escape_text" match="text()">
    <xsl:variable name="position" select="1"/>
    <xsl:call-template name="replace">
        <xsl:with-param name="position" select="$position"/>
        <xsl:with-param name="content" select="string(.)"/>
    </xsl:call-template>
  </xsl:template>

En quoi consiste le gabarit replace ? Il est récursif, utilisant pour cela le paramètre position. Il parcourra ainsi la totalité des <tolatex:replacement>.


  <xsl:template name="replace">
    <xsl:param name="position" select="1"/>
    <xsl:param name="content"/>
    <xsl:variable name="transformed">
      <xsl:call-template name="string_replace">
        <xsl:with-param name="string" select="$content" />
        <xsl:with-param name="search"
          select="$replacements/tolatex:replacement[$position]/@search" /> 
        <xsl:with-param name="replace"
          select="$replacements/tolatex:replacement[$position]" /> 
      </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$position &lt;
                             count($replacements/tolatex:replacement)">
        <!-- There are still replacements to perform. Call myself. -->
        <xsl:call-template name="replace">
          <xsl:with-param name="position" select="$position + 1"/>
          <xsl:with-param name="content" select="$transformed"/>        
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
         <!-- No more replacements to do -->
         <xsl:value-of select="$transformed"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

Pour une position donnée dans l'élément <tolatex:replacements>, le gabarit replace appelera string_replace qui va parcourir une chaîne de caractères en effectuant le remplacement indiqué :


  <xsl:template name="string_replace">
    <xsl:param name="string"/>
    <xsl:param name="search"/>
    <xsl:param name="replace"/>
    <xsl:choose>
      <xsl:when test="contains($string, $search)">
        <xsl:variable name="rest">
          <xsl:call-template name="string_replace">
            <xsl:with-param name="string" select="substring-after
                                                  ($string, $search)"/>
            <xsl:with-param name="search" select="$search"/>
            <xsl:with-param name="replace" select="$replace"/>
          </xsl:call-template>
        </xsl:variable>
        <xsl:value-of 
              select="concat(substring-before($string, $search), $replace, $rest)"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$string"/>
      </xsl:otherwise>
    </xsl:choose>

Ce gabarit string_replace est lui aussi récursif, pour pouvoir effectuer plusieurs remplacements dans la chaîne de caractères, au cas où un caractère spécial apparaitrait plusieurs fois.

Une version complète se trouve dans les sources de ce blog, voir notamment le fichier schema/common-latex.xsl.


L'article seul

Le mode hexadécimal d'Emacs

Première rédaction de cet article le 26 mars 2008


Après dix-huit ans d'utilisation d'Emacs, je découvre encore des choses sur cet éditeur. J'ai parfois à examiner un fichier à la recherche de caractères pas évidents à voir à l'œil nu, comme l'espace insécable et un mode special d'Emacs permet de faire très facilement.

M-x hexl-mode et on est lancé dans le mode hexadécimal où apparait tout à fait à gauche le nombre d'octets depuis le départ, puis la valeur en hexadécimal du contenu du fichier puis ce même contenu en mode normal. En pointant un des caractères, le curseur clignote sur l'emplacement de sa valeur en hexadécimal. On peut aussi rentrer un caractère quelconque en tapant sa valeur en hexadécimal (C-M-x, l'aide du mode fonctionne avec la commande habituelle, C-h m).

Contrairement à d'autres éditeurs binaires, c'est Emacs, toutes les commandes habituelles fonctionnent, il est donc très facile d'explorer un fichier à la recherche de caractères inhabituels.

C-c C-c ramène au mode normal.


L'article seul

Version PDF des articles de ce blog

Première rédaction de cet article le 25 mars 2008
Dernière mise à jour le 2 avril 2009


Malgré les avantages de la lecture sur écran, notamment pour la préservation des forêts, la lecture sur papier a des bienfaits considérables, notamment le fait qu'on puisse la pratiquer debout dans le métro ou allongé dans son bain. Une version PDF des articles de ce blog n'était donc pas inutile. Elle existe désormais et est accessible depuis chaque article.

Le plus agaçant avec les soi-disants e-books, outre leur limitation aux textes distribués par un éditeur payant, est leur prix : pas question de les emporter sur la plage, au risque de perdre ou de se faire voler un engin dont le prix évoque plutôt l'ordinateur que le livre.

Lorsqu'un article en ligne est un peu long, et que je préférerai le lire à loisir ailleurs que dans mon bureau, il m'arrive donc, plutôt que d'utiliser un engin électronique, de l'imprimer. Ce blog dispose d'une feuille de style CSS spécifique à l'impression, qui permet notamment de ne pas imprimer le menu (#left-column { display: none; }). On peut ainsi imprimer depuis son navigateur et avoir un résultat acceptable. (C'est un excellente pratique, que j'ai empruntée à Wikipédia, où l'impression des articles depuis le navigateur est très bien conçue.)

Mais on peut obtenir une qualité typographique encore meilleure en utilisant LaTeX. C'est ainsi que j'ai modifié les programmes qui gèrent ce blog pour produire du PDF en passant par LaTeX.

Le résultat est visible sous forme d'un lien discret en bas de chaque page. Si vous voulez voir la version PDF d'un article, vous pouvez aussi simplement éditer l'adresse en remplaçant le .html par un .pdf. N'hésitez pas à me tenir au courant d'éventuels problèmes.

Parmi les paquetages LaTeX utilisés :

  • vmargin, pour définir facilement les marges du document,
  • fancyhdr, pour mettre de jolis en-têtes et pieds de page.

L'article seul

Gérer tout Unicode avec LaTeX ?

Première rédaction de cet article le 25 mars 2008


Pour produire des documents de grande qualité typographique, surtout si on veut le faire de manière massive, sans passer par un cliquodrome nécessitant plusieurs clics par fichier, LaTeX reste imbattable. Mais si les documents contiennent de l'Unicode ?

LaTeX dispose depuis longtemps de moyens de formater du texte écrit dans différentes langues et différentes écritures. Par exemple, avec le paquetage Babel, on peut écrire des choses comme :

\usepackage[latin1]{inputenc}
\usepackage[french]{babel}

et typographier ainsi du français correct, directement saisi en Latin-1. Si on veut faire du grec, qui utilise un autre alphabet, ce n'est pas plus difficile :

\usepackage[greek]{babel}
...
\textgreek{...}

Mais ces techniques (décrites dans Langues exotiques [sic]) nécessitent de marquer le texte en connaissant sa langue. Elles ne reposent pas sur le modèle Unicode, où on peut représenter de manière non ambigüe tout caractère utilisé dans le monde. Écrire ces caractères en LaTeX n'est pas très difficile. On peut utiliser l'encodage UTF-8 ainsi :

\usepackage[utf8]{inputenc}

et taper ensuite de l'UTF-8. Mais cela ne règle que l'entrée dans le moteur TeX, pas la sortie, le rendu. En effet, les caractères non latins sont transformés en commandes LaTeX, mais pour un sous-ensemble d'Unicode seulement. Et ça ne marche pas à tous les coups. Ainsi, si le texte contient le caractère Ω (U+03A9, grand oméga), LaTeX proteste :

...
(/usr/share/texmf-texlive/tex/latex/ucs/data/uni-33.def)
(/usr/share/texmf-texlive/tex/latex/ucs/data/uni-3.def)
! Undefined control sequence.
\u-default-937 #1->\textOmega

l.135 omega}" , ...
                  , (les symboles scientifiques ne sont normalement pas
?

Le grand oméga a été transformé en une commande LaTeX, textOmega... qui n'existe pas. (Ironie, le Ω - U+2126, Ohm - passe sans problème.) Pour afficher ce caractère grec, il faudrait installer des polices grecques comme cbgreek ou cm-lgc et marquer ces caractères avec une commande comme textgreek, plus haut.

Même chose avec des caractères cyrilliques (ici le И, U+418, le grand I de Ivan) :

(/usr/share/texmf-texlive/tex/latex/ucs/data/uni-4.def)
! Undefined control sequence.
\u-default-1048 #1->\CYRI

l.98 programmes. En prenant l'exemple du ...

?

Pire, il n'y a pas de solution de repli, permettant de dire à LaTeX « si tu ne sais pas afficher un caractère, mets un joli carré blanc à la place ». Un caractère inexistant stoppe le programme LaTeX !

Si on tape directement en LaTeX, cela peut être supportable. Mais un programme qui recevrait de l'Unicode devrait décider d'une langue avant de pouvoir produire du LaTeX. Il devrait tester chaque caractère et faire quelque chose du genre (en pseudo-code) :

case groupe(le_caractère) is:

when greek => ...

when russian => ...

when arabic => ...

Des extensions complètement Unicode avaient été prévues comme Omega mais ont toutes été abandonnées. À l'heure actuelle, produire du LaTeX à partir de données contenant de l'Unicode quelconque est donc très pénible. C'est pour cela que la version PDF de mon blog contient souvent un triste remplacement « Caractère Unicode non affiché ».

Merci à Erwan David, Ollivier Robert, Marc Baudoin, Bertrand Petit et Kim-Minh Kaplan pour leur aide et explications.


L'article seul

RFC 5141: A Uniform Resource Name (URN) Namespace for the International Organization for Standardization (ISO)

Date de publication du RFC : Mars 2008
Auteur(s) du RFC : J. Goodwin (ISO), H. Apel (ISO)
Pour information
Première rédaction de cet article le 22 mars 2008


Un nouveau venu dans la famille des NID (Namespace identifier), les autorités qui gèrent un groupe d'URN, l'ISO, organisme international de normalisation, qui pourra ainsi enfin donner à ses textes, notamment aux normes, un identifiant unique et automatiquement analysable.

La section 1 du RFC présente l'ISO et ses procédures. Cette présentation est un peu idéalisée et oublie de signaler que l'ISO est renommée pour sa fermeture. Il est difficile d'en faire partie (l'ISO est une fédération d'organismes nationaux comme l'AFNOR en France, eux-mêmes en général tout aussi fermés), les processus sont compliqués et sans transparence.

Les normes produites ne sont pas distribuées sur Internet, sauf exceptions. Cette mentalité a beaucoup contribué à l'échec des protocoles OSI par rapport à ceux de l'Internet, normalisés dans des RFC librement accessibles. Outre les exceptions citées plus haut, parfois, les auteurs ou les agences de maintenance de la norme distribuent une version non officielle de la norme à partir de leur site (par exemple, Schematron, norme n° 19757 , est distribuée par son auteur en http://www.schematron.com/spec.html.) La section 4 du RFC parle entre autres de cette question, en faisant porter la responsabilité de cet état de fait sur les organisations membres de l'ISO ou associées, tout en prétendant que la disponibilité de la norme n'est finalement pas une question si importante (« Only the product engineer or software tool builder actually needs access to the text »).

Comme le détaille cette section, le vote à l'ISO est par pays. Ce ne sont pas les participants aux groupes de travail (souvent de vrais experts, comme cela a été le cas pour le groupe qui a donné à RelaxNG le statut de norme ISO) qui votent mais les représentants officiels de chaque pays. Ces votes étant non publics, le citoyen français n'a aucun moyen de savoir ce qu'a voté son pays. Par exemple, la rumeur dit que la France avait voté NON à ISO 639-3 mais on ne peut pas le vérifier, les votes n'étant pas connus.

Le cahier des charges de ces identificateurs ISO apparait dans l'excellente section 3 du RFC. Il s'agit d'avoir des identificateurs uniques, stables dans le temps, lisibles par des humains (d'autres critères figurent dans cette section). Chacun de ces choix est justifié en détail et on ne peut que recommander la lecture de cette section à tous ceux qui travaillent sur un projet de famille d'identificateurs. L'annexe A contient un examen d'autres identificateurs qui avaient été envisagés et rejetés, comme les OID du RFC 3061.

Avec la section 2 commence la description de ce nouveau groupe d'URN (RFC 8141). Le NID (Namespace Identifier) sera iso et le reste de l'URN identifiera le texte (pas forcément une norme), son statut, l'édition actuelle, la langue, etc.

Par exemple, la norme C, d'origine ANSI (l'ANSI est le membre états-unien de l'ISO), développée avec l'IEC et portant le n° 9899, seconde édition, en anglais, sera urn:iso:std:iso-iec:9899:ed-2:en (elle n'est apparemment pas disponible en ligne mais on peut la trouver sur eDonkey sous le nom ISO-C99-final-ISO9899-ed2.pdf). La norme ISO 15924 sur les écritures pourrait, elle, se noter urn:iso:std:iso:15924:en,fr (on notera qu'elle est disponible en deux langues, français et anglais et elle fait partie des normes distribuées par son agence de maintenance, le consortium Unicode).

La section 2.8 décrit une correspondance entre ces URN et des URI http, ce qui permettrait de résoudre les URN, grâce à une passerelle que l'ISO envisage de déployer (apparemment, elle n'est pas encore en service). (Cela ne veut pas dire qu'on aura accès à la norme, mais seulement aux métadonnées sur celle-ci.) Ainsi, la norme « Codes de représentation des sexes humains » (1 pour les hommes et 2 pour les femmes) dont l'URN serait urn:iso:std:iso-iec:5218:ed-1:en,fr aurait un URL de http://standards.iso.org/iso-iec/5218/ed-1/en,fr.


Téléchargez le RFC 5141


L'article seul

GPGME, une bibliothèque pour faire de la cryptographie assez simplement

Première rédaction de cet article le 17 mars 2008
Dernière mise à jour le 16 avril 2008


Sur l'Internet, les données qui circulent peuvent être modifiées ou écoutées à tout moment. Il est donc nécessaire d'utiliser la cryptographie pour protéger ces données. Mais cette technique est difficile et pleine de pièges. Il vaut donc mieux utiliser une bibliothèque comme GPGME, qui permet au programmeur non spécialiste de cryptographie d'ajouter des fonctions de cryptographie à ses programmes.


L'article complet

KVM, une technique de virtualisation simple et efficace

Première rédaction de cet article le 9 mars 2008
Dernière mise à jour le 16 avril 2008


Dans la grande famille des solutions de virtualisation, permettant de faire tourner un système d'exploitation sur un autre, KVM, spécifique à Linux, permet d'exécuter du code natif, donc avec de bonnes performances, mais sans nécessiter d'aide de la part du système d'exploitation hébergé (donc on peut lancer un autre système que Linux).

KVM est un module du noyau Linux qui offre un certain nombre de services de virtualisation permettant à sa partie en mode utiliseur, l'émulateur Qemu de parler au matériel avec efficacité. Notamment, si le processeur de la machine hôte est le même que celui de la machine hébergée, il n'y a pas besoin d'une phase d'interprétation, le code peut être évalué directement, donc à vitesse normale (Qemu seul est très lent).

Le fait que KVM+Qemu présentent une véritable machine virtuelle permet de faire tourner des systèmes d'exploitation non modifiés, dont on n'a qu'un binaire, comme par exemple Microsoft Windows. Si le système hôte doit être un Linux, le système hébergé est libre, contrairement à User-Mode-Linux. Contrairement à Xen, il ne nécessite pas de modifier le système d'exploitation invité. Je fais ainsi tourner un FreeBSD sans aucune modification sur un PC Ubuntu Linux.

KVM ne fonctionne pas entièrement en logiciel. Il a besoin d'un support du processeur (qui est légèrement différent entre Intel et AMD, toutes les instructions ultérieures sont pour un Intel). Sur mon Dell Latitude D430, ce support n'est pas activé automatiquement, il faut le faire dans le BIOS. Même chose sur les gros serveurs Dell Poweredge, il faut activer l'option Virtualization dans les options CPU. On peut ensuite tester qu'il est bien activé avec :

% grep vmx /proc/cpuinfo

Prenons maintenant l'exemple de l'installation de FreeBSD 7. Je télécharge une image ISO. On doit d'abord créer le fichier qui servira de disque dur à la machine virtuelle :

% qemu-img create -f qcow Machines-Virtuelles/snape-freebsd.qemu-cow 1400M

Ensuite, je lance KVM avec le script suivant (pour charger les modules noyau nécessaires) :

#!/bin/sh

cd $HOME/Machines-Virtuelles

sudo modprobe kvm
sudo modprobe kvm-intel

kvm -m 512 -hda snape-freebsd.qemu-cow -cdrom $HOME/tmp/7.0-RELEASE-i386-bootonly.iso -boot d

(Les options de la commande kvm sont les mêmes que celles de qemu.) Le programme d'installation de FreeBSD se lance alors et on peut installer FreeBSD comme d'habitude. Une fois que cela est fait, on peut désormais lancer KVM sur le « disque dur » sans CDROM :

% kvm -m 512 -hda snape-freebsd.qemu-cow -boot c

À noter que, si on ne veut pas installer soi-même, on trouve énormément d'images toutes prêtes, pour les principaux systèmes libres, sur Free OS Zoo.

Pour le réseau, c'est un peu plus compliqué. Il existe de nombreuses méthodes (décrites dans la documentation de Qemu). J'utilise ici tap, qui malheureusement nécessite d'être root pour lancer kvm, mais fournit le plus de possibilités. Le script est donc modifié ainsi :

sudo kvm -m 512 -hda snape-freebsd.qemu-cow -net nic -net tap -boot c

KVM lancera /etc/kvm/kvm-ifup qui, chez moi, contient :

#!/bin/sh -x

# My code:

iface=$1

# The Qemu host
myipv4addr=$(ip addr ls  eth0 | awk '/inet / {print $2}' | cut -d/ -f1)

remipv4addr=10.1.1.42

# IPv4
sudo /sbin/ifconfig $iface $myipv4addr  netmask 255.255.255.255
sudo route add -host $remipv4addr dev $iface

# activate ip forwarding
sudo sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'

# activate ARP proxy to "spoof" arp address
sudo sh -c "echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp"
sudo sh -c "echo 1 > /proc/sys/net/ipv4/conf/${iface}/proxy_arp"

# set "spoofed" arp address
sudo arp -Ds $remipv4addr eth0 pub

Si on veut gérer plusieurs machines virtuelles, chacune avec sa propre adresse, une solution possibe est de modifier le début du script ainsi :

if [ $iface == "tap0" ]; then
    remipv4addr=10.1.82.3
elif [ $iface == "tap1" ]; then
    remipv4addr=10.1.82.4
else
    exit 1
fi

Les numéros des interfaces tap seront attribués dans l'ordre de démarrage. Si on veut éviter que les machines ne changent d'adresse IP selon cet ordre, on peut définir un numéro explicitement en remplaçant -net tap par -net tap,ifname=tapN. (Il serait bien agréable que la valeur de l'option -name soit passée au script kvm-ifup mais cela ne semble pas être le cas.)

Et pour IPv6 ? C'est plus complexe car l'équivalent du proxy ARP est très pénible :

myipv6addr=$(ip addr ls  ${lan_iface}  | awk '/inet6 / {print $2}' | \
       cut -d/ -f1 |  head -n1)

if [ $iface == "tap0" ]; then
    ...
    remipv6addr=2001:660:3003:3::1:3
...

# IPv6
sudo /sbin/ifconfig $iface add $myipv6addr
sudo route add -Ainet6 $remipv6addr dev $iface 

# Proxy NDP (Neighbor Discovery Protocol)
sudo ip -6 neigh add proxy $remipv6addr dev ${lan_iface}

# Apparently, you need to put *every* IPv6 address of the LAN here :-(
# http://gentoo-wiki.com/IPV6_And_Freebox
lanipv6addr="2001:660:3003:3::1 2001:660:3003:3::1:1 2001:660:3003:3::1:2 2001:660
:3003:3:219:b9ff:fee4:25f9"
for addr in $lanipv6addr; do
    sudo ip -6 neigh add proxy $addr dev $iface
done

On notera que la console par défaut de KVM ne permet pas le copier/coller, ce qui est très pénible si on veut signaler une bogue en donnant tous les détails. La méthode que j'utilise alors est la console série. On ajoute l'option -serial file:tmp/MAMACHINE.log au lancement de KVM et, aux options de démarrage du noyau Linux (si on utilise Grub, ces options peuvent se changer en tapant 'e' comme Edit), console=ttyS0,115200.


L'article seul

Fiche de lecture : Les ghettos du gotha

Auteur(s) du livre : Michel Pinçon, Monique Pinçon-Charlot
Éditeur : Seuil
978 2 02 088920 9
Publié en 2008
Première rédaction de cet article le 8 mars 2008


Depuis plusieurs ouvrages (dont le plus connu est « Dans les beaux quartiers »), Michel Pinçon et Monique Pinçon-Charlot étudient, en sociologues, la grande bourgeoisie. Des tas d'études sociologiques ont été faites sur les banlieues difficiles, sur les ouvriers, sur les chômeurs mais très peu sur la grande bourgeoisie, peut-être par acceptation aveugle du tabou comme quoi les classes sociales n'existeraient pas. Ce dernier ouvrage (car les auteurs prennent leur retraite) discute de l'occupation de l'espace et de sa défense.

Leurs sujets d'étude ne sont pas forcément faciles. Certes, les risques physiques sont plus faibles que lorsqu'on va étudier les délinquants de banlieue. Et on mange mieux lorsqu'on enquête au Jockey Club. Mais cela ne rend pas forcément l'enquête plus facile, face à des interlocuteurs qui, eux aussi, ont lu Bourdieu, et sont rompus à l'art difficile de se montrer sous son meilleur jour, tout le temps.

Dans ce livre, les deux auteurs s'attaquent plus particulièrement à la gestion de l'espace par la grande bourgeoisie. Si on reproche aux immigrés de vivre dans des ghettos, que dire de cette classe dont l'étude du Bottin mondain montre que ses membres ne vivent que dans trois arrondissements de Paris (7, 8 et 16), sans compter évidemment le vingt-et-unième ? À les fois très cosmopolites (le monde est leur terrain de jeu depuis toujours) et très attachés à leurs territoires, les sujets de l'étude mettent en œuvre tous les moyens à leur disposition pour rester entre eux et ne pas permettre de mélanges avec d'autres classes sociales. Leur dévouement militant, lorsque ce territoire est menacé, n'a rien à envier à la rage du caïd de banlieue s'opposant au passage dans « sa » cité d'autres exclus venus d'une cité différente...

Le seul jeu du marché, et les prix de l'immobilier qu'il entraine, sont déjà un bon moyen de limiter la mixité sociale. Encore faut-il veiller à ce que les politiques publiques ne contrarient pas trop ce marché. C'est alors que rentre en jeu le travail d'influence, rarement public, pour s'assurer qu'aucune loi n'aura de conséquences trop graves. C'est ainsi que la loi SRU a certes été votée (elle impose notamment un minimum de 20 % de logements sociaux par commune) mais est systématiquement violée, les sanctions étant bien trop faibles (Neuilly n'a ainsi que 2,6 % de logements sociaux).

Cette occupation de l'espace est particulièrement nette dans le cas du Bois de Boulogne, qui fait l'objet d'un article étonnant du livre. Une partie de cet espace public est en effet réservée depuis des dizaines d'années à un petit nombre de clubs ultra-fermés, où on n'entre que par cooptation, comme le Cercle du Bois de Boulogne ou le Polo de Paris.

Comment se pratique cette défense du territoire ? Pas de manifestations dans la rue, pas de voitures brûlées, même pas de complot international où de mystérieux financiers apatrides tireraient les ficelles. Non, c'est beaucoup plus simple, montrent nos deux sociologues. Ce monde est irrigué par un intense réseau de sociabilité. On dine ensemble à l'Interallié ou lors d'une réception chez l'un ou l'autre, on prend des vacances dans les mêmes palaces, à Gstaad ou à Marrakech et les problèmes sont réglés entre gens du même monde, discrètement. Il y a certes de nombreux conflits internes (l'associations de grands bourgeois qui s'oppose à une autoroute urbaine peut compter dans ses membres des actionnaires de Renault ou de Vinci...) mais la plupart se règlent « entre soi ».

Bref, un livre qui donne envie d'être riche, pour pouvoir profiter d'une telle entraide, et de territoires protégés, défendus avec une bonne conscience en béton : les quartiers où ils vivent étant souvent historiquement importants, ils ne défendent pas leurs intérêts, non, ils protègent le patrimoine national...


L'article seul

RFC 5122: Internationalized Resource Identifiers (IRIs) and Uniform Resource Identifiers (URIs) for the Extensible Messaging and Presence Protocol (XMPP)

Date de publication du RFC : Février 2008
Auteur(s) du RFC : P. Saint-Andre (XSF)
Chemin des normes
Première rédaction de cet article le 7 mars 2008


Le protocole XMPP (RFC 6120) fournit notamment la possibilité de services de messagerie instantanée. Les adresses qu'utilise XMPP (par exemple bortzmeyer@gmail.com puisque j'utilise Google Talk, qui repose sur XMPP) ne sont pas des URI et il y a des cas où il serait utile de pouvoir désigner ces ressources XMPP par un URI, ce que fait notre RFC.

Succédant au RFC 4622 (les seuls changements sont des corrections d'erreurs), notre RFC décrit la syntaxe et la sémantique des URI XMPP. Le RFC 3920 excluait les URI pour désigner les ressources XMPP mais cette règle s'est avérée trop contraignante pour les applications, comme l'explique les sections 1 et 2.1. La section 2.2 nous introduit à la syntaxe des URI (ou plutôt des IRI, mais une raison compliquée liée aux procédures IANA fait que le RFC doit mentionner les deux familles) XMPP et leur formation à partir d'une classique adresse XMPP (détaillée en 2.7). Il faut notamment ajouter le plan xmpp: et encoder les caractères qui ne sont pas légaux dans un IRI. L'adresse XMPP donnée au premier paragraphe devient donc l'URI xmpp:bortzmeyer@gmail.com.

La section 2.3 couvre un cas délicat. La syntaxe des URI génériques, décrite dans le RFC 3986, spécifie, dans sa section 3.2, une autorité optionnelle, précédée de deux barres de division. Par exemple, dans http://www.bortzmeyer.org/5122.html, www.bortzmeyer.org est l'autorité. Il existe des URI sans mention d'une autorité, comme mailto:stephane+blog@bortzmeyer.olrg. Les URI XMPP, eux, peuvent avoir une autorité, qui a la forme d'un compte XMPP. Si elle est absente, c'est le compte par défaut qui est utilisé. C'est ainsi que xmpp:durand@example.net n'indique pas d'autorité (on utilisera le compte par défaut) alors que xmpp://martin@exemple.fr/durand@example.net désigne la même ressource mais en spécifiant le compte qui doit être utilisé.

Continuant dans les composants d'un URI, la section 2.4 traite le chemin et 2.5 la requête, qui se trouve après un point d'interrogation. Compte tenu de la variété des applications XMPP (ce protocole ne traite pas que la messagerie instantanée, même si c'est son utilisation principale aujourd'hui, voir le RFC 3921), le RFC ne spécifie pas de sémantique précise pour cette requête, elle dépendra de l'application. Par exemple xmpp:nicolas@pauvre-con.fr?message;subject=Casse%20toi pour déclencher l'envoi d'un message avec le sujet indiqué (on note que le séparateur des arguments avec ce plan XMPP est le point-virgule et pas l'habituelle esperluète).

La section 2.8 détaille le traitement de tels URI par les logiciels (il y a beaucoup de subtilités à gérer) et la 2.9 les questions d'internationalisation ; les adresses XMPP sont en UTF-8 et peuvent donc être converties directement en IRI XMPP. Pour avoir un URI XMPP, les adresses contenant des caractères non-ASCII devront être encodées, par exemple lors de la transformation de l'IRI en URI.

La section 3 du RFC est simplement le formulaire réglementaire d'enregistrement d'un plan (scheme) d'URI auprès de l'IANA, suivant le RFC 4395.


Téléchargez le RFC 5122


L'article seul

RFC 3263: Session Initiation Protocol (SIP): Locating SIP Servers

Date de publication du RFC : Juin 2002
Auteur(s) du RFC : J. Rosenberg (dynamicsoft), H. Schulzrinne (Columbia U.)
Chemin des normes
Première rédaction de cet article le 7 mars 2008


Le protocole SIP est normalisé dans le RFC 3261 qui décrit en détail la communication entre un client et un serveur SIP. Mais comment le client trouve t-il un serveur ? C'est l'objet de ce RFC d'accompagnement.

SIP est surtout utilisé pour la téléphonie sur Internet. L'ancien numéro de téléphone y est remplacé par un URI, tel que sip:support@apnic.net. Mais un client SIP (par exemple un UAC, le logiciel avec lequel interagit directement l'utilisateur, son téléphone : mais aussi un relais SIP que l'UAC aurait utilisé) doit, pour établir une connexion avec le serveur SIP, trouver son adresse, alors qu'il n'a que cet URI et donc uniquement un nom de domaine (et que SIP peut fonctionner sur plusieurs transports).

La méthode est donc d'utiliser le DNS. Le client va utiliser les enregistrements NAPTR du RFC 3403 puis les enregistrements SRV du RFC 2782. Suivons la section 4.1 du RFC qui nous donne un exemple, où on cherche à joindre sip:helpdesk@example.net. Le domaine example.net contient les enregistrements NAPTR suivants :

;             order pref   flags    service     regexp       replacement
    IN  NAPTR   50    50     "s"     "SIPS+D2T"    ""   _sips._tcp.example.com
    IN  NAPTR   90    50     "s"     "SIP+D2T"     ""   _sip._tcp.example.com
    IN  NAPTR   100   50     "s"     "SIP+D2U"     ""   _sip._udp.example.com
    IN  NAPTR   120   50     "s"     "SIP+D2S"     ""   _sip._sctp.example.com

On notera que le champ regexp est vide : quel que soit l'URI de départ, le résultat est donné par le champ replacement. Ici, quatre NAPTR sont intéressants (ceux dont le service est de type SIPx+D2x). Le premier spécifie un transport sécurisé par TLS au dessus de TCP. Le second un transport TCP simple, le troisième un transport UDP, le quatrième un SCTP.

Une fois obtenu ces noms de domaines grâce aux NAPTR, on utilise les enregistrements SRV pour avoir les serveurs et leurs numéros de port. Par exemple, _sip._tcp.example.com aura les SRV suivants :

;               Priority Weight Port      Target
      IN    SRV  0          1     5060     main-server.example.com.
      IN    SRV  10         1     53456    backup-server.example.com.

Le client tentera alors de se connecter à main-server.example.com (on notera que cela nécessitera une requête DNS supplémentaire, pour trouver son adresse IP) se rabattant, s'il est inaccessible, sur backup-server.example.com.

Le prédécesseur de notre RFC, le RFC 2543, n'utilisait pas les NAPTR, uniquement les SRV. Dans l'exemple ci-dessus, les serveurs étant dans un domaine différent de celui de l'URI, il aurait donc échoué.

Notons enfin que la section 5 du RFC décrit comment un serveur SIP trouve un client. Si ce dernier le contacte directement en TCP, c'est trivial mais il existe des cas où le client est en fait un relais et où la réponse doit suivre un cheminement analogue (avec recherche de SRV - mais pas de NAPTR) pour le trouver.


Téléchargez le RFC 3263


L'article seul

RFC 5155: DNSSEC Hashed Authenticated Denial of Existence

Date de publication du RFC : Mars 2008
Auteur(s) du RFC : B. Laurie, G. Sisson, R. Arends (Nominet), D. Blacka (Verisign)
Chemin des normes
Première rédaction de cet article le 6 mars 2008
Dernière mise à jour le 1 septembre 2010


L'enregistrement NSEC3 permet de résoudre un problème agaçant de DNSSEC, le fait que ce dernier permette l'enumération de tous les noms de domaine d'une zone signée. NSEC3 permet donc d'établir la non-existence d'un domaine sans rien révéler sur les autres domaines.

DNSSEC (RFC 4033) authentifie les enregistrements DNS en ajoutant un enregistrement RRSIG (RFC 4034) qui contient une signature des enregistrements qu'on veut authentifier. Le problème est que, si le nom de domaine demandé n'existe pas (réponse NXDOMAIN pour No Such Domain), il n'y a pas d'enregistrement à signer. Ce problème est connu sous le nom de preuve de non-existence et c'est un des points les plus difficiles de DNSSEC (section 5.4 du RFC 4035). Le RFC 4034, section 4, le traitait en introduisant un enregistrement NSEC, signé par un RRSIG, qui indiquait le domaine suivant celui demandé. En vérifiant que ce domaine suivant était bien situé après celui demandé (et que le domaine demandé était situé après le nom en partie gauche du NSEC), le résolveur pouvait être sûr de la non-existence du nom qu'il avait demandé.

Mais le gros problème de NSEC est qu'il permet l'énumération. Une fois qu'on a découvert le nom de domaine suivant, on peut passer au suivant, puis à celui d'après et ainsi de suite, on a récupéré toute la zone, même si son administrateur ne le voulait pas.

Le registre de .uk, Nominet, a clairement indiqué que c'était inacceptable pour eux et qu'ils ne déploieraient pas DNSSEC sans une solution à ce problème politico-légal.

Le nouvel enregistrement NSEC3 résout le problème en ne donnant pas le nom du domaine suivant mais son résumé cryptographique, son empreinte.

Le principe de NSEC 3 est le suivant. Les résumés de tous les noms sont classés par ordre alphabétique (c'est arbitraire, l'important est que cela soit reproductible). La partie gauche (owner name) de l'enregistrement NSEC3 n'est pas un nom de domaine mais un résumé. Idem pour la partie droite.

L'enregistrement contient aussi quelques autres paramètres comme l'algorithme de calcul du résumé (section 3.1.1, les sections suivantes décrivant les autres paramètres). Voici un enregistrement NSEC3 au format suggéré section 3.3 :

2t7b4g4vsa5smi47k61mv5bv1a22bojr.example.              NSEC3   1 1 12 aabbccdd (
                          2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG )

Le résolveur qui reçoit un NXDOMAIN peut calculer le résumé du nom qu'il a demandé et, si l'enregistrement NSEC3 est correct, ce résumé doit tomber entre les deux résumés du NSEC3 (celui de gauche et celui de droite). Ainsi, si la question est le nom D1, et que le résolveur reçoit :

... NXDOMAIN
H0     NSEC3   H2 ...
H0     RRSIG   ...

il doit calculer H1, le résumé de D1 et vérifier que H0 < H1 < H2 (et naturellement vérifier le RRSIG, la signature). Ne connaissant que H0 et H2, il ne peut pas retrouver D0 et D2. Notez bien que l'ordre ne concerne que H0, H1 et H2, D0, D1 et D2 sont situés dans un ordre complètement différent. Comme avec NSEC, tout repose sur l'existence d'un ordre des éléments sauf que, avec NSEC3, ce sont les résumés cryptographiques qui sont ordonnés.

La méthode de calcul du résumé est détaillée en section 5. Par exemple, un sel est ajouté au nom, pour rendre plus difficile les attaques par dictionnaire. Sans ce sel (annexe C.1 pour les détails), un méchant pourrait, hors-ligne, générer tous les résumés pour tous les noms potentiels et vérifier ensuite simplement leur existence. Toujours pour rendre plus difficile les attaques par dictionnaire, l'opération de résume est recommencé plusieurs fois, en suivant un paramètre qui indique le nombre d'itérations (il y en a toujours au moins une, section 10.3). Notez toutefois qu'en 2022, le RFC 9276 a remis en cause ces techniques et que sel et itérations sont désormais très déconseillés.

Ce nombre d'itérations a une influence sur les performances du résolveur et du serveur faisant autorité. Les chiffres exacts peuvent être trouvés dans l'article de Yuri Schaeffer, « NSEC3 Hash Performance ». En pratique, les zones actuellement signées ont de une à dix itérations (dig NSECPARAM $ZONE pour le voir, il faut un dig >= 9.6).

Due à Kim-Minh Kaplan, voici une mise en œuvre en Perl du résumé :

use MIME::Base32;
use Digest::SHA1 qw(sha1);

my ($salt, $iteration, $name) = @ARGV;

$salt = pack "H*", $salt;
$name =~ y/A-Z/a-z/;
$name =~ s/\.*$//;
my @labels = split('\.', $name . ".", -1);
@labels = map { pack("C", length($_)) . $_ } @labels;
$name = join '', @labels;
foreach (0..$iteration) {
    $name = sha1("$name$salt");
}
print MIME::Base32::encode($name), "\n";

On doit appeler ce programme avec trois paramètres, le sel, le nombre d'itérations supplémentaires et le nom à résumer.

Notez que les dernières versions de BIND (depuis au moins la 9.7) sont livrées avec un programme plus perfectionné, nsec3hash, qui comprend en plus d'autres algorithmes que SHA-1. Voici un exemple d'utilisation :

[Récupérer les paramètres avec lesquels les noms sont résumés.]
% dig +short NSEC3PARAM pm.
1 0 1 BADFE11A

% nsec3hash  BADFE11A 1 1 pm
P3JUUU69O1AP1AI8DLNVO7L7A0SKT56S (salt=BADFE11A, hash=1, iterations=1)

[Et on retrouve bien ce résumé dans les enregistrements NSEC3 :

% dig +dnssec ANY nimportequoi.pm.
...
P3JUUU69O1AP1AI8DLNVO7L7A0SKT56S.pm. 5400 IN NSEC3 1 1 1 BADFE11A \
       L6U66FHPKD109EODA9R2SV8RGFSUAUQ3 NS SOA RRSIG DNSKEY NSEC3PARAM

NSEC3 contient plein d'autres fonctions intéressantes, par exemple la section 6 décrit un mécanisme de retrait (opt-out) permettant aux enregistrement NSEC3 de « sauter » par dessus les zones non signées (dans un TLD, comme .se, il est clair que la majorité des zones ne seront pas signées, au moins au début).

Les détails sont très complexes (et couverts dans les sections 7 et 8 du RFC) ce qui explique que certains auteurs de logiciels DNS comme Bert Hubert, auteur de PowerDNS, aient estimé qu'il serait difficile de faire du NSEC3 en pratique (voir aussi son bon article sur DNSSEC).

Mais NSEC3 est aujourd'hui mis en œuvre dans plusieurs logiciels comme BIND, NSD ou le résolveur UNBOUND. NSEC3 sera probablement plus complexe et plus lent que NSEC mais c'est le prix à payer pour garder le contrôle de ses données.

Avec BIND 9.6 (ou supérieur), voici comment on génère une clé RSA utilisable pour NSEC 3 :

% dnssec-keygen -a NSEC3RSASHA1 -b 1024 -n ZONE

et comment on signe :

dnssec-signzone -g -t -H 3 -3 babecafe $MYZONEFILE Kmykey.+007+30869

(babecafe est le sel, en hexadécimal.) Avec le retrait (opt-out), l'opération de signature prend une option supplémentaire, -A. Cette option permet de réduire considérablement le temps de signature (pour une zone d'un million de sous-zones, dont très peu sont signées, le retrait diminue le temps de signature de dix minutes à vingt secondes), au prix de la sécurité (il n'est désormais plus possible, si on utilise le retrait de prouver l'existence ou la non-existence d'une sous-zone non signée).

Ici, si on a une zone example comportant trois noms, example (l'apex), preston.example et central.example :

@ IN  SOA ns3.bortzmeyer.org. hostmaster.bortzmeyer.org. (
...
  IN  NS  ns3.bortzmeyer.org.
...
  IN DNSKEY 256 3 7 AwEAAa...=

central   IN   A   192.0.2.187

preston IN AAAA  2001:db8:8bd9:8bb0:a00:20ff:fe99:faf4 

et qu'on la signe avec :

% dnssec-signzone -H 3 -3 babecafe -o example db.example Kmykey.+007+30869

(trois itérations supplémentaires, un sel qui vaut « babecafe »), on obtient un fichier db.example.signed qui comprend trois NSEC3, un par nom :

FIDQ6ATJMOUCGLV3PNHS9694C1LFDSDT.example. 43200 IN NSEC3 1 0 3 BABECAFE JKNM5TRUGDISFPUU0CCLEMG2GTGOD2IP AAAA RRSIG
JKNM5TRUGDISFPUU0CCLEMG2GTGOD2IP.example. 43200 IN NSEC3 1 0 3 BABECAFE O7FU7992IPFEUUUVC1A8NAF4255JF7JI NS SOA MX TXT RRSIG DNSKEY NSEC3PARAM
O7FU7992IPFEUUUVC1A8NAF4255JF7JI.example. 43200 IN NSEC3 1 0 3 BABECAFE FIDQ6ATJMOUCGLV3PNHS9694C1LFDSDT A RRSIG

et le programme Perl ci-dessus permet de retrouver quel nom a été résumé pour donner la partie gauche de chacun de ces NSEC3 :

% perl hash-nsec3.pl babecafe 3 preston.example    
FIDQ6ATJMOUCGLV3PNHS9694C1LFDSDT

et on trouve ainsi que le premier NSEC3 de la liste était celui de preston.example (mais l'opération inverse est impossible : c'est le principe du résumé).

Merci à Kim Minh Kaplan pour son aide à m'aider à comprendre ce difficile protocole et pour sa relecture.


Téléchargez le RFC 5155


L'article seul

Gérer ses fichiers de configuration personnels avec Subversion

Première rédaction de cet article le 2 mars 2008


Comment maintenir une configuration à peu près identique entre plusieurs comptes Unix sur des machines différentes ? En utilisant un logiciel de contrôle de versions, Subversion, pour gérer les fichiers de configuration personnels, les dotfiles.


L'article complet

Sciences et Vie Junior et Wikipédia

Première rédaction de cet article le 1 mars 2008


Wikipédia est désormais largement utilisé par tout le monde, y compris par certains de ceux qui snobaient l'encyclopédie libre à ses débuts. On a même vu récemment Pierre Assouline dire du bien de Wikipédia, ce qui est un peu comme si le pape disait du bien du mouvement féministe. Mais une bonne partie de la presse écrite continue à remâcher ses rancœurs contre Wikipédia, comme le montre l'article de Sciences et Vie Junior de mars 2008. Quelles sont les deux plus grosses erreurs de l'article ?

L'article reprend les thèmes classiques des autres campagnes de presse contre Wikipédia comme le soi-disant anonymat des auteurs, ou comme le manque de fiabilité de l'encyclopédie libre (parfaitement réel, tout comme le manque de fiabilité des autres sources, à commencer par les médias classiques). Mais deux arguments sont particulièrement développés. L'un est une erreur sur la capitale de l'état mexicain de Nayarit. Jouissant d'une moins grande célébrité que le Yucatán ou le Chiapas, cet état peu connu (et dont l'article était donc peu relu) s'était en effet vu affubler d'une capitale erronée. L'erreur a été corrigée, par un internaute mexicain, bien avant la publication de Sciences et Vie Junior (ce que l'article ne dit pas). Comme tout l'historique des modifications est accessible sur Wikipédia, voici le changement en question. Contrairement à ce que prétendent ceux qui parlent de Wikipédia sans connaitre, ce ne sont pas en général les articles sur les grands sujets, très souvent relus et corrigés, qui comptent le plus d'erreurs mais plutôt les articles sur les sujets obscurs, où une erreur peut trainer des mois, tout simplement parce que personne ne lit l'article.

L'autre angle d'attaque évoque les théories complotistes sur l'accord secret entre Wikipédia et Google, aux termes duquel Google placerait systématiquement Wikipédia en premier dans les résultats de recherche. L'article de Sciences et Vie Junior ne reprend pas cette théorie paranoïaque telle quelle mais il affirme que, Google donnant la priorité aux pages vers lesquelles pointent beaucoup de liens (le fameux Page Rank), Wikipédia l'emporte à cause de ses nombreux liens internes, entre articles ! C'est bien sûr tout à fait faux (autrement, ce blog, qui a beaucoup de liens internes, serait souvent premier chez Google). S'il suffisait de faire des liens internes pour être bien classés, tout le monde le ferait ! Il est au contraire très probable que de tels liens, qui ne prouvent rien quant à la qualité de la page pointée, sont ignorés par Page Rank.

L'article tenait un sujet bien plus intéressant avec le manque de style de certains articles de Wikipédia, trop corrigés et modifiés pour avoir gardé un style agréable à lire, ce qui aurait nécessité un éditeur unique. Mais ce problème bien réel n'est guère développé, les anecdotes sur Britney Spears ou Harry Potter sont plus spectaculaires.


L'article seul

RFC 5144: A Domain Availability Check (DCHK) Registry Type for the Internet Registry Information Service (IRIS)

Date de publication du RFC : Février 2008
Auteur(s) du RFC : A. Newton (Verisign), M. Sanz (DENIC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF crisp
Première rédaction de cet article le 29 février 2008


Notre RFC propose un profil d'IRIS pour répondre à une question simple : ce domaine est-il libre ou pas ?

Aujourd'hui, l'enregistrement d'un nom de domaine commence souvent par une recherche de sa disponibilité. L'utilisateur final va sur le site Web du registrar de son choix, tape le nom convoité, le registrar interroge le registre et renvoie la réponse à l'utilisateur. Mais comment le registrar contacte t-il le registre ? Il existe une solution à moitié standard, le protocole whois (RFC 3912). En analysant le résultat de la requête, on peut trouver si le domaine est libre (ici, avec .fr) :

% whois vraimentnimportequoi.fr 
...
domain:      vraimentnimportequoi.fr
status:      AVAILABLE

whois a quelques défauts. Le format de sortie n'est pas normalisé, donc il faut trouver une expression indiquant la disponibilité, et la trouver pour chaque registre. Ce manque de normalisation est encore plus gênant si le domaine n'est pas libre et qu'on veut trouver pourquoi. Est-il déjà réservé ? Est-ce un terme interdit ? Ensuite, whois nécessite un traitement assez importante du côté du serveur, puisqu'il doit extraire de la base de données du registre beaucoup d'informations, beaucoup plus que ce qu'on désirerait pour simplement connaitre la disponibilité d'un domaine.

Cette lourdeur des traitements d'un serveur whois fait que les registres mettent en général en place des limitations strictes à son usage, par exemple en limitant le rythme d'accès.

Quelles sont les solutions propres, donc ? Pour le cas des registrars, les registres proposent en général des outils spécifiques comme un service EPP, dont la commande <epp:check> permet de récupérer des informations utiles (section 2.9.2.1 du RFC 4930). Souvent, ces outils utilisent un protocole privé, par exemple, pour .fr, ce programme Python utilisant SOAP trouve la disponibilité d'un domaine :

import SOAPpy # In some versions, a bug prevents authentication, you have to
# add "import base64" yourself
import sys, os, string

SOAPpy.Config.debug = False
hostname = "XXXXXX.nic.fr"
path = ""
user = "REGISTRAR-NAME"
password = "REGISTRAR-PASSWORD"
namespace = 'http://soap.nic.fr/Domain'
action = 'check_domain'

if len(sys.argv) > 1:
    domain = string.lower(sys.argv[1])
else:
    print "Usage: %s domain-name" % sys.argv[0]
    sys.exit(1)

server = SOAPpy.SOAPProxy("https://%s:%s@%s/%s" %
                          (user, password, hostname, path),
                          namespace=namespace,
                          soapaction = namespace + '#' + action)

domain_reply = server.check_domain (domain);
if domain_reply["free"]:
    print "%s is available" % domain
else:
    print "%s is NOT available because \"%s\" (%s)" % (domain,
                                                       domain_reply["message"],
                                                       domain_reply["reason"])

Mais, si on n'est pas registrar ? Quelles sont les solutions pour le public, surtout s'il veut pouvoir effectuer un grand nombre de requêtes, à des fins plus ou moins légitimes ?

Une première solution est de proposer une version réduite de whois. C'est ce que fait .nl, avec l'option is :

% whois "is amsterdam.nl"     
amsterdam.nl is active
% whois "is certainlynonexistent.nl"
certainlynonexistent.nl is free

Ne fournissant qu'une information limitée, ce service charge moins le serveur et est donc disponible avec des limites plus larges.

Et enfin, une autre solution fait l'objet de ce RFC 5144 : utiliser le protocole IRIS (RFC 3981) et un sous-ensemble de son schéma de données pour les domaines, DREG, au dessus d'un transport le plus léger possible. DCHK est donc un sous-ensemble de DREG (RFC 3982), limité à quelques informations, la disponibilité, bien sûr, mais aussi la date d'enregistrement, le statut, etc. Voici un exemple de réponse à une requête DHCK (ici, le domaine n'est pas libre) :


 <domain>
     <domainName>example.org</domainName>
     <status><active/></status>
 </domain> 

Le registre qui déploie DCHK le rendra typiquement plus accessible (limites moins strictes) que son service IRIS/DREG complet ou bien que son service whois.

Le protocole de transport recommandé, section 3.3, pour sa légèreté, est LWZ (RFC 4993), basé sur UDP.

Denic avait annoncé la disponibilité de ce service et la distribution du code source du client. Mais, finalement, DENIC a renoncé marquant la fin d'IRIS, qui n'a jamais été sérieusement déployé.


Téléchargez le RFC 5144


L'article seul

RFC 4101: Writing Protocol Models

Date de publication du RFC : Juin 2005
Auteur(s) du RFC : Eric Rescorla (RTFM)
Pour information
Première rédaction de cet article le 28 février 2008


Écrire un protocole réseau n'est pas facile. La description doit être suffisamment rigoureuse pour qu'elle puisse être mise en œuvre sans ambiguïté et elle doit être suffisamment lisible pour être compréhensible par le lecteur pressé. Les implémenteurs des protocoles préfèrent la précision et l'exactitude, les simples lecteurs, par exemple ceux qui relisent le protocole avant sa publication, préfèrent un texte plus littéraire et de plus haut niveau. Ce RFC, publié par l'IAB, estime que les normes IETF, publiées dans les RFC, sont allées trop loin vers les besoins des seuls implémenteurs et que les RFC récents manquent d'un modèle, d'une description de haut niveau du protocole.

Les normes écrites par l'IETF et publiées dans les RFC sont toutes soumises à un examen public, avant leur officialisation. Relire des projets de RFC, comme l'explique la section 1, n'est pas une tâche facile. Si les RFC d'autrefois étaient courts et souvent écrits de manière assez littéraire, les RFC modernes sont bien plus longs, souvent écrits par plusieurs personnes et le style s'en ressent. Plus corrects dans leur description du protocole, ils sont bien plus difficiles à lire. Si on doit programmer le protocole en question, on doit lire tout le RFC de toute façon. Mais si on veut juste faire une analyse du document, il est pénible de « rétro-ingénierer » les concepts à partir du texte.

La section 2 explique donc qu'il faudrait, dans chaque RFC qui normalise un protocole, un modèle, qui décrive le protocole à un niveau plus élevé et qui permette de répondre à trois questions :

  • Quel problème le protocole tente t-il de résoudre ?
  • Quels messages sont transmis et quelle est leur signification ?
  • Quelles sont les caractéristiques importantes du protocole ?

Le modèle doit se fonder sur les caractéristiques essentielles du protocoles. Par exemple, le fait que Kerberos (RFC 1510) utilise un système KDC (Key Distribution Center) est essentiel mais le fait que la syntaxe soit décrite en ASN.1 est un détail, les S-expressions auraient aussi bien convenu.

La section 3 décrit ensuite en quoi consiste un modèle. Le principe essentiel est que le modèle est plus court que le protocole complet. C'est une carte, pas un territoire. Il va donc abstraire le protocole et n'en garder que ce qui est essentiel.

La section 4 parle ensuite de l'écriture concrète de ces modèles. Elle recommande une approche très graphique, avec « des boîtes et des flèches » (même si la section 5 note que l'obligation de publier les RFC uniquement en texte brut en ASCII ne facilite pas les choses ; j'en profite pour signaler l'excellent outil Graph::Easy, pour générer des diagrammes en art ASCII à partir d'une description de haut niveau).

D'abord (section 4.1), le modèle doit décrire le problème qu'on essaie de résoudre. L'exemple que donne notre RFC est celui de STUN (RFC 3489), qui ne contient pas cette description. Notre RFC 4101 en propose donc une, avec un diagramme des différents composants des entités qui tentent de communiquer malgré le NAT et de leurs échanges.

Ensuite (section 4.2), le modèle doit donner une vue générale du protocole. L'exemple est pris dans le protocole DCCP (RFC 4340) dont RFC 4101 propose une telle vue de DCCP.

Enfin (section 4.3), le modèle doit pointer du doigt les caractéristiques importantes du protocole, surtout si elles ne sont pas évidentes à première vue. Ainsi, dans l'exemple de WebDAV, RFC 4918, contrairement à ce qu'on pourrait croire en lisant rapidement le RFC sur WebDAV, notre RFC 4101 montre qu'une discussion détaillée de la différence entre un renommage d'une ressource (commande MOVE de WebDAV) et sa copie suivie de la destruction de l'original (commandes COPY et DELETE de WebDAV) ne sont pas équivalents (mais le RFC sur WebDAV décrivant chaque commande séparément, ce n'est pas évident à voir).

La section 6 du RFC synthétise toutes ses recommandations en fournissant un exemple d'un modèle complet pour le protocole IKE (RFC 4306), l'un des plus complexes de l'IETF.

Si les auteurs de RFC suivent ces recommandations, les RFC deviendront encore plus lisibles et accessibles.


Téléchargez le RFC 4101


L'article seul

Exposé sur les réseaux informatiques à l'Institut Pasteur

Première rédaction de cet article le 27 février 2008


Dans le cadre du cours d'Informatique en Biologie de l'Institut Pasteur, j'ai fait un exposé de trois heures sur les réseaux infomatiques et notamment Internet.

Ce cours s'adresse à un public de biologistes non familiers avec la programmation ou avec le fonctionnement desdits réseaux. Contrairement à pas mal de cours sur ce sujet, cet exposé ne part pas des couches basses, du matériel par exemple, mais d'un petit programme Python très simple, qui appelle urlli2.urlopen() pour récupérer une ressource sur le Web, et descend ensuite petit à petit vers des couches de plus en plus basses. Voici les transparents de cet exposé :

Un autre exposé de la même série a porté sur systèmes d'exploitation.


L'article seul

Naviguer dans les caractères Unicode

Première rédaction de cet article le 27 février 2008
Dernière mise à jour le 23 août 2024


Le jeu de caractères Unicode est vaste (149 000 caractères la dernière fois que j'ai compté et cela augmente régulièrement). Il est donc souvent difficile de trouver un caractère donné. Quels sont les outils pour cela ?

Prenons l'exemple des caractères permettant une citation comme les guillemets en français. Cela se dit quotation dans la langue de Donald Westlake. Peut-on trouver tous les caractères de citation facilement ?

Mon outil en ligne préféré, utilisant toutes les techniques modernes du Web est Uniview. Taper quotation dans le moteur de recherche permet d'avoir la liste et leur apparence (si la bonne police est bien connue du navigateur). Une alternative possible est Unicode-Explorer.

Autre outil en ligne, moins convivial mais plus adapté pour des extractions de masse du genre « Tous les caractères de ponctuation qui sont identiques à leur forme canonique » : Unicode Utilities. Ainsi, on peut extraire facilement, par exemple, tous les caractères introduits entre les version 4.1 et 6.0 incluses.

On peut aussi vouloir chercher dans les documents officiels et le consortium Unicode a une excellente page pour cela.

Pour le cas où on connait la forme du caractère et où on cherche son nom et son point de code, l'excellent reconnaisseur de formes https://www.shapecatcher.com/ peut aider.

Et si on préfère travailler en local, sans nécessiter un accès à Internet, et avec ses propres outils ?

Pour ceux qui aiment Emacs, le plus simple est certainement de charger le fichier de la norme (sur une Debian, et les dérivés comme Ubuntu, il est dans /usr/share/unicode/UnicodeData.txt si on a installé le paquetage unicode-data - voici l'intérêt des normes gratuites, leurs fichiers peuvent être inclus dans un système de paquetages). On peut alors utiliser la fonction de recherche d'Emacs, C-s et c'est parti :

00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;*;;;
...
00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;*;;;

Bertrand Petit me signale d'autres façons de faire avec Emacs : C-X 8 RET *quot TAB affiche la liste des caractères comprenant « quot », et permet de les insérer. Pour un caractère déjà présent dans le fichier, C-X = permet d'obtenir son point de code Unicode en diverses syntaxes (mais pas son nom).

Pour ceux qui préfèrent SQL, une approche possible est décrite dans mon article La base de données Unicode en SQL.

ucd=> SELECT To_U(codepoint) AS U_Codepoint, name FROM Characters WHERE name LIKE '%QUOTATION%' ORDER BY codepoint;
 u_codepoint |                        name                        
-------------+----------------------------------------------------
 U+22        | QUOTATION MARK
 U+AB        | LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
 U+BB        | RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
 U+2018      | LEFT SINGLE QUOTATION MARK

En local et en graphique, l'excellent Gucharmap permet de naviguer très agréablement dans les tables Unicode.

Enfin, pour les Vrais Hommes qui préfèrent la Ligne de Commande, l'excellent programme unicode, écrit pour Debian (mais qui tourne sans doute sur d'autres Unix) :


# Available at https://packages.debian.org/stable/unicode
% unicode quotation
U+0022 QUOTATION MARK
UTF-8: 22  UTF-16BE: 0022  Decimal: &#34;
"
Category: Po (Punctuation, Other)
Bidi: ON (Other Neutrals)

U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
UTF-8: c2 ab  UTF-16BE: 00ab  Decimal: &#171;
...


L'article seul

Faire des DVD à partir de fichiers vidéo

Première rédaction de cet article le 27 février 2008


Aujourd'hui où on peut récupérer plein de fichiers vidéos sur Internet ou bien via sa LibreBoîte, il est courant de les regarder sur son ordinateur. Mais le lecteur de DVD traditionnel a encore des avantages (prix, disponibilité, facilités pour regarder en famille) et il est donc intéressant de pouvoir produire des DVD-Vidéo à partir de ces fichiers vidéo. Disons-le franchement, ce n'est pas facile mais c'est possible. Ici, j'utiliserai une machine Unix, en l'occurrence une Ubuntu.

On trouve beaucoup de documentations et de HOWTO sur le réseau pour cette tâche. La plupart sont très complexes et supposent que l'utilisateur est prêt à concevoir et à écrire des commandes comme mencoder -o $OUTPUT -oac lavc -ovc lavc -of mpeg -mpegopts format=dvd -vf harddup -srate 48000 -ofps 25 -lavcopts acodec=ac3:abitrate=192:vcodec=mpeg2video:aspect=4/3:keyint=15:vrc_buf_size=183 5:vrc_maxrate=9800:vbitrate=$BITRATE:trell:mbd=2:precmp=2:subcmp=2:cmp=2:dia=-10:predia=-10:cbp:mv0:vqmin=1:lmin=1:dc=10 $INPUT. D'autres documentations supposent au contraire qu'on veut utiliser un outil à GUI qui va tout faire pour nous, sans nous dire comment. Je me situe entre les deux : je veux quelque chose de simple (je ne suis pas professionnel de la vidéo) mais je veux aussi quelque chose en ligne de commande, qu'on puisse adapter et programmer.

Avant de voir la solution que j'utilise, expliquons un peu les étapes. Il faut faire quatre choses pour avoir un DVD-Vidéo :

  • Encoder la vidéo selon un encodage que comprend une platine DVD ordinaire, typiquement MPEG-2 (à noter que ces platines évoluent, les plus récentes connaissent de nouveaux formats),
  • Fabriquer un menu pour le lecteur de DVD,
  • Fabriquer une structure de fichiers conforme à ce qu'attend le lecteur (format UDF, répertoires standard VIDEO_TS et AUDIO_TS),
  • Graver le tout avec un graveur de DVD.

Chacune de ces étapes peut être faite à la main, avec une commande Unix, mais la création de ces commandes est souvent cauchemardesque. C'est pour cela que je préfère utiliser les scripts du paquetage ToVid, simples et particulièrement bien documentés. Prenons le cas d'un film nommé « Parle à ma main » qu'on a récupéré en AVI et qu'on voudrait mettre sur DVD. Les quatre étapes citées ci-dessus correspondent à trois commandes de ToVid (la dernière commande fait deux étapes) :

# Ré-encoder le fichier. Le résultat sera bien plus gros, car les
# algorithmes de compression que comprennent les lecteurs DVD de salon
# ne sont pas aussi efficaces.
tovid -dvd -in parle-a-ma-main.avi -out parle-a-ma-main

# Créer le menu du DVD 
makexml /var/tmp/parle-a-ma-main.mpg -out parle-a-ma-main

# Créer le système de fichiers UDF et graver (makedvd appelle
# genisoimage pour cela)
makedvd -burn parle-a-ma-main.xml

Et c'est tout et ça fonctionne. Il n'y a pas de vrai menu, puisqu'un seul film est présent, ToVid crée un DVD qui démarre automatiquement sur l'unique film.

Et si on a plusieurs films et qu'on veut des menus ? Supposons qu'on a escaladé deux montagnes en Antarctique, l'Erebus et le Kirkpatrick. Pendant l'ascension, on a filmé et enregistré erebus.avi et kirpatrick.avi. On veut faire un menu présentant le choix entre les deux films :

# Réencoder les deux fichiers
tovid -dvd -in erebus.avi -out erebus
tovid -dvd -in kirkpatrick.avi -out kirkpatrick

# Faire le menu
makemenu -pal "Mont Erebus" "Mont Kirkpatrick" -out Antarctique

# Générer le fichier XML qui décrit le DVD
makexml -dvd -menu Antarctique.mpg erebus.mpg kirkpatrick.mpg -out Antarctique

# Graver
makedvd  -burn Antarctique.xml

Cela donnera un DVD avec un menu d'introduction proposant les deux choix « Mont Erebus » et « Mont Kirkpatrick ». makemenu dispose de nombreuses options (très bien expliquées). Par exemple, ici, on mettra vent.mp3 en musique de fond du menu et neige.jpg en image de fond.

 makemenu -pal "Mont Erebus" "Mont Kirkpatrick" -audio vent.mp3 \
          -background neige.jpg -fontsize 38 -out Antarctique

La première étape, celle du réencodage n'est pas forcément nécessaire si le lecteur de DVD sait lire le format utilisé. Attention, les formats vidéo sont typiquement en deux couches, un encodage des données vidéo et un emballage de la vidéo et d'autres informations dans un container. Par exemple, un AVI est un container, les données étant en général encodées en MPEG. Le script MediaInfo permet d'afficher le contenu d'un fichier multimédia, ici l'AVI contient une vidéo MPEG-4 et une piste audio :

% MediaInfo monfilm.avi
General #0
Complete name        : /tmp/monfilm.avi
Format               : AVI
Format/Info          : Audio Video Interleave
Format/Family        : RIFF
File size            : 5.76 MiB
PlayTime             : 1mn 47s
Bit rate             : 444 Kbps
StreamSize           : 176 KiB
Writing library      : VirtualDub build 24415/release

Video #0
Codec                : XviD
Codec/Family         : MPEG-4
Codec/Info           : XviD project
Codec settings/Packe : Yes
Codec settings/BVOP  : Yes
Codec settings/QPel  : No
Codec settings/GMC   : 0
Codec settings/Matri : Default
PlayTime             : 1mn 47s
Bit rate             : 313 Kbps
Width                : 576 pixels
Height               : 336 pixels
Aspect ratio         : 16/9
Frame rate           : 25.000 fps
Resolution           : 8 bits
Chroma               : 4:2:0
Interlacement        : Progressive
Bits/(Pixel*Frame)   : 0.063
StreamSize           : 3.99 MiB
Writing library      : XviD0041

Audio #0
Codec                : MPEG-1 Audio layer 3
Codec profile        : Joint stereo
PlayTime             : 1mn 47s
Bit rate             : 125 Kbps
Bit rate mode        : VBR
Channel(s)           : 2 channels
Sampling rate        : 48 KHz
Resolution           : 16 bits
StreamSize           : 1.59 MiB
Writing library      : Xing (new)

(mplayer -identify donne également des informations mais moins détaillées et semble difficile à utiliser de manière non-interactive.)

L'étape de la gravure est souvent la plus délicate (je n'ai jamais réussi à relire un DVD gravé avec wodim, par exemple.). Les erreurs à la gravure sont fréquentes, surtout avec les DVD bas de gamme. Il est recommandé d'utiliser des DVD RW (réinscriptibles), certes plus chers mais qui permettent de réessayer plusieurs fois. On peut aussi, avant la gravure, tester le DVD « virtuel » avec gxine ou codeine.

Une autre description de la même technique peut être trouvée (en anglais) dans DVD Authoring with Linux qui note, comme moi, que la méthode manuelle est vraiment pénible. Si on préfère quand même procéder à la main, et écrire un script à soi, on trouvera des informations utiles en français dans MPEG to DVD ou en anglais dans Some thoughts on DVD authoring ou Authoring PC media To DVD using the Linux Operating System.

On notera que le monde de la vidéo est particulièrement difficile pour les partisans du logiciel libre. Certains programmes ne sont pas accessibles sous une licence libre, d'autres sont sous l'épée de Damoclès des brevets logiciels, fréquents sur les formats vidéo (peu sont des formats vraiment ouverts). C'est ainsi que la documentation de ToVid note, à propos de l'installation sur Debian, que tovid isn't in the official Debian distribution because it depends on packages that don't comply with the Debian philosophy (and so it's very likely it never will be officially included in Debian) (les commandes utilisées ici ont été testées sur une Ubuntu, avec les jeux de paquetages universe et multiverse dont le statut n'est pas toujours clair).

Merci à Jean-Philippe Pick et à Emmanuel Chantreau pour m'avoir guidé dans mes débuts dans le monde merveilleux et hostile de la vidéo numérique.


L'article seul

RFC 2141: URN Syntax

Date de publication du RFC : Mai 1997
Auteur(s) du RFC : Ryan Moats (AT&T)
Chemin des normes
Première rédaction de cet article le 26 février 2008


Dans la grande famille des URI, il y a les URL et les URN, dont la syntaxe faisait l'objet de ce RFC, remplacé depuis par le RFC 8141.

Le RFC 3986, qui normalise la syntaxe générique des URI, délègue les détails des familles particulières d'URI à d'autres RFC comme celui-ci. Le RFC 2141 précisait la syntaxe générique pour le cas des URN, des URI dont les propriétés sont a priori la persistence et la non-résolvabilité (donc, plutôt des noms que des adresses, cf. RFC 1737 et RFC 3305).

La section 2, Syntax, forme donc l'essentiel de ce court RFC. Un URN est formé avec le plan urn, un NID (Namespace IDentifier) qui indique l'organisme qui gère la fin de l'URN, le NSS (Namespace Specific String), tous séparés par des deux-points. L'enregistrement des autorités identifiées par le NID était traité dans le RFC 3406, également remplacé depuis par le RFC 8141.

Par exemple, si on prend les URN néo-zélandais du RFC 4350, le NID est nzl et un URN ressemble donc à urn:nzl:govt:registering:recreational_fishing:form:1-0.

Comme avec les autres URI, les caractères considérés comme « spéciaux » doivent être protégés avec l'encodage pour cent (section 2.3).

La section 5, consacrée à l'équivalence lexicale de deux URN, explique comment on peut déterminer si deux URN sont égaux ou pas, sans connaitre les règles particulières de l'organisme qui les enregistre. Ainsi, urn:foo:BAR et urn:FOO:BAR sont lexicalement équivalents (le NID est insensible à la casse) mais urn:foo:BAR et urn:foo:bar ne le sont pas, le NSS étant, lui, sensible à la casse (les deux URN sont peut-être fonctionnellement équivalents mais cela dépend de la politique d'enregistrement de l'organisme désigné par foo).


Téléchargez le RFC 2141


L'article seul

Le Pakistan pirate YouTube

Première rédaction de cet article le 25 février 2008


Ce dimanche 24 février, YouTube a été inaccessible depuis une bonne partie de la planète pendant une à deux heures. Ce n'était pas une panne, mais le résultat d'une action délibérée en provenance du Pakistan.

Un bon résumé de l'affaire peut être trouvé sur site de la BBC. Le gouvernement du Pakistan a annoncé un blocage de YouTube. Pakistan Telecom a exécuté l'ordre. Ce qui est intéressant, c'est que, incompétence, méchanceté ou bien volonté de tester, Pakistan Telecom a réussi à couper YouTube sur l'ensemble de la planète.

La technique employée est très banale et des tas de méchants l'ont déjà utilisée (le cas le plus célèbre est connu sous le nom d'AS 7007). Elle se nomme « détournement d'adresse » (IP hijacking) et consiste à annoncer une route plus spécifique, pour les adresses IP de la victime. Les routes sur Internet sont propagées d'opérateur en opérateur (par le protocole BGP, RFC 4271) et peu d'entre eux limitent ce qu'on peut annoncer. N'importe quel routeur BGP de l'Internet peut tout à coup se mettre à dire « Envoyez tous les paquets IP à destination de 208.65.153.0/24 - l'adresse de YouTube - vers moi ». Cette annonce aura même la priorité sur celle, légitime, de YouTube, car elle est plus spécifique (la longueur du préfixe est de 24 bits, contre 22 pour l'annonce légitime - notez qu'elle a changé depuis le détournement). Authentifier le pair BGP en face ne sert à rien, puisque cela ne garantit pas qu'il aura authentifié ses propres pairs (avec BGP, la confiance doit être transitive).

Quelles sont les leçons à en tirer ? L'insécurité de BGP est bien connue depuis longtemps et devrait, logiquement, susciter plus d'inquiétudes pour la sécurité et la stabilité de l'Internet que les débats politiciens de l'ICANN ou de l'IGF. Elle n'est pas facile à résoudre, le problème n'étant pas technique mais politique et organisationnel. Mikael Abrahamsson, qui travaille pour un opérateur suédois, a bien expliqué pourquoi personne ne filtre les annonces BGP (de manière très injuste, certains avaient reproché à PCCW, le fournisseur de Pakistan Telecom, son absence de filtrage) : « Using pure routing-registry based filtering just isn't cost efficient today, as these borks (unintentional mostly) we see sometimes are few and fairly far between, but problems due to wrong or missing information in the routing registries is plentyful and constant. » Bref (et c'est une leçon à retenir pour d'autres protocoles de sécurité comme DNSSEC), il y a plus de coupures si on protège que si on ne protège pas.

Ce ne sont donc pas les solutions techniques qui manquent (il y en a au moins deux, Secure BGP et soBGP) mais le modèle de confiance à déployer derrière. Pour prendre une comparaison, il ne sert à rien qu'un document d'identité soit infalsifiable si les services administratifs attribuent ces documents n'importe comment.

Si on veut éviter de se faire détourner ainsi, il n'y a guère de solutions, notons toutefois qu'il existe des services d'alerte, qui peuvent vous prévenir lorsqu'ils détectent une annonce de votre réseau par un nouvel opérateur : voir http://www.ris.ripe.net/myasn.html et http://cs.unm.edu/~karlinjf/IAR/index.php. Il est amusant de noter que ces services utilisent la même propriété que l'attaque : BGP est ouvert à tous, tout le monde peut y participer, tout le monde peut regarder (par exemple via les looking glasses).

L'attaque (même si elle était involontaire, elle ne se distinguait pas d'une réelle attaque) a réactivé dans la communauté des opérateurs l'intérêt pour du filtrage politique (filtrer les opérateurs asiatiques et/ou musulmans) ou pour du filtrage économique (tout accepter des gros opérateurs et filtrer sévèrement les « petits », ceux qui n'ont pas YouTube pour client).

Cette attaque a été très médiatisée, puisqu'elle touchait une infrastructure critique de l'Internet : si on ne peut plus regarder des vidéos débiles tournées avec les pieds, la sécurité internationale est menacée. Trois semaines après, une bavure similaire a touché l'opérateur kenyan Africa on line et, là, cela n'a ému personne (voir un bon résumé de ce cas).

Trois très bons articles, sur des blogs de référence, résument la situation technique : http://www.cs.columbia.edu/~smb/blog//2008-02/2008-02-24.html, http://www.potaroo.net/ispcol/2008-03/routehack.html, et http://www.renesys.com/blog/2008/02/pakistan_hijacks_youtube_1.shtml. Une étude plus détaillée a été faite par la suite par le RIPE-NCC, utilisant RIS, leur système de surveillance de BGP.

Sur BGP, on peut aussi lire mon cours pratique. Une solution technique à des problèmes de sécurité comme celui-ci a été normalisée en 2012, sous le nom de RPKI+ROA.


L'article seul

RFC 5137: ASCII Escaping of Unicode Characters

Date de publication du RFC : Février 2008
Auteur(s) du RFC : J. Klensin
Première rédaction de cet article le 24 février 2008


Idéalement, aujourd'hui, tous les protocoles Internet devraient être complètement internationalisés et notamment devraient accepter que les données soient exprimées dans un des encodages classiques d'Unicode, comme UTF-8. Mais ce n'est pas encore le cas. Ce RFC propose une approche pour utiliser des caractères Unicode dans les derniers protocoles dinosauriens qui n'acceptent normalement que l'ASCII.

La section 1.1 explique bien que ce RFC ne s'applique pas aux protocoles qui acceptent déjà un ou plusieurs encodages Unicode, ce qu'ils feront tous dans le futur, espérons-le. Mais, en attendant ce jour, ce RFC s'applique aux vieux protocoles. Actuellement, ceux-ci acceptent presque tous une forme d'échappement qui leur permet de transporter plus ou moins d'Unicode. L'idée est de mettre un peu d'ordre dans ces formes, sans aller jusqu'à les standardiser complètement (ce que tentaient de faire les premières versions de l'Internet-Draft qui a donné naissance à ce RFC).

Le cas de textes parlant de caractères Unicode (« Les citations en français doivent commencer par un demi-cadratin, le U+2013 ») n'est pas non plus couvert : de tels textes, conçus pour les humains et non pour les programmes, doivent utiliser la notation Unicode traditionnelle U+nnnn comme ci-dessus (section 3).

Notre RFC recommande donc finalement deux formes pour les caractères Unicode dans les fichiers conçus pour être lus par des programmes. En prenant l'exemple du И cyrillique (U+0418, grand I), les deux formes recommandées sont :

  • \u'0418' (section 5.1), une forme qui a été conçue spécialement pour ce RFC,
  • &#x418; (section 5.2), la forme traditionnelles de XML et HTML.

Pourquoi ces deux formes ? Comme l'explique la section 2, il existe de nombreuses solutions. Un premier principe qui a guidé celle choisie est qu'il fallait encoder des points de code Unicode (les index dans la table Unicode comme le 418 hexadécimal ci-dessus) et surtout pas des octets d'un encodage particulier comme le font, malheureusement, les URI (section 2.1 du RFC 3986).

Un deuxième principe est d'utiliser des délimiteurs explicites, pour éviter toute ambiguïté, sans forcer les caractères à être représentés par un nombre fixe de chiffres (section 4).

Plusieurs formes couramment recontrées dans la nature sont discutées dans le RFC et rejetées (section 6 et annexe A) :

  • Celle de Java, \u0418 qui viole le premier principe (c'est un sur-encodage d'UTF-16, ce qui n'est pas gênant pour notre grand I cyrillique, qui fait partie du Plan Multilingue de Base d'Unicode, mais complique les choses pour les caractères en dehors de ce plan),
  • Celle de C, \u0418, mais qui utilise un grand U et huit chiffres pour les caractères en dehors du Plan Multilingue de Base, une astuce bien dans la ligne de ce langage,
  • Celle de Perl, \x{418}, qui avait personnellement ma préférence, notamment par ses délimiteurs symétriques, mais qui a été écartée car certains craignaient une ambiguïté possible due à la possibilité en Perl d'utiliser d'autres encodages.

Enfin, on notera que le RFC ne spécifie pas d'échappement standard si on veut écrire, par exemple \u'0418' sans qu'il soit interprété comme un caractère Unicode. Le truc classique du \\ est recommandé mais pas imposé.


Téléchargez le RFC 5137


L'article seul

RFC 3588: Diameter Base Protocol

Date de publication du RFC : Septembre 2003
Auteur(s) du RFC : P. Calhoun (Airespace), J. Loughney (Nokia), E. Guttman (Sun), G. Zorn (Cisco), J. Arkko (Ericsson)
Chemin des normes
Première rédaction de cet article le 22 février 2008


Pendant longtemps, le seul protocole standard d'authentification entre un NAS et sa base d'utilisateurs était Radius. Diameter, normalisé dans notre RFC, vise à le remplacer, et est bien plus riche en fonctions. Ce RFC était le premier sur Diameter, il a été remplacé depuis par le RFC 6733.

Traditionnellement, lorsqu'un client PPP ou d'un protocole similaire se connecte à son FAI, sa session est terminée sur un NAS, équipement qui ne possède en général pas de base des utilisateurs autorisés. Il y a plusieurs raisons à cela, comme le fait que le NAS n'est en général pas un ordinateur généraliste, il a peu de moyens, notamment en place disque ou bien comme le fait qu'un FAI a typiquement plusieurs NAS (au moins un par POP), et qu'il souhaite centraliser l'authentification. (Dans le monde 802.11, le NAS est typiquement nommé AP (Access Point.)

Le mécanisme habituel est donc que le NAS soit client d'un protocole d'authentification et que le FAI gère un serveur de ce protocole, serveur qui connaitra les utilisateurs autorisés. Le même protocole assure en général également des fonctions de comptabilisation des accès, d'où le sigle AAA (Authentication, Authorization and Accounting). Le premier protocole standard en ce sens est Radius (RFC 2865), que Diameter vise à remplacer. (Un protocole privé, Tacacs, qui sera documenté dans le RFC 1492, avait également été utilisé.)

Que reproche Diameter à Radius ? La section 1 de notre RFC détaille les faiblesses de Radius perçues par les auteurs de Diameter. Une analyse plus détaillée figure dans le RFC 3169 :

  • Utilisation d'UDP, protocole de transport n'assurant pas de fiabilité,
  • Pas de mécanisme de redondance standard,
  • Limites de taille pour certains paramètres (par exemple la longueur d'un attribut n'est codée que sur un octet, ce qui limite les attributs à 256 caractères).

Diameter est donc plus riche et plus complexe que Radius.

Diameter reprend aussi plusieurs idées de Radius comme le codage en doublets Attribut / Valeur (AVP pour Attribute-Value Pairs) ou comme l'utilisation des NAI du RFC 7542 pour coder l'identité vérifiée.

Le RFC est donc bien plus long et compliqué que son équivalent Radius. La section 1 introduit le protocole, et ses usages, et le compare aux exigences listées dans le RFC 2989..

La section 2 précise le protocole, par exemple le mécanisme de transport fait l'objet de la sous-section 2.1, qui impose au minimum TCP et SCTP (les détails sont dans le RFC 3539). Diameter écoute par défaut sur le port 3868. La 2.4 introduit le nouveau concept d'Application Identifier, valeur enregistrées auprès de l'IANA qui identifie un usage particulier de Diameter (plus riche que Radius, Diameter permet davantage d'usages). Par exemple, l'usage en tant que service d'authentification pour un NAS (Application Identifier n° 1) n'est pas dans le cœur du protocole, il est délégué au RFC 4005. D'autres RFC décrivent des applications de Diameter comme le RFC 4740 qui parle de son usage pour SIP. 2.5 parle de la différence entre connexions et sessions, une connexion étant un concept de la couche 4 alors qu'une session Diameter peut impliquer plusieurs connexions. En 2.8, on trouve le bestiaire des agents Diameter, les clients et les serveurs bien sûr mais également les relais ou bien les traducteurs, pour parler à des agents d'autres protocoles, notamment Radius.

La section 3 décrit l'en-tête des paquets Diameter et les codes de commande qu'ils contiennent comme Capabilities-Exchange-Request. Seuls les codes communs à toutes les applications sont définis dans la section 3.1, des codes aussi importants que AA-Request (demande d'authentification, l'équivalent du Access-Request de Radius) sont délégués à d'autres RFC (comme le RFC 4005).

En section 4, nous arrivons aux AVP eux-même, les doublets attributs-valeur qui portent l'information. On notera en 4.1 un concept désormais fréquent dans les protocoles réseaux, l'option Mandatory qui indique pour un AVP, s'il doit absolument être connu de l'implémentation (le dialogue Diameter avorte autrement) ou bien s'il peut tranquillement être ignoré, par exemple par une vieille implémentation qui ne connait pas ce nouvel AVP. La sous-section 4.3 décrit, entre autre, les URI Diameter, de plan aaa:, comme aaa://host.example.com:666:transport=stcp;protocol=diameter.

Les sections 5 à 8 spécifient les nombreuses machines à état qui doivent être mises en œuvre par les agents Diameter. Au contraire de Radius qui, comme le DNS, est purement requête/réponse, Diameter nécessite un vrai automate dans chaque agent.

La sous-section 5.2 explique comment un agent Diameter peut en trouver un autre. Avec Radius, la configuration (par exemple du serveur d'authentification) devait être manuelle. Avec Diameter, on peut utiliser SLP (RFC 2165) ou NAPTR combiné avec SRV (RFC 2782).

La section 13, sur la sécurité, est très stricte. On y notera qu'un agent Diameter doit disposer d'IPsec.

Une bonne introduction à Diameter a été publié en http://www.interlinknetworks.com/whitepapers/Introduction_to_Diameter.pdf. Il n'existe que deux implémentations de serveur Diameter en logiciel libre, Open Diameter et OpenBlox, et elles semblent peu maintenues.

Le bilan opérationnel de Diameter est mince : beaucoup plus complexe que Radius, il ne l'a pas réellement remplacé dans son secteur, l'authentification via un NAS. Diameter semble bien être une nouvelle victime de l'effet « Deuxième système ». (À noter qu'une deuxième version de Diameter est sortie, peu différente, dans le RFC 6733.)


Téléchargez le RFC 3588


L'article seul

La technique des trois marteaux

Première rédaction de cet article le 20 février 2008


Une logique manageriale impeccable fait que la capitaine Le Floch a été envoyé en Bretagne pour élucider un meurtre assez particulier. Certes, elle est très compétente mais son chef s'est surtout dit que son nom la rendait particulièrement adaptée aux villages des monts d'Arrée.

Raté, la capitaine n'a jamais connu son père, à qui elle doit son nom, et tient de sa mère japonaise une allure peu bretonne. Cela ne se passera donc pas tout seul dans ce roman de Vanessa Fuks. De toute façon, n'importe quel flic parisien aurait eu du mal dans cette Bretagne noire à plaisir où presque tout le monde est abruti, violent, bigot et croit à l'Ankou.

C'est court, c'est écrit avec beaucoup de verve et de style et les personnages sont extra, surtout Akiko Le Floch essayant de comprendre quelque chose à ces meurtres (oui, il y en aura d'autres).


L'article seul

RFC 5230: Sieve Email Filtering: Vacation Extension

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : T. Showalter, N. Freed (Sun)
Chemin des normes
Première rédaction de cet article le 20 février 2008


Le langage de filtrage du courrier électronique Sieve repose sur un socle minimum, que doivent comprendre toutes les implémentations de Sieve, et un certain nombre d'extensions, couvrant des besoins supplémentaires. Ce RFC déclare l'extension vacation, qui permet de mettre en place un répondeur automatique.

La section 4 du RFC détaille l'extension et son mode d'emploi. Comme toute extension Sieve, elle doit être introduite par un require. Elle prend comme paramètre une chaîne de caractères qui sera envoyée à l'expéditeur et diverses options comme :addresses qui indique les adresses de destinataire que le script Sieve considérera comme locales (car un répondeur automatique ne doit pas répondre à n'importe quel message, seulement ceux où son maître est listé dans les champs comme To:, cf. section 4.5). Voici un exemple :

   require "vacation";
   vacation :addresses ["stephane@bortzmeyer.org",
                        "bortzmeyer@gmail.com"]
        "Je suis parti, je lirai avec plaisir votre message plus tard.";

Comme l'avertit le RFC 3834, un répondeur automatique est un programme dangereux, et tout le monde a déjà reçu des réponses stupides, par exemple alors qu'on avait écrit à une liste de diffusion, pas directement au destinataire. Ou bien des réponses multiples alors qu'on avait déjà été prévenu. D'où la section 4.2 qui précise qu'une mise en œuvre de vacation doit se souvenir de qui a déjà été prévenu, pendant au moins sept jours (valeur modifiable par l'option :days). Cette section est très détaillée car la règle exacte est plus complexe, elle doit prendre en compte le résultat des autres tests Sieve.

La section 5 décrit le message de réponse lui-même, les en-têtes qu'il doit avoir (comme In-Reply-To, section 5.8).

Ces messages de réponse étant destinés à des humains, la question de leur internationalisation est cruciale. L'expéditeur qui écrit en zazaki à un zazakophone serait surpris de recevoir un message en anglais ! C'est l'objet de la section 7 qui précise comment utiliser les en-têtes du RFC 3282 comme Content-Language :

    if header :contains ["accept-language", "content-language"] 
              "fr"
   {
       vacation "Je ne suis pas là.";
   } else {
       vacation "I am away.";
   }

Téléchargez le RFC 5230


L'article seul

RFC 2553: Basic Socket Interface Extensions for IPv6

Date de publication du RFC : Mars 1999
Auteur(s) du RFC : Robert E. Gilligan (FreeGate Corporation), Susan Thomson (Bell Communications Research), Jim Bound (Compaq Computer Corporation), W. Richard Stevens
Pour information
Première rédaction de cet article le 19 février 2008


A priori, l'IETF ne normalise pas d'API (et c'est pour cela que ce RFC n'a que le statut de « pour information »), se limitant aux « bits qu'on voit passer sur le câble ». Mais le monde de la normalisation n'est pas toujours si simple et, à l'époque, il était important de publier rapidement une documentation sur la nouvelle API nécessaire aux applications pour faire de l'IPv6.

Les API Unix et réseaux sont typiquement gérées par l'IEEE, via sa norme POSIX. Mais POSIX n'est pas librement téléchargeable sur le réseau, ce qui limite son utilité. Pour cette raison et pour d'autres, l'IETF a donc publié ce RFC, dont on notera qu'un des auteurs est W. Richard Stevens, auteur de Unix network programming, le livre de référence sur le sujet. Il succède à un premier RFC sur la question, le RFC 2133 et a lui-même été remplacé par le RFC 3493.

Depuis leur apparition, les prises (socket dans la langue de Stevens) sont le principal mécanisme d'accès au réseau pour les programmes. Les programmes qui les utilisent sont relativement portables, bien au delà du système BSD où elles sont nées. Traditionnellement multi-protocoles, les prises ne permettaient néanmoins pas d'accéder à IPv6. C'est désormais le cas et l'interface décrite dans ce RFC est désormais largement présente (MacOS X a été le dernier système d'exploitation à la proposer).

Elle ne concerne que le langage C. Les autres langages disposent souvent de mécanismes de plus haut niveau que les prises comme les Streams de Java.

Idéalement, la plupart des applications ne devrait pas avoir besoin de savoir si elles utilisent IPv4 ou IPv6. Concentrée dans la couche Réseau, le protocole utilisé ne devrait pas concerner l'application. Mais C est un langage de bas niveau, et expose donc le protocole de couche 3 utilisé (même si la section 2 du RFC explique que l'API cherche à être la plus générale possible).

La section 2.1 résume les principaux changements qui ont été faits pour permettre l'utilisation d'IPv6. Ils incluent une nouvelle constante (section 3.1) pour indiquer les adresses IPv6 (AF_INET6, puisque AF_INET, comme son nom ne l'indique pas clairement, étant spécifique à IPv4) et une pour le protocole IPv6 (PF_INET6). Notons que le RFC documente aussi PF_UNSPEC, qui permet à l'application de dire qu'elle se moque du protocole utilisé (ce qui devrait être le cas le plus courant). Il y a bien sûr une nouvelle structure de données (section 3.3) pour placer les adresses IPv6, quatre fois plus grandes. Les sockaddr sont désormais des représentations de la prise, indépendantes de la famille d'adresses, les sockaddr_in6 étant spécifiques à IPv6. Elles contiennent :

struct sockaddr_in6 {
    sa_family_t     sin6_family;    /* AF_INET6 */
    in_port_t       sin6_port;      /* transport layer port # */
    uint32_t        sin6_flowinfo;  /* IPv6 traffic class & flow info */
    struct in6_addr sin6_addr;      /* IPv6 address */
    uint32_t        sin6_scope_id;  /* set of interfaces for a scope */
};

Les appels système sur les prises, décrits dans la section 3.5, eux, ont peu changés, socket, connect, bind, continuent comme avant.

Les sections 3.6. et 3.7 concernent l'interopérabilité avec IPv4. Le monde des applications a une forte inertie. Les développeurs, déjà très occupés, ne portent pas leurs applications vers la nouvelle interface instantanément. Ces deux sections expliquent donc comment assurer le recouvrement des deux protocoles. On notera qu'avec cette interface, pour faire un serveur qui écoute en IPv4 et IPv6, il faut créer une prise IPv6, les clients IPv4 recevront alors des adresses IPv4-mapped comme ::FFFF:192.0.2.24. Ce n'est pas très intuitif... (Heureusement, c'est plus simple pour un client.)

La section 6 du RFC parle des fonctions de bibliothèque pour effectuer les traductions de noms en adresses et réciproquement. L'ancienne gethostbyname, très spécifique à IPv4 et souffrant d'autres limitations, ne devrait plus être utilisée depuis des années (le nombre de programmes qui l'utilisent encore ou de tutoriels qui l'expliquent donne une idée de l'extrême inertie d'un secteur qui se prétend novateur et réactif). Les « nouvelles » fonctions getaddrinfo et getnameinfo (section 6.4) la remplacent. Le RFC propose également en sections 6.1 et 6.2 getipnodebyname et getipnodebyaddr, qui seront supprimées dans le RFC suivant, le RFC 3493. Un programme typique désormais fait :


char *server = "www.example.org";
char *port_name = "42";

int mysocket; 

/* addrinfo est défini dans netdb.h et inclus une "struct sockaddr"
(une prise, incluant l'adresse IP) dans son champ ai_addr. Sa
description figure dans la section 6.4 du RFC. */
struct addrinfo hints, *result;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;

error = getaddrinfo(server, port_name, &hints, &result);
if (error) {
          err_quit("getaddrinfo error for host: %s %s",
                   server, gai_strerror(error));
}
/* La première adresse IP sera dans result->ai_addr, pour les
suivantes, il faudra suivre result->ai_next */
mysocket = socket(...);
error = connect(mysocket, result->ai_addr, result->ai_addrlen);
...

Un des rares cas où un client réseau a besoin de manipuler des adresses IP (pas seulement de les stocker et de les passer d'une fonction à une autre) est lors de l'affichage, par exemple en mode bavard. Pour éviter que le programme ne doive connaitre les détails de syntaxe des adresses (celle d'IPv4 n'a jamais été normalisée, celle d'IPv6 est décrite dans le RFC 4291), notre RFC décrit en section 6.6 des fonctions de conversion de et vers un format texte, inet_ntop et inet_pton.

L'inertie des programmeurs étant très forte, et celle des enseignants également, on peut parier, bien que ce RFC soit vieux de neuf ans, que beaucoup de cours de programmation réseaux sont encore donnés avec la vieille interface, qui ne marche qu'en IPv4...


Téléchargez le RFC 2553


L'article seul

RFC 3493: Basic Socket Interface Extensions for IPv6

Date de publication du RFC : Février 2003
Auteur(s) du RFC : R. Gilligan, S. Thomson, J. Bound, J. McCann, W. Stevens
Pour information
Première rédaction de cet article le 19 février 2008


A priori, l'IETF ne normalise pas d'API (et c'est pour cela que ce RFC n'a que le statut de « pour information »), se limitant aux « bits qu'on voit passer sur le câble ». Mais le monde de la normalisation n'est pas toujours si simple et, à l'époque, il était important de publier rapidement une documentation sur la nouvelle API nécessaire aux applications pour faire de l'IPv6.

Les API Unix et réseaux sont typiquement gérées par l'IEEE, via sa norme POSIX. Mais POSIX n'est pas librement téléchargeable sur le réseau, ce qui limite son utilité. Pour cette raison et pour d'autres, l'IETF a donc publié ce RFC, dont on notera qu'un des auteurs est W. Richard Stevens, auteur de Unix network programming, le livre de référence sur le sujet. Il succède au RFC 2553 et est complété par un RFC sur l'interface « avancée », le RFC 3542.

Depuis leur apparition, les prises (socket dans la langue de Stevens) sont le principal mécanisme d'accès au réseau pour les programmes. Les programmes qui les utilisent sont relativement portables, bien au delà du système BSD où elles sont nées. Traditionnellement multi-protocoles, les prises ne permettaient néanmoins pas d'accéder à IPv6. C'est désormais le cas et l'interface décrite dans ce RFC est désormais largement présente (MacOS X a été le dernier système d'exploitation à la proposer).

Elle ne concerne que le langage C. Les autres langages disposent souvent de mécanismes de plus haut niveau que les prises comme les Streams de Java.

Idéalement, la plupart des applications ne devrait pas avoir besoin de savoir si elles utilisent IPv4 ou IPv6. Concentrée dans la couche Réseau, le protocole utilisé ne devrait pas concerner l'application. Mais C est un langage de bas niveau, et expose donc le protocole de couche 3 utilisé (même si la section 2 du RFC explique que l'API cherche à être la plus générale possible).

La section 2.1 résume les principaux changements qui ont été faits pour permettre l'utilisation d'IPv6. Ils incluent une nouvelle constante (section 3.1) pour indiquer les adresses IPv6 (AF_INET6, puisque AF_INET, comme son nom ne l'indique pas clairement, étant spécifique à IPv4) et une pour le protocole IPv6 (PF_INET6). Notons que le RFC documente aussi PF_UNSPEC, qui permet à l'application de dire qu'elle se moque du protocole utilisé (ce qui devrait être le cas le plus courant). Il y a bien sûr une nouvelle structure de données (section 3.3) pour placer les adresses IPv6, quatre fois plus grandes. Les sockaddr sont désormais des représentations de la prise, indépendantes de la famille d'adresses, les sockaddr_in6 étant spécifiques à IPv6. Elles contiennent :

struct sockaddr_in6 {
    sa_family_t     sin6_family;    /* AF_INET6 */
    in_port_t       sin6_port;      /* transport layer port # */
    uint32_t        sin6_flowinfo;  /* IPv6 traffic class & flow info */
    struct in6_addr sin6_addr;      /* IPv6 address */
    uint32_t        sin6_scope_id;  /* set of interfaces for a scope */
};

Les appels système sur les prises, décrits dans la section 3.5, eux, ont peu changés, socket, connect, bind, continuent comme avant.

Les sections 3.6. et 3.7 concernent l'interopérabilité avec IPv4. Le monde des applications a une forte inertie. Les développeurs, déjà très occupés, ne portent pas leurs applications vers la nouvelle interface instantanément. Ces deux sections expliquent donc comment assurer le recouvrement des deux protocoles. On notera qu'avec cette interface, pour faire un serveur qui écoute en IPv4 et IPv6, il faut créer une prise IPv6, les clients IPv4 recevront alors des adresses IPv4-mapped comme ::FFFF:192.0.2.24. Ce n'est pas très intuitif... (Heureusement, c'est plus simple pour un client.)

La section 6 du RFC parle des fonctions de bibliothèque pour effectuer les traductions de noms en adresses et réciproquement. L'ancienne gethostbyname, très spécifique à IPv4 et souffrant d'autres limitations, ne devrait plus être utilisée depuis des années (le nombre de programmes qui l'utilisent encore ou de tutoriels qui l'expliquent donne une idée de l'extrême inertie d'un secteur qui se prétend novateur et réactif). Les « nouvelles » fonctions getaddrinfo et getnameinfo (section 6.4) la remplacent. Un programme typique désormais fait :


char *server = "www.example.org";
char *port_name = "42";

int mysocket; 

/* addrinfo est défini dans netdb.h et inclus une "struct sockaddr"
(une prise, incluant l'adresse IP) dans son champ ai_addr. Sa
description figure dans la section 6.4 du RFC. */
struct addrinfo hints, *result;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;

error = getaddrinfo(server, port_name, &hints, &result);
if (error) {
          err_quit("getaddrinfo error for host: %s %s",
                   server, gai_strerror(error));
}
/* La première adresse IP sera dans result->ai_addr, pour les
suivantes, il faudra suivre result->ai_next */
mysocket = socket(...);
error = connect(mysocket, result->ai_addr, result->ai_addrlen);
...

Un des rares cas où un client réseau a besoin de manipuler des adresses IP (pas seulement de les stocker et de les passer d'une fonction à une autre) est lors de l'affichage, par exemple en mode bavard. Pour éviter que le programme ne doive connaitre les détails de syntaxe des adresses (celle d'IPv4 n'a jamais été normalisée, celle d'IPv6 est décrite dans le RFC 4291), notre RFC décrit en section 6.6 des fonctions de conversion de et vers un format texte, inet_ntop et inet_pton.

Enfin, la section 9 liste les différences avec son prédécesseur, le RFC 2553. Rien de très important ici.

L'inertie des programmeurs étant très forte, et celle des enseignants également, on peut parier, bien que le premier RFC sur le sujet soit vieux de onze ans, que beaucoup de cours de programmation réseaux sont encore donnés avec la vieille interface, qui ne marche qu'en IPv4... À l'appui de ce pari, notons que le service Code Search de Google trouve 255 000 occurrences de gethostbyname contre seulement 78 200 de getaddrinfo.


Téléchargez le RFC 3493


L'article seul

Quel est le plus rapide serveur DNS d'un groupe ?

Première rédaction de cet article le 13 février 2008


Mesurer les performances d'un service informatique est un art difficile mais néanmoins indispensable à l'administrateur système. Parmi ces services, le DNS présente la particularité que plusieurs serveurs répondent pour une zone donnée. De même, une machine connectée à l'Internet a souvent le choix entre plusieurs serveurs comme résolveurs. Dans un groupe, quel est le plus rapide de ces serveurs ? Un petit programme permet de répondre à cette question.

Supposons que je m'interroge sur le temps de réponse d'un service dont le nom figure dans la zone example.com. Le temps de réponse du DNS doit être pris en compte. Ou bien je me demande si je dois utiliser les résolveurs fournis par mon FAI, ou bien un BIND que j'ai installé sur ma machine, ou bien encore un service tiers comme OpenDNS, qui résout gratuitement des noms de domaine en échange d'une manipulation des réponses pour insérer de la publicité. Quel résolveur est le plus rapide ?

On peut mesurer le temps de réponse d'un serveur avec echoping :

% echoping -n 3  -m dns c.nic.fr -t SOA fr 
Elapsed time: 0.118128 seconds
Elapsed time: 0.074891 seconds
Elapsed time: 0.047331 seconds
---
Minimum time: 0.047331 seconds (5409 bytes per sec.)
Maximum time: 0.118128 seconds (2167 bytes per sec.)
Average time: 0.080116 seconds (3195 bytes per sec.)
Standard deviation: 0.029137
Median time: 0.074891 seconds (3418 bytes per sec.)

Ou bien on peut utiliser dig qui affiche, tout à la fin, le temps écoulé :

% dig @c.nic.fr SOA fr.              
...
;; Query time: 55 msec

Mais pour comparer N serveurs, c'est un peu pénible. D'autant plus que dig, contrairement à echoping, ne permet pas de répéter un test, ce qui est indispensable lorsqu'on fait des mesures sur Internet, où les temps de réponse varient souvent considérablement.

Joe Abley a donc développé pour cela qtest, le programme décrit plus bas, programme que j'ai un peu amélioré. Ce programme prend comme argument une requête DNS par exemple MX elysee.fr. ou bien ANY www.example.com. et une liste de serveurs à tester. Il affiche les N serveurs les plus rapides (N vaut 1 par défaut mais on peut le changer avec l'option -n) ainsi que leur temps de réponse en milli-secondes. Par exemple :

% qtest "SOA fr." a.nic.fr c.nic.fr e.nic.fr
46 c.nic.fr/192.134.0.129

Ce test permettra de comparer les temps de réponse de ces trois serveurs de l'AFNIC (bien sûr, le résultat dépendra de l'endroit où on se trouve, d'autant plus que e.nic.fr est à la Réunion). Pour tester pour une zone donnée (ici, la racine), on peut utiliser la possibilité qu'à le shell d'exécuter une commande et d'utiliser son résultat comme variable, ici avec la syntaxe $(commande arguments...) :

% qtest "SOA ." $(dig +short NS .)
3 F.ROOT-SERVERS.NET./2001:500:2f::f

f.root-servers.net a répondu le premier, en trois milli-secondes. Pour voir davantage de serveurs :

%  qtest -n 5 "SOA ." $(dig +short NS .) 
3 F.ROOT-SERVERS.NET./2001:500:2f::f
3 M.ROOT-SERVERS.NET./2001:dc3::35
6 F.ROOT-SERVERS.NET./192.5.5.241
21 I.ROOT-SERVERS.NET./192.36.148.17
21 K.ROOT-SERVERS.NET./193.0.14.129

qtest est écrit en shell. Après analyse de ses arguments avec getopt, il boucle sur les serveurs de noms passés en argument. Pour chacun d'eux, il cherche l'ensemble des adresses IPv4 et IPv6 (les temps de réponse peuvent être très différents entre les deux protocoles), stocke chaque couple <nom de machine, adresse IP> dans une chaîne de caractères, la barre oblique servant de séparateur (le shell Unix n'a pas de structures de données perfectionnées). Pour chaque couple, qtest fait trois essais avec dig. Les calculs statistiques (moyenne, tri, hélas pas de médiane) sont faits avec awk.

Ici, on va comparer un résolveur local, ceux fournis par le FAI, et ceux de deux services commerciaux, OpenDNS et DNS Advantage de Neustar. Cette fois, on fait appel à des serveurs récursifs, ayant un cache des réponses précédemment obtenues, et le choix de la question est donc important. Si la réponse est dans le cache (ce qui est typiquement le cas si on demande l'adresse de www.google.com), tout ira bien plus vite ! Essayons d'abord avec un nom qui est probablement dans le cache. 172.19.1.1 est un résolveur local, ceux commençant par 62.4 sont les résolveurs de mon FAI, ceux commençant par 208.67.222 sont à OpenDNS et ceux commençant par 156.154 sont ceux de DNS advantage. qtest affiche toujours l'adresse IP après la barre oblique même lorsque, comme ici, c'est inutile puisque l'identité du serveur était déjà une adresse IP :

% qtest -n3 "A a.gtld-servers.net" 172.19.1.1 62.4.16.70 62.4.17.69 208.67.222.222 208.67.220.220 156.154.70.1 156.154.71.1  
3 172.19.1.1/172.19.1.1
49 62.4.17.69/62.4.17.69
61 208.67.222.222/208.67.222.222

On voit que les résolveurs les plus proches sont les plus rapides (un test avec un nom inexistant, donc pas dans le cache, donne le même résultat) contrairement aux prétentions des vendeurs d'OpenDNS ou de Neustar. Il ne faut jamais se fier à la publicité. Le test a été fait depuis une machine en Europe, où OpenDNS et DNS Advantage ont peu de serveurs. Est-ce mieux aux États-Unis ? Non (ici, les serveurs du fournisseur d'hébergement sont ceux commençant par 208.75 et 208.78 :

0 127.0.0.1/127.0.0.1
0 208.78.97.155/208.78.97.155
1 208.75.87.250/208.75.87.250
23 156.154.70.1/156.154.70.1
25 156.154.71.1/156.154.71.1
29 208.67.220.220/208.67.220.220
29 208.67.222.222/208.67.222.222

Bref, si on veut des temps de réponse rapides, rien ne vaut les serveurs de son FAI.

Vous pouvez récupérer le programme qtest. Plus riche, plus graphique et plus complexe, il y a l'excellent Namebench.


L'article seul

RFC 2474: Definition of the Differentiated Services Field (DS Field) in the IPv4 and IPv6 Headers

Date de publication du RFC : Décembre 1998
Auteur(s) du RFC : Kathleen Nichols (Cisco), Steven Blake (Torrent Networking Technologies), Fred Baker (Cisco), David L. Black (EMC Corporation)
Chemin des normes
Première rédaction de cet article le 13 février 2008
Dernière mise à jour le 18 février 2008


La question du traitement differencié des paquets IP occupe beaucoup de monde depuis les débuts de l'Internet. En gros, il s'agit de savoir si les routeurs et autres équipements intermédiaires vont traiter tous les paquets IP de la même manière, où bien si certains auront la priorité, ou en tout cas un traitement particulier selon certains critères. Si la question a un aspect politique, lié à la revendication de neutralité du réseau, pour savoir qui va décider quels paquets seront sacrifiés, notre RFC ne couvre que l'aspect technique : il change complètement un des champs du paquet IP, pour tenir compte de l'échec qu'avait été ce champ Type Of Service.

Avant de mettre en œuvre des traitements differenciés, encore faut-il savoir à quels paquets les appliquer. Dans le RFC original sur IPv4, le RFC 791, un champ du paquet, TOS, Type Of Service était réservé au marquage du paquet. Il permettait d'indiquer la priorité souhaitée et les critères les plus importants pour ce paquet (débit, coût, latence, etc). La norme Posix prévoit des moyens pour les applications de définir ces champs (un programme comme echoping les met en œuvre avec ses options -p et -P). Voici un exemple en C de définition du champ TOS avec setsockopt :

result = setsockopt(mysocket, IPPROTO_IP, 
                   IP_TOS, IPTOS_THROUGHPUT, sizeof(int));
/* IPTOS_THROUGHPUT vaut 0x08 et était censé maximiser le débit. Cf. RFC 791,
   section 3.1 */

Pour voir les capacités des différents systèmes d'exploitation à fixer ces valeurs, on peut regarder mon article sur la fixation d'options IP depuis un programme.

Ce mécanisme n'a eu aucun succès, peu d'applications fixent ce champ et peu de routeurs le traitaient comme spécifié. Il y a plusieurs raisons à cet échec, et toutes ne sont pas techniques, loin de là. Par exemple, comment empêcher une application de toujours demander la plus forte priorité ? (La question est discutée dans le section 7.1 de notre RFC.)

Parmi les raisons techniques, il y avait le fait que le mécanisme du RFC 791 était trop rigide. Par exemple, les critères exprimables étaient en nombre limité et trop vagues. Une nouvelle architecture pour la qualité de service, Differentiated Services, connue sous l'abréviation de Diffserv a été définie dans le RFC 2475. Ses conséquences pratiques sur le format des paquets font l'objet de notre RFC 2474, qui met donc à jour le RFC 791 et qui s'applique également à son équivalent IPv6, le RFC 2460, pour la définition du champ Traffic class (équivalent IPv6 du champ TOS).

Le champ TOS de IPv4 change donc de nom. Il devient DS (Differentiated Services) et la sémantique n'est plus fixée par le RFC. Un TOS de 0x08 voulait toujours dire « Je cherche à maximiser le débit » alors qu'un DS de 0x08 aura une signification donnée par les routeurs du domaine administratif où le paquet passe. Aux frontières de ces domaines, par exemple pour passer d'un opérateur à un autre, il faudra changer le champ (section 2 du RFC) ou bien utiliser des valeurs attribuées par un accord entre opérateurs (Diffserv définit un mécanisme, pas une politique). La section 1 de notre RFC prévient que, si le forwarding de chaque paquet est un problème bien connu, l'attribution et la gestion de politiques de qualité de service est un problème bien plus ouvert. Neuf ans après la sortie du RFC, il ne semble pas en voie de résolution. La même section 1 rappelle que des politiques simples et appliquées statiquement sont peut être la meilleure solution.

La section 3 décrit le nouveau champ DS. Voici l'ancien champ ToS, sur huit bits, du RFC 791 :

         0     1     2     3     4     5     6     7
      +-----+-----+-----+-----+-----+-----+-----+-----+
      |                 |     |     |     |     |     |
      |   PRECEDENCE    |  D  |  T  |  R  |  0  |  0  |
      |                 |     |     |     |     |     |
      +-----+-----+-----+-----+-----+-----+-----+-----+

Et voici le nouveau champ DS (Differentiated Services) :


        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |         DSCP          |  CU   |
      +---+---+---+---+---+---+---+---+

        DSCP: differentiated services codepoint
        CU:   currently unused

(La partie réservée a été remplie ultérieurement par l'ECN du RFC 3168.) Le champ DSCP contient un index dans une table des PHB (per-host behavior) qui sont les traitements que le routeur applique. Des exemples de PHB sont « fait passer ce paquet devant tout le monde dans la queue » ou bien « n'hésite pas à jeter ce paquet si le réseau est congestionné ». Le PHB par défaut (section 4.1) étant le traditionnel « faire de son mieux » des routeurs IP. Certains RFC définissent des PHB comme le RFC 2597 sur le Assured Forwarding.

On voit sur les schémas que, contrairement à l'ancien TOS, le DSCP n'a pas de structure interne. 64 valeurs différentes sont possibles, et les sections 4 et 5 discutent de leur allocation, la section 6 couvrant d'éventuelles standardisations de certaines valeurs.

Si on regarde ce qui passe sur le réseau avec tshark (option -V), on verra :

Internet Protocol, Src Addr: 172.19.1.1 (172.19.1.1), Dst Addr: 172.19.1.2 (172.19.1.2)
...
    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

On voit que le 0x08 mis dans le champ équivaut à un DSCP de 0x02, qui ne correspond pas à une valeur connue de manière standard (d'où le Unknown DSCP).

L'informatique est un monde très conservateur et, neuf ans après la sortie de ce RFC, on continue couramment à utiliser des mots comme TOS, normalement abandonnés (cf. par exemple la bogue echoping #1892544). La norme Posix continue à définir uniquement des constantes pour l'ancien comportement (comme IP_TOS ou IPTOS_THROUGHPUT, utilisés plus haut). Il n'est pas facile de changer une API si utilisée !

Sur Linux, on peut aussi changer la valeur du champ DSCP avec Netfilter et sa commande iptables. Cela se fait en modifiant la table mangle (qui permet de modifier un paquet, pas seulement de l'accepter ou de le refuser), avec la pseudo-chaîne de destination DSCP. Par exemple :

# iptables -t mangle -A OUTPUT -p tcp --dport 22 -j DSCP --set-dscp 0x02

va changer le DSCP de tous les paquets à destination du port 22. Pour les raisons expliquées plus haut, tcpdump va afficher ce DSCP de 0x2 en 0x8 :

17:50:35.477598 IP (tos 0x8, ttl 64, id 1040, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.2.1.36067 > 10.22.58.30.22: Flags [S], cksum 0xe4b2 (correct), seq 3255303173, win 5840, options [mss 1460,sackOK,TS val 8714261 ecr 0,nop,wscale 6], length 0

Pour mettre en œuvre le traitement différencié sur un routeur Cisco, on peut consulter Implementing Quality of Service Policies with DSCP.

Aujourd'hui, DSCP ne semble pas avoir eu beaucoup plus de succès que son prédécesseur. Il est difficile de mesurer le taux de déploiement car tous sont internes à une organisation. Certains RFC comme le RFC 4504 (section 2.12) ont rendu obligatoire l'utilisation de DSCP mais ils n'ont pas forcément été respectés. Si une entreprise qui déploie de la VoIP utilise DSCP en interne pour permettre aux coups de téléphone de passer même lorsqu'un gros transfert de fichiers est en cours, tout en simplifiant la configuration de ses routeurs, cela ne se voit pas à l'extérieur.


Téléchargez le RFC 2474


L'article seul

Convertir un dépôt CVS en Subversion

Première rédaction de cet article le 12 février 2008


Le VCS (logiciel de gestion de versions) CVS est bien vieux et souffre de nombreux inconvénients (voir par exemple l'introduction de mon article à JRES sur les nouveaux VCS). Une fois prise la décision de migrer vers Subversion, comment convertir les données existantes ?

Si on part de zéro, migrer vers Subversion est très simple, les commandes pour l'utilisateur étant quasiment identiques à celles de CVS. Mais si on a déjà des années de développement logiciel ou d'écriture de documents derrière soi et qu'on ne veut pas abandonner l'historique ? Si on est hébergé par un service tel que SourceForge, ce service fournit probablement un mécanisme de conversion (celui de SourceForge est bien documenté et marche très bien). Mais si on gère l'hébergement soi-même ? Alors, il faut utiliser un logiciel de conversion. Il en existe un très grand nombre, le plus spectaculaire étant sans doute tailor, qui peut convertir de n'importe quel VCS vers n'importe quel autre. Toutefois, tailor n'est pas sans bogues et, si on veut simplement passer de CVS à Subversion, le plus simple cvs2svn suffit largement. Il a l'intérêt d'être très robuste et de gérer tous les cas, à commencer par les branches.

L'utilisation est très simple. Si mon dépôt CVS se trouve dans CVS_REPOSITORY et que je veux mettre le futur dépôt Subversion en SVN_REPOSITORY, je tape juste :

cvs2svn -s $SVN_REPOSITORY $CVS_REPOSITORY

Il détaille alors l'opération de conversion. Je n'ai plus qu'à tester le dépôt obtenu :

svn log file://$SVN_REPOSITORY/

et, si j'obtiens correctement l'historique, c'est que tout est bon.

Les dépôts CVS en France ont parfois des messages de commit avec des encodages variés. Si c'est le cas, il faut l'indiquer au convertisseur :

cvs2svn  --encoding iso-8859-1 -s $SVN_REPOSITORY $CVS_REPOSITORY

Je ne connais pas de moyen de convertir la copie de travail (le résultat du checkout). Il faut donc vérifier, avant la conversion, que tout a bien été committé, puis effacer chaque copie de travail et refaire un checkout.


L'article seul

Tester quels bits de l'en-tête IP on peut changer

Première rédaction de cet article le 12 février 2008


Le protocole IP permet d'indiquer dans l'en-tête des paquets plusieurs options, qui peuvent indiquer au routeur un traitement spécifique du paquet. Pour un programme ordinaire, utilisant les API standard, quelles options peuvent être facilement définies à l'émission, et lues à la réception ?

La question a surgi dans le groupe de travail Behave de l'IETF, à propos du protocole TURN (depuis normalisé dans le RFC 5766). TURN relaie des paquets, notamment UDP entre deux clients qui ne peuvent pas se parler directement. Le serveur TURN doit-il respecter les en-têtes des paquets IP ? Si le RFC impose cette contrainte, pourra t-on programmer un serveur TURN en n'utilisant que les API standard ? Si le serveur tourne sur Unix, devra t-il le faire en étant root ?

Les bits en question sont définis dans divers RFC. Ainsi, le RFC 791, qui définissait IPv4 à l'origine, définit un groupe de bits nommé le TOS (Type Of Service), qui permet de fixer la priorité du paquet et ses choix (privilégier le débit, le coût, etc). Ce groupe a été remplacé par le DSCP (Differentiated Services Code Point) dans le RFC 2474. Puis le RFC 3168 a utilisé deux autres bits pour ECN (Explicit Congestion Notification). D'autres bits sont modifiables potentiellement comme le TTL ou comme DF (Don't Fragment).

Mais une application typique ne fabrique pas les paquets IP à la main, bit par bit. Elle compte sur une API standard, typiquement sur Posix. (Sur un système comme Unix, faire des paquets entièrement soi-même et les envoyer nécessite d'être root de toute façon.) Que nous permet cette API ?

C'est pour répondre à cette question que j'ai développé un ensemble de petits programmes, qu'on peut récupérer dans le fichier tests-socket.tar.gz. Ces programmes sont prévus pour être compilés et exécutés sur un grand nombre de machines et ils affichent un rapport détaillé qui peut être transmis au groupe de travail.

Pour les compiler et les exécuter, voir les instructions dans le fichier README qui est joint. Voici des exemples d'exécution du programme ip-header-set qui teste s'il peut demander avec succès les options :

% ./ip-header-set 
Testing of the abilities to set bits in the IP header
My UID is 1000
The system is Linux 2.6.18-5-686, the machine is i686
TTL successfully set to 10
TOS successfully set to 8
ECN successfully set to 2
[PROBLEM] Cannot set the precedence to 160:  (Operation not permitted)
DF set through PMTU successfully set to 2
DF clear through PMTU successfully set to 0

Warning: we only tested that setsockopt was happy,
        not that the actual packet headers were changed

On voit que, sur Linux, on peut apparemment presque tout fixer à la valeur souhaitée, sauf la priorité qu'on ne peut pas augmenter (si on est root, ça marche). Sur un autre système, les succès et les échecs ne sont pas les mêmes :

Testing of the abilities to set bits in the IP header
My UID is 54131
The system is FreeBSD 6.2-RELEASE, the machine is i386
TTL successfully set to 10
TOS successfully set to 8
ECN successfully set to 2
precedence successfully set to 160
No known way to set the DF bit on this system

Warning: we only tested that setsockopt was happy,
        not that the actual packet headers were changed

Donc, la fonction de définition des options a marché. Mais le paquet IP émis a t-il réellement changé ? Pour le savoir, nous utilisons désormais deux programmes, sender qui va fixer les options et envoyer les paquets et receiver qui va les lire. sender affiche à peu près la même chose que ip-header-set mais il envoie réellement le paquet UDP :

% ./sender test.example.org 10000
Testing of the abilities to set bits in the IP header
My UID is 1000
The system is Linux 2.6.18-5-686, the machine is i686
TTL successfully set to 10
TOS successfully set to 8
ECN successfully set to 2
[PROBLEM] Cannot set the precedence to 160: 
DF set through PMTU successfully set to 2
DF clear through PMTU successfully set to 0

et, sur la machine de réception (ici, identique) :

% ./receiver 10000
Testing of the abilities to read bits in the IP header
My UID is 1000
The system is Linux 2.6.18-5-686, the machine is i686
Received 5 bytes
        The TTL is 10
        The TOS/DSCP is 0
Received 5 bytes
        The TTL is 64
        The TOS/DSCP is 8
Received 5 bytes
        The TTL is 64
        The TOS/DSCP is 2
Received 5 bytes
        The TTL is 64
        The TOS/DSCP is 0
Received 5 bytes
        The TTL is 64
        The TOS/DSCP is 0
Received 5 bytes
        The TTL is 64
        The TOS/DSCP is 0

On voit que l'API disponible sur Linux permet de lire les options, et qu'elles ont la bonne valeur. Si on n'a pas confiance, on peut vérifier avec un sniffer comme tcpdump :

09:44:00.127838 IP (tos 0x0, ttl  10, id 35166, offset 0, flags [DF], proto: UDP (17), length: 33) 192.0.2.69.47491 > 192.0.2.69.10000: UDP, length 5
09:44:00.127873 IP (tos 0x8, ttl  64, id 35166, offset 0, flags [DF], proto: UDP (17), length: 33) 192.0.2.69.47491 > 192.0.2.69.10000: UDP, length 5

Sur cette trace des deux premiers paquets, on voit le changement du TTL à 10, et on voit le TOS mis à 8.

Comment travaillent ces programmes ? Pour définir les options comme le TOS/DSCP ou comme ECN, ils utilisent l'appel système setsockopt ainsi :

myecn = 0x02;	/* ECN-capable transport */
result = setsockopt(mysocket, IPPROTO_IP, 
                    IP_TOS, myecn, sizeof(int));

On note que Posix appelle toujours TOS (cf. la constante IP_TOS) ce qui se nomme normalement DSCP depuis le RFC 2474 il y a neuf ans. Ce n'est pas facile de faire évoluer une API ! Cela explique un certain manque de rigueur dans mes programmes, où TOS et DSCP sont utilisés simultanément.

Pour fixer le TTL, le principe est le même. Mais pour mettre le bit DF (Don't Fragment, voir les RFC 1191 et RFC 2923) à un, il faut le faire indirectement, en demandant d'activer ou non la découverte de la MTU du chemin (et cela ne marche que sur Linux) :

result = setsockopt(mysocket, IPPROTO_IP, 
                    IP_MTU_DISCOVER, IP_PMTUDISC_DO, sizeof(int));

Et pour lire les options ? C'est nettement plus compliqué. Une méthode assez peu standard existe, qui dépend des messages de contrôle des prises (cf. cmsg) et de recvmsg :


const int       One = 1;
...
/* On demande à *recevoir* les messages de contrôle avec le TTL */        
result = setsockopt(mysocket, IPPROTO_IP, IP_RECVTTL, &One, sizeof(One));
...
/* Et, pour chaque paquet reçu */
memset(message, 0, sizeof(*message));
message->msg_iov = malloc(sizeof(struct iovec));
/* Les données seront mises dans "buffer" */
message->msg_iov->iov_base = buffer;
message->msg_iov->iov_len = length;
message->msg_iovlen = 1;
/* Et les messages de contrôle dans "control_buffer" */
message->msg_control = control_buffer;
message->msg_controllen = control_length;
result = recvmsg(mysocket, message, 0);
if (result <= 0) {
	err_ret("[PROBLEM] Cannot receive data (%s)", sys_err_str());
} else {
	fprintf(stdout, "Received %i bytes\n", result);
	for (c_msg = CMSG_FIRSTHDR(message); c_msg;
             c_msg = (CMSG_NXTHDR(message, c_msg))) {
			if (c_msg->cmsg_level == IPPROTO_IP && 
                             c_msg->cmsg_type == IP_TTL) {
				fprintf(stdout, "\tThe TTL is %i\n",
					*(int *) CMSG_DATA(c_msg));


L'article seul

RFC 5136: Defining Network Capacity

Date de publication du RFC : Février 2008
Auteur(s) du RFC : P. Chimento (JHU Applied Physics Lab), J. Ishac (NASA)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 12 février 2008


Ce RFC définit un concept important en matière de métrologie du réseau, le concept de capacité qui remplace celui, ambigu, de bande passante.

Le groupe de travail IP Performance Metrics de l'IETF continue à ajouter au savoir commun d'intéressants RFC normalisant notamment les concepts utilisés, afin que des comparaisons puissent être faites entre les mesures effectuées par des équipes différentes. Ce RFC s'attaque au concept de capacité (capacity), qui a vocation à remplacer celui, flou et peu exact, de bande passante.

Une des raisons du flou est la volontée délibérée par certains acteurs de présenter des chiffres plus favorables. On voit ainsi souvent, sur le marché de l'accès Internet par ADSL des chiffres donnés en débit de la couche physique, pas en débit des couches plus hautes, pourtant les seules qui intéressent les utilisateurs. Le concept de bande passante avait aussi d'autres défauts, comme son origine dans le monde de l'analogique qui faisait que, même utilisé correctement, son étymologie était source de confusion. Ainsi, la section 3.4 donne l'exemple d'un lien 802.11b où l'électronicien annoncera une « bande passante » de 25 Mhz, l'ingénieur réseaux une « bande passante » de 11 Mbps, alors que l'utilisateur final ne pourra pas obtenir plus de 8 Mbps de débit.

La section 1 de notre RFC donne d'autres exemples des différences de capacité selon les couches. Par exemple, le codage Manchester de l'Ethernet classique fait perdre une bonne partie de la capacité théorique. Tout mécanisme de somme de contrôle consomme également des bits qui sont perdus pour les couches hautes. Les mécanismes d'accès au réseau peuvent encore réduire la capacité théorique. C'est ainsi que le CSMA/CD de l'Ethernet classique ne permet pas d'utiliser toute la capacité théorique. Des chiffres de 35 % d'utilisation maximale de l'Ethernet avaient circulé à une époque mais ils ne reposaient, ni sur un calcul théorique, ni sur des expériences ; et ils étaient totalement faux. Ceci dit, on ne peut pas atteindre les 100 %.

Bref, la capacité ne peut être sérieusement définie que pour une couche donnée.

La section 2 s'attaque aux définitions proprement dites. Reprenant les notions de lien et de chemin du RFC 2330, ainsi que la notion de « paquets de type P » (paquets d'un type donné, pour tenir compte du fait que le débit mesuré peut dépendre du type de paquets, TCP plutôt que UDP, par exemple) notre RFC définit :

  • La capacité physique théorique du lien (Nominal physical link capacity). Elle est mesurée à la couche 1 et vaut donc, par exemple, 155,52 Mbps pour un OC-3.
  • La capacité IP du lien (IP-type-P link capacity ). Elle est mesurée à la couche 3 et elle inclus donc dans son calcul les bits de l'en-tête des paquets IP. Les applications, dans les couches plus hautes, ne pourront donc pas utiliser toute cette capacité.
  • La capacité IP du chemin (IP-type-P Path Capacity). Attention, c'est IP et pas TCP donc, en cas de retransmission de paquets erronés, la capacité TCP sera plus faible.
  • L'utilisation du lien (IP-type-P Link Usage et IP-type-P Link Utilization) qui indique l'usage effectif qui est fait du lien.
  • La capacité disponible (IP-type-P Available Link Capacity et IP-type-P Available Path Capacity), qui est simplement la capacité moins l'utilisation.

La section 3 est ensuite consacrée à discuter de cette terminologie et des difficultés de mesure. C'est là par exemple qu'est traité le cas de la compression (par exemple avec ROHC, RFC 3095) ou bien le rapport entre la capacité et les grandeurs définies par le RFC 3148 (ce dernier RFC traite de la capacité utile, c'est-à-dire des données effectivement transmises par le protocole de transport).


Téléchargez le RFC 5136


L'article seul

RFC 2050: INTERNET REGISTRY IP ALLOCATION GUIDELINES

Date de publication du RFC : Novembre 1996
Auteur(s) du RFC : Kim Hubbard (InterNIC Registration Services), Mark Kosters (InterNIC Registration Services), David Conrad (Asia Pacific Network Information Center), Daniel Karrenberg (RIPE NCC), Jon Postel (USC/Information Sciences Institute)
Première rédaction de cet article le 10 février 2008


Les règles d'affectation des adresses IP sont un des sujets chauds (ou qui devraient l'être) de la gouvernance de l'Internet. Comme toute ressource critique et limitée, sa gestion fait l'objet d'âpres débats. Ce RFC est le seul qui parle de cette gestion, domaine réservé des RIR. (Il a depuis été remplacé par le RFC 7020.)

Ce n'est pas l'IETF mais le groupe des RIR existants à l'époque qui a écrit ce RFC. Une note de l'IESG en tête précise d'ailleurs que ce RFC documente une politique, sans forcément l'approuver. En effet, les politiques d'attribution des adresses IP sont actuellement entièrement gérées au sein des RIR, même si des organismes comme l'ICANN ou, plus récemment, l'ITU ont parfois essayé de s'en mêler. Mais pourquoi des décisions aussi techniques que l'attribution des adresses du bloc 192.0.2.0/24 devraient-elles poser des problèmes politiques ?

Il y a deux problèmes avec ces adresses : l'un est la taille limitée du registre. Si un protocole prévoit huit bits pour un champ indiquant une option, cela ne laisse que 256 valeurs possibles et l'organisme qui gère ces valeurs (l'IANA pour les protocoles Internet) doit les attribuer avec prudence, pour ne pas épuiser trop tôt la ressource. Or, les adresses IPv4 étant sur 32 bits (quatre milliards de valeurs), on ne peut pas en affecter une à chaque habitant de la planète. En pratique, il y a même moins de quatre milliards d'adresses possibles, en raison du facteur H (expliqué en RFC 1715 et RFC 3194). IPv6 résout complètement ce problème, avec ses adresses sur 128 bits.

Mais il existe aussi un autre problème : les préfixes d'adresses IP sont manipulés par les routeurs, échangés avec le protocole BGP (RFC 4271) et stockés dans les tables de routage desdits routeurs. Il existe des limites, aussi bien à la taille de ces tables (les routeurs de haut de gamme n'utilisent typiquement pas de la mémoire standard mais des ASIC spécialisés, très rapides mais plus limités en taille), qu'à la quantité de données échangées en BGP si les tables grossissent « trop ». La controverse technique fait rage entre certains gros opérateurs acharnés à limiter la taille des tables de routage et certains utilisateurs qui pensent que les limites ne sont pas purement techniques et que le désir de limiter la concurrence entre opérateurs joue également un rôle (voir par exemple le RFC 4984 pour une passionnante discussion sur le sujet).

Cela explique que gérer des adresses IP ne soit pas une tâche purement administrative d'enregistrement. Les RIR, émanation des opérateurs Internet, ont donc des politiques d'allocation, qui sont en IPv4 très restrictives, et qui le deviendront encore plus au fur et à mesure que la pénurie s'aggrave.

Ce RFC, qui succède au RFC 1466, décrit ces politiques, dans leurs grands principes (les politiques précises sont décrites sur le site Web de chaque RIR, elles changent assez souvent). Sa section 1 pose les buts, qui découlent des problèmes décrits plus haut :

  • Conservation d'une ressource rare (un problème, on l'a vu, qui disparait avec IPv6).
  • « Routabilité ». Ce point technique est par contre quasi-identique en v4 et v6. Il fait référence au fait qu'une mauvaise gestion des adresses IP pourrait se traduire par un travail insupportable pour les routeurs. Par exemple, si les adresses IP des clients d'un même fournisseur ne sont pas agrégeables en un petit nombre de préfixes (par exemple parce qu'elles ne sont pas contigües), le fournisseur va annoncer en BGP beaucoup plus de préfixes, au détriment de tous (voir le fameux CIDR report pour l'état actuel de l'agrégation).
  • Enregistrement des informations sur les allocations, afin de pouvoir tracer l'utilisateur d'une adresse. C'est pour cela que les RIR ont un serveur whois (RFC 3912).

La même section 1 présente les différents acteurs, de l'IANA (fonction actuellement assurée par l'ICANN), qui alloue des adresses aux RIR, jusqu'aux LIR (en général des FAI) qui les reçoivent des RIR.

Notons que l'IANA n'a traditionnellement jamais mis de critères à la distribution d'adresses IP aux RIR. Malgré la très théorique section 6, qui donne aux utilisateurs le droit de faire appel des décisions auprès de l'IANA, le pouvoir reste concentré aux mains des RIR.

La section 2 décrit le mécanisme de distribution des adresses. Celles-ci sont allouées aux LIR par les RIR, en larges blocs, puis affectées aux clients finaux par les LIR, en blocs plus petits. Normalement, l'affectation, contrairement à l'allocation, est réversible : le client final n'est pas propriétaire de ses adresses (on parle d'adresses PA pour Provider-Aggregatable, les autres sont PI, Provider-Independent, et attribuées directement par le RIR).

Pour satisfaire les buts énumérés dans la section 1, le RFC énonce des règles comme le principe que les adresses soient prêtées et pas données. Il comporte aussi des micro-règles comme de spécifier que les clients finaux ne devraient pas avoir d'adresses IP statiques !

La section 2.2 est consacrée à l'enregistrement et insiste sur l'importance que les informations soient correctes et à jour. Comme pour les registres de noms de domaine, il s'agit d'un vœu pieux et les serveurs whois des RIR distribuent quotidiennement des informations dépassées, voire fausses.

La section 3 est plus spécifiquement consacrée à l'affectation, c'est à dire à la distribution des adresses des LIR vers les clients finaux. C'est elle qui explique les règles devant lesquelles va plancher l'utilisateur, comme « 25 % des adresses affectées doivent être pour un usage immédiat » ou comme la nécessité de fournir un plan d'adressage (section 3.2) comme le fameux ripe-141 (aujourd'hui 381 mais souvent connu sous son ancien numéro).

Notez que, contrairement à ce que prétend la section 4.4, où le RIR s'autorise à enquêter sur l'utilisation effective des adresses, il n'y a jamais de contrôle et bien des organisations ont obtenu des quantités importantes d'adresses IP avec des plans mirobolants d'accès Internet par ADSL pas cher avec des dizaines de milliers d'abonnés en quelques semaines. Les règles des RIR favorisent donc ceux qui savent bluffer avec talent.

Le RFC 2050 n'a jamais été mis à jour. Pour voir les politiques d'allocation actuelles des RIR, il faut consulter leurs sites Web :

On peut comparer facilement les différentes politiques en http://www.nro.net/documents/nro46.html.

Lors de forums de discussion sur la gouvernance de l'Internet, relativement peu de discussions ont eu lieu sur l'allocation d'adresses IP, si on compare avec la gestion de la racine du DNS. Parce que les RIR, plus anciens et beaucoup plus efficaces, ont une meilleure légitimité que l'ICANN ? Parce que les RIR ont réussi à convaincre les participants à ces forums de regarder ailleurs ? Parce que la question est trop technique pour les politiciens et les avocats qui remplissent ces forums ? En tout cas, aujourd'hui où l'épuisement rapide des adresses IPv4 pose de manière encore plus aigüe l'allocation des adresses restantes, on peut s'inquiéter de ce qui va se produire dans les prochaines années. Certains proposent déjà ouvertement un marché des adresses IP, permettant aux pays du Nord, qui ont obtenu le plus d'adresses au début de l'Internet, de les vendre. C'est officiellement interdit par les RIR, mais cette interdiction tiendra t-elle face aux forces du marché ?


Téléchargez le RFC 2050


L'article seul

Calculs calendaires en Haskell

Première rédaction de cet article le 7 février 2008
Dernière mise à jour le 13 février 2008


Les auteurs de l'ouvrage de référence sur les calendriers, Calendrical Calculations recommandent à ceux qui veulent vraiment comprendre les calculs calendaires de les programmer eux-mêmes. Et ils ajoutent qu'il est préférable de ne pas regarder le code source qu'ils fournissent, pour suivre réellement l'algorithme. C'est ce que j'ai fait ici.

Calendrical Calculations décrit les algorithmes en langage mathématique, joliment mis en page, et qui se prête bien à une implémentation dans un langage fonctionnel. Les auteurs avaient choisi Common Lisp, j'ai refait une petite partie de leur travail (uniquement les calendriers arithmétiques, les astronomiques sont bien plus complexes) en Haskell. La plupart des formules mathématiques du livre se traduisent directement en Haskell, ce qui facilite leur vérification. Par exemple, la définition d'une année bissextile dans le calendrier grégorien se dit simplement :


gregorianLeapYear y =
   (y `mod` 4) == 0 &&
               ((y `mod` 100) /= 0 || y `mod` 400 == 0)

ce qui est, à quelques détails de syntaxe près, la définition donnée dans le livre.

Haskell dispose de grands entiers, Integer, dépassant les limites des entiers de la machine (Int en Haskell), ce qui est pratique pour certains calculs (les calculs astronomiques dépassent facilement les capacités d'une machine de 32 bits). On définit donc :

type Fixed = Integer

Les structures de données (par exemple, une date est composée d'une année, d'un mois et d'un jour) se fait avec les constructeurs de tuples de Haskell. Par exemple, une date du compte long maya se définit avec :

data MayanLongCount = MayanLongCountData {baktun::Fixed, katun::Fixed, 
                                          tun::Fixed, uinal::Fixed, kin::Fixed}
                    deriving (Eq, Show)

qui se lit ainsi : une date est composée d'un baktun, d'un katun, d'un tun, d'un uinal, et d'un kin. Tous sont de type Fixed. Ce type MayanLongCount dérive des classes de type Eq et Show ce qui lui assure automatiquement une fonction d'égalité (utile pour les tests automatiques) et un affichage sommaire, notamment dans l'interpréteur. Si on ne veut pas de cet affichage par défaut, on omet Show et on crée sa propre instance. Ici, pour le calendrier grégorien, on choisit l'affichage à la syntaxe ISO 8601 (le code présenté ici est une version simplifiée ; ISO 8601 imposant une taille fixe aux champs comme le mois, qui doit tenir sur deux caractères, le code réel - voir le lien à la fin pour le télécharger - est plus complexe) :

data Gregorian = GregorianData {gregorian'year::Fixed, gregorian'month::Fixed,
                                             gregorian'day::Fixed} deriving (Eq)

-- We do not derive Show because ours is better (ISO 8601 look)
instance Show Gregorian where
    show = \g -> show (gregorian'year g) ++ "-" ++
           show (gregorian'month g) ++ "-" ++
           show (gregorian'day g) 

L'utilisation de la construction let qui permet de définir des variables, nous autorise à coller d'encore plus près aux définitions du livre. Ainsi, la fonction du calendrier révolutionnaire français modifié, modifiedFrenchRevFromFixed est presque entièrement composée de let, le corps de la fonction appelant juste un constructeur (la dernière ligne) :


modifiedFrenchRevFromFixed f =
    let approx = floor (fromIntegral (f - frenchRevEpoch + 2) / 
                                         (1460969 / 4000)) + 1 in
    let year = if f < fixedFromModifiedFrenchRev 
                          (FrenchRevolutionaryData approx 1 1) then
                   approx - 1
               else
                   approx 
         in
    let month = floor (fromIntegral (f - 
                          fixedFromModifiedFrenchRev  
                                 (FrenchRevolutionaryData year 1 1)) / 30) + 1 in
    let day = f - fixedFromModifiedFrenchRev 
                         (FrenchRevolutionaryData year month 1) + 1 in
    FrenchRevolutionaryData year month day

(floor est la fonction pré-définie en Haskell pour calculer une partie entière.)

L'un des points sur lequel Haskell est plus contraignant que Common Lisp est la différence de type entre entiers et réels, qui nous oblige à des conversions explicites avec la fonction pré-définie fromIntegral.

Testons maintenant ces fonctions avec l'environnement interactif ghci. Mettons qu'on veuille traduire le 7 novembre 1917 du calendrier grégorien en « date fixe » :

 % ghci Gregorian 
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.6.1, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base ... linking ... done.
Ok, modules loaded: Calendar.Global, Calendar.Gregorian.
Prelude Calendar.Gregorian>    fixedFromGregorian (GregorianData 1917 11 7)
700115

On charge le module correspondant au calendrier julien et on convertit la date ci-dessus vers ce calendrier :

Prelude Calendar.Gregorian> :load Julian
Ok, modules loaded: Calendar.Global, Calendar.Gregorian, Calendar.Julian.
Prelude Calendar.Julian> julianFromFixed 700115
1917-10-25

Donc, le 7 novembre 1917 est le 25 octobre et voilà pourquoi la révolution d'Octobre a eu lieu en novembre... (La Russie tsariste n'avait pas adopté le calendrier grégorien.)

Le fait que Haskell soit un langage statiquement typé (mais où la déclaration de types est facultative grâce à l'inférence) protège contre les mauvaises utilisations de ces fonctions. Si j'essayais la fonction mayanLongCountFromFixed, qui prend normalement un Fixed en paramètre, sur une chaîne de caractères, Haskell le refuserait :


*Calendar.Mayan> mayanLongCountFromFixed "3 may 1998"

<interactive>:1:24:
    Couldn't match expected type `Fixed' against inferred type `[Char]'

On peut demander à ghci le type qu'il a inféré :

*Calendar.Mayan> :t mayanLongCountFromFixed  
mayanLongCountFromFixed :: Fixed -> MayanLongCount

On le voit dans les exemples précédents, la faute de frappe est vite arrivée et les erreurs sont fréquentes dans les logiciels de calcul calendaires. D'où la nécessité de disposer de jeux de tests. J'en ai fait deux sortes, des tests avec des données connues et des tests aléatoires. Les tests avec des données connues reposent sur un système d'assertions et la bibliothèque HUnit. Des exemples d'assertions sont :

testsIslamic = TestList [
                  TestCase (assertBool "Today"
                                       (fixedFromIslamic (IslamicData 
                                                            1429 1 21) == 733071)),
                  TestCase (assertBool "Go to Medina" 
                                       (islamicFromFixed islamicEpoch ==
                                        IslamicData 1 1 1)),
                  TestCase (assertBool "One day offset"
                                       (fixedFromIslamic (IslamicData 1613 11 26) -
                                       fixedFromIslamic (IslamicData 1613 11 25) == 1)),
                  TestCase (assertBool "One day offset over a month"
                                       (fixedFromIslamic (IslamicData 2453 8 1) -
                                       fixedFromIslamic (IslamicData 2453 7 30) == 1)),
                  TestCase (assertBool "One day offset over a year" -- 4532 is leap year
                                       (fixedFromIslamic (IslamicData 4533 1 1) -
                                       fixedFromIslamic (IslamicData 4532 12 30) == 1)),
                  TestCase (assertBool "Non leap year 1429"
                                       (fixedFromIslamic (IslamicData 1430 1 1) -
                                       fixedFromIslamic (IslamicData 1429 12 29) == 1))
                 ]

(Le point de départ du calendrier musulman, l'epoch, est le départ de Mahomet pour Médine.) L'une des difficultés des tests à assertion est qu'il faut trouver des données fiables. On l'a vu, s'il existe plein de logiciels de calculs calendaires, beaucoup contiennent des bogues et il pourrait être imprudent de bâtir ses tests sur eux. J'ai surtout utilisé les tables données dans Calendrical calculations, annexe C, ce qui est insuffisant, rien ne dit que ces tables n'ont pas elles-mêmes des erreurs.

Un autre mécanisme de tests consiste à tester des propriétés des fonctions et non plus de données particulières. Pour vérifier ces propriétés, la bibliothèque Quickcheck va les vérifier sur un grand nombre de données aléatoires. Par exemple, une propriété évidente est la possibilité d'un aller-retour avec la « date fixe » :


prop_mayanLongCountRoundtrip = forAll generateFixed $ \f -> 
                        let m = mayanLongCountFromFixed f in
                        ((fixedFromMayanLongCount . mayanLongCountFromFixed) f == f &&
                          (mayanLongCountFromFixed . fixedFromMayanLongCount) m == m)

Par défaut, les données générées par Quickcheck sont trop proches de zéro pour nos besoins (les bogues ne se manifestent souvent que pour les valeurs éloignées de l'origine du calendrier). On crée donc un générateur à nous, generateFixed, défini avec les combinateurs de QuickCheck :


generateFixed = do 
  i <- frequency [ (5, choose(10000,1000000)),
                   (3, choose(-1000000,-10000)),
                   (2, choose(-1000,1000)) ]
  return i

Ce système a ses propres faiblesses puisque les différentes fonctions dépendent les unes des autres, empêchant ainsi de détecter certaines erreurs (le résultat sera cohérent même si la fonction est fausse).

Il vaut donc mieux ajouter d'autres propriétés. Une que j'ai trouvé utile est de vérifier que le jour suivant a incrémenté le jour ou le mois (et dans ce cas que le jour est le premier du mois). Pour le calendrier grégorien, cela s'écrit :


prop_gregorianNextDay = forAll generateFixed $ \f -> 
                        let nextFixed = f + 1 in
                        let gday = gregorianFromFixed f in
                        let nextGday = gregorianFromFixed nextFixed in
                        (
                         (  -- Same month
                           (gregorian'year gday == gregorian'year nextGday) &&
                           (gregorian'month gday == gregorian'month nextGday) &&
                           (gregorian'day gday + 1 == gregorian'day nextGday)
                         ) || (  -- Next month  
                           (gregorian'year gday == gregorian'year nextGday) &&
                           (gregorian'month gday +1 == gregorian'month nextGday) &&
                           (gregorian'day nextGday == 1)
                         ) || ( -- Next year
                           (gregorian'year gday + 1 == gregorian'year nextGday) &&
                           (gregorian'month nextGday == 1) &&
                           (gregorian'day nextGday == 1)
                         ))

Une telle propriété attrape beaucoup d'erreurs. Ainsi, l'erreur du livre, enregistrée sous le numéro 331 dans l'erratum de l'édition 2000 de Calendrical Calculations, et qui affecte le calendrier républicain en faisant sauter certains premiers Vendémiaire (on passe directement du dernier jour complémentaire au deux Vendémiaire) est vite détectée et Quickcheck nous dit pour quelle valeur une propriété est fausse (ici, le 810373, donc le jour qui devrait être le premier Vendémiaire 428) :

...
French revolutionary roundtrip: OK, passed 1000 tests.
French revolutionary next day: Falsifiable, after 199 tests:
810373

Pour réaliser des fonctions de conversion aisément, on passe par un pivot. En effet, si on a N calendriers, écrire N-au-carré fonctions de conversion serait trop lourd. On écrit donc, pour chaque calendrier deux fonctions de et vers les dates fixes. Par exemple, pour le calendrier égyptien, on a :

fixedFromEgyptian :: Egyptian -> Fixed
egyptianFromFixed :: Fixed -> Egyptian

Désormais, pour convertir de n'importe quel calendrier vers n'importe quel autre, il suffit de passer par la date fixe, qui sert de pivot (ce qu'on avait déjà fait pour la conversion grégorien -> julien plus haut). Ainsi, si je veux convertir du calendrier musulman vers le républicain, j'écris :

islamic2republican = modifiedFrenchRevFromFixed . fixedFromIslamic

("." étant l'opérateur de composition de fonctions). Cette fonction peut s'utiliser ainsi :

*Calendar.Utils> Calendar.FrenchRevolutionary.prettyShow (islamic2republican (IslamicData 1288 1 6))
"7 Germinal 79"

(Le 7 germinal 79 étant la date du rétablissement du calendrier républicain par la Commune de Paris.)

Une fois muni de toutes les fonctions de conversion, on peut les utiliser dans un programme principal qui affichera la date du jour. Pour lire l'horloge, on utilisera la fonction System.Time.getClockTime qui, comme elle réalise une entrée/sortie, est dans la monade IO :


getToday = do
  (TOD seconds _) <- getClockTime
  return (floor(fromIntegral seconds/86400) + systemTimeEpoch)

main = do
  today <- getToday
  let todayIslamic = islamicFromFixed today
  let todayGregorian = gregorianFromFixed today
  ...
  putStrLn "Today is... "
  putStrLn ("Fixed: " ++ (show today))
  putStrLn ("Gregorian: " ++ Calendar.Gregorian.prettyShow todayGregorian ++ " (" ++ show todayGregorian ++ ")")
  ...

Le résultat est montré ici, pour aujourd'hui :

% ./today 
Today is... 
Fixed: 733079
Egyptian: EgyptianData {egyptian'year = 2756, egyptian'month = 10, egyptian'day = 22}
Gregorian: 7 February 2008 (2008-2-7)
Julian: 2008-1-25
Islamic: Muharram 29, 1429 (1429-1-29)
Mayan (long count): 12.19.15.1.1
French revolutionary: 19 Pluviôse 216

Le même opérateur de composition de fonctions peut nous permettre de construire d'innombrables fonctions utiles. Supposons qu'on veuille une fonction pour connaitre le jour suivant du calendrier grégorien. Il suffit de composer les fonctions « conversion en fixe », « incrémentation de 1 » et « conversion en grégorien » :

*Calendar.Gregorian> let nextDay = gregorianFromFixed . (+1) . fixedFromGregorian
*Calendar.Gregorian> :t nextDay
nextDay :: Gregorian -> Gregorian
*Calendar.Gregorian> nextDay (GregorianData 2008 2 11)
2008-2-12
*Calendar.Gregorian> nextDay (GregorianData 1999 12 31)
2000-1-1
*Calendar.Gregorian> nextDay (GregorianData 2000 2 28)
2000-2-29
*Calendar.Gregorian> nextDay (GregorianData 2000 2 29)
2000-3-1

Pour donner une petit idée de la mise en œuvre originale, voici la même fonction de conversion d'une « date fixe » vers le calendrier républicain en Common Lisp :


(defun modified-french-from-fixed (date)
  ;; TYPE fixed-date -> french-date
  ;; French Revolutionary date (year month day) of fixed
  ;; $date$.
  (let* ((approx   ; Approximate year (may be off by 1).
          (1+ (quotient (- date french-epoch -2)
                        1460969/4000)))
         (year (if (< date
                      (fixed-from-modified-french
                       (french-date approx 1 1)))
                   (1- approx)
                 approx))
         (month    ; Calculate the month by division.
          (1+ (quotient
               (- date (fixed-from-modified-french
                         (french-date year 1 1)))
               30)))
         (day      ; Calculate the day by subtraction.
          (1+ (- date
                 (fixed-from-modified-french
                  (french-date year month 1))))))
    (french-date year month day)))

Vous pouvez télécharger le code de ces programmes en Calendar.tar.gz.


L'article seul

Fiche de lecture : Calendrical calculations

Auteur(s) du livre : Edward Reingold, Nachum Dershowitz
Éditeur : Cambridge University Press
0-521-77752-6
Publié en 2000
Première rédaction de cet article le 6 février 2008


Le moindre téléphone portable, aujourd'hui, beaucoup de sites Web (réservations de train ou d'avion), de nombreux autres logiciels, disposent de fonctions de calendrier. Les nombreuses bogues constatées dans ces logiciels montrent que des questions aussi simples que « Le 1er mars 2000 est-il un mardi ou un mercredi ? » ne sont pas si triviales qu'elle en ont l'air. Ce livre est l'ouvrage de référence sur les calculs calendaires, pour de nombreux calendriers existants ou disparus, avec tous les détails nécessaires pour programmer soi-même ces calculs.

Les auteurs sont deux experts, Nachum Dershowitz a écrit de nombreux articles sur le sujet et Edward Reingold est le mainteneur du paquetage calendar d'Emacs. L'ampleur de l'érudition nécessaire pour couvrir, non seulement le traditionnel calendrier grégorien mais aussi les calendriers chinois, hindou, musulman, maya et bien d'autres, est impressionnante. Les amateurs d'anecdotes seront ravis. Par exemple, ils apprendront que les chinois incrémentent l'âge des enfants, non pas à leur anniversaire, mais au nouvel an. De plus, un enfant a un an à sa naissance. S'il nait la veille du nouvel an chinois, il aura deux ans au bout de quelques jours de vie. Autre exemple amusant, dans le calendrier maya Tzolkin, les numéros des jours et ceux des « mois » varient ensemble, mais sur des cycles de taille différentes. Ainsi, le 1 Imix est suivi du 2 Ik, lui-même suivi du 3 Akbal, etc jusqu'au 13 Ben (le cycle des jours a une longueur 13) qui est suivi du 1 Ix...

Mais la variété des calendriers permet aussi de philosopher sur le nombre de solutions possibles à un problème donné. Vivant sur la même Terre, avec les mêmes alternances de jour et de nuit et le même parcours du Soleil et de la Lune, les différentes civilisations ont développé des calendriers très différents. Il y en a deux grandes familles : les calendriers arithmétiques et les calendriers astronomiques. Les premiers obéissent à des règles arithmétiques simples (les seules opérations nécessaires pour les mettre en œuvre sont les quatre opérations de base, plus la fonction partie entière) et sont donc les plus simples à programmer. Mais, ignorant des cycles astronomiques et utilisant leurs propres cycles, incommensurables avec ceux des astres, il sont voués à un décalage grandissant avec le temps. C'est ainsi que notre calendrier grégorien, archétype des calendriers arithmétiques, a remplacé le calendrier julien, devenu trop décalé. Et il devra à son tour être réformé ou remplacé.

Les européens ne sont pas les seuls à avoir conçu un calendrier arithmétiques. Les Mayas ou les musulmans l'ont également fait. Mais d'autres peuples ont choisi une voie différente, notamment les chinois avec un calendrier astronomique, c'est-à-dire où le passage d'une période à une autre (par exemple d'un mois au suivant) dépend d'un événement astronomique (la nouvelle Lune dans le cas chinois). Ainsi, le calendrier est toujours synchronisé avec les astres. En revanche, si on veut calculer des dates futures, pour lesquelles il n'est pas encore possible de faire des observations astronomiques, les calculs sont nettement plus compliqués (rien n'est simple en astronomie, même la durée du jour diminue avec le temps). (Les hindous ont également un calendrier astronomique.)

Il existe aussi des calendriers qui ont emprunté aux deux systèmes. Par exemple, le calendrier civil musulman est arithmétique, mais les dates des événements importants comme le début du Ramadan dépendent de phénomènes astronomiques. Les chrétiens ont un système similaire pour déterminer Pâques (mais pas Noël, qui survient à date fixe). De même, le calendrier révolutionnaire français est astronomique : la méthode pour déterminer les années bissextiles ne dépend pas d'un algorithme mais d'observations. On ne peut donc pas prévoir facilement si une année future sera bissextile ou pas. Une réforme tardive de ce calendrier introduisait un mécanisme algorithmique et le transformait donc en calendrier arithmétique (mais elle n'a pas eu le temps d'être déployée avant le coup d'État de Bonaparte).

Comme tous les bons geeks, les auteurs ont inventé leur propre calendrier, le « date fixe » (Rata Die), qui compte le nombre de jours depuis le début de l'ère commune. La préface nous apprend ainsi que le livre a été terminé le 730 120 en « date fixe ».

Les auteurs ne perdent pas de vue les implémentations pratiques. Leurs algorithmes sont décrits en langage mathématique, sous une forme qui permet une programmation assez directe dans un langage de programmation fonctionnel. C'est ce que j'ai fait pour une partie des calendriers, en Haskell. (La composition du livre, elle, a dû exiger une bonne compétence en LaTeX.) On notera que le livre est accompagné d'un CD d'une implémentation complète en Common Lisp (attention, elle n'est pas du tout sous une licence libre).

On notera que les erreurs dans la seconde édition, publiée en 2000, sont nombreuses et l'erratum, publié sur leur site, est un impressionnant document. (Une troisième édition a été publiée fin 2007 mais je ne l'ai pas lue, merci à Damien Wyart pour son information.)

Cet article a été terminé le 6 février 2008 du calendrier grégorien, le 733 078 en « date fixe », le 18 pluviôse an 216 de la Révolution française, le 28 Muharram 1429 du calendrier musulman, le 12.19.15.1.0 du long compte maya et le 78-24-12-30 du calendrier chinois.


L'article seul

Fiche de lecture : Unix network programming

Auteur(s) du livre : W. Richard Stevens
Éditeur : Prentice-Hall
0-13-490012-X
Publié en 1998
Première rédaction de cet article le 5 février 2008
Dernière mise à jour le 6 février 2008


Ce livre est la référence absolue pour la programmation réseau en C sur Unix. Trés détaillé, très concret, avec énormément de code source, il a formé beaucoup de programmeurs réseaux. (Il s'agit du volume 1, le volume 2 étant consacré à la communication entre processus.)

Hélas, il n'y aura plus de livre écrit par W. Richard Stevens, il est décédé en 1999. Mais ses épais ouvrages ont formé des milliers de programmeurs et d'administrateurs réseaux. La seconde édition d'Unix network programming, volume 1, ajoutait notamment la description détaillée de la programmation IPv6, Stevens étant un des auteurs de l'API (RFC 3493). (Le livre a été repris par deux autres auteurs, qui ont publié une troisième édition, que je n'ai pas lue, merci à Damien Wyart pour l'information.)

Unix network programming couvre en près de mille pages l'interface des prises, l'écriture de clients et de serveurs, l'utilisation intelligente d'UDP et de TCP, et d'innombrables services plus avancés comme l'utilisation des options IP. Rien à voir avec le cours de réseau universitaire classique, avec son obligatoire modèle en couches. Ici, tous les programmes ont été testés et le code source est distribué (voir adresse plus haut).

En vrai geek, Stevens a écrit son livre en troff, un art aujourd'hui bien perdu.

Sans doute la plupart des programmeurs n'ont pas besoin d'autant d'informations, il est même peut-être préférable qu'ils programment à niveau plus élevé. Mais celui ou celle qui veut approfondir tous les mystères de la programmation réseau aura toujours intérêt à se plonger dans ce livre.


L'article seul

L'ordinateur et l'éléphant

Première rédaction de cet article le 3 février 2008


Rapportée par ma fille de l'école, une jolie poésie de Jean Rousselot sur l'ordinateur et l'éléphant, animal réputé pour sa mémoire (ce qui lui a valu de devenir le logo de PostgreSQL).

On peut la trouver en ligne sur le site de l'école publique de Saint Paul de Varces. C'est rare, les poésies pour enfants où on parle d'ordinateur...


L'article seul

RFC 4818: RADIUS Delegated-IPv6-Prefix Attribute

Date de publication du RFC : Avril 2007
Auteur(s) du RFC : J. Salowey, R. Droms
Chemin des normes
Première rédaction de cet article le 3 février 2008


Une des grandes forces du protocole Radius est la possibilité d'ajouter de nouveaux attributs, par exemple pour spécifier des paramètres supplémentaires à une session. C'est ainsi que ce RFC normalise l'attribut qui permet de déléguer un préfixe IPv6 entier, pas une seule adresse.

Avec IPv4, l'utilisateur typique n'a qu'une adresse IP en tout et pour tout et l'attribut traditionnel de Radius (RFC 2865), Framed-IP-address, suffit largement. Mais avec IPv6, comme recommandé dans le RFC 6177, l'utilisateur, même simple particulier, peut avoir un préfixe (de longueur 48, disait le RFC 3177, même si tous les FAI n'en donnent pas autant, entre 48 et 64 pour le RFC 6177). Lorsqu'un utilisateur se connecte au NAS, il faut donc trouver un moyen pour le serveur Radius qu'interroge ce NAS de transmettre le préfixe et sa longueur.

Rien d'extraordinaire et ce RFC est très court : il définit (section 3) l'attribut Delegated-IPv6-Prefix qui contient le préfixe et sa longueur. Cet attribut apparait typiquement dans les réponses mais il peut aussi être présent dans la question, pour indiquer une préférence de l'utilisateur. Une fois reçu par le NAS, il peut être transmis à l'utilisateur, par exemple en DHCP (RFC 3633) puis être ensuite être diffusé sur le réseau local dudit utilisateur, par exemple avec les annonces RA du RFC 4862.

On note que cet attribut peut aussi être utilisé pour le concurrent de Radius, Diameter (RFC 6733), la section 5 expliquant comment.


Téléchargez le RFC 4818


L'article seul

RFC 5101: Specification of the IPFIX Protocol for the Exchange of IP Traffic Flow Information

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : B. Claise (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ipfix
Première rédaction de cet article le 1 février 2008


Le système IPFIX, successeur de Netflow est désormais normalisé. Des routeurs de différentes marques peuvent donc désormais envoyer des informations statistiques à des machines d'administration de différentes origines.

Un cahier des charges pour IPFIX avait été spécifié dans le RFC 3917. Le système lui-même est désormais normalisé, ce RFC prenant en charge le protocole d'autres RFC s'occupant du modèle d'informations ou bien de l'architecture des différents composants d'IPFIX. Une nouvelle série de RFC IPFIX est sortie en septembre 2013 donc ce RFC n'a plus qu'un intérêt historique, il faut désormais consulter le RFC 7011.

Notre RFC normalise donc le format des paquets (section 3). Comme avec d'autres protocoles, les paquets commencent par un numéro de version, 10 ici, IPFIX marquant sa descendance depuis Netflow, dont la dernière version était la 9. Le RFC décrit aussi l'encodage des données exportées par l'observateur IPFIX (section 6).

Enfin, notre RFC décrit le mécanisme de transport, au dessus d'UDP, le protocole traditionnel de Netflow, mais aussi de TCP ou bien du protocole recommandé, SCTP. Pour répondre au cahier des charges, qui insistait sur la sécurité, la section 10.4 décrit aussi l'utilisation de TLS.

IPFIX est déjà mis en œuvre dans plusieurs systèmes et l'annonce de l'IESG approuvant le RFC précise que deux tests d'interopérabilité ont eu lieu, avec cinq logiciels différents, et que tout marchait bien. Un exemple de mise en œuvre en logiciel libre est Maji. Toutefois, mi-2012, des années après la sortie du RFC, il semble que peu de routeurs soient capables de faire de l'IPFIX (v10). La plupart sont restés bloqués sur Netflow (v9).


Téléchargez le RFC 5101


L'article seul

RFC 5234: Augmented BNF for Syntax Specifications: ABNF

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : D. Crocker (Brandenburg InternetWorking), P. Overell (THUS plc.)
Chemin des normes
Première rédaction de cet article le 1 février 2008


Ce RFC fait partie des RFC ancillaires, qui ne spécifient pas directement un protocole IETF mais fournissent des outils pour les "vrais" RFC. En l'occurrence, il normalise le mini-language pour écrire des grammaires.

Beaucoup de RFC doivent spécifier un langage, en général assez simple (jamais de la taille d'un langage de programmation) mais néanmoins suffisamment important pour que les descriptions informelles du langage soient risquées. Depuis longtemps, on utilise en informatique des notations dérivées du langage BNF pour spécifier formellement un langage. Le problème est qu'il existe plusieurs dialectes de BNF (comme EBNF) et que les RFC ont besoin d'une référence stable. À une époque, chaque RFC définissait approximativement sa grammaire formelle et l'utilisait ensuite. ABNF est issue d'un effort de Dave Crocker de regroupement de la définition de la grammaire en un seul RFC, le RFC 2234 en 1997, devenu ensuite le RFC 4234 en 2006. Notre RFC succède au fameux RFC 4234 (avec très peu de changements, le principal étant le passage au statut de norme IETF à part entière, Full Standard) et qui décrit ABNF, le dialecte IETF de BNF. Classique sur beaucoup de points, ce dialecte a quand même quelques variations, issues d'une histoire très ancienne. Par exemple, le signe | pour le choix est remplacé par /.

Quelques outils sont disponibles pour aider les auteurs de grammaires (la page oublie de mentionner Dapar). Mais je trouve que c'est encore insuffisant. S'il existe deux vérificateurs (qui peuvent tester qu'une grammaire est cohérente), il n'existe guère de générateurs d'analyseurs syntaxiques. En revanche, à des fins de test, il existe au moins deux programmes, Eustathius et abnfgen, qui génèrent automatiquement des exemples à partir d'une grammaire. Vous trouverez de nombreux exemples de grammaires ABNF dans les sources d'Eustathius.

Notre RFC normalise non seulement le format des grammaires mais aussi une bibliothèque de productions prêtes à l'emploi comme HEXDIG pour les caractères utilisables pour écrire de l'hexadécimal ou ALPHA pour les lettres de l'alphabet latin. Baptisée Core, cette bibliothèque est décrite dans l'appendice B.

À titre d'exemple, voici la spécification de SPF (décrit dans le RFC 4408) en ABNF :


   record           = version terms *SP
   version          = "v=spf1"

   terms            = *( 1*SP ( directive / modifier ) )

   directive        = [ qualifier ] mechanism
   qualifier        = "+" / "-" / "?" / "~"
   mechanism        = ( all / include
                      / A / MX / PTR / IP4 / IP6 / exists )

   all              = "all"
   include          = "include"  ":" domain-spec
   A                = "a"      [ ":" domain-spec ] [ dual-cidr-length ]
   MX               = "mx"     [ ":" domain-spec ] [ dual-cidr-length ]
   PTR              = "ptr"    [ ":" domain-spec ]
   IP4              = "ip4"      ":" ip4-network   [ ip4-cidr-length ]
   IP6              = "ip6"      ":" ip6-network   [ ip6-cidr-length ]
   exists           = "exists"   ":" domain-spec

   modifier         = redirect / explanation / unknown-modifier
   redirect         = "redirect" "=" domain-spec
   explanation      = "exp" "=" domain-spec
   unknown-modifier = name "=" macro-string

   ip4-cidr-length  = "/" 1*DIGIT
   ip6-cidr-length  = "/" 1*DIGIT
   dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]

   ip4-network      = qnum "." qnum "." qnum "." qnum
   qnum             = DIGIT                 ; 0-9
                      / %x31-39 DIGIT       ; 10-99
                      / "1" 2DIGIT          ; 100-199
                      / "2" %x30-34 DIGIT   ; 200-249
                      / "25" %x30-35        ; 250-255
             ; conventional dotted quad notation.  e.g., 192.0.2.0
   ip6-network      = <as per [RFC 3513], section 2.2>
             ; e.g., 2001:DB8::CD30

   domain-spec      = macro-string domain-end
   domain-end       = ( "." toplabel [ "." ] ) / macro-expand
   toplabel         = ( *alphanum ALPHA *alphanum ) /
                      ( 1*alphanum "-" *( alphanum / "-" ) alphanum )
                      ; LDH rule plus additional TLD restrictions
                      ; (see [RFC3696], Section 2)

   alphanum         = ALPHA / DIGIT

   explain-string   = *( macro-string / SP )

   macro-string     = *( macro-expand / macro-literal )
   macro-expand     = ( "%{" macro-letter transformers *delimiter "}" )
                      / "%%" / "%_" / "%-"
   macro-literal    = %x21-24 / %x26-7E
                      ; visible characters except "%"
   macro-letter     = "s" / "l" / "o" / "d" / "i" / "p" / "h" /
                      "c" / "r" / "t"
   transformers     = *DIGIT [ "r" ]
   delimiter        = "." / "-" / "+" / "," / "/" / "_" / "="

   name             = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )

   header-field     = "Received-SPF:" [CFWS] result FWS [comment FWS]
                      [ key-value-list ] CRLF

   result           = "Pass" / "Fail" / "SoftFail" / "Neutral" /
                      "None" / "TempError" / "PermError"

   key-value-list   = key-value-pair *( ";" [CFWS] key-value-pair )
                      [";"]

   key-value-pair   = key [CFWS] "=" ( dot-atom / quoted-string )

   key              = "client-ip" / "envelope-from" / "helo" /
                      "problem" / "receiver" / "identity" /
                       mechanism / "x-" name / name

   identity         = "mailfrom"   ; for the "MAIL FROM" identity
                      / "helo"     ; for the "HELO" identity
                      / name       ; other identities

   dot-atom         = <unquoted word as per [RFC2822]>
   quoted-string    = <quoted string as per [RFC2822]>
   comment          = <comment string as per [RFC2822]>
   CFWS             = <comment or folding white space as per [RFC2822]>
   FWS              = <folding white space as per [RFC2822]>
   CRLF             = <standard end-of-line token as per [RFC2822]>

On notera qu'ABNF ne spécifie pas la représentation sous forme de bits, mais une structure abstraite. Ce point, qui n'était pas clair dans les premières versions de la norme, et qui est souvent oublié par les utilisateurs d'ABNF, est décrit dans la section 2.4. ABNF spécifie des caractères, pas des octets, et la production :

comment-start = %3b

décrit bien le caractère point-virgule, pas forcément qu'il sera représenté par un octet de valeur numérique 3B (59 en décimal). Un encodage d'Unicode comme UTF-32, par exemple, le codera différemment

L'un des rares changements par rapport à son prédécesseur, le RFC 4234, aura été l'ajout d'un avertissement à la production LWSP (Linear White SPace, qui permet des espaces en début de ligne). Cette production, décrite dans l'appendice B, qui définit la bibliothèque standard de productions, a en effet été critiquée comme trop puissante : des auteurs de RFC l'ont utilisée sans comprendre ses conséquences. La définition comprend désormais l'avertissement suivant, qui a été négocié à la virgule près, avec acharnement : Use of this linear-white-space rule permits lines containing only white space that are no longer legal in mail headers and have caused interoperability problems in other contexts. Do not use when defining mail headers and use with caution in other contexts.

Notons qu'il n'y a pas grand'chose d'obligatoire à l'IETF. Aucune autorité ne peut dire aux auteurs de RFC « Désormais, vous êtes obligés d'utiliser ABNF ». Ceux qui le font le choisissent volontairement. La principale « dissidence » venait du RFC 2616, qui normalise HTTP, et qui utilisait un langage différent. Mais, depuis, les nouveaux RFC sur HTTP ont supprimé cette exception et utilisés l'ABNF standard.

Notons aussi que, bien que l'un des principaux avantages des langages formels soit la possibilité de vérification automatique, cette possibilité n'est pas utilisée systématiquement. C'est ainsi que certains RFC ont été publiés avec des bogues dans leur grammaire ABNF...

Le RFC 2234 était « Proposition de norme », le RFC 4234 était « Projet de norme ». Pour franchir l'étape supplémentaire menant au statut de « Norme » tout court, ABNF a dû subir tout un processus, malgré l'extrême ancienneté de cette norme. Notamment, ABNF a dû subir l'examen des programmes qui le mettent en œuvre, examen décrit en http://ietf.org/IESG/Implementations/RFC4234_implem.txt.


Téléchargez le RFC 5234


L'article seul

RFC 5102: Information Model for IP Flow Information Export

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : J. Quittek (NEC), S. Bryant, B. Claise, P. Aitken (Cisco), J. Meyer (PayPal)
Chemin des normes
Première rédaction de cet article le 1 février 2008


Le protocole IPFIX d'envoi par un routeur de résumés statistiques sur le trafic qu'il voit passer (RFC 5101, depuis remplacé par le RFC 7011), dépend d'un modèle de données, que décrivait notre RFC (depuis remplacé par le RFC 7012).

Le RFC 5101 qui normalisait le protocole IPFIX indique comment transporter les données de l'exporteur (typiquement un routeur) vers le récolteur (typiquement la machine d'administration du réseau) mais n'indique pas quelles données sont transportées. Notre RFC va jouer ce rôle, équivalent à celui du SMI du RFC 2578 pour SNMP.

Notre RFC est très long mais il est surtout composé d'une longue liste (section 5) des informations qui peuvent être transmises en IPFIX. En fait, il est assez simple. Un élément d'information a un nom (par exemple destinationTransportPort), une description (cet élément indique le port de destination du flot), un type (ici unsigned16, nombre entier sur 16 bits) et d'autres informations utiles comme un ElementID qui identifie de manière unique un élément d'information. Les types sont décrits en détail dans la section 3 mais sont très classiques (entiers, booléens, adresses MAC, etc). Plus originaux sont les sémantiques de la section 3.2, qui précisent, par exemple, que les éléments ayant une sémantique de totalCounter repartent de zéro lorsqu'ils ont atteint leur valeur maximale.

Voici un exemple complet, tiré de la section 5.10.4 :

octetTotalCount
   Description:
      The total number of octets in incoming packets for this Flow at
      the Observation Point since the Metering Process
      (re-)initialization for this Observation Point.  The number of
      octets include IP header(s) and IP payload.
   Abstract Data Type: unsigned64
   Data Type Semantics: totalCounter
   ElementId: 85
   Status: current
   Units: octets

Téléchargez le RFC 5102


L'article seul

RFC 5110: Overview of the Internet Multicast Routing Architecture

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : P. Savola (CSC / FUNET)
Pour information
Première rédaction de cet article le 1 février 2008


Ce RFC tente de mettre un peu d'ordre dans la galaxie des protocoles Internet liés au multicast en indiquant lesquels sont aujourd'hui encore en utilisation et lesquels doivent être considérés comme abandonnés.

Ce RFC ne mérite pas tout à fait son titre. Il ne présente pas une vision de haut niveau du multicast aujourd'hui, simplement une liste des protocoles qui concourent à la diffusion multicast, avec les recommandations associées. Ainsi, les techniques normalisées dans les RFC 3913 ou RFC 1584 sont officiellement indiquées comme abandonnées. Gérer un réseau multicast a en effet nécessité une grande souplesse, les techniques ayant souvent changé.

Comme IPv6, le multicast n'a jamais connu de déploiement significatif sur Internet (certains réseaux privés, en revanche, l'utilisent intensivement, par exemple pour la diffusion de chaînes de télévision). Il existe un grand contraste entre l'intérêt que suscite le multicast chez les experts, le nombre étonnant de RFC sur le sujet, son enseignement massif à l'Université, les analyses de consultant prévoyant son déploiement massif, et son peu d'utilisation dans le monde réel. Une des raisons est que le multicast est surtout adapté aux cas où un grand nombre de gens veulent le même contenu pile en même temps (cas des chaînes de télévision traditionnelles) et pas au cas où les demandes sont décalées dans le temps (cas de la vidéo à la demande), même si les demandes sont proches (cas de la distribution d'un nouveau gros logiciel, où BitTorrent domine).

Pour diffuser en multicast, il faut plusieurs familles de protocoles et la section 2 du RFC est découpée selon ces familles. Ainsi, la section 2.1 est consacrée à la distribution de l'état d'aiguillage (forwarding), c'est-à-dire les règles qui permettent à chaque routeur de savoir où envoyer un flot multicast donné. Le protocole dominant ici est PIM-SM (RFC 4601), l'ancêtre DVRMP ayant été largement abandonné.

La section 2.2, elle, se consacre aux protocoles qui permettent de distribuer l'information topologique, pour que les routeurs apprennent leurs liaisons (en raison des tunnels, la topologie multicast n'est pas forcément congruente à la topologie unicast). C'est aujourd'hui le domaine de BGP dont les extensions multi-protocoles (décrites dans le RFC 4760) permettent de distribuer l'information multicast, ou bien d'IGP comme OSPF (RFC 4915).

Il existe encore d'autres familles de protocoles pour les routeurs multicast, dans les sections suivantes. La section 2.6, elle, passe aux interactions avec les machines finales, comme les protocoles permettant à celles-ci de signaler leur désir de joindre un groupe multicast, pour recevoir les flots associés. Ces protocoles sont IGMP (RFC 3376) en IPv4 et MLD (RFC 3810) en IPv6.

La section 2.7, elle, parle en détail de la réduction de la diffusion sur le réseau local. Si un commutateur réseau reçoit un paquet multicast, il doit en théorie l'expédier sur tous ses ports, même si aucune machine finale n'y écoute le flot. Diverses techniques comme l'« espionnage » des messages IGMP (RFC 4541) permettent de réduire cette diffusion aux seuls ports menant à une machine intéressée.


Téléchargez le RFC 5110


L'article seul

RFC 2865: Remote Authentication Dial In User Service (RADIUS)

Date de publication du RFC : Juin 2000
Auteur(s) du RFC : C. Rigney, S. Willens, A. Rubens, W. Simpson
Chemin des normes
Première rédaction de cet article le 31 janvier 2008


Radius, normalisé dans ce RFC, est un protocole très simple d'AAA, conçu pour des serveurs d'accès à l'Internet (NAS, Network Access Server ou Access Point, ce dernier terme étant davantage utilisé dans le monde du sans-fil) qui sous-traitent l'authentification des utilisateurs à un serveur Radius. La machine qui accède à Internet n'a donc pas besoin de Radius, ce protocole ne sert qu'entre le NAS et le serveur d'authentification.

Radius fait partie de la famille des protocoles simples, certains disent simplistes, qui font peu de choses mais les font bien et, comme résultat, sont indélogeables. Normalisé d'abord dans le RFC 2058, puis le RFC 2138, il est désormais défini par notre RFC. Son principe est simple : lorsqu'une machine cliente se connecte au serveur d'accès (le NAS), ce dernier envoie un paquet UDP au serveur d'authentification, paquet qui contient l'information sur le client (et, dans le cas le plus simple, le mot de passe que celui-ci a indiqué). Le serveur d'accès est donc client Radius. Le serveur Radius répond par une acceptation ou un refus, accompagné, si c'est une acceptation, par la valeur de certaines options de configuration (par exemple une adresse IP).

La section 2 du RFC décrit plus en détail ce modèle. Le client Radius doit mettre dans la requête toute l'information nécessaire (nom ou NAI de l'utilisateur, numéro de port du NAS, etc). Il est également responsable, comme pour le DNS, de la réémission des demandes, s'il n'y a pas de réponse (UDP ne garantit en effet pas la délivrance des requêtes). Le RFC précise que le serveur ne doit accepter que les clients connus, configurés avec un secret partagé, il n'existe pas de serveur Radius public. Le serveur Radius authentifie ensuite l'utilisateur par les mécanismes de son choix (les bons serveurs Radius offrent d'innombrables techniques d'authentification).

La section 2.1 explique comment Radius peut être utilisé même si la requête ne contenait pas tous les éléments pour l'authentification, par exemple parce qu'on a choisi d'utiliser une authentification défi/réponse. Radius permet de transmettre le défi au client.

La section 2.4 est d'explication : elle donne les raisons pour lesquelles UDP a été choisi comme protocole de transport, choix qui a beaucoup été critiqué.

La section 3 est consacré au format de paquet, la 4 décrivant en détail les différents types de paquet (notamment Acceptation et Rejet). Radius utilise les ports suivants (extraits d'un /etc/services) :

radius          1812/udp
radius-acct     1813/tcp        radacct

C'est également cette section qui décrit le secret que partagent le client et le serveur Radius, secret qui servira notamment à xorer le mot de passe de l'utilisateur (section 5.2) pour se protéger contre l'espionnage de la ligne.

La section 5 liste tous les attributs standard, mais Radius est extensible et permet d'en décrire d'autres comme les attributs spécifiquement Microsoft du RFC 2548 ou bien comme le préfixe IPv6 délégué du RFC 4818. Cette extensibilité est une des propriétés les plus importantes de Radius.

Un des attributs les plus répandus est User-Name (type 1), décrit dans la section 5.1. Sa valeur est le nom de l'utilisateur (par exemple p.dupont) ou bien son NAI (RFC 7542, par exemple stephane@gold.example.net). Si c'est un nom, il est stocké en UTF-8 (les précédentes versions de Radius n'acceptaient que l'ASCII).

L'attribut Service-Type (section 5.6), permet de demander un service particulier, par exemple que le NAS rappelle l'utilisateur pour lui épargner les frais de communication (à Internatif, j'utilisais ainsi, pour les tâches d'administration système effectuées à distance, la valeur Callback-Framed à l'époque où le téléphone était presque toujours facturé à la minuté).

Les attributs sont encodés en TLV.

La section 7 du RFC donne plusieurs exemples d'échanges Radius. Prenons un cas typique :

  • L'utilisateur arrive sur le NAS, qui lui demande nom (nemo) et mot de passe.
  • Le NAS, le client Radius, demande Access-Request, attributs User-Name = nemo, User-Password = <masqué par le secret partagé>, Nas-Port = 3 (pour le cas où le serveur veuille enregistrer cette information, ou même l'utiliser dans son processus de décision).
  • Le serveur Radius répond Access-Accept, avec les attributs Service-Type = Framed, Framed-Protocol = PPP (le PPP du RFC 1661), Framed-IP-address = 255.255.255.254 (une convention courante pour dire « prends une adresse IP dynamique dans ton pool »), Framed-MTU = 1500.
  • Le NAS commence alors la négociation PPP avec la machine de l'utilisateur.

Notre RFC 2865 a plusieurs compagnons, notamment le RFC 2866 qui spécifie la comptabilité (le troisième A, Accounting, du sigle AAA), et RFC 2869 le mécanisme d'extensions.

Radius a été très critiqué pour sa simplicité et un protocole concurrent, Diameter, a été développé et décrit dans le RFC 3588 (remplacé ensuite par le RFC 6733). Sur le créneau des serveurs d'accès à Internet, Diameter n'a eu aucun succès.

Il existe d'innombrables mises en œuvre de Radius, un protocole qu'on trouve aujourd'hui dans tous les NAS. Radius avait à l'origine été conçu par Livingston (et mes débuts personnels avec Radius, au CNAM, étaient avec un Livingston Portmaster, avant de passer, chez Internatif, à l'US Robotics Total Control) mais est aujourd'hui une norme très répandue. Livingston a depuis été rachetée par Lucent.

Côté serveur Radius, le serveur d'origine, fait par Livingston, est toujours d'actualité (paquetage radiusd-livingston dans Debian), mais le plus courant est désormais Free Radius, basé sur la version de Cistron. Free Radius est l'Apache des serveurs Radius : très riche en possibilités, pratiquement tout est configurable.

(Un autre serveur basé sur celui de Cistron, xtradius ne semble plus maintenu, il est par exemple très bogué sur machines 64bits.)

Côté client (NAS), voici par exemple comment se configure un Cisco en client Radius du serveur 192.168.8.8 :

radius-server host 192.168.8.8 auth-port 1812 key THESHAREDSECRET aaa group ...

Si le NAS est une machine Unix, elle peut utiliser le greffon Radius livré avec le démon pppd, qui permet à pppd d'authentifier avec Radius.

Pour déboguer le serveur, il vaut mieux utiliser d'abord un client en ligne de commande, comme le radclient qu'on trouve avec Free Radius. On peut aussi facilement construire un client à soi en Python avec pyrad (le code d'exemple marche du premier coup). Restons avec radclient :

% echo "User-Name = bortzmeyer\nUser-Password = foobar" | radclient MYRADIUSSERVER auth toto 
17:31:54.679926 IP 10.1.82.1.32772 > 10.1.82.2.1812: RADIUS, Access Request (1), id: 0xcd length: 32

et le radius.log du serveur (si on veut déboguer Free Radius, il est recommandé de suivre les conseils en http://wiki.freeradius.org/index.php/FAQ#Debugging_it_yourself) :

Fri Jan 25 17:32:21 2008 : Error: Ignoring request from unknown client 10.1.82.1:32772

En effet, rappelons que Radius impose que le serveur ne communique qu'avec des clients qui ont été enregistrés. Avec Free Radius, cela se fait dans le clients.conf :

client MYNAS.generic-nic.net {
    secret = toto
    shortname = MYNAS
}

Et, cette fois, ça marche :

% echo "User-Name = bortzmeyer\nUser-Password = foobar" | radclient MYRADIUSSERVER auth toto
Received response ID 233, code 2, length = 44
        Service-Type = Framed-User
        Framed-Protocol = PPP
        Framed-IP-Address = 172.16.3.33
        Framed-IP-Netmask = 255.255.255.0

tcpdump a vu :

16:13:09.963566 IP 10.1.82.1.32774 > 10.1.82.2.1812: RADIUS, Access Request (1), id: 0xec length: 50
16:13:09.963914 IP 10.1.82.2.1812 > 10.1.82.1.32774: RADIUS, Access Accept (2), id: 0xec length: 44

Si on l'avait lancé avec l'option -vvv pour qu'il soit plus bavard :

16:13:25.477228 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 78) 10.1.82.1.32774 > 10.1.82.2.1812: [udp sum ok] RADIUS, length: 50
        Access Request (1), id: 0xee, Authenticator: eb33a21f4d8fc351898adc0b47b90c87
          Username Attribute (1), length: 12, Value: bortzmeyer
            0x0000:  626f 7274 7a6d 6579 6572
          Password Attribute (2), length: 18, Value: 
            0x0000:  727b 82e4 ccab a138 a5cb 368e 8829 1555
16:13:25.477607 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 72) 10.1.82.2.1812 > 10.1.82.1.32774: [bad udp cksum f482!] RADIUS, length: 44
        Access Accept (2), id: 0xee, Authenticator: 779e320bca7cda5972412ee6b53b10dc
          Service Type Attribute (6), length: 6, Value: Framed
            0x0000:  0000 0002
          Framed Protocol Attribute (7), length: 6, Value: PPP
            0x0000:  0000 0001
          Framed IP Address Attribute (8), length: 6, Value: 172.16.3.33
            0x0000:  ac10 0321
          Framed IP Network Attribute (9), length: 6, Value: 255.255.255.0
            0x0000:  ffff ff00

On peut aussi tester la santé d'un serveur Radius (attention, tous ne le mettent pas en œuvre, sur Free Radius, il faut un status_server = yes dans la configuration) avec les requêtes de type Status-Server :

% echo "Message-Authenticator = 42" | radclient MYRADIUSSERVER status toto
Received response ID 131, code 2, length = 49
        Reply-Message = "FreeRADIUS up 0 days, 00:02"

Si on souhaite ajouter des attributs à soi sur un serveur Radius Unix, cela se fait en général en éditant le fichier dictionary, qui décrit les attributs. Imaginons un attribut indiquant la témpérature, je mets dans le /etc/freeradius/dictionary :

ATTRIBUTE      Temperature       3000    integer

Un exemple de réalisation d'un service Radius est décrit en http://lehmann.free.fr/Contributions/FreeRADIUS/


Téléchargez le RFC 2865


L'article seul

VMS vit encore

Première rédaction de cet article le 30 janvier 2008


J'ai été ingénieur système sur VMS de 1986 à 1988. C'était même mon premier vrai métier dans l'informatique. Signe de l'extrême permanence des choses en informatique, VMS est toujours là et des machines VMS consomment du courant et produisent des résultats aujourd'hui.

Difficile de se débarasser d'un système d'exploitation à succès, même lorsque la boîte qui l'a créé a été rachetée deux fois (Digital a été acheté par Compaq puis par HP). VMS a eu trente ans en novembre 2007 et marche toujours. Le nombre d'applications sur VMS est tel, surtout dans le secteur Banque & Assurances qu'on ne peut pas envisager d'arrêter, même si VMS n'a plus le vent en poupe. Des passionnés ont même développé une version libre.

On peut même aujourd'hui avoir un compte gratuit sur une machine VMS, sur la ferme de compilation Test Drive. Je suis un peu rouillé, j'avais même oublié qu'il fallait faire précéder les commandes par RUN mais je me souvenais encore de la syntaxe baroque des noms de répertoires. Voici comment j'ai compilé et exécuté mon programme (je tape les noms complets des commandes mais bien sûr l'interpréteur permet de les abréger, tant qu'il n'y a pas d'ambiguïté) :

Last interactive login on Tuesday, 29-JAN-2008 17:10:34.11
Last non-interactive login on Tuesday, 29-JAN-2008 09:49:04.69
Your default directory is USER1:[BORTZ]
You also have a directory on an ODS-5 device. USER5:[bortz]
$ 
$ set default [.tmp]
$ directory

Directory USER1:[BORTZ.TMP]

ECHOPING-5_0_1.DIR;1                    ECHOPING-5_0_1.TAR;1
IP-HEADER-SET.C;1   MAKEFILE.;1        

Total of 4 files.
$ cc IP-HEADER-SET
$ link IP-HEADER-SET
$ run IP-HEADER-SET
Testing of the abilities to set bits in the IP header
The system is OpenVMS 0, the machine is HP_rx2600__(1.40GHz/1.5MB)
...

On voit le numéro de version derrière chaque nom de fichier (précédé d'un point-virgule). On note aussi que l'extension du nom de fichier peut être omise (link cherche alors un .obj).


L'article seul

Le groupe de travail BEHAVE de l'IETF

Première rédaction de cet article le 30 janvier 2008


L'IETF, comme les autres acteurs de l'Internet, se pose depuis longtemps la question de l'attitude à adopter face au déploiement massif du NAT. Cette technique, qui permet de ne pas donner aux machines situées derrière le routeur NAT une « vraie » connectivité Internet, est très répandue. Au fur et à mesure de l'épuisement des adresses IPv4, on voit de plus en plus de FAI qui connectent leurs clients ainsi. À la maison, l'abonné moyen n'a, depuis longtemps, qu'une seule adresse IPv4 et donc pas beaucoup d'autres choix que le NAT (ou les relais applicatifs, qui posent des problèmes analogues). Or, le NAT brise le modèle de « connectivité de bout en bout » qui est à la base de l'Internet. Pour cette raison, et d'autres, il est très mal vu chez les concepteurs et implémenteurs de protocoles. Que doivent faire ceux-ci dans un monde où le NAT est si répandu ? C'est tout l'objet du groupe de travail BEHAVE.

En présence du NAT, les application strictement client/serveur comme le Web fonctionnent encore assez bien, lorsque le serveur n'est pas lui-même derrière un routeur NAT. Par contre, les applications pair-à-pair, où chacun doit pouvoir contacter chacun, ou bien les protocoles pour le multi-média comme SIP (RFC 3261), où l'appelé doit pouvoir envoyer son flot de données à l'appelant, sont très handicapés. Les programmes mettant en œuvre ces protocoles consacrent une grande partie de leur code à contourner les NAT. Divers bricolages sont parfois nécessaires pour que le monde extérieur puisse parler aux machines bloquées derrière le routeur NAT (par exemple le port fowarding comme documenté ici pour un routeur Linux). Bref, le NAT fait faire des économies aux opérateurs Internet (à qui il évite de déployer IPv6) mais coûte cher aux autres acteurs.

Aujourd'hui, le NAT est tellement largement déployé que, même si plus aucune installation n'était faite, l'Internet devrait vivre avec pendant des années. Alors, que doit faire un organisation de normalisation comme l'IETF ? Comme le NAT met en cause la connectivité de bout en bout, il est largement considéré à l'IETF comme un mal à éradiquer. Comme on ne pactise pas avec le mal, l'opinion dominante à l'IETF était qu'il ne fallait pas chercher à limiter les dégâts, à améliorer le NAT, puisqu'il ne méritait que d'être supprimé. Même la normalisation des moyens de contournement du NAT (rapidement apparus, vue la créativité des développeurs réseaux face aux obstacles) a été pendant longtemps tenue en suspicion. En novembre 2002, l'IAB, dans le RFC 3424 appelait ces moyens de contournement « UNSAF » (UNilateral Self-Address Fixing), laissant entendre que le danger venait d'eux et pas du NAT, et imposant dans sa section 4 une série de questions auxquelles devaient répondre tous les protocoles de contournement. Le but était d'éviter que le remède soit pire que le mal, que le NAT, mais cela revenait à jeter une suspicion contre ceux qui cherchaient à trouver des solutions partielles, comme STUN.

Finalement, c'est en septembre 2004 qu'a été créé le groupe de travail BEHAVE, avec une charte très prudente qui lui intimait de « ne pas encourager le déploiement de NAT » comme si le développement de la médecine encourageait les maladies. On touche là à un problème presque philosophique : tenter de soulager la misère du monde détourne t-il de la réalisation de changements de fond ?

BEHAVE a travaillé sur les points suivants :

  • Un travail de documentation et de classification des NAT (une partie du RFC 4787 et l'Internet-Draft draft-ietf-behave-p2p-state, qui est notament axé sur le pair-à-pair).
  • Un protocole de base, STUN (RFC 5389) servant aussi bien à la découverte du comportement d'un routeur NAT (Internet-Draft draft-ietf-behave-nat-behavior-discovery) qu'à la traversée des NAT par les applications, par la technique du hole punching (la description de cette technique n'est pas faite par BEHAVE mais dans d'autres groupes de travail, plus orientés applications). Une extension de STUN, TURN (RFC 5766) normalise le relais de toute la session via un serveur extérieur, ce qui sera normalement le « dernier recours » pour communiquer, si les deux pairs sont coincés derrière des routeurs NAT peu coopératifs.
  • Une série de règles auxquelles devraient idéalement obéir les routeurs NAT, pour que les techniques ci-dessus arrivent encore à fonctionner (RFC 4787, RFC 5382, RFC 5508).

BEHAVE a terminé plusieurs RFC dont les RFC 4787 (UDP), RFC 5135 et RFC 5382 (TCP).

Le groupe de travail a été depuis réorienté pour travailler sur les NAT dans le contexte de la coexistence d'IPv4 et IPv6. Son expertise sur les NAT44 lui a permis de normaliser rapidement NAT64 (cf. RFC 6144).


L'article seul

mkisofs et plusieurs répertoires à mettre dans l'image ISO

Première rédaction de cet article le 26 janvier 2008


mkisofs est un excellent logiciel Unix pour créer des images ISO 9660 à partir d'un ou de plusieurs répertoires locaux, images qu'on peut ensuite graver sur CD ou DVD. Mais mkisofs a un défaut pénible : si on lui indique plusieurs répertoires sur la ligne de commande, il met tous les fichiers qu'ils contiennent ensemble, ce qui fait perdre le rangement, et ne marche pas si certains fichiers ont le même nom. Une solution possible est dans l'option -graft-points.

Cette option indique à mkisofs de garder la structure en répertoires. Avec cette option, mkisofs regarde le nom de chaque répertoire donné sur la ligne de commande, utilise le signe égal comme séparateur, et prend ce qui est à droite du séparateur comme nom local et ce qui est à gauche comme nom sur le futur CD. On écrit donc, si on veut sauvegarder /etc/X11 et /etc/network :

% mkisofs -r -o /var/tmp/image.iso -graft-points xorg/=/etc/X11 net/=/etc/network

Bien sûr, il n'est pas agréable de taper à la main de tels noms avec leur « = ». Mais on peut utiliser le shell pour les fabriquer. Nous nous servirons pour cela des techniques suivantes :

  • $(COMMANDE) qui insère le résultat la commande (comme le fait `COMMANDE` mais l'avantage de cette forme est de permettre d'emboîter plusieurs commandes).
  • eval qui permet de forcer l'évaluation d'une chaîne de caractères, ici contenant une variable.

Voici la commande qui crée les paramètres à la syntaxe qu'attend mkisofs (la liste des répertoires à sauvegarder est dans la variable DIRS qui vaut ici X11 network) :

% cd /etc
% for dir in $(eval ls -d $DIRS); do echo "$dir/=$(pwd)/$dir"; done
X11/=/etc/X11
network/=/etc/network

La commande complète, utilisant la boucle ci-dessus est (j'ai mis toutes les options que j'ajoute habituellement à mkisofs, mais seule -graft-points est importante ici) :

% cd /etc
% DIRS="X11 network"
% ISO=/var/tmp/backup.iso 
% mkisofs -A Backups -V Backups -publisher Stephane_Bortzmeyer \
	-p Stephane_Bortzmeyer -graft-points -iso-level=3 \
	-J -r -o $ISO \
	$(for dir in $(eval ls -d $DIRS); do echo "$dir/=$(pwd)/$dir"; done)

On utilise eval au lieu de simplement indiquer $DIRS car $DIRS peut contenir des caractères spéciaux du shell comme l'astérisque, qui sert de joker. eval est nécessaire pour qu'ils soient interprétés.


L'article seul

RFC 5113: Network Discovery and Selection Problem

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : J. Arkko (Ericsson), B. Aboba (Microsoft), J. Korhonen (TeliaSonera), F. Bari (AT&T/UBC
Pour information
Réalisé dans le cadre du groupe de travail IETF eap
Première rédaction de cet article le 26 janvier 2008


Ce RFC décrit l'ensemble du problème de la découverte et de la sélection d'un réseau particulier, lorsque plusieurs sont accessibles à la machine, ce qui est courant avec les équipements portables.

Un ordinateur portable, aujourd'hui se trouve fréquemment confronté au problème de trouver les réseaux disponibles et d'en choisir un. Placé dans une chambre d'hôtel, il est connecté par un câble Ethernet au réseau de l'hôtel, mais il reçoit aussi le signal de trois réseaux Wifi différents, certains de ces quatre réseaux n'étant pas forcément accessibles à l'utilisateur (pas d'autorisation) et les autres différant par leur prix, leur qualité et les services qu'ils offrent. Lequel choisir ? Notre RFC ne résout pas le problème mais l'analyse et y met un peu d'ordre.

La section 1 détaille de manière précise cette question. Par exemple, les protocoles actuels permettent de publier assez clairement les caractéristiques de la couche 2 du réseau d'accès (par exemple, en 802.11, si le réseau est ouvert ou pas) mais ne donnent pas d'information sur les couches supérieures. Peut-être que ce réseau ne me donne qu'une adresse IP privée et m'enferme derrière un coupe-feu très strict alors que cet autre réseau me donne un vrai accès Internet mais comment le savoir sans s'y connecter ?

La section 2 liste ensuite les problèmes précis, notamment :

  • Le problème de la découverte des réseaux accessibles, pas seulement de leur existence mais aussi de leurs capacités. Le RFC 3017 proposait un mécanisme de « carnet d'adresses », bien trop rigide pour la variété et le changement rapide des points d'accès qu'on rencontre aujourd'hui. En 802.11, où il existe des mécanismes standard pour détecter les points d'accès, le problème est néanmoins plus difficile qu'il n'y parait (cf. Fixing 802.11 Access Point Selection). Un logiciel comme kismet est très utile aujourd'hui lorsqu'on veut explorer les réseaux Wifi disponibles.
  • Le problème du choix de l'identificateur (NAI, cf. RFC 7542) à donner, si on peut en utiliser plusieurs. Si j'ai un NAI pour mon compte personnel (stephane@fai.example.net) et un mis à ma disposition par mon entreprise (bortzmeyer@boulot.com), lequel utiliser ?
  • Le problème du routage de la requête d'authentification vers le bon serveur d'AAA. Radius (RFC 2865) fournit typiquement très peu de possibilités dans ce domaine, les point d'accès au réseau doivent connaitre la correspondance entre un domaine (la partie du NAI à droite du @) et l'adresse IP du serveur Radius. Diameter (RFC 6733) offre d'avantages de possibilités mais il est peu déployé.
  • Le problème de la découverte des capacités du réseau (couche 3) accessible. Comme noté par le RFC 4084, les différents FAI n'offrent pas tous un accès complet à Internet. Des restrictions, comme par exemple le blocage du port SMTP sont fréquentes et il serait bon qu'on puisse les connaitre avant de choisir un réseau.

La section 3 définit des principes qui devraient être suivis par les mécanismes permettant de traiter ces problèmes. Par exemple, les engins portables ayant souvent une autonomie limitée, il faudrait éviter les longs dialogues, qui peuvent vider la batterie plus vite. La sécurité y fait l'objet d'une attention particulière, car la sélection d'un réseau est un bon endroit où attaquer, par exemple en essayant de convaincre une machine de se connecter au réseau le moins sécurisé...

Enfin, la conclusion, en section 4, affirme qu'il reste beaucoup de travail à faire dans ce domaine et fournit quelques pistes de recherche. L'annexe A décrit en détail les travaux déjà effectués à l'IETF, les RFC 4284, RFC 4066, etc, mais aussi à l'IEEE ou dans 3GPP.

Un exemple d'un logiciel qui met en œuvre une telle sélection de réseau est NetworkManager sur Unix, logiciel qui est composé de deux parties, un démon tournant sous root qui détecte les événements réseau (comme l'insertion ou le retrait d'une carte) et une application graphique qui assure l'interface utilisateur, les deux communiquant via dbus. NetworkManager permet à l'utilisateur de sélectionner facilement un réseau mais ne semble pas lui-même capable de faire des choix à part des cas très simples comme « Un réseau filaire est préférable à un réseau sans-fil ».


Téléchargez le RFC 5113


L'article seul

Le choix d'un langage de programmation

Première rédaction de cet article le 25 janvier 2008


Le choix d'un langage de programmation pour une tâche de développement logiciel est souvent un choix difficile et qui suscite des débats passionnés. Utiliserons-nous Java ? Perl ? Caml ? Lua ? Ces débats sont parfois qualifiés de « religieux » du fait de l'enthousiasme qu'y mettent leurs participants, et de la rapidité avec laquelle ils écrasent les alternatives (« Java est le standard de l'industrie » ou « Python est trop lent ») sans trop chercher à collecter des faits précis. Mais appeler ces débats « religieux » est en fait souvent un moyen de nier l'importance de ce choix et de se moquer sans risques de ceux qui cherchent à défendre leur choix. C'est une fuite bien commode alors que, comme tout choix technique, celui d'un langage de programmation peut être basé sur des faits, à condition de chercher ces faits, non seulement dans le langage lui-même, mais aussi dans tout son environnement, technique et social.

On pourrait vouloir un seul langage de programmation, qui éviterait la difficulté du choix (les discours sur tel langage qui serait « le standard de l'industrie » relèvent souvent de cette vision). Mais ce n'est pas le cas. Il y a donc un vrai choix et qualifier les débats sur ce choix de « religieux » est un moyen peu courageux de refuser la discussion. Par contre, il est exact qu'il faut un gros effort sur soi-même pour ne pas trop se laisser aveugler par la passion et pour étudier les faits. Cette passion est normale (heureusement que les programmeuses sont passionnées par la programmation) et elle est même raisonnable, dans la mesure où le choix de l'outil influe, non seulement sur la productivité (si le langage d'assemblage a presque disparu, ce n'est pas par hasard, c'est largement à cause de la plus faible productivité qu'il permet), mais également sur les modes de pensée. L'outil détermine le travail, même si les décideurs, ne comprenant pas les arguments techniques du choix d'un langage, continuent à prétendre qu'on peut réaliser n'importe quelle tâche, avec n'importe quel style, dans tous les langages. C'est factuellement exact mais cela ne mène pas loin. C'est comme dire que tous les moyens de transport se valent et qu'on peut traverser l'Amérique à pied. Oui, on peut. Comme on peut réécrire un SGBD en assembleur. Et alors ? Qui va le faire ?

Il y a donc bien des arguments techniques au choix d'un langage. Un langage où il faut gérer la mémoire soi-même (allocation et désallocation, éviter les pointeurs pendants) comme C est une source de bogues sans fin. Un langage où les variables sont automatiquement déclarées (comme les vieux Basic ou comme Perl ou PHP par défaut) permet des bogues très difficiles à détecter en cas de faute de frappe sur le nom d'une variable. Ces arguments sont très importants et doivent être pris en compte.

Mais certains professionnels des langages de programmation, emportés par leur goût pour ces analyses et ces discussions, oublient un autre aspect : le langage lui-même, tel que spécifié dans son manuel de référence, n'est qu'une partie du système avec lequel les programmeurs vont travailler. Il y a aussi la disponibilité de bibliothèques, l'existence de plusieurs implémentations de qualité (et, si on développe du logiciel libre, sous une licence acceptable), la taille de la communauté, qui conditionne la facilité à recruter, l'aide qu'on pourra trouver...

Parmi ces critères non strictement liés au langage, on trouve la disponibilité de bibliothèques toutes faites pour assurer des tâches courantes comme parler à un serveur LDAP ou bien calculer une somme de contrôle SHA. Un langage comme Ada avait beaucoup souffert du manque de telles bibliothèques. À l'inverse, Haskell en a trop sur chaque sujet, et aucune n'étant « standard » (il existe par exemple de nombreuses façons de traiter du XML en Haskell). Lua a de telles bibliothèques mais elles ne sont pas installées par défaut. À l'inverse, un langage comme Perl doit une partie de son succès à la CPAN, un immense ensemble de bibliothèques de qualité, documentées, cohérentes et facilement disponibles.

Parmi les critères plus sociaux, il y a par exemple la taille de la communauté, qui gouverne la facilité à trouver des programmeurs ou de l'aide. Encore que la taille puisse avoir des effets pervers comme le fait que les listes de diffusion d'un langage très populaire seront trop actives pour qu'on puisse s'en servir. Ou comme le fait qu'un langage « trop » populaire attirera des masses de programmeurs sans éclat (le paradoxe Python).

Je pense que, dans le choix d'un langage de programmation pour une tâche pratique (i.e. écrire un programme), on ne prend pas en compte que le langage lui-même mais aussi ce que j'appelle la « mentalité de la communauté ». Certes, cette mentalité n'est pas obligatoire (on peut choisir le langage et ignorer cette mentalité) mais elle influence fortement la documentation, les programme écrits par les autres (qu'on lira et dont on récupérera du code), l'aide qu'on peut avoir sur des listes de diffusion, etc.

Cette mentalité est la culture du langage. Si on ne travaille pas tout seul, si on est dans un environnement de logiciel libre, il faut bien en tenir compte. Par exemple, je conseille à tous les débutants en programmation de lire des programmes. Avec Perl, cela va les amener à lire du code illisible même si « on peut programmer proprement en Perl » (on peut, de même qu'on peut construire soi-même le bateau avec lequel on va traverser l'Atlantique).

Donc, en pratique, c'est surtout la « mentalité de la communauté » qui me tient à l'écart de PHP et Java, bien plus que les problèmes de ces langages. Par exemple, la culture PHP est de bricolage, sans réfléchir, sans faire attention aux problèmes de sécurité. Bien sûr qu'on peut écrire des programmes sûrs en PHP. Mais la culture du monde PHP ne s'y intéresse pas et donc ne le fait pas. Inversement, j'apprécie beaucoup la mentalité des Pythoniens ou des Haskelliens, qui peuvent discuter de questions avancées et répondre aux questions des débutants. Ah, et pour ajouter une note humoristique, la fameuse « hiérarchie des programmeurs » contient beaucoup d'éléments de vérité...

Pour finir sur une note concrète, un excellent article de l'équipe de Bugzilla illustre très bien une bonne méthode de choix de langage. Contrairement à beaucoup de cas de choix d'un langage, ici les auteurs savent de quoi ils parlent et connaissent bien tous les langages impliqués.


L'article seul

RFC 1738: Uniform Resource Locators (URL)

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 plan 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.

Le plan file: est désormais normalisé dans le RFC 8089.

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.


Téléchargez le RFC 1738


L'article seul

Exposé sur les systèmes d'exploitation à l'Institut Pasteur

Première rédaction de cet article le 23 janvier 2008


Dans le cadre du cours d'Informatique en Biologie de l'Institut Pasteur, j'ai fait un exposé de trois heures sur les systèmes d'exploitation.

Ce cours s'adresse à un public de biologistes non familiers avec la programmation ou avec le fonctionnement des systèmes d'exploitation. Contrairement à pas mal de cours sur les systèmes d'exploitation, il ne part pas des couches basses, du matériel par exemple, mais d'un petit programme Python très simple, et descend ensuite petit à petit vers des couches de plus en plus basses. Voici les transparents de cet exposé :

Un autre exposé de la même série a porté sur réseaux.


L'article seul

RFC 3315: Dynamic Host Configuration Protocol for IPv6 (DHCPv6)

Date de publication du RFC : Juillet 2003
Auteur(s) du RFC : R. Droms, J. Bound, B. Volz, T. Lemon, C. Perkins, M. Carney
Chemin des normes
Première rédaction de cet article le 23 janvier 2008
Dernière mise à jour le 6 novembre 2012


DHCP est certainement un des plus grands succès de l'IETF. Le DHCP d'IPv4 est mis en œuvre dans tous les systèmes et présent dans presque tous les réseaux locaux. Mais, dans le monde IPv6, l'arrivée de DHCP est plus récente, et il est concurrencé par un autre système, l'autoconfiguration sans état. DHCP pour IPv6, initialement normalisé dans ce RFC, l'est désormais dans le RFC 8415.

DHCP permet à une machine (qui n'est pas forcément un ordinateur) d'obtenir une adresse IP (ainsi que plusieurs autres informations de configuration) à partir d'un serveur DHCP du réseau local. C'est donc une configuration « avec état », qui nécessite un serveur, par opposition aux systèmes « sans état », comme l'autoconfiguration du RFC 4862 qui ne dépendent pas d'un serveur (cette autoconfiguration sans état peut être utilisée à la place de, ou bien en plus de DHCP). Deux utilisations typiques de DHCP sont le SoHo où le routeur ADSL est également serveur DHCP pour les trois PC connectés et le réseau local d'entreprise où deux ou trois machines Unix distribuent adresses IP et informations de configuration à des centaines de machines.

Le DHCP spécifié par notre RFC (et remplacé depuis par le RFC 8415) ne fonctionne que pour IPv6, le RFC 2131 traitant d'IPv4.

DHCP fonctionne par diffusion restreinte. Un client DHCP, c'est-à-dire une machine qui veut obtenir une adresses, diffuse (DHCP fonctionne au dessus d'UDP) sa demande à l'adresse multicast locale au lien FF02::1:2. Le serveur se reconnait et lui répond. S'il n'y a pas de réponse, c'est, comme dans le DNS, au client de réémettre (section 14).

Le serveur choisit sur quels critères il alloue les adresses IP. Il peut les distribuer de manière statique (une même machine a toujours la même adresse IP) ou bien les prendre dans un pool d'adresses et chaque client aura donc une adresse « dynamique ». Le fichier de configuration ci-dessous montre un mélange des deux approches.

Il faut bien noter (et notre RFC le fait dans sa section 23) que DHCP n'offre aucune sécurité. Comme il est conçu pour servir des machines non configurées, sur lesquelles on ne souhaite pas intervenir, authentifier la communication est difficile. Un serveur DHCP pirate, ou, tout simplement, un serveur DHCP accidentellement activé, peuvent donc être très gênants. Les approches suggérées dans la section 21 ou dans la section 23 sont en général très complexes (comme l'IPsec du RFC 4301) et ne sont typiquement pas déployées.

Outre l'adresse IP, DHCP peut indiquer des options comme les adresses des serveurs DNS à utiliser (RFC 3646).

Notre version IPv6 de DHCP est assez différente de la version IPv4 (et le RFC est trois fois plus long). Par exemple, l'échange « normal » entre client et serveur prend quatre paquets IP (section 1.3) et non pas deux, l'encodage est très différent, il y a des nouveautés comme l'IA (Identity Association) de la section 10, etc. Il y a aussi des différences visibles à l'utilisateur comme le concept de DUID (DHCP Unique IDentifier), section 9, qui remplace les anciens client identifier et server identifier de DHCP v4. Les différences sont telles que le RFC précise que leur intégration n'est pas envisagée.

À l'heure actuelle, il semble qu'il existe au moins trois mises en œuvre de DHCPv6, Dibbler, celle de l'Institut Leibniz à Dresde et celle de l'ISC, à partir de la version 4.0. Le fichier de configuration de cette dernière ressemble beaucoup à ce qu'il est en v4 :

subnet6 2001:DB8:DEAD:BABE::/64 {
     range6      2001:DB8:DEAD:BABE::100 2001:DB8:DEAD:BABE::FFF; 
     # On peut aussi utiliser préfixe/longueur au lieu d'indiquer les
     # adresses de début et de fin de la plage
}

On doit lancer le serveur avec l'option -6 (le même démon ne peut pas servir le v4 et le v6 en même temps, les deux protocoles étant trop différents) :

# dhcpd -6 -d -f 
Internet Systems Consortium DHCP Server 4.0.0
...
Listening on Socket/eth0/2001:db8:dead:babe::/64
Sending on   Socket/eth0/2001:db8:dead:babe::/64

[Puis arrive une requête]

Solicit message from fe80::219:b9ff:fee4:25f9 port 546, transaction ID 0x4BB14F00
Picking pool address 2001:db8:dead:babe::fbb
Sending Advertise to fe80::219:b9ff:fee4:25f9 port 546
Request message from fe80::219:b9ff:fee4:25f9 port 546, transaction ID 0x46B10900
Sending Reply to fe80::219:b9ff:fee4:25f9 port 546

(Le concept de transaction ID est décrit sections 6 et 15.1.) La requête est émise depuis une adresse lien-local (ici fe80::219:b9ff:fee4:25f9) pas depuis une adresse « tout zéro » comme en IPv4 (section 16 du RFC). Vu avec tcpdump, la requête est :

15:07:43.455918 IP6 fe80::219:b9ff:fee4:25f9.546 > ff02::1:2.547: dhcp6 solicit
15:07:43.456098 IP6 fe80::219:b9ff:fee4:2987.547 > fe80::219:b9ff:fee4:25f9.546: dhcp6 advertise
15:07:44.512946 IP6 fe80::219:b9ff:fee4:25f9.546 > ff02::1:2.547: dhcp6 request
15:07:44.513233 IP6 fe80::219:b9ff:fee4:2987.547 > fe80::219:b9ff:fee4:25f9.546: dhcp6 reply

On note que l'échange a été celui à quatre messages (Solicit - Advertise - Request - Reply), décrit section 1.3. Le serveur n'a pas répondu directement avec un Reply, parce que le client n'a pas inclus l'option Rapid Commit (section 22.14). Cette option n'est pas actuellement gérée par le client DHCP utilisé (l'option dhcp6.rapid-commit existe mais la documentation précise qu'elle est ignorée).

Actuellement, l'attribution d'adresses statiques à une machine, en la reconnaissant, par exemple, à son adresse MAC est plus délicate avec le serveur de l'ISC (merci à Shane Kerr pour son aide). Il faut trouver le client identifier (section 22.2 du RFC, deux méthodes possibles pour le trouver sont expliquées plus loin) et le mettre dans dhcpd.conf :

host lilith {
  host-identifier option dhcp6.client-id 0:1:0:1:47:96:21:f7:0:19:b9:e4:25:f9;
  fixed-address6 2001:DB8:DEAD:BABE::2;
}

et cette adresse IP fixe est donnée au client.

Pour trouver le client identifier, une méthode spécifique au client DHCP de l'ISC est de regarder dans le fichier des baux du client (typiquement /var/db/dhclient6.leases) :

...
  option dhcp6.client-id 0:1:0:1:47:96:21:f7:0:19:b9:e4:25:f9;

Il suffit alors de le copier-coller.

Une autre méthode, plus complexe, mais qui marche avec tous les clients DHCP est de lancer tcpdump en mode bavard :

# tcpdump -n -vvv ip6 and udp and port 547
12:24:15.084006 IP6 (hlim 64, next-header UDP (17) payload length: 60) fe80::219:b9ff:fee4:25f9.546 > ff02::1:2.547: dhcp6 solicit (xid=4323ac (client ID hwaddr/time type 1 time 1201021431 0019b9e425f9) (option request DNS DNS name)[|dhcp6ext])

Le client identifier, le DUID, se fabrique en concaténant le type de DUID (ici, 1, Link-layer Address Plus Time, section 9.2 du RFC), le type de matériel (1 pour Ethernet), le temps (ici 1201021431, notons que la version actuelle du client DHCP viole le RFC en comptant les secondes à partir de 1970 et pas de 2000) et l'adresse MAC, ce qui redonne le même résultat au prix de quelques calculs avec bc.

Mais l'utilisation exclusive du DUID, au détriment de l'adresse MAC, n'est pas une obligation du RFC (le RFC, section 9, dit juste « DHCP servers use DUIDs to identify clients for the selection of configuration parameters », ce qui n'interdit pas d'autres méthodes), juste un choix des développeurs de l'ISC. Le serveur de Dresde, dhcpy6d, permet d'utiliser les adresses MAC, comme on le fait traditionnellement en IPv4. En combinaison avec des commutateurs qui filtrent sur l'adresse MAC, cela peut améliorer la sécurité.


Téléchargez le RFC 3315


L'article seul

De l'intérêt des règles d'intégrité dans un SGBD

Première rédaction de cet article le 17 janvier 2008


Les règles d'intégrité des SGBD permettent un accès bien plus sécurisé à la base de données et documentent le schéma. Pourquoi mettre de telles règles et comment ?


L'article complet

RFC 5228: Sieve: An Email Filtering Language

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : P. Guenther (Sendmail), T. Showalter (Mirapoint)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sieve
Première rédaction de cet article le 17 janvier 2008


L'utilisation massive du courrier électronique fait que, même sans compter le spam, chaque utilisateur professionnel reçoit désormais des dizaines et souvent des centaines de messages quotidiens dans sa boîte aux lettres. Il n'est donc plus question de les gérer entièrement à la main, il faut disposer d'un mécanisme de filtrage automatique.

On n'imagine plus aujourd'hui d'utiliser le courrier au bureau sans un tel mécanisme, permettant de mettre les messages dans des dossiers séparés selon, par exemple, la liste de diffusion concernée. Il en existe plusieurs, certains bâtis sur une interface graphique, d'autres autour d'un langage. Ces derniers, bien plus riches et puissants, sont variés. Le plus connu est procmail, célèbre pour son pouvoir expressif (on peut tout faire en procmail) mais aussi pour sa difficulté.

Sieve, l'objet de ce RFC, est nettement moins riche que procmail, ce qui peut être un inconvénient pour les utilisateurs avancés mais un avantage pour l'administrateur : permettre aux utilisateurs de configurer procmail revient à leur donner un accès shell alors que Sieve est plus contrôlable. Comme le note bien notre RFC, Sieve n'est pas un langage de Turing (par exemple, il ne connait pas les boucles). Ses capacités sont limitées, il est sandboxable, c'est-à-dire que l'administrateur système peut facilement limiter les choses que risquent de faire les auteurs de scripts Sieve.

Autre avantage par rapport à procmail, Sieve est normalisé et il en existe plusieurs mises en œuvre, dans Cyrus, dans Dovecot, dans GNU mailutils, dans Archiveopteryx...

Les scripts Sieve sont écrits par l'utilisateur avec un éditeur ordinaire ou bien via une interface graphique. Ils sont installés sur le serveur de messagerie via FTP ou bien par le protocole spécifique Manage Sieve (RFC 5804). Le programme de webmail SquirrelMail, par exemple, dispose d'une interface d'édition de scripts Sieve, qui gère le protocole Manage Sieve.

Voici un exemple de script Sieve inspiré du RFC et amélioré par Mathieu Arnold :

             if header :contains "from" "jfc" {
                discard;
             } elsif header :contains ["subject"] ["money", "viagra"] {
                discard;
             } else {
                fileinto "INBOX";
             }

Sieve lui-même est très limité mais le langage dispose d'un mécanisme d'extensions (qui doivent être déclarées dans le script avec require). Certaines sont définies dès notre RFC (comme fileinto), d'autres sont définies via d'autres RFC, par exemple pour utiliser des tests anti-spam ou antivirus (RFC 5235), ou bien pour tester sur des sous-adresses (RFC 5233).

Notre RFC est la mise à jour du RFC 3028, qui avait été le premier à normaliser Sieve. Les principaux changements (section 15) sont :

  • Retrait de l'action reject, qui migrera vers un RFC séparé, le RFC 5429.
  • Le mécanisme de comparaison de chaînes de caractères, dans la section 2.7.3, auparavant défini spécifiquement pour Sieve, est désormais dans une famille de RFC séparée, introduite par le RFC 4790, qui décrit le registre des algorithmes de collation. Seuls les algorithmes i;octet et i;ascii-casemap sont directement dans Sieve, les autres sont des extensions (et doivent donc être déclarées avec require).
  • La grammaire formelle a été corrigée. Un des traditionnels talons d'Achille des RFC est que les parties en langage formel, comme les grammaires en ABNF ou les MIB ne sont pas testées par un programme avant publication et que des RFC peuvent donc être publiés avec du code invalide. Notons aussi que notre RFC (section 8) est un des très rares RFC où les structures lexicales (les tokens) et syntaxiques sont séparées. La règle la plus fréquente dans les RFC est au contraire que la grammaire décrive les deux types de structure ensemble.

Pour les utilisateurs de procmail, il existe un script (que je n'ai pas testé) pour migrer certaines règles : http://www.earth.ox.ac.uk/~steve/sieve/procmail2sieve.pl). Si vous êtes curieux des extensions Sieve, vous pouvez lire tous les articles de mon blog qui en parlent.

Notez que certains hébergeurs de courrier permettent à leurs clients d'écrire des scripts Sieve, par exemple Gandi. (Ils ne pourraient pas le faire avec un langage plus général comme procmail, pour des raisons de sécurité.)


Téléchargez le RFC 5228


L'article seul

RFC 5134: A Uniform Resource Name Namespace for the EPCglobal Electronic Product Code (EPC) and Related Standards

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : M. Mealling (Refactored Networks)
Pour information
Première rédaction de cet article le 17 janvier 2008


Deux nouveaux membres de la grande famille des URN, epc: et epcglobal: vont désormais apparaitre dans les URN, notamment pour désigner les identificateurs portés par les code-barres ou bien par les puces RFID.

EPC est le cadre dans lequel sont gérés plusieurs protocoles et plusieurs familles d'identificateurs, liés en général à la notion de chaîne d'approvisionnement. Le but est de suivre des objets physiques passant dans les entrepôts, les containers, les magasins... Ces objets sont identifiés par un lecteur de code-barres ou bien par un lecteur RFID, qui détermine leur identificateur. Par exemple, les identificateurs GTIN, utilisés dans les code-barres en font partie (ils sont attribués par GS1). Ce RFC spécifie comment représenter ces identificateurs sous forme d'URN (RFC 8141) commençant par epc:. Un autre espace de noms, epcglobal:, servira pour les espaces de noms XML des protocoles associés.

Le RFC ne fait que résumer la syntaxe de ces nouveaux URN, la spécification complète est écrite par EPC sous le titre de EPC Tag Data Standards et ne semble pas disponible en ligne (EPCglobal est une organisation très fermée, la plupart des références données par le RFC ne sont pas accessibles). Un exemple d'un de ces URN est urn:epc:id:sgtin:0614141.100743.2, utilisant les identificateurs SGTIN.

Notons que ces identificateurs pourront peut-être servir d'entrées dans le DNS pour accéder à des informations sur ces objets. C'est le système ONS, qui utilisera les NAPTR du RFC 3401.


Téléchargez le RFC 5134


L'article seul

RFC 2923: TCP Problems with Path MTU Discovery

Date de publication du RFC : Septembre 2000
Auteur(s) du RFC : K. Lahey
Pour information
Première rédaction de cet article le 16 janvier 2008


Au moment de sa nomalisation, dans le RFC 1191, la découverte de la MTU du chemin semblait une excellente idée, en permettant d'adapter la taille des paquets IP de façon à minimiser la fragmentation. Mais plusieurs problèmes sont surgis à l'usage, notre RFC faisant la liste de ceux qui affectent plus particulièrement TCP.

Pour chaque problème, notre RFC donne un nom, décrit la question, fournit des traces tcpdump et suggère des pistes pour la résolution. Le plus fréquent des problèmes n'est pas spécifique à TCP, c'est le trou noir (section 2.1). Comme la découverte de la MTU du chemin repose sur des paquets ICMP indiquant que le paquet TCP était trop grand pour le lien, tout ce qui empêche de recevoir ces paquets ICMP perturbera la découverte de la MTU. Les paquets TCP seront abandonnés par les routeurs mais on ne verra pas pourquoi, d'où le nom de trou noir.

Qu'est-ce qui peut créer un trou noir ? Il existe plusieurs raisons (le RFC 1435 en donne une particulière) mais la plus fréquente, de loin, est l'ignorance abyssale de certains administrateurs de coupe-feux, qui bloquent complètement tout ICMP pour des « raisons de sécurité » en général fumeuses (un bon test pour détecter cette ignorance est de leur demander si le ping of death est spécifique à ICMP. S'ils disent oui, cela montre qu'ils n'ont rien compris.)

Le problème est suffisamment répandu pour qu'il ai fallu développer un nouveau protocole, où TCP fait varier la taille des paquets pour voir si les gros ont davantage de pertes, protocole décrit dans le RFC 4821. Ce protocole a été développé bien après notre RFC 2923, qui donne des conseils en ce sens mais fait preuve de prudence en craignant que, si les mises en œuvre de TCP réparent ce genre de problèmes, la cause (le filtrage d'ICMP) risque de demeurer (la section 3 revient sur cette question).

Ce débat est récurrent à l'IETF. Faut-il pratiquer la politique du pire, en refusant de contourner les erreurs de configuration (tenter de faire corriger les sites mal configurés est une entreprise courageuse, voire folle), ou bien faut-il essayer de réparer ce qu'on peut, au risque de diminuer la pression sur ceux qui ont fait ces erreurs ?

D'autres problèmes sont, eux, réellement spécifiques à TCP comme les acquittements retardés (section 2.2) provoqués par un envoi des acquittements TCP en fonction de la MSS, qui peut être bien plus grande que la MTU du chemin (cf. RFC 2525). Ce problème n'a pas de solution simple et unique.

Un autre problème lié à la MSS est la détermination de celle-ci (section 2.3). Une implémentation naïve qui déduirait le MSS à partir de la MTU du chemin annoncerait une MSS trop faible et, surtout, ne pourrait pas l'augmenter si un nouveau chemin apparait. La solution est de déduire la MSS de la MTU du réseau local (qui est stable), pas de la MTU du chemin (RFC 1122).


Téléchargez le RFC 2923


L'article seul

The catenet model for internetworking

Première rédaction de cet article le 15 janvier 2008


Les IEN (aujourd'hui abandonnés) ne sont pas aussi connus que les RFC mais ce sont souvent des documents utiles sur l'évolution de l'Internet. L'IEN 48, nommé The catenet model for internetworking et écrit par Vint Cerf est un passionnant exposé de l'architecture de l'Internet, avant qu'il ne reçoive ce nom (Cerf, suivant Pouzin, proposait catenet, qui n'a pas pris.)

Dans ce texte de 1978, on trouve une définition des règles que doivent suivre un réseau pour être connecté au catenet : offrir un service de datagrammes rapide, utilisant le format standard (le futur IP), faire tourner un protocole de routage avec le reste du catenet et pas grand'chose d'autres (notamment, il n'est pas exigé de préserver l'ordre des datagrammes, ni même de délivrer tous les datagrammes).

L'IEN discute de la différence entre routeur (nommé gateway à l'époque) et machine terminale, en concluant que les différences ne comptent pas pour le catenet : IP sera le même pour tous.

L'adressage était proche de ce qui sera IPv4, avec des adresses sur 32 bits, mais avec un préfixe de longueur fixe (8 bits).

Comme souvent avec les vrais chefs d'œuvre d'ingéniérie, ce sont les décisions sur ce qu'on ne garde pas qui sont importantes : l'IEN repousse à plus tard les questions de comptage des paquets ou de sécurité, et ce sont ces décisions qui ont permis à l'Internet de se développer, les routeurs pouvant router au lieu de faire la police.


L'article seul

RFC 3986: Uniform Resource Identifier (URI): Generic Syntax

Date de publication du RFC : Janvier 2005
Auteur(s) du RFC : Tim Berners-Lee (World Wide Web Consortium), Roy T. Fielding (Day Software), Larry Masinter (Adobe Systems Incorporated)
Chemin des normes
Première rédaction de cet article le 15 janvier 2008


Le Web repose sur trois piliers : le format HTML, le protocole HTTP et, surtout, le concept d'URI, une famille d'identificateurs à la fois compréhensibles par les humains et automatiquement analysables par les programmes. La syntaxe des URI est normalisée dans ce RFC.

Il y a des URI partout aujourd'hui. Sur le côté des autobus, sur les cartes de visite, dans les documentations techniques, dans les articles de la presse papier. Ils sont une des marques les plus spectaculaires du succès du Web. Peu de gens il y a quinze ans osaient dire qu'on verrait des URI à la devanture des boulangeries et des teintureries. Le Minitel n'avait pas d'équivalent (« Tapez 3615 JERAQUE puis choisissez le menu Locations puis allez dans Dernières locations ») et même les informaticiens connectés à Internet utilisaient souvent de telles descriptions (avant les URI, il n'y avait pas de syntaxe standard et analysable pour un nom de fichier accessible en FTP, on disait « ftp.sunet.se, dans /mirrors/macarchive/decoders/foobar.bin ». (Les URI ont été normalisés pour la première fois dans le RFC 1630 en 1994.) Même si certains utilisateurs n'ont pas encore compris les URI et donnent des instructions assez miniteliennes à leurs interlocuteurs comme « Tapez Locations en Bretagne dans Google » ou bien « Allez sur www.exemple.fr et choisissez Locations puis Bretagne », ils sont largement diffusés, bien au-delà du cercle des quelques informaticiens et physiciens qui les utilisaient en 1990.

Grâce aux URI, on a donc, pour la première fois, des identificateurs standards, à la syntaxe rigoureuse (donc pouvant être traités par un programme) mais décodables et mémorisables par des humains. Ils permettent de désigner sans ambiguïté une ressource (contrairement aux moteurs de recherche et aux systèmes de mots-clés, qui sont une référence floue et instable).

Aujourd'hui, qu'est-ce qu'un URI, du point de vue des normes ? URI est le terme qui désigne toute la famille des identificateurs du Web. Les deux membres les plus connus de cette famille sont les URL (RFC 1738) et les URN mais notre RFC préfère ne pas trop utiliser ces termes et ne parler que d'URI (section 1.1.3, voir aussi RFC 3305), entre autres parce que le statut de « localisateur » (locator) n'est pas clair (un URI http n'est pas forcément un URL, voir section 1.2.2). La syntaxe qui est décrite dans le RFC est générique, elle s'applique à tous les URI, quel que soit leur plan (scheme), la partie de l'URI avant le premier deux-points. Des syntaxes plus précises et plus restrictives peuvent être spécifiées par certains plans (le plus connu des plans est http). Notre RFC fournit, lui, ce qui est commun à tous les plans.

Le « cahier des charges » avait été écrit dans les RFC 1736 et RFC 1737. Le premier RFC qui l'avait mis en œuvre était le RFC 2396, que notre RFC 3986 remplace. Les trois lettres du sigle URI indiquent bien la démarche (section 1.1) :

  • « Uniform » car un URI peut décrire une très grande variété de ressources, accessibles (ou pas) via de nombreux protocoles, avec une syntaxe commune,
  • « Resource » car un URI identifie des ressources, sans poser de limites à ce que peut être une ressource (cela peut être un fichier mais aussi bien d'autres choses),
  • « Identifier » car un URI nomme une ressource, il ne dit pas forcément où la trouver (tous les URI ne sont pas des URL). Les URI s'inscrivent donc dans la grande tribu des identificateurs formels.

La section 1.1.1 décrit la syntaxe générique, détaillée en section 3 : un URI commence par un plan, suivi d'un deux-points, d'une autorité optionnelle (par exemple le nom de domaine d'une machine), puis d'un chemin (path), dont la syntaxe dépend du plan, d'une requête optionnelle et d'un fragment optionnel. Voici quelques exemples d'URI, inspirés du RFC :

http://fr.wikipedia.org/wiki/Jacques_Brel

ldap://[2001:DB8::7:23A]/dc=example,dc=org?objectClass?one

tel:+1-816-555-1212
      
urn:oasis:names:specification:docbook:dtd:xml:4.1.2

Ainsi, droite://example.org:8042/par/ici?label=ChezMoi#note se décompose en :

  • droite : le plan,
  • example.org:8042 : l'autorité,
  • /par/ici : le chemin,
  • label=ChezMoi : la requête,
  • note : l'identificateur d'un fragment.

En Python, on peut facilement analyser un URI avec le module urlparse :

>>> from urlparse import urlparse
>>> scheme,authority,path,params,query,fragment = urlparse("http://fr.wikipedia.org/wiki/Jacques_Brel#Discographie")
>>> scheme
'http'
>>> path
'/wiki/Jacques_Brel'
>>> fragment
'Discographie'

La section 1.2 revient sur les choix de conception. Elle part d'un scénario où deux personnes échangent des URI en les notant sur une nappe en papier dans un restaurant, ce qui nécessite des URI parlants, mais écrits dans un alphabet répandu (demande qui peut être contradictoire avec la précédente). D'une manière générale, il est préférable d'utiliser de beaux URI. C'est également dans cette section qu'est posé le principe que les URI n'utilisent qu'un jeu de caractères très limité, un sous-ensemble d'ASCII. Cette limite très contraignante est levée avec les IRI du RFC 3987.

La suite de la section parle du problème important de la récupération (retrieval) d'une ressource. Une des utilisations les plus courantes d'un URI est pour accéder à une ressource. Cela nécessite que l'URI soit résolvable (ce qui n'est pas, en général, le cas des URN). Mais tous les URI ne sont pas forcément résolvables, ne serait-ce que parce qu'ils peuvent n'être utilisés que comme identificateurs (c'est le cas, par exemple, des URI identifiant un espace de noms XML). Le RFC insiste aussi sur le fait que le plan n'est pas, en général, un protocole réseau. Même quand cela semble être le cas (URI http), divers mécanismes font que la ressource peut être récupérée par d'autres moyens que le protocole indiqué (par exemple, pour les documents XML, on utilise typiquement un catalogue qui indique une correspondance entre un URI et un fichier local, de sorte que le processeur XML n'aie pas besoin d'aller sur le réseau).

Puis cette section 1.2 discute le caractère hiérarchique des URI, avec ses composants allant du plus significatif, le plan, tout à fait à gauche, au moins significatif, à droite (à noter que les séparateurs des composants varient, ce que n'auraient pas apprécié Rob Pike et Peter J. Weinberger).

La section 2 est consacrée aux caractères utilisés pour former un URI, uniquement ASCII, on l'a vu. La section 2.2 donne une liste des caractères qui, quoique présents dans ASCII, ne peuvent pas être utilisés pour un URI car ils ont une signification spéciale. C'est le cas par exemple du # qui introduit l'identificateur d'un fragment de la ressource. La section 2.1 normalise le codage « pour cent » où les caractères non-ASCII sont remplacés par le signe % suivi de leur valeur en hexadécimal. (C'est hélas la valeur de chaque octet, pas le point de code Unicode.) Malheureusement, la section 2 précise qu'aucun encodage particulier n'est choisi. Il est donc très difficile de faire des URI utilisant des caractères non-ASCII, même en utilisant le codage « pour cent » puisqu'il n'y a pas de moyen d'indiquer l'encodage utilisé. Ainsi, http://example.org/caf%E9 est sans doute du Latin-1 mais sans qu'on puisse en être sûr. On limite les risques en supposant que l'encodage est UTF-8 comme dans l'URI http://fr.wikipedia.org/wiki/caf%C3%A9 (C3 A9 est l'encodage en UTF-8 du e accent aigu).

L'encodage d'une chaîne de caractères pour en faire un URI peut être effectuée en XSLT par la fonction EXSLT str:encode-uri, par exemple ainsi :


 <xsl:value-of select="str:encode-uri($word, true())"/>

ou bien en Python avec la fonction quote de la bibliothèque urllib :

>>> from urllib import quote
>>> quote("foo # bar ?")
'foo%20%23%20bar%20%3F'

Voyons plus en détail les différents composants d'un URI. Le plan, d'abord, décrit en section 3.1. Notre RFC ne contient pas de liste de plans. Ils doivent être enregistrés à l'IANA, comme indiqué dans le RFC 7595 (on peut aussi voir le RFC 2718). Les plans les plus connus sont http, mailto et urn. tag (RFC 4151) est moins connu mais est un de mes favoris.

L'autorité (section 3.2) indique quelle entité va gérer le reste de l'URI. Pour un URN, c'est un simple nom (comme isbn pour les ISBN du RFC 8254).Pour le plan http, l'autorité est un nom de domaine ou une adresse IP. Dans ce cas, elle peut aussi inclure un nom d'utilisateur, pour l'authentification. Si l'adresse IP est IPv6, il faudra un échappement spécial (la mettre entre crochets), décrit dans le RFC. Enfin, il peut y avoir un numéro de port, bien que cela pose un problème avec les enregistrements SRV (RFC 2782) qui peuvent aussi spécifier un port.

Le chemin (section 3.3) indique une ressource particulière pour une autorité. Il est composé de plusieurs parties séparées par une barre oblique (pour des raisons historiques : c'est le séparateur de répertoires sur Unix). Si l'URI est de type http et que les pages Web sont des fichiers HTML statiques, le chemin est un répertoire sur le disque dur, mais ce n'est pas forcément le cas pour tous les URI, loin de là !

La requête (section 3.4), située après le ? est un composant optionnel de l'URI. Elle est utilisée typiquement pour les ressources générées dynamiquement, en réponse à la question que représente ce composant, mais rien dans la norme n'oblige à les utiliser pour cela.

Le fragment (section 3.5), qui se place après le # désigne une partie de la ressource. Si l'URI est résolvable, le fragment est interprété par le client uniquement, le serveur ne le voit pas. L'exemple le plus courant est un fragment composé d'un nom, par exemple, si la ressource est en HTML, un attribut name ou id d'un élément HTML.

La section 4 explique l'utilisation des URI par un programme. Elle couvre le cas d'URI relatifs (la section 5 développe ce point) ou bien, dans la section 4.5, d'URI dont le début, par exemple le plan, manque. De tels URI sont courants dans la presse ou la publicité, par exemple www.afnic.fr au lieu de http://www.afnic.fr/. Le RFC note que cette pratique, quoique courante, est dangereuse car elle dépend du contexte pour une bonne résolution. Elle ne devrait pas être utilisé pour des URI à longue durée de vie.

La section 6 s'attaque à un problème difficile, la normalisation des URI. On a souvent besoin de comparer deux URI. Par exemple, un navigateur Web affiche les pages déjà visitées avec une couleur différente. Pour cela, il doit comparer les URI présents dans la page Web avec son historique des liens visités. Or, faire cette comparaison octet par octet peut rater beaucoup d'égalités. Par exemple, le plan est insensible à la casse donc urn:bortzmeyer:exemple:1 est égal à URN:bortzmeyer:exemple:1. D'autres canonicalisations dépendent du plan. Par exemple, avec les URI http, l'autorité est un nom de domaine et les noms de domaine sont insensibles à la casse donc http://www.demaziere.fr/eve/ est égal à http://www.Demaziere.FR/eve/ (la section 6.2.2.1 détaille les comparaisons insensibles à la casse ; sauf indiqué explicitement, les composants d'un URI sont sensibles à la casse). Le navigateur doit donc normaliser les URI avant de les comparer.

Le RFC note qu'aucune normalisation ne sera parfaite. Après tout, deux URI différents peuvent parfaitement indiquer la même ressource, sans que le logiciel ne puisse le deviner.

Une section 7 détaille les questions de sécurité associées aux URI. Elle note que beaucoup de ces questions n'ont pas de solution technique et qu'elles dépendent d'une approche sociale. Par exemple, la persistence des URI, un sujet de recherche très actif, dépend plutôt de bonnes pratiques sociales (notamment d'organisations stables, et qui peuvent voir sur le long terme) que d'une technique particulière. Une autre question de sécurité est traitée dans la section 7.6, c'est celle du hameçonnage, pour les cas où l'auteur du site de hameçonnage tente de fabriquer des URI trompeurs (très peu d'utilisateurs vérifient les URI et la plupart des hameçonneurs ne se donnent même pas la peine d'en fabriquer de vraisemblables). La syntaxe des URI est suffisamment compliquée pour que certains URI soient difficiles à décoder par un humain.

Enfin, notons que l'appendice D expose toutes les différences entre ce RFC et son prédécesseur, le RFC 2396. La principale est la section sur la normalisation, qui a été complètement refaite, mais il y en a beaucoup d'autres, en général de faible importance.


Téléchargez le RFC 3986


L'article seul

RFC 4648: The Base16, Base32, and Base64 Data Encodings

Date de publication du RFC : Octobre 2006
Auteur(s) du RFC : S. Josefsson (SJD)
Chemin des normes
Première rédaction de cet article le 14 janvier 2008
Dernière mise à jour le 29 septembre 2012


Même les plus simples encodages peuvent réveler des surprises. Base64 en est désormais à son quatrième RFC, mais il est vrai que c'est un des formats les plus utilisés, qu'on le trouve partout dans les protocoles. Ce RFC normalise donc Base64, ainsi que Base32 et Base16.

Quel est le problème que tentent de résoudre ces encodages ? Le fait que certains environnements n'acceptent pas le jeu de caractères qu'on voudrait utiliser. C'est bien sûr le cas si ce jeu de caractères est Unicode mais même le simple ASCII peut être trop vaste pour certains usages. Par exemple, les URL ne peuvent pas comporter d'espace, et nécessitent donc un encodage de ces espaces, pour les protéger. Base64 et ses camarades sont des encodages généralistes pour tous ces cas où on doit réduire d'un jeu de caractères trop vaste à un jeu restreint : Base64 (sections 4 et 5) utilise 64 caractères (les majuscules et les minuscules d'ASCII, les chiffres, le signe plus et la barre oblique). Base32 (sections 6 et 7) utilise uniquement les majuscules et les chiffres et Base16 (section 8, mais il faut noter que ce nom de Base16 n'a jamais pris) utilise uniquement les caractères des chiffres hexadécimaux (il sert par exemple, sous un autre nom, à l'encodage des URL, cf. RFC 3986, section 2.1).

La section 3 du RFC est très détaillée car elle doit expliquer tous les problèmes d'interopérabilité qui peuvent se poser avec l'encodage, notamment si celui-ci est incomplètement spécifié (ce qui était le cas avec les RFC précédant celui-ci, comme le RFC 2045). Ainsi, la section 3.1 parle du difficile problème des sauts de ligne, ou bien 3.3 se demande ce que doit faire le récepteur si des caractères en dehors du jeu normalement utilisé apparaissent néanmoins dans les données. Le monde des encodages est vaste et peu organisé... Heureusement que ce RFC décrit bien l'état actuel du problème.

Historiquement, des tas de variantes plus ou moins importantes d'un de ces encodages ont été utilisées, ce qui contribue à la difficulté de la tâche de décodeur. La section 5 normalise une de ces variantes, un encodage de Base64 qui n'utilise pas le / et le +, qui ont souvent une signification particulière, mais le _ et le -. Comme il est surtout utilisé pour les URL, cet encodage est souvent nommé URL encoding.

La section 12, sur la sécurité, est également très complète car, historiquement, plusieurs problèmes de sécurité ont été liés à ces encodages. Par exemple, beaucoup de spams sont encodés en Base64, même lorsque cela n'est pas nécessaire, pour tenter d'échapper à des logiciels de filtrage naïfs. (C'est au point que SpamAssassin donne désormais une mauvaise note aux messages ainsi encodés.)

Du fait de l'étendue des usages de Base64, il existe des bibliothèques pour l'encoder et le décoder dans tous les langages de programmation (Base32 est moins bien traité). Le RFC cite également une implémentation de référence en C.

Voici un exemple d'encodeur en Perl :

#!/usr/bin/perl

use MIME::Base64;

foreach $word (@ARGV) {
    print("$word: " . encode_base64($word) . "\n");
}

Et un exemple de décodage en une seule ligne de Perl :


% echo Y2Fm6Q= | perl -MMIME::Base64 -e 'printf "%s\n", decode_base64(<>)' 

Cet autre exemple est en D :


static import std.base64;
import std.stdio;

int main(char[][] argv)
{
  int argc = argv.length;
  char[] word;
  if (argc <= 1) {
    writefln("Usage: %.*s word ...", argv[0]); 
    return 1;
  }
  for (int i = 1; i < argc; i++) {
    // It would be cooler to use 'foreach (char[] word; argv)' but it
    // does not allow to skip 0th arg (and slices do not seem to work
    // in that context)
    word = argv[i];
    writefln("%s: %s", word, std.base64.encode(word));
  }
  return 0;
}

Voici un exemple d'encodage Base64 en Go, montrant la différence entre l'encodage standard et l'« encodage URL » :

package main

import (
	"bufio"
	"encoding/base64"
	"flag"
	"fmt"
	"io"
	"os"
)

const MAXSIZE int = 4096

func main() {
	result := make([]byte, MAXSIZE)
	value := make([]byte, MAXSIZE)
	rd := bufio.NewReader(os.Stdin)
	n, error := rd.Read(value)
        ...
	base64.StdEncoding.Encode(result, value[0:n])
	fmt.Printf("Standard encoding of %s is %s\n", value[0:n],
		result)
	base64.URLEncoding.Encode(result, value[0:n])
	fmt.Printf("URL encoding of %s is %s\n", value[0:n],
		result)
}

Depuis le shell, on cite parfois le logiciel aish, mais je l'ai toujours trouvé inutilisable. Je préfère OpenSSL qui a une option d'encodage en Base64 (l'argument -n d'echo permet de voir la différence selon qu'il y a un saut de ligne ou pas) :

% echo -n café | openssl enc -base64     
Y2Fm6Q==
% echo café | openssl enc -base64       
Y2Fm6Qo=

Et, pour décoder :

% echo Y2Fm6Qo=  | openssl enc -d -base64 

Il y a aussi dans les coreutils un utilitaire nommé base64.

Notre RFC 4648 succède au RFC 3548 (qui lui même complétait le RFC 2045 sur ce point). La section 13 liste les changements (modérés), comme par exemple l'ajout d'exemples à des fins de tests des logiciels.


Téléchargez le RFC 4648


L'article seul

Luz ou le temps sauvage

Première rédaction de cet article le 10 janvier 2008


Un terrible roman d'Elsa Osorio, sur la répression dans l'Argentine de la dictature militaire. L'héroïne a été enlevée, tout bébé, à sa mère, qui était prisonnière des militaires, et « donnée » à la famille de l'un d'eux. Devenue adulte et mère, elle part à la recherche de la vérité. C'est tendre, sensible, humain et pourtant très violent (et la première partie, qui se passe au plus fort de la répression, n'est pas forcément la plus dure).


L'article seul

Les beaux URL

Première rédaction de cet article le 10 janvier 2008
Dernière mise à jour le 14 janvier 2008


Beaucoup de sites Web affichent, dès qu'on dépasse la page d'accueil, et même parfois dès la page d'accueil, des URL incompréhensibles, très longs et bourrés de paramètres dont l'utilisateur ne connait pas la signification. C'est déplorable, à la fois pour des raisons esthétiques et pour des raisons pratiques. Pourquoi est-ce regrettable ? Comment éviter cela ?

Prenons quelques exemples affreux. L'UNESCO proclame 2008 l'« Année Internationale des Langues » et la page Web de présentation de l'activité est à l'URL http://portal.unesco.org/culture/en/ev.php-URL_ID=35559&URL_DO=DO_TOPIC&URL_SECTION=201.html. Pourquoi ne pas avoir utilisé le plus court et plus parlant http://www.unesco.org/iyl ?. Autre exemple, si on se promène sur le site de Dell à la recherche d'informations sur le Latitude 430, on arrive en http://premierconfigure.euro.dell.com/dellstore/config.aspx?cs=RC1077983&customer_id=RC1077983&oc=LD4301&~tgt=global_cfg&c=FR&l=fr&s=PAD. Pourquoi ne pas avoir un URL comme http://www.dell.com/computers/latitude-d430/ ? Un dernier exemple, alors que la loi est censée être facilement accessible à tous, il n'existe pas de moyen de fabriquer facilement l'URL pour, mettons le « Décret n°2006-1386 du 15 novembre 2006 fixant les conditions d'application de l'interdiction de fumer dans les lieux affectés à un usage collectif ». Sur Légifrance, on arrive à un URL de http://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000000818309&dateTexte=20080124&fastPos=5&fastReqId=621185253&oldAction=rechTexte. Pourquoi pas http://www.legifrance.gouv.fr/decrets/2006/11/15/1386 ? Manifestement, le webmestre de Légifrance a lui-même des problèmes avec de tels URL puisque, lorsqu'on regarde l'article R3512-1 du Code de la Santé Publique, et qu'on voit un beau lien vers le décret, ce lien ne fonctionne pas « Aucun document ne correspond à votre demande » !

C'est très laid. De tels URL heurtent mon sens esthétique. Pour se remonter le moral, voici quelques exemples de beaux URL :

Outre l'aspect esthétique, les URL laids posent aussi des problèmes pratiques (également bien détaillés dans un excellent article de Jakob Nielsen). Étant longs, ils sont difficiles à copier-coller, par exemple dans un courrier. Révélant le fonctionnement interne du site Web (noms des paramètres, type de langage utilisé comme PHP pour le site de l'UNESCO), ils ne sont pas stables. Si le site passe à un autre CMS, ces URL changeront probablement, en contradiction avec les principes posés dans l'article Cool URIs don't change.

Surtout, ces URL sont « indécodables ». Avec la meilleure volonté du monde, on ne peut pas les comprendre, on ne peut pas les mémoriser et on ne peut pas les bricoler de manière créative, par exemple en changeant la valeur d'un paramètre.

De tels URL sont parfois volontaires, par exemple pour décourager la création de « liens profonds » (liens hypertexte pointant vers une autre page que la page d'accueil). Pourquoi diable voudrait-on décourager les liens profonds ? Typiquement pour empêcher le lecteur d'accéder directement à l'information qui l'intéresse et pour l'obliger à suivre le parcours officiel, partant de la page d'accueil.

De tels URL très longs sont parfois volontaires parce qu'il y a beaucoup d'informations à indiquer. C'est le cas des URL de Google Maps où il y a beaucoup à encoder (notamment longitude et latitude). Par exemple, dans http://www.google.com/maps?f=q&hl=en&geocode=&time=&date=&ttype=&q=san+cristobal+de+las+casas,+chiapas,+mexico&sll=16.75655,-93.129044&sspn=0.425394,0.579529&ie=UTF8&ll=16.738551,-92.633286&spn=0.053179,0.072441&t=h&z=14&iwloc=addr&om=1, les chiffres dans le paramètre ll indiquent la latitude et la longitude. Mais de tels URL ne sont pas gratuitement compliqués, ils stockent de l'information et ils sont décodables et modifiables. Notamment, je peux générer un tel URL facilement, sans avoir besoin de Google Maps, ce qui permet des applications géographiques intéressantes de type mashup. Par exemple, comme le service Vélib' donne accès à la latitude et la longitude de chaque station (dans le fichier http://www.velib.paris.fr/service/carto), on peut facilement faire un programme qui crée un URL Google Maps pour chaque station, comme c'est le cas sur des sites comme Roulib ou bien http://v.mat.cc/. D'ailleurs, il existe même un langage pour décrire ces gabarits d'URL, normalisé dans le RFC 6570.

Mais, la plupart du temps, ces URL sont complexes car le webmestre a installé un logiciel de gestion du site Web (qu'il n'a pas toujours choisi) et que ce sont les URL par défaut du logiciel et que le webmestre ne peut pas ou ne sait pas les modifier (ou, pire, n'a pas compris à quoi servaient les URL).

A contrario, certains logiciels, comme la plupart des moteurs de blogs, fabriquent des URL clairs et simples, et faciles à décoder. Ils ne sont pas forcément stables sur le long terme (les professionnels de la stabilité suggèrent en général de ne pas mettre trop d'information dans l'URL car un changement de cette information changerait l'identificateur) mais ils sont bien agréables à manipuler.

Alors, que peut-on faire pour ne pas avoir de tels URL ? Si le webmestre est impossible à faire évoluer sur ce sujet (souvent, il ne lit même pas ses messages), il existe des mécanismes de contournement comme tinyurl. Ces systèmes créent une correspondance entre un URL et un identificateur à eux, et fournissent un service de redirection automatique. C'est ainsi que http://tinyurl.com/2u2ewd va au même endroit que l'affreux URL de l'UNESCO cité plus haut. Mais ces mécanismes ont leurs propres inconvénients, notamment le fait que l'URL soit encore moins décodable qu'avant (on ne voit même pas le nom de domaine, donc on ne peut pas savoir qui est responsable).

L'idéal est donc quand le webmestre fait bien son travail. Pour l'aider, voyons quelques techniques utiles. Notons d'avord qu'il n'existe aucune raison technique valable d'utiliser des URL affreux. On voit parfois certains débutants croire que des URL incluant un point d'interrogation sont nécessaires si la recherche de l'information est dynamique (par exemple http://www.maboutique.fr/catalogue?objet=642342). Mais c'est faux, l'URL est indépendant de la méthode utilisée pour générer la page. On peut avoir un URL qui va faire une recherche dynamique dans une base de données, sans point d'interrogation dedans. (On notera que, soucieux de prouver chaque jour qu'on peut breveter n'importe quoi, l'office états-unien des brevets a enregistré un brevet n° 7,287,042 qui réserve cette technique à Amazon, en dépit de nombreux précédents d'utilisation, que l'incompétence ou la malhonnêteté de l'office des brevets ne lui a pas permis de détecter.)

Notons d'abord que beaucoup de CMS ou de logiciels équivalents permettent de faire facilement des beaux URL. Si ce service n'est pas activé par défaut, il est souvent bien documenté. Par exemple, le CMS SPIP a une documentation détaillée « Utiliser des URLs personnalisées ».

Sinon, la solution générale, si on n'est pas l'auteur du CMS utilisé ou bien qu'on n'a pas envie de se plonger dans le code source est, si on utilise Apache, de se servir de l'excellent (mais complexe) module mod_rewrite.


L'article seul

Recommandations DNS lorsqu'on change d'adresse IP

Première rédaction de cet article le 9 janvier 2008


Aujourd'hui, avec les mécanismes d'allocations d'adresses IP existants (cf. RFC 7020), il est relativement fréquent d'avoir à changer son adresse IP. Quelles sont les précautions particulières liées au DNS lors de ce changement ?

Supposons donc qu'un utilisateur aie une machine à lui chez Slicehost, Gandi, OVH ou un autre. L'adresse IP de cette machine est « fixe » au sens où elle ne change pas toutes les 24 heures, mais rien ne garantit qu'elle ne changera jamais. Une nouvelle configuration du réseau, un changement de fournisseur (pour les hébergeurs qui n'ont pas leurs propres adresses IP) et on doit changer. Il existe plusieurs précautions à prendre lors d'un tel changement mais on ne parle ici que de celles liées au DNS.

D'abord et avant tout, il faut penser que les informations distribuées par le DNS sont gardées dans des caches. La durée de vie maximale dans le cache est gouvernée par un paramètre nommé le TTL (RFC 1034, section 3.6), que l'administrateur de la zone fixe lui-même. Il est recommandé de réduire ce TTL avant le changement.

dig peut afficher le TTL, ce qui permet de vérifier la configuration serveur :

% dig @mon-serveur A www.venezvoirchezmoi.fr.
...
www.venezvoirchezmoi.fr.        86400   IN      A       192.0.2.249

Le TTL indiqué par le serveur faisant autorité est donc de 86400 secondes. Sur un serveur ne faisant pas autorité, le TTL diminue petit à petit et indique donc combien de temps il reste avant le renouvellement du cache :

% dig A www.venezvoirchezmoi.fr.
www.venezvoirchezmoi.fr.        33982   IN      A       192.0.2.249

Cette deuxième requête a interrogé le résolveur local, qui ne fait pas autorité, et a donné l'information à partir de son cache. L'enregistrement était déjà dans ce cache depuis 86400 - 33982 = 52418 secondes.

Cas le plus simple ; soit un bête enregistrement ordinaire qui stocke une adresse IP d'un serveur Web (ici, en IPv6) :

www   IN  AAAA   2001:DB8::DEAD:BABE

Son TTL va être donné (si on utilise BIND ou NSD) par la directive $TTL. Mais on peut la changer pour chaque enregistrement :

www  300 IN  AAAA   2001:DB8::DEAD:BABE   ; Trois cents seconds, soit cinq minutes

Ainsi, lors du changement d'adresse, il n'y aura que cinq minutes de problème au maximum.

On peut descendre le TTL à 60 si on est pressé, mais il vaut mieux éviter de l'abaisser à zéro, pas mal de FAI l'ignorent (car il y a trop d'abus) et le forcent à une valeur plus élevée (ce qui, formellement, viole le RFC).

Évidemment, il faut faire ce changement de durée de vie à l'avance (si le TTL actuel est de 86 400 secondes, il faut faire le changement au moins une journée avant).

À l'heure H, on peut alors changer l'enregistrement (ici le AAAA, l'heure H est celle où on indique la nouvelle adresse IP). Il ne faut pas remonter le TTL tout de suite, il faut tester d'abord que tout marche bien.

Le TTL ne gouverne que la durée de vie dans les caches des résolveurs ne faisant pas autorité. Pour les serveurs faisant autorité sur la zone (le maître, autrefois nommé « primaire » et les esclaves, autrefois nommés « secondaires »), il faut aussi surveiller leur synchronisation. Si, par exemple, les NOTIFY (messages DNS normalisés dans le RFC 1996 et permettant de prévenir immédiatement les esclaves) sont ignorés (il peut y avoir des tas de raisons pour cela), le temps de synchronisation va s'ajouter au TTL. Les esclaves ayant raté le NOTIFY ne seront synchronisés qu'au prochain test. Les tests sont effectués toutes les Refresh secondes, avec rééssai toutes les Retry secondes en cas d'échec. Les paramètres Refresh et Retry sont fixés dans l'enregistrement SOA. On voit donc l'importance de tester la synchronisation des serveurs de la zone avant l'heure H.

Maintenant, cas compliqué, l'adresse IP peut se trouver à d'autres endroits que la zone :

Un coup de grep dans /etc/** est donc recommandé pour trouver toutes les occurrences de l'ancienne adresse IP.

Pour le cas registre / registrar, ça dépend de leur réactivité combinée. Là encore, il vaut mieux étudier avant. Il est donc prudent de prévoir un recouvrement (ancien serveur qui marche toujours) si on change la colle (enregistrements d'adresses qui sont stockés dans la zone parente).

Cette question étant souvent celle qui pose le plus de problèmes, il faut donc faire doublement attention lorsqu'on change l'adresse IP d'une machine qui est serveur de noms, surtout lorsqu'elle a un nom dans la zone servie (obligeant ainsi le registre à garder la colle).

Prenons l'exemple de la machine 192.0.2.53, qui est connue sous le nom de ns1.example.com et qui est serveur de noms de la zone example.com. Le fait qu'elle soit nommée dans la zone qu'elle sert oblige le registre de .com à distribuer la colle, et donc à mémoriser l'adresse IP (certains registres gardent l'adresse IP des serveurs même lorsqu'elle n'est pas nécessaire, ce qui est mal vu, mais arrive). Son changement d'adresse va donc nécessiter de vérifier l'information distribuée par le registre (et mise à jour via le registrar puisque .com impose le passage par un intermédiaire). Voyons avec dig comment vérifier l'adresse distribuée par le registre, en interrogeant les serveurs de noms de Verisign :

% dig @a.gtld-servers.net A ns1.example.com.
ns1.example.com.       172800  IN      A       192.0.2.3

(Notez que cette réponse ne fait pas autorité, le flag aa sera donc absent.) Le DNS ne reflète pas toujours l'état actuel de la base de données du registre. Selon les cas, il peut être prudent de vérifier avec whois :

% whois -h whois.internic.net ns1.example.com
   Server Name: NS1.EXAMPLE.COM
   IP Address: 192.0.2.3

Ces deux commandes permettent de voir si les changements ont bien été transmis au registre, et exécutés.


L'article seul

RFC 5039: The Session Initiation Protocol (SIP) and Spam

Date de publication du RFC : Janvier 2008
Auteur(s) du RFC : J. Rosenberg, C. Jennings (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF sipping
Première rédaction de cet article le 5 janvier 2008


Le spam est la plaie du courrier électronique. Peut-il également affecter d'autres services comme la téléphonie sur IP ? C'est la crainte de l'IETF, d'où ce RFC qui étudie les moyens de faire face au spam via le protocole SIP, avant que ce phénomène se développe.

Rien n'indique que le spam restera limité au courrier électronique. Au contraire, l'expérience semble indiquer que, du moment qu'une technique permet de joindre beaucoup de personnes pour pas cher, et sans introduction préalable, elle est utilisée par les spammeurs. Les techniques soi-disant « sans spam » sont uniquement celles qui ne sont peu ou pas utilisées, ou qui sont chères et peu pratiques.

Le message principal du RFC est qu'il faut s'y prendre à l'avance. Le spam aurait été plus facile à combattre si on avait déployé certaines techniques dès le début. Pour le protocole SIP (RFC 3261), de loin le principal protocol ouvert pour faire du multimédia, notamment de la téléphonie, sur Internet, il est donc peut-être encore temps d'agir. (Je suis personnellement prudent par rapport à cette affirmation. Pour le courrier électronique, je n'ai pas encore vu de solution qui, si elle avait été déployée plus tôt, aurait empêché le spam de prendre une telle ampleur.)

La section 2 explique les formes que pourrait prendre le spam avec SIP. Elle note qu'il n'est pas forcément nécessaire d'envoyer un message pour spammer. Par exemple, SIP a une méthode INVITE qui peut prendre un en-tête Subject: (section 20.36 du RFC 3261). Si ce sujet est affiché à l'utilisateur avant même qu'il n'accepte l'appel (ce que font certains soft phones), il peut servir de canal pour le spam.

Cette particularité de SIP, et quelques autres, font que certaines des techniques couramment utilisées pour le filtrage du courrier ne sont pas forcément efficaces. Ainsi, le filtrage par contenu (section 3.1 de notre RFC), comme les filtres bayésiens, n'est pas tellement appliquable dans le cas d'un message audio, encore moins pour un message vidéo.

Le RFC insiste sur importance de l'identité. Beaucoup de techniques marchent si on peut être à peu près certain de l'identité de l'émetteur. Par exemple, les listes blanches sont facilement prises en défaut si le spammeur peut se faire passer pour une personne connue. Le problème est d'autant plus difficile qu'on voudrait authentifier la personne, pas uniquement son ordinateur car, comme le note la section 3.3, si l'ordinateur est compromis et est devenu un zombie, l'authentifier ne servira à rien.

Un autre problème classique des listes blanches est le fait qu'elles ne gèrent que le cas des personnes proches. Le RFC propose dans sa section 3.5, d'utiliser les mécanismes de réseau social (« mes copains ont aussi des copains ») pour augmenter automatiquement les listes blanches (la plupart des logiciels SIP, comme les logiciels d'IM, ont un système analogue, en général nommé buddy list, liste des copains).

En revanche, les techniques de dissimulation d'adresses, comme on voit pour le courrier (stephane plus blog à bortzmeyer point org) ne fonctionnent pas bien si on reste aux traditionnels numéros de téléphone. L'espace possible est en effet restreint et relativement facile à parcourir de manière exhaustive (ENUM facilitera probablement les choses pour les spammeurs).

Les approches du problème peuvent aussi être basées, non pas sur une technique mais sur une organisation. Une architecture possible est décrite en section 3.13, avoir un petit nombre de fournisseurs SIP qui se transmettent des coups de téléphone entre eux, et n'en acceptent pas des autres fournisseurs. Un tel cartel, qui ressemble aux propositions de mail peering qui sont proposées pour le courrier par des organismes comme le MAAWG ou comme le FAI AOL aurait, note notre RFC, tous les avantages et tous les inconvénients de l'actuel réseau téléphonique, que SIP visait à remplacer.

Finalement, la section 6 du RFC est consacrée aux quatre recommendations importantes :

  • Développer un système d'identité fort, comme décrit dans le RFC 4474.
  • Utiliser largement les listes blanches.
  • Résoudre le problème de l'introduction. Si tout le monde utilise des listes blanches, on risque de ne pas pouvoir appeler quelqu'un à qui on n'a pas été introduit. Les mécanismes d'introduction visent à résoudre ce problème, par exemple via les réseaux sociaux (« les amis de mes amis sont mes amis »).
  • Ne pas attendre que le spam se soit répandu (voir le début de cet article).

Téléchargez le RFC 5039


L'article seul

Le Larousse n'aime pas Internet

Première rédaction de cet article le 4 janvier 2008


On le sait, les médias traditionnels n'aiment pas leur concurrent Internet. Mais l'édition 2006 du Larousse du Collège attaque particulièrement durement.

Cette édition du dictionnaire Larousse est destinée « aux 11-15 ans », un public sensible, qui rentre au collège. Outre des erreurs comme de faire remonter la naissance d'Arpanet à... 1957, on trouve dans cet article la conclusion suivante :

« Internet serait-il une machine qui s'emballe ? Devant le manque d'encadrement juridique, le système semble autoriser toutes les libertés. Internet consacre le piratage comme une sorte de sport international. S'introduisant dans le réseau, les crackers et les hackers [le second terme est absent de ce dictionnaire] inventent tous les moyens pour ruser. Ne parlons pas de la désorganisation des réseaux, vaste entreprise qui ressemble bien à une nouvelle forme de guerre. Par la force des images terrorisantes et des exécutions en direct, ce formidable outil peut à la fois servir de propagande et nous déstabiliser psychologiquement. C'est ce type d'infractions pénales que l'on désigne sous le terme de « cybercriminalité ». »

« Il est quasiment impossible de maîtriser le volume de données qu'Internet met à la disposition, de les classer ou de les hiérarchiser, d'en vérifier la fiabilité à cause de l'opacité des sources. Par ces lacunes, Internet ne risque t-il pas de devenir un moyen de manipulation planétaire ? »

Il n'y manque qu'une attaque contre Wikipédia pour que cet article soit la liste complète des préjugès anti-Internet :-)


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 davantage 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

Enregistrement de l'alsacien dans le registre IETF/IANA

Première rédaction de cet article le 3 janvier 2008
Dernière mise à jour le 30 mars 2008


L'alsacien est désormais enregistré dans le registre IETF/IANA des langues, après un processus qu'il est intéressant de décrire.

Le RFC 4646 spécifie un registre des langues, hébergé à l'IANA. Ce registre s'appuie largement sur des normes ISO comme ISO 639 (dont la version 3 est parue l'année dernière) ou ISO 15924. Mais, pour l'instant, aucune norme ISO n'enregistre les dialectes, les langues donnant déjà assez de travail à l'agence de maintenance, SIL. Le registre IETF/IANA est donc le seul à permettre l'enregistrement de dialectes (en attendant la future norme ISO 639-6), par son mécanisme de variant (le premier enregistré ayant été le valencien).

Rappelons que le mot « dialecte » n'a rien de péjoratif. Un dialecte est une variante d'une langue, qui ne forme pas une langue séparée (l'intercompréhension entre les différents dialectes demeure, alors qu'il n'y a pas intercompréhension entre les langues). Bien sûr, en pratique, la frontière est souvent floue (SIL a ainsi reclassifié le languedocien ou le provençal en dialectes de l'occitan alors qu'ils étaient d'abord considérés comme langues séparées) et c'est pour cela qu'un examen attentif par un expert, le Language Subtag Reviewer (actuellement Michael Everson) est nécessaire pour l'enregistrement d'une nouvelle étiquette.

La situation avec les dialectes est d'autant plus délicate que, si certaines langues, comme le français ou le japonais, sont assez normalisées par un État, une Académie, des médias nationaux, les dialectes, eux, ne sont pratiquement jamais spécifiés rigoureusement.

La procédure complète pour enregistrer une nouvelle étiquette de langue est décrite dans le RFC 4646. Une version simplifiée figure en http://www.langtag.net/register-new-subtag.html. C'est cette procédure qui a été appliquée au début pour l'alsacien dont voici la première demande (retirée par la suite).

L'alsacien désigne ici un dialecte particulier de l'alémanique. L'alémanique (code ISO gsw) est une langue germanique distincte de l'allemand (code ISO de), parlée en Allemagne, en Suisse, en Autriche et en France. Comme la plupart des langues non étatiques, elle n'a pas une forme unique, ni même de forme officielle, « de référence », elle est plutôt une collection de dialectes. Celui qui nous intéresse est surtout parlé en France, l'Alsace étant française depuis des siècles. L'alsacien est surtout parlé mais on trouve aussi des livres écrits dans le dialecte, comme un livre de la série Martine, que son dessinateur, Marcel Marlier est venu dédicacer à Strasbourg le 24 novembre 2007 : martine-en-alsacien.png. Microsoft avait annoncé la disponibilité de Office en alsacien.

On notera qu'il existe également des sous-dialectes selon les régions d'Alsace et aussi des dialectes en Alsace qui ne sont pas alémaniques mais franciques, voire romans, comme le welche. La demande d'enregistrement ne concerne que le dialecte alémanique, d'où le préfixe gsw qui indique que l'étiquette complète pour l'alsacien, si la demande avait été acceptée, aurait été gsw-alsatian.

La discussion a été très animée sur la liste ietf-languages, où sont examinées les demandes d'enregistrement. Il faut dire que les langues germaniques sont un sujet complexe, qui défie les classifications, comme l'a montré une demande, faite un peu plus tard, pour l'enregistrement de l'Erzgebirgisch. Beaucoup de personnes ayant participé à la discussion suggéraient, plutôt que d'enregistrer la nouvelle étiquette alsatian, de se contenter des étiquettes existantes et d'identifier l'alsacien avec gsw-FR (alémanique parlé en France). Le terme « alsacien » n'est en effet utilisé qu'en France (même si les frontières linguistiques et politiques ne coïncident pas). Reste la question de savoir comment les utilisateurs de l'alsacien trouveront cette étiquette, si le terme « alsacien » n'apparait pas dans le registre. Fin janvier 2008, j'ai retiré la demande originelle, une demande officielle ayant été faite à l'agence de maintenance de ISO 639-2 (qui avait enregistré le code gsw) pour ajouter explicitement l'alsacien dans la description de l'alémanique. Cette demande a été acceptée au bout de quelques semaines. « Alsacien » est désormais listé comme nom pour le code gsw. Il restait à la transcrire dans le registre des langues, ce qui a fait l'objet de la demande suivante, un PRR (proposed revised record), normalement, juste une formalité. En effet, cette demande a finie par être enregistrée par l'IANA le 26 mars 2008, marquant la fin du processus. Désormais, la description de l'alémanique, code gsw, inclus officiellement le fait que ce code s'applique à l'alsacien.

Merci à l'Office pour la Langue et la Culture d'Alsace pour son aide et sa documentation, mais la demande d'enregistrement est éditée par moi et ne représente pas forcément leur point de vue. Merci aussi à François Martin pour son aide érudite.


L'article seul

RFC 5095: Deprecation of Type 0 Routing Headers in IPv6

Date de publication du RFC : Décembre 2007
Auteur(s) du RFC : J. Abley (Afilias), P. Savola (CSC/Funet), G. Neville-Neil (Neville-Neil Consulting)
Chemin des normes
Première rédaction de cet article le 3 janvier 2008


Ce RFC supprime un type particulier d'en-tête IPv6, qui permettait de faire du routage IP contrôlé par la source mais qui ouvrait la voie à de graves attaques par déni de service.

Normalement, le routage dans IP se fait uniquement en fonction de l'adresse de destination. Une technique connue sous le nom de « routage par la source » (source routing) permet de placer dans un paquet IP des instructions pour les routeurs situés sur le trajet, forçant l'usage d'un chemin particulier. En IPv4, ce routage par la source se fait en indiquant la route (les routeurs par lesquels le paquet doit passer) dans l'en-tête IP, où la taille est limitée. Cela limitait donc sérieusement l'utilité de ce routage par la source, mais aussi ses dangers, puisque un paquet ne pouvait pas être forcé sur un chemin très long. Néanmoins, cette option est tellement facile à utiliser pour contourner les politiques de sécurité, qu'elle est désactivée sur la plupart des routeurs IP (option sysctl net.ipv4.conf.all.accept_source_route sur Linux, par exemple ou bien no ip source-route sur IOS).

Mais la menace en IPv6 était plus sérieuse. En effet, l'en-tête IPv6 est de taille fixe et les options sont placées dans des en-têtes auxiliaires, qui sont très variés (section 4 du RFC 2460). Cela permet de mettre des en-têtes de très grande taille. L'un d'eux, l'en-tête de routage (Routing Header, section 4.4 du RFC 2460) de type 0, permet de lister un plus grand nombre de routeurs intermédiaire qu'en IPv4 (et on peut indiquer plusieurs fois le même routeur, permettant ainsi des parties de ping-pong entre les routeurs). C'est celui, qui, suite à un article très médiatisé (souvent avec des exagérations ridicules) expliquant comment il pouvait être mal utilisé, et suite à l'analyse du RFC 4942, vient d'être déclaré abandonné. (La faille de sécurité avait été enregistrée sous le numéro CVE-2007-2242.)

Désormais, spécifie la section 3 de notre RFC 5095, une machine IPv6 doit ignorer les en-têtes de routage de type 0.

La section 4.2 couvre un problème intéressant, le risque que certains coupe-feux soient programmés de manière excessive pour rejeter tous les paquets ayant un en-tête de routage, même d'autres types (par exemple, le type 2 est utilisé par le RFC 3775). C'est une situation qui s'est déjà produite avec le soi-disant ping of death, où plusieurs administrateurs de coupe-feux ont bloqué complètement ICMP, alors que la vulnérabilité n'avait rien de spécifique à ICMP.

Notre RFC avertit donc qu'il ne faut pas surréagir : bloquer tous les paquets ayant un en-tête de routage empêcherait complètement le déploiement de beaucoup de protocoles.


Téléchargez le RFC 5095


L'article seul

RFC 3743: Joint Engineering Team (JET) Guidelines for Internationalized Domain Names (IDN) Registration and Administration for Chinese, Japanese, and Korean

Date de publication du RFC : Avril 2004
Auteur(s) du RFC : K. Konishi, K. Huang, H. Qian, Y. Ko
Pour information
Première rédaction de cet article le 3 janvier 2008


Une fois définie une norme pour les noms de domaines internationalisés, il reste à régler quelques problèmes liés à leur enregistrement. Par exemple, le chinois s'écrit couramment avec deux écritures, la traditionnelle et la simplifiée. Faut-il permettre l'enregistrement de deux noms de domaines identiques, ne se différenciant que par cette écriture ? Notre RFC propose un cadre pour spécifier de telles règles et crée la notion de lot (package), un ensemble de domaines qu'IDN considérerait différents mais que le registre préfère traiter comme équivalents, et ne pouvant donc faire l'objet que d'un seul enregistrement.

IDN, normalisé dans le RFC 3490 , permet d'exprimer des noms de domaine en Unicode. Une canonicalisation est effectuée par le mécanisme nameprep (RFC 3491) et certaines chaînes de caractères Unicode (commme Straße et strasse) sont donc identiques pour nameprep. Il ne peut donc y avoir qu'un seul nom de domaine pour ces deux chaînes.

Mais d'autres chaînes Unicode sont considérées comme distinctes par nameprep, et donc peuvent être enregistrées séparément, alors qu'un locuteur de telle ou telle langue pourrait les voir comme identiques. C'est le cas de deux mots en chinois en écriture traditionnelle ou simplifiée, par exemple. De même, en français, certains pourraient considérer que congres et congrès doivent être considérés comme identiques, car ne se différenciant que par un accent.

Notre RFC, qui n'a pas le statut de norme, n'essaie pas de décrire une telle politique pour toutes les langues du monde. Il fournit simplement un cadre permettant de décrire de telles politiques, en mettant l'accès sur les questions spécifiques des langues asiatiques, souvent désignées par le sigle CJC. Il a été co-écrit par les registres de noms de domaine de Chine, de Taïwan, de Corée et du Japon, regroupés dans une structure ad-hoc, le JET. Le RFC 4290 étendra ensuite cette méthode aux autres écritures du monde.

Avant de voir la technique, il est bon de se rappeler que l'IETF n'a aucune légitimité pour décider des politiques d'enregistrement suivies dans .tw ou .kr. Il ne peut s'agir ici que de recommandations, telles qu'exprimées dans la note de l'IESG qui précède le RFC, qui incite les autres registres à suivre le même chemin, en rappelant (à regret ?) que l'IESG ne peut pas les y obliger.

En quoi consiste le mécanisme de ce RFC ? Simplement en la définition d'une table des variantes de chaque caractère (sections 2.1.11 et 3.2.1). Toute chaîne peut donc être canonicalisée en étant réduite à la variante préférée (section 2.1.13). Les chaînes qui ont la même forme canonique font partie du même lot (package, section 2.1.18, nommé bundle dans le RFC 4290) et ne peuvent donc pas faire l'objet d'enregistrements distincts. Seule la variante préférée est enregistrée. Les autres sont réservées.

La section 3 du RFC détaille ce mécanisme et traite de certains cas particuliers, comme la suppression d'un nom de domaine (section 3.3).

Appliqué au français, avec une table de variantes telle que celle proposée pour .fr, cette méthode ferait de congres et congrès, mais aussi de côngrës et congrês les membres d'un même lot.

Notre RFC ne répond pas à la question posée plus haut sur l'équivalence des écritures chinoises traditionnelles et simplifiées. Comme expliqué en section 4, cette tâche est laissé à des tables de variantes, dont certaines sont déposées sur le registre (non obligatoire) de l'IANA.

La section 5 du RFC décrit une proposition de syntaxe pour les tables de variantes, qui sera reprise dans le RFC 4290.


Téléchargez le RFC 3743


L'article seul

Articles des différentes années : 2024  2023  2022  2021  2020  2019  2018  Précédentes années

Syndication : Flux Atom avec seulement les résumés et Flux Atom avec tout le contenu.

Un article de ce blog au hasard.