Loading...
An error has occurred

An error has occurred in Orbeon Forms. You may want to try one of the following:

  • Close this dialog and continue to use this page.
  • Reload this page. Note that you will lose any unsaved changes.
  • If the above does not work, try reloading the page yourself. Note that you will lose any unsaved changes:

    • With Firefox and Safari: hold down the shift key and click the Reload button in your browser toolbar.
    • With Internet Explorer: hold down the control key and click the Reload button in your browser toolbar.
  • Return home.
Help

PLANÈTE XMLFR

Agrégation de carnets web.

2018-01-23

☕︎ Employés de la donnée

Le défi qui attend la CNIL est de devenir non pas un gardien de la propriété sur les données, mais un défenseur des droits des travailleurs de la donnée.

La vie privée et les travailleurs de la donnée (Le Monde, 22 janv. 2018) (cache)

Sommes-nous encore des travailleurs de la données ? J’ai l’impression que l’on nous a confisqué ce savoir-faire, que l’on nous a prélevé ces données afin que l’on ne puisse plus en faire ce que l’on veut, que nous sommes devenus des employés de la donnée à travers une prolétarisation (cache) forcée (ça sonne tout de suite moins bien que le cloud…).

Au mieux sommes-nous des employés de la donnée, qui nous travaille à souhait via les algorithmes qu’elle entraine. Au pire, nous alimentons notre propre perte.

2018-01-22

☕︎ Bilingualism and elitism

I have an issue with languages in that space. On one hand, I consider that using both French and English is closer to my daily life in Montreal and I’m happy to reflect that here. On the other hand, I do realize that it forces part of my readers to miss half of the content.

At the end of the day, I’m not sure if it encourages inclusivity or elitism. Maybe I should split and reactivate an old domain to be clear, maybe I should translate each and every post, maybe I should mix both languages within the same sentence as a true Quebecer :-)

P.S.: I know I’m not consistent with myself over time.

2018-01-21

☕︎ La barre est haute

En ayant accès à beaucoup plus de choses, on est en capacité de montrer aux enfants davantage d’exceptions. Des extrêmes auxquels l’on n’avait pas forcément accès dans ma (pas si) lointaine jeunesse. Une simple recherche sur Youtube et ce sont des performances qui sont quasi-inaccessibles. Je me demande ce que cela peut produire en terme de découragement et de jusqu’au-boutisme. La popularité conduit à mettre en avant l’exception sans en montrer les marches pour y arriver. Si tant est qu’elle soit encore rejoignable.

Encore une question d’algorithme, qui cette fois influe sur notre façon de concevoir les possibles. Une influence difficile à identifier et à mesurer mais qui pourrait avoir des effets de leviers lorsqu’elle se personnalise.

Tous cobayes volontaires.

2018-01-20

☕︎ Groupes de discussion

Dans ce brouhaha général, j’échappe le fil de conversation avec la personne devant moi. Je ne l’entends pas plus fort que les autres bruits, et elle s’y dissout. En fait, je dois mettre une énergie titanesque pour continuer de suivre la conversation. Et cette énergie me rend anxieuse et physiquement épuisée au point de frôler l’effondrement.

Immanquablement, avec tous ces bruits, toute cette agitation des gens qui passent devant moi, avec les enfants qui jouent bruyamment, je vais sentir se matérialiser un vertige. Je manque d’air, mon ventre se crispe, et j’ai une envie criante de hurler et de me volatiliser. […]

À chaque addition de stimuli et de nombre d’individus, je m’enfonce un peu plus. Les bruits sont de moins en moins distincts, et je suis K.O. J’ai beau lutter, je ne parviens pas à faire semblant, à converser malgré tout. Il n’y a plus rien, rien qu’un genre de néant intellectuel ponctué de malaise physiques intenses, puis une sensation de détachement, d’un nuage de brume qui s’épaissit.

Derrière le mur de verre, Marie Josée Cordeau

J’ai du mal à établir un dialogue avec plus de quatre interlocuteurs. Au-delà de cette limite, plusieurs conséquences :

  • les discussions deviennent plus superficielles (sans aucun jugement, certaines personnes ont besoin de ces échanges et je respecte cela), il se produit une perte d’intimité à la discussion qui devient semi-publique et perd de sa consistance ;
  • les intervenants n’ont plus des pairs en face mais s’adressent à un auditoire avec tous les travers associés : figure du héros, concurrence d’attention, bouc émissaire, etc ;
  • je m’épuise à tenter de cerner trop de subtilités et à explorer de trop nombreuses possibilités vu le temps imparti ce qui a pour effet immédiat une mise en retrait de protection, à la fois pour moi mais aussi pour les autres au sujet de la franchise déplacée que je pourrais avoir dans ces moments là.

Les spammeurs ne sont même pas compétents en standards du courrier

Comme vous, je reçois du spam via le courrier électronique. J'en reçois peut-être davantage car mon adresse publiée sur ce blog a manifestement été mise sur des listes d'« influenceurs » et autres blogueurs mode. Ces spams, plus orientés « professionnels » sont souvent en deux parties, une en texte seul et l'autre en HTML. Mais ce qui est amusant est que les deux parties sont parfois désynchronisées.

[Si vous connaissez bien MIME, vous pouvez sauter l'essentiel de cet article, et aller directement aux observations de la fin. J'explique d'abord MIME pour les gens qui ne connaissent pas.] Cette possibilité d'envoyer un message en plusieurs parties est normalisée dans le standard dit MIME, spécifié dans le RFC 2045. Il existe de nombreuses possibilités de message en plusieurs parties dans MIME dont les deux plus connues sont les parties différentes (multipart/mixed dans les étiquettes MIME) et les parties alternatives (multipart/alternative pour MIME). Bien sûr, la plupart des gens qui envoient des newsletter et CP ne savent pas cela. Ils ignorent que les messages ont une forme normalisée dans le RFC 5322 et qui est assez différente de ce qu'ils voient sur leur écran. Ainsi, prenons un message qui ressemble à ceci avec Thunderbird :

Sur le réseau, il sera très différent. Ce qui passe, et qui est interprété par Thunderbird, sera :


Date: Sat, 20 Jan 2018 17:07:29 +0100
From: Stephane Bortzmeyer <stephane@bortzmeyer.org>
To: johndoe@example.com
Subject: Les roux, c'est sympa
Message-ID: <20180120160727.ehuvwpqhrhbzpv26@bortzmeyer.org>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="gr5ck6jng3husyqz"
User-Agent: NeoMutt/20170113 (1.7.2)


--gr5ck6jng3husyqz
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

Un potamochère roux au ZooParc de Beauval.
Date	       15 May 2016, 16:03:54
Source	       Own work
Author	       Thesupermat

--gr5ck6jng3husyqz
Content-Type: image/jpeg
Content-Disposition: attachment; filename*=utf-8''Zooparc_de_Beauval_-_Potamoch%C3%A8re_roux_-_2016_-_002%2Ejpg
Content-Transfer-Encoding: base64

/9j/4AAQSkZJRgABAgEBLAEsAAD/4UnURXhpZgAASUkqAAgAAAAMAA8BAgAGAAAAngAAABAB
AgAVAAAApAAAABIBAwABAAAAAQAAABoBBQABAAAAugAAABsBBQABAAAAwgAAACgBAwABAAAA
AgAAADEBAgAVAAAAygAAADIBAgAUAAAA4AAAADsBAgAMAAAA9AAAAJiCAgAJAAAAAAEAAGmH
...
   
    

Les parties différentes sont utilisées pour le cas où on envoie, par exemple, un texte et une image d'illustration (ce qui est le cas de l'exemple ci-dessus). Elles sont décrites dans le RFC 2046, section 5.1.3. Le message a un en-tête du genre (regardez l'exemple plus haut) :

    
Content-Type: multipart/mixed; boundary="------------514DC64B3521BD0334B199AA"

Une autre possibilité courante de message en plusieurs parties est le cas des parties alternatives (RFC 2046, section 5.1.4). Prenons ce spam typique :

Sur le réseau, le contenu avait en fait deux parties, une en texte brut et une en HTML. Normalement, les deux sont équivalentes, et le MUA va choisir laquelle afficher. Dans l'image ci-dessus, Thunderbird affichait le HTML. Ici, un autre MUA, mutt fait un autre choix et affiche le texte seul :

Quant à ce qui circulait sur le câble, cela ressemble à :


MIME-Version: 1.0
To: bortzmeyer+ietf@nic.fr
Content-Type: multipart/alternative;
	boundary="----=_NextPart_001_322D_019C6BD8.657D49B2"
X-Mailer: Smart_Send_2_0_138
Date: Thu, 18 Jan 2018 08:49:31 -0500
Message-ID: <5860441356088315066310@Ankur>
X-SMTPCOM-Tracking-Number: f5f27516-49b6-40ee-848b-62cb2597a453
X-SMTPCOM-Sender-ID: 6008902
Feedback-ID: 6008902:SMTPCOM
Subject: The SDN, NFV & Network Virtualization Ecosystem: 2017 - 2030 - Opportunities, Challenges, Strategies & Forecasts (Report
)
From: "Andy Silva" <andy.silva@snsreports.com>


------=_NextPart_001_322D_019C6BD8.657D49B2
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

The SDN, NFV & Network Virtualization Ecosystem: 2017 =96 2030 =96 Opportun=
ities, Challenges, Strategies & Forecasts

...

------=_NextPart_001_322D_019C6BD8.657D49B2
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<HTML xmlns:o><HEAD>
<META content=3D"text/html; charset=3Diso-8859-1" http-equiv=3DContent-Type>
<META name=3DGENERATOR content=3D"MSHTML 11.00.10570.1001"></HEAD>
<BODY>
<P><SPAN><FONT color=3D#000000><FONT color=3D#000000><FONT color=3D#000000>=
...
      
    

Enfin, il existe d'autres types de messages en plusieurs parties, comme les possibilités multilingues du RFC 8255.

Voilà, tout cela est ancien (le RFC 2046 date de 1996 !) Maintenant, passons aux observations récentes. J'ai reçu le 15 janvier 2018 un spam de l'agence Maatch annonçant un « Voyage de presse Roanne Tout & Simplement » (un voyage de presse est un événement où une enterprise nourrit et abreuve des « influenceurs » pour qu'ils écrivent ensuite des articles favorables). Bizarrement, le voyage est annoncé pour le 9 septembre 2016. Et le message est « signé » d'un nom différent de celui utilisé dans le champ From:. Il se trouve que je lis mon courrier avec mutt et l'option alternative_order text/plain qui lui indique de préférer, dans les messages composés de plusieurs parties alternatives, le texte seul. Si je regarde la partie HTML du message, je vois la bonne date (31 janvier 2018), le bon programme (« invitation au restaurant gastronomique Le Central, en compagnie de l'équipe de Roanne Tout & Simplement et de chefs d'entreprises numériques ») et la bonne « signature ». La personne qui a préparé le message n'a sans doute pas directement écrit au format IMF (Internet Message Format, RFC 5322) mais a utilisé un logiciel qui n'affichait que la partie HTML, la seule qu'elle met à jour quand elle prépare un nouvel envoi. Toutes les occurrences futures de ce voyage de presse seront donc envoyés avec une partie en texte brut restée figée en 2016. Et personne ne s'en est aperçu car l'agence ne teste pas ses messages avec divers MUA et que les destinataires, soit sont mariés avec les logiciels « HTML seulement », soit envoient automatiquement ce genre de messages dans le dossier Spam.

Le choix de l'utilisateur, présenté par mutt :

Est-ce un cas isolé dû à une agence de communication particulièrement incompétente ? Non, j'ai regardé d'autres spams et le phénomène ne semble pas exceptionnel. Par exemple, le 18 janvier, je reçois un spam de l'agence Srvsaas/Sellinity intitulé « Invitation personnelle: Dîner privilégié » et c'est encore plus amusant. La partie texte décrit un diner avec les commerciaux d'un fabricant de matériel réseau bien connu, la partie HTML un diner avec les commerciaux d'une autre entreprise, une entreprise de sécurité informatique importante. L'agence a repris un message conçu pour un client, a modifié la partie HTML pour un autre client et a oublié la partie texte !

D'autres accidents sont possibles avec ces deux parties pas toujours synchronisées. Par exemple, on me signale que les messages de confirmation de Ryanair ont une partie texte et une partie HTML et que la partie texte contient… du HTML. Bref, regarder la partie texte et la partie HTML des spams peut être une distraction intéressante.

2018-01-19

☕︎ Commit (hi)story

There is one tool that we under utilise in our communities for communicating our intent and that is our version control system. […]

Our commit history has some very special properties which make it particularly useful for documenting intent.

It is kept forever.

It is always up to date and this almost certainly not true of most of the documentation you have, perhaps in a wiki or even in code comments.

And, this may come as a surprise to some of you, it is searchable.

Telling stories through your commits (cache)

Even if I try to write good commit messages (cache), I never thought about actually using it as an up-to-date line by line documentation (cache). Which lead me to think about a more friendly way to visualize it. Using git blame or any other git trickery (cache) is a bit too nerdy for me. I’m still looking for the most appropriated plugin for my editor which would display the commit message related to each line without the hurdle of doing it by hand.

2018-01-18

☕︎ Unconditional Lifetime Warranty

This means if you break it, we will repair or replace it. We will not question the validity of your warranty claim for a broken knife. Warranty is lifetime and transferable. In other words, we warranty the knife no matter how many times it’s been traded, sold or given away – no sales receipt or proof of purchase required. We must have the knife returned to validate a warranty claim.

A lot of folks have asked us how we can stay in business offering such great customer service and warranty protection. The answer is simple; we believe that consumers, as a whole, are honest people. The occasional customers who are dishonest are few and far between, so even if we lose every once in a while due to dishonesty, our reputation of great customer service, regardless of the situation, brings us more good customers.

ESEE Warranty (cache)

Imagine the same kind of warranty for a website. The last time I saw something approaching (only 5 years), it was a single web page and it was worth a million!

Which are your engagements for the website you are developing today? Has it even been discussed? I sometimes wonder how many lines of code I produced these last 10 years are still online. If I’m really honest with myself, I prefer not to know, afraid to be guilty of being paid that much for such an obsolescent domain…

2018-01-17

☕︎ Constitution d’évènement

Une constitution est une loi fondamentale ou un ensemble de principes qui fixe l’organisation et le fonctionnement d’un organisme, généralement d’un État ou d’un ensemble d’États. Son but est la préservation du bien commun par les principes et bénéfices reconnus de la séparation des pouvoirs, pour une justice au plus égalitaire, pour la préservation de la souveraineté nationale ; incitant aux qualités individuelles d’impartialité des représentants, plus surement, intrinsèquement évitant par ses règles des conflits d’intérêts et de collusions ; limitant, supprimant au mieux nombre des risques de dérives naturels des pouvoirs sans contrôles, sans modérateurs, sans contre-pouvoirs […]

Constitution — Wikipedia

Inspiré par une discussion avec Julia suite à ma note sur le Code d’(in)conduite, peut-être qu’il faudrait rédiger les règles qui régissent un vivre ensemble — aussi court soit-il — dans un document prenant la forme d’une constitution. Établir ensemble les règles constitutionnelles qui vont régir la séparation des pouvoirs. Entre les participants et les orateurs, entre les organisateurs et les prestataires, entre les nouveaux-venus et les habitués, entre les oppressés et les oppresseurs, etc.

Je ne sais pas quel temps cela prendrait, ni si un/quel quorum serait nécessaire à son établissement. Mais imaginons. Peut-être que l’évènement aurait une saveur particulière ? Peut-être qu’une telle implication mènerait finalement à l’abandon ? Peut-être que cela motiverait l’expérimentation à une autre échelle ? (coucou Étienne) Peut-être que cela ne serait qu’une énième itération vers des évènements plus inclusifs ? Peut-être que la reproduction d’un système complexe qui a montré ses limites est voué à l’échec ? Peut-être que des essais ont déjà été fait dans ce sens ?

Il reste tant de choses à tester. À espérer.

2018-01-16

☕︎ Stratégies d’évolutions

Frédéric a remis en cause ses outils et en a sélectionné d’autres qui lui semblent plus adaptés pour atteindre son objectif.

De mon côté, au lieu de remettre en cause mes outils, j’ai choisi de me remettre en cause et de mieux comprendre les principes fondamentaux du paradigme que j’utilise, ce qui m’a amené à faire évoluer très fortement mes méthodes de développement.

Les outils sont-ils la solution à nos problèmes ? (cache)

Frédéric me propose son article comme suite de réflexion à une précédente note, depuis quelques mois/années je suis davantage sur la remise en question des objectifs : mieux cerner le besoin pour pouvoir utiliser des outils plus simples et pertinents.

Notre profession produit du périssable, comment rendre l’investissement rentable ? Mes pistes actuelles :

Est-ce que cela est économiquement viable ? Nous venons de souffler notre cinquième bougie chez scopyleft :-)

2018-01-15

☕︎ Stimulus, JS and HTML

Stimulus is concerned with manipulating this existing HTML document. Sometimes that means adding a CSS class that hides an element or animates it or highlights it. Sometimes it means rearranging elements in groupings. Sometimes it means manipulating the content of an element, like when we transform UTC times that can be cached into local times that can be displayed.

[…]

This makes Stimulus very different from the majority of contemporary JavaScript frameworks. Almost all are focused on turning JSON into DOM elements via a template language of some sort. Many use these frameworks to birth an empty page, which is then filled exclusively with elements created through this JSON-to-template rendering.

Stimulus also differs on the question of state. Most frameworks have ways of maintaining state within JavaScript objects, and then render HTML based on that state. Stimulus is the exact opposite. State is stored in the HTML, so that controllers can be discarded between page changes, but still reinitialize as they were when the cached HTML appears again.

The Origin of Stimulus (cache)

A different paradigm, an old one actually, revisited. I’m more inclined to use that kind of approach given my usual needs. And if it gets bigger, it’s probably not my fish and I’m happy with that. It looks more robust by default and does not serve a blank page for whatever valid reason.

La conservation des données numériques n'est ni une révolution, ni inatteignable

2018-01-15 Gautier Poupeau - Les petites cases - Système d&#039;information, Causeries, Conservation

Alors que je m’étonnais dans un tweet, suite à une interview d'Anne Both, qu'on puisse encore émettre des doutes sur la conservation des données numériques, Julien Benedetti a attiré mon attention sur la conférence-table ronde "Les archives : quoi de neuf" qui a eu lieu à l'Ecole des chartes le 12 décembre dernier avec trois éminents archivistes(-paléographes) : Christine Nougaret, Bruno Galland et Edouard Bouyé.

Etant donné les mots de Julien Benedetti, je me doutais bien que le sujet serait abordé sous l'angle défaitiste qui le caractérise depuis plusieurs années, mais je ne m'attendais pas à entendre deux grands professionnels des archives se sentir aussi démunis face à cette question. Lorsqu'on visionne les quelques minutes (de 34 min à 47 min environ...) consacrées à ce sujet, on s'aperçoit que les manques sont à tous les niveaux : formation, organisationnel, technique, stratégique et même économique. Je comprends alors mieux les mots d'Anne Both qui ne fait que retranscrire ce que les archivistes ont pu lui dire à ce sujet.

<!--break-->

Quelques certitudes....

Je ne prétend pas détenir la réponse à toutes les questions, d'autant que je ne suis pas archiviste et que certains pourraient, à raison, m'opposer un procès en légitimité. Par ailleurs, je ne voudrais pas paraître "donneur de leçons", je me doute bien de l'extrême difficulté des archives départementales dont les moyens informatiques ne sont pas ceux dont nous disposons à l'Ina ou dont nous avons disposé lorsque j'ai participé à la mise au point de SPAR à la BnF. De plus, cette question du numérique n'est qu'un aspect parmi tant d'autres de leurs missions. Malgré tout, il existe trois choses dont je suis aujourd'hui certain.

La conservation des données numériques n'est pas une révolution

Dire comme le font Christine Nougaret et Bruno Galland que l'arrivée du numérique est une révolution pour le métier d'archiviste est à mon avis une erreur. Cette problématique persiste à être placée en marge du reste de l'activité quotidienne alors même que la conservation des données numériques s'appuie sur exactement les mêmes fondements du métier d'archiviste que pour les supports physiques traditionnels. S'il est vrai, comme le rappelle Bruno Galland, que l'expérience du numérique est complètement différente de celle des supports traditionnels, cela ne change en fait pas grand chose et la question du support (d'écriture et de consultation) n'est qu'un leurre (voire un prétexte...) sur lequel se focalisent à mon avis trop les archivistes.

Un marché de la conservation des données numériques sur le long terme n'existe pas et ne peut pas émerger (pour le moment ?)

Edouard Bouyé voit dans l'émergence d'un marché économique une solution pour prendre en main sérieusement cette question. Le lancement par l’Etat du programme Vitam vise, si j’ai bien compris, à mutualiser les coûts de développement et à favoriser l’émergence d’un écosystème autour d’une solution logicielle open source. Malgré cela, en l'état actuel des choses, un marché pour la conservation des données numériques sur le long terme ne peut pas exister pour au moins trois raisons :

  1. Il n'y a pas d'investissements massifs autant dans le privé que dans le public autour de cette question. Les entreprises ont besoin d'effectuer du stockage sécurisé pour, au plus, une ou deux dizaines d'années, point qu'on sait assez facilement résoudre (j'y reviendrai). Quant au long terme des archives publiques, les moyens à investir pour y parvenir sérieusement dépassent de très loin les possibilités de chaque AD.
  2. Par conséquent, la mise en place d'un système pour effectuer la conservation du numérique passe immanquablement par une mutualisation des infrastructures (permise d’ailleurs depuis peu par le SIAF) ce qui implique l'existence d'un petit nombre de systèmes et rend complexe le retour sur investissement du développement.
  3. Déployer un système qui assure le stockage, la surveillance et la consultation des données numériques ne résout pas tous les problèmes. La difficulté principale réside dans la récupération des données dans les systèmes sources et leur formatage dans des formats maîtrisables par le centre d'archives. Or, il faut effectuer un travail spécifique pour chaque solution déployée dans la collectivité. Qui dit travail spécifique, dit impossibilité de déployer une solution logicielle et donc inexistence d'un marché spécifique.
Des solutions (spécifiques) existent et fonctionnent

Les solutions pour permettre la conservation des données numériques existent et fonctionnent et je ne donnerai qu'un exemple que je connais bien (parmi d'autres) pour appuyer mon propos : SPAR (Système de préservation et d’archivage réparti) à la BnF. On fêtera en mars les 10 ans du lancement du projet d'implémentation de ce système et force est de constater qu'il fait le job sans, à ma connaissance, de changements majeurs dans son fonctionnement ou son architecture. Or, SPAR est basé sur un principe de base : la maîtrise parfaite de l'information numérique conservée. Voilà la clé : tout comme pour les supports traditionnels dont on maîtrise tous les paramètres de stockage, la conservation du document numérique passe par la maîtrise et la surveillance constantes des objets conservés. Certes, les outils ne sont pas les mêmes mais les actions le sont : tri, stockage, inventaire/description, surveillance, restauration/migration, consultation.

Tour d'horizon de la conservation des données numériques

Dans la suite de ce billet, je vous propose de revenir sur ces différents points pour essayer de montrer qu'au-delà des solutions existantes en la matière, c'est bien les compétences et savoir-faire traditionnels des archivistes qui sont en jeu (et à 8 ans d'écart, j'ai un peu l'impression de me répéter...).

Interroger les objectifs de la conservation ou la question du tri

En premier lieu se pose bien évidemment la question du tri. Au regard de la production sans cesse grandissante de données au format numérique, il est évident qu'il n'est pas possible de tout conserver. Comme le rappelle bien Anne Both dans l'entretien cité ci-dessus, le tri est déjà nécessaire pour les archives "traditionnelles" et les archivistes maîtrisent parfaitement cette problématique (contrairement à ce que certains historiens ont l'air de penser...). Je me garderai donc bien de m'immiscer dans ce débat de même que dans la question du records management, d'autant que cette problématique n'en est pas vraiment une pour les institutions pour lesquelles j'ai travaillé ou je travaille actuellement.

En revanche, comme tout support, le numérique présente des particularités qui induisent des questionnements sur ce qui est conservé. Or, les réponses à apporter dépendent de ce qu'on cherche justement à pérenniser. En effet, là où les supports traditionnels embarquent à la fois le support d'écriture et de lecture et l'information elle-même, ce n'est pas le cas dans le numérique et on peut conserver de manière indépendante chacune des couches :

  • le support de stockage lui-même ;
  • l'appareil nécessaire à la lecture du support ;
  • les logiciels capables de décrypter les informations stockées ;
  • les données elles-mêmes.

A chacun de ces niveaux est associé un objectif de conservation différent :

  • la mémoire des systèmes techniques ;
  • la mémoire de l'expérience utilisateur ;
  • la mémoire des informations elles-mêmes.

Pour illustrer mon propos, je vous propose tout d'abord de revenir sur l'exemple cité par Anne Both dans l'entretien cité ci-dessus : les textes des revues mises en ligne sur CAIRN. Celui-ci est particulièrement intéressant car, contrairement à ce qu'affirme Anne Both, ces données sont déjà pérennisées à au moins un titre : le dépôt légal du Web, mission que se partagent l'Ina et la BnF. Le site CAIRN (dont la BnF est aussi actionnaire) a été intégralement crawlé par la BnF. Les données ainsi collectées sont ensuite stockées dans SPAR dans un format maîtrisé, le WARC, surveillées par les experts de préservation et mises à disposition via les interfaces dédiées du dépôt légal du Web à la BnF. Dans ce cas, l'objectif est de conserver les données et l'expérience de navigation dans le site (ce qui n'est pas sans poser des questions sur la consultation sur le long terme mais j'y reviendrai plus loin). Mais, pour Cairn, on pourrait aussi se "contenter" de conserver les données : il suffirait alors d'extraire les textes des bases de données du site Web et de les encoder dans un format maîtrisable comme le XML. C'est assez simple à faire et la conservation de ce type de données ne pose pas de problème particulier. Le CINES assure déjà ce service pour HAL ou Persée.

Il existe des cas plus complexes comme le jeu vidéo ou l'art numérique pour lesquels l'adhérence entre le support de stockage et l'appareil pour le lire sont très importantes et l'expérience utilisateur essentielle à l'appréhension de l'objet archivé. Mais comme le montrent deux événements récents organisés par la BnF (Conservation du patrimoine vidéoludique. Quels enjeux ? Quels acteurs ? et Art numérique et postérité), les solutions émergent et font la preuve de leur efficacité. Ainsi, pour le jeu vidéo, la BnF conserve d'une part les appareils et cartouches et travaille d'autre part à l'émulation de ces différents jeux sur nos ordinateurs actuels pour en faciliter la consultation et l'étude. Le choix est, dans ce cas, de conserver les différents niveaux.

Pour les archives numériques des administrations, il me semble que ce sont bien souvent les données elles-mêmes qui sont intéressantes à conserver en priorité. Il ne s'agit pas de nier l'intérêt de pérenniser les applications de l'administration (leur histoire et surtout ce qu'elles renvoient  de la vision de l'administration sur ses propres missions pourraient être intéressantes). Mais les coûts et la complexité seraient exponentiels et on peut plutôt dresser un registre des applications existantes avec quelques copies d'écran permettant de donner une idée de leur fonctionnement.

Conserver le train de bits ou le stockage sécurisé

En premier lieu, il est nécessaire d'assurer la conservation du train de bits, c'est-à-dire de garantir l'intégrité de la donnée numérique dans le temps. Or, on le sait maintenant, il n'existe pas de support de stockage pérenne. Certains présentent plus d'assurance que d'autres comme c'est le cas des bandes magnétiques LTO, mais sans garantie absolue.

Deux actions sont à mettre en place pour assurer le stockage sécurisé :

  • effectuer différentes copies de la donnée si possible sur des supports (LTO ou disque dans un serveur) situés dans des espaces géographiques différents ;
  • surveiller régulièrement que ces différentes copies sont toujours intègres et en cas de problème effectuer une migration de support, c'est-à-dire changer le support endommagé et copier une des copies intègres sur un nouveau support.

Pour vérifier l'intégrité des données, il suffit de calculer régulièrement une empreinte de chaque fichier stocké (le MD5 par exemple est un système d'empreinte simple, efficace en la matière et implémenté sur tous les OS) et de comparer les empreintes.

Ce niveau de conservation ne demande pas des investissements faramineux et permet déjà de résoudre bien des problèmes. Il existe des solutions clé en main qui assure parfaitement ce service et si j'étais un service d'archive, je m'orienterai vers les solutions dans le cloud pour cela (ce qui semble permis par cette note d’information du SIAF même si cela est restreint au territoire français d’après ce billet). Et peut-être vais-je faire hurler certains d'entre vous, mais je pense que la solution glacier backup d'Amazon pourrait représenter un des espaces de stockage de secours, en plus d'une solution de stockage plus "locale" à base de serveurs de stockage. Mais, pour cela, peut-être faudra-t-il accepter que la mondialisation des échanges passe aussi par les archives ?

Garantir l’exploitabilité sur le long terme ou la maîtrise de la collection de données numériques

Si le stockage sécurisé permet d’assurer l’intégrité des données conservées, il ne garantit pas la capacité à les exploiter. Pour ce faire, il existe deux méthodes :

  • l’émulation, sur laquelle nous reviendrons plus en détail dans la prochaine partie, qui vise à reproduire le comportement d’une application et/ou d’une machine sur une autre machine le plus souvent grâce à un logiciel spécialisé appelé émulateur ;
  • la migration de format qui consiste à transformer la donnée numérique du format dans lequel elle est conservée vers un nouveau format dont l’exploitation est toujours assurée.

Dans un cas comme dans l’autre, il s’agit de procédures bien plus complexes que la conservation du train de bits. En effet, dans le cas de cette dernière, au delà des métadonnées descriptives nécessaires pour connaître le contenu des données conservées et les retrouver, le système se “contente” d’enregistrer l’empreinte des données et de les comparer. Pour assurer une migration de format (et c’est aussi vrai dans une moindre mesure pour l’émulation), il faut connaître précisément les caractéristiques de chaque fichier et ce que cela implique. Dans le cas où vous disposez d’une collection homogène avec peu de formats à maîtriser et une collection de fichiers restreinte, cela peut rester assez simple à gérer, mais quand vous disposez de données aux formats très hétérogènes (ou des variantes d’utilisation du format, par exemple pour XML, il faudra aussi prendre en compte le schéma XML d’encodage…), il est absolument nécessaire de maîtriser parfaitement votre collection.

Vous allez me rétorquer qu’il suffit d’enregistrer les données dans un format pérenne et le tour est joué…. Certes, sauf qu’en fait, comme pour les supports de stockage, il n’existe pas de format pérenne. Comme je l’ai déjà expliqué sur ce blog (bon, d’accord, c’était il y a longtemps, alors je vais le répéter :), un format n’est pérenne que si l’organisation qui conserve est capable d’en maîtriser aussi l’exploitation sur le long terme. Bien évidemment, s’il s’agit de données textuelles issues d’une base de données, l’utilisation du CSV ou mieux du XML permet de simplifier cette maîtrise dans le temps. Pour autant, si vous n’avez pas conservé aussi la documentation de la structure du CSV, de la structure du fichier XML ou, mieux, le schéma XML lui-même, le travail de rétro-ingénierie sera plus important voire pourrait s’avérer impossible.

Outre le stockage sécurisé, maîtriser ses données numériques pour en garantir l’exploitabilité sur le long terme signifie :

  • s’assurer à l’entrée dans l’archive des caractéristiques techniques des données numériques et de leur conformité avec les attendus (c’est-à-dire ne jamais faire confiance à l’organisation qui vous verse les données) ;
  • Rendre les données conservées indépendantes de l’application dont elles sont issues mais aussi du système d’archivage lui-même : si votre système d’archivage plante, vous devez pouvoir récupérer et exploiter les données directement depuis les supports de stockage ;
  • documenter précisément les données conservées : leur contenu, leurs caractéristiques techniques et juridiques, leur structure, leur historique de traitement avant et après leur arrivée dans l’archive, en particulier les étapes de vérification de conformité des données à leur entrée dans l’archive et de migration ;
  • conserver les métadonnées et la documentation (répertoire de formats et des applications et environnements) au même titre que les données et les rendre interrogeables de manière la plus exhaustive possible (sinon ça ne sert à rien de produire des métadonnées…) ;
  • mettre au point des tableaux de bord pour disposer d’une vue aussi complète que possible du contenu de l’archive et pour suivre les indicateurs de l’activité et d’évolution de l’archive (pour anticiper d'éventuelles difficultés de maintien en condition opérationnelle, par exemple) ;
  • effectuer une veille régulière sur les différents formats utilisés par l’archive pour planifier de manière préventive une éventuelle migration ;
  • auditer régulièrement les données numériques par échantillon pour contrôler la validité des métadonnées et effectuer des contrôles de conformité en plus des audits de l’intégrité du train de bits pour assurer le stockage sécurisé

Si vous cochez toutes ces cases, vous devriez sans problème mener des opérations de migration de format et, au passage, la suppression de données numériques pour des raisons légales ou opérationnelles pourra se faire sans difficulté et en toute sécurité.

Exploiter les données ou la problématique de la consultation

Enfin, vient tout l’intérêt de la conservation de données numériques : en assurer l’exploitation et la consultation dans le temps. Trois cas de figure (au moins) dans la manière d’exploiter ou de donner à voir ces données peuvent être identifiés.

Exploitation des données par un système de valorisation

Les données numériques conservées peuvent alimenter un système tiers qui offre des interfaces de recherche, de navigation et de consultation, comme c’est le cas, par exemple, de Gallica à la BnF ou d’Ina.fr à l’Ina. La conservation des données numériques vise alors à assurer le stockage sécurisé de ces données issues de chantiers de numérisation (souvent coûteux et complexes à reproduire à cette échelle) et l’exploitabilité dans le temps.

Même si les entrepôts numériques dédiés à la conservation sont les sources des systèmes cibles, les données y sont recopiées de manière aysnchrone. En effet, les systèmes de stockage sécurisés utilisés (bibliothèque de bandes LTO), les différences de caractéristiques entre les formats des fichiers de conservation et les formats d’exploitation, les éventuelles vérifications liées aux problématiques de droits d’auteur et les besoins de haute disponibilité pour une consultation sur le Web empêchent de brancher directement les systèmes. Bref, pour le dire autrement, le temps et les caractéristiques de la valorisation ne sont pas ceux de la conservation et il est préférable de disposer de deux systèmes pour l’un et l’autre des usages, même si le système de valorisation est alimenté par le système d’archivage ou de conservation (ce fut une des grandes leçons apprises sur le projet SPAR…).

Emulation des logiciels et virtualisation des environnements

Dans le cas où vous conservez l’application elle-même, l’objectif est d’en permettre l’expérience par les utilisateurs. C’est essentiel pour les jeux vidéos, l’art numérique ou même le Web pour lesquels l’interaction avec l’utilisateur fait partie intrinsèque de l'appréhension de ces médias. Or, il arrive un moment où l’application en question ne peut plus être exploitée par les environnements matériels et logiciels standards, il existe alors deux solutions :

  • l’émulation qui consiste à reproduire le comportement de l’application sur un environnement matériel contemporain via un logiciel dédié appelé émulateur ;
  • la virtualisation qui consiste à exploiter un environnement logiciel complet (système d’exploitation et logiciels) sur une machine hôte.

Ces deux méthodes n’ont pas été mises au point spécifiquement pour la conservation des données numériques. L’émulation est apparue dans le milieu du piratage des jeux vidéos pour permettre l’exploitation d’un jeu sur une plateforme pour laquelle il n’était pas prévu à l’origine. A l’origine, la virtualisation est apparue pour exploiter au mieux les capacités des serveurs en y faisant tourner plusieurs “machines” virtuelles. Elle est aujourd’hui très massivement utilisée par les services informatiques et les systèmes de cloud.

Si l’émulation est presque exclusivement réservée aux jeux vidéos, la virtualisation constitue une solution très prometteuse pour la conservation des données numériques. En effet, elle permet d’assurer l’exploitation sur le long terme de données et/ou d’applications pour lesquelles la migration de format était difficilement envisageable. Dans ce cas, on se “contente” de stocker de manière sécurisée le fichier de virtualisation et de s’assurer qu’il existe encore des logiciels pour l’exploiter.

Cette méthode est d’ores et déjà utilisée pour assurer, par exemple, la consultation des premiers cédéroms d’art numérique à la BnF et pourrait être envisagée pour continuer à assurer la consultation des archives du Web les plus anciennes lorsque nos navigateurs ne le permettront plus.

Mise à disposition en téléchargement des fichiers

Le dernier cas de figure me semble le plus complexe : comment assurer la mise à disposition de données hétérogènes comme peuvent l’être celles issues des administrations ? Fichiers bureautiques ou fichiers issues de bases de données diverses, ils présentent des formats et des structures hétérogènes. Il me semble que, dans ce cas, on peut s’inspirer des portails de données ouvertes, c’est-à-dire proposer un catalogue organisé des jeux de données existants et en permettre le téléchargement pour une consultation et une exploitation locales. J’imagine que cela pourrait poser des problèmes juridiques, mais cela me semblerait à la fois le plus simple et le plus efficace pour accéder à toutes ces données hétérogènes.

Problème et perspectives

Au-delà de l'importance d'intégrer la question de l'archivage des données numériques au sein même des processus habituels du centre d'archives, force est de reconnaître que les circuits de versement posent des difficultés particulières.

La difficulté de la récupération et du formatage des données

Du strict point de vue technique, le problème principal de la conservation des données numériques est la récupération des données en question et leur formatage dans des formats maîtrisables par le centre d'archives. Il n'existe pas à proprement parler de verrous technologiques, les solutions existent en la matière : les logiciels du type ETL utilisés à l'origine pour alimenter les solutions d'informatique décisionnelle constituent des réponses adaptées. Mais, pour chaque système, avant même le développement, il est nécessaire de déterminer :

  • les données à récupérer ;
  • le format de récupération (CSV, XML, Json par exemple) et la structure des données­ ;
  • la fréquence et les modalités de récupération ;
  • les métadonnées associées pour assurer la documentation du contexte de production et des données elles-mêmes ;
  • les mécanismes de vérification de l'intégrité et de conformité des versements dans l'archive ;
  • la politique de conservation conformément aux cadres légaux et aux principes établis par le centre d'archives en accord avec le producteur.

Cette difficulté est renforcée par différentes problématiques :

  • l'absence de plateforme pour échanger, entre les centres d'archives, des connecteurs prêts à l'emploi pour les applications qui existeraient dans différentes collectivités (un espace github pour les archives sur le modèle de ce qui existe pour les générateurs Seda : ici,  ou encore ici) ;
  • la spécificité de la très grande majorité des applications et donc la complexité pour un éditeur logiciel d'industrialiser des solutions en la matière ;
  • le manque de compétences pour spécifier ces développements informatiques : la plupart des sociétés de service en informatique sont incapables d'effectuer ce genre de tâches, car les informaticiens n'ont pas été formés pour ;
  • le désintérêt total des services informatiques des collectivités qui ont (disent-ils...) des dossiers bien plus urgents à traiter et qui, de toute façon, n'y comprennent rien...

Bien évidemment, la première réponse à ces différentes problématiques est de disposer en interne de personnes capables justement de discuter avec les informaticiens, de spécifier, de suivre et de tester les développements voire d'implémenter des solutions ou au minimum d'expérimenter certaines choses. Les diplômés du master Technologies numériques appliquées à l'histoire de l'Ecole nationale des chartes, par exemple, disposent justement de cette double compétence et sont tout à fait capables d'accompagner n'importe quel centre d'archives pour effectuer ce travail. Mais, cela ne suffira peut-être pas à persuader un service informatique d'investir dans l'extraction des données des applications en vue de leur conservation sur le long terme.

Big data et open data à la rescousse

Il y a dix ans, je pensais que la question de la conservation des données numériques serait un moyen pour les organisations de s'intéresser sérieusement à la maîtrise de leur patrimoine informationnel et de changer le paradigme pour passer de systèmes d'information orientés "Processus" à des systèmes d'information orientés "Données". Mais promettre la souplesse dans le SI et laisser entrevoir de nouveaux usages possibles ne suffisaient pas : il fallait en faire la démonstration concrète et la question de la conservation n'était pas en soi un argument suffisant pour faire basculer les organisations.

L'évolution est en fait arrivée de deux autres initiatives : le Big data et l'Open Data. L'une comme l'autre ont eu pour effet d'obliger les organisations à s'intéresser aux données qu'elles possèdent et à les libérer de leurs silos d'origine au moins en interne pour les faire circuler au sein de l'organisation (Big Data) voire à l'extérieur (Open Data).

Au delà de leurs enjeux inhérents, le Big Data et l'Open Data sont une formidable opportunité pour les archives des collectivités d'engager une politique de conservation des données numériques.

La perspective de "l'Open Data par défaut" imposé par la loi pour une République numérique va obliger les collectivités à s'organiser pour mettre à disposition selon les principes réglementaires les données publiques et au minimum à maintenir à jour leur répertoire d'informations publiques. Au-delà de ces aspects réglementaires, dans le contexte actuel (demande de transparence et buzz autour de la donnée), il est aujourd’hui plus facile de faire adhérer un décideur à une démarche de libération des données qu’à un projet de conservation des données numériques sur le long terme. Or, les deux démarches se rejoignent : donner accès aux citoyens aux données produites par l’administration dans le premier cas à des fins de transparence et de réutilisation, dans le second à des fins de preuve et de mémoire.

On résout ainsi la principale difficulté dont il était question précédemment : la récupération et le formatage des données. Ainsi, pour mener à bien des projets de statistiques avancées, de mise en relation de données ou d'apprentissage automatique (Big Data) ou de mise à disposition de jeux de données sur des portails institutionnels (Open Data), il est absolument nécessaire d'extraire les données depuis leurs applications d'origine et de les formater dans des formats susceptibles d'en conserver la structure et faciles à manipuler (CSV, XML, Json...). Les archives pourraient tout à fait s'insérer dans ces processus et récupérer les jeux de données établis pour ces usages. Bien sûr, ils ne sont pas exhaustifs et il faudrait faire un travail pour ajouter quelques métadonnées, mais c'est toujours mieux que rien : ça permet d'enclencher le travail et d'insérer les archivistes dans ces processus dont ils sont, me semble-t-il, pour le moment complètement absents.

Je suis absolument certain que la société OpenDataSoft, dont le logiciel est utilisé par un très grand nombre de portails Open Data, pourrait développer un service supplémentaire capable de verser les données exposées à travers son application dans un SAE suivant le protocole SEDA. Et dans le même ordre d'idée, on peut imaginer des ponts entre Vitam et data.gouv.fr, mais peut-être est-ce déjà à l'ordre du jour : après tout les deux projets sont développés au sein de la DINSIC...

Cette idée n'est pas très originale : les Français ont comme d'habitude ajouté une nouvelle couche administrative, Etalab, pour s'occuper de cette nouvelle mission, mais nos voisins suisses l'ont confié aux archives fédérales ce qui, entre nous, paraît totalement logique. En effet, l'Open data n'est finalement  qu'une extension de la fonction des archives au vu de leur définition. Et, même si je n'ai pas trouvé de trace de la question de la conservation des données numériques dans la stratégie en matière de libre accès aux données publiques en Suisse pour les années 2014 à 2018, gageons que cette synergie entre Open Data et conservation sur le long terme des données numériques est au cœur de la réflexion des archives fédérales.

Si certaines collectivités ont déjà expérimenté ou sont sur le point d'expérimenter cette stratégie, n'hésitez pas à me le signaler par mail ou twitter ; je me ferai un plaisir de mettre à jour ce billet.

Quelques points pour finir


Ce n'est pas le système qui préserve !!

On ne le dira jamais assez : ce n'est pas le système qui préserve. La conservation est la conséquence d'une bonne gestion et maîtrise des données numériques sur le long terme : des données stockées de manière sécurisée, documentées, surveillées, le cas échéant, migrées et mises à disposition du public sous des formes exploitables. Un système d'archivage électronique seul n'est pas suffisant, quelles qu'en soient les fonctionnalités. Certes, il aidera à effectuer une partie du travail mais il ne remplacera jamais les compétences mises en œuvre par les archivistes disposant d'une expertise dans les données numériques (au même titre que d'autres en possèdent pour les chartes médiévales ou les archives notariales).

Ceux-ci pourront spécifier les versements, effectuer la veille nécessaire au suivi des différents formats des fichiers, décider de la migration des fichiers, auditer les données conservées, surveiller les indicateurs de l’archive et accompagner les utilisateurs dans leur utilisation des archives numériques. Bref, faire le travail que n'importe quel archiviste effectue. Stocker des archives traditionnelles dans un entrepôt n'a jamais suffi à assurer leur conservation, il en va de même avec le numérique.

Accordez-vous le droit d’expérimenter sans pression

Au vu de l'ensemble des éléments à prendre en compte au moment de se lancer dans la conservation du document numérique, cela pourrait s'avérer intimidant voire paralysant. Plus d'une fois dans les étapes de déploiement et même en phase de production, vous ressentirez un sentiment de vertige face à l'immensité de la tâche.

Ne vous mettez pas la pression : oui, vous allez faire des erreurs, oui, vous allez faire, défaire et refaire certains choix techniques, oui, vous allez perdre des données numériques en chemin... Et alors ? C'est inhérent à l'apparition d'un nouveau support : si on conservait tous les incunables, les enregistrements sonores ou les films, ça se saurait, pourquoi n'en serait-il pas de même pour les données numériques ?

Les normes et les standards sont là pour vous apporter un cadre de réflexion et vous aider, n'en faites pas des carcans qui vous empêchent d'avancer. Il sera toujours temps de rendre parfaitement conforme votre système à la norme ISO bidule et AFNOR NF machin chose. Je comprends tout à fait que ce soit absolument nécessaire pour des raisons légales et juridiques, mais si vous en faites un préalable, cela risque bien souvent d'être contre-productif. Les ignorer totalement, pour des raisons dogmatiques, par exemple, aurait d'ailleurs le même effet.

Ainsi, les spécialistes du domaine pourraient s'étonner du fait que je n'ai pas cité une seule fois l'OAIS (Open Archival Information System), norme référence en la matière. Loin de moi l'idée de la rejeter comme semblent le faire certains, il faut simplement prendre l'OAIS pour ce qu'il est : un vade-mecum pour bien gérer l'information (numérique) d'une organisation et en aucun cas un mode d'emploi qu'il faudrait suivre aveuglément comme une notice de montage d'un meuble de chez Ikéa...

Bref, expérimentez, expérimentez encore et expérimentez toujours...

Connaître les composants des systèmes d'information

Comme tous les corps de métier, les informaticiens ne laissent pas facilement une personne extérieure entrer dans les arcanes de leur système. Or, dans le cas de la conservation des données numériques, cela est absolument nécessaire pour évaluer les données, l'intérêt à les conserver et pour spécifier leur récupération.

Même si vous n'avez pas encore déployé de système pour récupérer et conserver les données numériques, vous pouvez d'ores et déjà vous familiariser avec les différentes applications qui composent le système d'information. N'hésitez pas à vous faire présenter le système d'information, à récupérer les schémas d'architecture (ils existent forcément), à poser des questions et à recommencer.

A partir de ces différentes informations, je vous invite à dresser un répertoire ou un registre des applications existantes avec les informations qui vous intéressent (objectifs fonctionnels, services concernés, intérêt pour la conservation, bases de données utilisées et/ou format des fichiers, perspectives d'évolution…) et quelques copies d’écran. Lorsqu'il sera constitué, retournez voir les informaticiens pour valider et compléter avec eux ce recensement. Normalement, vous devriez gagner en crédibilité et donc en visibilité au sein du service informatique. Peut-être même qu'au déploiement de la prochaine application, ils vous enverront les différents éléments voire ils vous inviteront dès l'origine du projet ?

2018-01-14

☕︎ Communs numériques

Pour faciliter l’émergence des services communs numériques, et surtout pour éviter que le concept ne s’écroule sous sa propre popularité avant même qu’il n’ait fini de se déployer, je crois qu’il nous faudrait une référence qui explique de manière claire le vocabulaire et les enjeux, et vers laquelle on puisse donner des liens. Une référence qui comprenne aussi des exemples et des bonnes pratiques. Et qui soit éditable par la communauté, bien sûr ! Malheureusement, je n’ai pas réussi à trouver une telle ressource en ligne.

Dessine-moi un commun numérique (cache)

Du coup, Matti a créé cette ressource et appelle à contribution : Construire des communs numériques. So meta :-).

Noms de domaine, DNS et vie privée

Le 13 janvier 2018, à Fontenay-le-Fleury, à l'invitation de l'association de libristes Root66, j'ai fait un exposé sur les noms de domaine, le DNS et la vie privée. Presque trois heures, ouf (mais une galette après).

Voici les transparents de l'exposé :

Désolé, pas de vidéo, ça n'a pas été filmé. Mais vous pouvez lire mes articles sur les RFC 7626 (description du problème), RFC 7858 (chiffrement du DNS) et RFC 7816 (minimisation des données envoyées). Et bien sûr l'excellent portail « DNS privacy ».

Merci beaucoup à Zenzla زنزلا pour la proposition et l'organisation.

RFC 8300: Network Service Header (NSH)

Ce Network Service Header est un mécanisme concret pour faire passer sur le réseau les paquets destinés à une SF (Service Function, voir RFC 7665 pour l'architecture et les définitions). On colle un NSH, stockant plusieurs métadonnées, au paquet à traiter, on encapsule ce paquet à traiter et on l'envoie au dispositif de traitement via un réseau overlay. Et on fait l'opération inverse au retour. L'encapsulation peut se faire dans IP (par exemple avec GRE) ou dans un autre protocole.

Les métadonnées mises dans le NSH sont le résultat d'un processus de classification où le réseau décide ce qu'on va faire au paquet. Par exemple, en cas de dDoS, le classificateur décide de faire passer tous les paquets ayant telle adresse source par un équipement de filtrage plus fin, et met donc cette décision dans le NSH (section 7.1). Le NSH contient les informations nécessaires pour le SFC (Service Function Chain, RFC 7665). Sa lecture est donc très utile pour l'opérateur du réseau (elle contient la liste des traitements choisis, et cette liste peut permettre de déduire des informations sur le trafic en cours) et c'est donc une information plutôt sensible (voir aussi le RFC 8165).

Le NSH ne s'utilise qu'à l'intérieur de votre propre réseau (il n'offre, par défaut, aucune authentification et aucune confidentialité, voir section 8 du RFC). C'est à l'opérateur de prendre les mesures nécessaires, par exemple en chiffrant tout son trafic interne. Cette limitation à un seul domaine permet également de régler le problème de la fragmentation, si ennuyeux dès qu'on encapsule, ajoutant donc des octets. Au sein d'un même réseau, on peut contrôler tous les équipements et donc s'assurer que la MTU sera suffisante, ou, sinon, que la fragmentation se passera bien (section 5 du RFC).

Tout le projet SFC (dont c'est le troisième RFC) repose sur une vision de l'Internet comme étant un ensemble de middleboxes tripotant les paquets au passage, plutôt qu'étant un ensemble de machines terminales se parlant suivant le principe de bout en bout. C'est un point important à noter pour comprendre les débats au sein de l'IETF.

2018-01-13

☕︎ GAFA movies

In May 2015 about 10 investigators for the Quebec tax authority burst into Uber Technologies Inc.’s office in Montreal. The authorities believed Uber had violated tax laws and had a warrant to collect evidence. Managers on-site knew what to do, say people with knowledge of the event.

Like managers at Uber’s hundreds of offices abroad, they’d been trained to page a number that alerted specially trained staff at company headquarters in San Francisco. When the call came in, staffers quickly remotely logged off every computer in the Montreal office, making it practically impossible for the authorities to retrieve the company records they’d obtained a warrant to collect. The investigators left without any evidence.

Uber’s Secret Tool for Keeping the Cops in the Dark (cache)

Spy movies are so 2000’s! Please Hollywood, make something out of this, it has to reach a wider audience…

2018-01-12

☕︎ Code d’(in)conduite

En ce qui concerne la personne à l’origine de la situation, l’exclusion est possible mais en aucun cas n’est obligatoire. Il y a une granularité possible. D’ailleurs on est plutôt partisan d’une granularité.

Code of Conduct | Sud Web (cache)

Et la loi dans tout ça ? Je suis toujours surpris qu’aussi peu de codes de conduite en réfèrent aux risques encourus légalement. Il y a une granularité dans les peines associées aux situations, sauf que ce n’est pas une équipe de bénévoles inexpérimentés qui prend les décisions. Ce n’est pas tant pour montrer le bâton pénal (encore que) mais pour ne pas avoir à assumer une responsabilité qui me semble démesurée vis-à-vis des enjeux.

Est-ce qu’il y a des évènements où un incident a été à l’origine d’un dépôt de plainte de la part de l’organisation ? Et si oui quelles en ont été les suites ? Une jurisprudence serait la bienvenue.

PS : ne croyez pas que je tape toujours sur SudWeb, ce n’est qu’un exemple (plutôt bon en l’occurence) et c’est surtout le seul événement pour lequel j’ai encore un intérêt car ils sont plein de vitalité et ça fait plaisir :-).

2018-01-11

☕︎ Blaming others

Hundreds of people were ecstatic when we added that arrow to PR pages. Out of those, not a single one indicated that this flow was confusing. A lot of people assumed it was their own fault for not just “getting” it.

Others get so accustomed to these flows that they don’t even notice their anxiety. If they do, it’s just part of life. The status quo. Something to live with, not improve.

[…]

The lesson here is that you can’t trust your users to bubble up the small stuff, which as we’ve seen can often be the best stuff to build). This means that you can’t exclusively rely on existing user feedback and tickets. You need to dig deeper.

Tiny Wins (cache)

How many people are blaming their connection because you made them load a 2 Mb image? How many people are blaming their outdated computer because you think a Single Page App is fancy on your latest Macbook Pro? How many people think they are stupid with your innovative mobile design full of anti-patterns?

Caring is accepting that it is your fault. And acting accordingly. Now.

2018-01-10

☕︎ Re: HTTPS considered harmful

Both Anthony and Matti — two persons I highly estimate — reacted to the previous note with overlapping suggestions, here are my answers trying to be my own devil’s advocate:

  • Let’s Encrypt is not a mafia.” When you turn an oligopole into a monopole, it cannot be a mafia anymore, heh. Is that better? Sure. Is that really what I want to encourage? Not so sure, and I’m not even talking about security issues with such a single point of failure. Governments are probably racing to get master keys.
  • “0-RTT will reduce initial load time.” One day, maybe. But for now it’s quite limited to say the least.
  • “HTTP2 is good for performances.” Sure, when you have to load a bunch of resources but in my case it’s not that pertinent. HTTPS highly impacts my First Byte Time though.
  • “You have the guarantee your content is not altered.” Except if done once downloaded. A bunch of views are now performed directly within apps without any feedback on certificates or integrity and can be modified as such.
  • “Get rid of your domain name too!” Well, glad you ask, I’m thinking about it for a while :-). Providing a downloadable archive is an option, for instance reusing kiwix and/or using dat and/or something new (cache).
  • “Don’t use HSTS!” Mmmh, I don’t get the point of providing content over HTTPS if you do not force it somehow, is that better to let the responsibility to the client? The user interface of browsers is not adapted to that.
  • “301 are honored over HTTPS.” Except that you need to keep a server running to handle this, it’s not anymore as easy as changing a redirection at your registar level. See the parenthesis in Why? (cache) for instance.
  • “certbot autorenew works well.” I was talking about the configuration of the server itself not only the update of certificates, security is a race and you have to keep up on best practices.
  • “You can use Service Workers!” Great, I can now break the refresh button ;-) (I’m half-joking here given that I often have to reload pages of websites badly implemented because of Service Workers…)

Did I even mentioned how tedious it can be (cache) to setup and use a self-signed certificate on localhost?

Cours BGP au CNAM

Le 9 janvier 2018, c'était la première édition de mon cours BGP de trois heures au CNAM. Pour l'anecdote, c'était dans le bâtiment où il y avait eu la première connexion UUCP/Usenet, et le premier serveur HTTP public, en France.

Voici les supports de l'exposé :

Désolé, pas de vidéo publique.

J'ai fait aussi un cours DNS au même endroit.

Merci à Éric Gressier pour l'idée et l'organisation, et aux élèves pour avoir posé plein de questions pas toujours faciles.

2018-01-09

☕︎ Coder ou écrire

Depuis mardi, j’oscille entre des envies de coder et d’écrire. J’ai tellement oscillé que je n’ai fait ni l’un ni l’autre, ou presque, et failli entrer en résonance. Là encore, cela contribue à mettre le doigt sur une de mes principales faiblesses : accorder des priorités aux tâches qui m’importent. Sur le plan professionnel, je suis parvenu à canaliser tout ça, au point d’en être devenu redoutable et de me discipliner mécaniquement. Lorsqu’il s’agit de mes occupations et de mes projets personnels, c’est une tout autre histoire. C’est tellement stupide et paradoxal. Alors qu’il s’agit de ma part de temps la plus rare et précieuse, j’en gaspille une bonne portion à faire la girouette. Et lorsque j’en prends conscience, je tends naturellement à me flageller, activité ô combien constructive et gratifiante, vous en conviendrez.

Tranquille (cache)

Cela m’arrive tellement souvent que ça en est presque ridicule :-).

Le pire étant d’avoir envie de coder un outil de publication (ce qui semble être mon cas chaque début d’année) car cela crée une boucle infernale : besoin de contenus à publier mais besoin de l’outil pour visualiser mais besoin de contenus à publier. Auto-émulation d’un côté, réelle démotivation de l’autre.

Et rien n’avance…

2018-01-08

☕︎ Idea × execution

AWFUL IDEA = -1
WEAK IDEA = 1
SO-SO IDEA = 5
GOOD IDEA = 10
GREAT IDEA = 15
BRILLIANT IDEA = 20

NO EXECUTION = $1
WEAK EXECUTION = $1000
SO-SO EXECUTION = $10,000
GOOD EXECUTION = $100,000
GREAT EXECUTION = $1,000,000
BRILLIANT EXECUTION = $10,000,000

To make a business, you need to multiply the two.

Ideas are just a multiplier of execution (cache)

So simply put and yet super effective. I keep that here for future reference.

2018-01-07

☕︎ Censurer l’alternative

« On observe une perte importante de lectorat des sites socialistes, antiguerre et progressistes au cours des trois derniers mois, avec une diminution cumulée de 45 % du trafic en provenance de Google. » Entre mai et juillet 2017, les visites de wsws.org issues de Google ont chuté de 67 %, celles du réseau Alternet.org de 63 %. La plate-forme audiovisuelle Democracynow.org enregistre un plongeon de 36 % ; Counterpunch.org, de 21 % ; et Theintercept.com, de 19 %. « Dans la bataille contre les “fake news”, alerte l’association américaine Fairness and Accuracy in Reporting (FAIR), une grande partie des reportages les plus indépendants et les plus précis sont en train de disparaître des résultats des recherches effectuées dans Google. » Tuer le pluralisme au nom de l’information ?

Censure et chaussettes roses (cache)

On en revient plus que jamais à l’aspect politique des algorithmes (cache), il faudra que j’écrive un article plus complet sur le sujet. Nous sommes dorénavant dans un vide législatif qui ne saurait évoluer suffisamment rapidement, il en est de même de notre conscience politique associée à ces choix. Si cette complexité ne peut être appréhendée humainement, il va falloir laisser cette tâche aux machines. Et c’est là où ça devient intéressant…

2018-01-06

☕︎ HTTPS considered harmful

If a website is served over HTTPS, this should be a good list of features to try out and improve end-user performance. Many major websites have already leveraged these technologies and have seen great results. Based on your existing infrastructure, the level of complexity for implementing each of these features may vary. But the general awareness is more important and will help us plan accordingly for the future.

At eBay, we are very excited about the possibilities that HTTPS has opened up. With the adoption of modern technologies that come with HTTPS, our web platform is now ready to build the next wave of compelling user experiences. Cheers to a secure and innovative future.

Beyond HTTPS (cache)

I strongly disagree today, it wasn’t the case six years ago. Vincent reminded me a few months ago about the inherent fragility of HTTPS and how centralized that system is. Nothing new but sometimes you need a little discussion to realize how critical it actually is.

Encouraging everybody to switch to HTTPS promotes strong dependency to a third-party mafia, increases load time, makes your content inaccessible if you have any trouble reconducting your certificate, avoids migrating easily from one hosting platform to another, forces upgrading on a lot more security issues if you are hosting yourself. Even worse, when you switch there is no harmless turning back! That’s not the Web I’m aiming for.

“Sharing is learning” was my conclusion at that moment. Please prove me wrong.

PS: I always dreamt about publishing a note “X considered harmful”, achievement unlocked!

Edit: see the follow up.

RFC 8289: Controlled Delay Active Queue Management

Ah, la gestion des files d'attentes… Le cauchemar de plein d'étudiants en informatique. Et cela ne cesse pas quand ils deviennent ingénieurs et qu'il faut construire un routeur pour connecter des réseaux de capacités différentes, et qui aura donc besoin de files d'attente. Bref, dès qu'on n'a pas assez de ressources (et on n'en aura jamais assez), il faut optimiser ses files d'attente. Ce nouveau RFC décrit le mécanisme CoDel (mis en œuvre depuis un certain temps dans le noyau Linux) qui permet notamment de limiter le terrible, l'épouvantable bufferbloat.

L'algorithme naïf pour gérer une file d'attente est le suivant (on prend le cas simple d'un routeur qui n'a que deux interfaces et une seule file d'attente dans chaque direction) : les paquets arrivent au routeur et sont mis dans la file gérée en FIFO. Dès que des ressources suffisantes sont disponibles pour envoyer un paquet (dès que l'interface de sortie est libre), on envoie le paquet et on le retire donc de la file. Si un paquet arrive quand la file est pleine, on le jette : TCP détectera cette perte, réduira son rythme d'envoi, et réémettra les données manquantes.

Avec cet algorithme simpliste, il y a une décision importante à prendre, la taille de la file. Le trafic sur l'Internet est tout sauf constant : des périodes de grand calme succèdent à des pics de trafic impressionnants. Si la file d'attente est trop petite, on ne pourra pas écluser ces pics, et on jettera des paquets. Ça tombe bien, le prix des mémoires baisse, on va pouvoir mettre des files plus grandes, non ? Eh bien non car arrive le fameux bufferbloat. Si la file est trop grande, les paquets y séjourneront très longtemps, et on augmentera ainsi la latence, au grand dam des applications sensibles comme SSH ou les jeux en ligne. Bref, on est coincés, il n'y a pas de solution idéale. Pire, si on ne jette des paquets que lorsque la file est pleine, on risque de tomber dans le cas où l'équilibre se fait avec une file d'attente toujours pleine, et donc avec une mauvaise latence.

Bien sûr, il y a longtemps que les routeurs n'utilisent plus d'algorithme aussi naïf que celui présenté ici. Tout un travail a été fait sur l'AQM : voir par exemple les RFC 7567 et RFC 8033. Mais le problème de la file d'attente toujours pleine est toujours là. Sa première description est dans le RFC 896 en 1984. Plus récemment, on le trouve mentionné dans une présentation de Jim Gettys à l'IETF 80 (« Bufferbloat: Dark Buffers in the Internet ») développé dans un article dans Communications of the ACM (Gettys a beaucoup fait pour la prise de conscience des dangers du bufferbloat.).

Résoudre le problème de l'« obésité du tampon » (bufferbloat) en réduisant la taille des files d'attentes ne serait pas une solution : les tampons sont là pour une bonne raison, pour absorber les problèmes brefs, lorsque, temporairement, on reçoit davantage de paquets que ce que l'on peut transmettre. Le fait que des files plus petites ne sont pas une solution a déjà été exposé dans le RFC 2309, dans « A Rant on Queues » de Van Jacobson, dans le rapport « RED in a Different Light » et dans l'article fondateur de CoDel, « Controlling Queue Delay » (article complet sur Sci-Hub, cherchez 10.1145/2209249.2209264). Le problème n'est pas tant la taille de la file en soi (ce n'est pas la taille qui compte), mais si c'est une « bonne » file ou une « mauvaise » file (au passage, si vous ne connaissez pas la différence entre le bon chasseur et le mauvais chasseur, ne ratez pas l'indispensable sketch des Inconnus).

CoDel est donc une vieille idée. Elle veut répondre, entre autres, aux critères suivants (section 1 du RFC) :

  • Être « zéro-configuration » (parameterless), ce qui avait été un problème fréquent de solutions comme RED. (Mon opinion personnelle est que CoDel n'est pas réellement sans configuration, comme on le voit plus loin dans le RFC, mais il est certainement « configuration minimale ».) CoDel s'ajuste tout seul, une fois défini l'ordre de grandeur du RTT des paquets qui passeront par le routeur.
  • Capable de différencier le mauvais chasseur du bon chasseur, euh, pardon, la mauvaise file d'attente de la bonne.
  • Être simple à programmer, pour fonctionner aussi bien dans les processeurs limités des routeurs low cost que dans les ASIC (rapides, mais pas très souples) des routeurs haut de gamme.

Lorsque CoDel estime nécessaire de prendre des mesures (le trafic entre trop vite), il peut jeter les paquets, ou les marquer avec ECN (RFC 3168).

La section 2 de notre RFC définit la terminologie de CoDel. Parmi les termes importants :

  • Temps de passage (sojourn time) : le temps passé par le paquet dans la file d'attente. C'est la donnée de base de CoDel, qui va essayer de minimiser ce temps de passage.
  • File persistante (standing queue) : une file d'attente qui reste pleine trop longtemps, « trop » étant de l'ordre du RTT le plus élevé parmi les flots des paquets qui attendent dans la file.

Passons maintenant à une description de haut niveau de CoDel. Son but est de différencier la mauvaise file (qui ne fait qu'ajouter du retard d'acheminement des paquets) de la bonne. Une file d'attente se forme lorsqu'il y a un goulet d'étranglement, parce qu'un lien à forte capacité se déverse dans un lien à faible capacité, ou bien parce que plusieurs liens convergent vers un lien ayant la capacité de seulement l'un d'eux. Une notion importante à ce sujet est celle de BDP, en gros le nombre d'octets en transit pour une connexion donnée, lorsque le débit atteint 100 % de la capacité. Imaginons une connexion TCP dont la fenêtre d'envoi est de 25 paquets (je sais bien que les fenêtres TCP se calculent en octets, pas en paquets, mais c'est le RFC qui fait cet abus de langage, pas moi) et où le BDP est de 20 paquets. En régime permanent, il y aura 5 paquets dans la file d'attente. Si la fenêtre est de 30 paquets, ce seront 10 paquets qui occuperont en permanence la file d'attente, augmentant encore le délai, alors que le débit ne changera pas (20 paquets arriveront par RTT). Au contraire, si on réduit la fenêtre à 20 paquets, la file d'attente sera vide, le délai sera réduit au minimum, alors que le débit n'aura pas changé. Ce résultat contre-intuitif montre que bourrer la connexion de paquets n'est pas forcément le meilleur moyen d'aller « vite ». Et que la taille de la file ne renseigne pas sur le rythme d'envoi des données. Et enfin que les files pleines en permanence n'apportent que du délai. Dans le premier exemple, la file contenant cinq paquets tout le temps était clairement une mauvaise file. Un tampon d'entrée/sortie de 20 paquets est pourtant une bonne chose (pour absorber les variations brutales) mais, s'il ne se vide pas complètement ou presque en un RTT, c'est qu'il est mal utilisé. Répétons : Les bonnes files se vident vite.

CoDel comporte trois composants : un estimateur, un objectif et une boucle de rétroaction. La section 3 de notre RFC va les présenter successivement. Pour citer l'exposé de Van Jacobson à une réunion IETF, ces trois composants sont :

  • a) Measure what you’ve got
  • b) Decide what you want
  • c) If (a) isn’t (b), move it toward (b)

D'abord, l'estimateur. C'est la partie de CoDel qui observe la file d'attente et en déduit si elle est bonne ou mauvaise. Autrefois, la principale métrique était la taille de la file d'attente. Mais celle-ci peut varier très vite, le trafic Internet étant très irrégulier. CoDel préfère donc observer le temps de séjour dans la file d'attente. C'est une information d'autant plus essentielle qu'elle a un impact direct sur le vécu de l'utilisateur, via l'augmentation de la latence.

Bon, et une fois qu'on observe cette durée de séjour, comment en déduit-on que la file est bonne ou mauvaise ? Notre RFC recommande de considérer la durée de séjour minimale. Si elle est nulle (c'est-à-dire si au moins un paquet n'a pas attendu du tout dans la file, pendant la dernière période d'observation), alors il n'y a pas de file d'attente permanente, et la file est bonne.

Le RFC parle de « période d'observation ». Quelle doit être la longueur de cette période ? Au moins un RTT pour être sûr d'écluser les pics de trafic, mais pas moins pour être sûr de détecter rapidement les mauvaises files. Le RFC recommande donc de prendre comme longueur le RTT maximal de toutes les connexions qui empruntent ce tampon d'entrée/sortie.

Et, petite astuce d'implémentation (un routeur doit aller vite, et utilise souvent des circuits de calcul plus simples qu'un processeur généraliste), on peut calculer la durée de séjour minimale avec une seule variable : le temps écoulé depuis lequel la durée de séjour est inférieure ou supérieure au seuil choisi. (Dans le pseudo-code de la section 5, et dans le noyau Linux, c'est à peu près le rôle de first_above_time.)

Si vous aimez les explications avec images, il y en a plein dans cet excellent exposé à l'IETF.

Ensuite, l'objectif (appelé également référence) : il s'agit de fixer un objectif de durée de séjour dans la file. Apparemment, zéro serait l'idéal. Mais cela entrainerait des « sur-réactions », où on jetterait des paquets (et ralentirait TCP) dès qu'une file d'attente se forme. On va plutôt utiliser un concept dû à l'inventeur du datagramme, Leonard Kleinrock, dans « An Invariant Property of Computer Network Power », la « puissance » (power). En gros, c'est le débit divisé par le délai et l'endroit idéal, sur la courbe de puissance, est en haut (le maximum de débit, pour le minimum de délai). Après une analyse que je vous épargne, le RFC recommande de se fixer comme objectif entre 5 et 10 % du RTT.

Enfin, la boucle de rétroaction. Ce n'est pas tout d'observer, il faut agir. CoDel s'appuie sur la théorie du contrôle, pour un système MIMO (Multi-Input Multi-Output). Placé à la fin de la file d'attente, au moment où on décide quoi faire des paquets, ce contrôleur va les jeter (ou les marquer avec ECN) si l'objectif de durée de séjour est dépassé.

Passons maintenant à la section 4 du RFC, la plus concrète, puisqu'elle décrit précisement CoDel. L'algorithme a deux variables, TARGET et INTERVAL (ces noms sont utilisés tels quels dans le pseudo-code en section 5, et dans l'implémentation dans le noyau Linux). TARGET est l'objectif (le temps de séjour dans la file d'attente qu'on ne souhaite pas dépasser) et INTERVAL est la période d'observation. Ce dernier est également le seul paramètre de CoDel qu'il faut définir explicitement. Le RFC recommande 100 ms par défaut, ce qui couvre la plupart des RTT qu'on rencontre dans l'Internet, sauf si on parle à des gens très lointains ou si on passe par des satellites (cf. M. Dischinger, « Characterizing Residential Broadband Networks », dans les Proceedings of the Internet Measurement Conference, San Diego, en 2007, si vous voulez des mesures). Cela permet, par exemple, de vendre des routeurs bas de gamme, genre point d'accès Wifi sans imposer aux acheteurs de configurer CoDel.

Si on est dans un environnement très différent de celui d'un accès Internet « normal », il peut être nécessaire d'ajuster les valeurs (CoDel n'est donc pas réellement « parameterless »). L'annexe A du RFC en donne un exemple, pour le cas du centre de données, où les latences sont bien plus faibles (et les capacités plus grandes) ; INTERVAL peut alors être défini en microsecondes plutôt qu'en millisecondes.

TARGET, lui, va être déterminé dynamiquement par CoDel. Une valeur typique sera aux alentours de 5 ms (elle dépend évidemment de INTERVAL) : si, pendant une durée égale à INTERVAL, les paquets restent plus longtemps que cela dans la file d'attente, c'est que c'est une mauvaise file, on jette des paquets. Au passage, dans le noyau Linux, c'est dans codel_params_init que ces valeurs sont fixées :

 	params->interval = MS2TIME(100);
	params->target = MS2TIME(5);
   

Les programmeurs apprécieront la section 5, qui contient du pseudo-code, style C++, mettant en œuvre CoDel. Le choix de C++ est pour profiter de l'héritage, car CoDel est juste une dérivation d'un classique algorithme tail-drop. On peut donc le programmer sous forme d'une classe qui hérite d'une classe queue_t, plus générale.

De toute façon, si vous n'aimez pas C++, vous pouvez lire le code source du noyau Linux, qui met en œuvre CoDel depuis longtemps (fichier net/sched/sch_codel.c, également accessible via le Web.

(Pour comprendre les exemples de code, notez que packet_t* pointe vers un descripteur de paquet, incluant entre autres un champ, tstamp, qui stocke un temps, et que le type time_t est exprimé en unités qui dépendent de la résolution du système, sachant que la milliseconde est suffisante, pour du trafic Internet « habituel ».) Presque tout le travail de CoDel est fait au moment où le paquet sort de la file d'attente. À l'entrée, on se contente d'ajouter l'heure d'arrivée, puis on appelle le traitement habituel des files d'attente :

void codel_queue_t::enqueue(packet_t* pkt)
   {
       pkt->tstamp = clock();
       queue_t::enqueue(pkt);
   }       
     
Le gros du code est dans le sous-programme dodequeue qui va déterminer si le paquet individuel vient de nous faire changer d'état :

dodequeue_result codel_queue_t::dodequeue(time_t now)
   {
   ...
       // Calcul de *la* variable importante, le temps passé dans la
       // file d'attente
       time_t sojourn_time = now - r.p->tstamp;
       // S'il est inférieur à l'objectif, c'est bon
       if (sojourn_time_ < TARGET || bytes() <= maxpacket_) {
           first_above_time_ = 0;
       } else {
           // Aïe, le paquet est resté trop longtemps (par rapport à TARGET)
           if (first_above_time_ == 0) {
	       // Pas de panique, c'est peut-être récent, attendons
	       // INTERVAL avant de décider
               first_above_time_ = now + INTERVAL;
           } else if (now >= first_above_time_) {
               // La file ne se vide pas : jetons le paquet
               r.ok_to_drop = true;
           }
       }
       return r;
   }

     
Le résultat de dodequeue est ensuite utilisé par dequeue qui fait se fait quelques réflexions supplémentaires avant de jeter réellement le paquet.

Ce code est suffisamment simple pour pouvoir être mis en œuvre dans le matériel, par exemple ASIC ou NPU.

L'annexe A du RFC donne un exemple de déclinaison de CoDel pour le cas d'un centre de données, où les RTT typiques sont bien plus bas que sur l'Internet public. Cette annexe étudie également le cas où on applique CoDel aux files d'attente des serveurs, pas uniquement des routeurs, avec des résultats spectaculaires :

  • Dans le serveur, au lieu de jeter le paquet bêtement, on prévient directement TCP qu'il doit diminuer la fenêtre,
  • Le RTT est connu du serveur, et peut donc être mesuré au lieu d'être estimé (on en a besoin pour calculer INTERVAL),
  • Les paquets de pur contrôle (ACK, sans données) ne sont jamais jetés, car ils sont importants (et de petite taille, de toute façon).
Sur l'Internet public, il serait dangereux de ne jamais jeter les paquets de pur contrôle, ils pourraient être envoyés par un attaquant. Mais, dans le serveur, aucun risque.

2018-01-05

☕︎ Robust JavaScript

Still, JavaScript is the most brittle of all front-end web technologies. An important skill of a front-end developer is to know when not to solve a problem with client-side JavaScript. It is always more robust to solve a problem further down in the stack.

If all techniques and tools did not help you to write robust JavaScript, consider reducing the code complexity and the amount of code. In the last resort, reduce the usage of client-side JavaScript. Find simpler solutions that rely on HTML, CSS and server-side logic alone.

Robust Client-Side JavaScript (cache)

Best. Conclusion. Ever. Before thinking about progressive enhancement, discuss if the enhancement in itself is worth the price of development, maintenance, performance, accessibility and so on.

The most robust JavaScript is by far the one you avoid to push to production.

2018-01-04

☕︎ Requiem pour un flou

Redonnons de la place au flou, à l’indéterminé. Essayer de comprendre le cheminement d’une pensée, cela demande du temps, du cerveau, du cœur. Cela demande de se parler, de s’écouter. Cela demande aussi d’admettre que les failles, les faiblesses, les manques fassent partie du débat. Nos faiblesses. Et celles des autres.

Plaidoyer pour le flou … (cache)

Merci Virginie.

2018-01-03

☕︎ Evolution vs. Revolution

I was amazed by Joy and then I discovered Dynamicland:

No screens, no devices. Just ordinary physical materials — paper and clay, tokens and toy cars — brought to life by technology in the ceiling.

Every scrap of paper has the capabilities of a full computer, while remaining a fully-functional scrap of paper.

Dynamicland is a computer where people literally work together, face-to-face, with eye contact and many hands. It’s as multiplayer as the real world.

Impressive to say the least. Kudos to Bret Victor for turning his ideas into concrete projects.

★ Cheminer, espérer et contrôler

Car dans le monde animiste, il y a un mot pour dire que les être de la métamorphose deviennent la norme, prolifèrent, il y a un terme pour dire que l’on ne sait plus prédire le climat ou le comportement de la rivière… On appelle ça le temps mythique. C’est un temps particulier. Une forme du temps dont la spécificité était d’être à l’origine du monde et qui à la fois continue à exister. C’est un temps des origines qui subsiste et continue à travailler le présent pour nous inviter à stabiliser le futur.

Dans le temps du monde, on sait avec qui on entre en relation : on connait le comportement du loup, de la rivière, du caribou…, on sait comment entrer dans une relation soutenable avec eux. Dans le temps du mythe, les êtres et relations sont instables, métamorphiques, en train de se faire. Dans le temps du mythe, humains et animaux ne sont pas toujours distingués, les genres ne sont pas circonscrits. L’histoire des mythes, c’est l’histoire de personnages, de chamans, de héros… qui nouent des pactes avec les êtres de la métamorphose pour stabiliser des relations viables avec eux. Le temps du monde hérite de cette stabilité, permet de cohabiter de manière décente, honorable, soutenable, avec ceux avec qui nous partageons la terre.

Est-ce que ça sert à quelque chose de comprendre notre temps comme un retour du temps du mythe ?

De l’impossible habitabilité de l’anthropocène (cache)

Cheminer

Grosse envie de parcourir la forêt. Seul, accompagné, en canot, en famille, en toute saison. Un besoin de nouvelles nécessités, de nouveaux bruits, de (pré)occupations différentes. Trouver des lieux à partager, d’autres à garder intimes, explorer un territoire sans se l’approprier d’aucune façon. Juste être un parmi d’autres, être de la multitude qui vit.

Encore en pleine recherche entre légèreté et résilience, avancée et contemplation, dépense et économie. Après avoir gambadé en nature plus d’une décennie, envie de ralentir la foulée pour découvrir une nouvelle dimension.

Espérer

Aller chercher l’espoir là où il est encore possible. En trouvant un cadre bienveillant, en transmettant des énergies positives, en acquérant des compétences constructives. Enfouir les culpabilités irrésolvables faute de mieux, fuir les échanges toxiques au lieu de résister. Lâcher-prise et croire en l’hyperlocal, même si cela doit se limiter à une famille.

Et en parallèle, chercher la congruence. Encore et encore. Découvrir de nouvelles pratiques propres à une équipe donnée. Tisser de la confiance en produisant du périssable.

Contrôler

Reprendre possession de mes outils, la compréhension comme thérapie à la fatigue. L’aventure initiée avec Yohan sur pyrates m’a fait prendre conscience du bienfondé de la (ré)écriture afin de s’aligner techniquement tout en ayant un sentiment de maîtrise sur la chaîne de production de la valeur. Aux antipodes d’une aggrégation de bouts de configuration cryptiques ;-).

Mais cela va peut-être plus loin que la technique avec la réalisation de pain, la culture potagère ou la pêche opportuniste. Repartir de bases saines, ré-interroger des besoins vitaux. Itérer sur des basiques, sans snobisme. Une pratique de la différence pour s’accepter dans un monde uniformisant. Et tenter de comprendre ces autres.

Dans les épisodes précédents
???

Le médecin qui voulut être roi

Voici un excellent livre sur le colonialisme, à travers le cas d'un médecin français, Jean-Joseph David, qui, en poste à Wallis, puis au Cameroun, a obtenu les pleins pouvoirs, et s'est lancé dans une utopie, créer une société parfaite.

C'est une banalité de parler de pouvoir médical et de dire que le médecin se sent souvent placé au dessus des autres humains. Mais ici, dans les deux pays, David a en effet réussi à avoir la totalité des pouvoirs, médical, mais aussi économique, administratif, policier et judiciaire (il pouvait punir, et il ne s'en privait pas). Tout partait pourtant d'une idée sympathique, celle de la « médecine sociale », l'idée, en rupture avec la médecine pasteurienne, qu'on ne pouvait pas considérer la maladie comme le résultat de la seule action des microbes, mais qu'il fallait prendre en compte tout l'environnement. Mais cette idée a vite mené à un dérapage qu'on doit pouvoir qualifier de totalitaire. Le médecin s'est en effet senti en droit de réorganiser toute la société selon ses vues, évidemment sans jamais demander leur avis aux habitants.

Jean-Joseph David était-il gentil ou méchant ? Il traitait bien les indigènes, mais comme un éleveur traite bien son troupeau. Il ne les considérait pas comme des citoyens, même pas complètement comme des humains, quand il parlait d'« améliorer la race » ou bien d'amener beaucoup d'enfants à l'âge adulte pour que la France ait beaucoup de tirailleurs. Et ses utopies ont parfois eu des conséquences graves. Il était clairement mégalomane (« la mégalomanie est une maladie tropicale », note un ancien des interventions en Afrique à l'auteur) mais était aussi le produit de son époque (la culture du Pharo, où tous ces médecins coloniaux étaient formés par d'anciens coloniaux) et de l'éloignement (depuis Yaoundé, le gouverneur français le laissait faire ce qu'il voulait).

Le titre du livre fait évidemment référence à Kipling mais, ici, le héros ne cherche pas juste à être roi et à en avoir les avantages, il veut vraiment transformer la société.

Le livre est un peu décousu, d'abord parce qu'on a peu d'archives sur David (une grande partie a disparu dans les troubles qu'a connu le Cameroun par la suite), ensuite parce que ce n'est pas un roman, mais un travail plutôt universitaire, avec beaucoup de notions de sociologie et d'anthropologie qui nécessiteront que l·e·a lect·eur·rice s'accroche. Mais cela vaut la peine, il y a eu peu de descriptions de ce genre d'« utopies coloniales » où un mégalomane, profitant du pouvoir que lui donnait la force militaire de la France, se disait « je vais enfin pouvoir remodeler la société ». On est choqués de sa dictature et en même temps, c'est fascinant de se demander « et moi, si j'avais un tel pouvoir, j'en ferais quoi ? »

RFC 8307: Well-Known URIs for the WebSocket Protocol

Il existe une norme pour un préfixe de chemin dans un URI, préfixe nommée .well-known, et après lequel plusieurs noms sont normalisés, pour des ressources « bien connues », c'est-à-dire auxquelles on peut accéder sans lien qui y mène. Le RFC 5785 normalise ce .well-known. Il n'était prévu à l'origine que pour les plans http: et https:. Ce très court RFC l'étend aux plans ws: et wss:, ceux des Web sockets du RFC 6455.

Les gens de CoAP avaient déjà étendu l'usage de .well-known en permettant (RFC 7252) qu'il soit utilisé pour les plans coap: et coaps:.

Il existe un registre IANA des suffixes (les termes après .well-known). Ce registre est le même quel que soit le plan d'URI utilisé. Il ne change donc pas suite à la publication de ce RFC.

2018-01-02

☕︎ Oublier Internet

Bref, en continuant à défendre Internet tel qu’il est, nous continuons, selon Morozov, à défendre des valeurs dont nous ne comprenons pas nécessairement tous les fondements idéologiques et nous continuons à éluder bien des enjeux qui devraient pourtant être discutés à mesure qu’Internet perd de son lustre comme support à la démocratie et à l’émancipation et s’avèrent plutôt un cheval de Troie pour certaines philosophies.

Morozov: oublier internet (cache)

Je m’interroge depuis un moment sur la conciliation entre la promotion d’un réseau décentralisé et mes revenus découlant directement de cette centralisation. Quel modèle économique — en tant que développeur — pour un autre Internet ? Quelle solvabilité autour d’un réseau marginal ?

2018-01-01

☕︎ Data portability

Third, while many speak about data portability in terms of providing access to “your data”, in reality data shared with third parties may include personal data about other people too. This might include data directly about other people in your social graph, or in your household, or with whom you transact through a peer-to-peer service. Similarly, it may include commercially sensitive data about businesses you frequent or charities you donate to. When analysed in bulk, data about a sample of the population becomes information about people who were not included directly in the analysis. For example, data about my shopping habits may be used to make guesses about the shopping habits of other middle class, middle aged mothers of two. Data about us is never only about us.

Data portability (cache)

In a relationship, my data becomes your data. In a global network, it gets even more complex. Share wisely, owning the place you publish to at least allows you to control it over time.

I really wonder how the General Data Protection Regulations (GDPR) will interact with paradigm shifts for the decentralized Web (cache). And how centralized silos will counterattack.

La mer des Cosmonautes

Il fait froid dehors, en ce début 2018 ? Voici un livre pour se réchauffer : partez en Antarctique avec les polyarniks russes.

Ce n'est pas un roman, mais un témoignage de l'auteur, qui est allé en Antarctique (en été, quand même…) à bord du Akademik Fedorov et en a rapporté plein d'histoires de travailleurs polaires. Et, oui, la mer des Cosmonautes du titre existe vraiment.

Le temps des explorateurs polaires avec trois types et quinze chiens qui se lançaient à l'assaut du continent blanc est passé : les bases sont maintenant bien plus grandes et peuplées, avec une débauche de matériel. Dans les bases russes, on trouve tous les fleurons de l'ex-industrie soviétique, devenues souvent épaves, de l'Iliouchine 14 au GAZ-69. On est maintenant dans l'exploitation plus que l'exploration. Mais les conditions de vie restent difficiles : le matériel casse, les humains s'épuisent, l'accident guette dès qu'on sort, il faut parfois allumer un feu sous le bulldozer pour qu'il démarre. Et les Russes prennent apparemment moins de précautions avec le matériel humain, alimentant le cimetière qui jouxte une des bases.

Mais pourquoi trouve-t-on des volontaires pour l'Antarctique ? À l'époque soviétique, une des raisons était le prestige attaché au métier de polyarnik. Leur prestige ne le cédait qu'aux cosmonautes, héros souvent cités par les polyarniks nostalgiques « à cette époque, on était quasiment aussi adulés que les cosmonautes », et les gamins dans les cours d'école jouaient en alternance au cosmonaute et au travailleur polaire. Tout ceci s'est effondré avec l'Union Soviétique, au point que, dans certaines bases, il a fallu vendre les breloques à étoile rouge aux touristes états-uniens de la base voisine, pour pouvoir se financer. Il n'y a plus qu'en Biélorussie, gelée dans les années Brejnev, que les polyarniks sont encore accueillis avec médailles et discours, à leur retour.

Aujourd'hui, la Russie continue l'exploitation antarctique, mais avec un nombre de bases réduit. Des nouveaux pays sont venus, et on s'échange les visites de courtoisie, dans ce territoire démilitarisé. Le travailleur polaire continue de bénéficier d'avantages matériels conséquents, et garde un peu de prestige, pas à cause de l'Antarctique, mais à cause des escales exotiques que fait le navire avant d'atteindre le continent blanc. Et puis, certains travailleurs le confient à l'auteur : après plusieurs rotations en Antarctique, ils ne se voient pas vraiment reprendre une vie « normale ».

En ligne, les photos de l'auteur.

2017-12-24

Géolocation d'une adresse IP via le DNS

Pour Noël, un truc complètement inutile mais amusant : trouver la longitude et la latitude d'une adresse IP via le DNS.

Ce service est fourni par Bert Hubert, l'auteur de PowerDNS, via le domaine geo.lua.powerdns.org. (Il ne marche apparemment que pour IPv4.) On inverse l'adresse IP (comme pour in-addr.arpa) et on fait une requête pour le type TXT. Exemple avec l'adresse du serveur Web de l'AFNIC, 192.134.5.24 :

      
% dig TXT 24.5.134.192.geo.lua.powerdns.org
...;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40951
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 1
...
;; ANSWER SECTION:
24.5.134.192.geo.lua.powerdns.org. 3600	IN TXT "48.858200 2.338700"

    

On peut automatiser l'opération avec awk (merci à Oli Schacher‏) :

% reverse() { echo $1  | awk -F. '{print $4"."$3"." $2"."$1}' }

% reverse 192.134.5.24
24.5.134.192
    
Une fois que c'est fait, on peut lancer un navigateur Web directement vers la carte, ici avec OpenStreetMap :

% show-ip() { x-www-browser https://www.openstreetmap.org/\?$(dig  $(echo $1 | awk -F. '{print $4"."$3"." $2"."$1}').geo.lua.powerdns.org TXT +short | head -1 | awk '{gsub(/"/, ""); print "mlat="$1"&mlon="$2"&zoom=12"}')}         

% show-ip 192.134.5.24

    
Et si vous préférez Evil Corp. :

% show-ip() { x-www-browser https://maps.google.com/maps\?q=$(dig  $(echo $1 | awk -F. '{print $4"."$3"." $2"."$1}').geo.lua.powerdns.org TXT +short | awk '{gsub(/"/, ""); print $1","$2}')}

    

La base de géolocalisation utilisée est celle de MaxMind qui, comme toutes les bases de géolocalisation vaut ce qu'elle vaut (le serveur Web de l'AFNIC n'est pas au centre de Paris…)

2017-12-22

✍ Lettre à Thomas

Thomas,

Suite d’une discussion récente inachevée faute de temps, au sujet de l’expatriation. Ou plutôt du sentiment que les choses bougent davantage en France au point de vouloir y revenir. Il s’agit d’un ressenti que j’ai eu en étant au Japon et qui m’a en partie motivé pour revenir. J’avais alors oublié les raisons du mouvement, ce mal-être latent qui devient le terreau fertile de nouvelles idées. Il y a une beauté et une énergie dans ce foisonnement mais les conditions pour y arriver me sont de plus en plus insupportables. Je n’ai plus envie d’un état d’urgence mais d’un état de bienveillance, quitte à devoir m’éloigner pour cela de l’innovation et la disruption.

Bien sûr, le prix à payer est élevé : les réflexions philosophiques me manquent, les mises en communs me manquent, de nombreuses rencontres me sont maintenant beaucoup moins accessibles. J’apprends à vivre avec et je sais que je pourrais être moteur de nouvelles initiatives dans d’autres lieux une fois acclimaté. Les réflexions y seront peut-être moins poussées compte tenu de la plus faible pression du milieu et les actions en découlant seront probablement différentes, à l’origine de l’évolution d’une culture locale.

David

2017-12-21

RFC 8305: Happy Eyeballs Version 2: Better Connectivity Using Concurrency

Une machine connectée à l'Internet et répondant aux requêtes venues du réseau a souvent plusieurs adresses IP pour son nom. C'est parfois une adresse IPv4 et une IPv6 mais cela peut aussi être plusieurs adresses IPv6, ou bien un mélange en proportions quelconques. Les développeurs d'application et les administrateurs système qui déploieront ces applications ensuite, ont un choix difficile si certaines de ces adresses marchent et d'autres pas (ou mal). Si les différentes adresses IP de cette machine passent par des chemins différents, certains marchant et d'autres pas, l'application arrivera-t-elle à se rabattre sur une autre adresse très vite ou bien imposera-t-elle à l'utilisateur un long délai avant de détecter enfin le problème ? Cette question est connue comme « le bonheur des globes oculaires » (les dits globes étant les yeux de l'utilisateur qui attend avec impatience la page d'accueil de PornHub) et ce RFC spécifie les exigences pour l'algorithme de connexion du client. En les suivant, les globes oculaires seront heureux. Il s'agit de la version 2 de l'algorithme, bien plus élaborée que la version 1 qui figurait dans le RFC 6555.

La section 1 rappelle les données du problème : on veut évidemment que cela marche aussi bien en IPv6 (RFC 8200) qu'en IPv4 (pas question d'accepter des performances inférieures) or, dans l'état actuel du déploiement d'IPv6, bien des sites ont une connexion IPv6 totalement ou partiellement cassée. Si un serveur a IPv4 et IPv6 et que son client n'a qu'IPv4, pas de problème. Mais si le client a IPv6, tente de l'utiliser, mais que sa connexion est plus ou moins en panne, ou simplement sous-optimale, ses globes oculaires vont souffrir d'impatience. On peut aussi noter que le problème n'est pas spécifique à IPv6 : du moment que la machine visée a plusieurs adresses, qu'elles soient IPv4 ou IPv6, le risque que certaines des adresses ne marchent pas (ou moins bien) existe, et l'algorithme des globes oculaires heureux doit être utilisé. (C'est un des gros changements avec le précédent RFC, le RFC 6555, qui n'envisageait que le cas IPv6.)

La bonne solution est donc que l'application elle-même gère le problème (ou, sinon l'application elle-même, la bibliothèque logicielle qu'elle utilise et où se trouve la fonction de connexion). Il existe plusieurs algorithmes pour cela, déjà largement déployés depuis des années. On peut donc se baser sur l'expérience pour spécifier ces algorithmes. Ce RFC normalise les caractéristiques que doivent avoir ces algorithmes. Si on suit ce RFC, le trafic (IP et DNS) va légèrement augmenter (surtout si la connectivité IPv6 marche mal ou pas du tout) mais la qualité du vécu de l'utilisateur va être maintenue, même en présence de problèmes, ce qui compense largement. Autrement, il existerait un risque élevé que certains utilisateurs coupent complètement IPv6, plutôt que de supporter ces problèmes de délai de connexion.

La cible principale de notre RFC est composée des protocoles de transport avec connexion (TCP, SCTP), les protocoles sans connexion comme UDP soulevant d'autres questions (s'ils ont une sémantique requête/réponse, comme dans ICE, les algorithmes de ce RFC peuvent être utilisés).

Donc, on a un nom de machine qu'on veut contacter, mettons www.example.com, avec plusieurs adresses associées, peut-être de familles (v4 et v6) différentes. Prenons une machine ayant une seule adresse IPv4 et une seule adresse IPv6, avec une connexion IPv6 qui marche mal. Avec l'algorithme naïf qu'utilisent encore certains logiciels voici la séquence d'évenements traditionnelle :

  • L'initiateur de la connexion utilise le DNS pour demander les enregistrements A (adresse IPv4) et AAAA (IPv6).
  • Il récupère 192.0.2.1 et 2001:db8::1.
  • Il tente IPv6 (sur Linux, l'ordre des essais est réglable dans /etc/gai.conf). L'initiateur envoie un paquet TCP SYN à 2001:db8::1.
  • Pas de réponse (connexion IPv6 incorrecte). L'initiateur réessaie, deux fois, trois fois, faisant ainsi perdre de nombreuses secondes.
  • L'initiateur renonce, il passe à IPv4 et envoie un paquet TCP SYN à 192.0.2.1.
  • Le répondeur envoie un SYN+ACK en échange, l'initiateur réplique par un ACK et la connexion TCP est établie.
Le problème de cet algorithme naïf est donc la longue attente lors des essais IPv6. On veut au contraire un algorithme qui bascule rapidement en IPv4 lorsqu'IPv6 ne marche pas, sans pour autant gaspiller les ressources réseau en essayant par exemple toutes les adresses en même temps.

L'algorithme recommandé (sections 3 à 5, cœur de ce RFC) aura donc l'allure suivante :

  • L'initiateur de la connexion utilise le DNS pour demander les enregistrements A (adresse IPv4) et AAAA (IPv6).
  • Il récupère 192.0.2.1 et 2001:db8::1. Il sait donc qu'il a plusieurs adresses, de famille différente.
  • Il tente IPv6 (l'algorithme du RFC est de toute façon facilement adaptable à des cas où IPv4 est prioritaire). L'initiateur envoie un paquet TCP SYN à 2001:db8::1, avec un très court délai de garde.
  • Pas de réponse quasi-immédiate ? L'initiateur passe à IPv4 rapidement. Il envoie un paquet TCP SYN à 192.0.2.1.
  • Le répondeur envoie un SYN+ACK en échange, l'initiateur réplique par un ACK et la connexion TCP est établie.
Si le répondeur réagit à une vitesse normale en IPv6, la connexion sera établie en IPv6. Sinon, on passera vite en IPv4, et l'utilisateur humain ne s'apercevra de rien. Naturellement, si le DNS n'avait rapporté qu'une seule adresse (v4 ou v6), on reste à l'algorithme traditionnel (« essayer, patienter, ré-essayer »).

Maintenant, les détails. D'abord, le DNS (section 3 de notre RFC). Pour récupérer les adresses appartenant aux deux familles (IPv4 et IPv6), il faut envoyer deux requêtes, de type A et AAAA. Pas de délai entre les deux, et le AAAA en premier, recommande le RFC. Notez qu'il n'existe pas de type de requête DNS pour avoir les deux enregistrements d'un coup, il faut donc deux requêtes.

Il ne faut pas attendre d'avoir la réponse aux deux avant de commencer à tenter d'établir une connexion. En effet, certains pare-feux configurés avec les pieds bloquent les requêtes AAAA, qui vont finir par timeouter. Du point de vue du programmeur, cela signifie qu'il faut faire les deux requêtes DNS dans des fils différents (ou des goroutines différentes en Go), ou bien, utiliser une API asynchrone, comme getdns. Ensuite, si on reçoit la réponse AAAA mais pas encore de A, on essaye tout de suite de se connecter, si on a la réponse A, on attend quelques millisecondes la réponse AAAA puis, si elle ne vient pas, tant pis, on essaie en IPv4. (La durée exacte de cette attente est un des paramètres réglables de l'algorithme. Il se nomme Resolution Delay et sa valeur par défaut recommandée est de 50 ms.)

À propos de DNS, notez que le RFC recommande également de privilégier IPv6 pour le transport des requêtes DNS vers les résolveurs (on parle bien du transport des paquets DNS, pas du type des données demandées). Ceci dit, ce n'est pas forcément sous le contrôle de l'application.

Une fois récupérées les adresses, on va devoir les trier selon l'ordre de préférence. La section 4 décrit comment cela se passe. Rappelons qu'il peut y avoir plusieurs adresses de chaque famille, pas uniquement une v4 et une v6, et qu'il est donc important de gérer une liste de toutes les adresses reçues (imaginons qu'on ne récupère que deux adresses v4 et aucune v6 : l'algorithme des globes oculaires heureux est quand même crucial car il est parfaitement possible qu'une des adresses v4 ne marche pas).

Pour trier, le RFC recommande de suivre les règles du RFC 6724, section 6. Si le client a un état (une mémoire des connexions précédentes, ce qui est souvent le cas chez les clients qui restent longtemps à tourner, un navigateur Web, par exemple), il peut ajouter dans les critères de tri le souvenir des succès (ou échecs) précédents, ainsi que celui des RTT passés. Bien sûr, un changement de connectivité (détecté par le DNA des RFC 4436 ou RFC 6059) doit entraîner un vidage complet de l'état (on doit oublier ce qu'on a appris, qui n'est plus pertinent).

Dernier détail sur le tri : il faut mêler les adresses des deux familles. Imaginons un client qui récupère trois adresses v6 et trois v4, client qui donne la priorité à IPv4, mais dont la connexion IPv4 est défaillante. Si sa liste d'adresses à tester comprend les trois adresses v4 en premier, il devra attendre trois essais avant que cela ne marche. Il faut donc plutôt créer une liste {une adressse v4, une adresse v6, une adresse v4…}. Le nombre d'adresses d'une famille à inclure avant de commencer l'autre famille est le paramètre First Address Family Count, et il vaut un par défaut.

Enfin, on essaie de se connecter en envoyant des paquets TCP SYN (section 5). Il est important de ne pas tester IPv4 tout de suite. Les premiers algorithmes « bonheur des globes oculaires » envoyaient les deux paquets SYN en même temps, gaspillant des ressources réseau et serveur. Ce double essai faisait que les équipements IPv4 du réseau avaient autant de travail qu'avant, alors qu'on aurait souhaité les retirer du service petit à petit. En outre, ce test simultané fait que, dans la moitié des cas, la connexion sera établie en IPv4, empêchant de tirer profit des avantages d'IPv6 (cf. RFC 6269). Donc, on doit tester en IPv6 d'abord, sauf si on se souvient des tentatives précédentes (voir plus loin la variante « avec état ») ou bien si l'administrateur système a délibérement configuré la machine pour préférer IPv4.

Après chaque essai, on attend pendant une durée paramétrable, Connection Attempt Delay, 250 ms par défaut (bornée par les paramètres Minimum Connection Attempt Delay, 100 ms par défaut, qu'on ne devrait jamais descendre en dessous de 10 ms, et Maximum Connection Attempt Delay, 2 s par défaut).

L'avantage de cet algorithme « IPv6 d'abord puis rapidement basculer en IPv4 » est qu'il est sans état : l'initiateur n'a pas à garder en mémoire les caractéristiques de tous ses correspondants. Mais son inconvénient est qu'on recommence le test à chaque connexion. Il existe donc un algorithme avec état (cf. plus haut), où l'initiateur peut garder en mémoire le fait qu'une machine (ou bien un préfixe entier) a une adresse IPv6 mais ne répond pas aux demandes de connexion de cette famille. Le RFC recommande toutefois de re-essayer IPv6 au moins toutes les dix minutes, pour voir si la situation a changé.

Une conséquence de l'algorithme recommandé est que, dans certains cas, les deux connexions TCP (v4 et v6) seront établies (si le SYN IPv6 voyage lentement et que la réponse arrive après que l'initiateur de la connexion se soit impatienté et soit passé à IPv4). Cela peut être intéressant dans certains cas rares, mais le RFC recommande plutôt d'abandonner la connexion perdante (la deuxième). Autrement, cela pourrait entraîner des problèmes avec, par exemple, les sites Web qui lient un cookie à l'adresse IP du client, et seraient surpris de voir deux connexions avec des adresses différentes.

La section 9 du RFC rassemble quelques derniers problèmes pratiques. Par exemple, notre algorithme des globes oculaires heureux ne prend en compte que l'établissement de la connexion. Si une adresse ne marche pas du tout, il choisira rapidement la bonne. Mais si une adresse a des problèmes de MTU et pas l'autre, l'établissement de la connexion, qui ne fait appel qu'aux petits paquets TCP SYN, se passera bien alors que le reste de l'échange sera bloqué. Une solution possible est d'utiliser l'algorithme du RFC 4821.

D'autre part, l'algorithme ne tient compte que de la possibilité d'établir une connexion TCP, ce qui se fait typiquement uniquement dans le noyau du système d'exploitation du serveur. L'algorithme ne garantit pas qu'une application écoute, et fonctionne.

Parmi les problèmes résiduels, notez que l'algorithme des globes oculaires heureux est astucieux, mais tend à masquer les problèmes (section 9.3). Si un site Web publie les deux adresses mais que sa connectivité IPv6 est défaillante, aucun utilisateur ne lui signalera puisque, pour eux, tout va bien. Il est donc recommandé que l'opérateur fasse des tests de son côté pour repérer les problèmes (le RFC 6555 recommandait que le logiciel permette de débrayer cet algorithme, afin de tester la connectivité avec seulement v4 ou seulement v6, ou bien que le logiciel indique quelque part ce qu'il a choisi, pour mieux identifier d'éventuels problèmes v6.)

Pour le délai entre le premier SYN IPv6 et le premier SYN IPv4, la section 5 donne des idées quantitatives en suggérant 250 ms entre deux essais. C'est conçu pour être quasiment imperceptible à un utilisateur humain devant son navigateur Web, tout en évitant de surcharger le réseau inutilement. Les algorithmes avec état ont le droit d'être plus impatients, puisqu'ils peuvent se souvenir des durées d'établissement de connexion précédents.

Notez que les différents paramètres réglables indiqués ont des valeurs par défaut, décrites en section 8, et qui ont été déterminées empiriquement.

Si vous voulez une meilleure explication de la version 2 des globes oculaires heureux, il y a cet exposé au RIPE.

Enfin, les implémentations. Notez que les vieilles mises en œuvre du RFC 6555 (et présentées à la fin de mon précédent article) sont toujours conformes à ce nouvel algorithme, elles n'en utilisent simplement pas les raffinements. Les versions récentes de macOS (Sierra) et iOS (10) mettent en œuvre notre RFC, ce qui est logique, puisqu'il a été écrit par des gens d'Apple (l'annonce est ici, portant même sur des versions antérieures). Apple en a d'ailleurs profité pour breveter cette technologie. À l'inverse, un exemple récent de logiciel incapable de gérer proprement le cas d'un pair ayant plusieurs adresses IP est Mastodon (cf. bogue #3762.)

Dans l'annexe A, vous trouverez la liste complète des importants changements depuis le RFC 6555. Le précédent RFC n'envisageait qu'un seul cas, deux adresses IP, une en v4, l'autre en v6. Notre nouveau RFC 8305 est plus riche, augmente le parallélisme, et ajoute :

  • La façon de faire les requêtes DNS (pour tenir compte des serveurs bogués qui ne répondent pas aux requêtes AAAA, cf. RFC 4074),
  • La gestion du cas où il y a plusieurs adresses IP de la même famille (v4 ou v6),
  • La bonne façon d'utiliser les souvenirs des connexions précédentes,
  • Et la méthode (dont je n'ai pas parlé ici) pour le cas des réseaux purement IPv6, mais utilisant le NAT64 du RFC 8305.

2017-12-20

★ Œuvrier du Web

J’emprunte ce terme à Roland Feuillas dans À la recherche du pain vivant qui parle davantage d’œuvriers paysans que d’œuvriers du web mais c’est la traduction que je trouve la plus juste de Web crafter que j’utilise maintenant en anglais pour définir mon métier : mettre en œuvre des connaissances et de l’empathie afin d’améliorer un irritant.

Je préfère de loin le terme crafter à celui de craftmanship qui comporte ce man excluant et ne s’inscrit pas dans l’action ; mais j’avais toujours du mal à trouver comment l’expliquer en français. Québec oblige, je réfléchis beaucoup au sens des mots et à leurs traductions en ce moment. Je repense souvent à Julien — qui m’a initié à la programmation — me répétant sans cesse « traduction == trahison ». Quid d’un néologisme ?

Je m’interroge encore et toujours sur ma valeur ajoutée à un produit. J’ai de plus en plus la croyance qu’elle vient de ma capacité — issue de l’expérience — à pouvoir remettre en question ce que j’ai développé à une échelle plus courte qu’auparavant. Être en capacité de ré-agencer avant que cela devienne critique en terme de dette technique. Or cette valeur est très difficile à appréhender car elle n’est interprétable qu’à la lumière d’une temporalité longue. Ce qui semble être aujourd’hui une perte de temps et un démarrage poussif devient après-demain indispensable pour pouvoir aller plus loin sereinement et/ou transmettre le produit ainsi que la connaissance acquise en le concevant.

Il y n’a que deux difficultés en informatique : choisir ses maux et invalider ses croyances. Il me reste encore beaucoup à explorer dans ces domaines, avec humilité.

???

RFC 8297: An HTTP Status Code for Indicating Hints

Lorsqu'un serveur HTTP répond, la réponse contient souvent des liens vers d'autres ressources. Un exemple typique est celui de la page Web dont le chargement va déclencher le chargement de feuilles de style, de JavaScript, etc. Pour minimiser la latence, il serait intéressant de prévenir le client le plus tôt possible. C'est le but de ce RFC, qui décrit le code de retour intérimaire 103, qui prévient le client qu'il peut tout de suite commencer à charger ces ressources supplémentaires.

Il existe un type de lien pour cela, preload, décrit par ses auteurs et enregistré dans le registre des types de liens (cf. RFC 8288). Il peut être utilisé dans la réponse « normale » :


HTTP/1.1 200 OK
Date: Fri, 26 May 2017 10:02:11 GMT
Content-Length: 1234
Content-Type: text/html; charset=utf-8
Link: </main.css>; rel="preload"; as="style"
Link: </script.js>; rel="preload"; as="script"    

    
Mais cela ne fait pas gagner grand'chose : une toute petite fraction de seconde après, le client HTTP verra arriver le source HTML et pourra y découvrir les liens. On voudrait renvoyer tout de suite la liste des ressources à charger, sans attendre que le serveur ait fini de calculer la réponse (ce qui peut prendre du temps, s'il faut dérouler mille lignes de Java et plein de requêtes SQL…)

Le nouveau code de retour, 103, lui, peut être envoyé immédiatement, avec la liste des ressources. Le client peut alors les charger, tout en attendant le code de retour 200 qui indiquera que la ressource principale est prête. (Les codes de retour commençant par 1, comme 103, sont des réponses temporaires, « pour information », en attendant le succès, annoncé par un code commençant par 2. Cf. RFC 7231, sections 6.2 et 6.3.) La réponse HTTP utilisant le nouveau code ressemblera à :


HTTP/1.1 103 Early Hints
Link: </main.css>; rel="preload"; as="style"
Link: </script.js>; rel="preload"; as="script"

HTTP/1.1 200 OK
Date: Fri, 26 May 2017 10:02:11 GMT
Content-Length: 1234
Content-Type: text/html; charset=utf-8
Link: </main.css>; rel="preload"; as="style"
Link: </script.js>; rel="preload"; as="script"    

Les détails, maintenant (section 2 du RFC). 103 indique au client qu'il y aura une série de liens vers des ressources supplémentaires qu'il peut être intéressant, par exemple, de charger tout de suite. Les liens finaux seront peut-être différents (dans l'exemple ci-dessus, ils sont identiques). 103 est juste une optimisation, pas une obligation. (Hint = suggestion.) Les liens qu'il indique ne font pas autorité. Le serveur peut indiquer des liens supplémentaires, ne pas indiquer des liens qui étaient dans la réponse 103, indiquer des liens différents, etc.

Il peut même y avoir plusieurs 103 à la suite, notamment si un relais sur le trajet ajoute le sien, par exemple en se basant sur une réponse qu'il avait gardée en mémoire. 103 n'est en effet pas toujours envoyé par le serveur d'origine de la ressource, il peut l'être par un intermédiaire. Voici un exemple qui donne une idée des variantes possibles :


HTTP/1.1 103 Early Hints
Link: </main.css>; rel="preload"; as="style"

HTTP/1.1 103 Early Hints
Link: </style.css>; rel="preload"; as="style"
Link: </script.js>; rel="preload"; as="script"

HTTP/1.1 200 OK
Date: Fri, 26 May 2017 10:02:11 GMT
Content-Length: 1234
Content-Type: text/html; charset=utf-8
Link: </main.css>; rel="preload"; as="style"
Link: </newstyle.css>; rel="preload"; as="style"
Link: </script.js>; rel="preload"; as="script"

On voit que la réponse finale n'est ni la première suggestion, ni la deuxième (ni une union des deux).

Note pour les programmeurs Python/WSGI. Je ne suis pas arrivé à utiliser ce code « intérimaire » avec WSGI, cela ne semble pas possible en WSGI. Mais on trouvera sans doute d'autres implémentations…

Le code 103 est désormais dans le registre IANA des codes de retour.

2017-12-14

RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format

Il existe une pléthore de langages pour décrire des données structurées. JSON, normalisé dans ce RFC (qui succède au RFC 7159, avec peu de changements), est actuellement le plus à la mode. Comme son concurrent XML, c'est un format textuel, et il permet de représenter des structures de données hiérarchiques.

À noter que JSON doit son origine, et son nom complet (JavaScript Object Notation) au langage de programmation JavaScript, dont il est un sous-ensemble (enfin, approximativement). La norme officielle de JavaScript est à l'ECMA, dans ECMA-262. JSON est dans la section 24.5 de ce document mais est aussi dans ECMA-404, qui lui est réservé. Les deux normes, ce RFC et la norme ECMA, sont écrites de manière différente mais, en théorie, doivent aboutir au même résultat. ECMA et l'IETF sont censés travailler ensemble pour résoudre les incohérences (aucune des deux organisations n'a, officiellement, le dernier mot).

Contrairement à JavaScript, JSON n'est pas un langage de programmation, seulement un langage de description de données, et il ne peut donc pas servir de véhicule pour du code méchant (sauf si on fait des bêtises comme de soumettre du texte JSON à eval(), cf. section 12 et erratum #3607 qui donne des détails sur cette vulnérabilité).

Voici un exemple, tiré du RFC, d'un objet exprimé en JSON :

  {
      "Image": {
          "Width":  800,
          "Height": 600,
          "Title":  "View from 15th Floor",
          "Thumbnail": {
              "Url":    "http://www.example.com/image/481989943",
              "Height": 125,
              "Width":  "100"
          },
          "IDs": [116, 943, 234, 38793]
        }
   }
Les détails de syntaxe sont dans la section 2 du RFC. Cet objet d'exemple a un seul champ, Image, qui est un autre objet (entre { et }) et qui a plusieurs champs. (Les objets sont appelés dictionnaires ou maps dans d'autres langages.) L'ordre des éléments de l'objet n'est pas significatif (certains analyseurs JSON le conservent, d'autres pas). Un de ces champs, IDs, a pour valeur un tableau (entre [ et ]). Les éléments d'un tableau ne sont pas forcément du même type (section 5). Un texte JSON n'est pas forcément un objet ou un tableau, par exemple  :
"Hello world!"
est un texte JSON légal (composé d'une chaîne de caractères en tout et pour tout). Une des conséquences est qu'un lecteur de JSON qui lit au fil de l'eau peut ne pas savoir si le texte est fini ou pas (il ne suffit pas de compter les crochets et accolades). À part les objets, les tableaux et les chaînes de caractères, un texte JSON peut être un nombre, ou bien un littéral, false, true ou null.

Et quel encodage utiliser pour les textes JSON (section 8) ? Le RFC 4627 était presque muet à ce sujet. Cette question est désormais plus développée. Le jeu de caractères est toujours Unicode et l'encodage est obligatoirement UTF-8 dès qu'on envoie du JSON par le réseau (bien des mises en œuvre de JSON ne peuvent en lire aucun autre). Les textes JSON transmis par le réseau ne doivent pas utiliser de BOM.

Lorsqu'on envoie du JSON par le réseau, le type MIME à utiliser est application/json.

Autre problème classique d'Unicode, la comparaison de chaînes de caractères. Ces comparaisons doivent se faire selon les caractères Unicode et pas selon les octets (il y a plusieurs façons de représenter la même chaîne de caractères, par exemple foo*bar et foo\u002Abar sont la même chaîne).

JSON est donc un format simple, il n'a même pas la possibilité de commentaires dans le fichier... Voir sur ce sujet une intéressante compilation.

Le premier RFC décrivant JSON était le RFC 4627, remplacé ensuite par le RFC 7159. Quels changements apporte cette troisième révision (annexe A) ? Elle corrige quelques erreurs, résout quelques incohérences avec le texte ECMA, et donne des avis pratiques aux programmeurs. Les principaux changements :

Voici un exemple d'un programme Python pour écrire un objet Python en JSON (on notera que la syntaxe de Python et celle de JavaScript sont très proches) :

import json

objekt = {u'Image': {u'Width': 800,
                     u'Title': u'View from Smith\'s, 15th Floor, "Nice"',
                     u'Thumbnail': {u'Url':
                                    u'http://www.example.com/image/481989943',
                                    u'Width': u'100', u'Height': 125},
                     u'IDs': [116, 943, 234, 38793],
                     u'Height': 600}} # Example from RFC 4627, lightly modified

print(json.dumps(objekt))
Et un programme pour lire du JSON et le charger dans un objet Python :
import json

# One backslash for Python, one for JSON
objekt = json.loads("""
{
      "Image": {
          "Width":  800,
          "Height": 600,
          "Title":  "View from Smith's, 15th Floor, \\\"Nice\\\"", 
          "Thumbnail": {
              "Url":    "http://www.example.com/image/481989943",
              "Height": 125,
              "Width":  "100"
          },
          "IDs": [116, 943, 234, 38793]
        }
   }
""") # Example from RFC 4267, lightly modified

print(objekt)
print("")
print(objekt["Image"]["Title"])

Le code ci-dessus est très simple car Python (comme Perl ou Ruby ou, bien sûr, JavaScript) a un typage complètement dynamique. Dans les langages où le typage est plus statique, c'est moins facile et on devra souvent utiliser des méthodes dont certains programmeurs se méfient, comme des conversions de types à l'exécution. Si vous voulez le faire en Go, il existe un bon article d'introduction au paquetage standard json. Un exemple en Go figure plus loin, pour analyser la liste des stations de la RATP.

Pour Java, qui a le même « problème » que Go, il existe une quantité impressionnante de bibliothèques différentes pour faire du JSON (on trouve en ligne plusieurs tentatives de comparaison). J'ai utilisé JSON Simple. Lire un texte JSON ressemble à :

import org.json.simple.*;
...
Object obj=JSONValue.parse(args[0]);
if (obj == null) { // May be use JSONParser instead, it raises an exception when there is a problem
	    System.err.println("Invalid JSON text");
	    System.exit(1);
} else {
	    System.out.println(obj);
}

JSONObject obj2=(JSONObject)obj; // java.lang.ClassCastException if not a JSON object
System.out.println(obj2.get("foo")); // Displays member named "foo"
Et le produire :
JSONObject obj3=new JSONObject();
obj3.put("name","foo");
obj3.put("num",new Integer(100));
obj3.put("balance",new Double(1000.21));
obj3.put("is_vip",new Boolean(true));

Voyons maintenant des exemples réels avec divers outils de traitement de JSON. D'abord, les données issues du service de vélos en libre-service Vélo'v. C'est un gros JSON qui contient toutes les données du système. Nous allons programmer en Haskell un programme qui affiche le nombre de vélos libres et le nombre de places disponibles. Il existe plusieurs bibliothèques pour faire du JSON en Haskell mais Aeson semble la plus utilisée. Haskell est un langage statiquement typé, ce qui est loin d'être idéal pour JSON. Il faut déclarer des types correspondant aux structures JSON :

     
data Velov =
  Velov {values :: [Station]} deriving Show
  
instance FromJSON Velov where
 parseJSON (Object v) =
    Velov <$> (v .: "values") 

data Station =
  Station {stands :: Integer,
           bikes :: Integer,
           available :: Integer} deriving Show

data Values = Values [Station]

   
Mais ça ne marche pas : les nombres dans le fichier JSON ont été représentés comme des chaînes de caractères ! (Cela illustre un problème fréquent dans le monde de JSON et de l'open data : les données sont de qualité technique très variable.) On doit donc les déclarer en String :
data Station =
  Station {stands :: String,
           bikes :: String,
           available :: String} deriving Show
   
Autre problème, les données contiennent parfois la chaîne de caractères None. Il faudra donc filtrer avec la fonction Haskell filter. La fonction importante filtre les données, les convertit en entier, et en fait la somme grâce à foldl :
sumArray a =
  show (foldl (+) 0 (map Main.toInteger (filter (\i -> i /= "None") a)))
   
Le programme complet est velov.hs. Une fois compilé, testons-le :
% curl -s https://download.data.grandlyon.com/ws/rdata/jcd_jcdecaux.jcdvelov/all.json | ./velov   
"Stands: 6773"
"Bikes: 2838"
"Available: 3653"
   
Je n'ai pas utilisé les dates contenues dans ce fichier mais on peut noter que, si elles sont exprimées en ISO 8601 (ce n'est hélas pas souvent le cas), c'est sans indication du fuseau horaire (celui en vigueur à Lyon, peut-on supposer).

Un autre exemple de mauvais fichier JSON est donné par Le Monde avec la base des députés français. Le fichier est du JavaScript, pas du JSON (il commence par une déclaration JavaScript var datadep = {…) et il contient plusieurs erreurs de syntaxe (des apostrophes qui n'auraient pas dû être échappées).

Voyons maintenant un traitement avec le programme spécialisé dans JSON, jq. On va servir du service de tests TLS https://tls.imirhil.fr/, dont les résultats sont consultables avec un navigateur Web, mais également téléchargeables en JSON. Par exemple, https://tls.imirhil.fr/https/www.bortzmeyer.org.json donne accès aux résultats des tests pour la version HTTPS de ce blog :

% curl -s https://tls.imirhil.fr/https/www.bortzmeyer.org.json| jq '.date'    
"2017-07-23T14:10:25.760Z"
   
Notons qu'au moins une clé d'un objet JSON n'est pas nommée uniquement avec des lettres et chiffres, la clé $oid. jq n'aime pas cela :
     
% curl -s https://tls.imirhil.fr/https/www.bortzmeyer.org.json| jq '._id.$oid'
jq: error: syntax error, unexpected '$', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
._id.$oid     
jq: 1 compile error

   
Il faut mettre cette clé entre guillemets :
   
% curl -s https://tls.imirhil.fr/https/bortzmeyer.org.json| jq '."_id"."$oid"'                                                                               
"596cb76c2525939a3b34120f"

Toujours avec jq, les données de la Deutsche Bahn, en http://data.deutschebahn.com/dataset/data-streckennetz. C'est du GeoJSON (RFC 7946), un profil de JSON. Ici, on cherche la gare de Ratisbonne :

%  jq '.features | map(select(.properties.geographicalName == "Regensburg Hbf"))' railwayStationNodes.geojson
[
  {
    "type": "Feature",
    "geometry": {
      "type": "Point",
      "coordinates": [
        12.09966625451,
        49.011754555481
      ]
    },
    "properties": {
      "id": "SNode-1492185",
      "formOfNode": "railwayStop",
      "railwayStationCode": "NRH",
      "geographicalName": "Regensburg Hbf",
...
   

Toujours avec jq, on peut s'intéresser aux données officielles états-uniennes en https://catalog.data.gov/dataset?res_format=JSON. Prenons les données sur la délinquance à Los Angeles (j'ai bien dit délinquance et pas criminalité, celui qui traduit crime par crime ne connait pas l'anglais, ni le droit). https://data.lacity.org/api/views/y8tr-7khq/rows.json?accessType=DOWNLOAD est un très gros fichier (805 Mo) et jq n'y arrive pas :

% jq .data la-crime.json
error: cannot allocate memory
   

Beaucoup de programmes qui traitent le JSON ont ce problème (un script Python produit un MemoryError) : ils chargent tout en mémoire et ne peuvent donc pas traiter des données de grande taille. Il faut donc éviter de produire de trop gros fichiers JSON.

Si vous voulez voir un vrai exemple en Python, il y a mon article sur le traitement de la base des codes postaux. Cette base peut évidemment aussi être examinée avec jq. Et c'est l'occasion de voir du GeoJSON :

% jq '.features | map(select(.properties.nom_de_la_commune == "LE TRAIT"))' laposte_hexasmal.geojson 
[
  {
    "type": "Feature",
    "geometry": {
      "type": "Point",
      "coordinates": [
        0.820017087099,
        49.4836816397
      ]
    },
    "properties": {
      "nom_de_la_commune": "LE TRAIT",
      "libell_d_acheminement": "LE TRAIT",
      "code_postal": "76580",
      "coordonnees_gps": [
        49.4836816397,
        0.820017087099
      ],
      "code_commune_insee": "76709"
    }
  }
]

J'avais promis plus haut un exemple écrit en Go. On va utiliser la liste des positions géographiques des stations RATP, en https://data.ratp.fr/explore/dataset/positions-geographiques-des-stations-du-reseau-ratp/table/?disjunctive.stop_name&disjunctive.code_postal&disjunctive.departement. Le programme Go read-ratp.go va afficher le nombre de stations et la liste :

% ./read-ratp < positions-geographiques-des-stations-du-reseau-ratp.json
26560 stations
Achères-Ville
Alésia
Concorde
...
Comme déjà indiqué, c'est plus délicat en Go que dans un langage très dynamique comme Python. Il faut construire à l'avance des structures de données :
  
type StationFields struct {
	Fields Station
}

type Station struct {
	Stop_Id   int
	Stop_Name string
}
   
Et toute violation du « schéma » des données par le fichier JSON (quelque chose qui arrive souvent dans la nature) plantera le programme.

Si on veut beaucoup de fichiers JSON, le service de données ouvertes officielles data.gouv.fr permet de sélectionner des données par format. Ainsi, https://www.data.gouv.fr/fr/datasets/?format=JSON donnera tous les fichiers en JSON. Prenons au hasard les frayères du centre de la France, https://www.data.gouv.fr/fr/datasets/points-de-frayere-des-especes-de-linventaire-frayeres-des-regions-centre-et-poitou-charentes/. Il est encodé en ISO-8859-1, ce qui est explicitement interdit par le RFC. Bref, il faut encore rappeler qu'on trouve de tout dans le monde JSON et que l'analyse de fichiers réalisés par d'autres amène parfois des surprises.

On peut aussi traiter du JSON dans PostgreSQL. Bien sûr, il est toujours possible (et sans doute parfois plus avantageux) d'analyser le JSON avec une des bibliothèques présentées plus haut, et de mettre les données dans une base PostgreSQL. Mais on peut aussi mettre le JSON directement dans PostgreSQL et ce SGBD fournit un type de données JSON et quelques fonctions permettant de l'analyser. Pour les données, on va utiliser les centres de santé en Bolivie, en http://geo.gob.bo/geoserver/web/?wicket:bookmarkablePage=:org.geoserver.web.demo.MapPreviewPage. On crée la table :

CREATE TABLE centers (
 ID serial NOT NULL PRIMARY KEY,
 info json NOT NULL
);
    
Si on importe le fichier JSON bêtement dans PostgreSQL (psql -c "copy centers(info) from stdin" mydb < centro-salud.json), on récupère un seul enregistrement. Il faut donc éclater le fichier JSON en plusieurs lignes. On peut utiliser les extensions à SQL de PostgreSQL pour cela, mais j'ai préféré me servir de jq :
%  jq --compact-output '.features | .[]' centro-salud.json |  psql -c "copy centers(info) from stdin" mydb
COPY 50
    
On peut alors faire des requêtes dans le JSON, avec l'opérateur ->. Ici, le nom des centres (en jq, on aurait écrit .properties.nombre) :
mydb=> SELECT info->'properties'->'nombre' AS Nom FROM centers;
                   nom                    
------------------------------------------
 "P.S. ARABATE"
 "INSTITUTO PSICOPEDAGOGICO"
 "HOSPITAL GINECO OBSTETRICO"
 "HOSPITAL GASTROENTEROLOGICO"
 "C.S. VILLA ROSARIO EL TEJAR"
 "C.S. BARRIO JAPON"
 "C.S. SAN ANTONIO ALTO (CHQ)"
 "C.S. SAN JOSE (CHQ)"
 "C.S. SAN ROQUE"
...
    

Bon, sinon, JSON dispose d'une page Web officielle, où vous trouverez plein d'informations. Pour tester dynamiquement vos textes JSON, il y a ce service.

2017-12-12

RFC 7929: DNS-Based Authentication of Named Entities (DANE) Bindings for OpenPGP

Un problème classique du système de cryptographie OpenPGP, normalisé dans le RFC 4880 est de vérifier les clés publiques des correspondants. Les trouver, c'est relativement facile : le correspondant pense à vous les envoyer ou bien on se sert tout simplement d'un serveur de clés. Mais ceux-ci ne garantissent rien sur la clé. N'importe qui peut créer une clé marquée flotus@whitehouse.gov et la mettre sur les serveurs de clé, même si cette clé n'a rien à voir avec la Maison-Blanche. Avant la solution de ce nouveau RFC, il n'existait pas de mécanisme sécurisé pour récupérer une clé publique PGP. Que propose ce RFC ? De mettre les clés dans le DNS (nouveau type d'enregistrement OPENPGPKEY), dans le domaine de la partie droite de l'adresse de courrier, sécurisée par DNSSEC. En gros, il s'agit de faire pour le courrier et PGP ce que fait déjà DANE (RFC 6698) pour le Web/TLS.

Les serveurs de clés utilisent le protocole HKP (jamais décrit dans un RFC). Ils fournissent un service très utile en permettant de chercher une clé, par son identificateur, ou par l'adresse de courrier associé. Voici un exemple par identificateur :

    
% gpg --recv-key  0xF3396311465F8E5D
gpg: requesting key 465F8E5D from hkps server hkps.pool.sks-keyservers.net
gpg: key 465F8E5D: public key "Amaelle G <amaelle.guiton@techn0polis.net>" imported
...
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
      
    
et un par adresse (notez que les adresses sont probablement toutes fausses) :

% gpg --search-key elysee.fr      
gpg: searching for "elysee.fr" from hkps server hkps.pool.sks-keyservers.net
(1)	hollande (flamby) <hollande@elysee.fr>
	  2048 bit RSA key CF22758A, created: 2014-01-06
(2)	jacques chirac (ancienne adresse) <jacques-chirac@elysee.fr>
	  2048 bit RSA key 2A97F759, created: 2007-11-15, expires: 2007-11-16 (expired)
(3)	kaziwan <kaziwan@elysee.gouv.fr>
	  1024 bit DSA key AA7FD67C, created: 2005-11-28
(4)	Gerard Calestroupat <gerard.calestroupat@elysee.fr>
	  1024 bit DSA key 82F02C73, created: 2003-08-05, expires: 2003-08-08 (expired)
(5)	Toto Berlingo <T.Berlingo@Elysee.fr>
	  1024 bit DSA key E9E920B7, created: 1999-06-10
    
Ces serveurs n'offrent aucune garantie : n'importe qui peut y publier une clé, avec n'importe quelle adresse et certaines clés sont clairement mensongères. L'usage normal est de récupérer la clé et ses signatures, puis de vérifier les signatures. Si elles sont faites par des gens qu'on a validés (directement, ou bien transitivement, jusqu'à une certaine profondeur), on estime la clé correcte (c'est ce qu'on nomme le web of trust). Autrement, la clé ne vaut rien. En outre, le seul système de révocation est de signer une révocation avec sa clé privée : si on l'a perdue, on ne pourra jamais retirer la clé des serveurs de clé. Pour ces deux raisons (fausses clés, et clés devenues inutilisables), il est donc difficile d'utiliser automatiquement, depuis un MUA ou un MTA, ces serveurs.

La solution proposée dans ce RFC est, comme souvent aujourd'hui, d'utiliser le DNS, qui a montré sa fiabilité et son ubiquité. Tout le monde peut faire des requêtes DNS, même coincé derrière un pare-feu, et tout le monde peut les valider, grâce à DNSSEC (RFC 4035).

On va donc publier dans sa zone DNS des enregistrements de type OPENPGPKEY, indexés par la partie gauche de l'adresse de courrier (c'est un peu plus compliqué, car elle peut contenir des caractères qui sont spéciaux pour le DNS ; voir plus loin). Le correspondant qui veut envoyer du courrier à quelqu'un cherchera cet enregistrement dans le DNS, et, s'il en trouve un, le validera avec DNSSEC et récupérera ainsi une clé PGP relativement sûre. La révocation d'une clé se fait simplement en retirant l'enregistrement du DNS.

La solution de ce RFC rend envisageable de récupérer et de vérifier automatiquement une clé avant l'envoi d'un message. Mais le RFC note bien qu'elle ne remplace pas complètement le web of trust, qui reste nécessaire si on veut une vérification sérieuse.

Ce RFC a le statut « Expérimental ». Il s'agit de tester l'idée et de voir si elle marche bien, et n'a pas trop d'inconvénients (par exemple de taille des zones DNS pour les domaines gérant beaucoup de comptes de courrier, surtout vu la taille des enregistrements OPENPGPKEY). Si le nombre de messages chiffrés avec OpenPGP augmente significativement suite à ce RFC, ce sera bon signe.

Notez qu'une expérience ressemblant à celle-ci avait déjà été faite avec le type d'enregistrement DNS CERT du RFC 4398. Ce fut un échec (peu de déploiement, peut-être en raison de la complexité du type CERT).

La section 2 de notre RFC décrit le format du nouveau type d'enregistrement DNS. Chaque enregistrement contient une et une seule clé. Si un utilisateur a plusieurs clés, il doit créer plusieurs enregistrements. Le type est 61 (et enregistré à l'IANA depuis août 2014). La partie droite de l'enregistrement (les données) contient la clé et au moins un ID et une auto-signature. Les clés PGP complètes, avec des tas de signatures, peuvent être grosses, trop pour le DNS ; le RFC recommande de ne publier que des clés minimales (pas trop de signatures, par exemple, et évidemment pas les photos qu'on peut inclure dans un attribut de la clé, cf. RFC 4880, section 5.12.1). Avec GnuPG, regardez l'exportation de ma clé avec toutes ses méta-données, et en exportation minimale (l'annexe A du RFC décrit les commandes GnuPG à utiliser) :

%  gpg --export CCC66677 > key.pgp 
% ls -lh key.pgp 
-rw-r--r-- 1 bortzmeyer bortzmeyer 86K Aug 25 17:17 key.pgp

%  gpg --export --export-options export-minimal,no-export-attributes CCC66677 > key.pgp
% ls -lh key.pgp                                                                       
-rw-r--r-- 1 bortzmeyer bortzmeyer 5.8K Aug 25 17:18 key.pgp   
    

Le format utilisé est celui du RFC 4880, section 11.1. C'est donc du binaire qui circule sur le réseau (rappelez-vous bien que, dans le DNS, le format de présentation, celui des fichiers de zone, et de la sortie de dig, n'a rien à voir avec le format binaire utilisé sur le réseau.) Les formats « texte » d'OpenPGP (« ASCII armor ») ne sont pas utilisés sur le réseau. (Donc, avec GnuPG, pas d'option --armor.)

Le format de présentation (celui des fichiers de zone et de la sortie de dig) encode la clé en Base64.

Et la partie gauche de l'enregistrement DNS ? Quel est le nom de domaine utilisé ? La section 3 du RFC fixe les règles :

  • Le domaine de l'adresse de courrier (partie droite de l'adresse de courrier) est celui où on met les enregistrements DNS OPENPGPKEY. La clé pour l'adresse stephane+chose@trucmachin.example sera donc dans la zone trucmachin.example.
  • Le nom de domaine sera la concaténation d'un condensat de la partie gauche de l'adresse de courrier (stephane+chose, dans l'exemple ci-dessus), et du composant _openpgpkey, avec le domaine de l'adresse de courrier (trucmachin.example dans l'exemple ci-dessus). Le condensat est tronqué à 28 octets. (Le nom de domaine n'est pas utilisé dans le condensat, pour faciliter la vie des opérateurs qui proposent la même adresse dans différents domaines.)
  • En fait, la règle est plus compliquée en raison des équivalences entre certains caractères (voir les exemples plus loin). Une correspondance est donc faite pour certains caractères. (Ce fut l'un des points les plus discutés dans le groupe de travail à l'IETF.)
  • Par exemple, les guillemets (oui, "jipoune le meilleur"@example.com est une adresse de courrier légale) sont retirés.
  • La condensation de la partie gauche de l'adresse de courrier est faite en SHA-256 (RFC 5754). Cela permet une protection limitée (cf. section 7.4) de la vie privée : même si un méchant met la main sur tout le fichier de zone, il ne trouvera pas facilement toutes les adresses (qui sont des données personnelles). Mais le but principal de cette condensation est de résoudre le problème de certains caractères qui sont permis dans la partie locale d'une adresse de courrier, mais qui posent des problèmes dans le DNS.
Ainsi, si l'adresse de l'utilisateur est hugh@example.com, la requête OPENPGPKEY devra chercher c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6._openpgpkey.example.com. Voici comment calculer cela avec les outils du shell Unix (28 octets = 56 caractères dans la représentation en hexadécimal) :
    
% echo -n hugh | sha256sum | cut -c -56
c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6

Une des difficultés pour trouver le bon nom de domaine est que les applications doivent traiter la partie gauche des adresses de courrier comme opaque (pas le droit d'analyser sa structure) et qu'elles ne connaissent pas les règles de canonicalisation qu'appliquera le domaine de destination, comme d'ignorer la casse de la partie locale (ce qui est souvent fait, mais pas toujours). Par exemple, Gmail ignore les points dans les adresses (donc foobar@gmail.com et foo.bar@gmail.com arrivent dans la même boîte aux lettres). L'émetteur qui ne connait pas cette règle va chercher la clé dans un domaine qui ne sera pas le bon. Idem avec les sous-adresses utilisées par certains domaines (en général avec le séparateur plus, comme stephane+blog, stephane+ietf, etc). Le RFC rappelle que l'émetteur ne peut pas se permettre de deviner ces règles locales, et qu'elles peuvent changer à tout moment. C'est au destinataire de se débrouiller, en publiant la clé à plusieurs noms, et en faisant attention aux variantes qu'il publie.

L'internationalisation des adresses de courrier complique évidemment encore un peu les choses (voir par exemple la section 10.1 du RFC 6530).

La section 6 du RFC se penche sur un problème pratique qu'on rencontre parfois avec le DNS : la difficulté à recevoir des réponses au-delà d'une certaine taille (il y a trois limites fréquemment rencontrées, la très ancienne limite de 512 octets du DNS, largement dépassée de nos jours, la limite de la MTU à 1 500 octets, au-delà de laquelle peut commencer la fragmentation, et la limite par défaut de la plupart des clients DNS à 4 096 octets). Les clés PGP peuvent être grosses, et le RFC recommende donc si possible de les récupérer sur TCP, pas UDP.

La section 7 de notre RFC analyse les questions de sécurité liées à cette technique. Elle rappelle que DNSSEC doit être utilisé : les enregistrements OPENPGPKEY récupérés ne doivent être utilisés que s'ils sont signés, et que la signature est valide. (Autrement, il serait trop facile à un attaquant de répondre avec une fausse clé.) Mais si DNSSEC est nécessaire, il n'est pas suffisant et la validation habituelle des clés PGP reste nécessaire si on veut un haut niveau de confidentialité. Ceci dit, comme souvent en sécurité, le mieux est l'ennemi du bien, et il vaut mieux une clé pas très vérifiée plutôt que d'envoyer le message en clair, comme le fait presque tout le monde aujourd'hui.

Et, évidemment, la sécurité DNSSEC doit être équivalente à la sécurité PGP puisqu'un attaquant qui aurait cassé la clé DNSSEC pourrait remplacer toutes les clés PGP du domaine. Il faut donc une cohérence dans les politiques de sécurité entre PGP et DNSSEC (section 7.6).

Autre problème de sécurité, cette fois lié à la vie privée : les requêtes DNS révèlent avec qui on veut communiquer de manière sécurisée par courrier (RFC 7626). Le fait que le nom de domaine utilisé soit un condensat de la partie locale de l'adresse de courrier limite un peu les risques, mais pas suffisamment (si on soupçonne qu'Alice écrit à bob@example.com mais qu'on n'en est pas sûr, il suffit de construire le nom où se trouve l'enregistrement OPENPGPKEY et de vérifier que ce nom est demandé, cf. section 7.4). C'est d'autant plus grave que les clients DNS actuels envoient en général le nom de domaine complet à tous les serveurs, même ceux qui n'en ont pas besoin. La minimisation de la requête (RFC 7816) limite ce problème. Le chiffrement des requêtes DNS (RFC 7858) peut faire le reste. Le cache du DNS limite un peu les risques et il est donc essentiel de ne pas faire une requête DNS externe à chaque fois qu'on envoie un message PGP à quelqu'un, cela ferait fuiter bien trop d'informations (section 7.5).

Pour limiter les risques qu'un attaquant récolte toutes les adresses de courrier du domaine, le RFC recommande de signer la zone en utilisant NSEC3 (RFC 5155).

À l'inverse de ce souci de protection de la vie privée, si une organisation veut lire le courrier de ses employés, la solution est qu'elle publie une clé d'organisation dans le DNS, pour pouvoir déchiffrer les messages entrants.

Un autre problème de sécurité est le risque d'utilisation dans des attaques par amplification. La taille importante des enregistrements OPENPGPKEY (surtout avec les clés RSA) aggrave ce risque. Le RFC suggère de n'envoyer ces enregistrements via UDP que si l'adresse IP source de la requête a été vérifiée, par exemple avec les petits gâteaux du RFC 7873.

Où en sont les mises en œuvre de ce RFC ? GnuPG contient le code pour gérer ces clés dans le DNS depuis la version 2.1.9. Même chose pour openpgp-milter.

L'outil hash-slinger permet quant à lui de générer et de vérifier des enregistrements OPENPGPKEY :

% openpgpkey --fetch --uid paul@nohats.ca  paul@nohats.ca
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: paul@nohats.ca key obtained from DNS
Comment: key transfer was protected by DNSSEC
Version: GnuPG v1

mQENBFaJkKsBCADDSwQawRsKYqY/DuxWZjNNn39f14tDaswbpuF+PorNnt0MrepI
0yVY28NQ+5P09j75Os1jlqksK06aAVBtkJvr+T1ip85AxPUdTjD3U3zhM5/YATMi
...
On peut alors enregistrer la clé dans le trousseau PGP :

% openpgpkey --fetch --uid paul@nohats.ca  paul@nohats.ca | gpg --import
gpg: key BBAE5D31: public key "Paul Wouters (online key) <paul@nohats.ca>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

   

Voici un exemple de récupération de ma clé :


% openpgpkey  --fetch --uid 'stephane@bortzmeyer.org' stephane@bortzmeyer.org |gpg  

pub  4096R/CCC66677 2014-02-08 Stéphane Bortzmeyer (Main key) <stephane@bortzmeyer.org>
uid                            Stéphane Bortzmeyer <stephane@sources.org>
uid                            Stéphane Bortzmeyer (Work address) <bortzmeyer@nic.fr>
uid                            TextSecure fingerprint (05 d6 3b dc b7 e4 d7 69 2f f6 24 d5 51 31 88 2f a5 59 ae 96 e0 fb a5 75 ab e6 6c 64 ca e9 bb 6a 77) <BdY73Lfk12kv9iTVUTGIL6VZrpbg+6V1q+ZsZMrpu2p3@base64>
sub  4096R/96A4A254 2014-02-09 [expires: 2018-01-10]
sub  4096R/57F02AA1 2014-02-09 [expires: 2017-01-10]

Mais comment ai-je fait pour que ça marche ? hash-slinger permet de créer la clé directement au bon format :

% openpgpkey --create stephane@bortzmeyer.org                                 
; keyid: 555F5B15CCC66677                                   
28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. IN OPENPGPKEY mQINBFL2VNABE...
Il n'y a plus qu'à la mettre dans le fichier de zone, et à re-signer. Mais, car il y a un mais, cela ne marche que si on a des logiciels récents, qui connaissent le type 61 (OPENPGPKEY). Si ce n'est pas le cas, le signeur refusera de signer, ou le serveur de recharger la zone. C'était mon cas, en raison d'une trop vieille version d'OpenDNSSEC. Trois solutions, commençons par la plus simple, demander à hash-slinger de générer un enregistrement DNS à la syntaxe générique (« types inconnus », du RFC 3597) :
% openpgpkey --create stephane@bortzmeyer.org --output generic
; keyid: 555F5B15CCC66677
28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. IN TYPE61 \# 5874 99020d0452f654d001100096b30513d96c42e697fd06674b1...
Et c'est cet enregistrement à la syntaxe générique qu'on met dans le fichier de zone. Sinon, si on aime bien faire l'encodage soi-même, utilisons xxd :
% openpgpkey --create stephane@bortzmeyer.org > key.zone
[Edit to keep the zone data]

% base64 -d key.zone > key.bin
[wc -c key.bin to know what number to put in the zone file]

% xxd -p key.bin > key.hex
Et on met le contenu de key.hex dans le fichier de zone. Sinon, l'annexe A du RFC fournit une variante de cette solution, utilisant hexdump.

Voici la récupération de cette clé dans le DNS, avec un dig récent, qui connait ce type OPENPGPKEY et sait formater le résultat :

% dig OPENPGPKEY   28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org  
;; Truncated, retrying in TCP mode.
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36368
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 9, ADDITIONAL: 13
...
;; ANSWER SECTION:
28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. 85841 IN OPENPGPKEY ( mQINBFL2VNABEACWswUT2WxC5pf9BmdLHzPeXzHZfvik
				ExJHaQ7LHPRVjAQtBiBN0vI3Uh0VgFzjA+0H2sqTduJY
				tqd8mrTh9clDnCbrMU8svc7MeWxkW21ogjqBYL8puA3d
                                ...         
Notez le « Truncated, retrying in TCP mode ». L'enregistrement est trop gros pour les paquets UDP qu'accepte dig par défaut (il fait huit kilo-octets, dig accepte quatre par défaut). Notez aussi le bit AD (Authentic Data) dans la réponse : celle-ci a bien été validée par DNSSEC.

Avec un dig ancien, qui ne connait pas ce nouveau type (et, cette fois, on demande directement en TCP, comme le recommande le RFC) :

% dig +tcp -t TYPE61 28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19989
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 9, ADDITIONAL: 29
...
;; ANSWER SECTION:
28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. 86206 IN TYPE61 \# 5874 ( 99020D0452F654D001100096B30513D96C42E697FD06
				674B1F33DE5F31D97EF8A4131247690ECB1CF4558C04
				2D06204DD2F237521D15805CE303ED07DACA9376E258
				B6A77C9AB4E1F5C9439C26EB314F2CBDCECC796C645B
                                ...

Sur ce sujet, vous pouvez aussi lire l'article de Johannes Weber, qui détaille une utilisation de l'outil de Shumon Huque.

2017-12-10

Les dix millénaires oubliés qui ont fait l'histoire

Quand on parle de la préhistoire, tout le monde voit ce que c'est : des types vêtus de peaux de bêtes partant chercher du feu ou chassant le mammouth, ou encore inventant plein de choses. Idem pour l'histoire, on a plein de livres et de films sur tous les aspects de l'histoire, depuis qu'on a inventé l'écriture, jusqu'à Stéphane Bern et Franck Ferrand. Mais entre les deux ? Entre les deux, dit l'auteur, il y a « dix millénaires zappés ». La période qui va en gros de 13 000 à 3 000 AEC : qu'en savons-nous ?

Le livre fait le tour des innovations qui ont marqué cette période un peu oubliée : l'agriculture, bien sûr, les villages, les outils en métal, mais aussi la religion organisée. Il y avait bien sûr des croyances depuis longtemps mais, pendant ces dix millénaires, on commence à en voir des manifestations partout, y compris au prix d'efforts colossaux, inimaginables quand on était chasseur-cueilleur. Et cela ne s'arrête pas là. C'est aussi pendant cette période, dix mille ans avant Macron, qu'on invente les inégalités. Avant, il y avait sans doute des chefs. Mais l'examen des tombes ne permettait pas de voir des vraies inégalités. Pendant les dix millénaires, on voit au contraire apparaitre la distinction entre ceux qu'on enterre simplement, et ceux dont le tombeau recèle des richesses qui feront la joie des archéologues. L'auteur examine comment des gens qui vivaient à peu près libres ont pu accepter cet asservissement, et note que cela n'a pas été un processus linéaire, mais qu'il y a eu de nombreux retours à des enterrements égalitaires (suite à des révoltes contre les chefs ?)

Mais la civilisation ne s'est pas arrêtée à la religion et aux chefs. On a aussi inventé la guerre. Oui, bien sûr, il y avait de la violence avant. Mais des armées entières s'affrontant, alors que la plupart des soldats n'avaient aucune raison personnelle de se battre, ça date aussi de cette époque. (L'Europe en dehors de la Grèce était en retard sur la voie de la civilisation, et n'a donc connu sa première grande bataille que vers 1 200 AEC.) Effet amusant de la guerre, c'est aussi pendant cette période que le cannibalisme est devenu tabou…

Et la domination masculine ? A-t-elle toujours existé ? Et, si non, a-t-elle été inventée pendant cette période ? Contrairement aux batailles, cela ne laisse pas forcément beaucoup de traces analysables. Là, on est forcément davantage dans la spéculation, comme les théories de Bachofen, qui cherchait à tout prix à prouver que la domination masculine n'est pas universelle (alors qu'apparemment, elle l'est).

Et je vous laisse découvrir dans ce livre les autres étonnantes innovations de l'époque.

2017-12-09

A small DNS trick to see Sci-Hub despite censorship attempts

The service Sci-Hub is a great help for the scientists, allowing them to access to a lot of scientific papers that were before locked behind paywalls. The publishing companies keep trying to censor Sci-Hub and block access to this service, for instance by taking down domain names like it happened a few days ago with sci-hub.io. If you control your DNS resolver, you can easily restore access.

Sci-Hub's domain sci-hub.io was recently taken down. There are several ways to still use Sci-Hub, such as "domain hopping" (using another TLD such as sci-hub.bz) or using Tor (the address is scihub22266oqcxt.onion). But there is one which does not seem to have been publically documented yet.

For the rest of the article, we will rely on a local DNS resolver. ("local" does not imply it is on your own machine: it may be on the local network. The important point is that you can change its configuration.) A local resolver is a great tool against DNS censorship. By default, it does not see Sci-Hub domains (NXDOMAIN means "No Such Domain"). Let's test with dig:


% dig A sci-hub.io

; <<>> DiG 9.10.4 <<>> A sci-hub.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 45356
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1
...
;; QUESTION SECTION:
;sci-hub.io.		IN A
...
;; Query time: 1408 msec
;; SERVER: ::1#53(::1)
...

    

OK, it failed, the domain being taken down. Let's configure our local resolver to work around the problem. Sci-Hub has a public name server that answers to the Sci-Hub domains. First, we'll be using the excellent program Unbound. We just add in unbound.conf:

server:
     domain-insecure: "sci-hub.io"
  
forward-zone:
     name:   "sci-hub.io"
     forward-addr: 80.82.77.83
     forward-addr: 80.82.77.84
and we restart Unbound and it works:

%  dig A sci-hub.io

; <<>> DiG 9.10.3-P4-Debian <<>> A sci-hub.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22120
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;sci-hub.io.		IN A

;; ANSWER SECTION:
sci-hub.io.		3483 IN	A 80.82.77.83

;; AUTHORITY SECTION:
sci-hub.io.		3483 IN	NS ns1.sci-hub.cc.
sci-hub.io.		3483 IN	NS ns2.sci-hub.cc.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 03 17:51:49 CET 2017
;; MSG SIZE  rcvd: 101
  
We can now use all the interesting features of Sci-Hub. My favorite: just add sci-hub.io at the end of the URL of a scientific article you want and you get it. Imagine you're a medical researcher and you work on venous thrombosis. You want to read "Prevalence and Prevention of Deep Venous Thrombosis of the Lower Extremities in High-Risk Pulmonary Patients" but it is behind a paywall. You just add Sci-Hub domain at the end, go to http://ang.sagepub.com.sci-hub.bz/content/39/6/505.short.sci-hub.io and it works! (By the way, this is one of the main reasons of the well-deserved success of Sci-Hub: it is very convenient. It is not just a matter of money if people use Sci-Hub.)

(DNS experts may discuss the use of forward-zone instead of stub-zone. The Sci-Hub servers accept recursive requests so both work. In my opinion, forward may be a bit more future-proof if the authoritative name server changes its IP address but a recursor stays in place at the old address.)

With Knot resolver, you just add a rule:

-- Sci-Hub
policy.add(policy.suffix(policy.STUB({'80.82.77.83', '80.82.77.84'}), policy.todnames({'sci-hub.io.'})))
    
to the configuration.

Doing the same with BIND is possible. Just put in its configuration file (somewhere/named.conf):

   zone "sci-hub.io" {
                 type forward;
                 forwarders {80.82.77.83; 80.82.77.84;};
   };
    
But there is a big "but": if you validate the DNS answers with DNSSEC (an excellent idea), this will be rejected since .io is signed and can prove that sci-hub.io does not exist. You'll get in your logs error messages such as "error (insecurity proof failed) resolving 'sci-hub.io/A/IN'".

The trick is to use the fact that 80.82.77.83 also allows DNS zone transfers. You can therefore configure your BIND as a slave for sci-hub.io. Once BIND is authoritative for this domain, it won't check with DNSSEC:

    zone "sci-hub.io" {
	         type slave;
                 masters {80.82.77.83; 80.82.77.84;};
};
Note: the option dnssec-must-be-secure addresses a different issue and is not useful here.

I do not use dnsmasq but Canari Bleu does and says you have to add server=/sci-hub.io/80.82.77.83 in dnsmasq.conf.

Of course, this hack is far from perfect. It doesn't scale (imagine if there were dozens of censored domains to make accessible this way). It's brittle (the IP addresses can change without warning). But this sort of imperfect workarounds will become more and more common with the increase of politically or business-motivated censorship.

2017-12-06

RFC 8270: Increase the Secure Shell Minimum Recommended Diffie-Hellman Modulus Size to 2048 Bits

Un RFC de moins de quatre pages, boilerplate administratif inclus, pour passer la taille minimum des modules des groupes Diffie-Hellman utilisés par SSH, de 1 024 bits à 2 048.

L'échange Diffie-Hellman dans SSH est décrit dans le RFC 4419, que notre nouveau RFC met à jour. C'est dans le RFC 4419 (sa section 3) que se trouvait la recommandation d'accepter au moins 1 024 bits pour le module du groupe. Or, cette taille est bien faible face aux attaques modernes comme Logjam.

Voilà, c'est tout, on remplace « minimum 1 024 bits » par « minimum 2 048 » et on peut continuer à utiliser SSH. Si vous êtes utilisateur d'OpenSSH, la commande de génération de clés, ssh-keygen, peut également générer ces modules (cf. la section Moduli generation dans le manuel.) Les versions un peu anciennes ne vous empêchent pas de faire des modules bien trop petits. Ainsi, sur une version 7.2 :

% ssh-keygen -G moduli-512.candidates -b 512
Fri Oct 20 20:13:49 2017 Sieve next 4177920 plus 511-bit
Fri Oct 20 20:14:51 2017 Sieved with 203277289 small primes in 62 seconds
Fri Oct 20 20:14:51 2017 Found 3472 candidates

% ssh-keygen -G moduli-256.candidates -b 256
Too few bits: 256 < 512
modulus candidate generation failed
    

Le RGS recommande quant à lui 3 072 bits minimum (la règle exacte est « RègleLogp-1. La taille minimale de modules premiers est de 2048 bits pour une utilisation ne devant pas dépasser l’année 2030. RègleLogp-2. Pour une utilisation au delà de 2030, la taille minimale de modules premiers est de 3072 bits. »)

Enfin, la modification d'OpenSSH pour se conformer à ce RFC est juste un changement de la définition de DH_GRP_MIN.

2017-12-05

RFC 8273: Unique IPv6 Prefix Per Host

Ce court RFC explique comment (et pourquoi) attribuer un préfixe IPv6 unique à chaque machine, même quand le média réseau où elle est connectée est partagé avec d'autres machines.

Ce RFC s'adresse aux gens qui gèrent un grand réseau de couche 2, partagé par de nombreux abonnés. Un exemple est celui d'un serveur dédié connecté à un Ethernet partagé avec les serveurs d'autres clients. Un autre exemple est celui d'une connexion WiFi dans un congrès ou un café. Dans les deux cas, la pratique sans doute la plus courante aujourd'hui est de donner une seule adresse IPv6 à la machine (ou, ce qui revient au même, un préfixe de 128 bits). C'est cette pratique que veut changer ce RFC. Le but est de mieux isoler les clients les uns des autres, et de bien pouvoir gérer les abonnements et leur utilisation. (Justement le problème de Comcast, dont un des auteurs du RFC est un employé, cf. section 1.) Les clients ne se connaissent en effet pas les autres et il est important que les actions d'un client ne puissent pas trop affecter les autres (et qu'on puisse attribuer les actions à un client précis, pour le cas où ces actions soient illégales). En outre, certaines options d'abonnement sont « par client » (section 3, qui cite par exemple le contrôle parental, ou la qualité de service, qui peut être plus faible pour ceux qui ne paient pas le tarif « gold ».)

Si chaque client a un préfixe IPv6 à lui (au lieu d'une seule adresse IP), toute communication entre clients passera forcément par le routeur géré par l'opérateur, qui pourra ainsi mieux savoir ce qui se passe, et le contrôler. (Les lecteurs férus de routage ont noté que le client, s'il est administrateur de sa machine, peut toujours changer les tables de routage, mais cela n'affectera que le trafic aller, le retour passera toujours par le routeur. De toute façon, je soupçonne que la technique décrite dans ce RFC ne marche que si le réseau donne un coup de main, pour isoler les participants.)

Le RFC affirme que cela protègera contre des attaques comme l'épuisement de cache Neighbor Discovery, les redirections malveillantes faites avec ICMP ou les RAcailles (RFC 6104). Cela éviterait de devoir déployer des contre-mesures comme le RA Guard (RFC 6105). Là aussi, il me semble personnellement que ça n'est complètement vrai que si l'attaquant n'est pas administrateur sur sa machine. Ou alors, il faut que le réseau ne soit pas complètement partagé, qu'il y ait un mécanisme de compartimentage.

Les mécanismes décrits ici supposent que la machine du client utilise SLAAC (RFC 4862) pour obtenir une adresse IP. Cette obtention peut aussi passer par DHCP (RFC 3315) mais c'est plus rare, peu de clients étant capable de demander une adresse en DHCP (RFC 7934).

La section 4 du RFC décrit comment le client obtient ce préfixe. Il va envoyer un message RS (Router Solicitation, voir le RFC 4861, section 3) et écouter les réponses, qui lui diront son adresse IP mais aussi d'autres informations comme les résolveurs DNS à utiliser (voir RFC 8106). Pas de changement côté client, donc (ce qui aurait rendu ce mécanisme difficile à déployer). Par contre, côté « serveur », il y a de légers changements. Le routeur qui reçoit les RS et génère des RA (Router Advertisement), qu'ils aient été sollicités ou pas, va devoir les envoyer uniquement à une machine (puisque chaque client a un préfixe différent : il ne faut donc pas diffuser bêtement). Comme le RFC 4861 (sections 6.2.4 et 6.2.6) impose que l'adresse IP de destination soit ff02::1 (« tous les nœuds IPv6 »), l'astuce est d'utiliser comme adresse MAC, non pas l'adresse multicast habituelle, mais une adresse unicast (RFC 6085). Ainsi, chaque client ne recevra que son préfixe.

Ce RA contient le préfixe que l'opérateur alloue à ce client particulier. Les options du RA (RFC 4861, section 4.2) sont :

  • Bit M à zéro (ce qui veut dire « pas d'adresse via DHCP »),
  • Bit O à un (ce qui veut dire « d'autres informations sont disponibles par DHCP, par exemple le serveur NTP à utiliser »),
  • Bit A du préfixe (RFC 4861, section 4.6.2) mis à un (ce qui veut dire « tu es autorisé à te configurer une adresse dans ce préfixe »),
  • Bit L du préfixe (RFC 4861, section 4.6.2) mis à zéro (ce qui veut dire « ce préfixe n'est pas forcément sur le lien où tu te trouves, ne suppose rien, sois gentil, passe par le routeur »).

Le bit A étant mis à un, la machine qui a obtenu le préfixe peut s'attribuer une adresse IP à l'intérieur de ce préfixe, , avec SLAAC, comme indiqué dans le RFC 4862. Elle doit suivre la procédure DAD (Duplicate Address Detection, RFC 4862, section 5.4) pour vérifier que l'adresse IP en question n'est pas déjà utilisée.

Voilà, l'essentiel de ce RFC était là. La section 5 concerne quelques détails pratiques, par exemple ce que peut faire la machine client si elle héberge plusieurs machines virtuelles ou containers (en gros, elle alloue leurs adresses en utilisant le préfixe reçu).

Ce mécanisme de préfixe IP spécifique à chaque client de l'opérateur n'est pas sans poser des questions liées à la vie privée, comme l'explique la section 7 du RFC. (Rappelez-vous la section 1, qui disait qu'un des buts de cette technique était de satisfaire aux « obligations légales », autrement dit de pouvoir suivre à la trace ses utilisateurs.) Bien sûr, la machine cliente peut utiliser le système du RFC 4941, mais, ici, il aurait peu d'impact. Même avec un identificateur d'interface temporaire et imprévisible, le préfixe resterait, et identifierait parfaitement le client. Le RFC mentionne (mais sans l'exiger) qu'on peut limiter les dégâts en changeant le préfixe de temps en temps.

2017-12-02

✍ Lettre à Yohan

Yohan,

C’est un plaisir de travailler avec toi depuis tant d’années, d’abord sur Libé, puis chez Mozilla et actuellement avec Etalab. J’ai l’impression de sortir grandi de nos interactions et tu as indirectement contribué à mes réflexions sur la simplicité dans le développement et au statut de dévelopeur expérimenté.

J’admire ton intégrité lorsqu’il est question d’outils avilissants (coucou Slack). J’apprécie ton humilité et ta soif de toujours explorer plus loin les possibilités que nous offre notre domaine. Il est tellement facile de se considérer comme étant brilliant (cache) dans cette profession qu’une approche impliquant peu d’égo (cache) est exceptionnellement rare. Il y a un enjeu politique dans la ré-acquisition de ses outils mais aussi social dans la (re)prise de contrôle que cela procure. On ne se fatigue plus à courir après les dernières nouveautés lorsqu’on est en train de les réinventer en se les réappropriant.

Je me demande de plus en plus si proposer les services d’une équipe (cache) qui a l’habitude de travailler ensemble ne serait pas plus pertinent qu’une somme d’égos afin de faire émerger un produit.

Nous avons encore de belles années devant nous :-).

David

Conserver sa clé avec Let's Encrypt, certbot et dehydrated

Beaucoup de gens utilisent désormais l'AC Let's Encrypt. Ce n'est pas la première autorité de certification qui permet d'avoir un certificat en faisant tout en ligne, ni la première gratuite, mais elle est néanmoins très utilisée (au point de devenir un nouveau SPOF de l'Internet). Par défaut, les outils Let's Encrypt comme certbot créent une nouvelle clé quand le certificat est renouvelé. Dans quels cas est-ce gênant et comment éviter cela ?

Un petit rappel sur les certificats : un certificat, c'est tout bêtement une clé publique, avec quelques métadonnées dont les plus importantes sont la signature de l'AC et la date d'expiration (qui, avec Let's Encrypt, est très rapprochée). Renouveler un certificat, c'est demander une nouvelle signature à l'AC. Si la clé n'est pas trop ancienne, ou n'a apparemment pas été compromise, il n'est pas nécessaire de la changer.

Mais les outils existants le font quand même systématiquement (c'est un choix des outils, comme certbot ou dehydrated, ce n'est pas une obligation du protocole ACME, ni de l'AC Let's Encrypt). Cette décision a probablement été prise pour garantir que la clé soit renouvelée de temps en temps (après tout, il est raisonnable de supposer que, tôt ou tard, elle sera compromise, et ce ne sera pas forcément détecté par le propriétaire).

Et pourquoi est-ce gênant de changer de clé à chaque renouvellement (donc tous les trois mois avec Let's Encrypt) ? Cela ne pose pas de problème pour l'utilisation habituelle d'un serveur HTTPS. Mais c'est ennuyeux si on utilise des techniques de sécurité fondées sur un épinglage de la clé, c'est-à-dire une authentification de la clé publique utilisée. Ces techniques permettent de résoudre une grosse faille de X.509, le fait que n'importe quelle AC, même si vous n'en êtes pas client, puisse émettre un certificat pour n'importe quel domaine. Parmi ces techniques de sécurité :

  • DANE, normalisé dans le RFC 6698. Si on met les utilisations 1 (« PKIX-EE ») ou 3 (« DANE-EE »), DANE déclare la clé, un changement de celle-ci invalide donc l'enregistrement DANE.
  • HPKP (RFC 7649).
  • Et les autres solutions d'épinglage comme celle spécifiée dans la section 4.2 du RFC 7858 pour les serveurs DNS-sur-TLS. La supervision des serveurs publics utilisant ce protocole les authentifie ainsi (« Strict mode - SPKI only »).

Si on utilise l'outil certbot, qui est celui officiellement recommandé par Let's Encrypt, la méthode normale d'utilisation est, la première fois :

  
% sudo certbot certonly --webroot --webroot-path /var/lib/letsencrypt -d www.example.com 
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.example.com
Using the webroot path /var/lib/letsencrypt for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0000_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem
...
Let's Encrypt a testé la présence du défi sur le serveur, on le voit dans le journal du serveur HTTP :
2600:3000:2710:200::1d - - [13/Sep/2017:16:08:46 +0000] "GET /.well-known/acme-challenge/2IlM1PbP9QZlAA22xvE4Bz5ivJi5nsB5MHz52uY8xT8 HTTP/1.1" 200 532 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
On va alors créer l'enregistrement TLSA (DANE) :
% tlsa --create --selector 1  www.example.com
Got a certificate with Subject: /CN=www.example.com
_443._tcp.www.example.com. IN TLSA 3 1 1 f582936844ec355cfdfe8d9d1a42e9565940602c71c7abd2c36c732daa64b9db
Got a certificate with Subject: /CN=www.example.com
_443._tcp.www.example.com. IN TLSA 3 1 1 f582936844ec355cfdfe8d9d1a42e9565940602c71c7abd2c36c732daa64b9db
(L'option --selector 1 est pour faire apparaitre dans l'enregistrement TLSA la clé publique seulement et non pas tout le certificat, ce que ferait le sélecteur par défaut, 0. C'est expliqué plus en détail plus loin.) À ce stade, on a un certificat Let's Encrypt, un enregistrement DANE qui correspond et tout le monde est heureux :
% tlsa --verify --resolvconf="" www.example.com 
SUCCESS (Usage 3 [DANE-EE]): Certificate offered by the server matches the TLSA record (x.y.z.t)
   

Maintenant, si on renouvelle le certificat quelques mois plus tard :

    
% certbot --quiet  --webroot --webroot-path /usr/share/nginx/local-html renew
Cela change la clé. Regardez avec OpenSSL :
# Avant  
 % openssl x509 -pubkey -in /etc/letsencrypt/live/www.example.com/fullchain.pem 
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsUd3mG5QK6EdTtYh0oLJ
nkIovYkWXV8QLQMvAthzURbyeIlQ8CXeTNCT6odh/VVyMn49IwkRJl6B7YNhYiRz
pbmIxxzceAhKNAg6TF/QylHa1HWvHPniZF02NJAXCxMO5Y8EZ7n0s0cGz4XD5PGA
XctV6ovA3fR8b2bk9t5N+UHklWvIOT7x0nVXWmWmrXzG0LX/P4+utZJjRR6Kf5/H
9GDXprklFCbdCTBkhyPBgdiJDnqzdb6hB1aBEsAMd/Cplj9+JKtu2/8Pq6MOtQeu
364N+RKcNt4seEr6uMOlRXzWAfOHI51XktJT64in1OHyoeRMV9dOWOLWIC2KAlI2
jwIDAQAB
-----END PUBLIC KEY-----

# Après
% openssl x509 -pubkey -in /etc/letsencrypt/live/www.example.com/fullchain.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MF8Dw3JQ58n8B/GvWYI
Vd+CG7PNFA+Ke7B+f9WkzEIUPzAHq7qk1v7dOitD3WsRKndJDPxZAq7JrgOiF/0y
4726HhYR1bXOTziAbk0HzR+HwECo1vz26fqPnNpZ3M46PQFQU9uq2pgHtBwCVMQ+
Hi1pYKnB2+ITl11DBLacSHP7WZZGHXbEqW5Cc710m6aTt18L+OgqxuQSgV+khh+W
qWqd2bLq32actLEVmfR4uWX7fh/g6I7/p3ohY7Ax4WC30RfWZk3vLyNc/8R0/67c
bVIYWmkDhgXy6UlrV2ZgIO2K8oKiJBMHjnaueHIfu1ktubqM1/u1yLKwXW16UAxm
5QIDAQAB
-----END PUBLIC KEY-----
À partir de là, l'enregistrement DANE ne correspond plus, la clé copiée à l'extérieur n'est plus la clé utilisée.

Avec certbot, la solution est de ne pas laisser le client ACME choisir le certificat, mais de fabriquer un CSR et de lui indiquer de l'utiliser systématiquement (cf. la documentation officielle) :

% certbot certonly --webroot -w /usr/share/nginx/local-html -d dns-resolver.yeti.eu.org --csr /etc/letsencrypt-local/yeti-resolver.csr --cert-path /etc/letsencrypt-local/tmp.pem 
No handlers could be found for logger "certbot.crypto_util"
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Performing the following challenges:
http-01 challenge for dns-resolver.yeti.eu.org
Using the webroot path /var/lib/letsencrypt for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Server issued certificate; certificate written to /etc/letsencrypt-local/dns-resolver.yeti.eu.org.pem
Comment on avait fabriqué un CSR ? OpenSSL le permet. Faisons-en un joli, utilisant la cryptographie à courbes elliptiques :
%  openssl ecparam -out yeti-resolver.pem -name prime256v1 -genkey

%  openssl req -new -key yeti-resolver.pem  -nodes -days 1000 -out yeti-resolver.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
...
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Dahu
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:dns-resolver.yeti.eu.org
Email Address []:yeti@eu.org
Avec ce CSR, et en appelant certbot depuis cron avec les options indiquées plus haut, indiquant le même CSR (certbot certonly --webroot -w /usr/share/nginx/local-html -d dns-resolver.yeti.eu.org --csr /etc/letsencrypt-local/yeti-resolver.csr --cert-path /etc/letsencrypt-local/tmp.pem), la clé reste constante, et DANE et HPKP fonctionnent. Petit inconvénient : avec ces options, certbot renouvelle le certificat à chaque fois, même quand ça n'est pas nécessaire.

Et si on utilise dehydrated au lieu de certbot, comme client ACME ? Là, c'est plus simple, on met dans le fichier de configuration /etc/dehydrated/config l'option :

PRIVATE_KEY_RENEW="no"
Et cela suffit. Ceci dit, dehydrated a un gros inconvénient, il est bavard. Quand on le lance depuis cron, il affiche systématiquement plusieurs lignes, même s'il n'a rien à dire.

Pour revenir à la question du choix du sélecteur DANE (RFC 6698 et RFC 7218), il faut noter que tout renouvellement change le certificat (puisqu'il modifie au moins la date d'expiration). Il ne faut donc pas utiliser le sélecteur 0 « Cert » (qui publie le condensat du certificat entier dans l'enregistrement TLSA) mais le sélecteur 1 « SPKI » (qui ne met que le condensat de la clé). Le problème existe avec toutes les AC mais est plus aigu pour Let's Encrypt où on renouvelle souvent. L'annexe A.1.2 du RFC 6698 l'explique bien.

Enfin, un avertissement de sécurité : avec les méthodes indiquées ici, le client ACME ne change plus de clé du tout. C'est donc désormais à vous de penser à créer une nouvelle clé de temps en temps, pour suivre les progrès de la cryptanalyse.

Si vous voulez des exemples concrets, dns-resolver.yeti.eu.org (uniquement en IPv6) utilise certbot, alors que dns.bortzmeyer.org et mercredifiction.bortzmeyer.org utilisent dehydrated. Prenons dns.bortzmeyer.org. Son enregistrement TLSA :

% dig TLSA _443._tcp.dns.bortzmeyer.org
...
;; ANSWER SECTION:
_443._tcp.dns.bortzmeyer.org. 80968 IN TLSA 1 1 1 (
				C05BF52EFAB00EF36AC6C8E1F96A25CC2A79CC714F77
				055DC3E8755208AAD0E4 )
				...
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Dec 02 17:03:18 CET 2017
;; MSG SIZE  rcvd: 2311
   
Il déclare une contrainte sur le certificat du serveur (champ Certificate usage à 1, PKIX-EE), ne testant que la clé (champ Selector à 1), l'enregistrement est un condensat SHA-256 (champ Matching type à 1). On peut vérifier que l'enregistrement DANE est correct avec hash-slinger :
% tlsa --verify --resolvconf="" dns.bortzmeyer.org
SUCCESS (Usage 1 [PKIX-EE]): Certificate offered by the server matches the one mentioned in the TLSA record and chains to a valid CA certificate (204.62.14.153)
SUCCESS (Usage 1 [PKIX-EE]): Certificate offered by the server matches the one mentioned in the TLSA record and chains to a valid CA certificate (2605:4500:2:245b::42)
   
ou bien avec https://check.sidnlabs.nl/dane/.

2017-12-01

✍ Lettre à Simone

Simone,

Ou Peggy, je ne sais plus. Merci pour ces voyages philosophiques et notamment ces thérapies. C’est un angle auquel je suis sensible pour avoir l’impression d’évoluer à mon échelle. Prendre soin en ayant davantage conscience de ce qui blesse au quotidien.

Ce qu’il me manque en tant qu’expatrié c’est de pouvoir participer aux après-midi et échanger avec d’autres sur ces thématiques. En espérant que cela t’encourage à continuer, et pourquoi pas… à essaimer.

David

2017-11-28

Choisir son résolveur DNS, pas si facile

Le 26 novembre 2017, à la Cité des Sciences à Paris, j'ai fait un exposé lors de l'Ubuntu Party sur la question des critères de choix d'un bon résolveur DNS. Les supports de cet exposé sont ici.

Les Ubuntu Party sont organisées par les bénévoles utilisateurs d'Ubuntu et comprennent une install party (des dizaines de personnes sont passées) et des exposés plus traditionnels. J'ai beaucoup aimé les deux exposés d'Elzen, le premier sur la piraterie et le piratage, et le second une « conférence dont vous êtes le héros », ainsi que l'exposé de Pamputt sur le remarquable Wiktionnaire, projet moins connu que Wikipédia mais tout aussi intéressant !

La question du choix d'un résolveur DNS fait toujours couler beaucoup d'encre sur les réseaux sociaux et a déjà fait l'objet de plusieurs articles sur ce blog, au sujet de Quad9, au sujet de Google Public DNS, à propos des résolveurs publics en général, de l'intérêt d'avoir son propre résolveur, de la protection de la vie privée (RFC 7626), de la censure, etc. Voici les transparents de l'exposé à l'Ubuntu Party :

L'exposé a été filmé mais je ne sais pas quand la vidéo sera en ligne.

2017-11-27

★ Bugs et complexité

« Lorsque nous utilisions des systèmes électromécaniques, nous pouvions les tester de manière exhaustive », regrette Nancy Leveson, spécialiste d’astronautique, d’aéronautique et de sécurité logicielle au MIT. Les systèmes logiciels sont différents parce qu’ils peuvent être changés à moindre coût, qu’ils sont sans cesse mis à jour et bien plus complexes. Pour Leveson, « le problème est que nous essayons de construire des systèmes qui dépassent notre capacité à les gérer intellectuellement ».

Réinventer la programmation ? (cache)

La recherche d’exhaustivité dans un système complexe est une bataille perdue d’avance contre des moulins à vent. Ce qu’il faut tenter d’améliorer ce n’est pas la réduction du nombre de bugs en amont mais la réactivité pour corriger ceux détectés lorsque le système est en place. Un logiciel (non-critique !) devrait être fait pour répondre à 80% des problématiques rencontrées. Si nous sommes si loin du compte aujourd’hui — en tout cas dans le Web (cache) — cela est dû au manque d’empathie des développeurs vis-à-vis de bénéficiaires qui ne peuvent exprimer leurs voix de façon pertinente à la fois par manque de compétences et de moyens de communication. Il est quasi-impossible de savoir quel est le ressenti d’une personne utilisant un outil informatique au sens large. Autant les frustrations que les joies seraient pourtant requises pour améliorer le système, mais comment réussir à faire une synthèse de ces ressentis ?

Ma solution actuelle est de tenter de réduire les boucles de rétro-actions permettant d’améliorer le système de manière progressive et éclairée ; une fois que la problématique a été elle-même simplifiée afin d’en réduire le périmètre. La complexité qui ne peut-être débuguée est un péché d’orgueil, pas forcément celui du développeur. Je ne pense pas qu’il faille réinventer la programmation en elle-même mais plutôt les conditions de son application et surtout de son évolution. Interviewer des utilisateurs en amont d’une conception ET une fois le système mis en production est malheureusement loin d’être une pratique courante.

Les languages et les modélisations afférentes ne sont que des grammaires sans vies, l’équipe et sa connaissance d’une problématique donnée sont les composantes qu’il faut soigner. En laissant le temps à la confiance de s’installer, condition indispensable à l’ouverture qu’est cet autre : l’utilisateur. Ce partenaire d’une symbiose dont on essaye de créer l’outil sans en mesurer les appétences ni les conséquences (cache).

Aujourd’hui encore, trop de développeurs regardent sur Stack Overflow, l’une des grandes plateformes de partage pour développeurs, les méthodes des autres, copient des bouts de code et de fonctions, les collent ensembles et les ajustent par itération. Ça fonctionne jusqu’à ce qu’on tombe sur un vrai problème !, souligne Newcombe.

Ibid.

Stack Overflow est l’équivalent de l’encyclopédie Wikipedia dont les entrées se font en langage naturel (par des questions) et il ne s’agit pas de copier bêtement des résultats mais d’analyser les différentes réponses pour se faire son propre avis sur une question complexe. Il ne s’agit pas uniquement d’assembler du code d’autrui mais de liens vers des documentations officielles mal indexées ou des parties de RFC (Request For Comment) pertinentes pour une problématique donnée. Je ne connais pas d’équivalent dans d’autres profession, aussi je conçois que cela soit difficile à appréhender. Le seul malheur de la plateforme est d’être détenue par des intérêts privés ce qui met notamment en question la pérennité d’un tel service. Je suis un développeur moyen qui utilise cet outil de manière quotidienne et je n’en éprouve aucune honte. Un grand merci à mes pairs qui viennent alimenter cette base de discussion continuellement mise à jour.

???

2017-11-21

Artemis

Le nouveau roman de l'auteur du Martien (oui, c'est nul de présenter un auteur par son bouquin précédent qui a eu du succès mais je n'avais pas d'autre idée). Il garde le côté « hard-tech », mais tend cette fois vers le polar.

Dans « Le Martien », le héros devait se débrouiller tout seul sur la planète Mars et l'un des principaux intérêts du roman était la description détaillée et correcte scientifiquement des différents problèmes qu'il affrontait, et de comment il les résolvait. Cette fois, ça se passe sur la Lune, et il s'agit de problèmes plus policiers, avec des méchants (très méchants), des complots et des sabotages (qui ont tout de suite un caractère plus dramatique quand il n'y a pas d'atmosphère dehors et qu'on ne peut donc pas sortir pour échapper au danger).

Comme le précédent, ce roman plaira aux geeks scientifiques. Ils y trouveront de la physique et de la chimie en quantité. Si vous le lisez en anglais, pensez à réviser la terminologie, notamment du monde de la soudure, qui joue un rôle essentiel dans le livre. « I wasn't sure what grade of steel [they] were made of, but most grades melt at or below 1450° C. So, just to be safe, my plate and stock rods were Grade 416 with a melting point of 1530° C. »

Mais les autres seront également ravis des personnages (surprenants), de la morale (curieuse), de l'intrigue (à rebondissements) et de l'(abondante) action. Mon fils, regardant par-dessus mon épaule, m'avait dit « c'est encore un livre où le héros affronte des épreuves, les surmonte puis pécho la jolie fille à la fin ? » Eh bien, non, ce n'est pas ça du tout, vous verrez en lisant.

SÉLECTION

Cette planète rassemble les principaux carnets web d'auteurs francophones traitant de XML. Ces blogs sont souvent bilingues français/anglais et éclectiques. Cette page rassemble l'ensemble de leurs billets et vous permet de sélectionner ceux que vous voulez voir.


Lien permanent pour cette sélection :
feed /actualites/planete/xmlfr/fr/
Les documents publiés sur ce site le sont sous licence " Open Content".

Valid XHTML 1.0 Transitional

logo DYOMEDEA
Conception, réalisation et hébergement

Questions ou commentaires
redacteurs@xmlfr.org