Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

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


RFC 4253: The Secure Shell (SSH) Transport Layer Protocol

Date de publication du RFC : Janvier 2006
Auteur(s) du RFC : T. Ylonen (SSH Communications Security Corp, C. Lonvick (Cisco Systems)
Chemin des normes
Première rédaction de cet article le 2 août 2020


Le protocole SSH de sécurité est composé de plusieurs parties, spécifiées dans des RFC différents. Ici, il s'agit de la couche basse de SSH, située juste au-dessus de TCP, et en dessous de protocoles qui permettent, par exemple, la connexion à distance. Cette couche basse fournit l'authentification (de la machine, pas de l'utilisateur) et la confidentialité, via de la cryptographie.

Le principe général de cette partie de SSH est classique, et proche de celui d'autres protocoles de cryptographie comme TLS (RFC 4251 pour une vue générale de l'architecture de SSH). Le client établit une connexion TCP avec le serveur puis chaque partie envoie une liste des algorithmes utilisés pour l'authentification, l'échange de clés et le chiffrement ultérieur. Une fois un accord trouvé, le serveur est authentifié, typiquement par de la cryptographie asymétrique, comme ECDSA. Un mécanisme d'échange de clés comme Diffie-Hellman permet de choisir des clés partagées qui serviront pour les opérations de chiffrement symétrique (par exemple avec AES) qui chiffreront tout le reste de la communication. Ce processus de négociation fournit l'agilité cryptographique (RFC 7696). Du fait de cette agilité, la liste des algorithmes utilisables n'est pas figée dans les RFC. Démarrée par le RFC 4250, sa version à jour et faisant autorité est à l'IANA.

Notez que j'ai simplifié le mécanisme de négociation : il y a d'autres choix à faire dans la négociation, comme celui de l'algorithme de MAC. Les autres fonctions de SSH, comme l'authentification du client, prennent place ensuite, une fois la session de transport établie selon les procédures définies dans notre RFC 4253.

L'établissement de connexion est normalisé dans la section 4 du RFC. SSH suppose qu'il dispose d'un transport propre, acheminant des octets sans les modifier et sans les interpréter. (TCP répond à cette exigence, qui est très banale). Le port par défaut est 22 (et il est enregistré à l'IANA, lisez donc le récit de cet enregistrement). En pratique, il est fréquent que SSH utilise d'autres ports, par exemple pour ralentir certaines attaques par force brute (OpenSSH rend cela très simple, en indiquant dans son ~/.ssh/config le port du serveur où on se connecte). Une fois la connexion TCP établie, chaque machine envoie une bannière qui indique sa version de SSH, ici la version 2 du protocole (la seule survivante aujourd'hui) et la version 7.6 de sa mise en œuvre OpenSSH :

% telnet localhost 22
...
SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3
  

Un établissement de session complet comprend :

  • Connexion TCP,
  • envoi des bannières (qui peut être fait simultanément par le serveur et le client, pas besoin d'attendre l'autre),
  • début de la procédure d'échange de clés (KEX, pour Key EXchange) avec les messages SSH_MSG_KEXINIT (qui peuvent aussi être envoyés simultanément),
  • échange de clés proprement dit, par exemple avec des messages Diffie-Hellman.

Comme certains messages peuvent être envoyés en parallèle (sans attendre l'autre partie), il est difficile de compter combien d'aller-retours cela fait. (Optimiste, le RFC dit que deux aller-retours suffisent dans la plupart des cas.)

Le protocole décrit dans ce RFC peut être utilisé pour divers services (cf. RFC 4252 et RFC 4254). Une des utilisations les plus fréquentes est celle de sessions interactives à distance, où SSH avait rapidement remplacé telnet. À l'époque, certaines personnes s'étaient inquiétées de l'augmentation de taille des paquets due à la cryptographie (nouveaux en-têtes, et MAC). Le débat est bien dépassé aujourd'hui mais une section 5.3 du RFC discute toujours la question. SSH ajoute au moins 28 octets à chaque paquet. Pour un transfert de fichiers, où les paquets ont la taille de la MTU, cette augmentation n'est pas importante. Pour les sessions interactives, où il n'y a souvent qu'un seul octet de données dans un paquet, c'est plus significatif, mais il faut aussi prendre en compte le reste des en-têtes. Ainsi, IP et TCP ajoutent déjà 32 octets au minimum (en IPv4). Donc l'augmentation due à SSH n'est pas de 2800 % mais de seulement 55 %. Et c'est sans même prendre en compte les en-têtes Ethernet. En parlant d'Ethernet, il faut aussi noter que la taille minimale d'une trame Ethernet est de 46 octets (cf. RFC 894), de toute façon et que donc, sans SSH, il faudrait de toute façon remplir la trame… Bref, le problème n'est guère important. (Le RFC donne un autre exemple, avec des modems lents, qui n'est probablement plus d'actualité aujourd'hui.)

La section 6 du RFC décrit ensuite le format des en-têtes SSH, un format binaire, comme le DNS ou BGP, mais pas comme SMTP ou HTTP version 1. Le tout est évidemment chiffré (même la longueur du paquet, qu'on ne peut donc pas connaitre avant de déchiffrer). Le chiffrement se fait avec l'algorithme sélectionné dans la phase de négociation. Si vous utilisez OpenSSH, l'option -v affichera l'algorithme, ici ChaCha20 :


% ssh -v $ADDRESS
...
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none

  

ChaCha20 n'existait pas à l'époque du RFC 4253. Il n'est toujours pas enregistré à l'IANA. C'est ce qui explique que le nom d'algorithme inclus un arobase suivi d'un nom de domaine, c'est la marque des algorithmes locaux (ici, local à OpenSSH), non enregistrés officiellement. Un article du programmeur décrit l'intégration de ChaCha20 dans OpenSSH. Il y avait eu une tentative de normalisation (dans l'Internet-Draft draft-josefsson-ssh-chacha20-poly1305-openssh) mais elle a été abandonnée. C'était peut-être simplement par manque de temps et d'intérêt, car ChaCha20 est utilisé dans d'autres protocoles cryptographiques de l'IETF comme TLS (cf. RFC 7905 et, pour une vision plus générale, RFC 8439). OpenSSH permet d'afficher la liste des algorithmes de chiffrement symétriques qu'il connait avec l'option -Q cipher :

% ssh -Q cipher
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
rijndael-cbc@lysator.liu.se
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
  

À l'inverse, le RFC 4253 listait des algorithmes qui ont été abandonnés depuis comme RC4 (nommé arcfour dans le RFC pour des raisons juridiques), retiré par le RFC 8758. La liste comprend également l'algorithme none (pas de chiffrement) qui avait été inclus pour des raisons douteuses de performance et dont l'usage est évidemment déconseillé (section 6.3 de notre RFC).

Le paquet inclut également un MAC pour assurer son intégrité. Il est calculé avant le chiffrement. Pour le MAC aussi, la liste des algorithmes a changé depuis la parution du RFC 4253. On peut afficher ceux qu'OpenSSH connait (les officiels sont dans un registre IANA) :

% ssh -Q mac        
hmac-sha1
hmac-sha1-96
hmac-sha2-256
hmac-sha2-512
hmac-md5
hmac-md5-96
umac-64@openssh.com
umac-128@openssh.com
hmac-sha1-etm@openssh.com
hmac-sha1-96-etm@openssh.com
hmac-sha2-256-etm@openssh.com
hmac-sha2-512-etm@openssh.com
hmac-md5-etm@openssh.com
hmac-md5-96-etm@openssh.com
umac-64-etm@openssh.com
umac-128-etm@openssh.com
  

Bon, mais les algorithmes de chiffrement symétrique comme ChaCha20 nécessitent une clé secrète et partagée entre les deux parties. Comment est-elle négociée ? Un algorithme comme par exemple Diffie-Hellman sert à choisir un secret, d'où sera dérivée la clé.

Le format binaire des messages est décrit en section 6 en utilisant des types définis dans le RFC 4251, section 5, comme byte[n] pour une suite d'octets ou uint32 pour un entier non signé sur 32 bits. Ainsi, un certificat ou une clé publique sera :

string    certificate or public key format identifier
byte[n]   key/certificate data
    

Un paquet SSH a la structure (après le point-virgule, un commentaire) :

uint32    packet_length
byte      padding_length
byte[n1]  payload; n1 = packet_length - padding_length - 1
byte[n2]  random padding; n2 = padding_length
byte[m]   mac (Message Authentication Code - MAC); m = mac_length    
  

La charge utile (payload) a un format qui dépend du type de messages. Par exemple, le message d'échange de clés initial, où chacun indique les algorithmes qu'il connait :

byte         SSH_MSG_KEXINIT
byte[16]     cookie (random bytes)
name-list    kex_algorithms
name-list    server_host_key_algorithms
name-list    encryption_algorithms_client_to_server
name-list    encryption_algorithms_server_to_client
name-list    mac_algorithms_client_to_server
name-list    mac_algorithms_server_to_client
name-list    compression_algorithms_client_to_server
name-list    compression_algorithms_server_to_client
name-list    languages_client_to_server
name-list    languages_server_to_client
boolean      first_kex_packet_follows
uint32       0 (reserved for future extension)
    

Les types de message (message ID ou message numbers) possibles sont listés dans un registre IANA. Par exemple l'exemple ci-dessus est un message de type SSH_MSG_KEXINIT, type qui est défini en section 12 et dans le RFC 4250, section 4.1.2. Il a la valeur 20.

Affiché par Wireshark, voici quelques messages que SSH transmet en clair, avant le début du chiffrement. Après l'échange des bannières, il y aura le KEXINIT en clair, Wireshark suit les termes du RFC donc vous pouvez facilement comparer ce message réel à la description abstraite du RFC, ci-dessus :

    
SSH Protocol
    SSH Version 2 (encryption:chacha20-poly1305@openssh.com mac:<implicit> compression:none)
        Packet Length: 1388
        Padding Length: 4
        Key Exchange
            Message Code: Key Exchange Init (20)
            Algorithms
                kex_algorithms length: 269
                kex_algorithms string [truncated]: curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,di
                server_host_key_algorithms length: 358
                server_host_key_algorithms string [truncated]: ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25
                encryption_algorithms_client_to_server length: 108
                encryption_algorithms_client_to_server string: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
                encryption_algorithms_server_to_client length: 108
                encryption_algorithms_server_to_client string: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
                mac_algorithms_client_to_server length: 213
                mac_algorithms_client_to_server string [truncated]: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-
                mac_algorithms_server_to_client length: 213
                mac_algorithms_server_to_client string [truncated]: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-
                compression_algorithms_client_to_server length: 26
                compression_algorithms_client_to_server string: none,zlib@openssh.com,zlib
                compression_algorithms_server_to_client length: 26
                compression_algorithms_server_to_client string: none,zlib@openssh.com,zlib

  

Notez qu'un seul message SSH contient tous les algorithmes, aussi bien ceux servant à l'authentification qu'à l'échange de clés, ou qu'au chiffrement symétrique. Le premier algorithme listé est le préféré. Si les deux parties ont le même algorithme préféré, il est choisi. Autrement, on boucle sur les algorithmes listés par le client, dans l'ordre, en sélectionnant le premier qui est accepté par le serveur. Voici maintenant le lancement de l'échange de clés :


SSH Protocol
    SSH Version 2 (encryption:chacha20-poly1305@openssh.com mac:<implicit> compression:none)
        Packet Length: 44
        Padding Length: 6
        Key Exchange
            Message Code: Diffie-Hellman Key Exchange Init (30)
            Multi Precision Integer Length: 32
            DH client e: c834ef50c9ce27fa5ab43886aec2161a3692dd5e3267b567...
            Padding String: 000000000000

  

Et la réponse en face :

    
SSH Protocol
    SSH Version 2 (encryption:chacha20-poly1305@openssh.com mac:<implicit> compression:none)
        Packet Length: 260
        Padding Length: 9
        Key Exchange
            Message Code: Diffie-Hellman Key Exchange Reply (31)
            KEX host key (type: ecdsa-sha2-nistp256)
            Multi Precision Integer Length: 32
            DH server f: 2e34deb08146063fdba1d8800cf853a3a6830a3b8549ee5b...
            KEX H signature length: 101
            KEX H signature: 0000001365636473612d736861322d6e6973747032353600...
            Padding String: 000000000000000000
    SSH Version 2 (encryption:chacha20-poly1305@openssh.com mac:<implicit> compression:none)
        Packet Length: 12
        Padding Length: 10
        Key Exchange
            Message Code: New Keys (21)
            Padding String: 00000000000000000000

  

À partir de là, tout est chiffré et Wireshark ne peut plus afficher que du binaire sans le comprendre :

    
SSH Protocol
    SSH Version 2 (encryption:chacha20-poly1305@openssh.com mac:<implicit> compression:none)
        Packet Length (encrypted): 44cdc717
        Encrypted Packet: ea98dbf6cc50af65ba4186bdb5bf02aa9e8366aaa4c1153f
        MAC: e7a6a5a222fcdba71e834f3bb76c2282

  

OpenSSH avec son option -v permet d'afficher cette négociation :

    
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none

  

Et les algorithmes acceptés pour l'échange de clés :

% ssh -Q kex
diffie-hellman-group1-sha1
diffie-hellman-group14-sha1
diffie-hellman-group14-sha256
diffie-hellman-group16-sha512
diffie-hellman-group18-sha512
diffie-hellman-group-exchange-sha1
diffie-hellman-group-exchange-sha256
ecdh-sha2-nistp256
ecdh-sha2-nistp384
ecdh-sha2-nistp521
curve25519-sha256
curve25519-sha256@libssh.org
  

(Ceux à courbes elliptiques comme curve25519-sha256 n'existaient pas à l'époque. curve25519-sha256 a été ajouté dans le RFC 8731.) On trouve aussi les algorithmes acceptés pour l'authentification du serveur via sa clé publique :

% ssh -Q key    
ssh-ed25519
ssh-ed25519-cert-v01@openssh.com
ssh-rsa
ssh-dss
ecdsa-sha2-nistp256
ecdsa-sha2-nistp384
ecdsa-sha2-nistp521
ssh-rsa-cert-v01@openssh.com
ssh-dss-cert-v01@openssh.com
ecdsa-sha2-nistp256-cert-v01@openssh.com
ecdsa-sha2-nistp384-cert-v01@openssh.com
ecdsa-sha2-nistp521-cert-v01@openssh.com
  

Ce RFC 4253 ne décrit que la couche basse de SSH. Au-dessus se trouvent plusieurs services qui tirent profit de la sécurité fournie par cette couche basse. Une fois la session chiffrée établie, le protocole SSH permet de lancer d'autres services. Ils ne sont que deux depuis le début, mais d'autres pourront se rajouter dans le registre IANA. Actuellement, il y a ssh-userauth (authentifier l'utilisateur, par mot de passe ou par clé publique, RFC 4252) et ssh-connection (connexion à distance, et services qui en dépendent, cf. RFC 4254).

Nous avons vu plus haut le type de messages SSH_MSG_KEXINIT (code numérique 20). Il y a de nombreux autres types, présentés dans la section 11 du RFC. Par exemple SSH_MSG_DISCONNECT (type 1 dans le registre IANA) est défini ainsi :

byte      SSH_MSG_DISCONNECT
uint32    reason code
string    description in ISO-10646 UTF-8 encoding [RFC3629]
string    language tag [RFC3066]
  

Il indique la fin de la session SSH (l'étiquette de langue pour indiquer la raison est désormais normalisée dans le RFC 5646, et plus le RFC 3066). Autre exemple, SSH_MSG_IGNORE (code 2) pour faire du remplissage afin de diminuer les risques d'analyse du trafic. Pour une vision complète des risques de sécurité de SSH, (re)lisez la très détaillée section 9 du RFC 4251.

Notez qu'il avait existé une version 1 du protocole SSH, qui n'a pas fait l'objet d'une normalisation formelle. La section 5 de notre RFC traite de la compatibilité entre la version actuelle, la 2, et cette vieille version 1, aujourd'hui complètement abandonnée. Ça, c'est le passé. Et le futur ? Le cœur de SSH n'a pas bougé depuis les RFC de la série du RFC 4250 au RFC 4254. Mais il existe un projet (pour l'instant individuel, non accepté par l'IETF de remplacer ce RFC 4253 par QUIC, en faisant tourner le reste de SSH sur QUIC (lisez draft-bider-ssh-quic).


Téléchargez le RFC 4253


L'article seul

RFC 8801: Discovering Provisioning Domain Names and Data

Date de publication du RFC : Juillet 2020
Auteur(s) du RFC : P. Pfister, E. Vyncke (Cisco), T. Pauly (Apple), D. Schinazi (Google), W. Shao (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF intarea
Première rédaction de cet article le 29 juillet 2020


Vous vous demandez certainement, chère lectrice et cher lecteur, ce qu'est un PvD (ProVisioning Domain). Cette notion n'est pas nouvelle, mais elle n'avait été formalisée rigoureusement qu'avec le RFC 7556. Un PvD est un domaine de l'Internet où des règles cohérentes de configuration du réseau s'appliquent. Au sein, d'un PvD, il y a un résolveur DNS à utiliser, des adresses IP spécifiques, des règles de routage et de sécurité que n'ont pas forcément les autres PvD. Ce nouveau RFC décrit une option IPv6 qui permet au PvD de signaler explicitement son existence, via un RA (Router Advertisement.)

La notion de PvD (ProVisioning Domain) est utile pour les machines qui ont plusieurs connexions, à des réseaux (et donc peut-être des PvD) différents, par exemple un ordinateur connecté à la fois à un FAI grand public et au VPN de l'entreprise. Il y a des PvD implicites : une machine qui connait le concept de PvD affecte un PvD implicite à chaque réseau et, par défaut, ne considère pas que le résolveur DNS de l'un convient pour les autres. Et il y a des PvD explicites, et c'est à eux qu'est consacré ce RFC. Un PvD explicite a un identificateur, qui a la syntaxe d'un FQDN. Attention, même si l'identificateur est un nom de domaine, le terme de « domaine » (le D de PvD) ne doit pas être confondu avec le sens qu'il a dans le DNS. L'intérêt d'un PvD explicite est qu'il permet d'avoir plusieurs domaines distincts sur la même interface réseau, et qu'on peut y associer des informations supplémentaires, récupérées sur le réseau ou bien préconfigurées.

On l'a vu, le concept de PvD avait été décrit dans le RFC 7556. Ce que notre nouveau RFC 8801 rajoute, c'est :

  • Une option aux RA (Router Advertisement, RFC 4861) pour indiquer aux machines IPv6 du réseau le PvD explicite,
  • Un mécanisme pour récupérer, en HTTPS, de l'information de configuration du réseau, pour les cas où cette information ne tiendrait pas dans le message RA. Elle est évidemment codée en JSON.

Le RA va donc indiquer le ou les identificateurs du ou des PvD du réseau. Notez qu'on peut avoir aussi le même PvD sur plusieurs réseaux, par exemple le Wi-Fi et le filaire chez moi font partie du même PvD et ont les mêmes règles et la même configuration.

Dans un monde idéal, l'utilisatrice dont l'ordiphone a à la fois une connexion 4G, une connexion Wi-Fi et un VPN par dessus, aurait un PvD pour chacun de ces trois réseaux différentes, et pourrait donc décider intelligemment quelle interface utiliser pour quel type de trafic. Par exemple, une requête DNS pour wiki.private.example.com (le wiki interne de l'entreprise) sera envoyée uniquement via le VPN, puisque les résolveurs des réseaux publics ne connaissent pas ce domaine. Autre exemple, l'information envoyée pour chaque PvD pourrait permettre aux applications de faire passer le trafic important (la vidéo en haute définition, par exemple), uniquement sur le réseau à tarification forfaitaire.

Bon, assez de considérations sur les PvD, passons aux nouvelles normes décrites dans ce RFC. D'abord, l'option RA. Elle est décrite dans la section 3. C'est très simple : une nouvelle option RA est créée, la 21, « PvD ID Router Advertisement Option », suivant le format classique des options RA, TLV (Type-Longueur-Valeur). Elle contient, entre autres :

  • Un bit nommé H qui indique que le client peut récupérer des informations supplémentaires en HTTP (c'est détaillé en section 4 du RFC),
  • Un bit nommé L qui indique que ce PvD est également valable pour IPv4,
  • Un bit nommé R qui indique que le RA contient un autre RA (détails en section 5),
  • Et bien sûr l'identificateur (PvD ID) lui-même, sous la forme d'un FQDN.

Si jamais il y a plusieurs PvD sur le réseau, le routeur doit envoyer des RA différents, il n'est pas autorisé à mettre plusieurs options PvD dans un même RA.

Que va faire la machine qui reçoit une telle option dans un RA ? Elle doit marquer toutes les informations de configuration qui étaient dans le RA comme étant spécifiques à ce PvD. Par exemple, si la machine a deux interfaces, et reçoit un RA sur chacune, ayant des PvD différents, et donnant chacun l'adresses d'un résolveur DNS (RFC 8106), alors ce résolveur ne doit être utilisé que pour le réseau où il a été annoncé (et avec une adresse IP source de ce réseau). Rappelez-vous que différents résolveurs DNS peuvent donner des résultats différents, par exemple un des réseaux peut avoir un Pi-hole qui donne des réponses mensongères, afin de bloquer la publicité. (En parlant du DNS, des détails sur cette question complexe figurent dans la section 5.2.1 du RFC 7556.) Autre exemple, si on utilise un VPN vers son employeur, les requêtes DNS pour les ressources internes (congés.rh.example.com…) doivent être envoyées au résolveur de l'employeur, un résolveur extérieur peut ne pas être capable de les résoudre. En fait, tous les cas où la réponse DNS n'est pas valable publiquement nécessitent d'utiliser le bon résolveur DNS. C'est aussi ce qui se passe avec NAT64 (RFC 6147).

Idem pour d'autres informations de configuration comme le routeur par défaut : elles doivent être associées au PvD. Une machine qui connait les PvD ne peut donc pas se contenter d'une table simple listant le résolveur DNS, le routeur par défaut, etc. Elle doit avoir une table par PvD.

Si la machine récupère par ailleurs des informations de configuration avec DHCP, elle doit également les associer à un PvD, par exemple en utilisant comme PvD implicite celui de l'interface réseau utilisée.

Et pour IPv4, si le bit L est à un ? Dans ce cas, l'information IPv4 reçue sur la même interface doit être associée à ce PvD. (Notez que si plusieurs PvD sur la même interface ont le bit L, on ne peut rien décider, à part que quelqu'un s'est trompé.)

Les machines qui partagent leur connexion (tethering), ce qui est fréquent pour les connexions mobiles comme la 4G (RFC 7278), doivent relayer le RA contenant l'option PvD vers le réseau avec qui elles partagent (comme elles relaient d'autres messages similaires, cf. RFC 4389). Cela permettra à des techniques qui facilitent le partage, comme la délégation de préfixe du RFC 8415, de bien fonctionner. Même si la machine partageuse ne reçoit pas d'option PvD, il est recommandé qu'elle en ajoute une pour le bénéfice des engins avec qui elle partage sa connectivité.

Tout cela, c'était pour une machine PvD-aware, une machine qui sait ce qu'est un PvD et qui sait le gérer. Mais avec du vieux logiciel, écrit avant le concept de PvD, que se passe-t-il ? Une machine munie de ce logiciel va évidemment ignorer l'option PvD du RA et donc utiliser un seul résolveur DNS, un seul routeur par défaut pour tous les cas. Elle aura sans doute beaucoup de problèmes si plusieurs interfaces réseau sont actives et, en pratique, il vaudra mieux n'avoir qu'une seule interface à un moment donné.

Nous avons vu plus haut que, si le bit H dans l'option PvD est à 1, la machine peut obtenir davantage d'informations (PvD Additional Information) en HTTP. Cette information sera encodée en I-JSON (RFC 7493.) Pourquoi ne pas avoir mis ces informations dans le RA ? Parce qu'elles sont trop grosses ou, tout simplement, pas critiques, et pouvant être ignorées. Et on les récupère où, ces informations ? Si le PvD est radio.example.com, l'URL à utiliser est https://radio.example.com/.well-known/pvd (préfixe .well-known désormais enregistré.) Attention, on ne doit tenter d'accéder à cet URL que si le bit H était à 1. C'est du HTTPS (RFC 2818) et il faut donc vérifier le certificat (cf. RFC 6125.) Vous voyez qu'on ne peut pas choisir un PvD au hasard : il faut qu'il soit un nom de domaine qu'on contrôle, et pour lequel on peut obtenir un certificat. Si on configure un des ces affreux portails captifs, il faut s'assurer que les clients auront le droit de se connecter au serveur HTTP indiqué.

Les données auront le type application/pvd+json. Elles contiennent obligatoirement :

  • Le PvD,
  • une date d'expiration, au format RFC 3339,
  • les préfixes IP du PvD.

Ainsi que, si on veut :

  • les domaines où chercher les noms qui ne sont pas des FQDN,
  • une indication que ce PvD n'a pas de connexion à l'Internet.

D'autres membres peuvent être présents, un registre IANA existe et, pour y ajouter des termes, c'est la procédure « Examen par un expert » du RFC 8126.

Voici un exemple, avec le PvD smart.mpvd.io (qui a servi à un hackathon IETF) :

% curl  https://smart.mpvd.io/.well-known/pvd 
{
	"name": "PvD for smart people",
	"prefixes": ["2001:67c:1230:101::/64", "2001:67c:1230:111::/64"],
	"noInternet": false,
	"metered": false,
	"captivePortalURL" : "https://smart.mpvd.io/captive.php"
}
  

On notera que le membre expires manque, ce qui n'est pas bien, et que le membre identifier, qui devrait indiquer le PvD, est également absent, ce qui est encore plus mal. On voit qu'il s'agissait d'une expérimentation. Voici ce qu'aurait dû être l'objet JSON :

{
        "identifier": "smart.mpvd.io",
        "expires": "2020-04-08T15:30:00Z",
	"prefixes": ["2001:67c:1230:101::/64", "2001:67c:1230:111::/64"],
	"noInternet": false,
	"name": "PvD for smart people",
	"metered": false,
	"captivePortalURL" : "https://smart.mpvd.io/captive.php"
}
  

Si vous connaissez d'autres serveurs d'information PvD, indiquez-les moi. Mais il est probable que la plupart ne seront accessibles que depuis un réseau interne.

Voilà, vous savez l'essentiel désormais. La section 5 du RFC ajoute quelques considérations pratiques. D'abord, le bit R qui permettait à une option PvD d'inclure un RA. À quoi ça sert ? L'idée est que, pendant longtemps, la plupart des réseaux accueilleront un mélange de machines qui connaissent les PvD, et de machines qui ne sont pas conscientes de ce concept. Le bit R sert à envoyer des informations qui ne seront comprises que des premières. Par exemple, on met un préfixe dans le RA et, dans l'option PvD, un autre RA qui contient un autre préfixe. Les machines qui connaissent les PvD verront et utiliseront les deux préfixes, celles qui ne connaissent pas les PvD ignoreront l'option et n'auront que le premier préfixe. On peut également envoyer deux RA, un ne contenant pas d'option PvD, et un en contenant une (plus le « vrai » RA).

Un peu de sécurité, pour finir (section 6). D'abord, il faut bien se rappeler que les RA, envoyés en clair et non authentifiés, n'offrent aucune sécurité. Il est trivial, pour un méchant connecté au réseau, d'envoyer de faux RA et donc de fausses options PvD. En théorie, des protocoles comme IPsec ou SEND (RFC 3971) peuvent sécuriser les RA mais, en pratique, on ne peut guère compter dessus. Les seules solutions de sécurisation effectivement déployées sont au niveau 2, par exemple 802.1X combiné avec le RFC 6105. Ce n'est pas un problème spécifique à l'option PvD, c'est la sécurité (ou plutôt l'insécurité) des RA.

Ah, et un petit mot sur la vie privée (section 7 du RFC). La connexion au serveur HTTP va évidemment laisser des traces, et il est donc recommandé de la faire depuis une adresse source temporaire (RFC 4941), et sans envoyer User-Agent: ou cookies.

Question mise en œuvre, il y a eu du code libre pour des tests (incluant une modification du noyau Linux, et un dissecteur pour Wireshark) mais je ne sais pas ce que c'est devenu et où en sont les systèmes d'exploitation actuels.


Téléchargez le RFC 8801


L'article seul

RFC 8744: Issues and Requirements for Server Name Identification (SNI) Encryption in TLS

Date de publication du RFC : Juillet 2020
Auteur(s) du RFC : C. Huitema (Private Octopus)
Pour information
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 29 juillet 2020


Le but du protocole de cryptographie TLS est de protéger une session contre l'écoute par un indiscret, et contre une modification par un tiers non autorisé. Pour cela, TLS chiffre toute la session. Toute la session ? Non, certaines informations circulent en clair, car elles sont nécessaires pour la négociation des paramètres de chiffrement. Par exemple, le SNI (Server Name Indication) donne le nom du serveur qu'on veut contacter. Il est nécessaire de le donner en clair car la façon dont vont se faire le chiffrement et l'authentification dépendent de ce nom. Mais cela ouvre des possibilités aux surveillants (savoir quel serveur on contacte, parmi tous ceux qui écoutent sur la même adresse IP) et aux censeurs (couper sélectivement les connexions vers certains serveurs). Il est donc nécessaire de protéger ce SNI, ce qui n'est pas facile. Ce nouveau RFC décrit les objectifs, mais pas encore la solution. Celle-ci reposera sans doute sur la séparation entre un frontal général qui acceptera les connexions TLS, et le « vrai » service caché derrière.

C'est que le problème est difficile puisqu'on est face à un dilemme de l'œuf et de la poule. On a besoin du SNI pour chiffrer alors qu'on voudrait chiffrer le SNI. Le RFC note qu'il n'y aura sans doute pas de solution parfaite.

Cela fait longtemps que le SNI (normalisé il y a longtemps, dans le RFC 3546, et aujourd'hui dans le RFC 6066) est connu pour les risques qu'il pose pour la vie privée. Les autres canaux de fuite d'information sont fermés petit à petit (par exemple le DNS, avec les RFC 7816, RFC 7858 et RFC 8484), souvent en utilisant TLS (RFC 8446). Même l'adresse IP de destination, qu'on ne peut pas cacher, perd de sa signification lorsque de nombreux services sont hébergés derrière la même adresse IP (c'est particulièrement vrai pour les gros CDN). Mais ces services comptent sur le SNI (Server Name Indication), transporté en clair dans le message TLS ClientHello, pour le démultiplexage des requêtes entrantes, et ce SNI tend donc à devenir le maillon faible de la vie privée, l'information la plus significative qui reste en clair. Voici, vu par tshark, un exemple de ClientHello, avec un SNI (server_name, affiche tshark) :

...
Secure Sockets Layer
TLSv1 Record Layer: Handshake Protocol: Client Hello
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 233
    Handshake Protocol: Client Hello
        Handshake Type: Client Hello (1)
            Length: 229
            Version: TLS 1.2 (0x0303)
...
            Extension: server_name (len=22)
                Type: server_name (0)
                Length: 22
                Server Name Indication extension
                    Server Name list length: 20
                    Server Name Type: host_name (0)
                    Server Name length: 17
                    Server Name: doh.bortzmeyer.fr
  

Résultat, le SNI est souvent utilisé de manière intrusive, le RFC 8404 donnant de nombreux exemples. Par exemple, il permet de censurer finement (si le SNI indique site-interdit.example, on jette les paquets, s'il indique site-commercial.example, on laisse passer). Il permet de shaper le trafic vers certains sites, en violation de la neutralité du réseau. Il permet aussi de laisser passer certains sites, lorsqu'on fait une attaque de l'homme du milieu, par exemple une entreprise qui fait de l'inspection HTTPS systématique peut utiliser le SNI pour en exempter certaines sites sensibles, comme ceux des banques ou des plate-formes médicales. Et, bien sûr, le SNI peut être passivement observé à des fins de surveillance (RFC 7258).

On peut s'amuser à noter que ces risques pour la vie privée n'avaient pas été notés dans la section « Sécurité » des RFC de normalisation de SNI, comme le RFC 6066. C'est peut-être parce qu'à l'époque, les éventuels attaquants avaient des moyens plus simples à leur disposition. (Je me souviens de discussions à l'IETF « à quoi bon masquer le SNI puisque le DNS révèle tout ? » ; c'était avant le RFC 7626.) Il restait un endroit où le nom du service était en clair, c'était le certificat renvoyé par le serveur TLS (subjectAltName) mais, depuis TLS 1.3 (RFC 8446), lui aussi est chiffré. Aujourd'hui, les progrès de la sécurité font que le moyen le plus simple de savoir à quel service un internaute se connecte devient souvent le SNI.

Notez toutefois que tout le monde n'est pas d'accord sur la nécessité de chiffrer le SNI. Certains craignent que cette nécessité débouche sur une solution compliquée et fragile. D'autres ne veulent tout simplement pas priver surveillants et censeurs d'un mécanisme si pratique. En réponse à cette dernière objection (cf. RFC 8404), le RFC note que la méthode recommandée (section 2.3 du RFC), si on peut surveiller et filtrer, est de le faire dans les machines terminales. Après tout, si l'organisation contrôle ces machines terminales, elle peut les configurer (par exemple avec le certificat de l'intercepteur) et si elle ne les contrôle pas, elle n'a sans doute pas le droit d'intercepter les communications.

La solution est évidente, chiffrer le SNI. Ce ne sont pas les propositions qui ont manqué, depuis des années. Mais toutes avaient des inconvénients sérieux, liés en général à la difficulté du bootstrap. Avec quelle clé le chiffrer puisque c'est justement le SNI qui aide le serveur à choisir la bonne clé ?

La section 3 de notre RFC énumère les exigences auxquelles va devoir répondre la solution qui sera adoptée. (Rappelez-vous qu'il s'agit d'un travail en cours.) C'est que beaucoup de solutions ont déjà été proposées, mais toutes avaient de sérieux problèmes. Petit exercice avant de lire la suite : essayez de concevoir un protocole de chiffrement du SNI (par exemple « le SNI est chiffré avec la clé publique du serveur, récupérée via DANE » ou bien « le SNI est chiffré par une clé symétrique qui est le condensat du nom du serveur [vous pouvez ajouter du sel si vous voulez, mais n'oubliez pas d'indiquer où le trouver] ») et voyez ensuite si cette solution répond aux exigences suivantes.

Par exemple, pensez à la possibilité d'attaque par rejeu. Si le SNI est juste chiffré avec une clé publique du serveur, l'attaquant n'a qu'à observer l'échange, puis faire à son tour une connexion au serveur en rejouant le SNI chiffré et paf, dans la réponse du serveur, l'attaquant découvrira quel avait été le service utilisé. La solution choisie doit empêcher cela.

Évidemment, la solution ne doit pas imposer d'utiliser un secret partagé (entre le serveur et tous ses clients), un tel secret ne resterait pas caché longtemps.

Il faut aussi faire attention au risque d'attaque par déni de service, avec un méchant qui générerait plein de SNI soi-disant chiffrés pour forcer des déchiffrements inutiles. Certes, TLS permet déjà ce genre d'attaques mais le SNI peut être traité par une machine frontale n'ayant pas forcément les mêmes ressources que le vrai serveur.

Autre chose importante quand on parle de protéger la vie privée : il ne faut pas se distinguer (Do not stick out). Porter un masque du Joker dans la rue pour protéger son anonymat serait sans doute une mauvaise idée, risquant au contraire d'attirer l'attention. La solution choisie ne doit donc pas permettre à, par exemple, un état policier, de repérer facilement les gens qui sont soucieux de leur vie privée. Une extension spécifique du ClientHello serait dangereuse, car triviale à analyser automatiquement par un système de surveillance massive.

Il est évidemment souhaitable d'avoir une confidentialité persistante, c'est-à-dire que la compromission d'une clé privée ne doit pas permettre de découvrir, a posteriori, les serveurs auxquels le client s'était connecté. Simplement chiffrer le SNI avec la clé publique du serveur ne convient donc pas.

L'hébergement Web d'aujourd'hui est souvent compliqué, on peut avoir un frontal géré par une société d'hébergement, et des machines gérées par le client de l'hébergeur derrière, par exemple. Ou bien plusieurs clients de l'hébergeur sur la même machine physique, voire sur la même machine virtuelle avec certaines hébergements mutualisés. Cela peut être utile pour certaines solutions, par exemple le fronting où une machine frontale reçoit une demande de connexion TLS pour elle puis, une fois TLS démarré, reçoit le nom du vrai serveur, et relaie vers lui. Si la machine frontale relaie pour beaucoup de serveurs, cela fournit une assez bonne intimité. Mais cela nécessite de faire confiance à la machine frontale, et le risque d'attaque de l'homme du milieu (qui nous dit que ce frontal est le frontal légitime choisi par le serveur TLS ?) augmente. Or, plus la machine frontale protège des serveurs, plus elle est un objectif tentant pour la police ou les pirates.

Ah, et j'ai parlé du Web mais la solution doit évidemment fonctionner avec d'autres protocoles que HTTPS. Par exemple, le DNS sur TLS du RFC 7858 ou bien IMAP (RFC 8314) doivent fonctionner. Même pour HTTP, certaines particularités de HTTP peuvent poser problème, et il est donc important que la future solution de chiffrement de SNI soit agnostique, pour marcher avec tous les protocoles. Et elle doit également fonctionner avec tous les protocoles de transport, pas seulement TCP, mais aussi DTLS ou QUIC.

Le RFC note aussi qu'il serait bon d'avoir une solution de chiffrement de la négociation ALPN (RFC 7301). ALPN est moins indiscret que SNI mais il renseigne sur l'application utilisée.

Puisque j'ai parlé plus haut du fronting, cela vaut la peine de parler du fronting HTTP car c'est une technique courante, aussi bien pour échapper à la censure que pour protéger la vie privée. La section 4 du RFC lui est consacrée. Elle est décrite dans l'article de Fifield, D., Lan, C., Hynes, R., Wegmann, P., et V. Paxson, « Blocking-resistant communication through domain fronting ». Le principe est que le client TLS établit une connexion avec le système de fronting puis, une fois le chiffrement TLS en marche, le client demande la connexion avec le vrai serveur. Un surveillant ne pourra voir que l'utilisation d'un service de fronting, pas le nom du vrai service (le SNI en clair dira, par exemple, fronting.example.net). En pratique, cela marche bien avec HTTPS si le serveur de fronting et le vrai serveur sont sur le même système : il suffit alors d'indiquer le domaine du fronting dans le SNI et le vrai domaine dans les en-têtes Host: de HTTP. Cela ne nécessite aucune modification du protocole TLS.

Le fronting a quelques limites :

  • Le client doit trouver un service acceptant de faire du fronting. (Ce qui n'est pas évident.)
  • Le client doit configurer son logiciel pour utiliser un service de fronting.
  • Il faut évidemment faire confiance au service de fronting, qui est, d'une certaine façon, un homme du milieu. (Ceci dit, si serveur de fronting et vrai serveur sont au même endroit, cela n'implique pas de faire confiance à un nouvel acteur.) Le problème est d'autant plus crucial qu'il n'existe pas de moyen standard, pour un serveur, d'authentifier publiquement le service de fronting par lequel on peut y accéder. Des variantes du fronting existent, qui limitent ce problème, par exemple en faisant du HTTPS dans HTTPS, si le serveur de fronting l'accepte.
  • Cela ne marche qu'avec HTTP, puisque cela utilise le fait que les requêtes HTTP indiquent le vrai serveur de destination. (C'est d'ailleurs une des raisons pour lesquelles a été développé DoH, spécifié dans le RFC 8484.)

À noter que les trames ORIGIN du RFC 8336 peuvent être utiles en cas de fronting, pour indiquer le contenu venant du « vrai » serveur.

Voilà, vous connaissez maintenant le problème, l'IETF est en train de travailler aux solutions, le brouillon le plus avancé est draft-ietf-tls-esni.


Téléchargez le RFC 8744


L'article seul

Panne du site Web de la Poste, et la révocation des certificats

Première rédaction de cet article le 23 juillet 2020
Dernière mise à jour le 24 juillet 2020


Ce matin, les visiteurs du site Web de La Poste ont la désagréable surprise de voir leur navigateur afficher une alerte de sécurité qui les empêche d'aller sur le site https://www.laposte.fr/. Pourquoi ? C'est un problème assez rare, une révocation du certificat.

Voyons d'abord les symptômes vus par l'utilisateur ou l'utilisatrice normale : poste-revoquee.png

Le certificat a donc été révoqué, ce qui veut dire que l'organisme qui l'a émis, l'Autorité de Certification, a signé un message disant que ce certificat ne devait plus être utilisé (cela peut être, par exemple, car la clé privée correspondante a été compromise).

Et voyons maintenant les détails techniques. D'abord, quel est le numéro de série du certificat ?

% gnutls-cli www.laposte.fr
... - subject `CN=laposte.fr,serialNumber=35600000000048,O=La Poste
   S.A.,street=Quai André
   citroën\,7-11,L=Paris,ST=Île-de-France,C=FR,postalCode=75015,
   businessCategory=Business
   Entity,jurisdictionOfIncorporationLocalityName=Paris,
   jurisdictionOfIncorporationStateOrProvinceName=Île-de-France,
   jurisdictionOfIncorporationCountryName=FR', issuer `CN=CA de
   Certificados SSL EV,OU=BZ Ziurtagiri publikoa - Certificado publico
   EV,O=IZENPE S.A.,C=ES',
   serial 0x279dad0bbf3d7a5e5b63f8aae70fa366,
   RSA key 4096 bits, signed using RSA-SHA256, activated `2018-08-03 06:39:37 UTC', expires `2020-08-03 06:39:31 UTC', pin-sha256="fICfTOyzreCYOYqWfcbL3yJzdWGVPAhmDv3+IDBjrRo="
    ...
  

(J'aime bien les informations en basque mises par l'AC, Izenpe.) OK, le certificat final est 279dad0bbf3d7a5e5b63f8aae70fa366 (c'est bien celui qui est révoqué, autrement, il aurait également fallu tester les autres certificats de la chaîne). Cherchons-le dans les journaux Certificate Transparency (normalisés par le RFC 6962). On les trouve en https://crt.sh/?serial=279dad0bbf3d7a5e5b63f8aae70fa366, ce qui permet de voir qu'il est en effet révoqué : poste-revoquee-ct-jnl.png

Le service crt.sh ne nous donne pas la date et la raison de la révocation. Regardons donc la CRL :

% openssl s_client -connect www.laposte.fr:443 -showcerts | openssl x509 -text
    ...
    X509v3 CRL Distribution Points: 
                Full Name:
                  URI:http://crl.izenpe.com/cgi-bin/crlsslev2
     ...

% wget http://crl.izenpe.com/cgi-bin/crlsslev2	  

% openssl crl -inform DER -text -noout -in crlsslev2
...
    Serial Number: 279DAD0BBF3D7A5E5B63F8AAE70FA366
        Revocation Date: Jul 22 07:35:53 2020 GMT
        CRL entry extensions:
            X509v3 CRL Reason Code: 
                Unspecified
  

Et nous avons désormais la révocation de ce certificat 279DAD0BBF3D7A5E5B63F8AAE70FA366 , sa date (il y a plus de vingt-quatre heures, mais notez que la CRL n'est pas forcément publiée immédiatement après l'opération de révocation) et la raison (enfin, si on peut dire).

Sinon, dans un cas comme cela, il peut être prudent de vérifier que le problème n'est pas local et qu'il ne s'agit pas, par exemple, d'un détournement vers un serveur pirate. On va donc utiliser cent sondes RIPE Atlas en France pour demander le certificat :

 % blaeu-cert --requested 100 --country FR --serial -4 www.laposte.fr
99 probes reported
[279dad0bbf3d7a5e5b63f8aae70fa366] : 99 occurrences 
Test #26427062 done at 2020-07-23T08:50:57Z
  

OK, toutes les sondes voient le même numéro de série donc ce n'est sans doute pas un détournement local.

Suite de l'affaire : vers 1100 UTC, le 23 juillet, le certificat révoqué a enfin été remplacé, par un Let's Encrypt. On peut le voir dans le journal. Un autre certificat, fait par Global Sign, a été émis et a remplacé le Let's Encrypt quelques heures après. Notez qu'il ne s'agit que du site Web public, www.laposte.fr. Le 24 juillet au matin, le service api.laposte.fr (API du système de suivi de colis) avait toujours un certificat révoqué de l'ancienne AC.

Sinon, il y a cet article du Monde Informatique, qui n'apprend rien de plus, et un autre du Figaro, où la Poste raconte que l'ancien certificat a été révoqué avant l'installation du nouveau.


L'article seul

RFC 8799: Limited Domains and Internet Protocols

Date de publication du RFC : Juillet 2020
Auteur(s) du RFC : B. E. Carpenter (Univ. of Auckland), B. Liu (Huawei)
Pour information
Première rédaction de cet article le 15 juillet 2020


Il y a depuis longtemps un débat sur l'architecture de l'Internet : dans quelle mesure faut-il un Internet uniforme, où tout est pareil partout, et dans quelle mesure faut-il au contraire des particularités qui ne s'appliquent que dans telle ou telle partie de l'Internet ? Bien sûr, la réponse n'est pas simple, et ce nouveau RFC explore la question et discute ses conséquences, par exemple pour le développement des normes.

Sur le long terme, la tendance est plutôt au développement de règles locales, et de services qui ne sont accessibles que d'une partie de l'Internet. Le NAS avec les photos de famille accessible uniquement depuis la maison, le site Web permettant aux employés d'indiquer leurs demandes de congés, qu'on ne peut voir que depuis le réseau de l'entreprise, parce qu'on y est présent physiquement, ou bien via le VPN, les lois d'un pays qu'il essaie, avec plus ou moins de succès, d'appliquer sur son territoire… Mais, d'abord, une précision : le terme « local » ne signifie pas forcément une région géographique précise. « Local » peut, par exemple, désigner le réseau d'une organisation spécifique, qui y applique ses règles. « Local » peut être un bâtiment, un véhicule, un pays ou bien un réseau s'étendant au monde entier.

À noter que certains ont poussé cette tendance très loin en estimant que l'Internet allait se fragmenter en réseaux distincts, ne communiquant plus, voire que cela avait déjà été fait. C'est clairement faux, aujourd'hui, comme l'explique bien, par exemple, le RFC 7754, ou bien Milton Mueller dans son livre « Will The Internet Fragment? ». On peut toujours visiter ce blog depuis tous les réseaux connectés à l'Internet…

Un petit point de terminologie : le RFC utilise le terme « domaine » pour désigner une région de l'Internet ayant des règles spécifiques. Ce terme ne doit pas être confondu avec celui de « nom de domaine » qui désigne quelque chose de tout à fait différent. « Domaine », dans ce RFC, est plutôt utilisé dans le même sens que dans les RFC 6398 et RFC 8085, pour indiquer un « domaine administratif ». C'est un environnement contrôlé, géré par une entité (entreprise, association, individu) et qui peut définir des règles locales et les appliquer.

Aujourd'hui, le concept de « domaine local » ou « domaine limité » n'est pas vraiment formalisé dans l'Internet. Des RFC comme le RFC 2775 ou le RFC 4924 ont plutôt défendu l'inverse, la nécessité de maintenir un Internet unifié, insistant sur le problème des middleboxes intrusives (RFC 3234, RFC 7663 et RFC 8517). Actuellement, il y a déjà une fragmentation de l'Internet en ilots séparés, puisque certaines fonctions ne marchent pas toujours, et qu'on ne peut donc pas compter dessus. C'est le cas par exemple des en-têtes d'extension IPv6 (RFC 7872), de la découverte de la MTU du chemin (RFC 4821) ou de la fragmentation. Sans compter le filtrage par les pare-feux. Bref, tous ces problèmes font que, de facto, l'Internet n'est plus transparent, et que des communications peuvent échouer, non pas en raison d'une panne ou d'une bogue, mais en raison de règles décidées par tel ou tel acteur sur le trajet. Donc, en pratique, on a des « domaines limités » mais sans que cela soit explicite, et cela joue un rôle important dans l'utilisation du réseau.

Si on avait des « domaines limités » ou « domaines locaux » explicites, quel serait le cahier des charges de ce concept ? La section 3 du RFC donne quelques idées à ce sujet. Par exemple, ces scénarios sont envisagés :

  • Un cas d'usage évident est le réseau de la maison, où des politiques spécifiques à ce logement sont tout à fait légitimes (par exemple, utilisation de Pi-hole pour bloquer les publicités). Typiquement non géré par des professionnels (voire pas géré du tout…), il doit marcher « à la sortie de la boîte ». Le RFC 7368 donne davantage de détails sur cette notion de réseau à la maison.
  • Le réseau interne d'une petite entreprise est souvent proche du réseau de la maison : politique locale (donc « domaine limité ») mais personne de compétent pour s'en occuper. Par contre, il est parfois installé par des professionels (mais attention, « professionnel » ≠ « compétent »).
  • Sujet à la mode, le réseau dans un véhicule. À l'intérieur du véhicule, il y a des exigences spécifiques, liées à la sécurité, et qui justifient des règles locales.
  • Les réseaux SCADA ont également d'excellentes raisons d'avoir une politique locale, notamment en sécurité (cf. RFC 8578).
  • Toujours dans le domaine industriel, il y a aussi les réseaux de capteurs et, plus généralement, l'IoT. Ils demandent également des règles locales spécifiques et, en prime, posent parfois des problèmes techniques ardus. C'est encore pire si les objets sont contraints en ressources matérielles (RFC 7228).
  • Plus science-fiction, un autre scénario où on ne peut pas suivre les règles de l'Internet public et où il faut des règles locales, les DTN (RFC 4838).
  • Les grands réseaux internes d'une organisation, répartie sur plusieurs sites physiques, peuvent également être concernées par le concept de politique locale. Notez qu'un seul RFC parle d'eux, à propos d'IPv6, le RFC 7381.
  • Il y a aussi le cas du réseau semi-fermé d'un opérateur. Le réseau est utilisé par des clients de cet opérateur, et celui-ci a une offre réservée à certains, qui propose des garanties de service (avec des techniques comme EVPN ou VPLS). (Le RFC n'en parle pas, mais attention, ici, on commence à s'approcher de la question de la neutralité de l'Internet.)
  • Et enfin (mais je n'ai pas recopié toute la liste du RFC), il y a les centres de données où, là encore, une organisation souhaite avoir une politique locale.

Bref, le cas est fréquent. On se dit, en regardant tous ces scénarios où un réseau, quoique connecté à l'Internet, a de très bonnes raisons d'avoir des règles locales spécifiques, qu'il serait bon qu'une organisation de normalisation, comme l'IETF, trouve une solution générale. Le problème est que, justement, chaque politique locale est différente. Néanmoins, les auteurs du RFC suggèrent de réfléchir à une nouvelle façon d'analyser les propositions à l'IETF, en ne considérant pas simplement leur usage sur l'Internet public (le vrai Internet, dirais-je) mais aussi ce qui se passera sur ces domaines limités.

Le RFC cite aussi le cas de protocoles qu'on avait cru pouvoir déployer sur l'Internet public mais qui en fait n'ont marché que dans des environnements fermés. Ce fut le cas bien sûr de RSVP (RFC 2205). Ses auteurs avaient pensé qu'un protocole de réservation de ressources pourrait marcher sur un réseau public, oubliant que, dans ce cas, chaque égoïste allait évidemment se réserver le plus de ressources possibles. (Ce n'est pas un problème spécifique à RSVP : aucun mécanisme de qualité de service ne peut marcher sur un réseau public décentralisé. Imaginez un bit « trafic très important, à ne jamais jeter » ; tout le monde le mettrait à 1 !)

Bon, maintenant qu'on a décrit les scénarios d'usage, quelle(s) solution(s) ? La section 4 du RFC liste quelques exemples de techniques conçues spécialement pour des domaines limités. Notons que le RFC parle des techniques en couche 3, la couche 2 étant évidemment toujours pour un domaine local (encore que, avec TRILLRFC 6325, la couche 2 peut aller loin). Par exemple :

  • DiffServ (RFC 2464), puisque la signification des bits utilisés est purement locale.
  • RSVP, déjà cité.
  • La virtualisation de réseaux, qui permet de créer un domaine local au-dessus de réseaux physiques divers. Idem pour celle dans les centres de données (RFC 8151).
  • Le SFC du RFC 7665, qui permet d'attacher des instructions particulières aux paquets (encodées selon le RFC 8300), instructions qui n'ont évidemment de sens que dans un domaine local.
  • Dans un genre analogue, il y a aussi le routage par les segments (RFC 8402).
  • L'IETF a une série d'adaptations des protocoles Internet spécialement conçues pour le cas de la maison, collectivement nommées Homenet (RFC 7368, RFC 7788).
  • Avec IPv6, d'autres possibilités amusantes existent. L'étiquette de flot (RFC 6294) peut permettre de marquer tel ou tel flot de données, pour ensuite lui appliquer une politique spécifique. Les en-têtes d'extension permettent de déployer des techniques comme le routage via des segments, cité plus haut. (Le fait que ces en-têtes passent mal sur l'Internet public - cf. RFC 7045 et RFC 7872 n'est pas un problème dans un domaine limité.) Et la grande taille des adresses IPv6 permet d'encoder dans l'adresse des informations qui seront ensuite utilisées par les machines du domaine.
  • Et enfin je vais citer les PvD (ProVisioning Domain) du RFC 7556, qui formalisent cette notion de domaine local, et lui donnent un cadre.

La section 5 du RFC conclut qu'il peut être souhaitable d'avoir des protocoles explicitement réservés à des domaines limités, et pour qui les règles pourraient être différentes de celles des protocoles conçus pour le grand Internet ouvert. Le RFC donne un exemple : si faire ajouter des en-têtes d'extension à un paquet IPv6 par le réseau qu'il traverse serait une abominable violation de la neutralité, en revanche, dans un domaine local, pourquoi ne pas se dire que ce serait possible, et peut-être intéressant dans certains cas ? Pour de tels protocoles, on ne pourrait pas garantir leur interopérabilité sur l'Internet, mais ils pourraient former une intéressante addition au socle de base du travail de l'IETF, qui sont les protocoles de l'Internet public.

Une fois posée l'opinion que les protocoles « à usage local » sont intéressants (et qu'ils existent déjà), comment les améliorer ? Actuellement, comme le concept de « domaine limité » n'est pas explicitement défini, le domaine est créé par la configuration des machines, des pare-feux, des résolveurs DNS, des ACL, du VPN… Un processus compliqué et où il est facile de se tromper, surtout avec le BYOD, le télétravail… Imaginez un serveur HTTP privé, qui ne sert que le domaine. Comment le configurer pour cela ? Compter sur les pare-feux ? Mettre des ACL sur le serveur (ce qui nécessite de connaître la liste, évolutive, des préfixes IP du domaine) ? Définir un domaine nécessite d'avoir un intérieur et un extérieur, et que chaque machine, chaque application, sache bien de quel côté elle est (ou à l'interface entre les deux, si elle sert de garde-frontière). Et, quand on est à l'intérieur, et qu'on envoie ou reçoit un message, il est important de savoir si on l'envoie à l'extérieur ou pas, si on le reçoit de l'intérieur ou pas. Bref, actuellement, il n'y a pas de solution propre permettant de répondre à cette question.

Le RFC définit alors un cahier des charges pour qu'on puisse définir des règles locales et que ça marche. Notamment :

  • Comme tout truc sur l'Internet, le domaine devrait avoir un identificateur. Le RFC suggère que ce soit une clé publique cryptographique, pour permettre les authentifications ultérieures. (Le RFC 7556, sur les PvD, propose plutôt que ce soit un simple FQDN.)
  • Il serait bien sympa de pouvoir emboîter les domaines (un domaine limité dans un autre domaine limité).
  • Les machines devraient pouvoir être dans plusieurs domaines.
  • Idéalement, les machines devraient pouvoir être informées des domaines qu'elles peuvent rejoindre, pour pouvoir choisir.
  • Évidemment, tout cela devrait être sécurisé. (Par exemple avec un mécanisme d'authentification de la machine.)
  • Il faudrait un mécanisme de retrait. (Une machine quitte le domaine.)
  • Ce serait bien de pouvoir savoir facilement si telle machine avec qui on envisage de communiquer est dans le même domaine que nous.
  • Et enfin on voudrait pouvoir accéder facilement aux informations sur la politique du domaine, par exemple sur ses règles de filtrage. (Exemple : un domaine limité de l'employeur interdisant de contacter tel ou tel service.)

À l'heure actuelle, tout ceci relève du vœu pieux.

Une motivation fréquente des domaines locaux (ou limités) est la sécurité. La section 7 de notre RFC, dédiée à ce sujet, fait remarquer qu'on voit souvent des gens qui croient que, dans un domaine limité, on peut réduire la sécurité car « on est entre nous ». Cela oublie, non seulement le fait que la plupart des menaces sont internes (par une malhonnêteté ou par une infection), mais aussi celui qu'un protocole qu'on croyait purement interne se retrouve parfois utilisé en extérieur. Un exemple classique est le site Web « interne » pour lequel on se dit que HTTPS n'est pas nécessaire. Si, suite à un problème de routage ou de pare-feu, il se retrouve exposé à l'extérieur, il n'y aura pas de seconde chance.

Enfin, l'annexe B du RFC propose une taxonomie des domaines limités : utile si vous voulez creuser la question.


Téléchargez le RFC 8799


L'article seul

Le rapport du CNNum sur l'interopérabilité pour les GAFA

Première rédaction de cet article le 6 juillet 2020


Aujourd'hui 6 juillet, le Conseil National du Numérique a publié son étude de cas sur l’interopérabilité des réseaux sociaux. Un petit résumé.

Si vous avez déjà essayé de convaincre un utilisateur ou une utilisatrice de Facebook ou d'un autre réseau social centralisé de quitter cet environnement néfaste et d'utiliser des réseaux sociaux libres et décentralisés comme le fédivers, vous savez que c'est très difficile, notamment en raison de l'argument choc « mais tous mes amis / clients / électeurs / camarades y sont, je dois y être aussi, quelles que soient mes opinions personnelles, je ne peux pas me permettre de me déconnecter d'eux ». (Très peu de gens justifieront leur choix en disant que le GAFA est de meilleure qualité que les alternatives.) Effectivement, ce verrouillage des utilisateurs est la grande force des GAFA : en pratique, on ne peut pas partir, sauf à se résigner à mener une vie peu sociale en compagnie de trois libristes dans un garage.

Le problème est connu depuis longtemps. Quelles sont les solutions ? On peut être optimiste et continuer à essayer de convaincre utilisatrices et utilisateurs. Cela prend du temps et le succès n'est pas garanti. On peut aussi se résigner, et n'utiliser que les réseaux sociaux des GAFA. Ou bien on peut essayer d'ouvrir une brèche dans le monopole de ces réseaux sociaux en leur imposant l'interopérabilité.

De quoi s'agit-il ? L'idée est très banale et déjà très répandue sur l'Internet : il s'agit de permettre à des serveurs gérés par des organisations différentes, et réalisés par des programmeurs différents, de communiquer. C'est banal car c'est exactement ainsi que fonctionne, depuis ses débuts (antérieurs aux débuts de l'Internet…) le courrier électronique. On peut échanger des messages avec des gens qui ne sont pas chez le même hébergeur de courrier que soi, et encore heureux. Comme le notait la rapporteuse de l'étude, Myriam El Andaloussi, « L'interopérabilité a déjà fait ses preuves. » L'interopérabilité est en général assurée par une norme technique rédigée : si tout le monde la suit, on pourra communiquer. (Si vous êtes informaticien·ne, vous savez que l'interopérabilité, en pratique, ne se fait pas forcément toute seule, mais je simplifie.) En fait, l'Internet lui-même est un exemple parfait que l'interopérabilité fonctionne : des machines de fournisseurs différents, gérées par des organisations différentes, communiquent entre elles tous les jours.

Mais le monde des réseaux sociaux, sous la pression des GAFA, ne fonctionne pas comme cela : la règle n'est pas l'interopérabilité, mais le silo isolé. Si vous n'êtes pas utilisateur de Facebook, vous ne pouvez pas envoyer de message à un utilisateur Facebook et réciproquement. Les GAFA pourraient techniquement utiliser des solutions interopérables pour communiquer avec l'extérieur, c'est banal, ce n'est pas très compliqué techniquement (d'autant plus qu'on parle de très grosses entreprises ayant des ressources humaines considérables, en qualité et en quantité). Mais ce n'est clairement pas leur intérêt. Si cela l'était, ils auraient pu le faire depuis longtemps.

Le travail du Conseil National du Numérique (CNN) était de regarder la possibilité d'imposer cette interopérabilité. Compte tenu du poids de ces réseaux sociaux centralisés, il serait anormal qu'ils puissent continuer à utiliser leur position dominante pour verrouiller le « marché » et empêcher toute communication entre eux et l'extérieur. Le CNN a donc consulté beaucoup de monde et produit l'étude qui en résulte. Elle fait donc le tour de la question, et est très exhaustive. Tous les aspects, techniques, politiques, juridiques, sont examinés, et tous les points de vue sont exposés.

C'est d'ailleurs la limite de ce travail : le CNN ne tranche pas vraiment, il ménage la chèvre et le chou, montre des pistes, liste les avantages et les inconvénients mais ne fait pas vraiment de recommandation concrète. Il déblaie le terrain mais ce ne sera pas suffisant face aux GAFA qui, pendant ce temps, consolident toujours plus leur position. Pour échapper à leur domination, il faudrait des mesures immédiates, poussées par une forte volonté politique. L'inertie joue en faveur des GAFA. Discuter sans fin de tel ou tel détail pratique de mise en œuvre de l'interopérabilité ne ferait que pérenniser leur domination.

Le 6 juillet, la sortie du rapport avait été suivi d'une présentation en ligne, puis d'un panel de discussion. En fait, comme beaucoup de panels, il s'était résumé à une juxtaposition de discours, sans interactivité. Il n'est pas étonnant que le représentant de Snapchat se soit déclaré opposé à toute « réglementation contraignante » (comme si le but d'une réglementation n'était pas justement d'obtenir ce que le libre jeu du marché ne produisait pas) et que celle de Facebook ait esquivé comme « trop technique » la seule question du public, sur l'abandon par Messenger du protocole XMPP qui assurait, à une époque, l'interopérabilité de Messenger.

Quelques lectures utiles sur ce sujet de l'interopérabilité des réseaux sociaux :


L'article seul

RFC 8792: Handling Long Lines in Content of Internet-Drafts and RFCs

Date de publication du RFC : Juin 2020
Auteur(s) du RFC : K. Watsen (Watsen Networks), E. Auerswald, A. Farrel (Old Dog Consulting), Q. Wu (Huawei Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF netmod
Première rédaction de cet article le 3 juillet 2020


Le sujet peut sembler un point de détail sans importance mais, dans un RFC, tout compte. Que serait une norme si les exemples de code et les descriptions en langage formel avaient la moindre ambiguïté ? C'est le cas par exemple des lignes trop longues : comment les couper pour qu'on comprenne bien ce qui s'est passé ? Ce RFC propose deux méthodes.

Le cas principal est celui des modules YANG (RFC 7950) et c'est pour cela que ce RFC sort du groupe de travail netmod. Mais le problème concerne en fait tous les cas où on veut mettre dans un RFC du texte dans un langage formel et que les lignes dépassent ce qui est généralement considéré comme acceptable. Notre RFC formalise deux solutions, toutes les deux traditionnelles et déjà souvent utilisées, mettre une barre inverse après les lignes coupées, ou bien mettre cette barre inverse et une autre au début de la ligne suivante. Donc, dans le premier cas, le texte :

Il n'est pas vraiment très long, mais c'est un exemple.
  

Ce texte, coupé à quarante-cinq caractères, donnerait :

Il n'est pas vraiment très long, mais c'est \
un exemple.
  

Ou bien :

Il n'est pas vraiment très long, mais c'est \
       un exemple.
  

Et, avec la seconde solution :

Il n'est pas vraiment très long, mais c'est \
\un exemple.
  

Si la forme officielle des RFC n'est plus le texte brut depuis le RFC 7990, il y a toujours une version en texte brut produite, suivant le format décrit dans le RFC 7994. Il impose notamment des lignes de moins de 72 caractères. Or, les exemples de code, ou les textes décrits en un langage formel (modules YANG, ABNF, ou ASN.1, par exemple), dépassent facilement cette limite. Les outils actuels comme xml2rfc ne gèrent pas vraiment ce cas, se contentant d'afficher un avertissement, et laissant l'auteur corriger lui-même, d'une manière non officiellement standardisée.

Désormais, c'est fait, il existe un tel standard, ce nouveau RFC, standard qui permettra notamment de bien traiter les textes contenus dans l'élement <sourcecode> (RFC 7991, section 2.48) du source du RFC. Naturellement, rien n'interdit d'utiliser cette norme pour autre chose que des RFC (section 2 du RFC).

Les deux stratégies possibles, très proches, sont « une seule barre inverse » et « deux barres inverses ». Dans les deux cas, un en-tête spécial est mis au début, indiquant quelle stratégie a été utilisée, pour qu'il soit possible de reconstituer le fichier original.

Dans le premier cas, la stratégie à une seule barre inverse (section 7 du RFC), une ligne est considérée pliée si elle se termine par une barre inverse. La ligne suivante (moins les éventuels espaces en début de ligne) est sa suite. Dans le deuxième cas, la stratégie à deux barres inverses (section 8), une autre barre inverse apparait au début des lignes de continuation.

Différence pratique entre les deux stratégies ? Avec la première (une seule barre inverse), le résultat est plus lisible, moins encombré de caractères supplémentaires. Par contre, comme les espaces au début de la ligne de continuation sont ignorés, cette stratégie va échouer pour des textes comportant beaucoup d'espaces consécutifs. La deuxième est plus robuste. La recommandation du RFC est donc d'essayer d'abord la première stratégie, qui produit des résultats plus jolis, puis, si elle échoue, la deuxième. L'outil rfcfold, présenté plus loin, fait exactement cela par défaut.

La section 4 rappellait le cahier des charges des solutions adoptées :

  • Repli des lignes automatisable (cf. le script rfcfold présenté à la fin), notamment pour le cas où un RFC ou autre document est automatiquement produit à partir de sources extérieures,
  • Reconstruction automatisable du fichier original, pour qu'on puisse réutiliser ce qu'on a trouvé dans un RFC en texte brut, ce qui est déjà utilisé par les outils de soumission d'Internet-Drafts, qui extraient le YANG automatiquement et le valident, pratique qui pourrait être étendu à XML et JSON, et qui assure une meilleure qualité des documents, dès la soumission.

En revanche, la section 5 liste les « non-buts » : il n'est pas prévu que les solutions fonctionnent pour l'art ASCII. Et il n'est pas prévu de gérer les coupures spécifiques à un format de fichier. Les stratégies décrites dans ce RFC sont génériques. Au contraire, des outils comme pyang ou yanglint connaissent la syntaxe de YANG et peuvent plier les lignes d'un module YANG plus intelligemment (cf. aussi RFC 8340).

L'annexe A du RFC contient un script bash qui met en œuvre les deux stratégies (le script rfcfold.bash). Ici, je pars d'un fichier JSON compact (au format du RFC 8785). D'abord, première stratégie (notez la ligne de documentation ajoutée au début) :

% ./rfcfold.bash -s 1 -i /tmp/i.txt -o /tmp/t.txt && cat /tmp/t.txt
========== NOTE: '\' line wrapping per RFC 8792 ===========

[{"af":6,"avg":23.4686283333,"dst_addr":"2001:67c:2218:e::51:41","ds\
t_name":"2001:67c:2218:e::51:41","dup":0,"from":"2a01:4240:5f52:bbc4\
::ba3","fw":5020,"group_id":26102101,"lts":30,"max":23.639063,"min":\
23.285885,"msm_id":26102101,"msm_name":"Ping","mver":"2.2.1","prb_id\
":1000276,"proto":"ICMP","rcvd":3,"result":[{"rtt":23.480937},{"rtt"\
:23.639063},{"rtt":23.285885}],"sent":3,"size":64,"src_addr":"2a01:4\
240:5f52:bbc4::ba3","step":null,"stored_timestamp":1593694541,"times\
tamp":1593694538,"ttl":52,"type":"ping"},{"af":6,"avg":65.9926666667\
...

Et avec la deuxième stratégie :

% ./rfcfold.bash -s 2 -i /tmp/i.txt -o /tmp/t.txt && cat /tmp/t.txt|more 
========== NOTE: '\\' line wrapping per RFC 8792 ==========

[{"af":6,"avg":23.4686283333,"dst_addr":"2001:67c:2218:e::51:41","ds\
\t_name":"2001:67c:2218:e::51:41","dup":0,"from":"2a01:4240:5f52:bbc\
\4::ba3","fw":5020,"group_id":26102101,"lts":30,"max":23.639063,"min\
\":23.285885,"msm_id":26102101,"msm_name":"Ping","mver":"2.2.1","prb\
\_id":1000276,"proto":"ICMP","rcvd":3,"result":[{"rtt":23.480937},{"\
\rtt":23.639063},{"rtt":23.285885}],"sent":3,"size":64,"src_addr":"2\
\a01:4240:5f52:bbc4::ba3","step":null,"stored_timestamp":1593694541,\
\"timestamp":1593694538,"ttl":52,"type":"ping"},{"af":6,"avg":65.992\

L'option -r du script permet d'inverser, c'està-dire de reconstituer le fichier original à partir du fichier aux lignes pliées.

L'outil rfcfold n'a pas de connaissance des formats de fichiers et coupe donc brutalement, y compris au milieu d'un nom de variable. Un outil plus intelligent (section 9.3) pourrait couper au bon endroit, par exemple, pour XML, juste avant le début d'un élément XML.


Téléchargez le RFC 8792


L'article seul

RFC 8820: URI Design and Ownership

Date de publication du RFC : Juin 2020
Auteur(s) du RFC : M. Nottingham
Première rédaction de cet article le 1 juillet 2020


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

Ce RFC est destiné aux concepteurs d'application (par exemple les API REST) et aux auteurs de protocoles qui étendent les protocoles existants.

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

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

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

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

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

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

La partie normative de notre RFC est la section 2. Elle explicite le principe. D'abord, éviter de contraindre l'usage d'un plan particulier. Par exemple, imposer http:// peut être trop contraignant, certaines applications ou extensions pourraient marcher avec d'autres plans d'URI comme par exemple file:// (RFC 8089).

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

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

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

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

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

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

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

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

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

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

Les changements depuis le premier RFC qui avait décrit ces règles (RFC 7320) sont résumés dans l'annexe A. En gros, moins d'interdictions, et davantage de conseils. Par exemple, la règle comme quoi une application ne devrait pas empêcher l'utilisation de futurs plans (comme file: en plus de http:) n'utilise maintenant plus le vocabulaire normatif du RFC 2119 et est donc désormais davantage un avis. De même, pour le composant « requête » de l'URI, l'interdiction de spécifier sa syntaxe dans les applications n'est désormais plus une règle absolue. Autre cas, le RFC 7320 parlait négativement, non seulement du préfixe de chemin d'URI fixe (le /Foobar dans mes exemples) mais même d'une partie fixe du chemin, y compris si elle n'était pas au début du chemin. Cela avait suscité des débats houleux dans la discussion du successeur du RFC 6962 et cette restriction a donc été supprimée.


Téléchargez le RFC 8820


L'article seul

RFC 8785: JSON Canonicalization Scheme (JCS)

Date de publication du RFC : Juin 2020
Auteur(s) du RFC : A. Rundgren, B. Jordan (Broadcom), S. Erdtman (Spotify AB)
Pour information
Première rédaction de cet article le 29 juin 2020


Des opérations cryptographiques comme la signature sont nettement plus simples lorsqu'il existe une forme canonique des données, une représentation normalisée qui fait que toutes les données identiques auront la même représentation. Le format de données JSON n'a pas de forme canonique standard, ce RFC documente une des canonicalisations possibles, JCS (JSON Canonicalization Scheme).

Pourquoi canonicaliser ? Parce que deux documents JSON dont le contenu est identique peuvent avoir des représentations texte différentes. Par exemple :

{"foo": 1, "bar": 3}
  

et

{
  "foo": 1,
  "bar": 3
}
  

représentent exactement le même objet JSON. Mais la signature de ces deux formes textuelles ne donnera pas le même résultat. Pour les mécanismes de signature de JSON (comme JWS, décrit dans le RFC 7515), il serait préférable d'avoir un moyen de garantir qu'il existe une représentation canonique de l'objet JSON. Ce RFC en propose une. Je vous le dis tout de suite, la forme canonique de l'objet ci-dessus sera :

{"bar":3,"foo":1}
  

JSON est normalisé dans le RFC 8259. Il n'a pas de canonicalisation standard. Comme c'est une demande fréquente, plusieurs définitions d'une forme canonique de JSON ont été faites (cf. annexe H du RFC), comme Canonical JSON ou comme JSON Canonical Form. Mais aucune n'est encore la référence. (Vous noterez que ce RFC n'est pas une norme.) Cette situation est assez embêtante, alors que XML, lui, a une telle norme (cf. XML Signature).

Notez que la solution décrite dans ce RFC se nomme JCS, mais qu'il y a aussi un autre JCS, JSON Cleartext Signature.

Parmi les concepts importants de la proposition de ce RFC, JCS :

  • Réutiliser les règles de sérialisation de la norme ECMA, connues sous le nom de « ES6 »,
  • Le JSON doit suivre le sous-ensemble I-JSON du RFC 7493, ce qui implique l'absence de duplication des noms de membres dans un objet, l'utilisation de IEEE-754 pour les nombres, etc.

La section 3 du RFC décrit les opérations qui, ensemble, forment la canonicalisation JCS. À partir de données en mémoire (obtenues soit en lisant un fichier JSON, ce que je fais dans les exemples à la fin, soit en utilisant des données du programme), on émet du JSON avec :

  • Pas d'espaces entre les éléments lexicaux ("foo":1 et pas "foo": 1),
  • Représentation des nombres en suivant les règles de sérialisation « ES6 » citées plus haut (3000000 au lieu de 3E6, c'est la section 7.12.2.1 de ES6, si vous avez le courage, les puissances de 10 où l'exposant est inférieur à 21 sont développées),
  • Membres des objets (rappel : un objet JSON est un dictionnaire) triés ({"a":true,"b":false} et non pas {"b:"false,"a":true}),
  • Chaînes de caractères en UTF-8.

Concernant le tri, André Sintzoff me fait remarquer que les règles de tri de JSON sont parfois complexes. Évidentes pour les caractères ASCII, elles sont plus déroutantes en dehors du BMP.

Plusieurs annexes complètent ce RFC. Ainsi, l'annexe B fournit des exemples de canonicalisation des nombres.

Et pour les travaux pratiques, on utilise quoi ? L'annexe A du RFC contient une mise en œuvre en JavaScript, et l'annexe G une liste d'autres mises en œuvre (que vous pouvez aussi trouver en ligne). Ainsi, en npm, il y a https://www.npmjs.com/package/canonicalize et, en Java, il y a https://github.com/erdtman/java-json-canonicalization. (Si vous voulez programmer la canonicalisation de JSON vous-même, l'annexe F contient d'utiles conseils aux programmeurs. Mais, ici, on se contentera de logiciels déjà écrits.)

Commençons avec Python, et https://github.com/cyberphone/json-canonicalization/tree/master/python3. Avec cet exemple de départ :

{
       "numbers": [333333333.33333329, 1E30, 4.50,
                   2e-3, 0.000000000000000000000000001],
       "string": "\u20ac$\u000F\u000aA'\u0042\u0022\u005c\\\"\/",
       "literals": [null, true, false]
 }
  

Et ce programme :

from org.webpki.json.Canonicalize import canonicalize

import json 
import sys

raw = open(sys.argv[1]).read()
data = canonicalize(json.loads(raw))
print(data.decode())
  

On obtient :

% git clone https://github.com/cyberphone/json-canonicalization.git
% export PYTHONPATH=json-canonicalization/python3/src
% ./canonicalize.py test.json
{"literals":[null,true,false],"numbers":[333333333.3333333,1e+30,4.5,0.002,1e-27],"string":"€$\u000f\nA'B\"\\\\\"/"}
  

Et en Go ? Avec le même fichier JSON de départ, et ce programme :

package main

import ("flag";
	"fmt";
	"os";)

import "webpki.org/jsoncanonicalizer"

func main() {
	flag.Parse()
	file, err := os.Open(flag.Arg(0))
	if err != nil {
		panic(err)
	}
	data := make([]byte, 1000000)
	count, err := file.Read(data)
	if err != nil {
		panic(err)
	}
	result, err := jsoncanonicalizer.Transform(data[0:count])
	if err != nil {
		panic(err);
	} else {
		fmt.Printf("%s", result);
	}
}
  

On arrive au même résultat (ce qui est bien le but de la canonicalisation) :

% export GOPATH=$(pwd)/json-canonicalization/go
% go build canonicalize.go
%  ./canonicalize.py test.json
{"literals":[null,true,false],"numbers":[333333333.3333333,1e+30,4.5,0.002,1e-27],"string":"€$\u000f\nA'B\"\\\\\"/"}
  

Comme notre RFC contraint le JSON à suivre le sous-ensemble I-JSON (RFC 7493), si le texte d'entrée ne l'est pas, il va y avoir un problème. Ici, avec un texte JSON qui n'est pas du I-JSON (deux membres de l'objet principal ont le même nom) :

% cat test3.json
{
  "foo": 1,
  "bar": 3,
  "foo": 42
}

% ./canonicalize test3.json
panic: Duplicate key: foo
  

(Un autre code en Go est en https://github.com/ucarion/jcs.)

L'excellent programme jq n'a pas d'option explicite pour canonicaliser, mais Sébastien Lecacheur me fait remarquer que les options -c et -S donnent apparemment le même résultat (y compris sur les nombres, ce qui ne semble pas documenté) :

% cat example.json 
{
  "foo":                               1,
  "bar": 3000000000000000000000000000000,
"baz": true
}

% jq -cS . example.json
{"bar":3e+30,"baz":true,"foo":1}
  

Par contre, je n'ai rien trouvé sur ce formateur en ligne.

Comme il y a un brevet pour tout, notez qu'apparemment VMware prétend avoir inventé la canonicalisation JSON (cf. ce signalement, et le commentaire « The patent is effectively a JSON based "remake" of XML's "enveloped" signature scheme which in the submitter's opinion makes it invalid. »).


Téléchargez le RFC 8785


L'article seul

RFC 8765: DNS Push Notifications

Date de publication du RFC : Juin 2020
Auteur(s) du RFC : T. Pusateri, S. Cheshire (Apple)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnssd
Première rédaction de cet article le 23 juin 2020


Lorsqu'une donnée DNS change dans les serveurs faisant autorité, les clients ne seront prévenus que lorsqu'ils reviendront demander, et cela peut être long s'ils ont mémorisé l'ancienne valeur. Ce RFC propose une autre approche, où les données DNS sont poussées vers les clients au lieu d'attendre qu'ils tirent.

Qu'est-ce qui fait que des données DNS changent ? Cela peut être l'administrateur système qui a changé la zone et rechargé le serveur faisant autorité. Ou bien il y a pu y avoir mise à jour dynamique (RFC 2136). Ou encore d'autres mécanismes. Dans tous les cas, certains clients DNS (par exemple pour la découverte de services du RFC 6763) aimeraient bien être prévenus tout de suite (et voir la nouvelle imprimante du réseau local apparaitre dans la liste). Le DNS est purement pull et ces clients voudraient un peu de push.

Cette idée de protocoles push, où on envoie les données vers les clients au lieu d'attendre qu'il les réclame, est nouvelle pour le DNS mais ancienne dans l'Internet (modèle publish/subscribe ou design pattern Observateur). Parmi les protocoles IETF, XMPP peut fonctionner ainsi (cf. XEP0060).

Il y a quand même un peu de push dans une variante du DNS, mDNS (RFC 6762, section 5.2), où les changements peuvent être poussés vers une adresse IP multicast. Mais des protocoles comme la découverte de services du RFC 6763 peuvent aussi fonctionner sans multicast et cette solution ne leur convient donc pas. Il existait une solution non-standard, LLQ (Long-Lived Queries), décrite dans le RFC 8764 et mise en œuvre dans les produits Apple (cf. RFC 6281). Utilisant UDP, elle ne convient guère au DNS moderne.

Il existe aujourd'hui un mécanisme plus pratique pour déployer des fonctions comme le push : DSO (DNS Stateful Operations, RFC 8490), qui repose sur des connexions de longue durée, sur TCP (et TLS pour la sécurité). La solution push est donc bâtie sur DSO, et il est donc bon d'avoir lu le RFC 8490 avant celui-ci.

La section 3 de notre RFC présente le protocole DNS push. Un client s'abonne à un service de notification et, une fois abonné, il reçoit les nouveautés. Quand il n'a plus besoin des données, le client se déconnecte. L'abonnement est valable pour un certain couple {nom de domaine, type de données}. Client et serveur utilisent le mécanisme DSO du RFC 8490. Comment le client trouve-t-il le serveur ? Ce n'est pas forcément un des serveurs listés comme faisant autorité pour la zone. Il peut être trouvé en demandant à son résolveur normal (s'il accepte DSO, le client peut tenter sa chance) dans le DNS, puis, si ça ne marche pas, via une requête SRV pour le nom _dns-push-tls._tcp.LA-ZONE (cf. section 6, et son enregistrement à l'IANA). Rappelez-vous que, si un serveur DNS accepte DSO mais pas DNS push, il répondra avec un code de retour DNS DSOTYPENI (RFC 8490, section 5.1.1).

Pour éviter de trop charger le serveur, le client ne doit s'abonner que s'il a une bonne raison, par exemple parce qu'une fenêtre de sélection d'une imprimante est ouverte, et qu'il veut la rafraichir en permanence. Lorsque le client va s'endormir ou estomper son écran pour économiser sa batterie, il devrait se désabonner d'abord. En tout cas, le mécanisme DNS push ne devrait pas être utilisé 24x7, ce n'est pas son but. (Et c'est inutile, le mécanisme est suffisamment rapide pour pouvoir être invoqué seulement quand on en a besoin.)

De toute façon, le serveur n'est pas obligé d'accepter tous les clients qui se présentent. Il peut rejeter les abonnements s'il manque de ressources (section 4 du RFC).

Comment est-ce que le client demande du DNS push ? En s'abonnant, une fois la session DSO établie. Il envoie une requête de type DSO SUBSCRIBE (la syntaxe des TLV DSO est dans le RFC 8490, section 5.4.4). Dans les données de la requête se trouvent le nom de domaine et le type de données qui intéressent le client. Le serveur répond alors NOERROR (ou bien un code DNS d'erreur s'il y a un problème, par exemple REFUSED si le serveur ne veut pas) et envoie une réponse de type SUBSCRIBE (même type que la requête, c'est le bit QR de l'en-tête DNS qui permet de différencier requête et réponse). Il est parfaitement légitime pour un client de s'abonner à un nom de domaine qui n'existe pas encore, et le serveur ne doit donc jamais répondre NXDOMAIN.

Une fois l'abonnement accepté, le client attend tranquillement et, lorsqu'un changement survient, le serveur envoie des messages de type DSO PUSH (code 0x0041). Les données contenues dans ce message sont formatées comme les messages DNS habituels, avec une exception : un TTL valant 0xFFFFFFFF signifie que l'ensemble d'enregistrements concerné a été supprimé.

À la fin, quand le client n'est plus intéressé, il envoie un message DSO UNSUBSCRIBE (code 0x0042). Encore plus radical, le client peut mettre fin à la session DSO, annulant ainsi tous ses abonnements.

Et la sécurité de ce DNS push (section 7 du RFC) ? DNS push impose l'utilisation de TLS (donc on a du DSO sur TLS sur TCP). Le client doit authentifier le serveur selon le profil strict du RFC 8310. Ensuite, DNSSEC est recommandé pour la découverte du serveur DNS push, lorsqu'on utilise les requêtes SRV, puis DANE pour vérifier le serveur auquel on se connecte (RFC 7673).

Ensuite, DNS push permet d'utiliser les données précoces du RFC 8446 (section 2.3), ce qui permet de diminuer la latence. Mais elles posent quelques problèmes de sécurité : plus de confidentialité persistante, et risque de duplication des messages. D'autre part, si on utilise la reprise de session du RFC 8446 (section 2.2), il faut noter que, si elle permet de ne pas recommencer toute la session TLS, en revanche, elle ne garde pas les abonnements DNS push, que le client devra donc renouveler.

Désolé, mais je ne connais pas encore de mise en œuvre de ce RFC, à part dans le monde Apple.


Téléchargez le RFC 8765


L'article seul

Risques pour la vie privée liés aux personnes proches

Première rédaction de cet article le 22 juin 2020


De nombreux articles ont été écrits sur la vie privée, et sur sa défense dans le monde numérique. Beaucoup de techniques ont été développées pour faire face aux menaces contre la vie privée, notamment autour du chiffrement. Mais ces techniques, quoique indispensables pour vous protéger d'un attaquant extérieur à votre entourage, ne sont pas forcément efficaces face à un proche. Or, les attaques contre la vie privée peuvent parfaitement être le fait de personnes proches, par exemple dans le cas d'un espionnage d'une épouse par un mari jaloux. Dans un article en anglais publié dans le Journal of Cybersecurity, Karen Levy et Bruce Schneier argumentent qu'il est urgent de traiter le cas des attaquants proches.

Un attaquant proche, cela peut être un ou une conjoint·e, les parents (ou les enfants !), un ou une colocataire. Beaucoup de mesures de sécurité sont fondées sur des suppositions sur l'attaquant, suppositions qui ne sont plus vraies dans le cas d'attaquants proches. Un exemple typique est celui des questions de sécurité « quel était le nom de jeune fille de votre mère », questions auxquelles un attaquant proche peut facilement répondre. Or, alors que la littérature technique et scientifique sur la sécurité informatique est pleine d'articles sur les attaquants, leurs motivations, leurs capacités, les meilleurs moyens de s'en protéger, il y a assez peu de publications sur la classe des attaquants proches (intimate threats). Mes lecteurs et lectrices orientés vers la technique peuvent se demander en quoi ces attaques par des proches sont si spéciales et si différentes des attaques plus connues. Patience, vous allez avoir des exemples.

Ces attaques par des proches sont difficiles à quantifier, mais semblent fréquentes : dans un sondage, 31 % des personnes interrogées ont admis avoir fouillé dans un ordiphone sans autorisation. (La grande majorité des exemples cités dans l'articles concernent les États-Unis, mais il n'y a pas de raison de penser que cela soit très différent ailleurs.) Parmi les gens hébergés dans des abris pour victimes de violences conjugales, les trois quarts ont été victimes de surveillance exercée par leur agresseur via des outils numériques. Et les attaques contre la vie privée sont souvent le préalable à des attaques plus dramatiques, par exemple des féminicides.

L'article classe dans les attaques de proches la surveillance exercée par les parents sur leurs enfants mineurs. Même si elle est bien intentionnée, elle n'est pas forcément une bonne idée, et elle contribue à banaliser la surveillance.

D'abord, les auteurs notent bien que la surveillance est inévitable dans une relation entre personnes proches. Quand on vit dans le même appartement, on sait quand l'autre rentre et sort, par exemple, une information typiquement considérée comme privée. On entend l'autre ou les autres parler au téléphone, on connait ses problèmes de santé, dans un couple, on a souvent un compte joint, on partage souvent le même PC, sans séparation entre plusieurs comptes sur la machine, etc (l'article donne plusieurs références d'études concernant le niveau de partage dans les couples). On pourrait en déduire qu'il n'y a pas de vie privée quand on vit ensemble mais ce n'est évidemment pas vrai. On ne veut pas que son conjoint, son colocataire, ou ses amis savent absolument tout de vous. Et c'est évidemment encore plus vrai si on a, par exemple, un conjoint violent. Mais le problème est compliqué : le partage d'informations n'est pas un mal en soi, et le niveau de partage dépend de goûts personnels et de normes sociales, tous les deux très variables. Et il peut être vu comme une preuve de confiance (« si on s'aime, on ne dissimule pas son mot de passe »).

Parfois, la question même de savoir si l'accès aux données des autres est légitime ou pas est compliquée. S'il n'y a aucun doute qu'on ne doit pas intercepter les messages échangés par un voisin dans le train, la question est moins claire dans le cas familial. Les parents doivent évidemment suivre ce qui arrive aux enfants mineurs (d'autant plus que certains problèmes, par exemple de harcèlement, ne seront pas toujours signalés spontanément). Et même entre adultes, chercher à savoir pourquoi son conjoint ou sa conjointe semble déprimé·e ou anxieu·x·se n'est-il pas souhaitable ? L'approche classique de la sécurité informatique, avec des règles simples (« dans une communication entre Alice et Bob, toute personne qui n'est pas Alice ou Bob est un attaquant »), ne marche pas forcément ici.

Cette difficulté à différencier ce qui est une communication normale et ce qui est de la surveillance est encore plus sérieuse sur le terrain juridique : porter plainte pour de l'espionnage par un proche est difficile, la justice pouvant hésiter à trancher la question de savoir ce qu'il est normal de partager au sein du couple. C'est encore plus compliqué dans les cas où la loi donne explicitement au mari le droit de surveiller sa femme, comme en Arabie saoudite, où l'État gère même un site Web permettant aux hommes de demander à être notifiés des déplacements de leur femme.

Notez que, dans des pays supposés plus civilisés, on voit également des horreurs, comme des applications de surveillance qui disent explicitement dans leur publicité que le but est de fliquer sa femme. Le pire étant sans doute cette société qui vend un matelas connecté permettant de détecter les mouvements suspects dans le lit, en votre absence (mais l'article contient d'autres exemples affreux ; aux États-Unis, les sociétés commerciales n'hésitent pas à faire ouvertement de la publicité pour des usages amoraux ; en Europe, on est plus hypocrites). Même quand la publicité ne dit pas explicitement que le but est de surveiller, beaucoup des gadgets connectés permettent de le faire facilement, et sont souvent utilisés en ce sens.

Un cas bien plus compliqué que celui du macho fliquant sa femme est celui, déjà mentionné, des parents surveillant leurs enfants. « Surveillance » n'est pas forcément un terme négatif, ici. Évidemment que les parents doivent surveiller leurs enfants mineurs, pour éviter qu'ils ne se mettent en danger, ou mettent en danger les autres. Mais le marketing exagère les dangers, pour vendre du matériel et des applications de surveillance. Cela va jusqu'à des bracelets connectés, comme ceux imposés aux prisonniers. (L'URL donné dans l'article ne marche plus, quoique la société soit toujours là, peut-être a-t-elle eu honte de son produit.) Dans le cas particulier des États-Unis, notez qu'il existe une énorme pression sociale contre tout ce qui apparait comme une négligence par les parents dans ce domaine. Policiers et même simple voisins se sentent autorisés à harceler les parents qui laissent ne serait-ce qu'un tout petit peu de liberté à leurs enfants. D'où le mouvement Free-range, qui plaide pour qu'on desserre la surveillance des enfants. Notez que ce soupçon contre les parents, et cette pression pour qu'ils resserrent la vis, est surtout dirigée contre les parents des classes populaires.

Quant à l'activité en ligne, aux États-Unis, la surveillance de l'activité des enfants par les parents est très répandue. (Et les parents qui ne le font pas ne sont pas forcément motivés par le désir de laisser de la liberté à leurs enfants, ils peuvent simplement être incompétents techniquement.) Le but n'est d'ailleurs pas uniquement d'assurer la sécurité de l'enfant, au moins une application prévient les parents quand… l'enfant utilise des gros mots en ligne.

L'article note aussi que le problème peut être inverse : dans les familles où la personne la plus à l'aise avec les outils numériques est un des enfants, les enfants peuvent violer la vie privée de leurs parents, et accéder à de l'information personnelle. Même la biométrie ne les arrête pas : comme les enfants ressemblent à leurs parents, ils peuvent parfois tromper la reconnaissance faciale.

Parmi les attaquants proches possibles, l'article note aussi le cas des personnes âgées. Comme pour le cas des enfants, une certaine surveillance peut être bien intentionnée. (Ce qui ne veut pas dire acceptable : les personnes âgées ne sont pas des mineures.) Le problème est que les visions de la personne âgée et de celle qui décide pour elle peuvent diverger, comme dans ce sondage du journal The gerontologist, cité dans l'article, où les surveillés avaient systématiquement une moins bonne opinion de la surveillance que les surveillants.

Enfin, parmi les personnes proches qui peuvent poser des problèmes en matière de vie privée, il y a les amis qui, sans partager autant de choses avec vous qu'un conjoint ou un ascendant, connaissent quand même pas mal de choses. Le problème est particulièrement net pour les jeunes, où les relations d'amitié peuvent être de courte durée. Les secrets confiés pendant la période d'amitié peuvent être dangereux ensuite.

Quels sont les points communs aux attaques contre la vie privée menées par des personnes proches, points qui méritent d'être pris en considération dans la recherche de solutions de protection ? D'abord, les auteurs notent que les attaquants ne sont pas toujours rationnels. Dans une attaque traditionnelle, le défenseur compte sur la rationalité de l'attaquant. Si celui-ci vise un gain financier, il ne dépensera pas d'avantage d'argent pour l'attaque que celle-ci lui aurait rapporté. Ce calcul devient faux dans le cas d'atteintes à la vie privée menées par des personnes proches, qui peuvent être motivées par des émotions irrationnelles comme la jalousie. L'un des auteurs se souvient d'avoir, enfant, occupé une journée d'oisiveté à essayer les 10 000 combinaisons possibles d'un cadenas, sans espoir d'un gain particulier, juste parce qu'il s'ennuyait. Un cambrioleur classique n'aurait pas fait cela.

Ensuite, les attaquants proches habitent souvent dans la même maison que les victimes. Cette coprésence complique sérieusement les questions de sécurité informatique où, souvent, le concepteur des solutions suppose que les différentes parties en cause sont physiquement séparées. Par exemple, regarder par dessus l'épaule pour apprendre un mot de passe est bien plus facile quand on vit ensemble. Même chose pour l'installation d'un logiciel malveillant sur l'ordinateur ou l'ordiphone de sa cible. Ou encore les systèmes d'exploitation d'ordiphone qui affichent tout ou partie d'un message entrant, même quand le téléphone est verrouillé. Un exemple plus amusant est celui de cette femme jalouse qui avait déverrouillé l'ordiphone de son mari en profitant d'une sieste pour placer son doigt sur le lecteur d'empreintes digitales.

Moins amusant, mais hélas fréquent dans le cas d'attaques par un proche, le risque de menaces ou de violences physiques. Le meilleur mot de passe du monde ne sert à rien si un mari violent menace de tabasser sa femme pour avoir accès à son ordinateur. Ce risque de pression physique est rarement pris en compte dans les analyses de sécurité.

Dans les analyses de sécurité classiques, on suppose que l'attaquant est un étranger complet, qui n'a pas de pouvoir particulier sur la victime. Dans les cas des attaques par les proches, ce n'est plus le cas : même sans menace physique explicite, l'attaquant peut exercer un certain pouvoir, par exemple dans les cas où la femme est (légalement, ou de facto) soumise au mari. Cette autorité (qui peut être en place pour d'excellentes raisons, cf. l'autorité des parents sur les enfants) complique encore les choses. Il y a également une « autorité implicite » : dans le foyer, il y a en général une personne qui pilote le système informatique et qui, via ses compétences techniques et sa mainmise sur ledit système, a un pouvoir supérieur. Et cette autorité implicite est souvent genrée : dans le couple, c'est souvent l'homme qui est l'administrateur système.

Enfin, les proches connaissent évidemment beaucoup de choses sur vous, ce qui est normal, mais peut rendre certaines attaques plus faciles.

Bon, ce n'est pas tout de décrire le problème. Et les solutions ? Évidemment, il n'est pas question d'arrêter de vivre en couple, ou d'avoir des amis, de même qu'on ne cesse pas d'avoir des relations sexuelles parce que les MST existent. La première étape est que les concepteurs de systèmes de sécurité devraient reconnaitre le problème des attaques par les proches, problème qui semble sous-estimé aujourd'hui. (J'ai écrit « les concepteurs », comme s'ils étaient tous des hommes, mais ce n'est pas parce que je ne connais pas l'écriture inclusive. L'auteure et l'auteur de l'article font remarquer que les victimes des attaques par les proches sont plus souvent des femmes, alors que les concepteurs des systèmes de sécurité sont plus souvent des hommes, et que cela peut expliquer le retard dans la prise en compte de ces attaques par les proches.)

Déjà, il n'y a pas que des solutions techniques. Il est par exemple anormal que les entreprises qui vendent des solutions de harcèlement restent impunies. La justice devrait les poursuivre, les antivirus devraient les détecter et les bloquer. Pour les systèmes à usages multiples, et qui ne sont donc pas de purs systèmes d'espionnage, c'est plus compliqué, mais l'article fournit plusieurs pistes. (L'article ne mentionne pas une autre piste de solution, celle de changements sociaux, par exemple de changement des relations entre hommes et femmes, avec moins d'indulgence pour la violence conjugale. Ces changements sont également une approche importante.)

Déjà, comme indiqué plus haut, il est temps de reconnaitre que le problème existe, et aussi d'admettre qu'il n'a pas de solution simple (personne ne propose une étanchéité complète dans les relations personnelles).

Plus concrètement, il faut que les concepteurs de systèmes informatiques cessent de considérer que l'attaquant est forcément lointain et fassent, entre autres, attention à ce qu'un système informatique affiche : l'attaquant peut être en train de regarder. C'est bien pour cela qu'on remplace les caractères d'un mot de passe par des puces, mais il faut pousser le raisonnement plus loin par exemple en se méfiant des notifications spontanées (« Vous avez reçu un message de Paul » « C'est qui, ce Paul qui t'écrit ? »). D'autre part, certaines indications visuelles peuvent poser problème. Firefox a un mode « navigation privée » (en général très mal compris et dont il y a beaucoup à dire mais ce n'est pas le sujet) et, au début, il était signalé par une barre violette très visible. Cette indication pouvait facilement être vue et attirer la suspicion (« pourquoi tu es en navigation privée ? Tu ne me fais pas confiance ? Tu as quelque chose à cacher ? ») Elle est depuis devenue plus discrète.

Ce cas contre-intuitif se rencontre également avec certaines options de sécurité bien intentionnées mais qui préviennent l'attaquant potentiel qu'on se méfie de lui. Par exemple, iOS affiche explicitement « Unetelle a cessé de partager sa localisation physique avec vous », ce qui est certainement un bon moyen de provoquer des réactions agressives chez un conjoint jaloux. Les auteurs de l'article estiment qu'il serait préférable de pouvoir « faire semblant », en évitant de montrer un téléphone vide ou un « vous n'avez pas l'autorisation de voir ces messages », qui risque au contraire de susciter des suspicions.

Les options sélectionnées par défaut sont toujours une question cruciale en informatique, car beaucoup d'utilisateurs ne les changent pas. Ils ne savent pas comment les changer, ou n'osent même pas imaginer que cela soit possible. Mais cette importance des choix par défaut est encore plus vraie dans le cas des attaques par les proches, car une fois que le mal est fait, il peut être difficile à rattraper (je ne vous donne pas l'URL vers l'article de TechCrunch en raison de la scandaleuse interface d'acceptation du fliquage du groupe Verizon Media/Oath ; c'est d'ailleurs intéressant de voir un média qui donne des leçons aux autres en matière de vie privée se comporter ainsi ; bref, vous avez l'URL dans l'article).

Autre problème lié aux attaques par les proches : les relations évoluent. À un moment, tout va bien, on se fait une confiance totale et aveugle, puis les choses changent et on doit commencer à prendre des précautions. Il est donc important que les systèmes informatiques prennent en compte ce caractère dynamique. Un exemple ? Il faudrait que le système vous rappelle de temps en temps vos réglages et vous demande s'ils sont toujours d'actualité (« Machin est autorisé à voir vos messages privés. Souhaitez-vous continuer ? »)

Dernier point sur les pistes de solutions, mais très important : arrêter de considérer que le foyer est forcément une unité où tout le monde partage tout. L'acheteur d'un produit n'est pas forcément son seul utilisateur (même s'il est la seule personne qui compte, pour les entreprises du numérique) et il est important de permettre que les utilisateurs aient chacun leur « espace ». Si Netflix permet plusieurs profils pour un compte, ils ne bénéficient d'aucune vie privée, chacun peut voir ce que les autres ont regardé. (YouTube TV est mieux fait de ce point de vue.) Idem avec les machines partagées : si vous avez un iPhone à vous, et qu'il y a un iPad partagé dans la maison, la synchronisation des données risque de montrer à tout utilisateur de l'iPad ce qu'a reçu l'iPhone.

Au minimum, les accès des autres personnes de la maison à vos données ne devraient pas être discrets mais au contraire, il est important que chacun soit prévenu. Dans le monde physique, la surveillance est à la fois très commune (comme je l'avais signalé au début, les personnes qui habitent avec vous savent forcément plein de choses sur vous, et ce n'est pas un problème) et très visible. Tout le monde, sans être un expert en sécurité, sait ce que les proches savent de nous. Le monde numérique est différent : beaucoup de personnes ne se rendent pas compte de ce que ces systèmes informatiques permettent de connaitre, d'autant plus que la littératie numérique est très loin d'être équitablement partagée (par exemple entre hommes et femmes). Une fois n'est pas commune, je vais dire du bien de Facebook : leur système interne permet à des collègues d'accéder à des informations sur vous, mais vous en êtes prévenu·e, par une alerte spirituellement nommée Sauron.

En conclusion, les auteurs de l'article (en anglais) nous préviennent que le problème va malheureusement sans doute s'aggraver dans le futur, avec la prolifération de gadgets connectés. Quelques efforts de protection de la vie privée sont faits, mais pas encore intégrés dans une vision globale de ce risque d'attaque par les proches.

Pour des conseils pratiques dans le cas du couple, je vous recommande l'article d'Éric, « Chacun ses comptes ».


L'article seul

RFC 8806: Running a Root Server Local to a Resolver

Date de publication du RFC : Juin 2020
Auteur(s) du RFC : W. Kumari (Google), P. Hoffman (ICANN)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 19 juin 2020


Toute résolution DNS commence par la racine (de l'arbre des noms de domaine). Bien sûr, la mémorisation (la mise en cache) des réponses fait qu'on n'a pas besoin tout le temps de contacter un serveur racine. Mais c'est quand même fréquent et les performances de la racine sont donc cruciales. L'idée documentée dans ce RFC est donc d'avoir en local un serveur esclave de la racine, copiant celle-ci et permettant donc de répondre localement aux requêtes. Ce RFC remplace le premier RFC qui avait documenté l'idée, le RFC 7706, avec des changements significatifs, notamment vers davantage de liberté (le précédent RFC restreignait sérieusement les possibilités).

Le problème est particulièrement important pour les noms qui n'existent pas. Si les TLD existants comme .com ou .fr vont vite se retrouver dans la mémoire (le cache) du résolveur DNS, les fautes de frappe ou autres cas où un TLD n'existe pas vont nécessiter la plupart du temps un aller-retour jusqu'au serveur racine le plus proche. Les réponses négatives seront également mémorisées mais 1) il y a davantage de noms non existants que de noms existants 2) le TTL est plus court (actuellement deux fois plus court). Ces noms non existants représentent ainsi la majorité du trafic de la racine.

Bien qu'il existe aujourd'hui des centaines de sites dans le monde où se trouve une instance d'un serveur racine, ce nombre reste faible par rapport au nombre total de réseaux connectés à l'Internet. Dans certains endroits de la planète, le serveur racine le plus proche est assez lointain. Voici les RTT en millisecondes avec les serveurs racine observés depuis un réseau tunisien (notez les deux serveurs qui répondent bien plus vite que les autres, car ils ont une instance à Tunis) :

% check-soa -4 -i .
a.root-servers.net.
	198.41.0.4: OK: 2015112501 (54 ms)
b.root-servers.net.
	192.228.79.201: OK: 2015112501 (236 ms)
c.root-servers.net.
	192.33.4.12: OK: 2015112501 (62 ms)
d.root-servers.net.
	199.7.91.13: OK: 2015112501 (23 ms)
e.root-servers.net.
	192.203.230.10: OK: 2015112501 (18 ms)
f.root-servers.net.
	192.5.5.241: OK: 2015112501 (69 ms)
g.root-servers.net.
	192.112.36.4: OK: 2015112501 (62 ms)
h.root-servers.net.
	128.63.2.53: OK: 2015112501 (153 ms)
i.root-servers.net.
	192.36.148.17: OK: 2015112501 (67 ms)
j.root-servers.net.
	192.58.128.30: OK: 2015112501 (55 ms)
k.root-servers.net.
	193.0.14.129: OK: 2015112501 (72 ms)
l.root-servers.net.
	199.7.83.42: ERROR: Timeout
m.root-servers.net.
	202.12.27.33: OK: 2015112501 (79 ms)
    

Ces délais peuvent sembler courts mais ils ne forment qu'une partie du travail de résolution, il est donc légitime de vouloir les réduire encore.

En outre, ces requêtes à la racine peuvent être observées, que ce soit par les opérateurs de serveurs racine, ou par des tiers sur le projet, ce qui n'est pas forcément souhaitable, question vie privée (cf. RFC 7626).

Donc, l'idée de base de ce RFC est de :

  • Mettre un serveur esclave de la racine sur sa machine, configuré pour ne répondre qu'aux requêtes de cette machine,
  • Configurer le résolveur pour interroger d'abord ce serveur.

Cette idée est documentée dans ce RFC mais n'est pas encouragée (c'est un très vieux débat, dont j'avais déjà parlé). En effet, cela ajoute un composant à la résolution (le serveur local faisant autorité pour la racine), composant peu ou pas géré et qui peut défaillir, entrainant ainsi des problèmes graves et difficiles à déboguer. Mais pourquoi documenter une idée qui n'est pas une bonne idée ? Parce que des gens le font déjà et qu'il vaut mieux documenter cette pratique, et en limiter les plus mauvais effets. C'est pour cela, par exemple, que notre RFC demande que le serveur racine local ne réponde qu'à la même machine, pour limiter les conséquences d'une éventuelle défaillance à une seule machine.

Pas découragé ? Vous voulez encore le faire ? Alors, les détails pratiques. D'abord (section 2 du RFC), les pré-requis. DNSSEC est indispensable (pour éviter de se faire refiler un faux fichier de zone par de faux serveurs racine). Ensuite (section 3), vous mettez un serveur faisant autorité (par exemple NSD ou Knot) qui écoute sur une des adresses locales (en 127.0.0.0/8, IPv6 est moins pratique car il ne fournit paradoxalement qu'une seule adresse locale à la machine) et qui est esclave des serveurs racine. À noter que votre serveur, n'étant pas connu des serveurs racine, ne recevra pas les notifications (RFC 1996) et sera donc parfois un peu en retard sur la vraie racine (ce qui n'est pas très grave, elle bouge peu).

Il est important de lister plusieurs serveurs maîtres dans sa configuration. En effet, si la mise à jour de la racine dans votre serveur esclave échoue, ce sera catastrophique (signatures DNSSEC expirées, etc) et cette configuration locale, contrairement à la « vraie » racine, n'a aucune redondance. (Une autre raison pour laquelle ce n'est pas une idée géniale.) Quels serveurs maîtres indiquer ? Certains serveurs racine permettent le transfert de zone (RFC 5936) mais ce n'est jamais officiel, ils peuvent cesser à tout moment (l'annexe A du RFC donne une liste et discute de ce choix). Une raison de plus de se méfier.

Il est donc important d'avoir un mécanisme de supervision, pour être prévenu si quelque chose échoue. On peut par exemple interroger le numéro de série dans l'enregistrement SOA de la racine et vérifier qu'il change.

Ensuite, une fois ce serveur faisant autorité configuré, il ne reste qu'à indiquer à un résolveur (comme Unbound) de l'utiliser (toujours section 3 du RFC).

Voici un exemple testé. J'ai choisi NSD et Unbound. Le RFC, dans son annexe B, donne plusieurs autres exemples, tous utilisant le même serveur comme résolveur et comme serveur faisant autorité. C'est en général une mauvaise idée mais, pour le cas particulier de ce RFC, cela peut se défendre.

D'abord, la configuration de NSD (notez la longue liste de maîtres, pour maximiser les chances que l'un d'eux fonctionne ; notez aussi l'adresse IP choisie, 127.12.12.12) :

# RFC 8806
server:
       ip-address: 127.12.12.12
zone:
       name: "."
       request-xfr: 199.9.14.201 NOKEY # b.root-servers.net
       request-xfr: 192.33.4.12 NOKEY    # c.root-servers.net
       request-xfr: 192.5.5.241 NOKEY    # f.root-servers.net
       request-xfr: 192.112.36.4 NOKEY   # g.root-servers.net
       request-xfr: 193.0.14.129 NOKEY   # k.root-servers.net
       request-xfr: 192.0.47.132 NOKEY   # xfr.cjr.dns.icann.org
       request-xfr: 192.0.32.132 NOKEY   # xfr.lax.dns.icann.org
       request-xfr: 2001:500:200::b NOKEY # b.root-servers.net
       request-xfr: 2001:500:2f::f NOKEY # f.root-servers.net
       request-xfr: 2001:7fd::1 NOKEY    # k.root-servers.net
       request-xfr: 2620:0:2830:202::132 NOKEY  # xfr.cjr.dns.icann.org
       request-xfr: 2620:0:2d0:202::132 NOKEY  # xfr.lax.dns.icann.org  

Le démarrage de NSD (notez qu'il faut patienter un peu la première fois, le temps que le premier transfert de zone se passe) :

[2020-05-04 17:51:05.496] nsd[25649]: notice: nsd starting (NSD 4.3.1)
[2020-05-04 17:51:05.496] nsd[25649]: notice: listen on ip-address 127.12.12.12@53 (udp) with server(s): *
[2020-05-04 17:51:05.496] nsd[25649]: notice: listen on ip-address 127.12.12.12@53 (tcp) with server(s): *
[2020-05-04 17:51:05.600] nsd[25650]: notice: nsd started (NSD 4.3.1), pid 25649
[2020-05-04 17:51:08.380] nsd[25649]: info: zone . serial 0 is updated to 2020050400

C'est bon, on a transféré la zone. Testons (notez le bit AA - Authoritative Answer - dans la réponse) :


% dig  @127.12.12.12 SOA . 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24290
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 27
...
;; ANSWER SECTION:
.			86400	IN	SOA	a.root-servers.net. nstld.verisign-grs.com. 2020050400 1800 900 604800 86400
...
;; Query time: 3 msec
;; SERVER: 127.12.12.12#53(127.12.12.12)
;; WHEN: Mon May 04 17:51:51 CEST 2020
;; MSG SIZE  rcvd: 868

C'est bon.

Maintenant, la configuration d'Unbound (différente de celle du RFC, qui utilise Unbound à la fois comme résolveur et comme serveur faisant autorité) :

server:
    # RFC 8806
    do-not-query-localhost: no
    
# Requires a slave auth. running (normally, nsd)
stub-zone:
       name: "."
       stub-prime: no
       stub-addr: 127.12.12.12

(John Shaft me fait remarquer que la directive stub-first devrait permettre d'utiliser le mécanisme de résolution classique si la requête échoue, ce qui apporterait une petite sécurité en cas de panne du serveur local faisant autorité pour la racine.) Et le test :


% dig www.cnam.fr
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30881
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; ANSWER SECTION:
www.cnam.fr.		86400	IN	CNAME	kaurip.cnam.fr.
kaurip.cnam.fr.		3600	IN	A	163.173.128.40
...

Ça a marché. Avec tcpdump, on voit le trafic (faible, en raison du cache) vers le serveur racine local :

18:01:09.865224 IP 127.0.0.1.54939 > 127.12.12.12.53: 55598% [1au] A? tn. (31)
18:01:09.865359 IP 127.12.12.12.53 > 127.0.0.1.54939: 55598- 0/8/13 (768)
  

Pour BIND, et d'autres logiciels, consultez l'annexe B du RFC.

À noter qu'il existe un brevet futile (comme tous les brevets...) de Verisign sur cette technique : déclaration #2539 à l'IETF. Il portait sur l'ancien RFC mais il est peut-être aussi valable (ou aussi ridicule) avec le nouveau.

La section 1.1 de notre RFC documente les changements depuis le RFC 7606. Le principal est que le serveur racine local n'a plus l'obligation d'être sur une adresse IP locale à la machine (comme ::1). Les autres changements, qui reflètent l'expérience pratique avec cette technique, après plus de quatre ans écoulés, vont en général dans le sens de la « libéralisation ». Il y a moins de restrictions que dans le RFC 7706.


Téléchargez le RFC 8806


L'article seul

RFC 8793: Information-Centric Networking (ICN): Content-Centric Networking (CCNx) and Named Data Networking (NDN) Terminology

Date de publication du RFC : Juin 2020
Auteur(s) du RFC : B. Wissingh (TNO), C. Wood (University of California Irvine), A. Afanasyev (Florida International University), L. Zhang (UCLA), D. Oran (Network Systems Research & Design, C. Tschudin (University of Basel)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF icnrg
Première rédaction de cet article le 18 juin 2020


Le terme d'ICN (Information-Centric Networking) désigne un paradigme de communication où tout est du contenu : plus d'adresses IP ou de noms de domaine, on désigne chaque ressource par un nom. Il en existe plusieurs déclinaisons comme le NDN (Named Data Networking) ou le CCNx (Content-Centric Networking). Ce nouveau RFC décrit le vocabulaire de ces deux déclinaisons.

La section 1 du RFC résume les concepts essentiels de l'ICN. Il s'agit d'une architecture de réseaux où le composant de base est un contenu auquel on veut accéder. Pour récupérer, mettons, une image de chaton, on donnerait le nom de cette image et elle arriverait sur votre écran. Dans cette architecture, la notion de machine disparait, il n'y a que du contenu. En théorie, cela permettra de faire du multicast, et de la mémorisation (caching) de contenu par les éléments du réseau, transformant chaque routeur en serveur miroir.

Le concept se décline ensuite en plusieurs architectures, utilisant des terminologies très variables, et peu normalisées. Toutes ne sont pas couvertes dans ce RFC, qui se focalise sur les sujets sur lesquels l'IRTF a le plus travaillé, NDN et CCNx (RFC 8569.)

La section 2 de notre RFC contient une description générale de l'ICN. Il y a un demandeur (requestor), également appelé consommateur, qui voudrait du contenu, mettons une photo de Scarlett Johansson. Il va manifester un intérêt (Interest) qui est un message demandant du contenu. Un ou plusieurs nœuds du réseau (l'équivalent des routeurs, mais la principale différence est qu'ils peuvent stocker du contenu) vont alors faire suivre cet intérêt jusqu'à une machine qui se trouve avoir le contenu en question, soit parce qu'elle en est la source (le producteur), soit parce qu'elle en a une copie. La machine répondra alors avec des données (Data) qui seront relayées en sens inverse, jusqu'au demandeur. Il y a donc deux types de messages, qui pourraient s'appeler requête et réponse mais que, dans le monde ICN, on nomme Intérêt et Données. Le message d'Intérêt contient le nom du contenu convoité. Chaque protocole particulier d'ICN a une façon différente de construire ces noms. Comme le message de Données arrive via plusieurs relais, l'authentification de ce message ne peut pas être déduit de sa source. Il faut qu'il soit signé, ou bien que le nom soit auto-certificateur, par exemple parce que le nom est un condensat du contenu. (Attention, l'authentification n'est pas la même chose que la confiance. Si un message est signé de la porte-parole du gouvernement, cela prouve qu'il vient bien d'elle, pas qu'elle dit la vérité. Voir la section 6 du RFC.)

Pour faire son travail, le nœud ICN va avoir besoin de trois base de données :

  • La FIB (Forwarding Interest Base), les moyens de joindre les données,
  • La PIT (Pending Interest Table), les requêtes en cours,
  • Le stockage (Content Store), puisque tout nœud ICN peut stocker les données qu'il voit passer, pour les transmettre la fois d'après.

Parfois, les données sont de grande taille. En ICN, on dit qu'on va segmenter ces données en plusieurs messages. Le RFC utilise le terme de paquet pour une unité de données après la segmentation. Ces paquets sont potentiellement plus gros que la MTU et on parle de trame (frame) pour l'unité qui passe sur le réseau, après le découpage du paquet.

Une fois qu'on a ce résumé en tête, on peut passer aux termes utilisés dans l'ICN. C'est la section 3 du RFC, le gros morceau. Je ne vais pas les lister tous ici, je fais un choix arbitraire. Attention, comme il s'agit d'un domaine de recherche, et peu stabilisé, il y a beaucoup de synonymes. On a :

  • ICN (Information-Centric Networking) ; c'est un concept dont le CCNx du RFC 8569 est une des déclinaisons possibles.
  • L'immuabilité est une notion importante en ICN ; si le nom d'un contenu est un condensat du contenu, l'objet est immuable, tout changement serait un nouvel objet, avec un nouveau nom.
  • Le contenu est produit par des producteurs et récupéré par des consommateurs. Il sera relayé par des transmetteurs (forwarders, un peu l'équivalent des routeurs.) Si le transmetteur stocke les données, pour accélérer les accès ultérieurs, on l'appelle une mule. La transmission est dite vers l'amont (upstream) quand il s'agit des Intérêts et vers l'aval (downstream) pour les Données et les rejets (lorsqu'un Intérêt ne correspond à aucune donnée connue).
  • Un transmetteur peut être à état, ce qui signifie qu'il se souvient des Intérêts qu'il a transmis (dans sa PIT), et qu'il utilisera ce souvenir pour transmettre les Données qui seront envoyées en réponse.
  • Un Intérêt peut ne pas être satisfait si on ne trouve aucune Donnée qui lui correspond (zut, pas de photo de Scarlet Johansson). Un rejet (Interest NACK) est alors renvoyé au demandeur. Notez que beaucoup de schémas d'ICN ont des noms hiérarchiques et que, dans ce cas, la correspondance dans la FIB entre un Intérêt et une interface se fait sur le préfixe le plus long.
  • Un des points importants de l'ICN est la possibilité pour les nœuds intermédiaires de mémoriser les données, pour faciliter leur distribution (stockage dans le réseau, ou In-network storage). Cette mémorisation ne se fait en général pas systématiquement mais uniquement quand l'occasion se présente (opportunistic caching). Cela améliore la distribution de contenus très populaires mais cela soulève des gros problèmes de vie privée, puisque tous les nœuds intermédiaires, les transmetteurs, doivent pouvoir voir ce qui vous intéresse. (Une photo de Scarlet Johansson, ça va. mais certains contenus peuvent être plus sensibles.)
  • Comme IP, ICN sépare le routage (construire les bases comme la FIB) et la transmission (envoyer des messages en utilisant ces bases).
  • Un lien est un paquet de données qui contient le nom d'un autre contenu. Une indirection, donc.
  • Et le nom, au fait, concept central de l'ICN ? Il est typiquement hiérarchique (plusieurs composants, parfois également appelés segments, je vous avais prévenu qu'il y avait beaucoup de synonymes) pour faciliter la transmission. Le début d'un nom se nomme un préfixe. Le nom peut indiquer la localisation d'un contenu ou bien peut être sémantique (indiquant le contenu). Dans ICN, on utilise en général le terme d'identificateur (packet ID) pour les identificateurs cryptographiques, calculés par condensation. Si le nom est l'identificateur, on parle de nommage à plat. (Et, évidemment, cela sera plus dur à router, il faudra sans doute une DHT.)
  • L'ICN a une notion de version. Dans le cas de noms hiérarchiques, la version d'un contenu peut être mise dans le nom.
  • Avec ICN, les propriétés de sécurité du contenu ne peuvent pas être garanties par le serveur où on l'a récupéré. Il faut donc une sécurité des données et pas seulement du canal. L'intégrité est vérifiée par la cryptographie, l'authenticité par une signature et la confidentialité par le chiffrement. Tout cela est classique. Plus délicate est la question de la confidentialité des noms, puisqu'elle empêcherait le nœuds intermédiaires de savoir ce qui est demandé, et donc de faire leur travail.

Téléchargez le RFC 8793


L'article seul

RFC 8789: IETF Stream Documents Require IETF Rough Consensus

Date de publication du RFC : Juin 2020
Auteur(s) du RFC : J. M. Halpern (Ericsson), E. K. Rescorla (Mozilla)
Première rédaction de cet article le 18 juin 2020


Un très court RFC pour une décision de clarification : les RFC publiés par l'IETF (qui ne sont pas la totalité des RFC) doivent recueillir l'accord (le consensus) de l'IETF.

Oui, cela parait assez évident, mais ce n'était pas écrit (le RFC 2026 n'était pas clair à ce sujet). Il existe plusieurs voies (streams) pour les RFC et l'une des voies est nommée IETF stream. Pour être ainsi publié, le RFC doit avoir recueilli le fameux consensus approximatif de l'IETF. Les autres voies, comme la voie indépendante, n'ont pas cette obligation.

Notez que cette obligation de consensus approximatif existait pour les RFC sur le chemin des normes mais pas pour ceux pour information ou expérimentaux. La nouvelle règle tient en une phrase : sur la voie IETF, l'IESG doit veiller à ce que tout RFC, même expérimental, recueille un consensus approximatif. Les documents qui ne réunissent pas un tel consensus peuvent toujours être publiées en RFC via d'autres voies comme la voie indépendante (cf. RFC 8730), ou celle de l'IRTF (cf. RFC 7418).

Certaines décisions précédentes (comme celle de l'IESG en 2007) se posaient déjà la question, mais sans interdire de telles publications.

Notez que le RFC ne rappelle pas comment on vérifie ce consensus approximatif. Un des moyens est via un dernier appel lancé sur la liste de diffusion de l'IETF avant l'approbation. (Voici un exemple récent, notez le Stream: IETF dans l'outil de suivi.)


Téléchargez le RFC 8789


L'article seul

Des émojis pour les codes de retour HTTP

Première rédaction de cet article le 13 juin 2020


Une suggestion lue sur Twitter : associer un émoji à chaque code de retour HTTP.

(C'est un article du week-end : n'attendez pas de savantes analyses, c'est plutôt pour la distraction.)

Le protocole HTTP prévoit que les réponses à une requête commencent par un code de retour sur trois chiffres, le premier chiffre identifiant une catégorie (2 = tout va bien, 4 = vous avez fait une erreur, 5 = j'ai fait une erreur, etc). Certains de ces codes sont très célèbres comme 404 pour « ressource non trouvée ». Ils sont normalisés dans le RFC 7231, section 6. Mais ces codes sont un peu arides, d'où la suggestion de francesc d'associer à chaque code HTTP un émoji. Par exemple le 404 pourrait être accompagné de 🤷 (U+1F937 en notation Unicode), un personnage qui lève les mains en signe d'impuissance (l'exemple de francesc est légèrement différent, voyez plus loin).

En partant du tweet original, et en ajoutant les suggestions qui ont fait suite à ce tweet, voici une liste possible. Notez que chaque émoji est un caractère Unicode (et pas une image, contrairement au tweet original) et est aussi un hyperlien vers l'excellent service d'exploration d'Unicode, Uniview. Et si vous voulez la signification de chaque code de retour HTTP, voyez le registre IANA de ces codes (ou, peut-être plus lisible, https://httpstatuses.com/).

  • 100 : 👂
  • 102 : 🖥
  • 200 : 👍 ou bien
  • 201 : 🆕 ou bien 👶
  • 202 : 👌 (il pourrait aussi servir au 200…)
  • 203 : 🤔
  • 204 : 😶 (pas facile de représenter quelque chose qui n'existe pas…)
  • 206 : 🥴
  • 226 : 📲
  • 301 : 👉
  • 302 : 🤏
  • 303 : 👀
  • 400 : 👎
  • 401 : 🔒
  • 402 : 💰
  • 403 : 🚫
  • 404 : 🤷 (si vous regardez avec un logiciel qui gère toutes les possibilités d'Unicode, l'auteur utilisait quatre caractères Unicode combinés pour être sûr que le personnage soit mâle, ce qui donne 🤷‍♂️ ; regardez ce que ça donne sur mon Firefox)
  • 405 : 👮 ou
  • 406 : 🙅
  • 408 :
  • 409 : ou bien 🤼 (si vous regardez avec un logiciel qui gère toutes les possibilités d'Unicode, l'auteur utilise également des caractères combinés, ce qui donne 🤼‍♂️)
  • 410 : 💨 ou bien 🦖
  • 413 : 😵
  • 415 : 🧐
  • 418 : 🍵 ou bien 🫖 (notez que vous ne trouverez pas ce code dans le registre IANA, il a été décrit dans un RFC du premier avril, le RFC 2324 ; d'autre part, si vous ne voyez pas le deuxième émoji, la théière, c'est peut-être car c'est un des rares émojis cités ici qui n'ait été introduit qu'en version 13 d'Unicode, la plus récente)
  • 422 : 🤦
  • 426 : 🦕
  • 429 : 😱 ou 🐇 (le lapin est l'idée que je préfère)
  • 451 : 🔥, 🚔, 👮 ou bien 📛
  • 500 : 💩, 💥, 🥴 ou bien 🤯
  • 503 : 😓 ou 🤬 ou bien 🤯
  • 504 : ou
  • 508 :

Pour vous amuser avec les codes de retour HTTP, il y a aussi des photos de chat et des explications à partir de films tamouls.


L'article seul

Fiche de lecture : Les nouvelles lois de l'amour

Auteur(s) du livre : Marie Bergström
Éditeur : La Découverte
978-2-7071-9894-5
Publié en 2019
Première rédaction de cet article le 8 juin 2020


« Sexualité, couple et rencontres au temps du numérique. » Une part très importante des activités humaines se passe désormais sur l'Internet. C'est donc logiquement également le cas de la drague et de toutes ses variantes. Mais comment se passent exactement les rencontres sur l'Internet, au-delà des discours faciles ? Une sociologue s'est penchée sur la question, a parlé avec utilisateurs et concepteurs de sites de rencontre, a eu accès à la base de données d'un gros site, pour des études quantitatives, et publie. Un livre qui parle d'amour, sous toutes ses formes.

C'est qu'il y a beaucoup d'idées fausses qui circulent sur les rencontres sexuelles et/ou amoureuses effectuées par le truchement d'un site Web. Il n'y aurait plus de couple stable, plus que des rencontres éphémères, celles-ci seraient égalitaires, sans considération de classe sociale, le passage par une entreprise commerciale tuerait tout romantisme, etc.

J'ai découvert ce livre lors des excellentes rencontres « Aux sources du numérique ». Vos pouvez lire l'entretien avec l'auteure fait à cette occasion. asdn-marie-bergstrom.jpg

L'auteure remet les sites de rencontre modernes dans l'histoire (et c'est un des chapitres les plus intéressants du livre). L'action d'intermédiaires dans la formation des couples est ancienne, et leurs arguments sont parfois très stables (cf. la délicieuse mise côte-à-côte d'une publicité du journal d'annonces matrimoniales « Les mariages honnêtes » en 1907 et d'une publicité de Tinder de 2017). On trouvera entre autre dans ce chapitre historique le Minitel rose, qui avait été un des facteurs de décollage de ce succès technico-industriel français, et la source de quelques fortunes, y compris de celle du fondateur d'un gros FAI français. (Et, j'ajoute, la source d'inspiration d'une jolie chanson sur le numérique, Goodbye, Marylou.) Mal vus à l'époque, les « sites de rencontre » sont mieux perçus aujourd'hui. Comme le note l'auteure, un des intérêts des sites de rencontre, est qu'on ne drague pas en public, contrairement aux rencontres sur le lieu de travail ou en boite. C'est particulièrement important pour les femmes, qui sont critiquées si elles expérimentent beaucoup. Les femmes de 18-25 ans sont le groupe qui utilisent le plus ces sites.

Autre étude intéressante, les discussions avec les concepteurs des sites de rencontre. Alors que les agences matrimoniales du passé se vantaient de leurs compétences en matière de rencontres, ceux qui réalisent Meetic et les autres clament bien fort qu'ils sont juste des techniciens, qu'ils mettent les gens en rapport, qu'ils n'essaient pas d'être des « marieurs ». Les créateurs des sites de rencontre nient l'influence du site, de son organisation, de ses algorithmes. On ne sait pas si cette insistance sur la neutralité est une coquetterie d'informaticien (« la technique est neutre ») ou bien un moyen d'éviter de faire des promesses imprudentes (« satisfaction garantie »).

Et l'homogamie ? Est-ce que l'Internet tient sa promesse d'être égalitaire, et d'effacer les barrières ? Est-ce que, grâce aux applications de rencontre, les bergères peuvent enfin épouser des princes ? Malheureusement, non. Bourdieu reste le plus fort. Comme dans les rencontres hors-ligne, l'homogamie reste forte. Si la sélection sur le physique ne doit pas trop se dire, celle sur l'orthographe est assumée par les interlocuteurs de l'auteure, et on sait que l'orthographe est un fort marqueur social. (L'auteure, qui est d'origine suédoise, critique la langue française pour son manque de cohérence entre l'oral et l'écrit. Mais toute langue est difficile quand ce n'est pas sa langue maternelle.) Plus étonnant, cette importance donnée à l'orthographe reste très forte même quand on cherche des rencontres « légères », « sans lendemain ». Il n'y a pas de simple « plan cul ». « Nos goûts sexuels et romantiques sont sociaux. », dit l'auteure. Même si c'est juste pour le sexe, il faut une bonne orthographe. Ce choix contribue d'autant plus à la sélection sociale que le seul canal, au début, est l'écrit : on ne peut pas compenser par son apparence physique.

Autre idée importante du livre : le cliché traditionnel comme quoi les hommes chercheraient du sexe et les femmes un mari n'est pas corroboré par les données. Il y a bien des attentes différentes des hommes et femmes vers 30 ans, où les femmes veulent déjà se mettre en couple, mais les hommes pas encore. Mais, avant et après les visions classiques sont fausses (les femmes jeunes aussi veulent du sexe, les hommes mûrs aussi de la conjugalité).

Et à propos de sexe, est-ce que, sur les sites de rencontre, on ne s'intéresse qu'à la relation sexuelle et pas à la mise en couple stable ? Pas vraiment. Tout juste peut-on observer que les rencontres en ligne deviennent plus vite sexuelles (un peu comme celles en vacances, et sans doute pour les mêmes raisons, « les histoires en ligne ne font pas d'histoires »). Et puis, les deux parties savent dès le début pourquoi ielles sont là : il n'y a pas l'ambiguité qu'il peut y avoir, par exemple lors de rencontres au bureau.

Notez que le livre se limite à l'hétérosexualité, l'auteure notant que les homosexuels ont des pratiques très différentes. Un prochain livre ?


L'article seul

Mon fichier a-t-il été modifié pendant son voyage ?

Première rédaction de cet article le 7 juin 2020


Une très intéressante discussion à l'IETF a lieu en ce moment sur la modification des données lorsqu'elles circulent sur l'Internet : les mécanismes de protection contre ces modifications suffisent-ils ? Ou bien est-ce que nous recevons de temps en temps des données modifiées, sans nous en rendre compte ?

Le problème a été posé par Craig Partridge dans un message récent. Pour le comprendre, il faut partir du fait que, lorsque des données circulent sur l'Internet, les bits n'arrivent pas toujours comme ils sont partis. Contrairement à ce qu'essaie de faire croire le discours commercial sur « le virtuel » ou « le nuage », l'Internet repose sur le monde physique, et sur la physique. Un bit, ce n'est qu'une information stockée dans un dispositif physique. Un rayon cosmique passe, un composant électronique défaille et paf, un zéro devient un ou le contraire. Notez aussi que le problème n'est pas uniquement sur le réseau : les équipements intermédiaires (les routeurs) et terminaux n'ont pas des mémoires parfaites (on n'utilise pas toujours ECC). Dans un monde physique, la perfection n'existe pas : il y aura toujours de la corruption de données. (J'ai déjà parlé de ce problème dans mon article sur le bitsquatting.)

Le problème s'aggrave évidemment avec la taille des données et il est donc plus aigu aujourd'hui. Si vous transférez un film en haute définition (mettons un fichier de 60 Go), et qu'un bit a une probabilité de 10^-12 (une chance sur mille milliards, les réseaux réels sont souvent bien moins fiables) d'être modifié, vous avez une chance - ou plutôt une malchance - sur deux que le fichier arrive corrompu.

Est-ce grave ? Dans le cas de ce film, il est probable que la modidication d'un seul bit ne soit pas détectable par le spectateur. De même que le changement d'un bit dans la phrase précédant celle-ci vous a sans doute échappé (merci à Brian Carpenter pour l'idée), d'autant plus qu'elle affectait un mot assez long pour qu'il reste compréhensible. Mais les couches basses de la communication ne savent pas ce qui est vital ou pas. Elles doivent donc essayer d'assurer une fiabilité, sinon totale (ce serait utopique), du moins raisonnable en pratique.

C'est pour cela que dans la plupart des couches, il y a des sommes de contrôle qui résument les données en une somme : si elle ne correspond pas entre le départ et l'arrivée, les données sont jetées et on recommence. Ethernet a une telle somme de contrôle, et, dans le domaine de l'IETF, TCP (RFC 793, section 3.1) et UDP (RFC 768) l'ont aussi. C'est le même algorithme, la « somme de contrôle de l'Internet », décrit dans le RFC 1071. (IPv4 a aussi une somme de contrôle, supprimée en IPv6 car redondante entre celles de la couche 2 et de la couche 4.) Si un paquet TCP arrive et que la somme de contrôle ne correspond pas, le récepteur n'envoie pas d'accusé de réception, l'émetteur note que le paquet est perdu (ce qui n'est pas faux) et réémet.

Est-ce que ces sommes de contrôle suffisent ? Non. Une somme de contrôle ne peut pas détecter tous les problèmes, notamment parce que Shannon ne veut pas : la somme de contrôle étant plus petite que les données, plusieurs paquets ont la même somme et certains changements dans les bits d'un paquet ne modifieront donc pas la somme de contrôle. (Notez que beaucoup de calculs sur la probabilité de corruption considèrent que les changements des bits sont indépendants, ce qui n'est pas forcément le cas. En général, quand un bit est changé, ses voisins ont une probabilité plus forte de l'être également, parce qu'ils sont dans la même barrette mémoire, ou bien parce qu'ils ont été victimes du même rayon cosmique.)

Bon, donc, l'application peut recevoir des données corrompues bien qu'on apprenne en cours d'informatique que TCP fournit un « canal fiable ». Que va-t-elle faire alors ? Parfois rien, elle accepte béatement les données corrompues. Dans le cas du film cité plus haut, ce n'est pas forcément idiot. Un léger changement d'une image ne se verra pas. Dans d'autres cas, le problème est plus sérieux et certaines applications calculent leur propre somme de contrôle une fois le transfert de données terminé, parfois avec des algorithmes meilleurs que la « somme de contrôle de l'Internet », comme SHA-2. (Les algorithmes de condensation comme SHA-2 fournissent en plus d'autres propriétés de sécurité, mais ils peuvent être utilisés comme de simples sommes de contrôle.) Le problème, dans ce cas, est d'efficacité : si on détecte un problème, il faut tout recommencer et, pour des données de grande taille, cela fait beaucoup. C'est pour cela que certaines applications, comme BitTorrent, ont leur propre découpage des données, comme le fait TCP, pour éviter de devoir retransmettre la totalité d'un fichier. (On peut faire la même chose avec HTTP et ses range requests, cf. RFC 7233 mais toutes les applications ne gèrent pas cela.)

Est-ce que ce problème arrive ? Combien de fois les applications acceptent des fichiers corrompus ? Et, pour les applications qui testent une somme de contrôle applicative, est-ce que la réémission est fréquente ? En fait, on ne le sait pas tellement et c'était le but originel de l'article de Craig Partridge : annoncer un projet de recherche visant à récolter des données sur ce phénomène.

Arrivé à ce stade, mes lectrices et mes lecteurs, qui sont toutes et tous de grands connaisseurs de l'Internet, pensent depuis longtemps « mais, aujourd'hui, toutes les communications sont chiffrées et, dans ce cas, c'est le mécanisme de cryptographie qui détecte la corruption ; au fur et à mesure que le chiffrement s'étend, ce problème de corruption devrait disparaitre ». D'abord, c'est plus compliqué que cela. Certains algorithmes de chiffrement ne détectent pas la corruption et, quand elle a lieu, produisent des données en clair qui sont elle-même corrompues. Le chiffrement intègre a justement pour but de résoudre ce problème, en détectant la corruption avant de perdre son temps à déchiffrer. Il est donc logique que ce chiffrement intègre soit de plus en plus répandu (il est même obligatoire en TLS 1.3, cf. RFC 8446). D'autre part, les protocoles qui utilisent le cryptographie ont souvent leur propre mécanisme de détection de la corruption, au-dessus du protocole de transport mais en dessous de celui d' application. Par contre, ces mécanismes ne sont pas forcément bien intégrés au transport. Ainsi, TLS peut détecter des erreurs que la somme de contrôle de TCP n'a pas vues mais n'a aucun moyen de demander la retransmission, il ne peut qu'avorter la communication (ou bien prévenir l'application). SSH a la même limite (ce qui est logique, tous les deux supposent une couche Transport fiable). Des études semblent indiquer que les gros transferts de fichiers sur TLS ou SSH échouent souvent pour cette raison, et doivent être relancés au niveau applicatif. QUIC, quand sa normalisation sera terminée, devrait améliorer les choses. Bref, le chiffrement aide (et on peut donc espérer qu'il continuera à se répandre) mais n'est pas une solution magique.

Bon, et quelles sont les solutions envisagées ? La faiblesse de la somme de contrôle de l'Internet, qui échoue à détecter un certain nombre d'erreurs, est connue depuis longtemps, et l'augmentation de la quantité de données transférées ne fait qu'aggraver les choses. Une première solution serait de la remplacer par une somme de contrôle plus forte (mettons SHA-256 pour donner une idée, mais MD5 suffirait, il s'agit de se protéger contre des accidents, pas des attaques) mais aussi plus lente à calculer (mais la vitesse des processeurs a augmenté plus vite que celle des réseaux). Un problème amusant est « comment déployer cette nouvelle somme de contrôle » dans l'Internet ossifié et pourri de middleboxes que nous avons aujourd'hui. En théorie, le protocole de transport est de bout en bout et les équipements intermédiaires ne devraient pas poser de problèmes, ils passent juste les paquets sans les comprendre. En pratique, ce n'est pas le cas. Le RFC 1146 fournit un mécanisme de changement de la somme de contrôle standard mais il est certain qu'il n'est pas massivement déployé et, si on essayait aujourd'hui, on peut être sûr que la majorité des middleboxes, intrusives et programmées avec les pieds, réagirait mal. Et UDP ? C'est encore pire, il n'a pas de mécanisme standard pour changer l'algorithme de somme de contrôle (un travail à ce sujet est en cours à l'IETF).

Bref, un remplacement de TCP par QUIC serait peut-être la meilleure solution…

Quelques lectures sur ce sujet, rassemblées par Craig Partridge :


L'article seul

Fiche de lecture : Le bug humain

Auteur(s) du livre : Sébastien Bohler
Éditeur : Robert Laffont
9782221240106
Publié en 2019
Première rédaction de cet article le 1 juin 2020


Dans cet essai, Sébastien Bohler explique et défend une thèse comme quoi une grande partie de nos comportements humains seraient dus à des règles très profondément enfouies dans notre cerveau et qui se résumeraient à « plus de tout, et tout de suite ». Selon lui, changer les choses, par exemple diminuer notre empreinte carbone, nécessite de prendre conscience de ces règles, avant de pouvoir les surmonter.

Après des romans comme « Les soldats de l'or gris », l'auteur passe à l'essai avec « Le bug humain ». Tout le monde peut constater, notamment à travers la destruction toujours plus poussée de l'environnement, que l'humanité, collectivement, n'est pas raisonnable. Pourquoi est-ce qu'on continue cette destruction alors qu'il est clair qu'il faudrait, au lieu de vouloir « relancer la croissance » et autres délires productivistes, diminuer la consommation de tout ? Depuis des siècles, des tas de gens ont réfléchi à ce problème, et ont proposé plein d'explications (qui ne sont pas forcément incompatibles entre elles). Ici, Sébastien Bohler a une théorie : l'essentiel du problème vient du striatum. Cet organe peu connu du cerveau est responsable de la motivation : c'est lui qui, via la dopamine qu'il secrète, pousse à consommer (de la nourriture, de l'information ou du sexe) et toujours davantage. En effet, lorsque l'évolution a façonné cet organe, on ne pouvait jamais consommer trop. On n'avait jamais assez à manger, par exemple et, même si c'était le cas temporairement, manger avec excès et accumuler des graisses était une bonne stratégie ; on perdrait ces graisses sans effort à la prochaine pénurie. De même, faire des enfants en quantité était raisonnable quand la plupart d'entre eux mourraient jeunes. Mais, aujourd'hui, cela mène à la surpopulation.

Aujourd'hui où la production de masse permet de consommer trop, le striatum est devenu dangereux ; il pousse à ne jamais s'arrêter, même au-delà du raisonnable. Et l'évolution naturelle, trop lente, ne va pas changer ce comportement avant qu'il ne soit trop tard et que toutes les ressources naturelles aient été détruites.

Est-ce une fatalité ? L'auteur estime que, si le striatum pousse à des comportements qui sont souvent négatifs dans notre société, il ne représente pas tout notre cerveau. D'autres parties, comme le cortex préfrontal, sont capables d'inhiber les instincts immédiats, et donc potentiellement de nous amener à un meilleur équilibre entre les désirs primaires et la réalité.

Le livre est très bien écrit, très convaincant. Vous apprendrez beaucoup de choses sur votre cerveau en le lisant. Mais je reste un peu sceptique car il résume un problème très vaste à une cause principale. Dans le cadre écologique, par exemple, les décisions individuelles poussées par le striatum ne sont pas tout. Il y a aussi la difficulté à parvenir à une décision commune lorsque le changement de mode de vie serait dans l'intérêt de tous mais heurtent les intérêts de certains (comme l'analyse bien Diamond dans « Effondrement »). Le pouvoir du striatum peut expliquer pourquoi, même quand on est déjà en surpoids, on reprend du dessert, mais peut-il vraiment expliquer l'avidité d'actionnaires qui, dans un bureau climatisé, sans qu'ils aient faim ou froid, prennent des décisions catastrophiques pour la biosphère ? Et, même quand tout le monde a les mêmes intérêts et en est conscient, une décision commune n'est pas facile, si chacun craint d'être le seul à faire des efforts.


L'article seul

RFC 8782: Distributed Denial-of-Service Open Threat Signaling (DOTS) Signal Channel Specification

Date de publication du RFC : Mai 2020
Auteur(s) du RFC : T. Reddy (McAfee), M. Boucadair (Orange), P. Patil (Cisco), A. Mortensen (Arbor Networks), N. Teague (Iron Mountain Data Centers)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dots
Première rédaction de cet article le 31 mai 2020


Le protocole DOTS (Distributed Denial-of-Service Open Threat Signaling) vise à permettre au client d'un service anti-dDoS de demander au service de mettre en route des mesures contre une attaque. Ce RFC décrit le canal de signalisation de DOTS, celui par lequel passera la demande d'atténuation de l'attaque.

Si vous voulez mieux comprendre DOTS, il est recommandé de lire le RFC 8612, qui décrit le cahier des charges de ce protocole. Ici, je vais résumer à l'extrême : un client DOTS, détectant qu'une attaque par déni de service est en cours contre lui, signale, par le canal normalisé dans ce RFC, à un serveur DOTS qu'il faudrait faire quelque chose. Le serveur DOTS est un service anti-dDoS qui va, par exemple, examiner le trafic, jeter ce qui appartient à l'attaque, et transmettre le reste à son client.

Ces attaques par déni de service sont une des plaies de l'Internet, et sont bien trop fréquentes aujourd'hui (cf. RFC 4987 ou RFC 4732 pour des exemples). Bien des réseaux n'ont pas les moyens de se défendre seuls et font donc appel à un service de protection (payant, en général, mais il existe aussi des services comme Deflect). Ce service fera la guerre à leur place, recevant le trafic (via des manips DNS ou BGP), l'analysant, le filtrant et envoyant ce qui reste au client. Typiquement, le client DOTS sera chez le réseau attaqué, par exemple en tant que composant d'un IDS ou d'un pare-feu, et le serveur DOTS sera chez le service de protection. Notez donc que client et serveur DOTS sont chez deux organisations différentes, communiquant via le canal de signalisation (signal channel), qui fait l'objet de ce RFC.

La section 3 de notre RFC expose les grands principes du protocole utilisé sur ce canal de signalisation. Il repose sur CoAP, un équivalent léger de HTTP, ayant beaucoup de choses communes avec HTTP. Le choix d'un protocole différent de HTTP s'explique par les spécificités de DOTS : on l'utilise quand ça va mal, quand le réseau est attaqué, et il faut donc pouvoir continuer à fonctionner même quand de nombreux paquets sont perdus. CoAP a les caractéristiques utiles pour DOTS, il est conçu pour des réseaux où il y aura des pertes, il tourne sur UDP, il permet des messages avec ou sans accusé de réception, il utilise peu de ressources, il peut être sécurisé par DTLSTCP est également utilisable mais UDP est préféré, pour éviter le head-of-line blocking. CoAP est normalisé dans le RFC 7252. Parmi les choses à retenir, n'oubliez pas que l'encodage du chemin dans l'URI est un peu spécial, avec une option Uri-Path: par segment du chemin (RFC 7252, section 5.10.1). Par abus de langage, j'écrirai « le client CoAP demande /foo/bar/truc.cbor » alors qu'il y aura en fait trois options Uri-Path: :

Uri-Path: "foo"
Uri-Path: "bar"
Uri-Path: "truc.cbor" 
  

Par défaut, DOTS va utiliser le port 4646 (et non pas le port par défaut de CoAP, 5684, pour éviter toute confusion avec d'autres services tournant sur CoAP). Ce port a été choisi pour une bonne raison, je vous laisse la chercher, la solution est à la fin de cet article. Le plan d'URI sera coaps ou coaps+tcp (RFC 7252, section 6, et RFC 8323, section 8.2).

Le fonctionnement de base est simple : le client DOTS se connecte au serveur, divers paramètres sont négociés. Des battements de cœur peuvent être utilisés (par le client ou par le serveur) pour garder la session ouverte et vérifier son bon fonctionnement. En cas d'attaque, le client va demander une action d'atténuation. Pendant que celle-ci est active, le serveur envoie de temps en temps des messages donnant des nouvelles. L'action se terminera, soit à l'expiration d'un délai défini au début, soit sur demande explicite du client. Le serveur est connu du client par configuration manuelle, ou bien par des techniques de découverte encore en cours de développement.

Les messages sont encodés en CBOR (RFC 7049). Rappelez-vous que le modèle de données de CBOR est très proche de celui de JSON, et notre RFC spécifie donc les messages avec une syntaxe JSON, même si ce n'est pas l'encodage utilisé sur le câble. Pour une syntaxe formelle des messages, le RFC utilise YANG (cf. RFC 7951). Le type MIME des messages est application/dots+cbor.

La section 4 du RFC décrit les différents messages possibles plus en détail. Je ne vais pas tout reprendre ici, juste donner quelques exemples. Les URI commencent toujours par /.well-known/dots (.well-known est normalisé dans le RFC 8615, et dots est désormais enregistré à l'IANA). Les différentes actions ajouteront au chemin dans l'URI /mitigate pour les demandes d'actions d'atténuation, visant à protéger de l'attaque, /hb pour les battements de cœur, etc.

Voici par exemple une demande de protection, effectuée avec la méthode CoAP PUT :

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "mitigate"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "mid=123"
Content-Format: "application/dots+cbor"

{
       ... Données en CBOR (représentées en JSON dans le RFC et dans
       cet article, pour la lisibilité).
}    
  

L'URI, en notation traditionnelle, sera donc /.well-known/dots/mitigate/cuid=dz6pHjaADkaFTbjr0JGBpw/mid=123. CUID veut dire Client Unique IDentifier et sert à identifier le client DOTS, MID est Mitigation IDentifier et identifie une demande d'atténuation particulière. Si ce client DOTS fait une autre demande de palliation, le MID changera mais le CUID sera le même.

Que met-on dans le corps du message ? On a de nombreux champs définis pour indiquer ce qu'on veut protéger, et pour combien de temps. Par exemple, on pourrait avoir (je rappelle que c'est du CBOR, format binaire, en vrai) :

     {
       "ietf-dots-signal-channel:mitigation-scope": {
         "scope": [
           {
             "target-prefix": [
                "2001:db8:6401::1/128",
                "2001:db8:6401::2/128"
              ],
             "target-port-range": [
               {
                 "lower-port": 80
               },
               {
                 "lower-port": 443
               }
              ],
              "target-protocol": [
                6
              ],
             "lifetime": 3600
           }
         ]
       }
     }
  

Ici, le client demande qu'on protège 2001:db8:6401::1 et 2001:db8:6401::2 (target veut dire qu'ils sont la cible d'une attaque, pas qu'on veut les prendre pour cible), sur les ports 80 et 443, en TCP, pendant une heure. (lower-port seul, sans upper-port indique un port unique, pas un intervalle.)

Le serveur va alors répondre avec le code 2.01 (indiquant que la requête est acceptée et traitée) et des données :

  {
     "ietf-dots-signal-channel:mitigation-scope": {
        "scope": [
           {
             "mid": 123,
             "lifetime": 3600
           }
         ]
      }
   }
  

La durée de l'action peut être plus petite que ce que le client a demandé, par exemple si le serveur n'accepte pas d'actions trop longues. Évidemment, si la requête n'est pas correcte, le serveur répondra 4.00 (format invalide), si le client n'a pas payé, 4.03, s'il y a un conflit avec une autre requête, 4.09, etc. Le serveur peut donner des détails, et la liste des réponses possibles figure dans des registres IANA, comme celui de l'état d'une atténuation, ou celui des conflits entre ce qui est demandé et d'autres actions en cours.

Le client DOTS peut ensuite récupérer des informations sur une action de palliation en cours, avec la méthode CoAP GET :

Header: GET (Code=0.01)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "mitigate"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "mid=123"    
  

Ce GET /.well-known/dots/mitigate/cuid=dz6pHjaADkaFTbjr0JGBpw/mid=123 va renvoyer de l'information sur l'action d'identificateur (MID) 123 :

   {
     "ietf-dots-signal-channel:mitigation-scope": {
       "scope": [
         {
           "mid": 123,
           "mitigation-start": "1507818393",
           "target-prefix": [
                "2001:db8:6401::1/128",
                "2001:db8:6401::2/128"
           ],
           "target-protocol": [
             6
           ],
           "lifetime": 1755,
           "status": "attack-stopped",
           "bytes-dropped": "0",
           "bps-dropped": "0",
           "pkts-dropped": "0",
           "pps-dropped": "0"
         }
       ]
     }
   }
  

Les différents champs de la réponse sont assez évidents. Par exemple, pkts-dropped indique le nombre de paquets qui ont été jetés par le protecteur.

Pour mettre fin aux actions du système de protection, le client utilise évidemment la méthode CoAP DELETE :

Header: DELETE (Code=0.04)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "mitigate"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "mid=123"
  

Le client DOTS peut se renseigner sur les capacités du serveur avec un GET de /.well-known/dots/config.

Ce RFC décrit le canal de signalisation de DOTS. Le RFC 8783, lui, décrit le canal de données. Le canal de signalisation est prévu pour faire passer des messages de petite taille, dans un environnement hostile (attaque en cours). Le canal de données est prévu pour des données de plus grande taille, dans un environnement où les mécanismes de transport normaux, comme HTTPS, sont utilisables. Typiquement, le client DOTS utilise le canal de données avant l'attaque, pour tout configurer, et le canal de signalisation pendant l'attaque, pour déclencher et arrêter l'atténuation.

Les messages possibles sont modélisés en YANG. YANG est normalisé dans le RFC 7950. Notez que YANG avait été initialement créé pour décrire les commandes envoyées par NETCONF (RFC 6241) ou RESTCONF (RFC 8040) mais ce n'est pas le cas ici : DOTS n'utilise ni NETCONF, ni RESTCONF mais son propre protocole basé sur CoAP. La section 5 du RFC contient tous les modules YANG utilisés.

La mise en correspondance des modules YANG avec l'encodage CBOR figure dans la section 6. (YANG permet une description abstraite d'un message mais ne dit pas, à lui tout seul, comment le représenter en bits sur le réseau.) Les clés CBOR sont toutes des entiers ; CBOR permet d'utiliser des chaînes de caractères comme clés mais DOTS cherche à gagner de la place. Ainsi, les tables de la section 6 nous apprennent que le champ cuid (Client Unique IDentifier) a la clé 4, suivie d'une chaîne de caractères en CBOR. (Cette correspondance est désormais un registre IANA.) D'autre part, DOTS introduit une étiquette CBOR, 271 (enregistrée à l'IANA, cf. RFC 7049, section 2.4) pour marquer un document CBOR comme lié au protocole DOTS.

Évidemment, DOTS est critique en matière de sécurité. S'il ne fonctionne pas, on ne pourra pas réclamer une action de la part du service de protection. Et s'il est mal authentifié, on risque de voir le méchant envoyer de faux messages DOTS, par exemple en demandant l'arrêt de l'atténuation. La section 8 du RFC rappelle donc l'importance de sécuriser DOTS par TLS ou plutôt, la plupart du temps, par son équivalent pour UDP, DTLS (RFC 6347). Le RFC insiste sur l'authentification mutuelle du serveur et du client, chacun doit s'assurer de l'identité de l'autre, par les méthodes TLS habituelles (typiquement via un certificat). Le profil de DTLS recommandé (TLS est riche en options et il faut spécifier lesquelles sont nécessaires et lesquelles sont déconseillées) est en section 7. Par exemple, le chiffrement intègre est nécessaire.

La section 10 revient sur les questions de sécurité en ajoutant d'autres avertissements. Par exemple, TLS ne protège pas contre certaines attaques par déni de service, comme un paquet TCP RST (ReSeT). On peut sécuriser la communication avec TCP-AO (RFC 5925) mais c'est un vœu pieux, il est très peu déployé à l'heure actuelle. Ah, et puis si les ressources à protéger sont identifiées par un nom de domaine, et pas une adresse ou un préfixe IP (target-fqdn au lieu de target-prefix), le RFC dit qu'évidemment la résolution doit être faite avec DNSSEC.

Question mises en œuvre, DOTS dispose d'au moins quatre implémentations, dont l'interopérabilité a été testée plusieurs fois lors de hackathons IETF (la première fois ayant été à Singapour, lors de l'IETF 100) :

Notez qu'il existe des serveurs de test DOTS publics comme coaps://dotsserver.ddos-secure.net:4646.

Ah, et la raison du choix du port 4646 ? C'est parce que 46 est le code ASCII pour le point (dot en anglais) donc deux 46 font deux points donc dots.


Téléchargez le RFC 8782


L'article seul

RFC 8783: Distributed Denial-of-Service Open Threat Signaling (DOTS) Data Channel Specification

Date de publication du RFC : Mai 2020
Auteur(s) du RFC : M. Boucadair (Orange), T. Reddy (McAfee)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dots
Première rédaction de cet article le 31 mai 2020


Le système DOTS (Distributed Denial-of-Service Open Threat Signaling) est conçu pour permettre la coordination des défenseurs pendant une attaque par déni de service (cf. RFC 8612). Pour cela, DOTS a deux protocoles, le protocole de signalisation, à utiliser en cas de crise, et le protocole de données, pour les temps plus calmes. Ce dernier fait l'objet de ce RFC.

Pourquoi deux protocoles ? Parce qu'il y a deux sortes de données : celles urgentes, de petite taille, transmises dans le feu de l'attaque, au moment où le réseau marche mal, c'est le domaine du protocole « signalisation », du RFC 8782. Et les données de grande taille, moins urgentes, mais qui doivent être transmises de manière fiable. Et c'est le but de notre RFC. Il y a donc deux canaux entre le client DOTS, qui demande de l'aide, et le serveur DOTS qui fournit des mécanismes d'atténuation des attaques : le canal « signalisation » du RFC 8782, et le canal « données », de notre RFC. Ce canal de données va servir, par exemple, à transporter :

  • La liste des préfixes IP qu'il faudra protéger. (Notez que le serveur ne va pas forcément les accepter, il peut faire des vérifications),
  • Des règles de filtrage, que le serveur appliquera en cas de crise (par exemple « laisse passer uniquement ce qui va vers le port 53 » ou bien « jette tout ce qui est à destination du port 666 », ou encore « voici une liste des préfixes vraiment importants, les seuls qu'il faudra accepter en cas de DDoS »).

Pour lire le reste du RFC, ne ratez pas la section 2, sur le vocabulaire à utiliser. Notamment, le terme d'ACL est utilisé dans un sens plus général que celui du RFC 8519.

Bon, le protocole, maintenant (section 3). Comme il n'a pas besoin de fonctionner en permanence, même dans les cas d'attaque, contrairement au protocole de signalisation, et comme il a par contre besoin de fiabilité, il va utiliser des technologies classiques : RESTCONF (RFC 8040) au-dessus de TLS (et donc au-dessus de TCP). RESTCONF utilise HTTP donc on aura les méthodes classiques, GET, DELETE, etc. Par exemple, le client DOTS qui veut récupérer des informations sur la configuration commence par faire un GET. Les données sont encodées en JSON (RFC 8259). Elles sont spécifiées dans un module YANG (RFC 7950) et on passe du modèle YANG à l'encodage concret en suivant les règles du RFC 7951.

La connexion entre le client DOTS et le serveur peut être intermittente (on se connecte juste le temps de faire un GET, par exemple) ou bien permanente, ce qui est pratique si le client faite des requêtes régulières, ou bien si le serveur pousse des notifications (section 6.3 du RFC 8040).

Ah, et j'ai parlé de client et de serveur DOTS. Comment est-ce que le client trouve le serveur ? Cela peut être fait manuellement, ou bien via la future procédure de découverte.

Les détails sur ce qu'on peut récupérer en DOTS ? Ils sont dans la section 4, sous forme d'un module YANG, nommé ietf-dots-data-channel (désormais dans le registre IANA). Par exemple, dans ce module, les ACL permettent d'indiquer les adresses IP et les protocoles de transport concernés, ainsi que les actions à entreprendre (laisser passer le paquet, jeter le paquet, etc), comme avec n'importe quel pare-feu. Le serveur DOTS agit donc comme un pare-feu distant. Si le serveur l'accepte, on peut aussi mettre des ACL portant sur les protocoles de la couche 4, par exemple pour filtrer sur le port.

Bon, passons maintenant à la pratique. Nous allons utiliser le serveur public de test dotsserver.ddos-secure.net. Comme le protocole de données de DOTS repose sur RESTCONF (RFC 8040) qui repose lui-même sur HTTP, nous allons utiliser curl comme client. Ce serveur public exige un certificat client, que nous récupérons en ligne. Ensuite, je crée un alias pour simplifier les commandes ultérieures :

% alias dotsdata='curl --cacert ./ca-cert.pem --cert ./client-cert.pem --key ./client-key.pem --header "Content-type: application/yang-data+json" --write-out "\n%{http_code}\n"'
  

Et enregistrons-nous, pour indiquer un identificateur de client DOTS :

% cat register.json 
{
  "ietf-dots-data-channel:dots-client": [
    {
      "cuid": "s-bortzmeyer"
    }
  ]
}

% dotsdata  --request POST --data @register.json https://dotsserver.ddos-secure.net/v1/restconf/data/ietf-dots-data-channel:dots-data/
201
  

Voilà, l'utilisateur s-bortzmeyer est enregistré (201 est le code de retour HTTP Created ; si cet identificateur avait déjà existé, on aurait récupéré un 409 - Conflict). Quand on aura fini, on pourra le détruire :

% dotsdata  --request DELETE https://dotsserver.ddos-secure.net/v1/restconf/data/ietf-dots-data-channel:dots-data/dots-client=MONIDENTIFICATEUR
204
  

Suivant la logique REST de RESTCONF, l'identité du client figure dans l'URL.

Maintenant, créons un alias pour le préfixe 2001:db8::/32 :

% cat create-alias.json
{
  "ietf-dots-data-channel:aliases": {
    "alias": [
      {
        "name": "TEST-ALIAS",
        "target-prefix": [
          "2001:cafe::/32"
        ]
      }
    ]
  }
}

% dotsdata --request POST --data @create-alias.json https://dotsserver.ddos-secure.net/v1/restconf/data/ietf-dots-data-channel:dots-data/dots-client=s-bortzmeyer
{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"invalid-value","error-message":"alias: post failed: dots r_alias: TEST-ALIAS: target_prefix \"2001:cafe::/32\" is not supported within Portal ex-portal1 (1.1.1.69,1.1.1.71,1.1.2.0/24,2001:db8:6401::/96)"}}}
400
  

Aïe, ça a raté (400 = Bad request). C'est parce que, comme nous le dit le message d'erreur, un vrai serveur DOTS n'accepte pas qu'un client joue avec n'importe quelle adresse IP, pour d'évidentes raisons de sécurité. Il faut prouver (par un moyen non spécifié dans le RFC) quels préfixes on contrôle, et ce seront les seuls où on pourra définir des alias et des ACL. Ici, le serveur de test n'autorise que trois préfixes, indiqués dans sa documentation et dans le message d'erreur. Reprenons :

% cat create-alias.json 
{
  "ietf-dots-data-channel:aliases": {
    "alias": [
      {
        "name": "TEST-ALIAS",
        "target-prefix": [
          "2001:db8:6401::f00/128"
        ]
      }
    ]
  }
}

% dotsdata --request POST --data @create-alias.json https://dotsserver.ddos-secure.net/v1/restconf/data/ietf-dots-data-channel:dots-data/dots-client=s-bortzmeyer

201
  

Ouf, c'est bon, vérifions que l'alias a bien été créé :

% dotsdata --request GET --data @create-alias.json https://dotsserver.ddos-secure.net/v1/restconf/data/ietf-dots-data-channel:dots-data/dots-client=s-bortzmeyer/aliases
{"ietf-dots-data-channel:aliases":{"alias":[{"name":"TEST-ALIAS","pending-lifetime":10078,"target-prefix":["2001:db8:6401::f00/128"]}]}}
200
  

C'est parfait, on va essayer de demander du filtrage, maintenant. D'abord, les capacités du serveur dans ce domaine :

% dotsdata --request GET --data @create-alias.json https://dotsserver.ddos-secure.net/v1/restconf/data/ietf-dots-data-channel:dots-data/capabilities | jq .
...
   "ipv6": {
      "length": true,
      "protocol": true,
      "destination-nprefix": true,
      "source-prefix": true,
      "fragment": true
    },
    "tcp": {
      "flags": true,
      "flags-bitmask": true,
      "source-port": true,
      "destination-port": true,
      "port-range": true
    },
  

Bien, le serveur sait filtrer sur la longueur des paquets, sur les adresses IP source et destination, et il sait traiter spécifiquement les fragments. Et il sait filtrer le TCP sur divers critères, comme les ports source et destination. On va lui demander de filtrer tout ce qui vient de 2001:db8:dead::/48 :

% cat install-acl.json 
{
  "ietf-dots-data-channel:acls": {
    "acl": [
      {
        "name": "TEST-ACL",
        "type": "ipv6-acl-type",
        "activation-type": "activate-when-mitigating",
        "aces": {
          "ace": [
            {
              "name": "TEST-RULE",
              "matches": {
                "ipv6": {
                  "source-ipv6-network": "2001:db8:dead::/48"
                }
              },
              "actions": {
                "forwarding": "drop"
              }
            }
          ]
        }
      }
    ]
  }
}
    
% dotsdata --request POST --data @install-acl.json https://dotsserver.ddos-secure.net/v1/restconf/data/ietf-dots-data-channel:dots-data/dots-client=s-bortzmeyer

201
  

Parfait, le serveur a accepté notre ACL. Vous avez vu les fonctions les plus importantes du protocole de données de DOTS. En cas d'attaque, il ne vous reste plus qu'à utiliser le protocole de signalisation (RFC 8782) pour utiliser alias et ACLs.

Quelques considérations de sécurité, maintenant, en section 10 du RFC. La sécurité est évidemment cruciale pour DOTS puisque, si on l'utilise, c'est qu'on a des ennemis et qu'ils nous attaquent. Les préfixes IP qu'on veut protéger ou au contraire qu'on veut filtrer sont par exemple une information confidentielle (elle pourrait aider l'attaquant). Le RFC impose donc la cryptographie pour protéger les communications, en utilisant TLS, et avec chiffrement intègre. Même avec TLS et ce chiffrement intègre, comme la couche transport n'est pas protégée, un attaquant actif pourrait perturber la communication, par exemple en injectant des paquets TCP RST (qui coupent la connexion). Il existe un mécanisme de protection, AO, normalisé dans le RFC 5925, mais il est très peu déployé en pratique.

La cryptographie ne protège pas contre un client DOTS malveillant, ou simplement mal configuré. Le serveur doit donc vérifier que le client a le droit de protéger tel ou tel préfixe IP. Autrement, un client DOTS pourrait demander le filtrage du préfixe d'un de ses ennemis. Le RFC ne spécifie pas quel mécanisme utiliser pour cette vérification, mais cela peut être, par exemple, l'utilisation des registres des RIR, qui indiquent qui est le titulaire légitime d'un préfixe.

Le protocole de ce RFC peut utiliser des noms de domaine pour configurer les ACL. Dans ce cas, le serveur doit veiller à sécuriser la résolution DNS, à la fois contre des manipulations, grâce à DNSSEC, et contre la surveillance, en utilisant du DNS chiffré comme dans le RFC 7858.

Pour les mises en œuvre de ce protocole, voyez mon article sur le RFC 8782. Mais le protocole de notre RFC étant fondé sur HTTPS, on peut dans une certaine mesure utiliser des outils existants comme, vous l'avez vu, curl.


Téléchargez le RFC 8783


L'article seul

Articles des différentes années : 2020  2019  2018  2017  2016  2015  2014  Précédentes années

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

Un article de ce blog au hasard.