Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

echoping

Ève

Recherche dans ce blog :

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.


RFC 7353: Security Requirements for BGP Path Validation

Date de publication du RFC : Août 2014
Auteur(s) du RFC : S. Bellovin (Columbia University), R. Bush (Internet Initiative Japan), D. Ward (Cisco Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 2 septembre 2014


La sécurité du routage BGP est un sujet de préoccupation sur l'Internet depuis de nombreuses années. Ce protocole ne dispose en effet par défaut d'aucune sécurité, n'importe quel opérateur (ou craqueur ayant piraté les routeurs d'un opérateur) pouvant annoncer une route vers n'importe quel préfixe, détournant, par exemple le trafic d'un service vital. Ce manque de sécurité ne vient pas d'une confiance naïve dans la nature humaine, mais plutôt de la nature même de l'Internet : il n'y a pas (heureusement !) de Haute Autorité Supérieure de l'Internet qui connaitrait tous les opérateurs et pourrait les autoriser et les surveiller. Un opérateur ne connait (et encore, pas toujours très bien) que ses voisins immédiats, et ne sait pas quelle confiance accorder aux autres. Dans ces conditions, la sécurisation de BGP est forcément un projet à long terme. La première grande étape avait été la normalisation et le déploiement de RPKI et ROA. L'étape suivante est la sécurisation du chemin entier (et pas uniquement de l'origine), dont ce nouveau RFC est la cahier des charges. En route donc vers BGPsec ! (Le nom PATHsec ne semble plus utilisé.)

Rappelons en effet qu'une annonce BGP (RFC 4271) comprend un chemin, la liste des AS par lesquels l'annonce est passée (et, dans la plupart des cas, celle, en sens inverse, dans lequel un paquet IP émis par le récepteur de l'annonce voyagera s'il veut atteindre l'AS d'origine). Voici un telle annonce, extraite du service de looking glass d'Hurricane Electric :

Prefix: 2001:678:c::/48,  Status: E,  Age: 31d9h14m31s
         NEXT_HOP: 2001:7fa:0:1::ca28:a116, Metric: 0,  Learned from Peer: 2001:7fa:0:1::ca28:a116 (1273)
          LOCAL_PREF: 100,  MED: 1,  ORIGIN: igp,  Weight: 0
         AS_PATH: 1273 2200 2484

Le chemin comprend trois AS, et l'origine, l'AS émetteur de l'annonce, est 2484 (oui, tout à droite : un chemin d'AS se lit de droite à gauche).

Avec les certificats de la RPKI (RFC 6480) et avec le système des ROA (Route Origin Authorization, RFC 6482), on peut désormais (RFC 6811) valider l'origine d'une annonce. Cela protège contre les détournements accidentels (comme celui de YouTube par Pakistan Telecom cité plus tôt), où l'AS d'origine est en général celle du détourneur. Mais lors d'une attaque délibérée, l'attaquant peut tricher sur le chemin et envoyer une annonce avec un chemin d'AS qui semble correct, avec la bonne origine. RPKI+ROA ne protègent pas contre cet attaquant compétent. (Les RFC 4593 et RFC 7132 décrivent en détail les vulnérabilités de BGP.)

Maintenant, place aux exigences que devra satisfaire la nouvelle solution de sécurisation. La section 3 du RFC liste les exigences générales et la section 4 celles spécifiques au traitement effectué lors de la réception d'une annonce BGP. Les exigences générales d'abord, numérotées de 3.1 à... 3.23 (oui, une longue liste). D'abord, 3.1 et 3.2, qui résument le projet complet : le routeur BGP qui reçoit une annonce doit pouvoir déterminer, avec un bon niveau de confiance, que l'origine dans l'annonce (exigence 3.1), et le chemin des AS (AS Path) dans l'annonce (exigence 3.2) sont authentiques. On veut être sûr que l'AS d'origine avait bien le droit d'annoncer ce préfixe, et que le chemin d'AS dans l'annonce reflète bien le chemin suivi par l'annonce (dans l'exemple ci-dessus, que 2484 avait bien le droit d'annoncer le préfixe 2001:678:c::/48, et qu'il a bien transmis l'annonce à 2200, qui l'a lui-même bien transmis à 1273). Attention, il ne s'agit pas uniquement de montrer que le chemin d'AS est possible (ces AS sont bien des pairs...) mais que c'est bien celui qui a effectivement été utilisé. Les autres attributs de l'annonce (comme le MED dans l'exemple ci-dessus) ne sont pas protégés (exigence 3.3) car ils ne sont utilisés que dans un AS ou ses voisins immédiats. (Voir aussi l'exigence 3.10.)

Comme toute technologie nouvelle, BGPsec aura des difficultés de déploiement, dans un Internet très ossifié, et la nouvelle solution devra donc être déployable de manière incrémentale (exigences 3.4 et 3.5) : les routeurs BGPsec devront pouvoir travailler avec les routeurs actuels (exigence 3.13 ; la section 5 reconnait que cette exigence ouvre la voie aux attaques par repli, où un attaquant réussit à faire croire qu'un pair ne gère pas BGPsec et qu'il faut donc se replier sur un protocole non sécurisé). Au début, les routeurs BGPsec auront sans doute des pairs BGPsec et d'autres en BGP non sécurisé et BGPsec doit donc pouvoir être configuré pair par pair (exigence 3.12). La cryptographie peut coûter cher en ressources matérielles et un routeur BGP typique a un CPU moins puissant que celui d'un smartphone. L'exigence 3.6 autorise donc BGPsec à réclamer du matériel nouveau (par exemple des processeurs cryptographiques spécialisés). La compatibilité avec le matériel existant n'est donc pas exigée.

L'attaquant n'est pas forcément situé dans un garage à des milliers de kilomètres, comme dans le cas des détournements BGP spectaculaires connus. Il peut aussi être mieux placé, par exemple sur le lien entre deux routeurs (l'attaquant peut être sur le même point d'échange que ses victimes...) L'exigence 3.8 impose donc une solution qui marche même en cas d'ennemi sur le lien Ethernet (le RFC note que AO - RFC 5925 - ou TLS - RFC 5246 suffisent).

La cryptographie ne sert pas à grand'chose si on n'a pas de moyen de vérifier l'authenticité des clés utilisés. C'est bien joli de tester l'intégrité d'une signature mais il faut aussi que la clé de signature soit reliée aux ressources qu'on veut protéger (ici, les préfixes d'adresses IP et les numéros d'AS). L'exigence 3.9 dit donc que la solution technique a le droit de s'appuyer sur une infrastructure existante établissant ce lien, comme la RPKI (et qu'évidemment cette infrastructure doit être fiable, cf. section 5). 3.17 ajoute que cette infrastructure doit permettre le choix, par l'opérateur, des entités à qui faire confiance (toutes les mises en œuvre actuelles de la RPKI permettent cela, en éditant la liste des trust anchors).

L'exigence 3.14 concerne une question de gouvernance. Il a souvent été reproché aux projets de sécurisation de BGP de faire un déplacement de pouvoir, des opérateurs BGP aux RIR qui gèrent les points de départ de la RPKI. Avec le BGP traditionnel, le RIR a un pur rôle de registre, il ne prend aucune décision opérationnelle concernant le routage. Avec un BGP sécurisé, ce n'est plus le cas. Pour rassurer les opérateurs, 3.14 rappelle que, signature correcte ou pas, la décision d'accepter, de refuser, de prioriser ou de déprioriser une annonce doit rester locale au routeur et à son opérateur. La question « que doit faire un routeur BGPsec en recevant une annonce invalide ? » n'a donc pas de sens et les futurs RFC n'y répondront pas. BGPsec permettra de dire « cette annonce est invalide », il ne dira pas quelle politique adopter vis-à-vis de ces annonces.

Pas question de sacrifier le secret des affaires à la sécurité BGP : l'exigence 3.18 dit que BGPsec ne doit pas révéler au monde plus que ce que BGP diffuse déjà. On ne pourra donc pas exiger, par exemple, qu'un opérateur publie la liste de ses pairs privés ou de ses clients.

Bien sûr, la solution adoptée devra permettre (exigence 3.19) la journalisation des événements pertinents, notamment en matière de sécurité (c'est plus une exigence pour les mises en œuvre que pour les futurs RFC).

Rien n'étant éternel dans l'Internet, le BGP sécurisé devra ré-authentifier les informations de temps en temps, par exemple suite aux mises à jour de la RPKI (exigence 3.20), même s'il n'y a pas eu de changement BGP (ce protocole n'annonce en effet que les changements : une route qui n'a pas changé ne sera pas ré-annoncée périodiquement, et les sessions BGP peuvent durer des mois, l'annonce montrée au début de cet article était vieille de 31 jours).

Enfin, pour en finir avec les exigences générales, la 3.21 impose que la solution BGPsec permette de changer les algorithmes cryptographiques utilisés, pour faire face aux progrès de la cryptanalyse.

La section 4 décrit les exigences spécifiques au traitement des messages BGP UPDATE qui annoncent une nouvelle route ou bien en retirent une ancienne. C'est le moment où il faut valider (exigences 4.1 et 4.2). L'exigence 4.3 dispense BGPsec d'une protection générale contre les attaques par rejeu, qui resteront donc possibles (retransmission d'une annonce BGP qui était valide mais ne l'est plus, vu les changements dans le graphe BGP). Plus difficile, 4.4 demande qu'on puisse se protéger, au moins partiellement, contre le retrait par l'attaquant d'un message BGP.

Pour terminer, la section 5, sur les problèmes généraux de sécurité, rappelle plusieurs choses importantes notamment le fait que la sécurité du routage ne garantit pas celle des paquets IP (« The data plane may not follow the control plane ») et le fait qu'une sécurité de bout en bout, assurée par les deux machines qui communiquent, reste nécessaire. (Il existe d'autres moyens de détourner le trafic que les attaques BGP.)

Le protocole n'est pas encore terminé (ce RFC n'est qu'un cahier des charges) et il n'existe donc pas encore de mise en œuvre de BGPsec dans du code livré aux opérateurs.


Téléchargez le RFC 7353


L'article seul

RFC 7351: A Media Type for XML Patch Operations

Date de publication du RFC : Août 2014
Auteur(s) du RFC : E. Wilde (UC Berkeley)
Pour information
Première rédaction de cet article le 31 août 2014


Vous voulez patcher des documents XML, c'est-à-dire envoyer juste la différence entre deux documents à un serveur pour qu'il applique les opérations de transformation qui vont rendre les deux documents identiques ? Le RFC 5261 fournissait un format de description de ces patches. Il manquait toutefois un type MIME décrivant ce format. C'est désormais fait, avec la normalisation dans ce RFC du type de média application/xml-patch+xml.

Outre le RFC 5261, qui décrivait un format pour les patches XML, l'un des protocoles qui utilisent le plus XML, HTTP, a une opération PATCH qui permet de mettre à jour une ressource Web distante (RFC 5789). HTTP, comme d'autres protocoles de l'Internet, étiquette les ressources envoyées ou récupérées avec un type de média (dit aussi « type MIME », cf. RFC 6838), et pour utiliser le format du RFC 5261 avec l'opération PATCH du RFC 5789, il fallait un tel type, désormais application/xml-patch+xml. (Pour l'opération PATCH, les serveurs HTTP choisissent librement les formats de patch qu'ils gèrent, il n'existe pas de format obligatoire. Ils peuvent accepter diff, ce nouvel application/xml-patch+xml et/ou bien d'autres.)

Notez que le RFC 5261 définissait un type MIME mais uniquement pour les messages d'erreur, application/patch-ops-error+xml.

Outre l'enregistrement du type MIME application/xml-patch+xml, ce nouveau RFC corrige également les erreurs du RFC 5261, liées à la complexité de la combinaison entre XPath et les namespaces XML.

Une des raisons pour lesquelles le RFC 5261 ne définissait pas de type MIME est qu'il ne définissait pas un format complet mais juste les éléments XML indiquant l'ajout, la suppression ou la modification d'éléments XML dans le document cible. Notre nouveau RFC, lui, définit un format complet, où les éléments de patch sont inclus dans un document dont l'élément racine est <patch> (et qui sera donc servi avec le type MIME application/xml-patch+xml). Voici un exemple d'un tel document :


<p:patch xmlns:p="urn:ietf:rfc:7351">
     <p:add sel="/section"><para>Nouveau paragraphe, lorem, ipsum, dolor, etc</p:add>
</p:patch>

Notez que l'élément à la racine, <patch> et les éléments du RFC 5261 comme <add> sont dans le même espace de noms urn:ietf:rfc:7351. À part ça, on peut reprendre les exemples du RFC 5261 tels quels (voir la section 2.2 de notre nouveau RFC).

L'annexe A contient un certain nombre de détails techniques. D'abord, une discussion détaillée du problème de la correspondance de deux espaces de noms en XML, problème difficile et où le RFC 5261 s'était planté. Ensuite, le problème des espaces de noms dans le document résultat, où les règles ne sont pas les mêmes en XML et en XPath.

Pour comprendre ce dernier problème, regardez ce document XML :


<x xmlns:a="tag:42">
       <y/>
</x>

L'espace de noms est le même pour les deux éléments XML (URI tag:42, qui utilise de manière inhabituelle le RFC 4151). Mais dans ce document XML quasi-identique :


<x xmlns:a="tag:42">
       <y xmlns:a="tag:42"/>
</x>

Chaque élément a sa propre déclaration d'espace et de noms et, si le patch veut modifier /x/namespace::a, ce sélecteur XPath ne désigne que le nœud <x>, et <y> ne doit pas, lui, être modifié. Or, XPath ne fournit pas assez d'informations pour cela, un logiciel de patch XML doit donc trouver une autre façon de déterminer où stopper sa récursion (par exemple en utilisant DOM). Une mise en œuvre naïve du RFC 5261 qui ne s'appuyerait que sur XPath échouerait dans des cas comme celui indiqué dans ce paragraphe.

Enfin, l'annexe B contient une grammaire ABNF des expressions autorisées par le sous-ensemble de XPath du RFC 5261, pour ceux qui n'aiment pas le W3C Schema qu'utilisait le premier RFC.

Des mises en œuvre complètes de XML Patch+ ce nouveau RFC ? Il y en a apparemment une dans le xDB d'EMC.


Téléchargez le RFC 7351


L'article seul

Fiche de lecture : Hackers, au cœur de la résistance numérique

Auteur(s) du livre: Amaelle Guiton
Éditeur: Au Diable vauvert
9-782846-265010
Publié en 2013
Première rédaction de cet article le 31 août 2014


S'il y a un mot galvaudé, dans l'univers du numérique, c'est bien celui de « hacker ». Ce terme est utilisé aussi bien pour parler du méchant en cagoule dans son sous-sol et qui fait sauter des centrales nucléaires à distance, que pour le type qui se croit un génie parce qu'il a installé Yo sur son iPhone. Ici, dans le livre d'Amaelle Guiton, « hacker » retrouve son sens original : celui (ou celle) qui ne se contente pas de faire fonctionner des systèmes techniques existants, mais qui veut les comprendre, les modifier, voire les subvertir.

Un petit livre trop court pour couvrir tous les hackers intéressants : on rencontre WikiLeaks, Telecomix, des gens anonymes et d'autres très exposés, toute la galaxie de ceux qui pensent qu'on peut changer le monde, et en tout cas la technique. À lire et surtout à faire lire par ceux qui ne connaissent du hacker que les reportages de TF1.

À noter que le livre n'est pas facile à trouver dans les librairies, le mieux, comme je l'ai fait, est de le faire commander par sa librairie de quartier (vous n'allez pas le commander sur Amazon, quand même, vu le sujet.) Mais vous avez aussi d'autres solutions expliquées sur le site officiel (oui, je sais, le lien vers  « version papier » ne marche plus. Comme je l'ai dit, demandez à votre libraire.)

Vous pouvez aussi regarder un interview de l'auteure ou un autre.


L'article seul

J'ai un téléphone Fairphone

Première rédaction de cet article le 29 août 2014


Voilà, il y a quelques jours, j'ai reçu mon téléphone « équitable » Fairphone. Qu'a-t-il d'équitable et que fournit-il ?


L'article complet

Les quatorze qui soi-disant contrôlent tout l'Internet

Première rédaction de cet article le 28 août 2014


Hier, le magazine GQ a cru bon de publier un article intitulé « Qui détient (vraiment) les clés d’Internet ? » et qui contient tellement d'erreurs, d'exagérations, et de sensationnalisme que c'était un exercice intéressant que de tenter de les lister toutes, de rectifier la vérité de manière (je l'espère) compréhensible par des gens qui ne sont pas des experts de l'infrastructure Internet, et d'en profiter pour regarder comment travaillent les médias auxquels tant de gens font confiance pour s'informer.

D'abord, il faut noter qu'il n'y a aucun travail d'enquête : cet article et d'autres qui l'ont précédé en français (comme celui de Paris-Match) sont juste de mauvaises traductions et adaptations d'un article du Guardian, qui était également pas mal sensationnaliste mais qui reposait au moins sur un reportage réel. Chaque adaptation successive de cet article a dégradé un peu plus le contenu. Mais, que voulez-vous, produire du contenu de qualité coûte cher, et adapter des articles déjà faits est plus rapide. Pour faire croire que le contenu est original, l'article doit prétendre qu'il va révéler « un des secrets les mieux gardés » alors que, on l'a vu, ce système a déjà été décrit dans plusieurs journaux.

Maintenant, reprenons l'article de GQ. Il use et abuse de termes sensationnels (« L’histoire est digne d’un film de science-fiction. ») pour faire du spectacle à partir d'une réalité nettement plus austère, qui n'intéresse normalement que les ingénieurs réseau. Résumé simplement, il s'agit de la technologie DNSSEC, un mécanisme technique et organisationnel qui permet de sécuriser une partie importante de l'infrastructure de l'Internet, le système des noms de domaine. Sans DNSSEC, il est relativement facile à un craqueur de subvertir ce système en redirigeant un nom (mettons bortzmeyer.org qui sert au courrier que je reçois) ailleurs que ce que voulait le titulaire du nom. Il est amusant que l'article de GQ ne mentionne pas une seule fois ce sigle DNSSEC. Une caractéristique importante de DNSSEC est qu'il est optionnel : aujourd'hui, seule une petite minorité des noms (bortzmeyer.org en fait partie) est protégée par DNSSEC et seule une minorité des utilisateurs se servent de serveurs de noms qui vérifient les signatures que DNSSEC appose. Il est donc ridicule de présenter ce système comme étant la sécurité de l'Internet (« le cœur de la sécurité du Net »). Il existe d'autres systèmes de sécurité qui jouent un rôle bien plus important pour l'instant.

Ce n'est pas trop glamour, bien sûr, et donc un certain nombre de personnes ont choisi de gonfler les choses, en menant une politique de communication personnelle active. On l'a vu, produire des articles de qualité coûte cher. Alors que les journalistes sont bombardés de contenus tout prêts, deversés sur eux par des entreprises ou des personnes qui veulent se mettre en avant. Il suffit de reprendre leurs discours, sans contre-enquête, sans nuance critique, et hop, on a une jolie histoire. Sur Internet comme ailleurs, ceux qui communiquent le plus ne sont pas forcément ceux qui font le travail (de « plombiers »)...

Bon, on va être indulgent, on va dire que ces abus sensationnalistes sont un choix de récit, que cela n'affecte pas le fond de l'article.

Mais c'est qu'il y a plein d'erreurs dans l'article. Citons-les dans l'ordre. D'abord, il y a une confusion entre l'Internet et le Web (les deux articles de Wikipédia sur ces deux technologies expliquent bien la différence). Des phrases comme « [une] simple clé qui permet de sécuriser tout le web » sont donc fausses : DNSSEC n'est pas spécifique au Web.

Ensuite, l'article parle d'une « une clé centrale de chiffrement » alors que DNSSEC ne fait pas de chiffrement ! Le chiffrement sert à garantir la confidentialité des communications mais ce n'est pas le rôle de DNSSEC. Son rôle est d'assurer l'authenticité des données, via un mécanisme de signature.

Passons sur « des data centers aussi sécurisés qu’une centrale nucléaire ». Si c'était vrai, les riverains de Fessenheim pourraient s'inquiéter...

Plus embêtant, « Ce que contrôle cette clé centrale est le "serveur-racine" ». Non, non, non. D'abord, il n'existe pas un seul serveur racine mais plusieurs (leur nombre dépend de comment on compte) et, surtout, la clé en question est tout simplement la clé de signature des données situées à la racine des noms de domaine. Elle ne contrôle pas une machine mais des données.

Revenons maintenant à la propriété la plus importante de DNSSEC, le fait qu'il soit optionnel. Ce point est complètement oublié dans l'article, parce que cela obligerait à dire que cette fameuse clé n'est pas si importante que cela, puisque seuls les gens qui utilisent DNSSEC pourraient éventuellement être affectés par sa perte ou son vol. Et l'infographie dans l'article cite un seul exemple de « nom de domaine sécurisé »... gqmagazine.fr qui justement ne l'est pas. Ce nom n'est pas signé avec DNSSEC et la perte ou le vol des clés de la racine n'auraient donc rigoureusement aucune influence sur la sécurité de GQ.

La partie de l'article concernant la gouvernance n'est pas épargnée, avec une affirmation comme quoi l'ICANN « définit également les protocoles qui permettent aux machines de communiquer entre elles » (c'est faux, c'est le rôle de l'IETF).


L'article seul

RFC 7342: Practices for Scaling ARP and Neighbor Discovery (ND) in Large Data Centers

Date de publication du RFC : Août 2014
Auteur(s) du RFC : L. Dunbar (Huawei), W. Kumari (Google), I. Gashinsky (Yahoo)
Pour information
Première rédaction de cet article le 28 août 2014


Les protocoles de résolution d'adresse IP en adresse MAC sur un réseau local, ARP pour IPv4 et ND pour IPv6, fonctionnent par diffusion. Le client crie à tout le monde « qui connaît 2001:db8:376:ab::23:c0f ? » et la machine qui se reconnaît répond. L'inconvénient de ce mécanisme est qu'il passe mal à l'échelle : lorsque des centaines de milliers de machines virtuelles sont sur le même réseau local dans un grand data center, et crient toutes en même temps, le réseau va souffrir. Ce nouveau RFC ne propose pas de solution mais décrit les pratiques qui sont actuellement utilisées pour limiter les dégâts.

Le problème des protocoles ARP (RFC 826) et ND (RFC 4861) dans les grands data centers a été décrit en détail dans le RFC 6820. Le problème a toujours existé mais est devenu bien plus sérieux depuis qu'on pratique massivement la virtualisation et que le nombre de machines qui font de l'ARP ou du ND a explosé. Le désir de souplesse dans la gestion de ces machines fait qu'il est difficile d'architecturer le réseau en fonction de ce problème. Par exemple, faire de chaque machine physique un réseau limiterait la diffusion des requêtes ARP ou ND mais obligerait à changer l'adresse IP des machines virtuelles lorsqu'elles passent d'une machine physique à une autre, annulant ainsi cette souplesse que fournit la virtualisation.

Les trois principales conséquences de cette augmentation du trafic ARP/ND :

  • Consommation de capacité réseau au détriment du trafic « utile » (bien sûr, avec les liens modernes à 10 Gb/s, c'est moins grave qu'avant),
  • Augmentation de la charge de travail des routeurs, sans doute la conséquence la plus gênante aujourd'hui (cf. une étude de Merit),
  • En IPv4, augmentation de la charge de toutes les machines car la diffusion est totale (IPv6 utilise le multicast). Là encore, l'augmentation des ressources de calcul des équipements réseau peut aider : un test en laboratoire indique que 2 000 messages ARP par seconde consomment 2 % du CPU d'un serveur.

Comme expliqué dans la section 3, le réseau interne d'un grand data center a en général une de ces trois architectures :

  • Connectivité au niveau 3 (L3), c'est-à-dire qu'on fait du routage IP dans le data center,
  • Tout en niveau 2, le data center est un grand réseau L2,
  • Virtualisation du réseau (overlay).

Pour chacune de ces architectures, une section de notre RFC décrit les pratiques actuelles pour limiter l'effet des protocoles de résolution.

Dans le premier cas (réseau L3), c'est la section 4. Les réseaux utilisant le routage mettent un routeur IP dans chaque baie, voire un pour chaque machine physique. Gros avantage : la diffusion des messages ARP ou ND, qui ne va pas au delà du premier routeur, est très limitée. Le problème décrit dans le RFC 6820 disparaît donc complètement. Inconvénient : on n'a plus aucune souplesse. Changer une VM de baie, voire de serveur physique dans la même baie, oblige à la changer d'adresse IP, ce qui va casser les sessions en cours, nécessiter une reconfiguration, etc. Cette architecture ne convient donc que lorsque le data center est assez statique, ou bien lorsque les services qui y tournent peuvent supporter ces changements d'adresses IP.

Deuxième architecture possible (section 5), le grand réseau L2 où toute diffusion va frapper toutes les machines. Cette fois, le problème des messages de diffusion ARP ou ND va se poser en grand. Les routeurs qui vont faire communiquer ce réseau L2 avec l'extérieur vont souffrir. Comment diminuer cette souffrance ? D'abord, pour le cas où une machine cherche à communiquer avec une machine externe et doit donc résoudre l'adresse IP du routeur en adresse MAC. Si cette adresse MAC n'est pas dans le cache de la machine, elle envoie une requête, et le routeur doit la traiter, ce qui se fait en général via le CPU généraliste du routeur, pas dans les circuits spécialisés.

Première solution : pré-charger l'adresse MAC du routeur dans toutes les machines (options -s et -f de la commande arp sur Unix). Deuxième solution, plus souple : que le routeur envoie des réponses ARP ou ND spontanément, sans attendre les requêtes (cf. RFC 5227). Ainsi, son adresse MAC sera quasiment toujours dans les caches. Cela marche très bien pour IPv4. Mais cela ne résoud pas complètement le problème pour IPv6 : ce protocole impose l'envoi de requêtes au routeur, pour valider que la liaison avec celui-ci fonctionne (RFC 4861, section 7.3, notamment « Receipt of other Neighbor Discovery messages, such as Router Advertisements and Neighbor Advertisement with the Solicited flag set to zero, MUST NOT be treated as a reachability confirmation. Receipt of unsolicited messages only confirms the one-way path from the sender to the recipient node. In contrast, Neighbor Unreachability Detection requires that a node keep track of the reachability of the forward path to a neighbor from its perspective, not the neighbor's perspective. ». Malgré cela, notre RFC recommande que cette pratique soit utilisée pour les réseaux IPv4 et que l'on travaille à améliorer la situation pour IPv6, dans la ligne du RFC 7048.

Second cas dans ce grand réseau L2, celui du traitement du trafic entrant dans le réseau. Le routeur de bordure reçoit un paquet pour une machine interne. L'adresse MAC de cette dernière n'est pas dans le cache ARP ou ND du routeur. Il faut donc émettre une requête ARP ou ND, ce qui fait du travail pour le CPU et utilise de nombreux tampons d'attente. Première solution : limiter la quantité de requêtes par seconde. Celles en excès seront simplement abandonnées. Deuxième solution : en IPv4, le routeur peut également surveiller le trafic ARP des machines afin d'apprendre leurs adresses MAC et de remplir son cache à l'avance. En IPv6, le trafic ND n'est pas toujours diffusé et donc pas toujours écoutable, et cette solution n'aide donc pas tellement. Notre RFC recommande cette deuxième solution, au moins pour IPv4, en notant que, s'il est possible que beaucoup de paquets soient destinés à des machines éteintes ou injoignables (et qui n'émettent donc jamais), il vaut mieux trouver d'autres solutions.

De même qu'on peut pré-configurer statiquement l'adresse MAC du routeur dans toutes les machines, on peut aussi pré-configurer statiquement les adresses MAC de toutes les machines dans les routeurs. C'est évidemment un cauchemar à gérer (ceci dit, ce n'est pas fait à la main pour chaque VM, mais typiquement à l'intérieur du programme de création des VM) et il n'existe pas de mécanisme standard pour cela. Le RFC suggère que l'IETF regarde si on peut augmenter des protocoles comme NETCONF pour faire ce genre d'opérations.

Autre approche, rendre la résolution ARP hiérarchique (voir RFC 1027 et les travaux ultérieurs comme cette proposition). Au lieu de n'avoir que deux niveaux, le client et le serveur, on pourrait avoir un relais ARP spécialisé qui puisse répondre aux requêtes, garder en cache les résultats, etc. Le RFC 4903 déconseillait cette approche, notamment parce qu'elle peut gêner le déplacement rapide d'une machine (il faut alors invalider les caches) et parce qu'elle est incompatible avec SEND (que personne n'utilise, il est vrai, cf. RFC 3971). Même possibilité, au moins en théorie, avec ND (RFC 4389 décrit un relais mais qui ne réduit pas le nombre de messages). Au bout du compte, notre RFC ne recommande pas cette technique, bien qu'elle ait parfois été déployée.

Troisième architecture possible pour un grand data center, les réseaux virtuels (overlays, section 6). Il existe des normes pour cela (TRILL ou IEEE 802.1ah) et plusieurs projets. L'idée est que seul un petit nombre d'adresses MAC sont visibles dans les paquets qui circulent entre les baies, les paquets étant décapsulés (révélant l'adresse MAC interne) à un endroit très proche des VM. Les équipements qui font l'encapsulation et la décapsulation doivent être suffisamment dimensionnés puisqu'ils se taperont presque tout le trafic ARP et ND. L'intensité du travail peut être diminuée par des correspondances statiques (comme cité pour les autres architectures) ou bien en répartissant astucieusement la charge entre les machines d'encapsulation/décapsulation.

La section 7 du RFC résume les recommandations : pas de solution miracle qui conviendrait à tous les cas, plusieurs solutions mais aucune parfaite. Certaines améliorations nécessiteraient un changement des protocoles et cela fait donc du travail possible pour l'IETF :

  • Atténuer certaines obligations de ND concernant la bidirectionnalité, obligations qui interdisent actuellement de profiter complètement des messages ND spontanés.
  • Spécifier rigoureusement les sémantiques des mises à jour (lorsqu'on reçoit une réponse ARP ou ND alors qu'on a déjà l'infrmation en cache).
  • Développer des normes pour des relais/cache pouvant stocker les réponses ARP ou ND et les redistribuer largement. Le RFC 4389 peut donner des idées.

À l'heure actuelle, il n'y a plus de groupe de travail IETF sur ce sujet et ce développement de nouvelles solutions risque donc de ne pas être immédiat.


Téléchargez le RFC 7342


L'article seul

Sécurité, facilité d'usage, et les utilisateurs non-informaticiens

Première rédaction de cet article le 25 août 2014


La question de la facilité d'usage des solutions de sécurité informatique revient régulièrement sur le devant de la scène. S'il y a si peu d'utilisateurs de l'Internet qui se servent de la cryptographie ou d'autres mesures techniques qui les protégeraient, ne serait-ce pas parce que les techniques en question sont trop complexes, amenant les utilisateurs à préférer prendre des risques plutôt que de tenter de les maîtriser ?

La question revient souvent, mais elle est très ancienne. L'article qui avait été le premier à pointer ce problème de l'utilisabilité est « Why Johnny Can't Encrypt » d'Alma Whitten et J. D. Tygar1, en... 1999 Peu de progrès dans le débat depuis, à part une large reconnaissance, par la communauté des gens qui travaillent dans la sécurité informatique, que l'utilisabilité est en effet cruciale : la meilleure solution de sécurité du monde ne servira à rien si elle n'est pas utilisée car trop compliquée. Or, les révélations du héros Snowden ont rappelé l'importance de se protéger, face à l'espionnage massif qui a lieu sur l'Internet. La cryptographie fait donc l'objet d'un regain d'intérêt. Et il y a également une reprise du débat critique. Il y a deux semaines, Matthew Green avait écrit « What's the matter with PGP? » où il estimait que ce système devait disparaître (attention, son article contient bien des confusions, notamment entre le logiciel GPG et la norme OpenPGP, et des malhonnêtetés intellectuelles comme de comparer la longueur d'une clé avec celle d'un certificat).

Plus récemment, en France, Okhin à Pas Sage en Seine s'est attaqué aux informaticiens en critiquant vigoureusement « les barbus auto proclamés gourous des internets, cyber hactivistes, hackers, sysadmin et autre » et en annonçant que « Ce qui est cassé ce sont nos égos, nos réactions de sociopathes nihilistes face à un problème politique et social. » Ce thème a ensuite été repris par Barbayellow dans « Sécurité : pourquoi ça ne marche pas » et par Numendil en « Chers nous... » ainsi que par Tris Acatrinei dans « Une histoire de privilèges ».

Je vous laisse lire tous ces articles avant de voir le mien. Je ne vais pas essayer de réfuter la thèse « L'utilisabilité est essentielle pour la sécurité » car elle est exacte. La grande majorité des attaques réussies ne viennent pas d'une brillante réussite technique contre un algorithme de cryptographie, elles viennent d'erreurs commises par les utilisateurs. Mais je voudrais discuter un peu d'autres affirmations, comme de prétendre que la balle est à 100 % dans le camp des informaticiens/hackers/programmeurs, ou comme l'idée selon laquelle la difficulté d'utilisation des logiciels de sécurité est essentiellement due au manque d'intérêt des techniciens pour l'utilisabilité.

Alors, commençons par un problème pratique : clamer qu'il faut améliorer les logiciels, notamment du point de vue de l'ergonomie, c'est bien mais c'est vain. Encore faudrait-il dire en quoi on peut améliorer l'ergonomie existante. J'ai lu attentivement tous les articles cités plus haut et il y a beaucoup plus de temps passé à critiquer les développeurs (orgueilleux, autistes, méprisants, privilégiés) qu'à discuter de solutions concrètes. Il faut dire que le problème n'est pas trivial. Même un informaticien professionnel a du mal à configurer HTTPS sur son serveur Web, ou à utiliser PGP (et, plus encore, à l'utiliser tous les jours sans jamais faire d'erreur). C'est qu'il ne s'agit pas uniquement de compétences : même quand on a les compétences de base, on n'a pas forcément le temps. Donc, si on pouvait rendre ces logiciels plus faciles d'accès, ne nécessitant pas un week-end de travail pour générer une clé PGP conforme aux exigences de la cryptographie moderne, cela profiterait à tout le monde, de M. Michu au gourou informaticien. La question est « comment ? » Certaines améliorations sont assez évidentes (pour PGP, avoir des choix par défaut corrects, au lieu d'obliger les utilisateurs à demander à des experts en cryptographie comment les améliorer). D'autres le sont nettement moins. J'aimerai voir moins d'articles « les informaticiens sont méchants, ils font des logiciels peu utilisables » et plus d'articles « proposition concrète d'amélioration / de nouveau logiciel ». (Je ne suis pas exigeant, je ne demande pas de logiciel fini.) Donc, oui, les logiciels d'aujourd'hui peuvent et doivent être considérablement améliorés. Mais tout le monde en est convaincu ! Ce qu'il faudrait faire désormais, c'est d'avancer un peu et de proposer des améliorations précises, et je n'en ai pas encore vu. Et c'est un problème difficile, loin des Yakafokon. L'article « Why Johnny Can't Encrypt », cité plus haut, explique bien pourquoi le problème des interfaces utilisateur en sécurité est différent des problèmes d'ergonomie habituels. (Il explique également bien pourquoi le manque d'interface graphique est un faux problème : « All this failure is despite the fact that PGP 5.0 is attractive, with basic operations neatly represented by buttons with labels and icons, and pull-down menus for the rest ».)

Comme exemple de difficulté à concevoir une interface utilisateur simple et efficace, prenons le gros problème de la cryptographie, la gestion des clés. Une des difficultés de PGP est qu'il faut récupérer la clé publique de son correspondant (typiquement via un serveur de clés), la valider (c'est l'opération essentielle, sans laquelle il n'y a plus guère de sécurité) et la stocker. Ces opérations compliquées sont difficiles à expliquer et une erreur est vite arrivée (par exemple d'accepter une clé sans l'avoir vraiment vérifiée). OTR fonctionne sur un principe proche : comme OTR, contrairement à PGP, est limité aux communications synchrones, on n'a pas à récupérer la clé de son correspondant, mais il faut toujours la vérifier. Peut-on faire mieux ? Tout dépend de ce qu'on est prêt à abandonner en échange. Dans une discussion sur Twitter, Okhin vantait le modèle de clés de X.509 (utilisé dans TLS et donc dans HTTPS) comme étant plus simple : l'utilisateur n'a aucune vérification à faire. Mais Okhin oublie de dire que le prix à payer est la sous-traitance complète de sa sécurité aux autorités de certification qui valent... ce qu'elles valent. Si on veut protéger sa vie privée, devoir faire confiance à ces entreprises n'est pas l'idée la plus géniale qui soit. Autre solution au problème de la gestion de clés, SSH et son principe TOFU (Trust On First Use). Il est amusant que SSH soit si rarement cité par ceux qui réclament des logiciels de sécurité plus faciles à utiliser. Car SSH est justement une réussite de l'interface utilisateur, puisqu'il est plus simple que ne l'était son concurrent non sécurisé, telnet. Si on veut un exemple de conception réussie, il ne faut pas regarder TLS ou OTR mais certainement plutôt le grand succès qu'est SSH (cf. annexe A.3 du RFC 5218). Mais, là encore, rien n'est parfait. SSH est facile grâce au TOFU : la première fois qu'on se connecte à un nouveau serveur, la clé est vérifiée (en théorie...) et elle est automatiquement mémorisée pour la suite. Ce principe est assez bon (c'est un compromis raisonnable entre utilisabilité et sécurité) mais il a aussi des inconvénients : vulnérabilité lors du premier usage, difficulté à changer les clés par la suite...

Outre la notion de compromis, essentielle en sécurité (mais trop rarement citée dans les articles réclamant des logiciels plus simples), il y a une autre notion essentielle, et souvent oubliée : l'éducation. En général, elle est balayée avec des phrases du genre « il n'y a pas besoin d'être ingénieur pour conduire une voiture ». Mais c'est une illusion : bien sûr qu'il faut apprendre beaucoup de choses pour conduire une voiture. Pas besoin d'être ingénieur, certes, mais n'importe quel conducteur a dû apprendre beaucoup, simplement, comme c'est aujourd'hui un savoir banalisé, il ne s'en rend pas compte (voir à ce sujet l'hilarant texte sur le support de General Motors). Dans une société où de plus en plus de choses dépendent de l'informatique, dire que les outils modernes doivent être accessibles sans aucune éducation, c'est illusoire. Il faut au contraire développer une littératie numérique, qui implique un minimum de choses sur la sécurité. L'apprentissage de cette littératie va nécessiter des efforts des deux côtés. Réclamer des systèmes informatiques qui soient utilisables sans aucune formation, ni effort de la part des utilisateurs, va entretenir des illusions.

Quand Barbayellow écrit « [Le métier des journalistes], ce n'est pas de savoir comment fonctionne un ordinateur, un serveur ou même Internet », il se trompe. Aujourd'hui, où une si grande partie des activités humaines (le journalisme, mais pas uniquement), se passe sur l'Internet, il faut y connaître quelque chose. Dire que les journalistes ne devraient pas connaître l'Internet, c'est comme s'il disait « connaître le droit n'est pas notre métier », alors que tant de métiers aujourd'hui nécessitent forcément une culture juridique minimale. Et dire qu'il n'est pas nécessaire d'apprendre l'Internet en 2014, c'est comme dire en 1450 qu'il n'est pas nécessaire d'apprendre à lire si on n'est pas un professionnel de l'édition...

A translation in english of this article was kindly done by Pete Dushenski (footnotes are not mine).


L'article seul

RFC 7336: Framework for Content Distribution Network Interconnection (CDNI)

Date de publication du RFC : Août 2014
Auteur(s) du RFC : L. Peterson (Akamai Technologies), B. Davie (VMware), R. van Brandenburg (TNO)
Pour information
Réalisé dans le cadre du groupe de travail IETF cdni
Première rédaction de cet article le 22 août 2014


Ce RFC est le nouveau cadre technique pour les solutions standard d'interconnexion de CDN. Après le document de description du problème (RFC 6707), une liste de scénarios d'usage (RFC 6770) et un cahier des charges formel (RFC 7337), voici une nouvelle étape du travail du groupe CDNI de l'IETF. Il remplace un ancien travail équivalent, qui n'avait pas débouché, dans le RFC 3466.

Personnellement, je trouve qu'il ne va pas très loin par rapport aux RFC 6707 et RFC 7337. Mais, bon, c'est la description officielle de l'architecture des futurs protocoles d'interconnexion de CDN donc, allons-y.

N'attendez pas de ce RFC des protocoles précis : les spécifications viendront plus tard, ce qui est décrit ici est une architecture de haut niveau, très proche de ce qui avait été écrit dans le RFC 6707. (Par contre, terminologie et architecture du vieil RFC 3466 sont abandonnés.) Le principal ajout est que l'interface de routage des requêtes (Request routing interface) est désormais découpée en deux, une interface de redirection (Request routing indirection Interface) et une interface d'échange d'informations (Footprint & Capabilities Interface). Autrement, je vous renvoie à mon article sur le RFC 6707. Outre la terminologie des RFC 6707 et RFC 7337, quelques concepts nouveaux apparaissent :

  • [Rappel] « CDN amont » : celui sollicité par le client qui veut du contenu, mais qui n'a pas le contenu (ou bien, pour une raison ou pour une autre, qui ne peut pas / ne veut pas servir la requête) et doit donc utiliser les mécanismes CDNI pour déléguer ; le RFC écrit aussi uCDN pour upstream CDN,
  • [Rappel] « CDN aval » : celui qui a le contenu et va donc servir le client ; le RFC écrit aussi dCDN pour downstream CDN,,
  • « Domaine CDN » : le nom de domaine dans l'URL qui identifie le CDN. Par exemple, pour le site Web de l'Élysée, qui utilise le CDN de Level 3, c'est actuellement cdn.cdn-tech.com.c.footprint.net.
  • « Redirection Itérative » : lorsque le CDN amont renvoie simplement au CDN aval, sans essayer de traiter la requête lui-même,
  • « Redirection Récursive » : lorsque le CDN amont fait le travail de redirection lui-même, sans que le client qui accédait au contenu en soit même conscient.

La section 3 du RFC est un survol général du fonctionnement de CDN interconnectés. L'opérateur A gère le CDN amont, celui qui a un lien avec le fournisseur de contenu, qui a choisi A pour servir ses ressources. L'opérateur A a un accord avec l'opérateur B, qui gère un possible CDN aval, qui pourra servir des clients intéressés, par exemple sur une base de proximité géographique (mettons que A est en Europe et B aux États-Unis). Avant que le client n'arrive, A et B auront donc échangé des messages (via les interfaces MI et FCI, cf. RFC 7337) pour que B sache quoi servir (interface MI, envoi de métadonnées) et pour que A sache les capacités de B (interface FCI). Lorsque le client final envoie sa requête, elle est d'abord dirigée (par les techniques habituelles des CDN existants) vers A. Via l'interface RI, le client est redirigé vers B (voir plus loin les techniques de redirection). Le client envoie alors ses requêtes à B. Celui-ci doit contacter A pour obtenir le contenu lui-même (cette opération n'utilise pas les protocoles CDNI) et il sert ce contenu au client. Ensuite, il contactera A pour remplir les statistiques de ce dernier (interface LI).

La section 3 détaille ensuite les mécanismes de redirection récursifs et itératifs. La section 2 du RFC avait déjà résumé ces techniques de base utilisées par les CDN pour la redirection des requêtes. Dans le cas le plus simple, un client (par exemple un navigateur Web) va interroger un CDN qui, soit lui répondra, soit le renverra vers le CDN aval. Pour cette redirection, on peut utiliser le DNS ou bien des mécanismes de redirection du protocole applicatif (par exemple, en RTSP, un code de retour 302). D'abord, le DNS. Le principe est d'envoyer des réponses différentes selon le client. Ce dernier est situé en Europe et interroge un CDN amont qui ne sert de contenu qu'en Amérique ? Pas de problème, aux requêtes sur le domaine CDN, on renvoie l'adresse IP d'un CDN aval qui est présent en Europe. Il y a quelques précautions à prendre (se souvenir que les réponses DNS seront gardées en cache et qu'il faut donc choisir intelligemment le TTL, sans compter le fait que certains résolveurs trichent en gardant en cache plus longtemps, prêter attention à DNSSEC si on génère les redirections au vol, cf. section 3.4.1) mais cette méthode est simple et est déjà utilisée par les CDN actuels, non connectés entre eux. L'avantage de la technique DNS est qu'elle est complètement invisible à l'application, qui ne se rend même pas compte qu'elle a été servie par un autre CDN que celui demandé. L'un de ces inconvénients est que le serveur DNS qui fait autorité ne connait pas le client mais son résolveur DNS. Si le client utilise un résolveur DNS public (comme OpenDNS), le client du contenu et le résolveur peuvent être sur des continents différents et la redirection ne se fera pas vers le CDN optimal. Autre inconvénient, on ne pourra tenir compte, dans l'URL original, que du nom de domaine, le reste de l'URL n'étant pas connu du serveur DNS.

À noter qu'il existe une variante, où on ne renvoie pas directement l'adresse IP mais un nom (technique CNAME ou, mieux, DNAME). C'est le cas de l'Élysée citée plus haut :

% dig A www.elysee.fr
...
;; ANSWER SECTION:
www.elysee.fr.		3600 IN	CNAME cdn.cdn-tech.com.c.footprint.net.

Autre possibilité de redirection, la redirection HTTP : cette fois, on se sert des codes de retour 301 ou 302 qui indiquent au client HTTP qu'il doit aller chercher ailleurs ce qu'il voulait. La nouvelle URL est donnée dans la réponse (en-tête Location:). Cette fois, le serveur peut changer tout l'URL, pas juste le nom de domaine, on connait l'adresse IP du client original (le RFC oublie de mentionner qu'il peut être un relais), ce qui peut permettre de mieux choisir le serveur, et enfin on a plein d'autres informations qui peuvent être utiles pour une redirection intelligente, comme la marque du logiciel client utilisé.

Il y a par contre des inconvénients, le changement de domaine fait que les cookies ne suivront pas, et les caches ne gardent pas en mémoire les redirections (le RFC 7234 le permet mais ce n'est pas fréquemment mis en œuvre).

La section 4 du RFC donne quelques détails sur les différentes interfaces du système, interfaces qui avaient été présentées dans les RFC 6707 et RFC 7337. Dans certains cas, l'interconnexion des CDN se fait à l'intérieur du protocole de communication déjà utilisé (in-band). C'est le cas des redirections HTTP. Dans d'autres cas, on utilise un protocole externe (out-of-band). Il faut également noter, pour comprendre la complexe combinaison d'interfaces de CDNI que, bien que les interfaces soient largement indépendantes, elles reposent sur des conventions communes, par exemple pour le nommage des ressources.

Parmi les détails creusés dans ce RFC 7336 sur les interfaces :

  • Une liste des éléments d'information qui peuvent être intéressants pour l'interface de journalisation, LI (Logging Interface). Conceptuellement, cette interface peut être vue simplement comme une copie des fichiers apache/access.log du CDN aval vers l'amont... Attention, le champ indiquant le nom de domaine demandé (VirtualHost dans Apache) peut être différent de l'original, s'il y a eu redirection HTTP.
  • Certains services de l'interface de communication de métadonnées (MI pour Metadata Interface) peuvent être assurés par le mécanisme de redirection. Par exemple, si le fournisseur de contenu veut limiter l'accès aux utilisateurs européens, il suffit que le CDN amont ne redirige pas vers le CDN américain, pour les requêtes de ce contenu à accès limité. (Le RFC note toutefois que cela manque de souplesse : par exemple, il y a peu de chances que le CDN aval ait une couverture géographique qui coïncide parfaitement avec les exigences de géo-limitation du fournisseur de contenu.)

La section 5 du RFC décrit plusieurs scénarios d'usage de CDNI quand il sera terminé. Par exemple, bien que le modèle de référence (et les exemples que j'ai cités) soient unidirectionnels (le CDN A délègue au CDN B et jamais le contraire), on pourra se servir de CDNI pour les CDN maillés, avec des graphes arbitraires entre les différents CDN.

Déléguer ses fonctions soulève évidemment tout un tas de questions, comme toute sous-traitance. Le CDN amont peut-il faire confiance au CDN aval pour servir le contenu correctement ? Les statistiques de trafic qu'il remonte sont-elles correctes ou bien modifiées dans l'intérêt exclusif du CDN aval ? La section 6 explore le problème de la confiance dans un monde de CDN connectés. Notons que le fournisseur de contenu a déjà aujourd'hui le même problème avec son opérateur CDN : dès qu'on sous-traite, la question de la confiance surgit. Mais CDNI rend les choses un peu plus compliquées : un fournisseur de contenu qui a signé avec l'opérateur de CDN amont peut ne pas être conscient que celui-ci a un accord avec l'opérateur CDN aval. Et si un opérateur CDN modifiait les fichiers avant de les envoyer ? Il existe évidemment des solutions techniques, comme la signature cryptographique des fichiers. Mais, fondamentalement, il faut une combinaison de confiance et de quelques vérifications (par exemple des sondages aléatoires faits par divers clients pour vérifier que le contenu est bien là, et bien conforme à ce qui est demandé).

En parlant de confiance et de sécurité, la section 7 se demande quelles sont les conséquences de l'interconnexion de CDN pour la vie privée (l'existence d'une section nommée Privacy considerations est récente dans les RFC et vient du RFC 6973). Un CDN est bien placé pour observer beaucoup de choses dans le comportement de l'utilisateur, par exemple à quels fichiers il accède, de mécanique_quantique_pour_les_nuls.epub à how_to_make_bombs.avi. L'utilisateur qui accède à un site Web ne sait typiquement pas si celui-ci utilise un CDN (cela se trouve relativement facilement mais tout le monde n'a pas les compétences ou le temps nécessaire). Il fait confiance au site Web, mais ne se rend pas compte qu'il fait également confiance à l'opérateur CDN (qui peut avoir une autre éthique, ou être soumis à d'autres lois : lorsqu'on visite http://www.elysee.fr/, on croit faire confiance à un organisme public français, alors qu'il est en fait servi par un CDN états-unien, soumis au Patriot Act).

Certaines fonctions de CDNI sont justement conçues pour faire circuler de l'information sur l'activité des utilisateurs, notamment l'interface de journalisation (LI). Il faudra donc s'assurer qu'elles disposent de protections appropriées.

Et, toujours sur la sécurité, la section 8 note également d'autres points délicats, qui s'ajoute aux questions de sécurité déjà existantes pour les CDN actuels :

  • Certaines exigences des fournisseurs de contenu (distribution limitée géorgraphiquement, ou bien limitée dans le temps) sont plus difficiles à satisfaire lorsqu'il y a interconnexion des CDN,
  • Par contre, les menottes numériques ne sont pas affectées par CDNI puisqu'elles reposent typiquement sur des mécanismes présents dans le contenu lui-même,
  • Les interfaces entre CDN doivent être protégées, contre l'écoute (cas des journaux d'activité dans la section précédente) mais aussi contre les modifications non autorisées (imaginez qu'un méchant modifie les contenus servis lorsqu'ils passent d'un CDN amont au CDN aval), même si l'interconnexion se fait en utilisant l'Internet public, non sécurisé.

Deux fournisseurs de solutions techniques, Cisco et Alcatel-Lucent, ont annoncé qu'ils travaillaient sur des prototypes d'interconnexion de CDN, utilisant le futur protocole qui sera la concrétisation de ce cadre.


Téléchargez le RFC 7336


L'article seul

RFC 7305: Report from the IAB Workshop on Internet Technology Adoption and Transition (ITAT)

Date de publication du RFC : Juillet 2014
Auteur(s) du RFC : E. Lear
Pour information
Première rédaction de cet article le 19 août 2014


En décembre 2013, à Cambridge, l'IAB a tenu un atelier sur l'adoption des nouvelles technologies dans l'Internet. Qu'est-ce qui fait que telle technologie réussit dans le monde réel et que telle autre reste éternellement sur le papier ? Sérieuse question pour l'IETF, qui a a normalisé aussi bien des succès fous que des échecs plus ou moins complets. (Par exemple, le déploiement de la grande œuvre de l'IETF, IPv6, est extrêmement lent.)

Ce RFC résume les contributions à l'atelier. Comme on s'en doute, il n'y a eu aucun consensus, à part sur l'importance d'étudier l'angle de l'économie, et sur la référence à Bitcoin, grande vedette de l'atelier et source de nombreux exemples. Attention, donc, ce RFC n'est pas une prise de position de l'IAB, mais le compte-rendu d'un colloque pluraliste, aussi bien dans ses participants que dans les opinions exprimées. (Le rôle de l'IAB n'est pas de faire des protocoles - c'est la tâche de l'IETF, sous la direction de l'IESG - mais de réfléchir sur le long terme et sur les questions les plus fondamentales.)

On représente souvent l'écosystème de l'Internet sous forme d'un sablier : le protocole standard d'interconnexion est forcément unique et occupe donc la « taille », le tuyau fin du sablier. Au contraire, les protocoles d'application, beaucoup plus nombreux, occupent le bulbe du haut, et les protocoles « physiques », pour lesquels il y a également un grand choix, sont le bulbe du bas. Dans la vision traditionnelle de l'Internet, la taille était IP.

Dans la biologie, c'est l'ATP qui joue ce rôle central, la brique de base sur laquelle tout le reste est bâti (papier de Meyer).

Aujourd'hui, en raison de l'ossification de l'Internet et de la prévalence de stupides middleboxes qui bloquent tout, la taille (ou faut-il l'appeler le cou ?) du sablier est plutôt HTTP... Il devient de plus en plus difficile pour un protocole de s'imposer, surtout s'il ne tourne pas sur HTTP. En prime, le poids de l'existant est bien plus important qu'aux débuts de l'Internet. Aujourd'hui, un nouveau protocole doit lutter contre des concurrents bien installés.

La section 2 de notre RFC résume les motivations de ce travail, et les travaux équivalents déjà réalisés. On constate souvent que des protocoles, développés soigneusement par l'IETF, ont peu ou pas de succès dans le monde réel et, quand ils se répandent, c'est à un rythme bien trop lent. Trois exemples sont cités par le RFC, IPv6 (RFC 2460), SCTP (RFC 4960) et DNSSEC (RFC 4034). Ce retard peut à son tour retarder d'autres déploiements. Ainsi, DNSSEC est indispensable à DANE (RFC 6698) et le déploiement trop lent de DNSSEC, goulet d'étranglement, affecte donc DANE. Par contre, si les protocoles nouveaux ont du mal, les protocoles existants continuent à évoluer (le RFC cite SMTP et IMAP, qui peuvent être vus comme des réfutations de la théorie comme quoi « HTTP est le nouvel IP, la taille du sablier »).

Un excellent RFC avait déjà étudié les causes du succès ou de l'échec des protocoles, le RFC 5218. Une conséquence de ce RFC 5218 est l'importance plus grande désormais donnée aux facteurs de réussite. Faire un bon protocole ne suffit plus. Les groupes de travail de l'IETF doivent désormais aussi réfléchir à la valeur ajoutée de leurs propositions : le nouveau protocole apporte-t-il suffisamment pour surmonter les barrières situées devant l'adoption ?

Ces barrières étant largement financières, il n'est pas étonnant que plusieurs des papiers présentés à l'atelier portaient sur l'économie (section 3). Le RFC en résume quelques uns. D'abord, la théorie de Weber, S., Guerin, R., et J. Oliveira, sur le couplage. Peut-on augmenter les chances de succès d'un protocole en le livrant avec d'autres ? Ou, au contraire, le couplage va-t-il ralentir le succès ? Comme cité précédemment, DANE dépend de DNSSEC. Cela simplifie son développement, permettant de s'appuyer sur les propriétés de sécurité de DNSSEC. Mais, du point de vue économique, cela fait dépendre DANE du succès de DNSSEC. Le couplage peut aider quand une technologie à succès en tire une autre, et ralentir si une technologie dépend d'une autre.

Autre exemple, très discuté à l'atelier (et c'est une nouveauté à l'IETF, puisque ce système a été développé en dehors de celle-ci), le succès de Bitcoin. Dans son papier, R. Boehme suggère que les protocoles Internet s'inspirent de Bitcoin, exemple de grand succès (section 3.2 de notre RFC). Bitcoin n'a pas eu la partie facile : des médias hostiles (parfois au point de la propagande, comme dans le mensonge souvent répété comme quoi Bitcoin était une pyramide de Ponzi), des incertitudes juridiques (est-ce bien légal ?), des failles techniques (immédiatement exploitées par des voleurs), plusieurs tentatives de « monnaies Internet » avaient déjà été des échecs, des attaques par des spéculateurs visant le gain à court terme, même au prix de l'existence même du système. Mais Bitcoin a survécu à ces campagnes de presse et à ces problèmes techniques et de sécurité. Selon l'auteur, les raisons principales sont :

  • Un mécanisme de récompense des premiers qui adoptent le système. Au début de Bitcoin, miner (créer de nouveaux bitcoins) est relativement facile et cela se durcit par la suite. Les plus difficiles à convaincre, les premiers adoptants, sont donc récompensés davantage, ce qui est logique et efficace. (J'ajoute personnellement que c'est juste : il est normal que ceux qui ont pris des risques au début reçoivent plus que ceux qui attendaient passivement.)
  • Bitcoin ne vit pas dans son coin, isolé. Dès le début, des mécanismes de conversion ont été mis en place de et vers les monnaies d'État. Ainsi, adopter Bitcoin ne signifiait pas s'enfermer dans un monde à part. Un autre exemple, cité par le RFC, est le succès du courrier électronique : dès le début, le courrier Internet a eu des passerelles de et vers les autres systèmes de courrier. Autrement, il n'aurait pas été choisi.
  • Les bitcoins ont une valeur pour leurs possesseurs, ce n'est pas juste pour le bien de l'humanité qu'on demande aux utilisateurs d'adopter la nouvelle technologie : ils y trouvent un intérêt. (Une remarque personnelle : les discussions à l'atelier supposaient acquis un point de vue égoïste, où les gens n'agissent qu'en fonction d'un intérêt personnel à court terme. Le problème serait très différent si on se plaçait dans une perspective plus volontariste, où on considère que les humains peuvent changer leur mentalité.)

Bref, Bitcoin fournit des motivations à ses adopteurs. (Un problème bien connu des militants pro-IPv6 : lorsqu'on suggère aux gens de migrer vers IPv6, la question est souvent « qu'est-ce que ça m'apporte, à moi ? », et elle n'a guère de réponse.)

Troisième étude de cas, le déploiement de DNSSEC (section 3.3) via le récit de A. Eklund Lowinder et P. Wallstrom sur le déploiement de cette technique en Suède, à commencer par le TLD .se. Le travail d'IIS pour encourager DNSSEC a pris la forme d'une contribution au financement d'OpenDNSSEC (pour abaisser les barrières techniques), et d'incitations financières (auprès des bureaux d'enregistrement).

Une des conclusions de cette partie de l'atelier était qu'il faut éviter d'accrocher une technologie exclusivement à une autre. Le logiciel privateur Skype a été cité comme exemple : il teste plusieurs transports disponibles et choisit celui qui marche. De même, lier une application à SCTP serait probablement une erreur : si SCTP ne réussit pas à se répandre, cette application serait fichue). Il faudrait plutôt essayer plusieurs transports et garder le premier qui marche, un peu comme le fait l'algorithme des globes oculaires heureux dans le RFC 6555.

Et puisqu'on parlait d'économie, il y a eu évidemment des discussions sur le modèles de prix, comme suite au papier de S. Sen. Par exemple, certains protocoles pourraient bénéficier d'un prix dépendant de l'heure (pour encourager le trafic à se déplacer vers les heures creuses).

Ah, une question qui est dans la section 5 mais qui aurait eu sa place dans celle sur l'économie : celle des brevets. Leurs effets néfastes sont bien connus. Le papier de E. Lear et D. Mohlenhoff décrit leurs relations avec la normalisation. Le plus gros problème identifié est celui des « brevets sous-marins », brevets que l'IETF ne connait pas... jusqu'au moment où il est trop tard.

Mais l'économie ne peut pas tout résoudre. Les choix se font aussi, mais si ce n'est pas la seule motivation, sur la qualité technique. De ce point de vue-là, pour qu'un protocole réussisse, il faut aussi faire en sorte qu'il soit le « meilleur » possible. Par exemple, est-ce que le processus de normalisation de l'Internet est suffisamment bien connecté au monde de la recherche, où s'élaborent les idées du futur ? Normalement, l'IETF ne normalise que des technologies bien maîtrisées. L'interaction avec la recherche se fait via l'IRTF.

Les chercheurs suggèrent parfois que l'architecture actuelle de l'Internet n'est plus adaptée aux défis futurs, et qu'il faudrait la changer, par exemple dans la direction du Lowest Common Denominator Networking, idée qui a apparemment été mal reçue à l'atelier.

Un atelier n'est pas complet sans une rubrique « Divers » (section 6) et deux autres points ont donc été abordés. D'abord, la résilience de l'Internet, et notamment la sécurité du routage. Le papier d'A. Robachevsky l'abordait en partant de l'éculée référence à la tragédie des terres communales. L'Internet est composé d'un grand nombre de réseaux distincts, sans administration centrale (ce qui est une bonne chose). La tentation peut donc être forte de se servir des communs (comme la table de routage globale) sans souci de leur pérennité, sans gestion collective.

Et un deuxième point « Divers » concernait TLS. TLS est très largement adopté et ne souffre pas, a priori, du syndrome du protocole qu'on n'arrive pas à déployer. Mais la très grande majorité des clients et serveurs existants utilisent des vieilles versions du protocole TLS, ayant des vulnérabilités connues (comme Beast). La version la plus récente de TLS, la 1.2, est normalisée dans le RFC 5246. Comment faire en sorte qu'elle soit déployée partout ? Et le problème ne concerne pas que le protocole lui-même mais aussi les algorithmes de cryptographie utilisés. (Au cours de l'atelier, il a été noté qu'une grande partie du trafic est toujours chiffrée avec Triple DES, algorithme aux faiblesses connues.)

Maintenant, les actions (section 7). La conclusion de ce RFC reconnait l'importance de regarder le succès des systèmes comme Bitcoin, mentionné pour la première fois dans un RFC, et un exemple pour tout nouveau système. Autrement, l'idée la plus intéressante me semble être celle de pousser la collaboration avec le monde académique, par exemple en enrôlant des étudiants pour relire et critiquer les documents IETF. Cela fournirait à ces étudiants une excellente occasion d'apprendre, et à l'IETF plein de regards neufs.


Téléchargez le RFC 7305


L'article seul

RFC 7337: Content Distribution Network Interconnection (CDNI) Requirements

Date de publication du RFC : Août 2014
Auteur(s) du RFC : K. Leung (Cisco), Y. Lee (Comcast)
Pour information
Réalisé dans le cadre du groupe de travail IETF cdni
Première rédaction de cet article le 18 août 2014


Le projet IETF CDNI (Content Delivery Network Interconnection) vise à permettre l'interconnexion de CDN, ces réseaux de serveurs répartis dans le monde qui servent à amortir la charge des serveurs Internet les plus populaires. CDNI a été expliqué dans le RFC 6707 et trois études de cas ont fait l'objet du RFC 6770. Ce troisième RFC du projet décrit les exigences formelles, le cahier des charges du projet. (Le cadre général de la solution technique adoptée est dans le RFC 7336.)

Le projet est important car, aujourd'hui, les CDN ne coopèrent pas, en partie en raison du manque d'interfaces standards. Si un CDN très présent en Amérique veut s'associer avec un autre CDN fort en Europe, à la grande joie de leurs clients respectifs, qui auront ainsi un meilleur service dans les deux cas, ils doivent développer un système ad hoc. Le but de CDNI est de développer cette interface standard (RFC 7336), de manière à ce que plusieurs CDN puissent coopérer et apparaître à l'utilisateur comme un seul service. Dans le futur, une fois le projet complété, le CDN d'origine (« CDN amont ») pourra faire en sorte que le CDN qui l'aide (« CDN aval ») ait accès au même contenu et puisse le servir lui-même aux clients.

Les exigences listées par ce cahier des charges sont classées par priorité : « haute » signifie que cette exigence est impérative, même si elle est compliquée à réaliser, « moyenne » que l'exigence est importante, qu'elle doit être satisfaite sauf si, par sa complexité, elle entraîne un retard dans le projet et, enfin, « basse » est utilisé pour les exigences certes utiles mais pas nécessaires au projet.

Les exigences sont rangées selon l'interface à laquelle elles s'appliquent. Une interface (RFC 7336) est un ensemble de fonctions du CDN, qu'on peut appeler en utilisant des mécanismes normalisés, et qui correspondent à un ensemble de services proches. Par exemple, LI (Logging Interface) regroupe les services de journalisation, permettant à un CDN amont d'avoir des informations sur l'activité d'un CDN aval associé.

Je ne vais pas ici recopier les nombreuses exigences, me focalisant sur celles de niveau élevé, donc impératives à satisfaire.

D'abord, en section 3, les exigences générales, indépendantes de l'interface. La solution ne doit évidemment pas nécessiter de changer les clients (exigence GEN-2), par exemple les navigateurs Web. Elle ne doit pas nécessiter que le fournisseur de contenu change son système de publication (GEN-3) : si celui-ci permet de publier dans un CDN, il doit permettre de profiter de l'interconnexion. Elle doit être assez abstraite pour que chaque CDN soit une « boîte noire » pour les autres, sans avoir besoin de publier de l'information interne. Elle doit marcher au moins lorsque la délivrance au client est faite en HTTP (exigence GEN-5, il existe d'autres protocoles - voir GEN-7 - mais moins cruciaux), et elle doit éviter de créer des boucles entre CDN et elle doit fonctionner même quand les références à une tierce partie sont cassées (exigence GEN-12), par exemple à cause du NAT ou du split DNS.

Suivent en section 4 les exigences pour la CI. CI (Control Interface) est l'interface qui contrôle les autres interfaces, par exemple pour les opérations de démarrage (ce sera là qu'on indiquera le serveur de statistiques auquel il faudra indiquer l'ampleur du trafic, par exemple). Elle doit permettre au CDN amont de demander le nettoyage (la destruction de contenu, exigence CI-1), et elle doit fournir un mécanisme de rétroaction par lequel le CDN aval informe le CDN amont de ce qu'il a fait (CI-4).

En section 5, la RI (Request routing indirection Interface) est l'interface vers le système de routage des requêtes. Elle doit fonctionner rapidement quelle que soit la taille du contenu (exigence RI-1) ce qui veut dire qu'il faut un mécanisme de redirection ultra-léger pour les objets de petite taille (ceux où le temps de redirection risque de dépasser le temps de transfert des données), et qu'il faut pouvoir choisir le compromis entre fraîcheur des données et rapidité. Pour les gros objets (exigence RI-2) où le temps de transfert sera long, il faut bien choisir le CDN d'où il sera servi et il faut donc que la solution permette un choix précis, lié aux caractéristiques de la requête. Autrement dit, un mode où on passe du temps à sélectionner la source des données, pour que le transfert aille ensuite plus vite.

Il faut aussi que cette redirection puisse être récursive (exigence RI-3), c'est-à-dire que la cible d'une redirection va elle-même suivre les éventuelles nouvelles redirections, et itérative (RI-4), c'est-à-dire que l'initiateur suive lui même les redirections multiples. Cela implique que le CDN aval reçoive du CDN amont toutes les informations nécessaires (exigence RI-8), comme l'origine géographique de la requête, les en-têtes HTTP, etc, et à l'inverse que le CDN aval transmette la réponse complète dans le cas d'une redirection (l'URI complet en HTTP, exigence RI-10).

En section 6, la FCI (Footprint & Capabilities Interface). Elle permet l'échange d'informations entre CDN, de manière à permettre le routage des requêtes (leur transmission au CDN le plus approprié) par l'interface RI. Si on compare RRI (Request Routing Interface, une méta-interface qui regroupe FCI et RI) à IP, FCI est l'équivalent des protocoles d'échange de routes comme OSPF et RI est l'équivalent du lookup dans une table de routage.

La FCI doit au minimum permettre de communiquer au CDN amont que le CDN aval est prêt (exigence FCI-1). Idéalement (mais ces exigences sont seulement au niveau moyen, donc pas indispensables), il faudrait aussi qu'il puisse communiquer des méta-informations comme les formats et protocoles qu'il gère, son extension géographique, les protocoles de redirection, les capacités de journalisation, etc.

En section 7, l'interface MI (Metadata Interface), qui permet l'échange de métadonnées sur les contenus servis, comme les restrictions géographiques, les durées de vie des contenus, les limitations d'accès (par exemple, aux abonnés)... Pour cette interface, l'exigence de base (MI-1) est de permettre l'envoi d'informations depuis le CDN amont. Parmi ces informations, il y a évidemment l'endroit d'où le CDN aval doit tirer le contenu (exigences MI-5 et MI-6). Il faut pouvoir ajouter des métadonnées dans le CDN aval (exigence MI-7) et en retirer (MI-8). La granularité de ces métadonnées doit être au niveau d'un objet (MI-9) mais il faut aussi pouvoir regrouper les objets, de manière à gérer ces métadonnées plus facilement (MI-10), avec un système d'héritage entre les groupes d'objets (MI-11).

L'industrie du contenu étant ce qu'elle est, il n'est pas étonnant qu'une longue exigence MI-13 décrive toutes les conditions d'accès au contenu, filtrage selon les pays, selon les adresses IP, dans le temps, etc.

Enfin, en section 8, la LI (Logging Interface), qui permet de transmettre les informations sur l'activité du CDN, de manière à avoir des journaux d'activité. Le transports desinformations de journalisation doit être fiable (exigence LI-1, pas question de se contenter de syslog sur UDP), doit être exhaustif (le CDN amont veut connaître tous les téléchargements faits à partir du CDN aval, exigence LI-2), le transferts des journaux doit pouvoir se faire en batch (LI-4), et utiliser un format standard (LI-6) et un transport standard (LI-7).

Il n'y a plus qu'à normaliser la sécurité (section 9). Bien sûr, la première exigence, SEC-1, est que toutes les opérations entre CDN soient sécurisables, même quand elles s'effectuent au-dessus de l'Internet normal, non sécurisé. Il faut donc pouvoir fournir authentification, intégrité, et confidentialité. Mais il faut aussi se défendre contre les attaques par déni de service, dont les CDN sont souvent victimes (SEC-2).


Téléchargez le RFC 7337


L'article seul

RFC 7328: Writing I-Ds and RFCs using Pandoc and a bit of XML

Date de publication du RFC : Août 2014
Auteur(s) du RFC : R. Gieben (Google)
Pour information
Première rédaction de cet article le 13 août 2014


Vous voulez écrire un RFC ? Il faut commencer par faire un Internet-Draft (I-D) et il existe pour cela deux formats, en XML ou bien en Word. Ce RFC présente une troisième solution, utilisant Markdown, ou plutôt sa variante définie par Pandoc.

Le format d'écriture de RFC le plus répandu est sans doute XML, tel que décrit dans le RFC 2629. Le format Word est dans le RFC 5385. (Il existe aussi le format historique, utilisant nroff mais je ne suis pas sûr qu'il soit encore accepté aujourd'hui.) Certaines personnes trouvent que les tags XML les distraient pendant qu'ils écrivent leur Internet-Draft (I-D) et ils préfèrent donc utiliser un autre format « texte », avec les marquages de Markdown, jugés moins intrusifs. Markdown est très populaire et est utilisé à plein d'endroits différents (par exemple, dans les formulaires du système de suivi de bogues de GitHub). Markdown a plein de dialectes et de variantes et celle utilisée ici est celle du logiciel Pandoc, un sur-ensemble de Markdown. (Par abus de langage, j'écris ensuite « Pandoc » pour désigner ce format.)

(Au passage, vous pouvez regarder la page officielle de Markdown et celle de Pandoc.)

Le document en Pandoc peut ensuite être traduit dans d'autres formats, HTML, EPUB, DocBook, etc, d'où on peut ensuite tirer le futur RFC dans un format de publication officiel (comme le texte seul). L'outil Pandoc2rfc convertit le Pandoc en Docbook, qui est ensuite traduit en XML-RFC2629, puis ensuite dans les différents formats de publication souhaités (on passe donc d'un texte quasi-brut avec instructions de formatage, à XML, pour revenir à du texte brut...) Dans le futur, peut-être existera-t-il un chemin plus rapide, allant directement du Pandoc au RFC final. En attendant, ce chemin impose quelques contraintes, notamment qu'on ne peut pas complètement éviter d'éditer du XML. L'auteur doit éditer quatre documents :

  • Un document Markdown abstract.mkd contenant le résumé,
  • Un document Markdown middle.mkd contenant le gros du RFC,
  • Un document Markdown facultatif back.mkd contenant les annexes,
  • Un document XML template.xml contenant auteurs et références bibliographiques.

Un exemple du gabarit template.xml figure dans la section 2 de notre RFC.

Pour installer l'outil Pandoc2rfc, vous allez avoir besoin du processeur XSLT xsltproc (la transformation du Docbook en XML-RFC2629 est faite avec XSLT) et bien sûr de Pandoc lui-même.

Pandoc2rfc contient un script shell qui fait les transformations nécessaires (voir la section 3 du RFC).

Pour apprendre la syntaxe de Pandoc, il faut regarder le guide. Pandoc2rfc traduit via xml2rfc (l'outil du RFC 2629) et met en correspondance les concepts Markdown avec ceux de XML-RFC2629. Par exemple, une énumération avec * va être traduite en une liste (<list> XML) style="symbols" et une énumération avec des numéros (comme "1.", "2.", etc) va être traduite en style="numbers" (RFC 2629, section 2.3.1.2). La section 4 de notre RFC donne une liste complète des équivalences Pandoc<->XML, résumées sous forme d'un tableau dans l'annexe B.

Il est d'ailleurs difficile de faire du Pandoc2rfc sans connaître xml2rfc. Par exemple, pour afficher une table des matières, il faut inclure l'invocation xml2rfc <?rfc toc="yes"?>.

La section 5 liste quelques limitations de Pandoc2rfc par rapport à Pandoc : pas de gestion des index, les commentaires doivent être faits avec des commentaires HTML dans le source Pandoc, les citations se font avec les références XML, le système de citation de Pandoc n'est pas utilisé, et enfin les auteurs doivent se résigner à voir apparaître des erreurs de xml2rfc, la traduction Pandoc vers Docbook ne gère pas toutes les erreurs possibles. De mon expérience, il faut pas mal bricoler pour faire marcher le tout. Écrire des RFC en Markdown est sympa mais on n'y arrive pas en cinq minutes.

Si vous voulez un exemple concret, la distribution de Pandoc2rfc contient un répertoire test/ avec un exemple de RFC bidon utilisant toutes les fonctions de Pandoc2rfc. J'ai un peu modifié le Makefile pour faire des versions texte, XML et HTML du RFC :

% make all
pandoc2rfc -t template.xml back.mkd middle.mkd
pandoc2rfc -H -t template.xml back.mkd middle.mkd
pandoc2rfc -X -t template.xml back.mkd middle.mkd

Et cela produit les trois versions, à partir du source Markdown (essentiellement en middle.mkd) et du gabarit template.xml.


Téléchargez le RFC 7328


L'article seul

RFC 7194: Default Port for IRC via TLS/SSL

Date de publication du RFC : Août 2014
Auteur(s) du RFC : Richard Hartmann
Pour information
Première rédaction de cet article le 8 août 2014


Le protocole de messagerie instantanée IRC est toujours très utilisé, malgré la concurrence de XMPP. Il n'existait pas de port « officiel » pour les connexions IRC sécurisées par TLS, ce qui est fait avec ce RFC, qui décrit l'usage, déjà très répandu, du port 6697.

IRC est officiellement standardisé dans les RFC 1459, RFC 2810, RFC 2811, RFC 2812 et RFC 2813 mais il ne faut pas s'y fier : la pratique réelle est loin de ces RFC, qu'il faut plutôt utiliser comme point de départ d'une description du protocole que comme une « Bible » définitive. IRC avait depuis longtemps deux ports standards, 194 pour le trafic en clair et 994 pour le trafic chiffré avec TLS. Ces deux ports sont inférieurs à 1 024 et nécessitent donc que le serveur soit lancé par root sur une machine Unix. Comme ce n'est pas toujours possible, ou souhaitable, en pratique, les serveurs IRC écoutent en général sur 6667 en clair et 6697 en chiffré. Le port 6667 a été documenté pour cet usage mais ce n'était pas encore le cas du 6697. Les clients IRC n'avaient donc pas de moyen standard fiable de découvrir si un serveur gérait les connexions IRC sur TLS.

La section 2 du RFC décrit le fonctionnement d'IRC sur TLS : le client se connecte à un serveur IRC. Une fois la connexion établie, la négociation TLS a lieu. Le serveur est censé présenter un certificat d'une autorité reconnue, dont le nom est le nom du serveur. Le client peut s'authentifier, aussi comme décrit dans la documentation d'OFTC . Une fois la négociation terminée avec succès, les identités vérifiées et tout, le trafic passe alors par cette connexion protégée.

Le nouveau numéro est désormais dans le registre IANA :

ircs-u             6697        tcp    Internet Relay Chat via    TLS/SSL               2014-02-11

À noter que ce mécanisme ne protège que la liaison client<->serveur. IRC a aussi des communications serveur<->serveur (coordination non standardisée entre les différentes machines qui mettent en œuvre un service IRC) qui ne sont pas traitées ici, même si le RFC recommande aux opérateurs IRC de systématiquement chiffrer le trafic entre machines d'un même service. À noter aussi qu'IRC ne fait pas de liaison directe en pair à pair. Quand Alice et Bob se parlent en IRC, cela passe toujours par un serveur et, même si TLS sécurise la connexion avec le serveur, cela ne protège pas Alice et Bob d'un espionnage par le serveur (par exemple si celui-ci participe au programme PRISM), comme le rappelle la section 3 du RFC. Le chiffrement qui n'est pas de bout en bout a des pouvoirs de protection limités ! Seul OTR fournirait une protection de bout en bout (mais nécessite un peu plus d'action de la part d'Alice et Bob alors que TLS est largement invisible).

L'annexe A du RFC rappelle qu'en 2010, une étude avait montré que dix des vingt principaux services IRC géraient TLS.

La plupart des grands serveurs IRC aujourd'hui gèrent TLS. Parmi les exceptions, j'ai trouvé ircnet.nerim.fr mais aussi le serveur IRC du W3C qui n'est hélas accessible en TLS que par les membres du W3C. Avec un serveur qui gère TLS, et avec Pidgin comme client, il faut cocher la case Use SSL [sic] mais aussi changer manuellement le port, pour 6697 :

On verra alors des connexions TLS :

(09:00:20) gandalf.geeknode.org: (notice) *** You are connected to gandalf.geeknode.org with TLSv1-AES256-SHA-256bits

À noter que Geeknode est signé par CAcert comme beaucoup de serveurs IRC. Freenode, par contre, est signé par Gandi :

% openssl s_client -connect chat.freenode.net:6697
CONNECTED(00000003)
depth=1 C = FR, O = GANDI SAS, CN = Gandi Standard SSL CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/OU=Domain Control Validated/OU=Gandi Standard Wildcard SSL/CN=*.freenode.net
   i:/C=FR/O=GANDI SAS/CN=Gandi Standard SSL CA
 1 s:/C=FR/O=GANDI SAS/CN=Gandi Standard SSL CA
   i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
---
...

Téléchargez le RFC 7194


L'article seul

delv, le futur outil principal de déboguage de DNSSEC ?

Première rédaction de cet article le 26 juillet 2014


La version 9.10 de BIND vient avec un nouvel outil de déboguage en ligne de commande, delv. Qu'apporte-t-il par rapport à dig ? C'est surtout pour ce qui concerne DNSSEC qu'il est utile.

L'outil de base de celui qui débogue un problème DNS, l'équivalent de ce que sont ping et traceroute pour l'ingénieur réseaux, c'est dig. Cet outil permet de récupérer des données DNS et de les afficher. Avec le DNS traditionnel, on n'avait pas besoin de plus. Mais avec DNSSEC, un problème supplémentaire survient : les données obtenues sont-elles vérifiées cryptographiquement ? dig avait bien une option +sigchase pour tester cela mais, très boguée, elle est restée peu connue. On n'avait donc pas d'outil simple, en ligne de commande, pour valider du DNSSEC. On a bien sûr drill (livré avec ldns) mais son option -S est très bavarde.

Depuis la version 9.10 de BIND, est apparue avec ce logiciel un nouvel outil, nommé delv. delv permet de faire la même chose que dig (en moins bavard par défaut) :

% delv  www.ssi.gouv.fr
; unsigned answer
www.ssi.gouv.fr.	21600	IN	A	86.65.182.120

% delv -t mx  laposte.net
; unsigned answer
laposte.net.		600	IN	MX	10 smtp4.laposte.net.

Mais c'est surtout lorsque le domaine est signé que delv est utile. (Autrement, comme vous l'avez vu plus haut, il affiche un triste unsigned answer.) Testons avec un nom correctement signé :

% delv www.bortzmeyer.org
; fully validated
www.bortzmeyer.org.	52712	IN	A	204.62.14.153
www.bortzmeyer.org.	52712	IN	RRSIG	A 8 3 86400 20140813162126 20140724102037 37573 bortzmeyer.org. ZU9fgjc34O2xfBoN1crbGpMsw8Ov56Jex/6yuSHiAEUFSYTK1H4kBrcK H6MIoeUPrA6/4gmtPTBrc6+KWv765ioWgvHiGPPa8v85T2w0zLsX24NT 4Zz0XVsfybu1re/Nr6V//BOnVF3cZ2hFvdI1Yp9EiKLnRFfPrYX316Hx aJI=

Cette fois, il a procédé à une validation DNSSEC de la réponse (correcte, dans ce cas, fully validated).

Vous allez le dire « mais il suffit d'utiliser un résolveur DNS validant et on sait, via le bit AD (Authentic Data) que les données sont correctement signées ». Mais delv donne des informations supplémentaires. Par exemple, si le domaine est signé mais pointe vers un domaine non-signé :

% delv www.paypal.co.uk           
; fully validated
www.paypal.co.uk.	3600	IN	CNAME	www.intl-paypal.com.edgekey.net.
www.paypal.co.uk.	3600	IN	RRSIG	CNAME 5 4 3600 20140816050243 20140717044122 22776 paypal.co.uk. TU8EubeTmR0NCU+bLlhWPTJL91fUkoExM/86ZIL6qr1kJU7g69lqRzLJ N33TzZdIOgj7g1O4eEyUUgBKxe8GpH5dLisXlHhi64aluT4DkL3PwqDi W9enJobC660aPSp0vebasOnJlCZ2rRwKKqmWUiRfXhhkKmu1U1l4IOMV wmY=

; unsigned answer
www.intl-paypal.com.edgekey.net. 120 IN	CNAME	e493.a.akamaiedge.net.
e493.a.akamaiedge.net.	20	IN	A	23.58.178.37

Dans ce cas (aucun CDN ne gère aujourd'hui DNSSEC, hélas), delv indique bien quelle partie de la réponse est signée et laquelle ne l'est pas.

Et en cas de problème ? Si on teste avec des domaines délibérement cassés :

% delv -t mx servfail.nl 
;; resolution failed: failure

Eh oui, on utilise un résolveur validant, il ne nous donne donc pas les données liées à ce domaine. Il faut donc (paradoxalement !) utiliser un résolveur non-validant ou bien, tout simplement, ajouter l'option +cd, Checking Disabled, à delv :

% delv +cd -t mx servfail.nl
;; validating servfail.nl/DNSKEY: verify failed due to bad signature (keyid=25594): RRSIG has expired
;; validating servfail.nl/DNSKEY: no valid signature found (DS)
;; no valid RRSIG resolving 'servfail.nl/DNSKEY/IN': 127.0.0.1#53
;;   validating R6K26LDO0GS7N66JPQALLM0JIDU6PHML.servfail.nl/NSEC3: bad cache hit (servfail.nl/DNSKEY)
;; broken trust chain resolving 'servfail.nl/MX/IN': 127.0.0.1#53
;; resolution failed: broken trust chain

Voilà, on connait désormais la raison du problème, l'enregistrement DNSKEY de servfail.nl a une signature expirée. Avec un autre domaine, comportant une autre erreur (une signature délibérement modifiée) :

% delv +cd -t mx dnssec-failed.org
;; validating dnssec-failed.org/DNSKEY: no valid signature found (DS)
;; no valid RRSIG resolving 'dnssec-failed.org/DNSKEY/IN': 127.0.0.1#53
;;   validating dnssec-failed.org/NSEC: bad cache hit (dnssec-failed.org/DNSKEY)
;; broken trust chain resolving 'dnssec-failed.org/MX/IN': 127.0.0.1#53
;; resolution failed: broken trust chain

Et, ici, avec une date de signature dans le futur :

% delv +cd -t aaaa futuredate-aaaa.test.dnssec-tools.org
;; validating futuredate-aaaa.test.dnssec-tools.org/AAAA: verify failed due to bad signature (keyid=19442): RRSIG validity period has not begun
;; validating futuredate-aaaa.test.dnssec-tools.org/AAAA: no valid signature found
;; RRSIG validity period has not begun resolving 'futuredate-aaaa.test.dnssec-tools.org/AAAA/IN': 127.0.0.1#53
;; resolution failed: RRSIG validity period has not begun

Comme vous avez vu, delv est parfait pour du premier déboguage, donc, quitte à utiliser des outils plus complexes par la suite. Au fur et à mesure que les versions récentes de BIND se diffuseront, et que DNSSEC sera plus courant, dig sera sans doute souvent remplacé par delv.

Voir aussi l'article « Debugging dnssec with delv ».


L'article seul

RFC 7301: Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension

Date de publication du RFC : Juillet 2014
Auteur(s) du RFC : S. Friedl (Cisco Systems), A. Popov (Microsoft), A. Langley (Google), E. Stephan (Orange)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 24 juillet 2014


On le sait, désormais, tout l'Internet tourne sur le port 443 (et aussi sur 80 mais de moins en moins, en raison des révélations de Snowden). C'est en effet l'un des rares ports dont on peut être sûr qu'il est à peu près tout le temps ouvert, même sur les réseaux les plus affreux genre hôtel ou aéroport. En prime, les communications sur ce port sont chiffrées avec TLS (RFC 5246). Si seul HTTP se servait de ce port, cela marcherait mais de plus en plus de protocoles applicatifs se bousculent pour l'utiliser. Comment leur permettre de partager le port 443 sans émeutes ? En ajoutant une extension à TLS qui permet d'indiquer le protocole applicatif qui va utiliser ce port, une fois la session TLS démarrée.

Cette extension avait surtout été conçue pour les besoins de HTTP/2 (autrefois nommée SPDY), version qui est loin d'être terminée. ALPN (Application-Layer Protocol Negotiation), objet de notre RFC, sert à indiquer la version de HTTP, et aussi désigner les services qui vont tourner au dessus de HTTP, comme WebRTC. Mais elle pourra servir à d'autres protocoles. Comme, par exemple, faire coexister IMAP et HTTP sur le même port. Vous allez peut-être me dire « mais pourquoi ne pas faire cela dans une couche entre TLS et l'application, de manière à éviter de complexifier TLS ? » et le RFC vous répond que le but est de performance (éviter les allers-retours entre client et serveur) et de souplesse (choisir un certificat différent selon le protocole d'application).

À noter qu'il s'agit d'une extension TLS : si on veut faire coexister sur un même port des applications TLS comme HTTP et non-TLS comme SSH, il faut une autre solution (par exemple sslh).

Comment fonctionne ALPN (section 3 de notre RFC) ? Le client envoie la liste des applications qu'il gère dans son message TLS ClientHello (section 7.4.1.2 du RFC 5246), le serveur en choisit une et la renvoie dans son ServerHello. Tout se fait donc dans la poignée de mains de TLS, sans imposer d'allers-retours supplémentaires. Si le client ne veut qu'une seule application, il envoie un message avec une liste ne comportant que cette application.

L'extension se nomme application_layer_protocol_negotiation et a le numéro 16 (désormais dans le registre IANA). Elle a un contenu (de type ProtocolNameList) qui contient la liste des protocoles applicatifs, en ordre de préférence décroissante. En termes TLS, cela s'écrit :


enum {
       application_layer_protocol_negotiation(16), (65535)
   } ExtensionType;

opaque ProtocolName<1..2^8-1>;

struct {
       ProtocolName protocol_name_list<2..2^16-1>
   } ProtocolNameList;

Les valeurs possibles pour les protocoles applicatifs sont dans un registre IANA. Des nouveaux protocoles pourront être ajoutés après un examen par un expert (RFC 5226, section 4.1). Pour l'instant, on y trouve le HTTP actuel, 1.1 (RFC 7230) et les variantes de SPDY. HTTP/2 sera placé dans ce registre après sa normalisation.

Cette extension sert aussi bien au client (liste des applications que le client veut utiliser) qu'au serveur (application - au singulier - choisie, après avoir ignoré celles que le serveur ne connait pas). Si le serveur ne met pas cette extension dans sa réponse, c'est ce qu'est un vieux serveur, qui ne la connait pas. S'il répond avec une alerte no_application_protocol, c'est que l'intersection de la liste du client avec celle configurée dans le serveur est hélas vide.

Si vous utilisez une application qui peut attirer l'attention de la NSA, attention : la négociation ALPN est en clair, avant que le chiffrement ne démarre (sections 4 et 5). C'était un des points les plus controversés lors des discussions à l'IETF mais cela a été décidé pour être cohérent avec le modèle d'extension de TLS. Si vous tenez à cacher le protocole applicatif utilisé, vous devez faire une renégociation une fois le chiffrement commencé.

Des mises en œuvre de cette extension ? C'est apparemment fait pour NSS (voir #996250 et #959664). Et Wireshark va pouvoir le décoder. Pour les autres, voir le tableau synthétique.


Téléchargez le RFC 7301


L'article seul

RFC 7290: Test Plan and Results for Advancing RFC 2680 on the Standards Track

Date de publication du RFC : Juillet 2014
Auteur(s) du RFC : L. Ciavattone (AT&T Labs), R. Geib (Deutsche Telekom), A. Morton (AT&T Labs), M. Wieser (Technical University Darmstadt)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 23 juillet 2014


Le RFC 2680 normalise une métrique utile à l'analyse des performances des réseaux informatiques, le taux de perte de paquets (mesuré sur un aller simple). Pour faire avancer ce RFC sur le chemin des normes, pour qu'il accède au statut de « norme tout court », il faut une évaluation : la description du RFC est-elle claire et complète ? Les mises en œuvre logicielles sont-elles équivalentes ? C'est ce travail d'évaluation que ce nouveau RFC documente.

Évaluer la norme d'une métrique est un peu plus compliqué qu'évaluer un protocole. La méthode traditionnelle à l'IETF pour évaluer un protocole est de regarder si deux mises en œuvre différentes peuvent interopérer. Pour une métrique, ce n'est pas possible et on utilise donc une autre méthode, regarder si deux mises en œuvre différentes d'une métrique, confrontées au même trafic, produisent des résultats compatibles (pas forcément identiques : les mesures ne sont jamais parfaitement précises).

Le groupe de travail IPPM de l'IETF travaille depuis longtemps sur ce problème d'avancement des métriques sur le chemin des normes. Les principes de l'évaluation d'une métrique ont été décrits dans le RFC 6576 et ont déjà été mis en pratique dans le RFC 6808, pour la métrique « délai d'acheminement d'un paquet (en aller simple) ». L'idée de base est que, si deux mesures, par des mises en œuvre différentes, donnent des résultats suffisamment proches, c'est que la métrique était correctement définie, claire et sans ambiguité. Cette évaluation permet aussi de voir quelles options de la métrique n'ont jamais été implémentées, et sont donc candidates à être supprimées dans une future révision de la norme.

En suivant le même plan que le RFC 6808, voici donc l'évaluation du RFC 2680 en pratique. La configuration de test est décrite en section 3 : les deux mises en œuvre testées étaient un NetProbe (ce qu'utilise WIPM), utilisant des paquets UDP avec une distribution périodique (RFC 3432) ou de Poisson (RFC 2330), et un Perfas+ (description en allemand), également avec UDP. Dans les deux cas, on passait par un tunnel L2TP (RFC 3931), pour dissimuler aux équipements intermédiaires les adresses IP et ports des équipements de tests (autrement, le trafic risquerait de passer par des chemins différents pour les deux tests). À l'extrémité du tunnel, le trafic est renvoyé donc cela permet d'avoir l'émetteur et le récepteur au même endroit, tout en faisant une mesure unidirectionnelle sur une longue distance. Pour introduire des phénomènes rigolos comme des pertes de paquet, un émulateur Netem est installé sur une machine Fedora, qui assure la communication entre le tunnel et un VLAN où se trouve l'équipement de test, via un lien FastEthernet. Les équipements testés ont envoyé des flots à 1 et 10 p/s, avec des centaines de paquets, de tailles variables (de 64 à 500 octets). Le type-P (cf. RFC 2680, section 2.8.1) des paquets était « UDP avec DSCP best effort » (de toute façon, l'encapsulation dans le tunnel L2TP fait que ces bits DSCP ont probablement été ignorés).

La section 4 de notre RFC décrit l'étalonnage (vérifier les horloges, par exemple).

On l'a dit, c'est bien joli de comparer deux programmes mais que doit être le résultat de la comparaison ? Une égalité rigoureuse ? Ce n'est pas possible. La section 5 indique les critères de comparaison : on fait de l'ADK avec un facteur de confiance à 0,95 (et de l'adéquation à la loi de distribution).

Enfin, après toutes ces précautions méthodologiques, la section 6 contient les résultats. Par exemple, en périodique, les deux systèmes mesurés donnent des résultats largement compatibles mais, en distribution de Poisson, les résultats sont tout juste acceptables. Les mesures ont bien résisté à des tests comme celui du délai maximal d'attente (avant de déclarer un paquet perdu) ou comme celui du désordonnement des paquets (lorsqu'un paquet est tellement en retard qu'il arrive après un paquet parti après).

Conclusions (section 7) : les deux mises en œuvre sont compatibles, ce qui indique que le RFC 2680 est suffisamment clair et précis. Le processus de test a toutefois noté quelques points où le RFC 2680 pouvait être rendu plus clair (sans compter les erreurs connues du RFC).

Pour les fanas, la section 10 rassemble toutes les commandes de configuration des équipements qui ont été utilisées. Par exemple, Netem a été configuré avec tc (ici, pour ajouter un retard variable et en prime 10 % de perte de paquets) :

tc qdisc change dev eth1 root netem delay 2000ms 1000ms loss 10%

Téléchargez le RFC 7290


L'article seul

Un petit galop d'essai avec le système Haka (filtrage, sécurité, paquets, protocoles, etc)

Première rédaction de cet article le 20 juillet 2014


Le 10 juillet dernier, lors des RMLL à Montpellier, j'ai eu le plaisir de participer à l'« Atelier HAKA : un langage open source [sic] de sécurité réseau ». Haka est un langage permettant d'analyser les paquets, de réagir à certaines caractéristiques des paquets et de générer des réponses diverses. Cela permet entre autres de faire des pare-feux très souples car complètement programmables.

Haka est fondé sur Lua et il faut donc un peu réviser ses connaissances Lua avant de pratiquer l'atelier. (J'ai déjà écrit ici et sur Lua et réalisé un tout petit programme avec.) Haka étend Lua en ajoutant au langage de base des extensions permettant de tripoter les paquets réseau facilement. Je ne vais pas vous faire un cours sur Haka (il y en a un en ligne et les transparents de l'atelier sont disponibles en ligne), juste documenter mon expérience.

L'atelier se faisait dans une machine virtuelle Debian dans VirtualBox. La machine virtuelle utilisée pouvait être téléchargée en https://hakasecurity.files.wordpress.com/2014/07/haka-live-iso.zip. (Je n'ai pas encore essayé d'installer Haka moi-même.) Une machine plus récente est, depuis, en http://www.haka-security.org/resources.html. Une fois la machine démarrée, il faut faire un setxkbmap fr dans un terminal pour passer en AZERTY, le clavier par défaut étant QWERTY. Si vous éditez les sources Lua avec Emacs, notez qu'il n'y a pas de mode Lua pour Emacs dans la machine virtuelle. Bon, on s'en passe, sinon, on le télécharge avec apt-get. Les pcap d'exemple sont livrés avec la machine virtuelle, dans /opt/haka/share/haka/sample/hellopacket.

Premier exercice, s'entraîner aux bases de Haka et apprendre à afficher certains paquets. Allons-y en Lua :

-- On charge le dissecteur IPv4 (pas encore de dissecteur IPv6,
-- malheureusement ; un volontaire pour l'écrire ?)
local ip = require('protocol/ipv4')

-- Haka fonctionne en écrivant des *règles* qui réagissent à des
-- *évènements*, ici, l'évènement est le passage d'un paquet IPv4
haka.rule{
    hook = ip.events.receive_packet,
    -- Suit une série d'actions, qui reçoivent un paramètre qui dépend
    -- du dissecteur. Le dissecteur IPv4 passe à l'évènement
    -- receive_packet un paquet.
    eval = function (pkt)
        haka.log("Hello", "packet from %s to %s", pkt.src, pkt.dst)
    end
}

Et comment on a trouvé que les champs de pkt qui contenaient les adresses IP source et destination se nommaient src et dst ? On a lu la doc (également disponible dans la machine virtuelle en /lib/live/mount/medium/haka/manual/modules/protocol/ipv4/doc/ipv4.html#dissector). Il existe aussi un mode interactif de Haka, permettant d'explorer les paquets, pas montré ici.

Si on lance ce script Haka sur un pcap existant, il affiche :

% hakapcap hellopacket.lua hellopcaket.pcap

info  core: load module 'packet/pcap.ho', Pcap Module
info  core: load module 'alert/file.ho', File alert
info  core: setting packet mode to pass-through

info  core: loading rule file 'hellopacket.lua'
info  core: initializing thread 0
info  dissector: register new dissector 'raw'
info  pcap:      opening file 'hellopacket.pcap'
info  dissector: register new dissector 'ipv4'
info  core:      1 rule(s) on event 'ipv4:receive_packet'
info  core:      1 rule(s) registered

info  core:      starting single threaded processing

info  Hello:     packet from 192.168.10.1 to 192.168.10.99
info  Hello:     packet from 192.168.10.99 to 192.168.10.1
info  Hello:     packet from 192.168.10.1 to 192.168.10.99
info  Hello:     packet from 192.168.10.1 to 192.168.10.99
info  Hello:     packet from 192.168.10.99 to 192.168.10.1
info  Hello:     packet from 192.168.10.1 to 192.168.10.99
info  Hello:     packet from 192.168.10.99 to 192.168.10.1
info  Hello:     packet from 192.168.10.1 to 192.168.10.99
info  core:      unload module 'Pcap Module'
info  core:      unload module 'File alert'

Ça a bien marché, chaque paquet du pcap a été affiché.

Deuxième exercice, filtrage des paquets qui ne nous plaisent pas, en l'occurrence, ceux qui viennent du méchant réseau 192.168.10.0/27 :

local ip = require('protocol/ipv4')

local bad_network = ip.network("192.168.10.0/27")

haka.rule{
    hook = ip.events.receive_packet,
    eval = function (pkt)
      -- On teste si le paquet appartient au méchant réseau
      if bad_network:contains(pkt.src) then
        -- Si oui, on le jette et on journalise
        haka.log("Dropped", "packet from %s to %s", pkt.src, pkt.dst)
	pkt:drop()
      -- Si non (pas de 'else') le paquet suit son cours
      end
   end
}

Une fois lancé le script sur un pcap, on obtient :

...
info  Dropped:   packet from 192.168.10.1 to 192.168.10.99
info  Dropped:   packet from 192.168.10.1 to 192.168.10.99
info  Dropped:   packet from 192.168.10.1 to 192.168.10.99
info  Dropped:   packet from 192.168.10.1 to 192.168.10.99
info  Dropped:   packet from 192.168.10.10 to 192.168.10.99
info  Dropped:   packet from 192.168.10.10 to 192.168.10.99
info  Dropped:   packet from 192.168.10.10 to 192.168.10.99

Si vous regardez le pcap avec tcpdump, vous verrez qu'il y a d'autres paquets, en provenance de 192.168.10.99 qui n'ont pas été jetés, car pas envoyés depuis le méchant réseau :

14:49:27.076486 IP 192.168.10.1 > 192.168.10.99: ICMP echo request, id 26102, seq 1, length 64
14:49:27.076536 IP 192.168.10.99 > 192.168.10.1: ICMP echo reply, id 26102, seq 1, length 64
14:49:28.075844 IP 192.168.10.1 > 192.168.10.99: ICMP echo request, id 26102, seq 2, length 64
14:49:28.075900 IP 192.168.10.99 > 192.168.10.1: ICMP echo reply, id 26102, seq 2, length 64
14:49:31.966286 IP 192.168.10.1.37542 > 192.168.10.99.80: Flags [S], seq 3827050607, win 14600, options [mss 1460,sackOK,TS val 2224051087 ecr 0,nop,wscale 7], length 0
14:49:31.966356 IP 192.168.10.99.80 > 192.168.10.1.37542: Flags [R.], seq 0, ack 3827050608, win 0, length 0
14:49:36.014035 IP 192.168.10.1.47617 > 192.168.10.99.31337: Flags [S], seq 1811320530, win 14600, options [mss 1460,sackOK,TS val 2224052099 ecr 0,nop,wscale 7], length 0
14:49:36.014080 IP 192.168.10.99.31337 > 192.168.10.1.47617: Flags [R.], seq 0, ack 1811320531, win 0, length 0
14:49:46.837316 ARP, Request who-has 192.168.10.99 tell 192.168.10.10, length 46
14:49:46.837370 ARP, Reply 192.168.10.99 is-at 52:54:00:1a:34:60, length 28
14:49:46.837888 IP 192.168.10.10.35321 > 192.168.10.99.8000: Flags [S], seq 895344097, win 14600, options [mss 1460,sackOK,TS val 2224054805 ecr 0,nop,wscale 7], length 0
14:49:46.837939 IP 192.168.10.99.8000 > 192.168.10.10.35321: Flags [R.], seq 0, ack 895344098, win 0, length 0
14:49:50.668580 IP 192.168.10.10 > 192.168.10.99: ICMP echo request, id 26107, seq 1, length 64
14:49:50.668674 IP 192.168.10.99 > 192.168.10.10: ICMP echo reply, id 26107, seq 1, length 64
14:49:51.670446 IP 192.168.10.10 > 192.168.10.99: ICMP echo request, id 26107, seq 2, length 64
14:49:51.670492 IP 192.168.10.99 > 192.168.10.10: ICMP echo reply, id 26107, seq 2, length 64
14:49:51.841297 ARP, Request who-has 192.168.10.10 tell 192.168.10.99, length 28
14:49:51.841915 ARP, Reply 192.168.10.10 is-at 52:54:00:30:b0:bd, length 46

Bon, jusqu'à présent, on n'a rien fait d'extraordinaire, Netfilter en aurait fait autant. Mais le prochain exercice est plus intéressant. On va faire du filtrage TCP. La documentation du dissecteur TCP nous apprend que le champ qui indique le port de destination est dstport :

local ip = require('protocol/ipv4')

-- On charge un nouveau dissecteur
local tcp = require ('protocol/tcp_connection')

haka.rule{
    -- Et on utilise un nouvel évènement, qui signale un nouveau flot TCP
    hook = tcp.events.new_connection,
    eval = function (flow, pkt)
      -- Si le port n'est ni 22, ni 80...
      if flow.dstport ~= 22 and flow.dstport ~= 80 then
        haka.log("Dropped", "flow from %s to %s:%s", pkt.ip.src, pkt.ip.dst, flow.dstport)
	flow:drop()
      else	
        haka.log("Accepted", "flow from %s to %s:%s", pkt.ip.src, pkt.ip.dst, flow.dstport)
      end
   end
}

Et on le teste sur un pcap :

info  Accepted:  flow from 192.168.10.1 to 192.168.10.99:80
info  Dropped:   flow from 192.168.10.1 to 192.168.10.99:31337
info  Dropped:   flow from 192.168.10.10 to 192.168.10.99:8000

Il y avait trois flots (trois connexions TCP) dans le pcap, une seule a été acceptée.

Maintenant, fini de jouer avec des pcap. Cela peut être intéressant (analyse de pcap compliqués en ayant toute la puissance d'un langage de Turing) mais je vous avais promis un pare-feu. On va donc filtrer des paquets et des flots vivants, en temps réel. On écrit d'abord le fichier de configuration du démon Haka :

[general]
# Select the haka configuration file to use
configuration = "tcpfilter.lua"

# Optionally select the number of thread to use. 
#thread = 4

# Pass-through mode
# If yes, haka will only inspect packet
# If no, it means that haka can also modify and create packet
pass-through = no

[packet]
# Select the capture model, nfqueue or pcap
module = "packet/nfqueue"

# Select the interfaces to listen to
interfaces = "lo"
#interfaces = "eth0"

# Select packet dumping for nfqueue
#dump = yes
#dump_input = "/tmp/input.pcap"
#dump_output = "/tmp/output.pcap"

[log]
# Select the log module
module = "log/syslog"

[alert]
# Select the alert module
module = "alert/syslog"

Le script est le même que dans l'essai précédent, il accepte uniquement les connexions TCP vers les ports 22 ou 80. On lance le démon (notez que celui-ci fera appel à Netfilter pour lui passer les paquets) :

% sudo haka -c haka.conf --no-daemon
info  core: load module 'log/syslog.ho', Syslog logger
info  core: load module 'alert/syslog.ho', Syslog alert
info  core: load module 'alert/file.ho', File alert
info  core: load module 'packet/nfqueue.ho', nfqueue
info  nfqueue: installing iptables rules for device(s) lo
info  core:    loading rule file 'tcpfilter.lua'
info  core:    initializing thread 0
info  dissector: register new dissector 'raw'
info  dissector: register new dissector 'ipv4'
info  dissector: register new dissector 'tcp'
info  dissector: register new dissector 'tcp_connection'
info  core:      1 rule(s) on event 'tcp_connection:new_connection'
info  core:      1 rule(s) registered

info  core:      starting single threaded processing

Et on tente quelques connexions (143 = IMAP) :

info  Accepted:  flow from 127.0.0.1 to 127.0.0.1:80
info  Dropped:   flow from 127.0.0.1 to 127.0.0.1:143
info  Dropped:   flow from 127.0.0.1 to 127.0.0.1:143
info  Dropped:   flow from 127.0.0.1 to 127.0.0.1:143

Et en effet, les clients IMAP vont désormais timeouter. Dès qu'on arrête le démon, avec un Control-C, IMAP remarche :

% telnet 127.0.0.1 imap2
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS AUTH=PLAIN] Dovecot ready.

J'ai beaucoup aimé la possibilité de journaliser ou de jeter un flot TCP entier, pas en agissant paquet par paquet. Pour la partie IP au début de cet atelier, Haka a un concurrent évident, Scapy (mêmes concepts mais Python au lieu de Lua). Mais Scapy ne sait pas gérer les flots TCP, il ne travaille que par paquet.

Exercice suivant, le protocole du Web, HTTP. On va modifier les pages HTML en vol (et vous comprendrez pourquoi il faut toujours utiliser HTTPS). Il faut changer haka.conf pour indiquer le nouveau script, blurring-the-web.lua. D'abord, on se contente d'afficher les requêtes HTTP :

local ip = require('protocol/ipv4')

-- On charge un nouveau dissecteur
local http = require ('protocol/http')

-- Pas d'indication du protocole supérieur dans TCP, seulement du
-- numéro de port, donc il faut être explicite
http.install_tcp_rule(80)

haka.rule{
    -- Et on utilise un nouvel évènement
    hook = http.events.request,
    eval = function (connection, request)
      haka.log("HTTP request", "%s %s", request.method, request.uri)
      -- Il faut être sûr que les données ne soient pas comprimées,
      -- pour que la modification ultérieure marche. On modifie donc
      -- la requête.
      request.headers['Accept-Encoding'] = nil
      request.headers['Accept'] = "*/*"
    end
}

Haka fait beaucoup de choses mais il ne décomprime pas les flots HTTP. Comme la compression est souvent utilisée sur le Web, on modifie les en-têtes de la requête pour prétendre qu'on n'accepte pas la compression (cf. RFC 7231, sections 5.3.4 et 5.3.2).

On lance maintenant le démon Haka avec ce nouveau script. Pour tester que les requêtes du navigateur Web ont bien été modifiées, on peut aller sur un site qui affiche les en-têtes de la requête comme http://www.bortzmeyer.org/apps/env. Par défaut, le Firefox de la machine virtuelle envoie :

HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_ENCODING: gzip, deflate

alors qu'une fois le démon en route, on n'a plus que (mettre une entrée de tableau à nil la détruit) :

HTTP_ACCEPT: */*

Attention au passage : Firefox peut maintenir des connexions TCP persistantes avec le serveur HTTP. Si vous lancez Firefox avant Haka, vous risquez de récupérer fréquemment des :

alert: id = 8
	time = Sat Jul 19 16:31:32 2014
	severity = low
	description = no connection found for tcp packet
	sources = {
		address: 127.0.0.1
		service: tcp/56042
	}
	targets = {
		address: 127.0.0.1
		service: tcp/80
	}

C'est parce que Haka a vu passer des paquets d'une connexion TCP antérieure à son activation et qu'il ne sait donc pas rattacher à un flot qu'il suit. (C'est le problème de tous les filtres à état.)

Attention aussi, Haka ne gère pas IPv6. Si on se connecte à un serveur Web en indiquant son nom, on peut utiliser IPv6 (c'est le cas de http://localhost/ sur la Debian de la machine virtuelle) et Haka ne verra alors rien. D'où l'option -4 de wget, pour tester :

% wget -v -4 http://localhost/
...
# Haka affiche
info  HTTP request: GET /

Maintenant, on ne va pas se contenter d'observer, on modifie la réponse HTTP en ajoutant du CSS rigolo :


local ip = require('protocol/ipv4')
local http = require ('protocol/http')

local re = require('regexp/pcre')

-- Ce CSS rend tout flou
local css = '<style type="text/css" media="screen"> * { color: transparent !important; text-shadow: 0 0 3px black !important; } </style>'

http.install_tcp_rule(80)

-- Bien garder cette règle, pour couper la compression, qui est
-- activée par défaut sur beaucoup de serveurs
haka.rule{
    hook = http.events.request,
    eval = function (connection, request)
      haka.log("HTTP request", "%s %s", request.method, request.uri)
      request.headers['Accept-Encoding'] = nil
      request.headers['Accept'] = "*/*"
    end
}

-- Deuxième règle, pour changer la réponse
haka.rule{
    hook = http.events.response_data,
    options = {
        streamed = true,
    },
    eval = function (flow, iter)
      -- Chercher la fin de l'élément <head>
      local regexp = re.re:compile("</head>", re.re.CASE_INSENSITIVE)
      local result = regexp:match(iter, true)
      -- Si on a bien trouvé un <head>
      if result then 
         result:pos('begin'):insert(haka.vbuffer_from(css))
      end
    end
}

Et re-testons :


% wget -O - -v -4 http://localhost/
--2014-07-19 16:41:48--  http://localhost/
Resolving localhost (localhost)... 127.0.0.1, 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 190 [text/html]
Saving to: `STDOUT'

 0% [                                               ] 0           --.-K/s              <html><head><style type="text/css" media="screen"> * { color: transparent !important; text-shadow: 0 0 3px black !important; } </style></head><body><h1>It works!</h1>
100%[==============================================>] 190         --.-K/s   in 0s      

2014-07-19 16:41:48 (45.0 MB/s) - written to stdout [190/190]

Le CSS a bien été inséré ! Et, avec un vrai site Web, on voit bien l'effet :

Attention, le haka.conf indiqué ici n'écoute que sur l'interface lo. Pour tester sur le Web en grand, pensez à changer le haka.conf (et rappelez-vous que Haka n'aura aucun effet sur les sites Web accessibles en IPv6 comme http://www.ietf.org/, si la machine virtuelle a une connectivité IPv6).

Voilà, sur ce truc spectaculaire, ce fut la fin de l'atelier. À noter que nous n'avons pas testé les performances de Haka, question évidemment cruciale pour des filtrages en temps réel. En première approximation, Haka semble bien plus rapide que Scapy pour les tâches d'analyse de pcap mais il faudra un jour mesurer sérieusement.


L'article seul

RFC 7314: Extension Mechanisms for DNS (EDNS) EXPIRE Option

Date de publication du RFC : Juillet 2014
Auteur(s) du RFC : M. Andrews (ISC)
Expérimental
Première rédaction de cet article le 18 juillet 2014


L'enregistrement DNS SOA (Start Of Authority) a un champ expire qui indique au bout de combien de temps un serveur esclave qui ne réussit pas à contacter le maître peut arrêter de servir la zone. Si l'esclave a eu les données, non pas directement du maître, mais d'un autre esclave, la durée d'expiration peut ne pas être correcte. C'est ce (rare) problème que règle l'option EDNS EXPIRE.

En effet, il faut se rappeler que la distribution d'une zone DNS depuis un serveur maître (le RFC utilise l'ancien terme de « serveur primaire ») n'est pas forcément directe. On peut avoir un maître qui envoie des données à un esclave, qui à son tour les envoie à un autre esclave. Cela permet notamment davantage de robustesse (si le maître n'est temporairement pas joignable depuis certains esclaves). Notez que l'esclave ne sait même pas si la machine qui lui a envoyé les données était un maître ou pas.

Si la période de validité donnée par le champ expire du SOA (RFC 1035, section 3.3.13) vaut V et que le transfert de l'esclave à un autre esclave prend place S secondes après le transfert depuis le maître (les transferts ne sont pas forcément instantanés, par exemple en cas de coupure réseau), la zone sera servie pendant V + S secondes et pas seulement pendant V secondes. Pire, s'il existe une boucle dans le graphe de distribution, la zone risque de ne jamais expirer, les esclaves se rafraichissant mutuellement.

Personnellement, le problème me semble rare et de peu d'importance. Il y a des tas d'autres choses plus urgentes à régler dans le DNS. Mais, bon, c'est juste une expérience.

La nouvelle option de ce RFC dépend de EDNS (RFC 6891). Elle a le numéro 9. Mise dans une requête (a priori une requête de type SOA, AXFR ou IXFR), elle indique que le client DNS connait cette option et voudrait sa valeur. Un serveur qui ne connait pas l'option EXPIRE ne mettra pas l'option dans sa réponse.

Par contre, un serveur qui connait cette option répondra avec une option EXPIRE dans sa réponse. Elle comporte quatre octets de données (comme pour le champ expire du SOA), indiquant le nombre de secondes de la période de validité. Si le serveur est un maître, il met toujours dans cette option la valeur du champ expire du SOA. S'il est un esclave, il met la valeur actuelle de son compteur d'expiration. Ainsi, si le champ expire du SOA vaut 7 200 secondes (2 heures) et que le serveur secondaire reçoit une demande 30 minutes après le transfert depuis le maître, il mettra 5 400 dans l'option EDNS EXPIRE (120 minutes de validité moins les 30 minutes écoulées). C'est ainsi qu'on évite l'accumulation des périodes de validité en cas de transfert indirect.

Un serveur esclave (le RFC utilise l'ancien terme de « serveur secondaire ») qui utilise l'option, et qui reçoit une réponse lors d'un transfert initial de la zone, devrait utiliser comme durée de validité la valeur de l'option EXPIRE (et pas le champ expire du SOA, sauf si ce champ a une valeur inférieure à celle de l'option EXPIRE). Cette durée de validité est ensuite mise dans un compteur d'expiration qui décroît avec le temps. Pour les rafraichissements ultérieurs, le serveur esclave doit également utiliser comme durée de validité la valeur de l'option, sauf si le compteur actuel a une valeur plus élevée. Par exemple, si le compteur du secondaire dit que la zone est encore valable pour 4 500 secondes, et qu'une réponse IXFR (RFC 1995) contient une option EXPIRE de valeur 9 300 secondes, alors le compteur est mis à 9 300 secondes. Si l'option EXPIRE avait valu 2 400 secondes, le compteur n'aurait pas été modifié.

Une conséquence amusante de cette option est qu'elle permet de savoir quand a eu lieu le dernier transfert de zone réussi, juste en interrogeant un esclave. Cela peut être vu comme indiscret, mais cela peut aussi être un outil de supervision très pratique.

Cette option est utilisable depuis dig, à partir de la version 9.10. Wireshark a récemment été modifié pour reconnaître cette option.


Téléchargez le RFC 7314


L'article seul

RFC 7291: DHCP Options for the Port Control Protocol (PCP)

Date de publication du RFC : Juillet 2014
Auteur(s) du RFC : M. Boucadair (France Telecom), R. Penno, D. Wing (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF pcp
Première rédaction de cet article le 15 juillet 2014


Le protocole PCP, normalisé dans le RFC 6887 permet à la machine de M. Michu de configurer un routeur/traducteur, par exemple pour lui demander de laisser passer le trafic entrant vers un port donné. La norme PCP ne précisait pas tellement comment le client était censé trouver le serveur PCP. Dans certains cas, c'est trivial, c'est le routeur par défaut. Dans d'autres, il faut d'autres mécanismes et c'est là que notre RFC 7291 est utile : il normalise un moyen de découvrir le serveur PCP grâce à une nouvelle option DHCP.

Le mécanisme est le même pour DHCP IPv6 (RFC 3315) ou DHCP IPv4 (RFC 2131). Pour DHCP IPv6, l'option est décrite en section 3. Elle est nommée OPTION_V6_PCP_SERVER et a le code 86 (mis dans le registre IANA). Suit une liste d'adresses IPv6, qui sont celles d'un serveur PCP. S'il y a plusieurs serveurs PCP, on met plusieurs occurrences de l'option OPTION_V6_PCP_SERVER.

On note que c'est une adresse IP et pas un nom de domaine qui est utilisée pour identifier le ou les serveur(s) PCP. Un nom de domaine aurait permis un niveau d'indirection supplémentaire. Le sujet a donc fait l'objet d'une certaine controverse au sein du groupe de travail PCP à l'IETF avant que le consensus se fasse sur l'adresse IP.

Pour obtenir cette liste d'adresses, le client DHCP doit mettre l'option OPTION_V6_PCP_SERVER dans sa requête et, si le serveur DHCP connait des serveurs PCP, il mettra leur(s) adresse(s) dans sa réponse.

Le mécanisme est quasiment le même en IPv4 (section 4), avec l'option OPTION_V4_PCP_SERVER de code 158 (registre IANA). La principale différence est le mécanisme utilisé pour mettre plusieurs serveurs PCP (pas juste plusieurs adresses IP pour un serveur, mais plusieurs serveurs) : en IPv6, on répétait l'option. En IPv4, on envoie plusieurs listes dans la même réponse.

Donc, attention, aussi bien côté client que côté serveur, ce RFC permet d'avoir plusieurs serveurs PCP, ayant chacun plusieurs adresses IP. Par exemple, côté serveur, le mécanisme de configuration du serveur (mettons son fichier de configuration) doit permettre de distinguer les deux cas, afin de choisir le bon encodage. Si le fichier de configuration permet de mettre un nom de domaine pour le serveur PCP, et que le serveur DHCP, en résolvant ce nom, trouve plusieurs adresses IP, il doit bien les mettre dans une seule option (en IPv6) ou une seule liste (IPv4).

Notez une différence entre IPv6 et IPv4 : un serveur DHCP IPv6 peut retourner des adresses IPv4 (encodées selon la section 2.5.5.2 du RFC 4291) dans sa réponse (cas d'un réseau purement IPv6 mais qui reçoit une connectivité IPv4 via un mécanisme spécifique), l'inverse n'étant pas vrai.

À noter que, dans le cas de multi-homing, on peut recevoir plusieurs serveurs PCP via des réponses DHCP différentes, sur des liens réseau différents (par exemple un lien WiFi et un 3G). Dans ce cas, la machine doit bien faire attention à associer chaque serveur PCP à son réseau, pour ne configurer que le bon serveur PCP correspondant à l'adresse qu'on veut utiliser.

Les praticiens noteront avec plaisir qu'il existe au moins une mise en œuvre documentée (sur Fedora).


Téléchargez le RFC 7291


L'article seul

RFC 7320: URI Design and Ownership

Date de publication du RFC : Juillet 2014
Auteur(s) du RFC : M. Nottingham
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 12 juillet 2014


Ah, les URI... Comme ces identificateurs sont très souvent vus et manipulés par un grand nombre d'utilisateurs, ils suscitent forcément des passions et des discussions sans fin. Ce RFC de bonne pratique s'attaque à un problème fréquent : les applications ou extensions qui imposent des contraintes sur l'URI, sans que cela soit justifié par le format de ces URI. Par exemple, on voit des CMS imposer, au moment de l'installation, que le CMS soit accessible par un URI commençant par le nom du logiciel. S'il s'appelle Foobar, on voit parfois des logiciels qui ne marchent que si l'URI commence par http://www.example.org/Foobar/. Pourquoi est-ce une mauvaise idée et que faudrait-il faire à la place ?

D'abord, l'argument d'autorité qui tue : la norme des URI, le RFC 3986, dit clairement que la structure d'un URI est déterminé par son plan (scheme en anglais) et que donc l'application n'a pas le droit d'imposer des règles supplémentaires. Les deux seuls « propriétaires » sont la norme décrivant le plan (qui impose une syntaxe, et certains éléments, par exemple le nom du serveur avec le plan http://) et l'organisation qui contrôle cet URI particulier (par exemple, toujours pour http://, l'organisation qui contrôle le domaine dans l'URI). Imposer des règles, pour une application ou une extension, c'est violer ce principe de propriété. (Il est formalisé dans une recommandation du W3C, section 2.2.2.1.)

Un exemple de structure dans les URI est l'interprétation du chemin (path en anglais) comme étant un endroit du système de fichiers. Ainsi, bien des serveurs HTTP, en voyant l'URI http://www.example.org/foo/bar/toto.html, chercheront le fichier en $DOCUMENT_ROOT/foo/bar/toto.html. C'est une particularité de la mise en œuvre de ce serveur, pas une obligation du plan d'URI http://. Un autre exemple est l'utilisation de l'extension du nom de fichier comme moyen de trouver le type de média de la ressource. (« Ça se termine en .png ? On envoie le type image/png. ») Ces deux cas ne violent pas forcément le principe de propriété des URI car l'utilisateur, après tout, choisit son serveur.

Mais, dans certains cas, l'imposition d'une structure (autre que celle déjà imposée par la norme du plan d'URI) a des conséquences néfastes :

  • Risque de collisions entre deux conventions différentes.
  • Risque d'instabilité si on met trop d'informations dans l'URI (voir la section 3.5.1 du document « Architecture of the World Wide Web, Volume One », cité plus haut). Pour reprendre l'exemple de l'extension du fichier, si on change le format de l'image de PNG en JPEG, l'URI changera, ce qui est néfaste.
  • Rigidité accrue. Si un logiciel impose d'être installé en /Foobar comme dans l'exemple au début, il contraint les choix pour l'administrateur système (et si je veux des URI avec un chemin vide, genre http://foobar.example.org/, je fais quoi ?)
  • Risque que le client fasse des suppositions injustifiées. Si une spécification décrit le paramètre sig comme étant forcément une signature cryptographique, il y a une possibilité qu'un logiciel client croit, dès qu'il voit un paramètre de ce nom, que c'est une signature.

Donc, pour toutes ces raisons, notre RFC déconseille fortement de rajouter des règles de structure dans les URI. Ces règles diminuent la liberté du propriétaire de l'URI.

Qui risque de violer ce principe ? Les auteurs d'applications, comme dans l'exemple Foobar plus haut, mais aussi des gens qui font des extensions aux URI, par le biais de nouvelles spécifications (par exemple pour mettre des signatures ou autres métadonnées dans l'URI). En revanche, ce principe ne s'applique pas au propriétaire lui-même, qui a évidemment le droit de définir ses règles pour la gestion de ses URI (exemple : le webmestre qui crée un schéma de nommage des URI de son site Web). Et cela ne s'applique pas non plus au cas où le propriétaire de l'URI reçoit lui-même une délégation pour gérer ce site (par exemple, un RFC qui crée un registre IANA et spécifie la structure des URI sous http://www.iana.org/ est dans son droit, l'IANA agissant sur délégation de l'IETF). Le principe « bas les pattes » de ce RFC n'est pas technique : on n'interdit pas de mettre de la structure dans les URI, on dit juste qui a le droit de le faire.

Notre RFC reconnait que certaines normes IETF (non citées...) violent ce principe, et appelle à profiter de la prochaine révision pour les corriger.

La partie normative de notre RFC est la section 2. Elle explicite le principe « bas les pattes » (« get off my lawn » dans le nom original du document en anglais...) D'abord, éviter de contraindre l'usage d'un plan particulier. Par exemple, imposer http:// peut être trop contraignant, certaines applications ou extensions pourraient marcher avec d'autres plans d'URI comme par exemple file://.

D'autre part, si on veut une structure dans les URI d'un plan particulier, cela doit être spécifié dans le document qui définit le plan (RFC 7230 pour http://, RFC 6920 pour ni:, etc) pas dans une extension faite par d'autres (« touche pas à mon plan »).

Les URI comprennent un champ « autorité » juste après le plan. Les extensions ou applications ne doivent pas imposer de contraintes particulières sur ce champ. Ainsi, pour http://, l'autorité est un nom de domaine et notre RFC ne permet pas qu'on lui mette des contraintes (du genre « le premier composant du nom de domaine doit commencer par foobar-, comme dans foobar-www.example.org »).

Même chose pour le champ « chemin », qui vient après l'autorité. Pas question de lui ajouter des contraintes (comme dans l'exemple du CMS qui imposerait /Foobar comme préfixe d'installation). La seule exception est la définition des URI bien connus du RFC 5785. Le RFC 6415 donne un exemple d'URI bien connus, avec une structure imposée.

Autre conséquence du principe « bas les pattes » et qui est, il me semble, plus souvent violée en pratique, le champ « requête » (query). Optionnel, il se trouve après le point d'interrogation dans l'URI. Notre RFC interdit aux applications d'imposer l'usage des requêtes, car cela empêcherait le déploiement de l'application dans d'autres contextes où, par exemple, on veut utiliser des URI sans requête (je dois dire que mes propres applications Web violent souvent ce principe). Quant aux extensions, elles ne doivent pas contraindre le format des requêtes. L'exemple cité plus haut, d'une extension hypothétique, qui fonctionnerait par l'ajout d'un paramètre sig aux requêtes pour indiquer une signature est donc une mauvaise idée. Une telle extension causerait des collisions (applications ou autres extensions qui voudraient un paramètre de requête nommé sig) et des risques de suppositions injustifié (un logiciel qui se dirait « tiens, un paramètre sig, je vais vérifier la signature, ah, elle est invalide, cet URI est erroné »). Au passage, les préfixes n'aident pas. Supposons qu'une extension, voulant limiter le risque de collisions, décide que tous les paramètres qu'elle définit commencent par myapp_ (donc, la signature serait myapp_sig). Cela ne supprime pas le risque de collisions puisque le préfixe lui-même ne serait pas enregistré.

Sauf erreur, Dotclear gère bien cela, en permettant, via les « méthodes de lecture » PATH_INFO ou QUERY_STRING d'avoir les deux types d'URI (sans requête ou bien avec).

Pourtant, HTML lui-même fait cela, dans la norme 4.01, en restreignant la syntaxe lors de la soumission d'un formulaire. Mais c'était une mauvaise idée et les futures normes ne devraient pas l'imiter.

Comme précédemment, les URI bien connus ont, eux, droit à changer la syntaxe ou contraindre les paramètres puisque, d'une certaine façon, l'espace sous .well-known est délégué à l'IETF et n'est plus « propriété » de l'autorité.

Dernier champ de l'URI à étudier, l'identificateur de fragment (ce qui est après le croisillon). Les définitions d'un type de média (RFC 6838) ont le droit de spécifier la syntaxe d'un identificateur de fragment spécifique à ce type de média (comme ceux du texte brut, dans le RFC 5147). Les autres extensions doivent s'en abstenir.

Bon, assez de négativité et d'interdiction. Après les « faites pas ci » et les « faites pas ça », la section 3 de notre RFC expose les alternatives, les bonnes pratiques pour remplacer celles qui sont interdites ici. D'abord, si le but est de faire des liens, il faut se rappeler qu'il existe un cadre complet pour cela, décrit dans le RFC 5988. Une application peut utiliser ce cadre pour donner la sémantique qu'elle veut à des liens. Autre technique rigolote et peu connue, les gabarits du RFC 6570, qui permettent de gérer facilement le cas de données spécifiques à l'application dans un URI.

Et, comme cité plusieurs fois, les URI bien connus du RFC 5785 sont un moyen de déclarer sa propre structure sur des URI. Par contre, ils sont censés avoir un usage limité (accéder à des métadonnées avant de récupérer une ressource) et ne sont pas un moyen générique d'échapper aux règles qui nous dérangent !


Téléchargez le RFC 7320


L'article seul

RFC 7303: XML Media Types

Date de publication du RFC : Juillet 2014
Auteur(s) du RFC : H. Thompson (University of Edinburgh), C. Lilley (W3C)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 11 juillet 2014


Voici la nouvelle norme décrivant les types MIME XML, comme application/xml. Elle remplace le RFC 3023. Cette norme décrit aussi l'utilisation de +xml comme suffixe pour des formats de données fondés sur XML comme TEI, avec son application/tei+xml.

XML est une norme du W3C et n'est donc pas dans un RFC mais dans un document du W3C. Lorsque des documents sont envoyés sur l'Internet, ils sont souvent étiquetés avec un type de média, dit aussi, pour des raisons historiques, type MIME. Pour XML, il existe cinq types, application/xml, text/xml, application/xml-external-parsed-entity, text/xml-external-parsed-entity et application/xml-dtd. Il existe aussi une convention, formalisée dans le RFC 6838, pour les formats bâtis au-dessus de XML, comme Atom (RFC 4287). On écrit les types de média pour ces formats avec un +xml à la fin, indiquant ainsi qu'un processeur XML généraliste pourra toujours en faire quelque chose, même s'il ne connait pas ce format spécifique. Ainsi, Atom est application/atom+xml. (Ces suffixes sont désormais banals mais, à l'époque du RFC 3023, ils étaient contestés et l'annexe A du RFC 3023 contient une justification détaillée, qui n'a pas été reprise dans ce nouveau RFC 7303.)

Pour normaliser quelque chose à propos de XML, il faut d'abord se pencher sur les problèmes d'encodage de caractères. Le modèle de caractères de XML est forcément Unicode.Les encodages de documents peuvent être très divers, mais la norme Unicode n'en définit que trois, UTF-8, UTF-16 et UTF-32. UTF-8 (RFC 3629) représente les caractères par une suite d'octets de longueur variable. Il n'a qu'une seule sérialisation en octets possible. UTF-16 en a deux, car il représente les caractères (enfin, ceux du PMB) par des seizets. Selon qu'on mette l'octet de poids fort du seizet en premier ou en dernier, on parle d'UTF-16 gros-boutien (utf-16be dans une déclaration XML) ou d'UTF-16 petit-boutien (utf-16le). Quant à UTF-32, qui est le plus simple des encodages, car le plus uniforme (tout caractère Unicode est représenté par quatre octets, codant son point de code), il a quatre sérialisations possibles en théorie mais deux seulement sont définies, UTF-32BE, gros-boutien, et UTF32-LE, petit-boutien. UTF-32 est malheureusement peu déployé (qu'on ne me dise pas que c'est parce qu'il prend plus de place : quatre octets par caractère, à l'époque où on s'échange des vidéos HD, ce n'est rien). Ce RFC déconseille désormais son usage. (Une bonne discussion des problèmes avec UTF-32 est dans ce rapport de bogue chez Mozilla.)

La section 3 du RFC décrit toutes les recommandations actuelles pour l'encodage des documents XML envoyés sur l'Internet. UTF-8 est recommandé (et sans BOM : il faut le retirer si, par exemple, on convertit de l'UTF-16 en UTF-8). Les producteurs/envoyeurs de XML devraient mettre un paramètre charset (pour les protocoles qui ont ce paramètre) et utiliser la déclaration XML (le truc qui commence par <?xml version="1.0" encoding=...) lorsqu'ils utilisent autre chose qu'UTF-8.

Cela suppose qu'ils sachent exactement quel est l'encodage. Si on envoie de l'XML et qu'on ne peut pas déterminer son encodage, il vaut mieux ne rien dire que de raconter n'importe quoi. Le RFC note que c'est particulièrement important pour les serveurs Web : avoir un paramètre global pour tout le site qui indique un encodage est dangereux, à moins qu'on puisse être absolument sûr que tous les documents du site auront cet encodage. Le RFC recommande que cet étiquetage soit configurable par l'utilisateur, pour qu'il puisse l'adapter à ses fichiers (AddDefaultCharset et AddCharset dans Apache.)

Quant aux consommateurs de documents XML, ils doivent considérer le BOM comme faisant autorité, et utiliser le paramètre charset si le BOM est absent. Les consommateurs qui comprennent le XML peuvent, s'il n'y a ni BOM, ni charset, utiliser les techniques purement XML, exposées dans la norme de ce format (en gros, utiliser la déclaration par exemple <?xml version="1.0" encoding="ISO 8859-1"?>. Il y a plein d'exemples en section 8 du RFC. Par exemple, ce cas-ci :


Content-Type: application/xml; charset=utf-8
...
<?xml version="1.0" encoding="utf-8"?>

est trivial : tout le monde est d'accord, le document est en UTF-8 et c'est explicite. En revanche, ce cas :


Content-Type: application/xml; charset=iso-8859-1
...
<?xml version="1.0" encoding="utf-8"?>

est pathologique : le type MIME dans l'en-tête HTTP et la déclaration XML se contredisent. Ici, un logiciel respectueux des normes doit traiter le document comme de l'ISO 8859-1, le type MIME ayant priorité (il n'y a pas de BOM, qui aurait une priorité supérieure). Mais, évidemment, l'envoyeur n'aurait pas dû générer ces informations incohérentes. Il vaut mieux ne pas envoyer de charset que d'envoyer un incorrect (voir aussi annexe C.2). Ainsi, dans ce troisième exemple :


Content-Type: application/xml
...
<?xml version="1.0"?>

il n'y a rien d'explicite : pas de BOM, pas de charset dans le type MIME et pas d'encodage indiqué dans la déclaration XML. Dans ce cas, puisque MIME ne dit rien, on applique la règle XML : l'encodage par défaut en XML est UTF-8.

À noter que le transport le plus utilisé pour XML, HTTP, avait un encodage de caractères par défaut, ISO 8859-1 mais ce n'est plus le cas depuis le RFC 7230. Voir aussi le RFC 6657 pour l'encodage par défaut des types text/*.

Assez fait d'encodage, place aux types MIME, sujet principal de ce RFC. La section 4 donne leur liste :

  • Les documents XML eux-mêmes auront le type application/xml ou text/xml. Le RFC ne tranche pas entre les deux possibilités, alors que ce choix a fait se déplacer beaucoup d'électrons, lors des innombrables discussions sur le « meilleur » type. (Le prédécesseur, le RFC 3023 recommandait text/xml.)
  • Les DTD auront le type application/xml-dtd.
  • Les « entités externes analysées » (external parsed entities), sont de type application/xml-external-parsed-entity ou text/xml-external-parsed-entity. Si elles sont par ailleurs des documents XML bien formés (ce qui n'est pas toujours le cas), elles peuvent avoir les types application/xml ou text/xml.
  • Les paramètres externes (external parameter entities) ont le même type que les DTD, application/xml-dtd.

Ils sont tous mis dans le registre IANA (cf. section 9 du RFC).

Il y a aussi le suffixe +xml (section 4.2), utilisant la notion de suffixe du RFC 6839. Il a vocation à être utilisé pour tous les formats XML. Si les concepteurs de ce format ne veulent pas d'un traitement générique XML (un cas probablement rare), ils doivent choisir un type MIME sans ce suffixe.

À noter que, si on envoie du XML en HTTP, le système de négociation de contenu de HTTP ne prévoit pas de mécanisme pour dire « j'accepte le XML, quel que soit le format ». Pas question de dire Accept: text/*+xml, donc.

La section 5 décrit ensuite le cas des identificateurs de fragment (le texte après le # dans un URI, pour désigner une partie d'un document). Ils sont décrits dans la section 3.5 du RFC 3986. Pour le cas particulier de XML, on se sert de la syntaxe XPointer pour écrire ces identificateurs (pas exemple, http://www.example.org/data.html#xpointer(/foo/bar)).

Le document XML envoyé peut utiliser l'attribut xml:base (section 6) pour spécifier un URI de référence, utilisé pour construire des URI absolus à partir des relatifs qu'on peut trouver dans le document XML (par exemple, lors de l'inclusion d'un autre document XML).

Et les versions de XML (il existe actuellement deux versions normalisées, 1.0 et 1.1) ? Voyez la section 7, qui précise que les types MIME sont exactement les mêmes pour toutes les versions : un analyseur XML doit utiliser les techniques XML (le champ version dans la déclaration) pour identifier les versions, pas les types MIME.

Enfin, si vous vous intéressez à la sécurité, voyez la section 10 qui résume rapidement les grandes questions de sécurité de XML. D'abord, les documents XML étant souvent modulaires (un document déclenche le chargement de paramètres ou d'entités XML externes, ou encore de feuilles de style), la sécurité doit prendre en compte tous les documents extérieurs et leur technique de chargement. Si un document XML est chargé en HTTPS mais qu'il contient une référence HTTP à une feuille de style CSS, la sécurité de HTTPS ne protégera pas cette dernière, alors qu'elle pourrait, par exemple, faire disparaître certains des éléments XML (display: none;...) Ainsi, beaucoup de documents XML se réfèrent à des entités XML qui sont sur les serveurs du W3C, sans se préoccuper d'analyser la sécurité desdits serveurs. Si la définition de l'entité mdash est remplacée par le texte de Winnie l'ourson, de drôles de résultats peuvent survenir.

Il y a aussi des attaques par déni de service : un document XML qui contient une référence à une entité qui contient à son tour de nombreuses autres références, qui contiennent chacune de nombreuses autres références, et ainsi de suite, jusqu'au dépassement de pile. (La forme la plus triviale de l'attaque, où l'entité se référence elle-même, est normalement empêchée par la prohibition de ces auto-références.)

Également d'un grand intérêt pratique, l'annexe C, sur les questions opérationnelles. La situation actuelle, notamment pour trouver l'encodage des caractères d'un document, n'est pas idéale. La nouvelle règle sur les BOM (priorité sur le paramètre charset) casse, en théorie, la compatibilité mais, en pratique, n'aggrave pas la situation et devrait l'améliorer à terme. Si on veut se simplifier la vie lors de l'envoi de XML, on le met en UTF-8 : c'est l'encodage recommandé par défaut, et il se passe de BOM. Si on n'utilise pas UTF-8, alors, il faut mettre un BOM.

Et le consommateur de XML ? Il lui suffit de regarder le BOM sinon le charset sinon la déclaration XML. En suivant ces règles simples, tout le monde devrait être heureux.

Depuis le RFC 3023, la précédente norme, que s'est-il passé ? L'annexe D résume les nombreux et sérieux changements. Les sous-types de text comme text/xml ont vu leur définition alignée avec celle du sous-type d'application. text/xml est donc désormais un simple synonyme de application/xml, ce qui reflète la réalité des mises en œuvre logicielles de XML. Le BOM est désormais prioritaire sur le charset. D'autre part, XPointer est désormais intégré. Et UTF-32 est maintenant officiellement déconseillé, au nom de l'interopérabilité.


Téléchargez le RFC 7303


L'article seul

Articles des différentes années : 2014  2013  2012  2011  2010  2009  2008  Précédentes années

Syndication : Flux Atom avec seulement les résumés et Flux Atom avec tout le contenu