Rémy Grünblatt 🍃https://remy.grunblatt.org/2022-12-24T00:00:00+01:00Accéder à des articles scientifiques de manière éthique2022-12-24T00:00:00+01:002022-12-24T00:00:00+01:00Rémy Grünblatttag:remy.grunblatt.org,2022-12-24:/acceder-a-des-articles-scientifiques-de-maniere-ethique.html<p>Avec le début de la nouvelle année 2023, il est possible que votre université ou institution de recherche ait stoppé son abonnement à un éditeur scientifique à but lucratif, possiblement en raison d’un coût trop élevé. Toute ressemblance avec la réalité est bien évidemment fortuite.</p>
<p>Comment alors accéder aux …</p><p>Avec le début de la nouvelle année 2023, il est possible que votre université ou institution de recherche ait stoppé son abonnement à un éditeur scientifique à but lucratif, possiblement en raison d’un coût trop élevé. Toute ressemblance avec la réalité est bien évidemment fortuite.</p>
<p>Comment alors accéder aux articles scientifiques, lorsque l’on est doctorante, professeur, chercheuse, maître de conférence, et que notre institution ne paye plus un abonnement (<strong>avec de l’argent public</strong>) pour accéder à des articles (produits <strong>avec de l’argent public</strong>) évalués <strong>gratuitement</strong> par des pairs (dont <strong>l’employeur est très souvent public</strong>) et dont la mise en forme est très souvent effectuée par ces mêmes auteurs ou autrices, avec des interventions mimimes sur la forme ou le fond de la part de ces éditeurs à but lucratif, <strong>dont les bénéfices sont eux privés</strong> ?</p>
<p>Je liste dans ce simili-article quelques solutions et stratégies d’évitement.</p>
<p>Sur le même sujet, on peut noter <a href="https://bjoern.brembs.net/2016/12/so-your-institute-went-cold-turkey-on-publisher-x-what-now/">cet article en anglais</a> intitulé <em>« So your institute went cold turkey on publisher X. What now? »</em>.</p>
<h1 id="extensions-de-navigateur">Extensions de navigateur<a class="headerlink" href="#extensions-de-navigateur" title="Permanent link">¶</a></h1>
<p>Il existe plusieurs extensions qui permettent d’accéder à des versions non payantes des articles, par exemple des versions auteurs, hébergées par des archives ouvertes, des pages persos d’académiques…</p>
<p>Leur utilisation suit très souvent le même schéma : on accède à l’article de manière gratuite en allant sur le site web de l’éditeur et en cliquant sur le bouton de l’extension, qui apparait dans la barre d’extensions ou directement sur la page.</p>
<p>Ces extensions ont l’avantage de faciliter l’accès à des articles disponibles en « open access » sur plusieurs archives en ligne, là où une recherche manuelle sur <a href="https://hal.science/">HAL</a> par exemple ne risque de retourner des résultats que si l’une des personnes ayant écrit l’article est payée par un organisme de recherche Français.</p>
<h2 id="google-scholar">Google Scholar<a class="headerlink" href="#google-scholar" title="Permanent link">¶</a></h2>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/google-scholar-button/ldipcbpaocekfooobnbcddclnhejkcpn?hl=en">Google Scholar Button (Chrome)</a></li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/google-scholar-button/">Google Scholar Button (Firefox)</a></li>
</ul>
<p><img alt="" src="/images/google_scholar.svg" /></p>
<h2 id="unpaywall">Unpaywall<a class="headerlink" href="#unpaywall" title="Permanent link">¶</a></h2>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/unpaywall/iplffkdpngmdjhlpjmppncnlhomiipha">Unpaywall (Chrome)</a></li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/unpaywall/">Unpaywall (Firefox)</a></li>
</ul>
<p><img alt="" src="/images/unpaywall.svg" /></p>
<h2 id="open-access-button">Open Access Button<a class="headerlink" href="#open-access-button" title="Permanent link">¶</a></h2>
<p>Il suffit de cliquer sur le bouton OpenAccess dans la barre d’extension pour être redirigé vers l’article, si disponible.</p>
<ul>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/openaccessbutton/">Open Access Button (Firefox)</a></li>
<li><a href="https://chrome.google.com/webstore/detail/open-access-button/gknkbkaapnhpmkcgkmdekdffgcddoiel">Open Access Button (Chrome)</a></li>
</ul>
<p><img alt="" src="/images/OpenAccessButtonLogo.svg" /></p>
<h1 id="demander-aux-autrices-et-auteurs">Demander aux autrices et auteurs<a class="headerlink" href="#demander-aux-autrices-et-auteurs" title="Permanent link">¶</a></h1>
<p>Un des moyen d’accéder à des articles sans avoir besoin de débourser le moindre centime est de demander une copie aux autrices et auteurs de ces articles. Ces personnes seront, la plupart du temps, plus que ravies de vous envoyer ces articles, par email !</p>
<h1 id="sci-hub">Sci-Hub<a class="headerlink" href="#sci-hub" title="Permanent link">¶</a></h1>
<p><img alt="" src="/images/sci-hub.webp" /></p>
<p>Un autre moyen d’accéder à des articles est l’utilisation de Sci-Hub, dont je n’aborderai pas la question de la légalité ici. Une URL à jour de Sci-Hub devrait être disponible en cliquant sur le lien ci-dessous :</p>
<ul>
<li><a href="https://hub.toolforge.org/Q21980377?property=P856">Site Web Sci-Hub</a></li>
</ul>
<p>On peut copier le nom de l’article ou son DOI dans le champs de recherche, et, si l’article n’est pas trop récent, i.e. il a plus d’un an, on devrait pouvoir y accéder.</p>
<p>On notera que l’accès à Sci-Hub est bloqué chez <a href="https://www.soundofscience.fr/2724">plusieurs FAI français, mais pas chez Renater</a>. Ce lien discute de plusieurs stratégies de contournement dans l’accès à Sci-Hub.</p>
<h1 id="sur-le-long-terme">Sur le long terme<a class="headerlink" href="#sur-le-long-terme" title="Permanent link">¶</a></h1>
<p>Sur le long terme, la démarche à aborder est celle de publier dans des revues ou des conférences qui pratiquent l’Open Access « diamant », c’est-à-dire un Open Access où la publication est gratuite pour les auteurs et autrices, l’accès est gratuit pour les lecteurs et lectrices, l’article a bien fait l’objet d’une revue par les pairs formelle, et les personnes ayant écrit l’article gardent leurs droits sur leurs travaux.</p>
<p><img title="CC-BY SA -- Jamie-farquharson" src="/images/Open_Access.svg" /></p>Nix and NixOS, my pain points2022-12-23T00:00:00+01:002022-12-23T00:00:00+01:00Rémy Grünblatttag:remy.grunblatt.org,2022-12-23:/nix-and-nixos-my-pain-points.html<!--
Je suis un utilisateur de Nix (un gestionnaire de paquets « reproductible ») et de NixOS (la distribution Linux basée sur ce gestionnaire de paquets) depuis bientôt deux ans. Je l'utilise dans un contexte personnel mais aussi professionnel. Dans cet article, je vais me concentrer sur les points « douloureux » dans *mon* utilisation de Nix et de NixOS. Il y a certes beaucoup de points positifs, mais l'*expérience* NixOS est loin d'être un long fleuve tranquille.
## Une documentation mauvaise
La documentation de Nix et de NixOS est plutôt mauvaise. Pour comprendre comment fonctionne un service ou une option, il est très souvent nécessaire d'aller lire le code source (des fichiers `.nix`) car il n'y a pas d'explications dans le manuel, ou alors les explications ne sont pas très compréhensibles.
Sur ce point, l'utilisation de GitHub pour l'hébergement des dépôts des projets rend cette recherche parfois difficile. Par exemple une recherche sur le mot-clef ["pass-wayland"](https://github.com/NixOS/nixpkgs/search?q=%22pass-wayland%22) devrait renvoyer un résultat dans l'onglet "Code", mais ce n'est pas le cas, car Github n'indexe pas la totalité du dépôt.
Le [wiki](https://nixos.wiki/) de Nix / NixOS est rarement à jour. Il mélange des informations liées à des versions spécifiques de nixpkgs (e.g. `22.05`, `unstable`, …) sans nécessairement préciser de quelle version il s'agit. Comme il ne s'agit pas d'une ressource « officielle », ses pages contiennent de nombreuses références à l'utilisation d'outils *tiers* (comme le programme *home-manager* ou le service *cachix*) ou de fonctionnalités non stables (comme les *flakes*). Des configurations spécifiques sont postées directement dans le wiki (e.g. [https://nixos.wiki/wiki/Sway](https://web.archive.org/web/20220617040332/https://nixos.wiki/wiki/Sway)) sans qu'il y ait d'explication sur les choix fait ou leur spécificité, ce qui que l'aspect déclaratif de la configuration de NixOS tend à encourager.
## Une évaluation poreuse
La reproductibilité de NixOS / Nix / Nixpkgs est très perfectible. On pourrait croire que par défaut, NixOS est « reproductible » (pour une certaine définition de reproductible). Ce n'est pas vraiment le cas: deux machines qui possèdent les mêmes fichiers de configuration (`/etc/nixos/configuration.nix`) peuvent différer largement du fait de la dépendance à d'autres fichiers de configurations comme `~/.config/nixpkgs/config.nix`, de la possibilité de changer le comportement de Nix en utilisant des [variables d'environnements, des arguments sur sa ligne de commande](https://www.tweag.io/blog/2020-05-25-flakes/) ou même à cause de l'utilisation de versions différentes de Nix.
Le dépôt Nixpkgs (qui contient l'ensemble des recettes liées aux paquets présents dans NixOS) étant différent du dépôt Nix (qui contient le code source du gestionnaire de paquet Nix), utiliser un commit spécifique de Nixpkgs n'est pas suffisant, il est aussi nécessaire de faire attention à la version de Nix utilisée, sous peine de [régressions](https://github.com/NixOS/nix/issues/4859). De ce point de vue, Guix possède une approche à mon sens meilleure, [un unique dépôt](https://github.com/guix-mirror/guix) étant utilisé pour le gestionnaire de paquet et les « recettes » des paquets.
## Des sources fragiles
La reproductibilité de NixOS / Nix n'est aussi assurée que si les sources utilisées restent réellement accessibles. Un [exemple récent](https://github.com/NixOS/nixpkgs/issues/187314) souligne la fragilité de ces sources, et la fragilité de Nix qui [n'exploite pas](https://github.com/NixOS/nixpkgs/issues/53653) des solutions comme [Software Heritage](https://www.softwareheritage.org/) (là où Guix le fait [depuis au moins trois ans](https://guix.gnu.org/blog/2019/connecting-reproducible-deployment-to-a-long-term-source-code-archive/)).
## Pas de reproductibilité binaire
L'un des problèmes de Nix / NixOS / Nixpkgs concernant la sauvegarde de ces sources est tout simplement la découverte des sources à archiver. En effet, il n'est pas possible de facilement extraire l'ensemble des dépendances (e.g. les URLs utilisées dans les recettes des paquets de Nixpkgs) pour les archiver, car un certain nombre de ces URLs ne sont « calculées » qu'à l'évaluation, ce qui nécessite donc d'évaluer l'ensemble de Nixpkgs, dans toutes ses configurations possibles, pour s'assurer que l'on archive bien ce qu'il faut archiver (une partie de ce travail travail est [actuellement effectuée par Hydra](https://nix-community.github.io/nixpkgs-swh/)). Et cela, sans même parler des *Fixed Output Derivation*. On rappellera sur ce sujet que la reproductibilité de Nix / NixOS / Nixpkgs n'est qu'une reproductibilité des sources: si les sources changent, on est prévenu, mais il ne s'agit pas de la reproductibilité des binaires (qui peuvent changer à chaque build).
Cette reproductibilité *binaire* de Nix / NixOS / Nixpkgs n'est en effet pas vraiment testée, en tout cas pas systématiquement. Le site web [« Is NixOS Reproducible? »](https://r13y.com/) souligne que l'ISO de NixOS est reproductible à 99.77%, mais il s'agit là d'une vérification sur un pourcentage minuscule, moins de 2%, de l'ensemble des paquets. Là encore, Guix est bien meilleur avec notamment des stats effectuées sur [l'ensemble des paquets du dépôt](http://data.guix.gnu.org/repository/1/branch/master/latest-processed-revision/package-reproducibility).
## NixOS: c'est tout ou rien
Lorsque l'on utilise NixOS, et que l'on souhaite utiliser un paquet qui n'est pas disponible sous NixOS / Nixpkgs (ce qui arrive quand même assez régulièrement), un unique choix s'offre à nous: le packager dans NixOS. Il n'est en général [pas possible de prendre un raccourci](https://nixos.wiki/wiki/Packaging/Binaries) et d'utiliser des binaires précompilés, ce qui veut dire qu'il n'est pas possible de travailler *sous contraintes* sur Nix / NixOS, à moins d'être un utilisateur suffisamment motivé pour parfois packager plusieurs niveaux de dépendances, ce qui a tendance à prendre du temps. Utiliser uniquement NixOS n'est ainsi pas tenable, pour moi: il m'est nécessaire d'avoir accès à une seconde machine, sous une distribution plus classique. -->
<!-- ### Des intégrations incomplètes
Contrairement à d'autres distributions, il est plutôt simple de devenir mainteneur d'un paquet sur NixOS. Il n'y a pas de mécanisme de cooptation, il suffit de soumettre une pull request et c'est bon. Ce mécanisme est tentant, car c'est parfois la manière la plus simple d'ajouter un paquet dans la distribution. À ce jour, près de 2 431 mainteneurs sont présents dans la liste des [mainteneurs](https://github.com/NixOS/nixpkgs/blob/master/maintainers/maintainer-list.nix) (c'est d'ailleurs mon cas sur quelques paquets). Contrairement à [AUR](https://aur.archlinux.org) de Archlinux, ces paquets sont disponibles comme des paquets classiques, et n'ont pas à être compilés sur les machines de chaque utilisateur. C'est probablement l'une des raisons expliquant la première place de Nixpkgs sur [Repology](https://repology.org/repositories/statistics/total) en termes de nombre de paquets disponibles.
Cette abondance de paquets s'accompagne cependant de quelques effets de bords. Tout d'abord, une partie importante des commits sont effectués de manière automatique, car il n'est plus possible de maintenir à jour et *à la main* les paquets présents sur nixpkgs. L'une des raisons est une implication plus faible des mainteneurs ayant ajouté un paquet une fois ce paquet effectivement intégré (et je me place dans cette catégorie). Cette abondance de paquets est aussi à mettre en lien avec un nombre de tickets important: actuellement, prêt de de 5 616 tickets sont ouverts sur GitHub, et la tendance ne semble pas être à la baisse. -->
<p>I have been a user of Nix (a “reproducible” package manager) and NixOS (the Linux distribution based on this package manager) for almost two years. I use it in a personal and professional context. In this article I will focus on the “pain points” in <em>my</em> use of Nix and …</p><!--
Je suis un utilisateur de Nix (un gestionnaire de paquets « reproductible ») et de NixOS (la distribution Linux basée sur ce gestionnaire de paquets) depuis bientôt deux ans. Je l'utilise dans un contexte personnel mais aussi professionnel. Dans cet article, je vais me concentrer sur les points « douloureux » dans *mon* utilisation de Nix et de NixOS. Il y a certes beaucoup de points positifs, mais l'*expérience* NixOS est loin d'être un long fleuve tranquille.
## Une documentation mauvaise
La documentation de Nix et de NixOS est plutôt mauvaise. Pour comprendre comment fonctionne un service ou une option, il est très souvent nécessaire d'aller lire le code source (des fichiers `.nix`) car il n'y a pas d'explications dans le manuel, ou alors les explications ne sont pas très compréhensibles.
Sur ce point, l'utilisation de GitHub pour l'hébergement des dépôts des projets rend cette recherche parfois difficile. Par exemple une recherche sur le mot-clef ["pass-wayland"](https://github.com/NixOS/nixpkgs/search?q=%22pass-wayland%22) devrait renvoyer un résultat dans l'onglet "Code", mais ce n'est pas le cas, car Github n'indexe pas la totalité du dépôt.
Le [wiki](https://nixos.wiki/) de Nix / NixOS est rarement à jour. Il mélange des informations liées à des versions spécifiques de nixpkgs (e.g. `22.05`, `unstable`, …) sans nécessairement préciser de quelle version il s'agit. Comme il ne s'agit pas d'une ressource « officielle », ses pages contiennent de nombreuses références à l'utilisation d'outils *tiers* (comme le programme *home-manager* ou le service *cachix*) ou de fonctionnalités non stables (comme les *flakes*). Des configurations spécifiques sont postées directement dans le wiki (e.g. [https://nixos.wiki/wiki/Sway](https://web.archive.org/web/20220617040332/https://nixos.wiki/wiki/Sway)) sans qu'il y ait d'explication sur les choix fait ou leur spécificité, ce qui que l'aspect déclaratif de la configuration de NixOS tend à encourager.
## Une évaluation poreuse
La reproductibilité de NixOS / Nix / Nixpkgs est très perfectible. On pourrait croire que par défaut, NixOS est « reproductible » (pour une certaine définition de reproductible). Ce n'est pas vraiment le cas: deux machines qui possèdent les mêmes fichiers de configuration (`/etc/nixos/configuration.nix`) peuvent différer largement du fait de la dépendance à d'autres fichiers de configurations comme `~/.config/nixpkgs/config.nix`, de la possibilité de changer le comportement de Nix en utilisant des [variables d'environnements, des arguments sur sa ligne de commande](https://www.tweag.io/blog/2020-05-25-flakes/) ou même à cause de l'utilisation de versions différentes de Nix.
Le dépôt Nixpkgs (qui contient l'ensemble des recettes liées aux paquets présents dans NixOS) étant différent du dépôt Nix (qui contient le code source du gestionnaire de paquet Nix), utiliser un commit spécifique de Nixpkgs n'est pas suffisant, il est aussi nécessaire de faire attention à la version de Nix utilisée, sous peine de [régressions](https://github.com/NixOS/nix/issues/4859). De ce point de vue, Guix possède une approche à mon sens meilleure, [un unique dépôt](https://github.com/guix-mirror/guix) étant utilisé pour le gestionnaire de paquet et les « recettes » des paquets.
## Des sources fragiles
La reproductibilité de NixOS / Nix n'est aussi assurée que si les sources utilisées restent réellement accessibles. Un [exemple récent](https://github.com/NixOS/nixpkgs/issues/187314) souligne la fragilité de ces sources, et la fragilité de Nix qui [n'exploite pas](https://github.com/NixOS/nixpkgs/issues/53653) des solutions comme [Software Heritage](https://www.softwareheritage.org/) (là où Guix le fait [depuis au moins trois ans](https://guix.gnu.org/blog/2019/connecting-reproducible-deployment-to-a-long-term-source-code-archive/)).
## Pas de reproductibilité binaire
L'un des problèmes de Nix / NixOS / Nixpkgs concernant la sauvegarde de ces sources est tout simplement la découverte des sources à archiver. En effet, il n'est pas possible de facilement extraire l'ensemble des dépendances (e.g. les URLs utilisées dans les recettes des paquets de Nixpkgs) pour les archiver, car un certain nombre de ces URLs ne sont « calculées » qu'à l'évaluation, ce qui nécessite donc d'évaluer l'ensemble de Nixpkgs, dans toutes ses configurations possibles, pour s'assurer que l'on archive bien ce qu'il faut archiver (une partie de ce travail travail est [actuellement effectuée par Hydra](https://nix-community.github.io/nixpkgs-swh/)). Et cela, sans même parler des *Fixed Output Derivation*. On rappellera sur ce sujet que la reproductibilité de Nix / NixOS / Nixpkgs n'est qu'une reproductibilité des sources: si les sources changent, on est prévenu, mais il ne s'agit pas de la reproductibilité des binaires (qui peuvent changer à chaque build).
Cette reproductibilité *binaire* de Nix / NixOS / Nixpkgs n'est en effet pas vraiment testée, en tout cas pas systématiquement. Le site web [« Is NixOS Reproducible? »](https://r13y.com/) souligne que l'ISO de NixOS est reproductible à 99.77%, mais il s'agit là d'une vérification sur un pourcentage minuscule, moins de 2%, de l'ensemble des paquets. Là encore, Guix est bien meilleur avec notamment des stats effectuées sur [l'ensemble des paquets du dépôt](http://data.guix.gnu.org/repository/1/branch/master/latest-processed-revision/package-reproducibility).
## NixOS: c'est tout ou rien
Lorsque l'on utilise NixOS, et que l'on souhaite utiliser un paquet qui n'est pas disponible sous NixOS / Nixpkgs (ce qui arrive quand même assez régulièrement), un unique choix s'offre à nous: le packager dans NixOS. Il n'est en général [pas possible de prendre un raccourci](https://nixos.wiki/wiki/Packaging/Binaries) et d'utiliser des binaires précompilés, ce qui veut dire qu'il n'est pas possible de travailler *sous contraintes* sur Nix / NixOS, à moins d'être un utilisateur suffisamment motivé pour parfois packager plusieurs niveaux de dépendances, ce qui a tendance à prendre du temps. Utiliser uniquement NixOS n'est ainsi pas tenable, pour moi: il m'est nécessaire d'avoir accès à une seconde machine, sous une distribution plus classique. -->
<!-- ### Des intégrations incomplètes
Contrairement à d'autres distributions, il est plutôt simple de devenir mainteneur d'un paquet sur NixOS. Il n'y a pas de mécanisme de cooptation, il suffit de soumettre une pull request et c'est bon. Ce mécanisme est tentant, car c'est parfois la manière la plus simple d'ajouter un paquet dans la distribution. À ce jour, près de 2 431 mainteneurs sont présents dans la liste des [mainteneurs](https://github.com/NixOS/nixpkgs/blob/master/maintainers/maintainer-list.nix) (c'est d'ailleurs mon cas sur quelques paquets). Contrairement à [AUR](https://aur.archlinux.org) de Archlinux, ces paquets sont disponibles comme des paquets classiques, et n'ont pas à être compilés sur les machines de chaque utilisateur. C'est probablement l'une des raisons expliquant la première place de Nixpkgs sur [Repology](https://repology.org/repositories/statistics/total) en termes de nombre de paquets disponibles.
Cette abondance de paquets s'accompagne cependant de quelques effets de bords. Tout d'abord, une partie importante des commits sont effectués de manière automatique, car il n'est plus possible de maintenir à jour et *à la main* les paquets présents sur nixpkgs. L'une des raisons est une implication plus faible des mainteneurs ayant ajouté un paquet une fois ce paquet effectivement intégré (et je me place dans cette catégorie). Cette abondance de paquets est aussi à mettre en lien avec un nombre de tickets important: actuellement, prêt de de 5 616 tickets sont ouverts sur GitHub, et la tendance ne semble pas être à la baisse. -->
<p>I have been a user of Nix (a “reproducible” package manager) and NixOS (the Linux distribution based on this package manager) for almost two years. I use it in a personal and professional context. In this article I will focus on the “pain points” in <em>my</em> use of Nix and NixOS. While there are many positives, the NixOS <em>experience</em> is far from being a smooth ride. I still mostly enjoy using Nix and NixOS, and this article is not about blaming anyone. I’m also a part of the problem, as I could probably participate more actively in the project.</p>
<h2 id="poor-documentation">Poor documentation<a class="headerlink" href="#poor-documentation" title="Permanent link">¶</a></h2>
<p>The documentation of Nix and NixOS is rather poor. To understand how a service or an option works, it is very often necessary to read the source code (`.nix’ files) because there are no explanations in the manual, or the explanations are not very comprehensible.</p>
<p>On this point, the use of GitHub to host project repositories makes this search sometimes difficult. For example, a search on the keyword <a href="https://github.com/NixOS/nixpkgs/search?q=%22pass-wayland%22">“pass-wayland”</a> should return a result in the “Code” tab, but it does not, because Github does not index the entire repository (you can check that it is present by using your browser search feature on the <a href="https://raw.githubusercontent.com/NixOS/nixpkgs/master/pkgs/top-level/all-packages.nix">all-packages.nix</a> file)</p>
<p>The Nix / NixOS <a href="https://nixos.wiki/">wiki</a> is rarely up to date. It mixes information related to specific versions of nixpkgs (e.g. <code>22.05</code>, <code>unstable</code>, …) without necessarily specifying which version it is. As it is not an “official” resource, its pages contain many references to the use of <em>third party</em> tools (such as the <em>home-manager</em> program or the <em>cachix</em> service) or non-stable features (such as <em>flakes</em>). Specific configurations are posted directly to the wiki (e.g. <a href="https://web.archive.org/web/20220617040332/https://nixos.wiki/wiki/Sway">https://nixos.wiki/wiki/Sway</a>) without any explanation of the choices made or their specificity, which the declarative aspect of the NixOS configuration tends to encourage.</p>
<h2 id="a-porous-evaluation">A porous evaluation<a class="headerlink" href="#a-porous-evaluation" title="Permanent link">¶</a></h2>
<p>The reproducibility of NixOS / Nix / Nixpkgs is very perfectible. One might think that by default NixOS is ‘reproducible’ (for some definition of reproducible). This is not really the case: two machines that have the same configuration files (<code>/etc/nixos/configuration.nix</code>) can differ widely due to dependency on other configuration files such as <code>~/.config/nixpkgs/config.nix</code>, the ability to change Nix’s behaviour using <a href="https://www.tweag.io/blog/2020-05-25-flakes/">environment variables, command line arguments</a> or even due to using different versions of Nix.</p>
<p>Since the Nixpkgs repository (which contains all the recipes related to the packages present in NixOS) is different from the Nix repository (which contains the source code of the Nix package manager), using a specific commit of Nixpkgs is not enough, it is also necessary to pay attention to the version of Nix used, or else <a href="https://github.com/NixOS/nix/issues/4859">regressions</a> might appear. From this point of view, Guix has a better approach in my opinion, <a href="https://github.com/guix-mirror/guix">a single repository</a> being used for the package manager and the package “recipes”.</p>
<h2 id="fragile-sources">Fragile sources<a class="headerlink" href="#fragile-sources" title="Permanent link">¶</a></h2>
<p>The reproducibility of NixOS / Nix is also only assured if the sources used remain truly accessible. A <a href="https://github.com/NixOS/nixpkgs/issues/187314">recent example</a> underlines the fragility of these sources, and the fragility of Nix which <a href="https://github.com/NixOS/nixpkgs/issues/53653">does not</a> exploit solutions such as <a href="https://www.softwareheritage.org/">Software Heritage</a> (where Guix does <a href="https://guix.gnu.org/blog/2019/connecting-reproducible-deployment-to-a-long-term-source-code-archive/">for at least three years</a>). This means, in a scientific context for example, the user, that is to say me, still has to care for source preservation if they wants to be sure five or ten years after they developed their code and used nix, it still runs.</p>
<h2 id="no-binary-reproducibility">No binary reproducibility<a class="headerlink" href="#no-binary-reproducibility" title="Permanent link">¶</a></h2>
<p>One of the problems with Nix / NixOS / Nixpkgs regarding the backup of these sources is simply the discovery of the sources to archive. Indeed, it is not possible to easily extract the set of dependencies (e.g. URLs used in the recipes of Nixpkgs packages) to archive them, as a certain number of these URLs are only “computed” at evaluation time, which requires to evaluate the whole Nixpkgs set, in all its possible configurations, to make sure that one is actually archiving what needs to be archived (part of this work is <a href="https://nix-community.github.io/nixpkgs-swh/">currently done by Hydra</a>, but unfortunately <a href="https://github.com/nix-community/nixpkgs-swh/issues/5">broken</a>). And that’s without even mentioning <em>Fixed Output Derivation</em>. It should be remembered that the reproducibility of Nix / NixOS / Nixpkgs is only a reproducibility of the sources: if the sources change, one is warned, but it is not a question of the reproducibility of the binaries (which can change at each build).</p>
<p>This <em>binary</em> reproducibility of Nix / NixOS / Nixpkgs is indeed not really tested, at least not systematically. The website <a href="https://r13y.com/">“Is NixOS Reproducible?”</a> points out that the NixOS ISO is 99.77% reproducible, but this is a check on a tiny percentage, less than 2%, of all packages. Again, Guix is much better with stats on <a href="http://archive.today/2022.12.26-133826/http://data.guix.gnu.org/repository/1/branch/master/latest-processed-revision/package-reproducibility">all packages in the repository</a>. And even more classical distributions such as <a href="https://archlinux.org/">Archlinux</a> or <a href="https://www.debian.org/">Debian</a> are better at this than Nix / NixOS / Nixpkgs ! As of now :</p>
<ul>
<li><a href="https://reproducible.archlinux.org/">Archlinux is <s>78% reproducible</s> between 86% and 90% reproducible</a> on amd64 packages (Thanks Foxboron for <a href="https://news.ycombinator.com/item?id=34127581">the correction</a>);</li>
<li><a href="https://tests.reproducible-builds.org/debian/reproducible.html">Debian is 95.7% reproducible</a> on amd64 packages ;</li>
<li>Both distribution actually test binary reproducibility, and offer good dashboards to follow the reproducibility of the packages.</li>
</ul>
<h2 id="managing-state-could-be-easier">Managing state could be easier<a class="headerlink" href="#managing-state-could-be-easier" title="Permanent link">¶</a></h2>
<p>To handle « state », e.g. data that is not software but which is linked to certain software versions, e.g., postgresql data, NixOS uses the <code>system.stateVersion</code> option which specifies how compatible is the state with software versions. For example, for postgresql, the package version depends on <code>system.stateVersion</code>, unless overwritten manually :</p>
<div class="highlight"><pre><span></span><code> mkDefault (if versionAtLeast config.system.stateVersion "22.05" then pkgs.postgresql_14
else if versionAtLeast config.system.stateVersion "21.11" then pkgs.postgresql_13
else if versionAtLeast config.system.stateVersion "20.03" then pkgs.postgresql_11
else if versionAtLeast config.system.stateVersion "17.09" then mkThrow "9_6"
else mkThrow "9_5");
</code></pre></div>
<p>Because any module can depend on this stateVersion, this means updating between different stateVersions is harder than it should be, in an ideal world. The <a href="https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion">NixOS FAQ</a> states (haha) you can update <code>system.stateVersion</code> when :</p>
<ol>
<li>You have read all release notes starting from your stateVersion.</li>
<li>You have verified all instances of stateVersion in the code in <code><nixpkgs/nixos></code>.</li>
<li>You have made all manual interventions as required by the changes previously inventoried.</li>
</ol>
<p>While reading release notes is ok, verifying the source code of <code><nixpkgs/nixos></code>, especially when the Github Search is broken, is less ok. Currently, there is also no policy on how long a given <code>system.stateVersion</code> should be supported. This seems harder than it should be.</p>
<h2 id="nix-and-nixos-its-all-or-nothing">Nix and NixOS: it’s all or nothing<a class="headerlink" href="#nix-and-nixos-its-all-or-nothing" title="Permanent link">¶</a></h2>
<p>When we use NixOS, and we want to use a package that is not available under NixOS / Nixpkgs (which happens quite often), we have only one choice: pack it into NixOS. And, to be clear, by « pack it into NixOS », I mean writing a derivation for the package, whether it uses <code>buildFHSEnv</code> or not. It is generally <a href="https://nixos.wiki/wiki/Packaging/Binaries">not possible to take a shortcut</a> and use precompiled binaries, which means that it is not possible to work <em>with constraints</em> (such as <em>time constraints</em>) on Nix / NixOS, unless you are a motivated enough user to sometimes package several levels of dependencies.</p>
<p>To give an example, the <a href="https://pypi.org/project/swh.core/">project you want to package</a> might depend on <a href="https://github.com/ClearcodeHQ/pytest-postgresql">pytest-postgresql</a> or <a href="https://github.com/sloria/aiohttp_utils">aiohttp-utils</a>, which are not packaged, and which depend in turn on <a href="https://github.com/ClearcodeHQ/mirakuru">mirakuru</a> and <a href="https://github.com/sloria/webtest-aiohttp">webtest-aiohttp</a>, which are not packaged.</p>
<p>Packaging all this tends to take time. And, of course, because Nix or NixOS are radically different from more classical package management, you can’t really mix them together in a single project and expect to have a good user experience. Using only NixOS is thus not tenable, for me: I need to have access to a second machine, under a more classical distribution. That would also be true on Guix System.</p>
<h2 id="nix-tool-fatigue">Nix* « Tool Fatigue »<a class="headerlink" href="#nix-tool-fatigue" title="Permanent link">¶</a></h2>
<p><em>I originally didn’t include this section in this article, so if you have been here before and you don’t remember seeing this, it’s normal.</em></p>
<p>Finally, and probably one of the least pleasant parts of working with Nix*, is what I (and probably others) call « tool fatigue ». This is not a problem limited to Nix*, but Nix* is particularly affected.</p>
<p>I put behind this expression the bazillion of tools built around Nix*: tools to manage secrets in NixOS, tools to deploy NixOS machines, frameworks to package the dependencies of certain languages (e.g. python or rust) in Nix, opinionated tools for the management of development environments… tools that are not really « endorsed » by Nix and NixOS, and are not « official ». As someone told me once on the Nix matrix room, « “official” means a lot less than you seem to think. », and I think that’s a problem, because there is no incentive for the « community » (whatever its form) to work <em>together</em> on a specific piece of software to make it better, which would help with e.g. documentation, integration, and so on. And because the Nix* ecosystem is moving so fast, you may have to « bet » on the best tools to use because you have not many guarantees with regards to their longevity.</p>
<p>For example, it has become a kind of running joke in the Nix* world that there are more deployments tools than deployment tools users. Yes, you have <a href="https://github.com/NixOS/nixops">NixOps</a> that is the kind of official tool (as in « living under the NixOS namespace on Github ») to deploy configuration to possibly remote machines, but it has not seen a stable release in more than three and half years. Instead, you get new deployment tools every year, which is nice, in a way, because it means the community is active, but is less nice because a newcomer has too many choices to choose from.</p>
<p>There is no « standard », safe answer to the question « what do I use to manage and deploy NixOS configurations », because NixOps is lagging behind because we’re in a state where mostly everybody use <a href="https://nixos.wiki/wiki/Flakes">flakes, which are unstable</a>, but the NixOps <a href="https://hydra.nixos.org/build/115931128/download/1/manual/manual.html">does not mention them a single time</a>. Instead, you can deploy NixOS configurations with tools such as <a href="https://github.com/zhaofengli/colmena">colmena</a>, <a href="https://github.com/serokell/deploy-rs">deploy-rs</a>, <a href="https://github.com/DBCDK/morph">morph</a>, <a href="https://github.com/Infinisil/nixus">nixus</a>, <a href="https://github.com/awakesecurity/nix-deploy">nix-deploy</a>, <a href="https://github.com/rapenne-s/bento">bento</a>, <a href="https://cgit.krebsco.de/krops/about/">krops</a>, <a href="https://github.com/arnarg/pushnix">pushnix</a>, …</p>
<p>And, it’s the same with language dependencies : to package rust in your development environment, you could use <a href="https://devenv.sh/">devenv</a>, <a href="https://github.com/oxalica/rust-overlay">rust-overlay</a>, <a href="https://github.com/nix-community/fenix">fenix</a>, <a href="https://github.com/mozilla/nixpkgs-mozilla">nixpkgs-mozilla</a>, <a href="https://github.com/nix-community/dream2nix/blob/main/docs/src/subsystems/rust.md">dream2nix</a>, <a href="https://github.com/cargo2nix/cargo2nix">cargo2nix</a>, <a href="https://nixos.wiki/wiki/Rust#Packaging_Rust_projects_with_nix">and so on</a>…</p>
<p>It feels, to me, the Nix* community lacks a bit of focus on the ways of achieving things, and, as usual, this problem is difficult because it is not a <em>technical</em> one but a <em>human</em> one.</p>Accès aux données à caractère personnel chez le FAI Sosh / Orange2022-07-02T00:00:00+02:002022-07-02T00:00:00+02:00Rémy Grünblatttag:remy.grunblatt.org,2022-07-02:/acces-aux-donnees-a-caractere-personnel-chez-le-fai-sosh-orange.html<p>L’<a href="https://www.cnil.fr/fr/reglement-europeen-protection-donnees/chapitre3#Article15">article 15 du très célèbre Règlement Général sur la Protection des Données</a> intitulé « Droit d’accès de la personne concernée » permet à la personne concernée par un traitement de données à caractère personnel d’obtenir plusieurs informations concernant ce traitement, et, en particulier, peut demander une copie des données …</p><p>L’<a href="https://www.cnil.fr/fr/reglement-europeen-protection-donnees/chapitre3#Article15">article 15 du très célèbre Règlement Général sur la Protection des Données</a> intitulé « Droit d’accès de la personne concernée » permet à la personne concernée par un traitement de données à caractère personnel d’obtenir plusieurs informations concernant ce traitement, et, en particulier, peut demander une copie des données à caractère personnel faisant l’objet d’un traitement.</p>
<p>Le <a href="https://www.legifrance.gouv.fr/codes/id/LEGITEXT000006070987/">Code des postes et des communications électroniques</a> (mais pas uniquement) définit, en France, un ensemble de données que les opérateurs de communications électroniques doivent conserver, pour les besoins des procédures pénales, la prévention des menaces contre la sécurité publique, la sauvegarde de la sécurité nationale, contre les menaces graves, actuelles ou prévisibles, etc.</p>
<p>Dans cet article, je fais un résumé de ma demande d’accès aux données à caractère personnel me concernant chez le fournisseur d’accès à Internet <a href="https://orange.fr/">Orange</a> / <a href="https://sosh.fr">Sosh</a> (j’utiliserai Orange pour désigner les deux entités dans la suite de cet article), concernant mon abonnement à Internet Fixe et Mobile, en particulier aux données dont le <abbr title="Code des Postes et des Pommunications Électroniques">CPCE</abbr> demande la conservation.</p>
<ol>
<li><a href="#quelles-sont-les-donnees-concernees">Quelles sont les données concernées ?</a></li>
<li><a href="#echanges-avec-orange-et-la-cnil">Échanges avec Orange et la CNIL</a></li>
</ol>
<h2 id="quelles-sont-les-donnees-concernees">Quelles sont les données concernées ?<a class="headerlink" href="#quelles-sont-les-donnees-concernees" title="Permanent link">¶</a></h2>
<p><em>Avant de commencer, je souhaite rappeler que je ne suis pas juriste, et donc l’ensemble de ce qui suit est bien évidemment à prendre avec des pincettes (comme, au fond, tout ce qu’on peut lire partout). Des inexactitudes se sont probablement glissées dans cet article.</em></p>
<h3 id="contexte-legal">Contexte légal<a class="headerlink" href="#contexte-legal" title="Permanent link">¶</a></h3>
<p>Les articles <a href="https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000043887545/">L. 34-1</a> et <a href="https://www.legifrance.gouv.fr/codes/id/LEGIARTI000044231067/2022-06-24/">R10-13</a> du <a href="https://www.legifrance.gouv.fr/codes/id/LEGITEXT000006070987/"><abbr title="Code des Postes et des Pommunications Électroniques">CPCE</abbr></a> définissent respectivement le cadre général et les données spécifiques que les <abbr title="Opérateurs de Communications Électroniques">OCE</abbr> doivent conserver. Cette conservation peut avoir lieu de manière habituelle, ou sous ordre du premier ministre qui peut <em>« enjoindre par décret aux opérateurs de communications électroniques de conserver, pour une durée d’un an, certaines catégories de données de trafic […] et de données de localisation »</em>.</p>
<p>Cet ordre du premier ministre prend la forme du <a href="https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000044228976">décret n° 2021-1363</a>, qui « enjoint » aux « aux opérateurs de communications électroniques » mais aussi aux « personnes mentionnées aux 1 et 2 du I de l’article 6 de la loi du 21 juin 2004 » (c’est-à-dire la <a href="https://www.legifrance.gouv.fr/loda/id/JORFTEXT000000801164/2022-06-24/"><abbr title="Loi pour la confiance dans l'économie numérique">LCEN</abbr></a>) de conserver les données de trafic et de localisation énumérées au V de l’article R. 10-13 du <abbr title="Code des Postes et des Pommunications Électroniques">CPCE</abbr> et à l’article 6 du <a href="https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000044228912">décret n° 2021-1362</a>.</p>
<p>On remarque que des <abbr title="Opérateurs de Communications Électroniques">OCE</abbr> comme Orange sont doublement couverts, à travers la dénomination d’<abbr title="Opérateurs de Communications Électroniques">OCE</abbr> mais aussi à travers le I.1 de l’article 6 de la <abbr title="Loi pour la confiance dans l'économie numérique">LCEN</abbr>, qui concerne <em>« Les personnes dont l’activité est d’offrir un accès à des services de communication au public en ligne »</em>. Notons que le I.2 de l’article 6 de la <abbr title="Loi pour la confiance dans l'économie numérique">LCEN</abbr> s’applique lui aux <em>« personnes physiques ou morales qui assurent, même à titre gratuit, pour mise à disposition du public par des services de communication au public en ligne, le stockage de signaux, d’écrits, d’images, de sons ou de messages de toute nature fournis par des destinataires de ces services »</em>. En bref: les hébergeurs de sites webs, les réseaux sociaux, les messageries instantanées, fournisseurs d’e-mails, etc.</p>
<h3 id="quelle-lecture-pour-le-r-10-12">Quelle lecture pour le R. 10-12 ?<a class="headerlink" href="#quelle-lecture-pour-le-r-10-12" title="Permanent link">¶</a></h3>
<p>L’article <a href="https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000044231061/2022-06-24/">R. 10-12</a> du <abbr title="Code des Postes et des Pommunications Électroniques">CPCE</abbr> explique: </p>
<blockquote>
<p>« Les données de trafic et de localisation, mentionnées aux IV et V de l’article R. 10-13 et à l’article R. 10-14, s’entendent des informations rendues disponibles par les procédés de communication électronique, susceptibles d’être enregistrées par l’opérateur à l’occasion des communications électroniques dont il assure la transmission. »</p>
</blockquote>
<p>Ma lecture de cet article est la suivante: les données de trafic et de localisation sont toute donnée (ou méta-donnée) qu’il est techniquement possible d’enregistrer en tant qu’opérateur (c’est-à-dire, <em>disponibles</em>, <em>observables</em>), qu’elles soient enregistrées ou non.</p>
<div class="admonition red">
<h3 id="mise-a-jour-du-06072023"><span class="red-9-fg">Mise à jour du 06/07/2023</span><a class="headerlink" href="#mise-a-jour-du-06072023" title="Permanent link">¶</a></h3>
<p><a href="https://www.conseil-etat.fr/fr/arianeweb/CE/decision/2023-06-30/459724">Une décision du Conseil d’État</a> du 30 juin 2023 faisant suite à une requête de Free / Free mobile / Scaleway, vient infirmer cette lecture :</p>
<blockquote>
<p>Si, s’agissant des dispositions issues du décret n° 2021-1361 codifiées dans le code des postes et des communications électroniques, citées au point 6, l’article R. 10-12, qui définit les données de trafic et de localisation au sens des IV et V de l’article R. 10-13, indique qu’il s’agit ” des informations rendues disponibles par les procédés de communication électronique, susceptibles d’être enregistrées par l’opérateur à l’occasion des communications électroniques dont il assure la transmission “, <strong>cette précision ne saurait être interprétée comme imposant aux opérateurs de communications électroniques de conserver des données autres que celles qu’ils sont amenés à collecter dans le cadre de leur activité</strong> en ce qui concerne celles mentionnées aux I, II et III du même article R. 10-13.</p>
</blockquote>
</div>
<h3 id="le-cas-complexe-des-donnees-de-trafic-et-de-localisation">Le cas complexe des données de trafic et de localisation<a class="headerlink" href="#le-cas-complexe-des-donnees-de-trafic-et-de-localisation" title="Permanent link">¶</a></h3>
<p><img alt=""Map data from OpenStreetMap"" src="/images/Paris_Neon.webp" title="Map data from OpenStreetMap" /></p>
<p>Les données techniques qu’il faut conserver sur injonction du premier ministre posent un problème. En effet, l’<a href="https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000025622766/">article R10-13</a>, au V., contient:</p>
<blockquote>
<p>« V.-Les données de trafic et de localisation mentionnées au III de l’article L. 34-1, que les opérateurs de communications électroniques sont tenus de conserver sur injonction du Premier ministre, sont :</p>
<p>1° Les caractéristiques techniques ainsi que la date, l’horaire et la durée de chaque communication ;</p>
<p>2° Les données relatives aux services complémentaires demandés ou utilisés et leurs fournisseurs ;</p>
<p>3° Les données techniques permettant d’identifier le ou les destinataires de la communication, mentionnées aux 1° à 4° du IV du présent article ;</p>
<p>4° Pour les opérations effectuées à l’aide de téléphones mobiles, les données permettant d’identifier la localisation de la communication.</span> »
</p>
</blockquote>
<p>Cependant, ces données de trafic et de localisation sont aussi mentionnées dans l’article 6 du <a href="https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000044228912">Décret n° 2021-1362</a>, qui contient: </p>
<blockquote>
<p>« Les catégories de données de trafic et de localisation mentionnées au III de l’article L. 34-1 du Code des postes et des communications électroniques, que les personnes mentionnées à l’article 1er sont tenues de conserver pour une durée d’un an en cas d’injonction du Premier ministre, sont les suivantes :</p>
<p>1° Pour les personnes mentionnées au 1 du I de l’article 6 de la loi du 21 juin 2004 susvisée et pour chaque connexion de leurs abonnés :</p>
<p>a) Les dates et heure de début et de fin de la connexion ;</p>
<p>b) Les caractéristiques de la ligne de l’abonné ;</p>
<p>2° Pour les personnes mentionnées au 2 du I de l’article 6 de la loi du 21 juin 2004 susvisée et pour chaque opération de création d’un contenu :</p>
<p>a) L’identifiant attribué par le système d’information au contenu, objet de l’opération ;</p>
<p>b) La nature de l’opération ;</p>
<p>c) Les date et heure de l’opération ;</p>
<p>d) L’identifiant utilisé par l’auteur de l’opération lorsque celui-ci l’a fourni.</p>
<p>Le délai mentionné au premier alinéa du présent article court à compter du jour de la connexion ou de la création d’un contenu, pour chaque opération contribuant à cette création. »</p>
</blockquote>
<p>Les données de trafic et de localisation qu’il faut conserver sont donc différentes selon que l’on soit un <abbr title="Opérateurs de Communications Électroniques">OCE</abbr> (article R10-13) ou que l’on soit concerné par le 1 et 2 du I de l’article 6 de la <abbr title="Loi pour la confiance dans l'économie numérique">LCEN</abbr>, c’est-à-dire que l’on soit des <em>« personnes dont l’activité est d’offrir un accès à des services de communication au public en ligne »</em> ou des <em>« personnes physiques ou morales qui assurent, même à titre gratuit, pour mise à disposition du public par des services de communication au public en ligne, le stockage de signaux, d’écrits, d’images, de sons ou de messages de toute nature »</em>.</p>
<p>Cependant, le L. 34-1 affirme que les <abbr title="Opérateurs de Communications Électroniques">OCE</abbr> recouvrent les personnes dont l’activité est d’offrir un accès à des services de communication au public en ligne:</p>
<blockquote>
<p><em>« Les opérateurs de communications électroniques, et notamment les personnes dont l’activité est d’offrir un accès à des services de communication au public en ligne »</em></p>
</blockquote>
<p>Aussi, par son article 8, le décret n° 2021-1362 contient aussi:</p>
<blockquote>
<p>« <em>Les données mentionnées aux articles 2 à 6 ne doivent être conservées que dans la mesure où elles sont collectées par les personnes mentionnées aux 1 et 2 du I de l’article 6 de la loi du 21 juin 2004 susvisée lorsqu’elles assurent la mise en œuvre des services de communication au public en ligne.</em> ».</p>
</blockquote>
<p>La conservation des informations mentionnées à l’article 6 du décret n° 2021-1362 ne serait donc obligatoire qu’au cas où ces mesures sont effectivement collectées <strike>là où l’article R10-13 ne mentionne pas ce caractère <em>conditionnel</em> de la collecte (avec la lecture de l’article R. 10-12 précédemment mentionnée).</strike> (mise à jour du 06/07/2023, voir <a href="#mise-a-jour-du-06072023">encadré rouge ci-dessus</a>).</p>
<h3 id="une-confusion-loin-detre-nouvelle">Une confusion loin d’être nouvelle<a class="headerlink" href="#une-confusion-loin-detre-nouvelle" title="Permanent link">¶</a></h3>
<p><img alt=""Image under the CC-BY 3.0 license by Ragesoss (via Wikimedia)"" src="/images/Wall.webp" title="Image under the CC-BY 3.0 license by Ragesoss (via Wikimedia)" /></p>
<p>Cette confusion autour de ce qu’il est nécessaire d’enregistrer pour un FAI (par exemple) rejoint l’observation faite par la CNIL dans sa <a href="https://www.legifrance.gouv.fr/cnil/id/CNILTEXT000017652102/">délibération 2005-254 du 10 novembre 2005</a>, à propos du futur R. 10-13:</p>
<blockquote>
<p>« Cette rédaction ne permet pas aux opérateurs de mesurer précisément l’obligation qui leur est faite de conserver certaines données en dérogation au principe général d’effacement et d’anonymisation posé par la loi. Cette incertitude juridique est d’autant plus préjudiciable que le non-respect de cette obligation est sanctionnée pénalement (article L. 39-3 du <abbr title="Code des Postes et des Pommunications Électroniques">CPCE</abbr>). De plus, ce choix ne permet pas à la Commission de s’assurer que ces données sont conformes aux exigences du V de l’article L. 34-1 - à savoir l’interdiction que ces données portent sur le contenu des correspondances échangées ou des informations consultées sous quelque forme que ce soit - ni d’effectuer le contrôle de proportionnalité posé par l’article 6 de la loi du 6 janvier 1978 modifiée. »</p>
</blockquote>
<p>De même, en 2007, dans sa <a href="https://www.legifrance.gouv.fr/cnil/id/CNILTEXT000023654277">délibération 2007-391 du 20 décembre 2007</a>, la CNIL soulignait la difficulté de déterminer sous quel statut un FAI était soumis à l’obligation de rétention des données:</p>
<blockquote>
<p>« De même, la Commission relève que les FAI sont soumis à une double obligation de rétention des données d’une part, au titre du II de l’article 6 de la <abbr title="Loi pour la confiance dans l'économie numérique">LCEN</abbr>, d’autre part, au titre de l’article L. 34-1 du Code des postes et des communications électroniques en tant qu’opérateurs de communications électroniques.</p>
<p>Enfin, la Commission observe que tant les textes législatifs que les débats parlementaires ou la jurisprudence ne permettent pas d’établir une définition claire des catégories de personnes soumises à l’obligation de rétention des données prévue par la <abbr title="Loi pour la confiance dans l'économie numérique">LCEN</abbr> et le Code des postes et des communications électroniques. Il résulte de cette situation une insécurité juridique préjudiciable à la protection de la vie privée et des données à caractère personnel des internautes. »</p>
</blockquote>
<h3 id="recapitulatif">Récapitulatif<a class="headerlink" href="#recapitulatif" title="Permanent link">¶</a></h3>
<p>On peut donc identifier différentes grandes familles de données concernées par les divers articles, lois, décrets susmentionnés, qu’un <abbr title="Opérateurs de Communications Électroniques">OCE</abbr> comme Orange devrait collecter, si l’on se place du point de vue de l’article R10-13:</p>
<ol>
<li>
<p>Les données liées à l’identité de la personne physique agissant en son nom ou pour le compte d’une personne morale:</p>
<ul>
<li>nom</li>
<li>prénom</li>
<li>raison sociale</li>
<li>date et lieu de naissance</li>
<li>adresse postale</li>
<li>adresse de courrier électronique</li>
<li>numéro de téléphone</li>
</ul>
</li>
<li>
<p>Les données liées à la <em>numérisation</em> de l’identité de cette personne:</p>
<ul>
<li>identifiant</li>
<li>pseudonyme</li>
<li>données de vérifications de mots de passes (e.g. phrases secrètes)</li>
</ul>
</li>
<li>
<p>Les données permettant de retracer l’argent:</p>
<ul>
<li>type de paiement (virement, chèque, CB, liquide, …)</li>
<li>référence du paiement (numéro de virement, de chèque, ID de transaction…)</li>
<li>montant du paiement</li>
<li>en cas de transaction physique, date, heure et lieu</li>
</ul>
</li>
<li>
<p>Les données techniques liées à l’activité sur le medium de communication:</p>
<ul>
<li>adresse IP / port attribuée à la source de la connexion</li>
<li>numéro d’identifiant de l’utilisateur</li>
<li>numéro d’identification du terminal</li>
<li>numéro de téléphone à l’origine de la communication</li>
</ul>
</li>
<li>
<p>Les données techniques qu’il faut conserver sur injonction du premier ministre (et injonction il y a):</p>
<ul>
<li>caractéristiques techniques, date, horaire et durée de chaque communication</li>
<li>données relatives aux services complémentaires demandés ou utilisés et leurs fournisseurs (e.g. plus d’enveloppe data, une option internationale, la télé)</li>
<li>données techniques permettant d’identifier le ou les destinataires de la communication (c’est-à-dire les données mentionnées au 4.)</li>
<li>pour les opérations effectuées à l’aide de téléphones mobiles, les données permettant d’identifier la localisation de la communication</li>
</ul>
</li>
</ol>
<p>Si l’on se place cependant du point de vue du décret n° 2021-1362, d’une part ces données ne doivent être conservées « que dans la mesure où elles sont collectées » (sous-entendu: cela n’est pas nécessairement le cas), et le point numéro 5. de cette liste ne contient plus que les données techniques suivantes:</p>
<ul>
<li>dates et heure de début et de fin de la connexion</li>
<li>caractéristiques de la ligne de l’abonné</li>
</ul>
<h2 id="echanges-avec-orange-et-la-cnil">Échanges avec Orange et la CNIL<a class="headerlink" href="#echanges-avec-orange-et-la-cnil" title="Permanent link">¶</a></h2>
<p><img alt="" src="/images/CNIL.webp" /></p>
<p>Maintenant que le cadre légal est plus clair (ou pas), concentrons-nous sur ma demande à Orange. Celle-ci a été effectuée en plusieurs étapes.</p>
<h3 id="genese-une-demande-a-la-cnil">Genèse : Une demande à la CNIL<a class="headerlink" href="#genese-une-demande-a-la-cnil" title="Permanent link">¶</a></h3>
<p>L’origine de cet article est liée à la demande de Benjamin Somers à la CNIL détaillée dans le numéro 2 du mensuel de l’association FedeRez, intitulée « <em>Des nouvelles de la CNIL ou comment ennuyer votre FAI</em> ». À la question « Les logs de connexion font-ils partie des données que je dois transmettre à un client qui exerce son droit d’accès aux données que je collecte ? » (c’est un résumé, il y a eu d’autres échanges), la CNIL répond (la mise en forme venant de la CNIL):</p>
<blockquote>
<p>[…]</p>
<p>Au vu des éléments que vous nous avez communiqué, je vous
confirme d’une part que, toute personne physique a le droit
d’obtenir du responsable d’un fichier <strong>l’accès à l’ensemble des
données la concernant</strong> ainsi que l’origine de celles-ci (article
15 du Règlement général sur la protection des données - <abbr title="Règlement Général sur la Protection des Données">RGPD</abbr>).</p>
<p>[…]</p>
</blockquote>
<h3 id="premier-round">Premier Round<a class="headerlink" href="#premier-round" title="Permanent link">¶</a></h3>
<h4 id="la-demande-a-orange-22-fevrier-2022">La demande à Orange – 22 février 2022<a class="headerlink" href="#la-demande-a-orange-22-fevrier-2022" title="Permanent link">¶</a></h4>
<p>La demande complète est disponible <a href="/orange/ANON_Orange_Demande_0.pdf">à cette adresse</a>; l’essence de la demande tient en ces lignes:</p>
<blockquote>
<p>[…]</p>
<p>Conformément à l’article 15 du <abbr title="Règlement Général sur la Protection des Données">RGPD</abbr>, veuillez me fournir toutes les données personnelles me concernant, le but du traitement, ainsi que pourquoi et comment vous collectez ces données.</p>
<p>En particulier, l’article L. 34-1 du Code des postes et communication électronique (<abbr title="Code des Postes et des Pommunications Électroniques">CPCE</abbr>) imposant une obligation de conservation pendant un an des données de connexion (ou « données de trafic ») lorsqu’un organisme met à disposition du public un accès à Internet, ce qui est votre cas, ces données devront être intégrées à votre réponse</p>
<p>[…]</p>
</blockquote>
<p>La demande a été effectuée par courrier recommandé (on est jamais trop prudent).</p>
<h4 id="une-premiere-reponse-dorange-15-mars-2022">Une première réponse d’Orange – 15 mars 2022<a class="headerlink" href="#une-premiere-reponse-dorange-15-mars-2022" title="Permanent link">¶</a></h4>
<blockquote>
<p>Bonjour,</p>
<p>Suite à votre demande, vous trouverez ci-joint l’ensemble des données à caractère personnel vous concernant. Ces données sont traitées par Orange conformément à la Politique de protection des données que vous pouvez retrouver sur orange.fr</p>
<p>En ce qui concerne les données de connexion, les données relatives à la navigation internet, notamment les sites et/ou IP visitées ne sont pas collectées et traitées par Orange après l’acheminement du trafic. Il ne nous est donc pas possible de répondre favorablement à votre demande sur ce point précis .</p>
<p>Afin de sécuriser vos données personnelles, un mot de passe a été envoyé sur votre mobile de contact. Saisissez-le pour lire les fichiers de votre dossier informatique.</p>
<p>Un lexique contenant les codes et abréviations utilisés dans les zones “commentaires” vous est fourni en complément pour vous aider à prendre connaissance de votre dossier informatique.</p>
<p>Merci de votre confiance.</p>
<p>Le service clients Orange</p>
</blockquote>
<p>La réponse d’Orange était accompagnée d’une archive 7-zip chiffrée avec un mot de passe reçu par SMS, et de deux fichiers:</p>
<ul>
<li>Un <a href="/orange/ANON_LEXIQUE 2018V1.pdf">lexique</a></li>
<li>La <a href="/orange/ANON_Politique de protection des données - 2021.pdf">politique de protection des données</a></li>
</ul>
<p>Concernant l’archive, deux fichiers de tableur en .xlsx contenant mes données personnelles:</p>
<ul>
<li>Un <a href="/orange/ANON_Copie de Grunblatt.xlsx">premier fichier concernant mon abonnement mobile</a></li>
<li>Un <a href="/orange/ANON_Grünblatt Rémy.xlsx">second fichier concernant mon abonnement fixe</a></li>
</ul>
<p><em>Note</em>: Ces fichiers ne sont pas strictement ceux envoyés par Orange, certaines données sensibles (IMEI, …) ont été enlevées par mes soins et remplacées par un placeholder.</p>
<h4 id="des-meta-donnees-non-nettoyees">Des méta-données non nettoyées<a class="headerlink" href="#des-meta-donnees-non-nettoyees" title="Permanent link">¶</a></h4>
<p>La première chose que l’on peut remarquer, avant même de se plonger dans les données, c’est que les fichiers n’ont pas été nettoyés de leurs méta-données. Le lexique a été généré le 2 juillet 2018 en utilisant Microsoft® Word pour Microsoft 365 par « G****** B****** OF/DRCGP », de même que la politique de protection des données, générée le 27 janvier 2022. Le fichier de tableur concernant l’abonnement mobile a probablement été manipulé, à un moment, par un certain « G********* F****** SCO IDF », et le fichier de tableur concernant mon abonnement fixe par un certain « D***** E*** SCO NDF ». Supprimer ces méta-données représente, à mon sens, une piste d’amélioration pour Orange.</p>
<p><em>Note</em>: les méta-données ont été nettoyées avant la mise en ligne.</p>
<h4 id="des-donnees-lacunaires">Des données lacunaires<a class="headerlink" href="#des-donnees-lacunaires" title="Permanent link">¶</a></h4>
<table>
<thead>
<tr>
<th><img alt="Une partie des données de compte de mon abonnement mobile." src="/images/Informations_Client.webp" title="Une partie des données de compte de mon abonnement fixe." /></th>
</tr>
</thead>
<tbody>
<tr>
<td><em>Une partie des données de compte de mon abonnement mobile. Je suis identifié comme « bon payeur » malgré quelques retards de paiement de ma part (expiration de CB, …).</em></td>
</tr>
</tbody>
</table>
<p>Sans aller dans le détail des fichiers, ce qu’on remarque, c’est l’absence de certaines données mentionnées dans le <a href="#recapitulatif">récapitulatif</a> ci-dessus. Les données liées à mon identité, mon moyen de paiement, mon contrat sont bien présentes, de même que l’adresse IPv4 publique de ma box concernant mon abonnement fixe ( 83.202.119.89 ) ou encore son adresse MAC (<em>numéro d’identification du terminal</em>).</p>
<table>
<thead>
<tr>
<th><img alt="Une partie des données techniques de mon abonnement mobile." src="/images/Données_Techniques.webp" title="Une partie des données techniques de mon abonnement mobile." /></th>
</tr>
</thead>
<tbody>
<tr>
<td><em>Une partie des données techniques de compte de mon abonnement mobile. Deux IMEI sont identifiés car j’ai probablement utilisé les deux slots de carte SIM de mon mobile.</em></td>
</tr>
</tbody>
</table>
<p>Cependant, pas de traces de ports, pas de trace de mon adresse IPv6.</p>
<p>Concernant mon abonnement mobile, pas de traces de données de localisations, et pas de traces de données techniques de type IP ou ports (il y a cependant les IMEI de mes deux emplacements SIM de mon téléphone). Sosh utilisant du CGNAT, et mon adresse IPv4 étant « dynamique », ces informations sont très probablement stockées par Sosh dans un format ou un autre, car dans le cas contraire, impossible de remonter jusqu’à mon identité réelle depuis un triplet (IPv4, port source, horaire) (qui serait par exemple fourni par un hébergeur à qui un juge aurait demandé « Oui, là, le contenu pas gentil, qui l’a posté? »).</p>
<p>Même si l’on considère la version <em>la moins forte</em> du cadre légal (celle du décret n° 2021-1362), il manque des données dont on peut confirmer qu’elles sont collectées par Orange car elles apparaissent par exemple dans ma facture ou dans mon espace abonné en ligne, e.g. : </p>
<ul>
<li>le numéro de mes correspondants</li>
<li>la durée de mes appels</li>
<li>la destination de mes appels (france métropolitaine, …)</li>
<li>le pays dans lequel je passe ces appels</li>
</ul>
<h3 id="second-round">Second Round<a class="headerlink" href="#second-round" title="Permanent link">¶</a></h3>
<h4 id="demande-a-orange-et-plainte-a-la-cnil-15-et-17-mars-2022">Demande à Orange et plainte à la CNIL – 15 et 17 mars 2022<a class="headerlink" href="#demande-a-orange-et-plainte-a-la-cnil-15-et-17-mars-2022" title="Permanent link">¶</a></h4>
<p>Compte tenu de la première réponse lacunaire d’Orange, je décide du dépôt d’une <a href="/orange/ANON_CNIL_Plainte_0.pdf">plainte à la CNIL</a> le 15 mars et sollicite Orange <a href="/orange/ANON_Orange_Demande_1.pdf">une seconde fois</a>, en mentionnant cette plainte à la CNIL, le 17 mars, toujours par courrier recommandé.</p>
<h4 id="reponse-de-la-cnil-14-avril-2022">Réponse de la CNIL – 14 avril 2022<a class="headerlink" href="#reponse-de-la-cnil-14-avril-2022" title="Permanent link">¶</a></h4>
<blockquote>
<p>[…]</p>
<p>Vous avez saisi la CNIL d’une réclamation à l’encontre d’Orange relative aux difficultés que vous rencontrez dans l’exercice de votre demande de droit d’accès.</p>
<p>Nous vous informons que nous sommes intervenus auprès de la société Orange pour l’interroger sur les faits que vous avez portés à notre connaissance.</p>
<p>[…]</p>
</blockquote>
<h4 id="reponse-dorange-19-avril-2022">Réponse d’Orange – 19 avril 2022<a class="headerlink" href="#reponse-dorange-19-avril-2022" title="Permanent link">¶</a></h4>
<blockquote>
<p>[…]</p>
<p>Nous revenons vers vous suite à votre courrier de réclamation reçu le 22 mars dernier et votre saisine de la CNIL sur le même sujet.</p>
<p>Nous vous informons que la récupération des informations techniques est en cours par nos équipes techniques afin de vous les transmettre au plus vite.</p>
<p>[…]</p>
</blockquote>
<p>De ce courrier, je déduis que l’opération de récupération de données n’a probablement pas été automatisée, au choix, par manque d’intérêt économique, ou tout simplement car je suis le premier à effectuer une telle demande (ce qui expliquerait pourquoi ces données ne sont pas sorties par défaut dans les données présentées par Orange).</p>
<p>Une première question est soulevée: les opérateurs français ont-ils identifié quelles données à caractère ils traitent effectivement ?</p>
<h4 id="reponse-dorange-6-mai-2022">Réponse d’Orange – 6 mai 2022<a class="headerlink" href="#reponse-dorange-6-mai-2022" title="Permanent link">¶</a></h4>
<blockquote>
<p>[…]</p>
<p>Nous faisons suite à votre courrier du 17 mars dernier, arrivé dans nos services le 22 mars, et vous prions de bien vouloir trouver ci-joint les fichiers correspondant aux informations demandées (Voix, SMS, MMS) pour l’année écoulée. Concernant les traces liées à l’internet, Orange dispose uniquement de l’historique sur 6 mois.</p>
<p>Pour une parfaite lecture, chaque fichier comprend un onglet destiné à présenter un lexique des termes utilisés.</p>
<p>Afin de sécuriser vos données personnelles, un mot de passe a été envoyé sur votre mobile de contact. Saisissez-le pour lire les fichiers de votre dossier informatique.</p>
<p>[…]</p>
</blockquote>
<p>Cette fois-ci, plus de données ! Toujours sous la forme d’une archive chiffrée, je récupère cette fois-ci quatres fichiers:</p>
<ul>
<li>Deux fichiers concernant mon abonnement mobile, <a href="/orange/ANON_Grunblatt Remy DATA_Mob29042022.xlsx">Grunblatt Remy DATA_Mob29042022.xlsx</a> et <a href="/orange/ANON_Grunblatt Remy MOB Vx SMS MMS .xlsx">Grunblatt Remy MOB Vx SMS MMS .xlsx</a></li>
<li>Deux fichiers concernant mon abonnement fixe, <a href="/orange/ANON_Grunblatt Remy DATA_FTI.xlsx">Grunblatt Remy DATA_FTI.xlsx</a> et <a href="/orange/ANON_Grunblatt Remy LIGNE_FIXE_IP.xlsx">Grunblatt Remy LIGNE_FIXE_IP.xlsx</a></li>
</ul>
<p>À nouveau, les méta-données révèlent des informations sur les modifications, avec cette fois-ci l’apparition d’une nouvelle identité, un certain G******* G****** DTSI/DSI.</p>
<p>J’obtiens désormais la chronologie de mes appels sortants (avec numéro de téléphone du destinataire), SMS, et données consommées de manière plutôt précise (durée, volume de données échangé en up et down), ainsi que la localisation de chaque opération lorsqu’elle est disponible, par exemple lorsque je ne suis pas en itinérance. Les appels entrants n’apparaissent pas.</p>
<h4 id="des-donnees-geographiques-de-mauvaise-qualite">Des données géographiques de mauvaise qualité<a class="headerlink" href="#des-donnees-geographiques-de-mauvaise-qualite" title="Permanent link">¶</a></h4>
<p>Les données de localisation présentes dans les fichiers d’Orange sont de mauvaise qualité. J’aurais adoré avoir des coordonnées GPS liées à chaque événement (par exemple, les coordonnées des antennes utilisées), mais seules des dénominations géographiques sont présentées: noms de villes, codes postaux. Le nom des villes n’est pas uniformisé: ces noms apparaissent parfois en capitales, parfois non, et de nombreuses typos empêchent le traitement automatique de ces données sans nettoyage. On trouve par exemple:</p>
<ul>
<li>Des caractères spéciaux: <code>╔griselles-le-Bocage</code></li>
<li>Des codes postaux erronés: le code postal de <code>MORANGIS</code> est annoncé comme étant <code>91423</code>, le code postal de Belfort est parfois <code>90002</code></li>
<li><code>Ligny-le-Châtel</code> qui devient <code>LIGNY-LE-CHÔTEL</code></li>
<li><code>Marçay</code> qui devient <code>MARÞAY</code></li>
<li><code>Vémars</code> qui devient <code>VÚMARS</code></li>
<li><code>Pliboux</code> qui devient <code>PLIBLOUX</code></li>
<li><code>Pussigny</code> qui devient <code>Pussiny</code></li>
<li><code>Paray-Vieille-Poste</code> qui devient <code>PARAY-VIELLE-POSTE</code></li>
<li>[…]</li>
</ul>
<p>Sur la carte ci-dessous, je représente les localisations (SMS, MMS, Appels, Data) telles que renvoyées par le service <a href="https://nominatim.openstreetmap.org/">Nominatim</a>, avec les données nettoyées et réparées à la main. Les points sont agrégés par localité; la couleur représente la date moyenne des événements associés à cette localité; la taille représente le nombre d’événement par localité.</p>
<p><iframe
width="100%"
height="700"
frameborder="0" style="border:0"
referrerpolicy="no-referrer-when-downgrade"
src="/orange/map.html"
allowfullscreen>
</iframe>
</p>
<p>La visualisation est assez basique, n’hésitez pas à en créer de nouvelles en utilisant mes données ! </p>
<p>Autre visualisation, la distribution des événements concernant ma ligne mobile:</p>
<p><iframe
width="100%"
height="400"
frameborder="0" style="border:0"
referrerpolicy="no-referrer-when-downgrade"
src="/orange/hours.html"
allowfullscreen>
</iframe></p>
<h4 id="toujours-aucune-trace-des-donnees-de-trafic-precises">Toujours aucune trace des données de trafic précises<a class="headerlink" href="#toujours-aucune-trace-des-donnees-de-trafic-precises" title="Permanent link">¶</a></h4>
<p>J’obtiens cette fois-ci plus de données techniques concernant ma connexion à Internet fixe, notamment, mon range IPv6 (sous la forme <code>2a01cb0402399b</code>) qui n’était auparavant pas disponible, des numéros de sessions et des horodatages de ce qui semble être le client DHCP de ma box Orange. Cependant, toujours aucune trace de ports ou de données de trafic plus précises.</p>
<p>Rappelons que le R10-13 explicite que les <em>« données techniques permettant d’identifier la source de la connexion ou celles relatives aux équipements terminaux utilisés »</em> comprennent, entre autres l’<em>« adresse IP attribuée à la source de la connexion et le port associé »</em>. La couche IP et les protocoles TCP/UDP semblent plus particulièrement concernés (du fait de la notion de port), et on peut donc s’interroger.</p>
<p>Tout d’abord, sur la notion de connexion. En effet, en toute généralité, la source d’une « connexion » d’un abonné (comme un <em>stream</em> TCP) n’est pas forcément un équipement terminal dudit abonné: n’importe qui possédant mon adresse IP peut décider de m’envoyer des données, tout en me laissant le choix d’établir une connexion avec lui si l’occasion s’en présente.</p>
<p>Ensuite, sur l’absence d’informations liées aux ports dans la réponse consolidée d’Orange. En effet, l’utilisation de CGNAT déjà mentionnée plus haut rend ces informations essentielles pour permettre l’identification de la source de la connexion, et ces informations ne sont pas présentes dans ce qu’Orange m’a présenté.</p>
<h4 id="cloture-par-la-cnil-16-mai-2022">Clôture par la CNIL - 16 mai 2022<a class="headerlink" href="#cloture-par-la-cnil-16-mai-2022" title="Permanent link">¶</a></h4>
<p>Sans nouvelles de ma part (trop occupé par les autres choses de la vie, et notamment par l’écriture de ce billet de blog), la CNIL a clôturé ma demande le 16 mai:</p>
<blockquote>
<p>Comme nous vous l’avions indiqué, nous sommes intervenus auprès d’Orange pour l’interroger sur votre demande.</p>
<p>La société Orange nous indique qu’il y aurait eu une incompréhension sur la portée de votre demande par le service en charge de son traitement.</p>
<p>Elle nous indique néanmoins que, depuis, le 6 mai dernier, le service client vous a adressé les données concernées.</p>
<p>En conséquence, nous estimons que l’action de la CNIL a permis d’apporter une réponse appropriée à la situation pour laquelle vous nous avez saisis et procédons donc à la clôture de votre plainte.</p>
</blockquote>
<h1 id="le-mot-de-la-fin">Le mot de la fin<a class="headerlink" href="#le-mot-de-la-fin" title="Permanent link">¶</a></h1>
<p>Pour finir, quelques observations et plus d’interrogations. Orange a été relativement réactif, et s’est preté au jeu (enfin, a respecté la loi, tout du moins, j’en ai l’impression), même si j’ai dû pour cela impliquer la CNIL. Merci donc à Orange. Cependant, plusieurs questions restent sans réponses pour moi:</p>
<ul>
<li>Le non-respect (ou plutôt, une lecture permissive) du R10-13 est elle admise par la jurisprudence ? Ma lecture de cet article et de la loi est elle la bonne ?</li>
<li>Des données plus précises concernant mon trafic (par exemple mes interlocuteurs au niveau IP) ne sont elles pas collectées, à un moment ou un autre ?</li>
<li>Certaines données ont elles été omises par Orange car trop difficiles à récolter ?</li>
<li>N’existe-t-il pas une localisation plus précise concernant mes opérations mobiles (en tout cas, plus précises qu’une ville et un code postal ?)</li>
</ul>Doctolib est trop bavard2021-03-09T00:00:00+01:002021-03-09T00:00:00+01:00Rémy Grünblatttag:remy.grunblatt.org,2021-03-09:/doctolib-est-trop-bavard.html<p>Le 8 mars 2021, France Inter a <a href="https://www.franceinter.fr/justice/doctolib-le-chiffrement-des-donnees-incomplet">publié un article sur son site web</a> affirmant que des données comme « les médecins consultés, la fréquence de rendez-vous et même parfois, le motif de ce rendez-vous » étaient confiées à Amazon Web Services, et étaient « en clair ». L’article de France Inter est …</p><p>Le 8 mars 2021, France Inter a <a href="https://www.franceinter.fr/justice/doctolib-le-chiffrement-des-donnees-incomplet">publié un article sur son site web</a> affirmant que des données comme « les médecins consultés, la fréquence de rendez-vous et même parfois, le motif de ce rendez-vous » étaient confiées à Amazon Web Services, et étaient « en clair ». L’article de France Inter est plutôt fouillis, et on ne comprend pas vraiment de quoi il retourne, par manque de détails techniques et d’informations sur ce qui a été effectivement observé.</p>
<p>Pour rappel, Doctolib est une plateforme française privée qui met en relation médecins, praticiens, et patients, et qui doit donc traiter des données à caractère personnel médicales, données médicales dont l’actualité <a href="https://www.francetvinfo.fr/internet/securite-sur-internet/cyberattaques/sante-les-donnees-medicales-de-500-000-francais-piratees_4309377.html">a montré qu’elles ne sont pas toujours bien sécurisées</a>.</p>
<p>Toujours est-il que Doctolib, par le biais de son co-fondateur et président, <a href="https://stanniox.medium.com/r%C3%A9ponse-%C3%A0-plusieurs-fausses-affirmations-relay%C3%A9es-sur-france-inter-les-donn%C3%A9es-des-utilisateurs-b6bf6250d229">a répondu dans un article publié sur medium</a> en affirmant que les affirmations de France Inter étaient « fausses ». La réponse a au moins le mérite d’être un peu plus claire, mais ce n’est toujours pas complètement gagné.</p>
<p>Dans cet article, je vais essayer d’apporter quelques précisions afin de déterminer qui a tort et qui a raison. Dans sa réponse, Stanislas Niox-Chateau affirme que « L’ensemble des données des utilisateurs de Doctolib est chiffré au repos. » et « Les données en transit sont toujours chiffrées. ».</p>
<p>Tout d’abord, concernant le chiffrement au repos, cela est à vérifier sur les serveurs de Doctolib, et ceci n’est donc pas vraiment ce qui était reproché à l’entreprise par France Inter, je vais donc passer sur ce point. Le second point est plus intéressant : le fait que des données soient chiffrées en transit.</p>
<p>Est-ce bien le cas? La réponse est très probablement « oui », même avant de vérifier le fonctionnement de l’application Doctolib ou du site web Doctolib. Cela ne veut pas dire que c’est suffisant : si je chiffre mes données pour les envoyer à Facebook, et que Facebook peut les lire, mes données seront probablement confidentielle sur le chemin qu’elles prennent jusqu’à Facebook, mais rien ne me garantie que Facebook ne va pas en faire n’importe quoi derrière.</p>
<p>Quand le président de Doctolib affirme ensuite que le chiffrement de bout en bout est une « technique de chiffrement avant-gardiste qui est encore très faiblement déployée dans le monde », ce n’est pas un bon signe quant à sa véracité. Plusieurs messageries instantanées, comme Signal, WhatsApp ou encore Telegram supportent le chiffrement de bout-en-bout depuis plusieurs années, et ce ne sont pas des services mineurs.</p>
<p>Vérifions.</p>
<h1 id="protocole-de-test">Protocole de test<a class="headerlink" href="#protocole-de-test" title="Permanent link">¶</a></h1>
<p>Pour tester si les données de Doctolib s’échappent vers des tiers comme Amazon, j’ai étudié l’application Android de la société, et ré-utilisé la même technique que lors de mon analyse de l’<a href="https://remy.grunblatt.org/mais-avec-qui-communique-lapplication-izly.html">application Izly</a>, que je ne vais donc pas re-détailler ici. En résumé, je me place sur le chemin de communication entre l’application et Internet, et j’observe les données qui passent pour déterminer leur contenu et leur destinataire.</p>
<p>Grâce à cette étude, j’observe que Doctolib est en effet trop bavard, et fait fuiter des données liées à la santé des personnes qui utilisent le service à d’autres entreprises privées.</p>
<h1 id="meta-donnees-envoyees-a-cloudinary">Méta-données envoyées à Cloudinary<a class="headerlink" href="#meta-donnees-envoyees-a-cloudinary" title="Permanent link">¶</a></h1>
<p>Tout d’abord, Doctolib utilise le service de gestion d’images <a href="https://en.wikipedia.org/wiki/Cloudinary">Cloudinary</a> pour héberger les images des médecins et autres établissements de santé. Lorsqu’une recherche est effectuée par un utilisateur de Doctolib pour trouver un médecin ou un établissement de santé, les images liées sont chargées par le biais des serveurs de Cloudinary. Ainsi, Cloudinary peut savoir si l’utilisateur cherche un oncologue, un chirugien dentiste, et peut techniquement re-construire la requête de l’utilisateur en utilisant les photos des praticiens. Je donne ici un exemple d’images affichées quand on recherche le mot-clef « cancer » :</p>
<p><img alt="" src="/images/doctolib-leak-cloudinary.webp" /></p>
<p>Les miniatures chargées sont, entre autres, celles de l’Institut Curie, un <a href="https://curie.fr/">centre de recherche et de traitement du <strong>cancer</strong> en France</a>, et du <a href="https://www.chirurgie-viscerale-digestive-oncologie.fr/fr/">Pôle de chirurgie viscérale et digestive // <strong>Oncologie</strong> de Montpellier</a>, établissement spécialisés sur les cancers. </p>
<p>Techniquement, Cloudinary peut donc faire le lien entre l’adresse IP de l’utilisateur et sa recherche sur le mot clef « cancer », une recherche à caractère médical.</p>
<h1 id="meta-donnees-envoyees-a-amazon">Méta-données envoyées à Amazon<a class="headerlink" href="#meta-donnees-envoyees-a-amazon" title="Permanent link">¶</a></h1>
<p>L’application Doctolib envoie de la télémétrie, à la fois à Google Analytics et Amazon. Sauf que dans certaines données envoyées à Amazon, on peut retrouver des URLs qui correspondent à ce que visite ou recherche l’utilisateur, comme illustré sur l’image ci-dessous (cliquez pour agrandir):</p>
<p><a href="/images/doctolib-leak-amazon.webp"><img src="/images/doctolib-leak-amazon.webp"></img></a></p>
<h1 id="un-certificat-doctolib-derriere-une-ip-cloudflare">Un certificat doctolib derrière une IP Cloudflare<a class="headerlink" href="#un-certificat-doctolib-derriere-une-ip-cloudflare" title="Permanent link">¶</a></h1>
<p>L’application communique avec des IPs de Cloudflare, à travers les requêtes pour la récupération du fichier <code>appointments.json</code>. Ce fichier contient les informations concernant les rendez-vous, le nom du patient, la localisation du praticien, sa spécialité…</p>
<p>Ici, par exemple, un test de dépistage du COVID que j’ai effectué il y a quelques mois.</p>
<p><a href="/images/doctolib-leak-cloudflare-details.webp"><img src="/images/doctolib-leak-cloudflare-details.webp"></img></a></p>
<p>Certes, le certificat TLS est bien celui de Doctolib, mais l’adresse IP qui répond est une adresse IP de Cloudflare, ce qui veut très probablement dire que Doctolib a uploadé sa clef privée sur les serveurs de Cloudflare (qui sert ainsi de terminaison TLS), ou que Doctolib repose sur le mécanisme « keyless » de CloudFlare, ce qui signifierait que Cloudflare peut lire les données « en clair », contrairement aux affirmations du président de Doctolib.</p>
<p>Il est techniquement possible que Cloudflare ne serve qu’à faire <a href="https://github.com/dlundquist/sniproxy">proxy SNI</a>, permettant ainsi à Doctolib d’effectuer la terminaison TLS (et rendre impossible la lecture des données par Cloudflare), mais la probabilité que cela soit le cas est faible, car cela enleverait une bonne partie de l’intérêt à utiliser Cloudflare.</p>
<p>Quant à l’utilisation du mode <a href="https://www.cloudflare.com/fr-fr/ssl/keyless-ssl/">mode « keyless »</a> de CloudFlare, qui permet de ne pas avoir à partager la clef privée avec ce dernier, celui ci n’est pas magique: l’entreprise rappelle en effet sur sa page que « Keyless SSL nécessite que Cloudflare déchiffre, inspecte et rechiffre le trafic pour le renvoyer au serveur d’origine du client. », ce qui signifie que Cloudflare a accès aux données <em>en clair</em>, même si il n’a pas accès à la clef privée.</p>
<p><a href="/images/doctolib-leak-cloudflare.webp"><img src="/images/doctolib-leak-cloudflare.webp"></img></a></p>
<h1 id="en-resume">En résumé<a class="headerlink" href="#en-resume" title="Permanent link">¶</a></h1>
<p>Certaines données et méta-données de santé des personnes qui utilisent Doctolib sont envoyées, directement ou indirectement, à d’autres entreprises privées, comme Amazon, Cloudflare, ou Cloudinary.</p>
<p>Même si « Doctolib utilise uniquement les données de ses utilisateurs pour le bon fonctionnement de ses services », comme l’affirme son président, peut-il en affirmer autant pour ces autres entreprises privées dont les sièges sociaux sont situés en dehors de l’Europe, aux États Unis, pays qui n’a pas été <a href="https://www.nextinpact.com/article/30416/109182-retour-sur-invalidation-privacy-shield-par-justice-europeenne">jugé aussi sûr que l’Europe pour l’hébergement de données</a> ?</p>
<p>Je pense que la réponse est « non », et à ce titre, Doctolib peut largement mieux faire.</p>How easy is it to detect (and relay) BLE beacons?2020-05-28T00:00:00+02:002020-05-28T00:00:00+02:00Rémy Grünblatt 🍃tag:remy.grunblatt.org,2020-05-28:/how-easy-is-it-to-detect-and-relay-ble-beacons.html<p>Most of the <a href="https://en.wikipedia.org/wiki/Digital_contact_tracing">digital contact tracing</a> applications use Bluetooth, and Bluetooth Low Energy (BLE) in order to determine if smartphones (and smartphone users) are close to each other. Smartphones are expected to exchange and record <em>beacons</em>, which are small pieces of data used to uniquely identify each other and allow …</p><p>Most of the <a href="https://en.wikipedia.org/wiki/Digital_contact_tracing">digital contact tracing</a> applications use Bluetooth, and Bluetooth Low Energy (BLE) in order to determine if smartphones (and smartphone users) are close to each other. Smartphones are expected to exchange and record <em>beacons</em>, which are small pieces of data used to uniquely identify each other and allow people that have been in close contact with sick individual to get a notification. Such tracking systems present <a href="https://tracing-risks.com">many privacy risks</a>, and their effectiveness has been questioned (but this is not the subject of this article). One class of attack against BLE based digital contact tracing systems is the class of <em>relay attacks</em>.</p>
<h2 id="relay-attacks">Relay Attacks<a class="headerlink" href="#relay-attacks" title="Permanent link">¶</a></h2>
<p>This class of attack consist in relaying data between users. For example, by listening to beacons that are emitted near an hospital or a medical laboratory, and re-emitting them in a shopping mall, you can increase the « perceived » exposure risk of a shopping mall user, as its phone will believe it is in contact with more people than it actually is, therefore increasing the risk of getting an exposure notification.</p>
<p><img alt="" src="/images/attack.png" width="100%" /></p>
<p>Let’s note in reality, the relay has to be bi-directional so that the fake retransmitted beacons cannot be filtered against what the original senders received.</p>
<p>Many attack scenarios based on relay attacks have been described in the litterature on covid apps, for example scenario 15 of <a href="https://tracing-risks.com/docs/tracing-risks.pdf">https://tracing-risks.com/docs/tracing-risks.pdf</a> or point 4.5 of <a href="https://eprint.iacr.org/2020/399.pdf">https://eprint.iacr.org/2020/399.pdf</a>.</p>
<h3 id="feasibility">Feasibility<a class="headerlink" href="#feasibility" title="Permanent link">¶</a></h3>
<p>Are these attack feasible at a low cost, hard to implement? Let’s find out. In the following, we focus on one digital contact tracing protocole, the <a href="https://github.com/ROBERT-proximity-tracing/documents/blob/master/ROBERT-specification-EN-v1_0.pdf">ROBERT protocol</a>, but everything should be applicable to other protocols (such as <a href="https://github.com/3rd-ways-for-EU-exposure-notification/project-DESIRE/blob/master/DESIRE-specification-EN-v1_0.pdf">DESIRE</a>) as well, and we focus on the on the <a href="https://fr.wikipedia.org/wiki/StopCovid">StopCovid</a> app, which will be an implementation of the ROBERT protocol.</p>
<h2 id="requirements">Requirements<a class="headerlink" href="#requirements" title="Permanent link">¶</a></h2>
<p>To implement a relay attack, we need a few components. If we use the analogy of the diagram above, we need:</p>
<ol>
<li>a <strong>listening</strong> device, the <em>microphone</em>, hearing the BLE beacons emitted in its vicinity;</li>
<li>a <strong>broadcasting</strong> device, the <em>loudspeaker</em>, transmitting the data heard by the listening device;</li>
<li>a <strong>network component</strong>, the <em>cable</em>, transmitting the data from the microphone to the loudspeaker;</li>
</ol>
<p>An android phone, albeit being pricey, ticks all the prerequisites: it can receive and emit BLE beacons (otherwise, no digital contact tracing apps), and can transmit the data to another phone using a cellular connection. And it can do all of this in parallel, of course.</p>
<h2 id="detecting-ble-beacons-on-android">Detecting BLE beacons on Android<a class="headerlink" href="#detecting-ble-beacons-on-android" title="Permanent link">¶</a></h2>
<p>In the ROBERT protocol, <em>HELLO</em> messages have « <em>a total length of 128 bits (16 bytes)</em> ». I believe this means the whole protocol will fit into the Universally Unique Identifier (UUID) field of the BLE beacons, which has exactly this size. Other protocols may use a different method to convey proximity messages: for example, the DESIRE protocol use a scan request / scan response mechanism to be able to transmit up to 32 bytes, requiring two additional messages (one from the receiver, and one from the initial emitter).</p>
<p>But because we are lazy, and because the way beacons are advertised is not exactly specified in the documentation, we can directly go read the <a href="https://gitlab.inria.fr/stopcovid19/stopcovid-blesdk-android">source code</a> of the soon-to-be StopCovid Application to check how the beacons are sent on Android:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*</span>
<span class="cm">* This Source Code Form is subject to the terms of the Mozilla Public</span>
<span class="cm">* License, v. 2.0. If a copy of the MPL was not distributed with this</span>
<span class="cm">* file, You can obtain one at https://mozilla.org/MPL/2.0/.</span>
<span class="cm">*</span>
<span class="cm">* Authors</span>
<span class="cm">* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span>
<span class="cm">* Created by Orange / Date - 2020/04/27 - for the STOP-COVID project</span>
<span class="cm">*/</span>
<span class="c1">// […]</span>
<span class="kd">private</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">buildAdvertiseData</span><span class="p">(</span><span class="n">data</span><span class="p">:</span><span class="w"> </span><span class="n">ByteArray</span><span class="p">):</span><span class="w"> </span><span class="n">AdvertiseData</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">AdvertiseData</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="w"> </span><span class="p">.</span><span class="na">addServiceUuid</span><span class="p">(</span><span class="n">ParcelUuid</span><span class="p">(</span><span class="n">settings</span><span class="p">.</span><span class="na">serviceUuid</span><span class="p">))</span>
<span class="w"> </span><span class="p">.</span><span class="na">addServiceData</span><span class="p">(</span><span class="n">ParcelUuid</span><span class="p">(</span><span class="n">settings</span><span class="p">.</span><span class="na">serviceUuid</span><span class="p">),</span><span class="w"> </span><span class="n">data</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">setIncludeDeviceName</span><span class="p">(</span><span class="kc">false</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">setIncludeTxPowerLevel</span><span class="p">(</span><span class="kc">false</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">build</span><span class="p">()</span>
<span class="p">}</span>
<span class="kd">private</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">buildAdvertiseSettings</span><span class="p">():</span><span class="w"> </span><span class="n">AdvertiseSettings</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">AdvertiseSettings</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="w"> </span><span class="p">.</span><span class="na">setAdvertiseMode</span><span class="p">(</span><span class="n">AdvertiseSettings</span><span class="p">.</span><span class="na">ADVERTISE_MODE_LOW_LATENCY</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">setConnectable</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">setTxPowerLevel</span><span class="p">(</span><span class="n">AdvertiseSettings</span><span class="p">.</span><span class="na">ADVERTISE_TX_POWER_MEDIUM</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">setTimeout</span><span class="p">(</span><span class="m">0</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">build</span><span class="p">()</span>
<span class="p">}</span>
<span class="c1">// […]</span>
</code></pre></div>
<p>All beacons advertised by Android share the same service UUID, which has not yet been made public:</p>
<blockquote>
<p>« <em>In your service implementation you will have to declare the settings of the ProximityNotification SDK such as service UUID used to advertise and scan in BLE</em> »</p>
</blockquote>
<p>This service UUID will be easy to find once the actual application is released, though.</p>
<p>To listen to BLE beacons, we can use the <a href="https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner">Android BluetoothLeScanner API</a> and log the results to the console:</p>
<div class="highlight"><pre><span></span><code><span class="kd">private</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">mScanCallback</span><span class="p">:</span><span class="w"> </span><span class="n">ScanCallback</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nc">ScanCallback</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onScanResult</span><span class="p">(</span><span class="n">callbackType</span><span class="p">:</span><span class="w"> </span><span class="kt">Int</span><span class="p">,</span><span class="w"> </span><span class="n">result</span><span class="p">:</span><span class="w"> </span><span class="n">ScanResult</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Log</span><span class="p">.</span><span class="na">i</span><span class="p">(</span><span class="s">"scanResult"</span><span class="p">,</span><span class="w"> </span><span class="n">result</span><span class="p">.</span><span class="na">toString</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onBatchScanResults</span><span class="p">(</span><span class="n">results</span><span class="p">:</span><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="n">ScanResult</span><span class="o">></span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">sr</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">results</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Log</span><span class="p">.</span><span class="na">i</span><span class="p">(</span><span class="s">"scanResult"</span><span class="p">,</span><span class="w"> </span><span class="n">sr</span><span class="p">.</span><span class="na">toString</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onScanFailed</span><span class="p">(</span><span class="n">errorCode</span><span class="p">:</span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Log</span><span class="p">.</span><span class="na">e</span><span class="p">(</span><span class="s">"scanFailed"</span><span class="p">,</span><span class="w"> </span><span class="s">"Error: </span><span class="si">$</span><span class="n">errorCode</span><span class="s">"</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="cm">/* StopCovid UUID */</span>
<span class="kd">var</span><span class="w"> </span><span class="nv">serviceUuid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">UUID</span><span class="p">.</span><span class="na">fromString</span><span class="p">(</span><span class="s">"XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"</span><span class="p">)</span>
<span class="cm">/* Filter what's not using this UUID */</span>
<span class="kd">val</span><span class="w"> </span><span class="nv">scanFilters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arrayListOf</span><span class="p">(</span>
<span class="w"> </span><span class="n">ScanFilter</span><span class="p">.</span><span class="na">Builder</span><span class="p">().</span><span class="na">setServiceUuid</span><span class="p">(</span><span class="n">ParcelUuid</span><span class="p">(</span><span class="n">serviceUuid</span><span class="p">)).</span><span class="na">build</span><span class="p">()</span>
<span class="p">)</span>
<span class="cm">/* Mostly boilerplate */</span>
<span class="kd">val</span><span class="w"> </span><span class="nv">scanSettings</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ScanSettings</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="w"> </span><span class="p">.</span><span class="na">setScanMode</span><span class="p">(</span><span class="n">ScanSettings</span><span class="p">.</span><span class="na">SCAN_MODE_LOW_LATENCY</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">setCallbackType</span><span class="p">(</span><span class="n">ScanSettings</span><span class="p">.</span><span class="na">CALLBACK_TYPE_ALL_MATCHES</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">setNumOfMatches</span><span class="p">(</span><span class="n">ScanSettings</span><span class="p">.</span><span class="na">MATCH_NUM_ONE_ADVERTISEMENT</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">setReportDelay</span><span class="p">(</span><span class="m">0L</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">build</span><span class="p">()</span>
<span class="cm">/* […] */</span>
<span class="n">BluetoothLeScanner</span><span class="o">?.</span><span class="na">startScan</span><span class="p">(</span><span class="n">scanFilters</span><span class="p">,</span><span class="w"> </span><span class="n">scanSettings</span><span class="p">,</span><span class="w"> </span><span class="n">mScanCallback</span><span class="p">)</span>
</code></pre></div>
<h2 id="transmitting-ble-beacons-to-another-phone">Transmitting BLE beacons to another phone<a class="headerlink" href="#transmitting-ble-beacons-to-another-phone" title="Permanent link">¶</a></h2>
<p>Now that we have the data, we have to transmit it to another phone. A simple solution is to use a MQTT broker, e.g. <a href="https://mosquitto.org/">Mosquitto</a> as a backend and a MQTT client application on the phone, e.g. <a href="https://www.eclipse.org/paho/">Paho</a>. This way, we can easily scale to multiple <em>listener</em> and multiple <em>broadcaster</em>, which would increase the efficiency of the attack. On the screenshot below, we can see an example of a BLE beacon emitted by a <a href="https://en.wikipedia.org/wiki/Lime_(transportation_company)">Lime electric scooter</a> as received by my phone, and broadcasted to the MQTT broker. Nothing interesting to see here, really.</p>
<p><a target="_blank" href="/images/lime.png"></p>
<p><img alt="" src="/images/lime.png" /></p>
<p></a></p>
<h2 id="advertising-ble-beacons-on-android">Advertising BLE beacons on Android<a class="headerlink" href="#advertising-ble-beacons-on-android" title="Permanent link">¶</a></h2>
<p>Transmitting the beacons is the most difficult task of this attack, because to be notified as being « at risk », you need to be at close distance (<= 1m) for at least 15 minutes, with someone with the application, and will be later diagnosed. So fire and forget won’t do: one needs to transmit what one receives, multiple times. Good thing is, since version 8.0, Android supports Bluetooth 5.0, which enables to broadcast multiple beacons at the same time (well, not exactly the <em>same</em> time, but kind of). To do so, we can use <a href="https://developer.android.com/reference/android/bluetooth/le/AdvertisingSet">AdvertisingSet</a> which allows to dynamically change the data advertised by the beacons, and use some thread that will update the data every 100ms (for example).</p>
<p>Another interesting point is that one can change the advertisement parameters to advertise with a higher energy (e.g. ADVERTISE_TX_POWER_HIGH) than what the official application is doing (i.e. ADVERTISE_TX_POWER_MEDIUM), which would probably allow the attack to reach more people.</p>
<h2 id="poc-and-caveats">PoC and Caveats<a class="headerlink" href="#poc-and-caveats" title="Permanent link">¶</a></h2>
<p>A proof of concept has been developped, and it looks like it works, but much more testing would be necessary to be sure everything <em>actually</em> works with the real Stop Covid application (because, of course, the application is not out there yet, so there’s no guarantee I got everything right).</p>
<p>A screenshot showing a phone running Stop Covid receiving its own beacon (retransmitted by another node faking the data) is shown below. For multiple reasons, i’ll not publish the source code: it’s pretty easy to reproduce with what’s written there, and you don’t have to trust me, so, reproduce.</p>
<h3 id="random-mac-addresses">Random Mac Addresses<a class="headerlink" href="#random-mac-addresses" title="Permanent link">¶</a></h3>
<p>Of course, the MAC address used to broadcast the beacons is not exactly the same as the original one, but as it’s expected that the operating system (e.g. Android or IOS) will change them randomly for privacy purpose, it’s not really a problem. Also, such a MAC Address could also be spoofed, if more work were put into the proof of concept, using something like an ESP32 microcontroller or even a SDR equipped with <a href="https://github.com/JiaoXianjun/BTLE">BTLE</a></p>
<h3 id="latency">Latency<a class="headerlink" href="#latency" title="Permanent link">¶</a></h3>
<p>Latency is not a problem: a round-trip message between Lyon and Paris will take less than 20ms through the internet, allowing any beacon being heared by such a system to be retransmitted pretty much anywhere in France in less than 1 second. And from what I observe, the Stop Covid App will emit the same beacons for at least a few tens of seconds.</p>
<p><center>
<a target="_blank" href="/images/rebroadcast.png"> <img alt="" height="350px" src="/images/rebroadcast.png" /> </a>
</center></p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Permanent link">¶</a></h2>
<p>Relay attacks are not new, and the only way to defend against them is to use some kind of bounding protocol that will prevent silently rebroadcasting beacons from one place to another. Such a protocol would use localization information (e.g. GPS localization) or limits imposed by physics (e.g. the speed of light), which is not feasible for contact tracing mechanisms based on bluetooth, or in a way that an user will trust (not using the GPS is a feature for an app such as Stop Covid). And it seems to me relay attacks are not really hard to deploy.</p>Comment compter le nombre de voix du Referendum ADP en respectant la vie privée?2019-06-18T00:00:00+02:002019-06-18T00:00:00+02:00Rémy Grünblatttag:remy.grunblatt.org,2019-06-18:/comment-compter-le-nombre-de-voix-du-referendum-adp-en-respectant-la-vie-privee.html<p>Le Référendum d’Initiative Partagée (RIP) concernant la privatisation du groupe Aéroports de Paris (ADP) est en ligne depuis le 13 juin 2019. Ce référendum permet d’apporter son soutien à une proposition de loi visant à affirmer le caractère de service public national de l’exploitation du Groupe aéroports …</p><p>Le Référendum d’Initiative Partagée (RIP) concernant la privatisation du groupe Aéroports de Paris (ADP) est en ligne depuis le 13 juin 2019. Ce référendum permet d’apporter son soutien à une proposition de loi visant à affirmer le caractère de service public national de l’exploitation du Groupe aéroports de Paris, en « signant » un équivalent de pétition en ligne.</p>
<h2 id="la-problematique">La problématique<a class="headerlink" href="#la-problematique" title="Permanent link">¶</a></h2>
<p>Le site de soutiens ne comporte pas de compteur de signatures, tel que <a href="https://www.liberation.fr/checknews/2019/06/16/referendum-adp-le-ministere-de-l-interieur-communiquera-t-il-regulierement-le-nombre-de-soutiens_1734078">rappelé par CheckNews</a>, ce qui peut poser problème aux soutiens de la proposition de loi. Il n’est en effet pas possible de savoir si l’on approche du seuil de 10% des inscrits sur les listes électorales, qui correspond à un total de 4 717 396 voix.</p>
<p>Comment alors faire un compteur, en respectant la vie privée des personnes ayant signé cette pétition, c’est-à-dire en évitant de récupérer les noms et prénoms de l’ensemble des participants? Cet article présente une méthode simple qui permet d’avoir une première estimation.</p>
<h2 id="donnees-disponibles-et-mecanismes-de-protection">Données disponibles et mécanismes de protection<a class="headerlink" href="#donnees-disponibles-et-mecanismes-de-protection" title="Permanent link">¶</a></h2>
<p>Le site permet cependant à chacun de consulter les noms, prénoms et départements des personnes ayant apportée leurs soutiens à ce référendum, et <a href="https://www.reddit.com/r/france/comments/c06bcd/site_pour_compter_les_voix_du_referendum_sur_ladp/erfe0rg/">certains</a> utilisent du <a href="https://fr.wikipedia.org/wiki/Micro-travail">micro-travail</a> pour automatiser la récolte de données. Ce micro-travail est nécessaire car plusieurs mécanismes empêchent la prospection automatique à l’aide de robots de ces données, qui sont des données à caractère personnel:</p>
<ol>
<li>La présence d’un fichier <code>robots.txt</code> interdisant la consultation automatique du site, situé à l’adresse <a href="https://www.referendum.interieur.gouv.fr/robots.txt">https://www.referendum.interieur.gouv.fr/robots.txt</a>. Ce mécanisme est purement cosmétique, puisqu’il est simplement possible d’ignorer les directives de ce fichier;</li>
<li>L’utilisation d’une solution anti-ddos de la société <a href="https://en.wikipedia.org/wiki/Incapsula">Imperva Incapsula</a>, comme relevé par <a href="https://twitter.com/CelestinMatte/status/1139147453284999168">Célestin Matte</a>, qui utilise notamment une captcha ReCaptcha de Google, visible sur l’image ci-dessous;</li>
<li>L’utilisation d’une captcha « fait maison » mis en place par le ministère de l’intérieur, qui semble cependant simple à résoudre automatiquement;</li>
</ol>
<p><img alt="Solution anti-ddos mise en place par Imperva Incapsula" src="/images/incapsula.png" style="width: 48%;" />
<img alt="Captcha « fait maison » mis en place par le ministère de l'intérieur" src="/images/captcha.png" style="width: 48%;" />
<em>Gauche: Solution anti-ddos de Imperva Incapsula - Droite: Captcha « fait maison » du ministère de l’intérieur</em></p>
<h2 id="une-solution-possible">Une solution possible<a class="headerlink" href="#une-solution-possible" title="Permanent link">¶</a></h2>
<p>Pour obéir au fichier robots.txt, la solution doit être manuelle: il n’est pas question d’utiliser du crawling automatique, puisque ce dernier est « interdit » (tout du moins, très très fortement déconseillé). Par suite, il n’est pas nécessaire d’automatiser de la résolution de captchas, d’autant plus que les services utilisés reposent sur <a href="http://diplab.eu/">l’exploitation de précaires à travers le monde, et en France</a>.</p>
<p>On remarque que sur le site web, les signatures sont organisées alphabétiquement selon les deux premières lettres du nom de famille: AA, AB, AC, AD, etc. Par ailleurs, les participations sont regroupées par pages contenant 200 signatures, avec en bas de page des liens permettent d’accéder aux différentes pages contenant ces participations.</p>
<p>Ainsi, étant donné deux lettres (par exemple, “GR”), en utilisant un nombre réduit de résolutions de captchas, il est possible de savoir combien de pages de participation sont disponibles, c’est-à-dire savoir combien de personnes ont participé, à plus ou moins 200 participations.</p>
<p><img alt="Calcul du nombre de signatures" src="/images/computation.png"/></p>
<p>Il est possible de combiner cette information avec les statistiques de l’Insee sur les noms par années de naissance, <a href="https://www.insee.fr/fr/statistiques/3536630">disponibles en Open Data</a>, pour obtenir une estimation du nombre de « votes ». Ainsi, si l’on considère les noms commençant par “G” pour les personnes nées entre 1950 et 2000, la distribution des secondes lettres est visible sur la figure suivante.</p>
<p><img alt="Distribution de la seconde lettre des noms commençant par G entre les années de naissance 1950 et 2000" src="/images/noms_distribution.png" style="width: 70%"/></p>
<p>Sous des hypothèses d’indépendance entre le patronyme et le pourcentage de participation à ce référendum (donc sur l’inscription sur des listes électorales), on peut à partir de ces données obtenir une image de la participation globale.
On peut aussi choisir quelles paires de lettres choisir en priorité, pour avoir le plus de votes (et réduire ainsi l’erreur relative à l’incertitude sur le nombre de vote de la dernière page, inconnu et situé entre 1 et 200).</p>
<p>Ainsi, il est possible de calculer une participation, extrapolée à partir des données liées aux noms de famille. La dernière colonne du tableau suivant correspond à cette participation extrapolée.</p>
<table>
<thead>
<tr>
<th style="text-align: center;">Premières lettres</th>
<th style="text-align: center;">Pourcentage (INSEE)</th>
<th style="text-align: center;">Nombre de page (Referendum)</th>
<th style="text-align: center;">Nombre de participation (extrapolé)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">LE</td>
<td style="text-align: center;">4,78%</td>
<td style="text-align: center;">29</td>
<td style="text-align: center;">121338</td>
</tr>
<tr>
<td style="text-align: center;">MA</td>
<td style="text-align: center;">4,3039%</td>
<td style="text-align: center;">28</td>
<td style="text-align: center;">130114</td>
</tr>
<tr>
<td style="text-align: center;">DE</td>
<td style="text-align: center;">3,8845%</td>
<td style="text-align: center;">25</td>
<td style="text-align: center;">128716</td>
</tr>
<tr>
<td style="text-align: center;">BO</td>
<td style="text-align: center;">3,521%</td>
<td style="text-align: center;">18</td>
<td style="text-align: center;">102243</td>
</tr>
<tr>
<td style="text-align: center;">LA</td>
<td style="text-align: center;">3,0816%</td>
<td style="text-align: center;">21</td>
<td style="text-align: center;">136292</td>
</tr>
<tr>
<td style="text-align: center;">…</td>
<td style="text-align: center;">…</td>
<td style="text-align: center;">…</td>
<td style="text-align: center;">…</td>
</tr>
</tbody>
</table>
<h2 id="en-bref">En bref<a class="headerlink" href="#en-bref" title="Permanent link">¶</a></h2>
<p>En se contentant de faire une simple règle de proportionalité sur le nombre de pages des listes de participation disponibles, il est possible d’obtenir une estimation de la participation au référendum. Le 18 juin, à 14h30, l’estimation était d’environ 123 000 voix. Cette estimation s’obtient sans avoir besoin de passer par un service de résolution de captcha, et sans contournement des protections mises en place par le ministère de l’Intérieur. Par ailleurs, la méthode est suffisamment simple pour pouvoir être répétée régulièrement. Cette estimation se base cependant sur une hypothèse qui peut être critiquée, celle que les participations au référendum sont suffisamment bien réparties selon les premières lettres du nom de famille (i.e. quelqu’un dont le nom commence par “LE” n’a pas plus de chance de voter que quelqu’un dont le nom commence par “ZX”).</p>
<p><b>Ajout du 1er juillet 2019: Le conseil constitutionnel a <a href="https://www.conseil-constitutionnel.fr/actualites/communique/communique-du-conseil-constitutionnel-sur-le-recueil-de-soutiens-dans-le-cadre-de-la-procedure-du">communiqué de manière officielle sur le décompte</a>. Un coefficient correcteur (multiplication de ~ 1.08) a donc été ajouté pour faire correspondre la valeur du 01 juillet 2019 à celle du conseil constitutionnel qui fait référence. Cette différence s’explique par la prise en compte par le conseil constitutionnel de signatures n’apparaissant pas en ligne pour des raisons de « bugs » d’affichage (par exemple, les noms à une lettre n’aparaissent pas, de même que certains noms accentués). De même, le nombre de signatures présent sur le site web n’est pas forcément le nombre de soutiens validé, puisque cette communication peut prendre jusqu’à 5 jours. Il n’est pas certain que la communication du conseil constitutionnel concerne le nombre de soutiens communiqués en ligne (et pas uniquement les validés).</b></p>
<h2 id="annexe-et-donnees">Annexe et données<a class="headerlink" href="#annexe-et-donnees" title="Permanent link">¶</a></h2>
<p>Les données brutes sont disponibles sur <a href="https://www.data.gouv.fr/fr/datasets/participation-par-digrammes-au-projet-de-referendum-dinitiative-partagee-sur-les-aeroports-de-paris/">data.gouv.fr</a>, la plateforme Open Data du Gouvernement Français.</p>
<p>Ce tableau présente l’évolution au cours du temps de l’estimation du nombre de participations:</p>
<table>
<thead>
<tr>
<th style="text-align: center;">Date</th>
<th style="text-align: center;">Participation</th>
<th style="text-align: center;">Participation<br>après correction</th>
<th style="text-align: center;">Déviation Standard</th>
<th style="text-align: center;">Pourcentage</th>
<th style="text-align: center;">Gain</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">13 juin 2019</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">0.0 %</td>
<td style="text-align: center;">0</td>
</tr>
<tr>
<td style="text-align: center;">18 juin 2019</td>
<td style="text-align: center;">123 741</td>
<td style="text-align: center;">130 535</td>
<td style="text-align: center;">13 863</td>
<td style="text-align: center;">2.77 %</td>
<td style="text-align: center;">130 535</td>
</tr>
<tr>
<td style="text-align: center;">19 juin 2019</td>
<td style="text-align: center;">216 722</td>
<td style="text-align: center;">228 621</td>
<td style="text-align: center;">9 413</td>
<td style="text-align: center;">4.85 %</td>
<td style="text-align: center;">98 086</td>
</tr>
<tr>
<td style="text-align: center;">20 juin 2019</td>
<td style="text-align: center;">256 451</td>
<td style="text-align: center;">270 533</td>
<td style="text-align: center;">10 386</td>
<td style="text-align: center;">5.73 %</td>
<td style="text-align: center;">41 912</td>
</tr>
<tr>
<td style="text-align: center;">21 juin 2019</td>
<td style="text-align: center;">278 147</td>
<td style="text-align: center;">293 420</td>
<td style="text-align: center;">12 072</td>
<td style="text-align: center;">6.22 %</td>
<td style="text-align: center;">22 887</td>
</tr>
<tr>
<td style="text-align: center;">22 juin 2019</td>
<td style="text-align: center;">300 793</td>
<td style="text-align: center;">317 309</td>
<td style="text-align: center;">11 109</td>
<td style="text-align: center;">6.73 %</td>
<td style="text-align: center;">23 889</td>
</tr>
<tr>
<td style="text-align: center;">23 juin 2019</td>
<td style="text-align: center;">329 868</td>
<td style="text-align: center;">347 981</td>
<td style="text-align: center;">12 122</td>
<td style="text-align: center;">7.38 %</td>
<td style="text-align: center;">30 672</td>
</tr>
<tr>
<td style="text-align: center;">24 juin 2019</td>
<td style="text-align: center;">354 699</td>
<td style="text-align: center;">374 175</td>
<td style="text-align: center;">12 254</td>
<td style="text-align: center;">7.93 %</td>
<td style="text-align: center;">26 194</td>
</tr>
<tr>
<td style="text-align: center;">25 juin 2019</td>
<td style="text-align: center;">369 829</td>
<td style="text-align: center;">390 135</td>
<td style="text-align: center;">12 397</td>
<td style="text-align: center;">8.27 %</td>
<td style="text-align: center;">15 960</td>
</tr>
<tr>
<td style="text-align: center;">26 juin 2019</td>
<td style="text-align: center;">387 870</td>
<td style="text-align: center;">409 167</td>
<td style="text-align: center;">14 972</td>
<td style="text-align: center;">8.67 %</td>
<td style="text-align: center;">19 032</td>
</tr>
<tr>
<td style="text-align: center;">27 juin 2019</td>
<td style="text-align: center;">400 622</td>
<td style="text-align: center;">422 619</td>
<td style="text-align: center;">16 634</td>
<td style="text-align: center;">8.96 %</td>
<td style="text-align: center;">13 452</td>
</tr>
<tr>
<td style="text-align: center;">28 juin 2019</td>
<td style="text-align: center;">412 060</td>
<td style="text-align: center;">434 685</td>
<td style="text-align: center;">15 581</td>
<td style="text-align: center;">9.21 %</td>
<td style="text-align: center;">12 066</td>
</tr>
<tr>
<td style="text-align: center;">29 juin 2019</td>
<td style="text-align: center;">420 259</td>
<td style="text-align: center;">443 334</td>
<td style="text-align: center;">16 959</td>
<td style="text-align: center;">9.4 %</td>
<td style="text-align: center;">8 649</td>
</tr>
<tr>
<td style="text-align: center;">30 juin 2019</td>
<td style="text-align: center;">433 197</td>
<td style="text-align: center;">456 983</td>
<td style="text-align: center;">16 669</td>
<td style="text-align: center;">9.69 %</td>
<td style="text-align: center;">13 649</td>
</tr>
<tr>
<td style="text-align: center;">01 juillet 2019</td>
<td style="text-align: center;">441 650</td>
<td style="text-align: center;">465 900</td>
<td style="text-align: center;">16 655</td>
<td style="text-align: center;">9.88 %</td>
<td style="text-align: center;">8 917</td>
</tr>
<tr>
<td style="text-align: center;">02 juillet 2019</td>
<td style="text-align: center;">449 021</td>
<td style="text-align: center;">473 675</td>
<td style="text-align: center;">16 827</td>
<td style="text-align: center;">10.04 %</td>
<td style="text-align: center;">7 775</td>
</tr>
<tr>
<td style="text-align: center;">03 juillet 2019</td>
<td style="text-align: center;">454 708</td>
<td style="text-align: center;">479 675</td>
<td style="text-align: center;">17 924</td>
<td style="text-align: center;">10.17 %</td>
<td style="text-align: center;">6 000</td>
</tr>
<tr>
<td style="text-align: center;">04 juillet 2019</td>
<td style="text-align: center;">460 921</td>
<td style="text-align: center;">486 230</td>
<td style="text-align: center;">18 287</td>
<td style="text-align: center;">10.31 %</td>
<td style="text-align: center;">6 555</td>
</tr>
<tr>
<td style="text-align: center;">05 juillet 2019</td>
<td style="text-align: center;">474 504</td>
<td style="text-align: center;">500 558</td>
<td style="text-align: center;">18 691</td>
<td style="text-align: center;">10.61 %</td>
<td style="text-align: center;">14 328</td>
</tr>
<tr>
<td style="text-align: center;">06 juillet 2019</td>
<td style="text-align: center;">481 874</td>
<td style="text-align: center;">508 333</td>
<td style="text-align: center;">18 847</td>
<td style="text-align: center;">10.78 %</td>
<td style="text-align: center;">7 775</td>
</tr>
<tr>
<td style="text-align: center;">07 juillet 2019</td>
<td style="text-align: center;">487 519</td>
<td style="text-align: center;">514 288</td>
<td style="text-align: center;">19 055</td>
<td style="text-align: center;">10.9 %</td>
<td style="text-align: center;">5 955</td>
</tr>
<tr>
<td style="text-align: center;">08 juillet 2019</td>
<td style="text-align: center;">492 185</td>
<td style="text-align: center;">519 210</td>
<td style="text-align: center;">18 876</td>
<td style="text-align: center;">11.01 %</td>
<td style="text-align: center;">4 922</td>
</tr>
<tr>
<td style="text-align: center;">09 juillet 2019</td>
<td style="text-align: center;">497 830</td>
<td style="text-align: center;">525 165</td>
<td style="text-align: center;">19 140</td>
<td style="text-align: center;">11.13 %</td>
<td style="text-align: center;">5 955</td>
</tr>
<tr>
<td style="text-align: center;">10 juillet 2019</td>
<td style="text-align: center;">502 727</td>
<td style="text-align: center;">530 331</td>
<td style="text-align: center;">19 918</td>
<td style="text-align: center;">11.24 %</td>
<td style="text-align: center;">5 166</td>
</tr>
<tr>
<td style="text-align: center;">11 juillet 2019</td>
<td style="text-align: center;">507 774</td>
<td style="text-align: center;">535 655</td>
<td style="text-align: center;">20 382</td>
<td style="text-align: center;">11.35 %</td>
<td style="text-align: center;">5 324</td>
</tr>
<tr>
<td style="text-align: center;">12 juillet 2019</td>
<td style="text-align: center;">511 412</td>
<td style="text-align: center;">539 493</td>
<td style="text-align: center;">19 463</td>
<td style="text-align: center;">11.44 %</td>
<td style="text-align: center;">3 838</td>
</tr>
<tr>
<td style="text-align: center;">13 juillet 2019</td>
<td style="text-align: center;">515 241</td>
<td style="text-align: center;">543 532</td>
<td style="text-align: center;">20 842</td>
<td style="text-align: center;">11.52 %</td>
<td style="text-align: center;">4 039</td>
</tr>
<tr>
<td style="text-align: center;">14 juillet 2019</td>
<td style="text-align: center;">519 581</td>
<td style="text-align: center;">548 110</td>
<td style="text-align: center;">21 224</td>
<td style="text-align: center;">11.62 %</td>
<td style="text-align: center;">4 578</td>
</tr>
<tr>
<td style="text-align: center;">15 juillet 2019</td>
<td style="text-align: center;">522 612</td>
<td style="text-align: center;">551 307</td>
<td style="text-align: center;">21 012</td>
<td style="text-align: center;">11.69 %</td>
<td style="text-align: center;">3 197</td>
</tr>
<tr>
<td style="text-align: center;">16 juillet 2019</td>
<td style="text-align: center;">525 269</td>
<td style="text-align: center;">554 110</td>
<td style="text-align: center;">22 194</td>
<td style="text-align: center;">11.75 %</td>
<td style="text-align: center;">2 803</td>
</tr>
<tr>
<td style="text-align: center;">17 juillet 2019</td>
<td style="text-align: center;">529 905</td>
<td style="text-align: center;">559 001</td>
<td style="text-align: center;">19 564</td>
<td style="text-align: center;">11.85 %</td>
<td style="text-align: center;">4 891</td>
</tr>
<tr>
<td style="text-align: center;">18 juillet 2019</td>
<td style="text-align: center;">533 954</td>
<td style="text-align: center;">563 272</td>
<td style="text-align: center;">21 814</td>
<td style="text-align: center;">11.94 %</td>
<td style="text-align: center;">4 271</td>
</tr>
<tr>
<td style="text-align: center;">19 juillet 2019</td>
<td style="text-align: center;">538 150</td>
<td style="text-align: center;">567 699</td>
<td style="text-align: center;">21 597</td>
<td style="text-align: center;">12.03 %</td>
<td style="text-align: center;">4 427</td>
</tr>
</tbody>
</table>
<p><img alt="Évolution du nombre de participation au réferendum ADP" src="/images/evolution.png" style="width: 80%;" /></p>
<p>Un compte twitter a été mis en ligne à l’adresse <a href="https://twitter.com/CompteurADP">https://twitter.com/CompteurADP</a> pour suivre cette évolution de manière régulière.</p>Renater et le surblocage: un cas d'école ?2019-04-04T00:00:00+02:002019-04-04T00:00:00+02:00Rémy Grünblatttag:remy.grunblatt.org,2019-04-04:/renater-et-le-surblocage-un-cas-decole.html<p>Le 27 novembre 2018, le tribunal de grande instance de Paris a ordonné le blocage du site raciste et nazi “DemocratieParticipative.biz”, nous rapporte <a href="https://www.nextinpact.com/news/107348-le-jugement-blocage-site-raciste-et-homophobe-democratieparticipative-biz.htm">NextINpact</a>. RENATER, Fournisseur d’Accès Internet (FAI) de nombreux laboratoires et universités françaises n’est pas concerné par ce jugement. Il a pourtant procédé au blocage …</p><p>Le 27 novembre 2018, le tribunal de grande instance de Paris a ordonné le blocage du site raciste et nazi “DemocratieParticipative.biz”, nous rapporte <a href="https://www.nextinpact.com/news/107348-le-jugement-blocage-site-raciste-et-homophobe-democratieparticipative-biz.htm">NextINpact</a>. RENATER, Fournisseur d’Accès Internet (FAI) de nombreux laboratoires et universités françaises n’est pas concerné par ce jugement. Il a pourtant procédé au blocage du site, bloquant par ailleurs de manière excessive d’autres sites, procédant ainsi à un « surblocage ».</p>
<h2 id="le-contenu-du-jugement">Le contenu du jugement<a class="headerlink" href="#le-contenu-du-jugement" title="Permanent link">¶</a></h2>
<p>Le jugement en question est un référé qui fait suite à l’assignation des principaux fournisseurs d’accès internet français par le procureur de la République de Paris, le 11 et 12 octobre 2018.
Dans <a href="/pdfs/tgi-paris-27-novembre-2018.pdf">le jugement</a> (document issu de NextINpact), des <em>« mesures de blocage »</em> effectuées de manière <em>« définitive et illimitée »</em> à l’encontre de <em>« du nom de domaine www.democratieparticipative.biz ou à tout site comportant le nom democratieparticipative.biz »</em> sont demandées aux fournisseurs d’accès à Internet suivants</p>
<ul>
<li>SFR Fibre;</li>
<li>Société française du radiotéléphone: SFR;</li>
<li>Société réunionnaise du radiotéléphone: SRR;</li>
<li>Orange;</li>
<li>Orange Caraïbe;</li>
<li>Bouygues Telecom;</li>
<li>Free;</li>
<li>Colt Technology Services;</li>
<li>Outremer Telecom.</li>
</ul>
<p>Il est tout d’abord intéressant de noter que dans le cas (plus récent) du <a href="/la-censure-de-sci-hub-et-libgen-vue-depuis-le-reseau-ripe-atlas.html">blocage de Sci-Hub et de LibGen</a>, la liste des fournisseurs d’accès est assez différente.
Dans ces deux affaires, le nombre de concernés est d’ailleurs ridiculeusement petit par rapport à la taille de la <a href="https://www.arcep.fr/professionnels.html">liste des opérateurs télécoms</a> déclarés à l’<a href="https://www.arcep.fr/">ARCEP</a>, Autorité de régulation des communications électroniques et des postes (la liste contient 2853 entités).</p>
<h2 id="un-blocage-au-niveau-dns-des-operateurs-concernes">Un blocage au niveau DNS des opérateurs concernés<a class="headerlink" href="#un-blocage-au-niveau-dns-des-operateurs-concernes" title="Permanent link">¶</a></h2>
<p>Grâce aux sondes <a href="https://atlas.ripe.net/">RIPE Atlas</a> déjà utilisées dans <a href="/la-censure-de-sci-hub-et-libgen-vue-depuis-le-reseau-ripe-atlas.html">l’article précédent</a>, il est possible de savoir comment le blocage est mis en place par les FAIs susmentionnés. Ainsi, Orange et Free bloquent l’accès au site en laissant leurs résolveurs renvoyer une adresse IP erronée (<code>127.0.0.1</code> au lieu de <code>104.27.185.150</code> et de <code>104.27.184.150</code>) lors de la résolution du nom de domaine du site. SFR renvoie une réponse vide, ou une réponse de type NXDOMAIN, tout comme Bouygues (<a href="https://atlas.ripe.net/measurements/20490345/#!probes">données brutes</a>).</p>
<p>Aucun blocage de « niveau 3 » n’est en place chez ces opérateurs: un ping tcp sur le port 80 vers l’adresse ip du site web aboutit généralement (<a href="https://atlas.ripe.net/measurements/20494929/#!probes">données brutes</a>).</p>
<h2 id="un-blocage-au-niveau-ip-de-la-part-de-renater">Un blocage au niveau IP de la part de RENATER…<a class="headerlink" href="#un-blocage-au-niveau-ip-de-la-part-de-renater" title="Permanent link">¶</a></h2>
<p>Quant à lui, RENATER annonce le blocage dans un mail envoyé à l’ensemble des établissements utilisant son réseau:</p>
<blockquote>
<p>Même si RENATER n’est pas formellement mentionné dans cet arrêt, un certain nombre d’utilisateurs pourraient se plaindre que RENATER laisse libre accès à ce site, dont le contenu a pourtant été jugé répréhensible au sens de la loi sur la liberté de la presse (loi du 29 juillet 1881). <strong>Nous devons donc nous sentir concernés par cette affaire.</strong>
Nous rappelons par ailleurs que, sauf cas particulier, l’accès à ce site n’est pas en accord avec la Charte déontologique de RENATER.
Ainsi, pour éviter à chaque établissement de prendre des mesures à son niveau, <strong>RENATER a mis en œuvre un dispositif rendant ce site inaccessible</strong>.
Pour autant, nous sommes bien sûr conscients de la forte probabilité pour que ces mesures soient rapidement contournées.</p>
</blockquote>
<p>RENATER ne fournissant pas de résolveur DNS, le FAI a procédé au blocage du site au niveau IP: toute communication avec l’adresse IP du site web est bloquée, comme on peut le voir sur <a href="https://atlas.ripe.net/measurements/20478910/#!tracemon">cette mesure</a>.</p>
<p><img alt="" src="/images/ripe-censorship.png" />
<em>Capture d’écran des résultats des mesures d’un TCP ping sur le port 80 vers l’adresse ip du site bloqué. En haut: les sondes RIPE Atlas représentées par des nœuds. En bas: l’AS hébergeant le site web. La communication ne peut pas être établie, souligné par la présence de pointillés oranges.</em></p>
<h3 id="menant-a-un-surblocage">… menant à un surblocage<a class="headerlink" href="#menant-a-un-surblocage" title="Permanent link">¶</a></h3>
<p>Problème, <code>DemocratieParticipative.biz</code> n’est pas le seul site hébergé utilisant cette adresse IP. En effet, l’adresse appartient à <a href="https://fr.wikipedia.org/wiki/Cloudflare">CloudFlare</a>, entreprise fournissant, entre autres, un service de <em>proxy inversé</em>, utilisé par ce site, mais aussi par des centaines d’autres qui partagent son adresse IP.</p>
<p>Pour avoir une liste de ces sites, il est possible de faire appel à un service comme <a href="https://dnslytics.com/ip/104.27.184.150">DNSlytics</a> qui fournit une association “Adresse IP -> Nom de domaine”.</p>
<p><img alt="" src="/images/dnslytics.png" />
<em>Capture d’écran du site DNSlytics.com</em></p>
<p>Ainsi, on assiste à un blocage illégitime de dizaines / centaines de sites, auxquels il n’est plus possible d’accéder:</p>
<ul>
<li><a href="https://www.masscience.com/">https://www.masscience.com/</a> : un site d’échange autour de la science, en langue espagnole;</li>
<li><a href="https://www.astrostones.com/">https://www.astrostones.com/</a> : un site de vente de bijoux;</li>
<li><a href="https://www.hopperslondon.com">https://www.hopperslondon.com</a> : un restaurant à Londres;</li>
<li><a href="https://www.justalittlepatience.com">https://www.justalittlepatience.com/</a> : un blog photo;</li>
<li>[…]</li>
</ul>
<p>Les symptomes sont facilement détectables, avec un simple traceroute:</p>
<div class="highlight"><pre><span></span><code><span class="c">% traceroute www.masscience.com</span>
<span class="n">traceroute</span><span class="w"> </span><span class="s">to</span><span class="w"> </span><span class="s">www.masscience.com</span><span class="w"> </span><span class="s">(104.27.184.150),</span><span class="w"> </span><span class="s">30</span><span class="w"> </span><span class="s">hops</span><span class="w"> </span><span class="s">max,</span><span class="w"> </span><span class="s">60</span><span class="w"> </span><span class="s">byte</span><span class="w"> </span><span class="s">packets</span>
<span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">_gateway</span><span class="w"> </span><span class="p">(</span><span class="n">X1</span><span class="p">.</span><span class="n">Y1</span><span class="p">.</span><span class="n">Z1</span><span class="p">.</span><span class="n">W1</span><span class="p">)</span><span class="w"> </span><span class="mf">3.004</span><span class="w"> </span><span class="n">ms</span><span class="w"> </span><span class="mf">3.564</span><span class="w"> </span><span class="n">ms</span><span class="w"> </span><span class="mf">3.612</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="n">subdomain</span><span class="p">.</span><span class="n">domain</span><span class="p">.</span><span class="n">tld</span><span class="w"> </span><span class="p">(</span><span class="n">X2</span><span class="p">.</span><span class="n">Y2</span><span class="p">.</span><span class="n">Z2</span><span class="p">.</span><span class="n">W2</span><span class="p">)</span><span class="w"> </span><span class="mf">2.860</span><span class="w"> </span><span class="n">ms</span><span class="w"> </span><span class="mf">2.949</span><span class="w"> </span><span class="n">ms</span><span class="w"> </span><span class="mf">3.041</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="n">X3</span><span class="p">.</span><span class="n">Y3</span><span class="p">.</span><span class="n">Z3</span><span class="p">.</span><span class="n">W3</span><span class="w"> </span><span class="p">(</span><span class="n">X3</span><span class="p">.</span><span class="n">Y3</span><span class="p">.</span><span class="n">Z3</span><span class="p">.</span><span class="n">W3</span><span class="p">)</span><span class="w"> </span><span class="mf">4.496</span><span class="w"> </span><span class="n">ms</span><span class="w"> </span><span class="mf">5.679</span><span class="w"> </span><span class="n">ms</span><span class="w"> </span><span class="mf">5.699</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="mf">193.55</span><span class="p">.</span><span class="mf">215.202</span><span class="w"> </span><span class="p">(</span><span class="mf">193.55</span><span class="p">.</span><span class="mf">215.202</span><span class="p">)</span><span class="w"> </span><span class="mf">4.735</span><span class="w"> </span><span class="n">ms</span><span class="w"> </span><span class="mf">5.369</span><span class="w"> </span><span class="n">ms</span><span class="w"> </span><span class="mf">5.374</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="mi">5</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span>
<span class="w"> </span><span class="mi">6</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span>
<span class="w"> </span><span class="mi">7</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span>
<span class="w"> </span><span class="p">[</span>…<span class="p">]</span>
<span class="w"> </span><span class="mi">28</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span>
<span class="w"> </span><span class="mi">29</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span>
<span class="w"> </span><span class="mi">30</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">*</span>
</code></pre></div>
<h2 id="au-fait-renater-cest-quoi">Au fait, Renater, c’est quoi?<a class="headerlink" href="#au-fait-renater-cest-quoi" title="Permanent link">¶</a></h2>
<p>Renater, Réseau national de télécommunications pour la technologie, l’enseignement et la recherche, est un groupement d’intérêt public, qui <em>« offre un réseau hautement fiable et sécurisé, facilitant la collaboration et la convergence de projets scientifiques et académiques au niveau national mais aussi européen et international »</em>, au service des <em>« des étudiants, chercheurs, enseignants et personnels de la communauté Education-Recherche »</em> ( d’après <a href="https://www.renater.fr/fr/le-reseau-RENATER">https://www.renater.fr/fr/le-reseau-RENATER</a> ).</p>
<h3 id="un-fai-ferme-au-public">Un FAI fermé au public…<a class="headerlink" href="#un-fai-ferme-au-public" title="Permanent link">¶</a></h3>
<p>Sur son site, l’entité se présente de cette manière: <em>« Au niveau national, RENATER fournit un accès internet et des services associés à plus de 1300 sites de la communauté Education – Recherche »</em>.</p>
<p>RENATER n’est cependant pas présent dans la liste des opérateurs télécoms de l’ARCEP. Cette dernière précise <em>« En application du code des postes et communications électroniques, l’établissement et l’exploitation des réseaux ouverts au public et la fourniture au public des services de communications électroniques sont libres, sous réserve d’une déclaration préalable auprès de l’Arcep. »</em>.</p>
<p>On en déduit donc que RENATER ne fournit pas de services de communications électroniques au public, car il n’apparait pas dans la liste de ces opérateurs télécoms.</p>
<h3 id="mais-utilise-dans-les-residences-etudiantes">… mais utilisé dans les résidences étudiantes<a class="headerlink" href="#mais-utilise-dans-les-residences-etudiantes" title="Permanent link">¶</a></h3>
<p>Ainsi, même si RENATER ne fournit pas de service au public, et n’est pas un FAI grand public, il est cependant utilisé comme tel par beaucoup d’étudiants des grandes écoles et universités françaises.</p>
<p>En effet, bon nombre de résidences étudiantes (notamment du CROUS, à en croire <a href="http://web.archive.org/web/20190403195510/https://www.renater.fr/sites/default/files/IMG/pdf/Charte-indivi-vf2013.pdf">la charte que doivent signer les utilisateurs</a>) sont branchées sur le réseau RENATER et fournissent Internet à leurs occupants par ce biais. Il n’est souvent pas possible aux étudiants de ces résidences d’utiliser un abonnement classique chez Free, Orange, SFR ou Bouygues pour se connecter à Internet, les forçant à utiliser la connexion de RENATER à des fins personnelles (en opposition avec la charte individuelle).</p>
<h2 id="le-mot-de-la-fin">Le mot de la fin<a class="headerlink" href="#le-mot-de-la-fin" title="Permanent link">¶</a></h2>
<p>On assiste donc à un « cas d’école »:</p>
<ul>
<li>RENATER bloque un site web, sans y être invité ou contraint par la justice;</li>
<li>Plusieurs dizaines / centaines de sites webs légitimes sont bloqués, victimes d’un surblocage;</li>
<li>RENATER n’ayant pas le statut d’opérateur télécom, pas certain que cette mesure soit couverte par la loi (mais, <a href="https://en.wikipedia.org/wiki/IANAL">I Am Not A Lawyer</a>);</li>
<li>Pourtant, il y a parfois peu de différence en pratique entre l’utilisation du réseau de RENATER avec celui d’un FAI grand public.</li>
</ul>La censure de Sci-Hub et LibGen vue depuis le réseau RIPE Atlas2019-03-30T00:00:00+01:002019-03-30T00:00:00+01:00Rémy Grünblatttag:remy.grunblatt.org,2019-03-30:/la-censure-de-sci-hub-et-libgen-vue-depuis-le-reseau-ripe-atlas.html<p><em>2 avril: ajout de détails concernant un éventuel blocage par Renater et concernant le tcp ping. Merci à Stéphane Bortzmeyer !</em></p>
<p><a href="https://sci-hub.se/">Sci-Hub</a> et <a href="http://libgen.io">LibGen</a> sont deux sites web de partages d’articles et d’ouvrages scientifiques (mais pas uniquement) fournissant un accès libre à des articles scientifiques en contournant les paywalls …</p><p><em>2 avril: ajout de détails concernant un éventuel blocage par Renater et concernant le tcp ping. Merci à Stéphane Bortzmeyer !</em></p>
<p><a href="https://sci-hub.se/">Sci-Hub</a> et <a href="http://libgen.io">LibGen</a> sont deux sites web de partages d’articles et d’ouvrages scientifiques (mais pas uniquement) fournissant un accès libre à des articles scientifiques en contournant les paywalls mis en place par les éditeurs desdits articles.</p>
<p>Le 7 mars 2019, les fournisseurs d’accès internet (FAI) classiques (Bouygues Télécom, Free, Orange et SFR) ont reçu l’ordre de procéder au blocage de ces sites, suite à une <a href="/pdfs/jugement-sci-hub-mars-2019.pdf">décision du tribunal de grande instance de Paris</a>, comme le rapporte <a href="https://www.nextinpact.com/news/107689-les-principaux-fai-francais-doivent-bloquer-sci-hub-et-libgen.htm">NextINpact</a> (source du document précédent).</p>
<p>Le jugement concerne un ensemble de 57 noms de domaines, tels que <code>sci-hub.tw</code>, <code>sci-hub.cat</code>, <code>libgen.io</code> ou <code>scihub.unblocked.app</code>, et demande la mise en place de <em>« toutes mesures propres à empêcher l’accès aux plateformes Sci-Hub et LibGen »</em>, pendant <em>« une durée de 12 mois à compter de la mise en œuvre des mesures ordonnées »</em>. L’actualisation de cette liste de site n’est pas automatique, et demande la saisie du juge des référés.</p>
<p>Comment cette censure est-elle mise en place par les FAIs concernés ?</p>
<p>D’autres FAIs ont-ils mis en place une telle censure, de leur propre initiative, sans être pourtant concernés par ce jugement ?</p>
<p>Pour répondre à ces questions, il est possible d’utiliser la plateforme RIPE Atlas.</p>
<h3 id="ripe-atlas">RIPE Atlas<a class="headerlink" href="#ripe-atlas" title="Permanent link">¶</a></h3>
<p>RIPE Atlas est une plateforme distribuée composée de sondes connectées à Internet que l’on peut controller à distance pour effectuer des mesures « réseau » comme un ping, un traceroute ou une résolution dns depuis ces dernières. On compte actuellement plus de 10 000 sondes en activité, dont la majorité est située aux États-Unis et en Europe.</p>
<p><img alt="Capture d'écran de la [carte des sondes RIPE Atlas" src="/images/ripe-atlas-map.png"><br/>
<em>Capture d'écran de la <a href="https://atlas.ripe.net/results/maps/network-coverage/">carte des sondes RIPE Atlas</a>.</em></p>
<p>Atlas permet de choisir l’origine et la destination de ces mesures, par exemple, pour n’utiliser que des sondes connectées à Internet en utilisant l’opérateur Orange, ou pour n’obtenir que les résultats de sondes situées physiquement en France (chaque propriétaire de sonde ayant renseigné l’emplacement géographique de cette dernière).</p>
<p>Il est donc possible de vérifier si la résolution d’un nom de domaine (celui de Sci-Hub et de LibGen) est correcte, ou si l’on a affaire à un <a href="https://fr.wikipedia.org/wiki/Manipulation_de_l%27espace_des_noms_de_domaine">DNS Menteur</a>, c’est-à-dire à un serveur qui manipule les données pour, par exemple, empêcher l’accès à un site web (i.e. de la censure).</p>
<h3 id="mesures-sur-les-sondes-francaises">Mesures sur les sondes françaises<a class="headerlink" href="#mesures-sur-les-sondes-francaises" title="Permanent link">¶</a></h3>
<p>Il y a 1933 sondes localisées en France actuellement, mais seulement une partie est connectée à internet et disponible à l’utilisation.</p>
<p>Pour interroger ces sondes, on utilise l’outil <a href="https://framagit.org/bortzmeyer/blaeu">blaeu</a> développé par <a href="https://fr.wikipedia.org/wiki/St%C3%A9phane_Bortzmeyer">Stéphane Bortzmeyer</a> en lui précisant quelles sont les sondes que l’on souhaite utiliser (dans notre cas, des sondes localisées en France).</p>
<p>Une liste de l’ensemble des sondes disponibles ainsi que les numéros d’<a href="https://fr.wikipedia.org/wiki/Autonomous_System">Autonomous System</a> associés (en IPv6 et IPv4) peuvent être obtenus en utilisant les données disponibles sur <a href="https://ftp.ripe.net/ripe/atlas/probes/archive/2019/03/">cette page d’archive</a>.</p>
<p>On limite pour l’instant la mesure à la résolution des noms de domaines principaux des deux plateformes, c’est-à-dire <code>libgen.io</code> et <code>sci-hub.se</code>, et on effectue des mesures en IPv4 sur 1000 sondes, le maximum pour une unique mesure:</p>
<div class="highlight"><pre><span></span><code><span class="nx">blaeu</span><span class="o">-</span><span class="nx">resolve</span><span class="w"> </span><span class="o">--</span><span class="nx">country</span><span class="p">=</span><span class="nx">FR</span><span class="w"> </span><span class="o">--</span><span class="nx">requested</span><span class="p">=</span><span class="mi">1000</span><span class="w"> </span><span class="o">--</span><span class="nx">ipv4</span><span class="w"> </span><span class="o">--</span><span class="k">type</span><span class="w"> </span><span class="nx">A</span><span class="w"> </span><span class="nx">libgen</span><span class="p">.</span><span class="nx">io</span>
<span class="nx">blaeu</span><span class="o">-</span><span class="nx">resolve</span><span class="w"> </span><span class="o">--</span><span class="nx">country</span><span class="p">=</span><span class="nx">FR</span><span class="w"> </span><span class="o">--</span><span class="nx">requested</span><span class="p">=</span><span class="mi">1000</span><span class="w"> </span><span class="o">--</span><span class="nx">ipv4</span><span class="w"> </span><span class="o">--</span><span class="k">type</span><span class="w"> </span><span class="nx">A</span><span class="w"> </span><span class="nx">sci</span><span class="o">-</span><span class="nx">hub</span><span class="p">.</span><span class="nx">se</span>
</code></pre></div>
<p>On effectue aussi une mesure d’accessibilité de l’adresse ip <code>93.174.95.87</code> (vers laquelle <code>libgen.io</code> pointe) afin de déterminer si un blocage au niveau IP est effectué (il n’est pas possible de faire ce test avec <code>sci-hub.se</code> qui semble de toute façon bloquer les ping):</p>
<div class="highlight"><pre><span></span><code>blaeu-reach --country=FR --requested=1000 93.174.95.87
</code></pre></div>
<p>Les résultats bruts sont disponibles aux adresses suivantes: <a href="https://atlas.ripe.net/measurements/20436655/">1</a>, <a href="https://atlas.ripe.net/measurements/20436656/">2</a> et <a href="https://atlas.ripe.net/measurements/20437326/">3</a>.</p>
<h3 id="differentes-strategies-de-censure">Différentes stratégies de censure<a class="headerlink" href="#differentes-strategies-de-censure" title="Permanent link">¶</a></h3>
<p>En analysant les résultats, on remarque différentes stratégies de censure selon les opérateurs, uniquement au niveau DNS (en utilisant les DNS de l’opérateur):</p>
<ul>
<li>Orange (AS 3215): une réponse invalide est renvoyée (<code>127.0.0.1</code>);</li>
<li>Bouygues Télecom (AS 5410): Une réponse de type NXDOMAIN est renvoyée;</li>
<li>SFR/Cegetel/Numericable (AS 15557, 21502 et 8228): Une réponse de type NXDOMAIN est renvoyée;</li>
<li>Free (AS 12322): aucun blocage DNS n’est en place (au 30 mars 2019).</li>
</ul>
<p>Par ailleurs, presque l’ensemble des sondes a accès au niveau IP à <code>libgen.io</code>, en tout cas pour des requêtes de type ping (il est possible qu’un filtrage soit en place uniquement pour des requêtes http sur le port 80 ou 443 (port <code>http</code> et <code>https</code>), mais cela est peu probable).</p>
<p>Pour vérifier cette hypothèse, Stéphane Bortzmeyer me précise par email qu’il est possible d’utiliser un <a href="https://labs.ripe.net/Members/wilhelm/measuring-your-web-server-reachability-with-tcp-ping">tcp ping</a>, et confirme, par le biais <a href="https://atlas.ripe.net/measurements/20478697/# !tracemon">d’une nouvelle mesure</a> qu’un tel blocage (« niveau 3 » de la couche OSI) n’est pas en place.</p>
<p>Un unique autre AS est associé à des réponses erronées (de type <code>127.0.0.1</code>) dans les résultats obtenus: l’AS 35540, correspondant à OVH. En examinant les adresses des résolveurs utilisés, on remarque qu’elles sont du type <code>192.168.100.1</code> et <code>192.168.0.100</code>, adresses utilisées par défaut dans les solutions de type <a href="https://www.ovhtelecom.fr/overthebox/">OverTheBox</a> permettant l’agrégation de plusieurs connexions à internet. L’une de ces connexions est probablement fournie par Orange, et utilise les DNS d’Orange.</p>
<h3 id="et-renater-dans-tout-ca">Et Renater dans tout ça ?<a class="headerlink" href="#et-renater-dans-tout-ca" title="Permanent link">¶</a></h3>
<p>Il apparait que RENATER, réseau de télécommunications français reliant les différents établissements d’enseignement et de recherche entre eux, et à ce titre particulièrement lié à cette problématique, n’a pas mis en place de blocage (Renater ne fournissant pas de résolveurs dns, il serait nécessaire de bloquer au niveau “ip” pour empêcher l’accès à ces sites). La pertinence d’une telle demande de blocage auprès de fournisseurs d’accès grand public apparait alors comme assez limitée, me semble-t-il, une grosse partie des utilisateurs de sci-hub utilisant probablement ce FAI.</p>
<p>L’année dernière, RENATER avait procédé au blocage d’un site de sa propre initiative, au titre qu’ <em>« un certain nombre d’utilisateurs pourraient se plaindre que RENATER laisse libre accès à ce site, dont le contenu a pourtant été jugé répréhensible au sens de la loi sur la liberté de la presse »</em>. Il reste donc à déterminer si il fera de même pour sci-hub et libgen.</p>Capteur de glycémie Freestyle Libre: un peu trop bavard?2019-03-05T00:00:00+01:002019-03-05T00:00:00+01:00Rémy Grünblatttag:remy.grunblatt.org,2019-03-05:/capteur-de-glycemie-freestyle-libre-un-peu-trop-bavard.html<p>Le capteur <a href="https://www.freestylelibre.fr/libre/">Freestyle Libre</a> de Abbott est un capteur à glycémie qui se pose sur le bras et permet de mesurer la glycémie « en continu » à l’aide d’un <a href="https://www.freestylelibre.fr/libre/produits/lecteur.html">lecteur physique</a> ou d’une <a href="https://www.freestylelibre.fr/libre/produits/applicationmobilelibrelink.html">application android</a>.</p>
<p>Ce dispositif médical est remboursé par la sécurité sociale depuis mai 2017 (<a href="https://www.legifrance.gouv.fr/affichTexte.do;jsessionid=80B4EC3F0762957F7A9CE9A46A2346B4.tpdila13v_3?cidTexte=JORFTEXT000034580576&dateTexte=&oldAction=rechJO&categorieLien=id&idJO=JORFCONT000034579357">arrêté …</a></p><p>Le capteur <a href="https://www.freestylelibre.fr/libre/">Freestyle Libre</a> de Abbott est un capteur à glycémie qui se pose sur le bras et permet de mesurer la glycémie « en continu » à l’aide d’un <a href="https://www.freestylelibre.fr/libre/produits/lecteur.html">lecteur physique</a> ou d’une <a href="https://www.freestylelibre.fr/libre/produits/applicationmobilelibrelink.html">application android</a>.</p>
<p>Ce dispositif médical est remboursé par la sécurité sociale depuis mai 2017 (<a href="https://www.legifrance.gouv.fr/affichTexte.do;jsessionid=80B4EC3F0762957F7A9CE9A46A2346B4.tpdila13v_3?cidTexte=JORFTEXT000034580576&dateTexte=&oldAction=rechJO&categorieLien=id&idJO=JORFCONT000034579357">arrêté du 4 mai 2017</a> correspondant)). Il est décrit comme permettant la « mesure du glucose interstitiel dans le traitement des patients atteints d’un diabète de type 1 ou de type 2 ».</p>
<p>Dans cet article, je m’intéresse aux implications sur la vie privée que peut avoir un tel dispositif.</p>
<h1 id="communication-entre-le-lecteur-et-le-capteur-et-application-android">Communication entre le lecteur et le capteur et application Android<a class="headerlink" href="#communication-entre-le-lecteur-et-le-capteur-et-application-android" title="Permanent link">¶</a></h1>
<p>Ce qui interpelle, premièrement, c’est la possibilité d’utiliser un téléphone portable pour effectuer une telle mesure. On comprend vite que ces capteurs communiquent en RFID, ce qui est confirmé par le matériel présent dans le capteur, une puce <a href="http://www.ti.com/product/RF430FRL152H">RF430FRL152H</a> de Texas Instrument qui implémente ISO/IEC 15693, un protocole pour des communications « longue distances » jusqu’à « 1,5 mètre », et la norme ISO/IEC 18000-3. En pratique, le wiki de Digi-Key affirme que la portée est <a href="https://www.digikey.com/eewiki/display/Wireless/Getting+Started+with+the+TI+RF430FRL152HEVM">au maximum de 50 cm</a> (« It should also be noted that the range for the RF430FRL152 tops out at roughly 50cm »), et des <a href="http://e2e.ti.com/support/wireless-connectivity/other-wireless/f/667/p/711850/2625062#">tests semblent confirmer</a> une portée possible d’environ 30 cm.</p>
<p>En essayant d’utiliser l’application « officielle », on est accueilli par des CGUs et un <a href="http://web.archive.org/web/20190112114658/https://freestyleserver.com/Payloads/Mobile/fsllPrivacyNotice/DOC38902-003_rev-A_fr-FR.html"><em>avis de confidentialité</em></a> de 3km de long, et on est obligé de créer un compte: très peu pour moi, il n’est pas question que je signe un tel contrat. Exit donc cette application, qui semble d’ailleurs communiquer principalement avec les services d’Amazon, et de Google (pour ce dernier, on peut se fier à l’<a href="https://reports.exodus-privacy.eu.org/en/reports/12515/">analyse automatisée</a> de l’application par Exodus Privacy).</p>
<p>Je découvre alors qu’il existe d’autres applications qui prétendent pouvoir lire ces données: <a href="https://play.google.com/store/apps/details?id=it.ct.glicemia">Glimp</a>, <a href="https://play.google.com/store/apps/details?id=de.cm.liapp">Liapp</a>, <a href="https://play.google.com/store/apps/details?id=net.srey.android.glycemia">Glycemia</a>, etc… On en installe donc une, par exemple Glimp, et on tente la lecture d’un capteur.</p>
<p>Surprise. Ça fonctionne. Avec Glimp et Liapp, en tout cas, on obtient des courbes semblables à celles qui ont été obtenues par une lecture avec l’appareil officiel:</p>
<p><img alt="Mesure avec le Freestyle Libre" src="/images/freestyle_libre.jpg" style="width: 250px;" />
<img alt="Mesure avec l'application Glimp" src="/images/Glimp.jpg" style="width: 250px;" />
<img alt="Mesure avec l'application Liapp" src="/images/Liapp.jpg" style="width: 250px;" /></p>
<p><strong>Pourquoi est-ce surprenant?</strong> Car la mesure n’est pas authentifiée: le téléphone est un parfait inconnu aux yeux du capteur, qui renvoie sans broncher une mesure d’un paramètre vital de son porteur. Ainsi, <strong>n’importe qui avec une telle application peut récupérer en un instant jusqu’à 8h d’historique de la glycémie du porteur</strong>.</p>
<p>On remarque par ailleurs que la mesure immédiate n’est pas la même (208 mg/dL contre 189 mg/dL), mais l’allure de la courbe est la bonne. Cela souligne sûrement que l’association « données renvoyées par le capteur » -> « Glycémie » est faite en logiciel plutôt qu’au niveau matériel.</p>
<p>Désormais que l’on sait que les données ne sont pas chiffrées, la question se pose: jusqu’à quelle distance peut-on récupérer ces données? Peut-on imaginer qu’il soit possible pour un publicitaire de détecter qu’un passant porte un tel dispositif médical, et de lui afficher une publicité ciblée, par exemple sur des produits faibles en glucides? Voir, pour un parfait inconnu, de récupérer la glycémie de l’ensemble des personnes dans un certain rayon?</p>
<p>À suivre…</p>Prises de positions officielles sur le projet « Bienvenue en France »2018-12-04T00:00:00+01:002018-12-04T00:00:00+01:00Rémy Grünblatttag:remy.grunblatt.org,2018-12-04:/prises-de-positions-officielles-sur-le-projet-bienvenue-en-france.html<p>Suite à l’annonce du projet « Bienvenue en France » par le gouvernement, dont l’un des points prévoit l’augmentation des frais d’inscription pour les étudiants du supérieur hors Union Européenne, Espace Économique Européen, Suisse et Québec ( 2 770 euros pour une année en cycle de Licence, 3 770 …</p><p>Suite à l’annonce du projet « Bienvenue en France » par le gouvernement, dont l’un des points prévoit l’augmentation des frais d’inscription pour les étudiants du supérieur hors Union Européenne, Espace Économique Européen, Suisse et Québec ( 2 770 euros pour une année en cycle de Licence, 3 770 euros pour une année en cycle Master, 3 770 euros pour une année en cycle de Doctorat), plusieurs établissement du supérieur ont pris position.</p>
<p>Cet article détaille le contenu de ces prises de positions, avec des liens vers les dites prises de position. Si vous connaissez d’autres prises de position « officielles », merci de m’envoyer un mail à remy[at]grunblatt.org pour que je puisse mettre à jour cette page!</p>
<h2 id="sorbonne-universite">Sorbonne Université<a class="headerlink" href="#sorbonne-universite" title="Permanent link">¶</a></h2>
<h3 id="conseil-dadministration-de-sorbonne-universite">Conseil d’Administration de Sorbonne Université<a class="headerlink" href="#conseil-dadministration-de-sorbonne-universite" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le Conseil d’Administration de Sorbonne Université a toujours défendu une université de service public visant tout à la fois le développement d’une recherche de pointe et des formations exigeantes ouvertes à toutes et tous.</p>
<p>Trois mesures annoncées vont dans ce sens : la facilitation d’un visa pluriannuel pour les étudiants étrangers, l’amélioration de leur accueil et pour les diplômés, la possibilité de rester ou revenir travailler en France.</p>
<p>En revanche, l’augmentation importante des droits d’inscription pour les étudiants extra-communautaires contrevient à ces principes fondamentaux.</p>
<p>Le Conseil d’Administration désapprouve cette mesure.</p>
<p>Motion adoptée à l’unanimité le 11 décembre 2018</p>
</blockquote>
<p>Source: <a href="/pdfs/Sorbonne.pdf">Motion du CA de Sorbonne Université</a></p>
<h2 id="agroparistech">AgroParisTech<a class="headerlink" href="#agroparistech" title="Permanent link">¶</a></h2>
<h3 id="conseil-dadministration-de-agroparistech">Conseil d’administration de AgroParisTech<a class="headerlink" href="#conseil-dadministration-de-agroparistech" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le conseil d’administration d’AgroParisTech, réuni dans sa séance du 04 décembre 2018, se pronence fermement contre la hausse discriminatoire des frais d’inscription dans l’enseignement supérieur, ciblant les étrangères et étrangers extra-communautaires, annoncée par le Premier ministre Édouard Philippe. Il adresse toute sa solidarité aux étudiantes et étudiants, doctorantes et doctorants étrangers que notre établissement accueille aujourd’hui ou souhaite accueillir à l’avenir. Il exprime à ses Ministères de tutelle son souhait du maintien de frais d’inscription nationaux pour les ressortissants des “économies en développement” et “économies en transition” (selon la définition de la CNUCED).</p>
</blockquote>
<p>Source: <a href="/pdfs/Motion_CA du 4 décembre.pdf">Motion du CA de l’université AgroParisTech</a></p>
<h2 id="universite-de-lille">Université de Lille<a class="headerlink" href="#universite-de-lille" title="Permanent link">¶</a></h2>
<h3 id="presidence-universite-de-lille">Présidence Université de Lille<a class="headerlink" href="#presidence-universite-de-lille" title="Permanent link">¶</a></h3>
<blockquote>
<p>Chères et chers collègues,
Chères étudiantes et chers étudiants,</p>
<p>Le Ministère de l’Enseignement supérieur et de la Recherche a décidé, dans le cadre d’un programme nommé « Bienvenue en France / Choose France », de différencier les droits d’inscription des étudiants, à partir de la rentrée universitaire 2019 dans toutes les universités françaises.</p>
<p>**Les nouveaux droits d’inscription des étudiants étrangers non européens **</p>
<p>Les universités ont été informées de cette décision relative aux nouveaux droits d’inscription des étudiants étrangers non européens fin novembre par un communiqué du cabinet de la Ministre de l’Enseignement supérieur et de la Recherche. Des discussions ont lieu actuellement entre les universités et le Ministère sur les modalités et les conséquences d’une telle mesure.</p>
<p>Attaché à un service public de qualité accessible à tous sans condition de nationalité et à la dimension internationale de notre université, notre conseil d’administration a adopté collégialement dès le 22 novembre une motion qui /«//désapprouve le projet de hausse spectaculaire dès la rentrée 2019 des frais d’inscriptions pour les étudiant.e.s extérieur.e.s à l’Espace Économique Européen //»/ et souligne son inquiétude à l’égard des conséquences qu’une telle mesure, si elle n’était pas compensée, aurait sur les formations et la recherche de l’Université de Lille.</p>
<blockquote>
<p>[…]</p>
</blockquote>
<p>Le Ministère laisserait à chaque établissement la possibilité de développer sa propre politique d’exonération des frais d’inscription et de bourses. Cette possibilité sera encadrée par le Ministère selon des critères à définir. Il a été évoqué, par exemple, un plafond d’exonération sous forme d’un pourcentage maximum d’étudiants pouvant être exonérés.</p>
<p>L’Université de Lille utilisera, le cas échéant, cette possibilité d’exonération pour atténuer les effets de ce programme.</p>
<p>[…]</p>
<p>*Jean-Christophe Camart *</p>
</blockquote>
<p>Source: Droits d’inscription des étudiants non européens à l’Université de Lille, mail envoyé sur les listes du personnel et des étudiants</p>
<h2 id="universite-grenoble-alpes">Université Grenoble Alpes<a class="headerlink" href="#universite-grenoble-alpes" title="Permanent link">¶</a></h2>
<h3 id="conseil-academique-de-la-comue">Conseil Académique de la ComUE<a class="headerlink" href="#conseil-academique-de-la-comue" title="Permanent link">¶</a></h3>
<blockquote>
<p>Motion du Conseil Académique</p>
<p>Suite à l’annonce du Gouvernement du 19 novembre 2018, relative à l’augmentation des droits d’inscription pour les étudiants extra-communautaires</p>
<p>Le Conseil Académique de la ComUE Université Grenoble Alpes, attaché aux valeurs d’ouverture et d’accueil de la diversité qui sont celles de l’université, exprime ses inquiétudes et ses fortes réticences par rapport aux récentes mesures annoncées par le Gouvernement d’augmentation importante des droits d’inscription pour les étudiants extra-communautaires dans les différents cycles de formation.</p>
<p>Il regrette la méthode employée par le gouvernement et l’absence de concertation sur un sujet majeur et complexe qui mérite un large débat.</p>
<p>Le Conseil Académique de la ComUE Université Grenoble Alpes juge ces mesures discriminatoires, potentiellement nuisibles au rayonnement de la francophonie et plus généralement au rayonnement international de l’enseignement supérieur et de la recherche.</p>
<p>C’est pourquoi il demande au gouvernement de revenir sur cette décision.</p>
<p>Il se tient prêt à contribuer à une large réflexion sur les moyens de renforcer l’attractivité de nos établissements, les conditions d’accueil et d’accompagnement des étudiants étrangers en France.</p>
<p>La Présidente de la Communauté Université Grenoble Alpes transmettra l’avis du Conseil Académique au Ministère de l’Enseignement Supérieur, de la Recherche et de l’Innovation.</p>
</blockquote>
<p>Source: <a href="/pdfs/grenoble-alpes.pdf">Augmentation des droits d’inscription des étudiants étrangers (hors UE)</a></p>
<h2 id="universite-paris-sud">Université Paris-Sud<a class="headerlink" href="#universite-paris-sud" title="Permanent link">¶</a></h2>
<h3 id="conseils-cac-et-ca-de-luniversite-paris-sud">conseils CAC et CA de l’Université Paris-Sud<a class="headerlink" href="#conseils-cac-et-ca-de-luniversite-paris-sud" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le 19 novembre, le Premier Ministre a annoncé la mise en place, dès la rentrée 2019, d’une série de mesures dans le cadre d’une stratégie internationale globale pour l’enseignement supérieur français. A côté de mesures portant sur la simplification de procédures d’obtention de visas et de titres de séjours pour permettre par exemple aux étudiants étrangers de venir travailler en France, ou encore sur la création de fonds destinés à aider les universités à améliorer leur accueil et leur développement à l’international, l’une d’entre elles concerne la mise en place de droits d’inscription « différenciés » pour certains étudiants extra-communautaires, fixés au tiers du coût réel des formations, soit 2770€ en 1er cycle et 3770€ en Master, école interne et en Doctorat. Ces droits d’inscriptions, versés aux établissements, sont supposés leur permettre de développer leur politique d’accueil (amélioration des dispositifs d’accueil et mise en place de bourses d’établissement par exemple).</p>
<p>L’impact de ces frais différenciés inquiète fortement les membres des deux conseils de l’Université Paris-Sud. La mission de l’université est d’accueillir un grand nombre d’étudiants d’origines diverses pour les accompagner vers la réussite. Même si une augmentation du nombre de bourses du gouvernement a été annoncée simultanément par le ministère, notamment pour attirer les meilleurs étudiants, les deux conseils redoutent les conséquences de cette mesure concernant les droits d’inscription, sur les étudiants les plus pauvres, notamment ceux issus des pays en voie de développement, qui, déjà, ont à prendre en charge des frais conséquents à l’arrivée en France (visas, transports, logement, etc.).</p>
<p>Des actions doivent nécessairement être mises en œuvre afin de mener à la réussite de ces publics souvent en difficulté.</p>
<p>NOUS DEMANDONS DONC UN MORATOIRE AFIN D’ENGAGER UN TRAVAIL DE CONCERTATION.</p>
<p>En cas de maintien d’une application pour la rentrée 2019, et en accord avec les conseils, la présidence proposera au conseil d’administration de voter le maintien de droit identiques entre les étudiants nationaux et extra communautaires</p>
<p>Sylvie Retailleau, Présidente de l’Université Paris-Sud </p>
</blockquote>
<p>Source: Annonce de presidence@u-psud.fr: Motion relative aux droits d’inscription pour les étudiants extra communautaires </p>
<h2 id="universite-paris-est-creteil-val-de-marne">Université Paris Est Créteil Val de Marne<a class="headerlink" href="#universite-paris-est-creteil-val-de-marne" title="Permanent link">¶</a></h2>
<h3 id="president-de-luniversite-et-son-equipe">Président de l’université et son équipe<a class="headerlink" href="#president-de-luniversite-et-son-equipe" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le Premier Ministre Edouard Philippe a annoncé une forte augmentation des droits d’inscription pour les étrangers n’appartenant pas à la communauté européenne (2 770 euros par an pour le niveau L au lieu de 170 euros ; 3 770 euros pour les niveaux M et D, au lieu de 243 euros et 380 euros). Ces tarifs sont publiés sur le site de Campus France, sans qu’un arrêté ait encore été pris.</p>
<p>Plus qu’un supposé label de qualité pour les formations dispensées par les universités françaises, de tels droits d’inscription sont de nature à empêcher une grande proportion des étudiants étrangers de venir étudier en France, à commencer par les plus fragiles économiquement. Cette mesure touchera en particulier des étudiants venus du Maghreb et d’Afrique subsaharienne, qui représentent 45 % des étudiants étrangers en France. Obstacle à l’attractivité internationale et à la démocratisation de notre enseignement supérieur, cette mesure est contradictoire avec la volonté affichée par le gouvernement de passer de 320 000 étudiants étrangers actuellement accueillis en France à 500 000 d’ici à 2027, et de mener une politique active au service du développement. Cette soudaine élévation des tarifs n’est pas non plus ce qui permettra de capter de nouveaux flux d’étudiants issus de pays émergeants attirés par des universités anglophones.</p>
<p>Dans un contexte de mondialisation accélérée, accueillir des étudiants étrangers est en effet une chance : ils sont des acteurs essentiels des échanges scientifiques, économiques et culturels entre la France et leur pays d’origine. Ils participent au rayonnement de l’Université et de la culture françaises, dans une société globalisée et ouverte sur le monde. Le partage des savoirs et des cultures sont des fondements essentiels de la construction d’une société démocratique et inclusive.</p>
<p>Repousser les étrangers non communautaires en grand nombre, à commencer par de nombreux étudiants francophones, ce serait tourner le dos à une société envisageant l’avenir de manière confiante et dynamique, une société à la fois enracinée dans la richesse de la diversité de cultures et ouverte sur la créativité / fécondité des échanges scientifiques, économiques et culturels internationaux.
Opposés à cette hausse des droits d’inscription pour les étudiants hors de la communauté européenne, nous voulons pouvoir continuer d’accueillir les étudiants étrangers qui souhaitent venir étudier en France et qui en ont les capacités, sans distinction d’origine et sans que des barrières soient érigées à l’encontre des étudiants les plus fragiles économiquement.</p>
<p>Notre vision de l’Université est humaniste et ancrée dans l’esprit des Lumières. Universelle, elle s’enrichit de la diversité culturelle et s’ouvre largement sur le monde.</p>
<p>Nous demandons que les dispositions tarifaires concernant les étudiants étrangers hors de la communauté européenne soient reconsidérées conformément aux valeurs fondatrices de l’Université publique française. </p>
</blockquote>
<p>Source: <a href="http://www.u-pec.fr/universite/actualites/accueillir-des-etudiants-etrangers-une-chance-pour-l-universite-francaise-877724.kjsp">Accueillir des étudiants étrangers : une chance pour l’Université française (site web de l’université)</a></p>
<h2 id="universite-de-nantes">Université de Nantes<a class="headerlink" href="#universite-de-nantes" title="Permanent link">¶</a></h2>
<h3 id="president-de-luniversite-les-vice-presidents-et-les-conseillers">Président de l’Université, les Vice-présidents et les Conseillers<a class="headerlink" href="#president-de-luniversite-les-vice-presidents-et-les-conseillers" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le Président, les Vice-présidents et les Conseillers de l’Université de Nantes ont transmis un message à l’ensemble des personnels et des étudiants pour faire part de leur position sur l’annonce de l’augmentation des droits d’inscription pour les étudiants étrangers hors Union européenne.</p>
<p>Dans son allocution du 19 novembre dernier présentant la stratégie d’attractivité pour les étudiants internationaux, le Premier ministre a, parmi d’autres dispositions, annoncé l’augmentation substantielle des droits d’inscription pour les étudiants étrangers hors Union européenne.</p>
<p>Si l’amélioration de l’accueil des étudiants étrangers est évidemment une nécessité, la mesure proposée ne nous paraît, pour autant, ni pertinente, ni juste.
Entre désir d’attractivité et politique migratoire, cette augmentation concerne les étudiants parmi les plus fragiles. C’est une discrimination par l’argent qui risque de nous priver de nombreux talents. C’est aussi un coup dur porté à la francophonie qui est une chance pour notre pays.</p>
<p>Cette mesure pourrait apparaître comme le prélude à une hausse des frais étendue à tous les étudiants. Nous rappelons ici que les droits d’inscriptions ne peuvent et ne doivent pas être le moyen de compenser les sous-dotations des universités.</p>
<p>Le Président de l’Université de Nantes et son équipe demandent donc que cette mesure soit reconsidérée dans le respect du principe d’égalité de traitement entre usagers du service public de l’enseignement supérieur et de la recherche.</p>
<p>Le Président, les Vice-présidents et les Conseillers </p>
</blockquote>
<p>Source: <a href="https://unnews.univ-nantes.fr/pour-un-accueil-sans-discrimination-des-etudiants-etrangers-dans-les-universites-francaises-2364138.kjsp">Pour un accueil sans discrimination des étudiants étrangers dans les universités françaises - Site web de l’université</a></p>
<h2 id="ecole-normale-superieure">École Normale Supérieure<a class="headerlink" href="#ecole-normale-superieure" title="Permanent link">¶</a></h2>
<h3 id="conseil-dadministration">Conseil d’Administration<a class="headerlink" href="#conseil-dadministration" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le conseil d’administration de l’École normale supérieure réaffirme son attachement à l’ouverture de l’École à tous les étudiants sans distinction de nationalité. Il proteste contre les mesures récemment annoncées concernant les droits d’inscription des étudiants internationaux extracommunautaires en France, réprouve la méthode même qui consiste à prendre la question des droits d’inscription sous l’angle des étudiants étrangers au mépris des traditions de l’accueil universitaire, regrette l’absence de concertation préalable avec les établissements et d’information sur les modalités d’application de ces mesures, attire l’attention sur la situation spécifique des demandeurs d’asile.</p>
</blockquote>
<p>Source: Motion du Conseil d’administation de l’École Normale Supérieure, le 3 décembre 2018</p>
<h2 id="paris-1-pantheon-sorbonne">Paris 1 Panthéon-Sorbonne<a class="headerlink" href="#paris-1-pantheon-sorbonne" title="Permanent link">¶</a></h2>
<h3 id="conseil-academique">Conseil Académique<a class="headerlink" href="#conseil-academique" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le Conseil Académique de Paris 1 Panthéon-Sorbonne se prononce fermement contre la hausse discriminatoire des frais d’inscription dans l’enseignement supérieur, ciblant les étrangères et étrangers extra-européens annoncée par le Premier ministre Édouard Philippe.</p>
<p>Il exprime toute sa solidarité aux étudiantes et étudiants, doctorantes et doctorants étrangers que notre établissement accueille aujourd’hui ou souhaite accueillir à l’avenir. Il demande au président de l’université de relayer auprès de la CPU et du ministère de l’Enseignement supérieur, de la Recherche et de l’Innovation (MESRI) sa dénonciation de cette décision inique afin que le MESRI renonce à faire rentrer en vigueur cette disposition. Le Conseil Académique demande instamment au gouvernement de renoncer à ce projet.</p>
<blockquote>
<p>Cette motion est communiquée directement au ministère par le président de l’université.</p>
</blockquote>
</blockquote>
<p>Source: Conseil Académique de Paris 1</p>
<h2 id="alliance-des-universites-de-recherche-et-de-formation-auref">Alliance des universités de recherche et de formation (AUREF)<a class="headerlink" href="#alliance-des-universites-de-recherche-et-de-formation-auref" title="Permanent link">¶</a></h2>
<blockquote>
<p>Cette mesure interroge le principe d’une Université française ouverte à tous et la stratégie internationale de la France en matière d’accueil des étudiants étrangers et de développement de la francophonie alors que la France est le premier pays d’accueil non anglophone. Cela pose aussi la question de la conformité de cette augmentation avec la constitution de 1958, qui dispose que «l’organisation de l’enseignement public gratuit et laïc à tous les degrés est un devoir de l’État. »</p>
<p>[…]</p>
<p>Ainsi, il apparait clairement que le gain attendu de ces droits différenciés pour l’inscription dans une filière menant à un diplôme national sera sans commune mesure avec la somme des effets négatifs que cela générera, tant du point de vue humain que scientifique, stratégique ou économique. Au demeurant, les ressources générées, diminuées par le doublement annoncé des bourses de l’Etat français et par le financement des mesures d’accueil supplémentaires annoncées spécifiquement pour les étudiants internationaux, ne permettrontpas de répondre à la question récurrente du sous-financement des universités.</p>
<p>Ainsi l’AUREF considère que la mise en place de droits d’inscription différenciés, faite sans concertation, aura un effet globalement négatif pour la France et la francophonie. En tout état de cause, cela n’évitera pas le débat nécessaire sur la stratégie générale de l’Etat en ce qui concerne l’avenir et le financement del’enseignement supérieur et de la recherche publics dans un cadre constitutionnel qui affirme sa gratuité.</p>
</blockquote>
<p><a href="/pdfs/droits-inscription-hors-ue-vf-1.pdf">Communiqué de l’AUREF</a></p>
<h2 id="universite-lyon-2">Université Lyon 2<a class="headerlink" href="#universite-lyon-2" title="Permanent link">¶</a></h2>
<h3 id="commission-recherche-cs">Commission Recherche (CS)<a class="headerlink" href="#commission-recherche-cs" title="Permanent link">¶</a></h3>
<blockquote>
<p>La Commission recherche de l’Université Lumière Lyon 2 réunie le 26/11/2018, ayant pris connaissance de l’annonce du gouvernement d’augmenter les droits d’inscription à l’Université pour les étudiant.es étranger.es hors Union Européenne, exprime sa profonde opposition à cette mesure et demande que les droits d’inscription à l’Université ne soient pas augmentés, quelle que soit l’origine des étudiant.es.</p>
</blockquote>
<p>Source: <a href="/pdfs/motion-cr-26-11-2018.pdf">Motion votée à l’unanimité par la commission recherche plénière de l’Université Lumière Lyon 2 du 26/11/18</a></p>
<h2 id="universite-de-poitiers">Université de Poitiers<a class="headerlink" href="#universite-de-poitiers" title="Permanent link">¶</a></h2>
<h3 id="president-et-vice-presidents">Président et vice-présidents<a class="headerlink" href="#president-et-vice-presidents" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le gouvernement a annoncé l’augmentation des droits d’inscription des étudiants extracommunautaires en les passant de 170€ à 2770 €/an pour le niveau Licence et de 243€ / 380€ à 3770 €/an pour les niveaux Master/Doctorat.</p>
<p>Le Président de l’université de Poitiers et son équipe manifestent leur opposition à cette augmentation.</p>
<p>Cette mesure est un obstacle majeur à la démocratisation et à l’internationalisation de l’accès à l’enseignement supérieur. Elle est en contradiction avec l’objectif national fixé de 500 000 étudiants en mobilité en France d’ici à 2027, contre 320 000 aujourd’hui. Elle est aussi orthogonale à la politique de l’Union Européenne s’appuyant sur l’éducation comme vecteur majeur d’inclusion et de citoyenneté, au-delà des frontières européennes, promue par ailleurs par le Président de la République française.</p>
<p>Cette mesure se heurte au constat d’une France récemment redevenue attractive pour les étudiants internationaux. Ces derniers choisissent à 70% d’intégrer nos universités et non les autres établissements aux frais d’inscription élevés. Prendre le risque de réduire l’accès des étudiants internationaux à nos formations revient à négliger leur apport à la diversité culturelle de notre société et au développement économique de nos territoires.</p>
<p>L’augmentation des droits est une mesure de sélection par l’argent contraire aux valeurs humanistes portées par l’Université. Elle est discriminatoire. Elle s’oppose profondément aux valeurs de l’université de Poitiers qui, riche de ses 17% d’étudiants internationaux, a fait de « l’université dans la Cité » sa signature.</p>
<p>Le Président de l’université de Poitiers et son équipe demandent au gouvernement de reconsidérer cette mesure dans le sens d’un service public de l’enseignement supérieur, favorisant l’accueil équitable de tous les étudiants.</p>
<p>Le Président et les vice-présidents de l’université de Poitiers </p>
</blockquote>
<p>Source: <a href="http://www.univ-poitiers.fr/actualites/international/pour-une-universite-francaise-ouverte-sur-le-monde-1653268.kjsp">Site web de l’université de Poitiers</a></p>
<h2 id="universite-de-lorraine">Université de Lorraine<a class="headerlink" href="#universite-de-lorraine" title="Permanent link">¶</a></h2>
<h3 id="conseil-dadministration_1">Conseil d’Administration<a class="headerlink" href="#conseil-dadministration_1" title="Permanent link">¶</a></h3>
<blockquote>
<p>Texte proposé au CA le 4 décembre.</p>
<p>Pour transmission à la Ministre à la Ministre de l’Enseignement Supérieur, de la Recherche et de l’Innovation.</p>
<p>L’université de Lorraine fait partie des universités françaises qui est fière d’accueillir le plus d’étudiants étrangers extra-communautaires en France. Elle est aussi engagée dans des réseaux d’universités notamment avec de nombreux doubles diplômes avec des établissements allemands. Le premier Ministre a annoncé le 19 novembre dernier six mesures pour favoriser l’attractivité de la France qui changent radicalement la politique Française, le modèle de relation que nos universités entretiennent avec leurs partenaires étrangers, la relation directe de nos établissements avec les étudiants extra-communautaires. Parmi ces mesures, celle qui consiste à différencier les frais d’inscription entre étudiants communautaires et extra-communautaires, à tripler le nombre de bourses et à augmenter les exonérations, divise profondément la communauté universitaire.</p>
<p>Une partie importante de la communauté universitaire lorraine est opposée au principe même de la différenciation des frais d’inscription et, comme en Allemagne, préfère une politique d’attractivité qui ne fait pas des frais d’inscription un outil de différenciation entre les étudiants. Pour une autre partie de notre communauté cette différenciation pourrait être compréhensible mais les modalités rigides proposées inquiètent notamment pour nos relations avec les pays francophones d’Afrique ; pays avec lesquelles la Lorraine, terre d’immigration, a une longue tradition de partenariat.</p>
<p>Nous pensons que cette mesure ne permettra plus d’accueillir une partie des étudiants modestes qui avait fait le choix de la France en raison’de la qualité des études mais également pour sa politique de tarification de l’enseignement supérieur public.</p>
<p>Pour toute ces raisons, le conseil d’administration de l’université de Lorraine demande urgemment la révision de cette mesure et plus largement une réflexion globale sur le modèle de financement des universités françaises.</p>
</blockquote>
<p>Source: <a href="/pdfs/université-lorraine.pdf">Motion votée à l’unanimité par le CA de l’Université de Lorraine</a></p>
<h3 id="conseil-scientifique">Conseil Scientifique<a class="headerlink" href="#conseil-scientifique" title="Permanent link">¶</a></h3>
<blockquote>
<p>Motion du CS de l’Université de Lorraine du 4 décembre 2018</p>
<p>Le Conseil Scientifique de l’Université de Lorraine ne peut cautionner une telle explosion des frais d’inscription, qui brise le principe d’égalité cher à la France, et ouvre la porte à une politique de financement des universités très dangereuse. L’Université de Lorraine demande à ce que le gouvernement revienne sur cette hausse démesurée et propose des solutions plus durables de financement de l’Enseignement Supérieur.</p>
<p>Cette hausse ne nous rendra attractifs qu’auprès d’élites sociales et considérant des frais d’inscription élevés comme un gage de qualité. Quand on sait qu’un rapport récent de la Cour des Comptes estime préférable d’augmenter les frais d’inscription de tous les étudiants, on s’attend à ce que cette hausse se généralise au cours des années à venir. Dès lors, quid des étudiants de l’espace européen, et des étudiants de nationalité française ? Devront- ils aussi s’endetter de plusieurs milliers d’euros pour accéder à un diplôme plus « attractif » ? Ce n’est pas aux étudiants de combler le sous-financement de l’Enseignement Supérieur, ni de payer les pots cassés d’une stratégie minimaliste qui dure depuis vingt ans. L’Etat français doit assumer et sensiblement augmenter son investissement dans les universités, plutôt que de rendre les étudiants plus précaires encore.</p>
<p>Le Conseil Scientifique considère que cette mesure fait peser une menace sur la formation à la recherche et par la recherche à l’Université de Lorraine (filiation licence-master-doctorat). Elle porte atteinte au développement et au rayonnement des unités de recherche; elle obère les collaborations internationales, en particulier dans le contexte du développement de la francophonie.</p>
</blockquote>
<p>Source: CS de l’université de Lorraine du 4 décembre 2018</p>
<h2 id="universite-paris-3">Université Paris 3<a class="headerlink" href="#universite-paris-3" title="Permanent link">¶</a></h2>
<h3 id="conseil-dadministration_2">Conseil d’Administration<a class="headerlink" href="#conseil-dadministration_2" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le gouvernement a annoncé le 19 novembre une augmentation conséquente des droits d’inscription pour les étudiant·es extracommunautaires dès la rentrée prochaine : de 170 euros à 2770 euros par an pour le niveau Licence et de 243 et 380 euros à 3770 euros pour les niveaux Master et Doctorat.</p>
<p>Le Conseil d’administration de la Sorbonne Nouvelle, réuni le 30 novembre 2018, manifeste son opposition à ces augmentations.</p>
<p>Cette mesure serait en effet catastrophique pour notre université, dont près de 30 % des étudiant·e·s sont étranger·e·s. Elle porte en outre atteinte aux valeurs humanistes que nous défendons.</p>
</blockquote>
<p>Source: <a href="http://www.univ-paris3.fr/medias/fichier/20181130-sorbonne-nouvelle-ca-motion-fi-etudiant-e-s-etranger-e-s_1543850915607.pdf">Motion votée lors du Conseil d’administration du 30 novembre 2018</a></p>
<h2 id="universite-paul-valery-montpellier-3">Université Paul Valéry Montpellier 3<a class="headerlink" href="#universite-paul-valery-montpellier-3" title="Permanent link">¶</a></h2>
<h3 id="conseil-dadministration_3">Conseil d’Administration<a class="headerlink" href="#conseil-dadministration_3" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le conseil d’administration approuve à l’unanimité, un élu ne prenant pas part au vote, la motion suivante :
« Le gouvernement a annoncé la semaine passée un projet de loi visant à instaurer des frais de scolarité pour
les étudiant.e.s étrangers non communautaires sous la forme d’un plan nommé « Bienvenue en France –
Choose me ». Ces frais de scolarité s’élèvent à hauteur de 2800€ pour une année de licence et 3800€ par
année de Master.</p>
<p>Réuni le 27 novembre 2018, le Conseil d’administration de l’UPV réaffirme son attachement à une université
accessible à tous et à toutes sans conditions de nationalité.
Il dénonce et demande le retrait de ce projet de loi présenté par le gouvernement.</p>
</blockquote>
<p>Extrait n°528-016 du registre de délibérations du conseil d’administration, séance du 27 novembre 2018</p>
<p>Source: <a href="https://www.univ-montp3.fr/fr/file/26442/download?token=ucsmL5I9">https://www.univ-montp3.fr/fr/file/26442/download?token=ucsmL5I9</a></p>
<h2 id="universite-rennes-2">Université Rennes 2<a class="headerlink" href="#universite-rennes-2" title="Permanent link">¶</a></h2>
<h3 id="conseil-dadministration_4">Conseil d’Administration<a class="headerlink" href="#conseil-dadministration_4" title="Permanent link">¶</a></h3>
<blockquote>
<p>Le gouvernement a annoncé lundi l’augmentation des droits d’inscription des étudiants extracommunautaires en les multipliant par seize dans certains cas: 2770 €/an pour le niveau L (contre 170€ jusque-là) et 3770 €/an pour les niveaux M et D (contre respectivement 243€ et 380€ jusque-là). Première conséquence: impossibilité de s’inscrire en France pour une très grande majorité des étudiant.e.s des pays les plus pauvres.</p>
<p>Le CA de l’Université Rennes-2 manifeste son opposition à l’augmentation des droits d’inscription à l’université car elle est un obstacle majeur à la démocratisation et à l’internationalisation de l’accès à l’enseignement supérieur. L’augmentation des droits, même partiellement compensée par une augmentation du nombre des bourses qui leur seraient allouées, est une mesure de sélection par l’argent contraire aux valeurs humanistes portées par notre établissement, et scandaleusement discriminatoire contre les étudiant.e.s étranger.e.s les plus modestes, dont un très grand nombre ne pourra plus venir étudier dans notre pays. La mesure proposée par Édouard Philippe est en contradiction flagrante avec les incitations à l’internationalisation des universités françaises, et l’objectif fixé de 500 000 étudiants en mobilité en France d’ici à 2027, contre 320 000 aujourd’hui, ne pourra pas être atteint en élevant de façon aussi radicale les droits d’inscription pour les étudiant.e.s étranger.e.s.</p>
<p>L’Université Rennes-2 accueille un nombre important d’étudiant.e.s extra-communautaires (2800), et elle est reconnue pour la qualité de son centre de formation en Français Langue étrangère (le CIREFE). La plupart sont des étudiant.e.s de qualité aux revenus modestes, provenant d’Afrique, d’Amérique latine ou d’Asie, et un grand nombre d’entre elles·eux contribue au rayonnement de notre université et de la culture française dans leur pays d’origine après la fin de leurs études.</p>
<p>En l’état, cette mesure risque de déstabiliser des dispositifs fragiles et de décourager les futurs étudiants étrangers à s’inscrire à l’Université. Le CA de l’Université Rennes-2 demande donc au gouvernement de revenir sur cette décision, et reste disposé à étudier toutes les propositions visant à favoriser l’accueil des étudiant.e.s étranger.e.s en France.</p>
</blockquote>
<p>Source: <a href="/pdfs/motion-Rennes-2.pdf">Motion proposée par le SNESup-FSU votée à l’unanimité par le C.A. de l’Université Rennes-2 le 23/11/2018</a></p>
<h2 id="universite-paris-8">Université Paris 8<a class="headerlink" href="#universite-paris-8" title="Permanent link">¶</a></h2>
<h3 id="equipe-presidentielle">Équipe présidentielle<a class="headerlink" href="#equipe-presidentielle" title="Permanent link">¶</a></h3>
<blockquote>
<p>Cher.e.s collègues, cher.e.s étudiant.e.s.</p>
<p>Suite à l’annonce des grandes lignes du programme “Bienvenue en France” par le Premier ministre Edouard Philippe le 19 novembre 2018, qui prévoit une augmentation très forte des droits d’inscription des étudiants étrangers (2 770 euros pour la licence contre 170 aujourd’hui et 3 770 euros pour le master contre 243), un certain nombre d’inquiétudes légitimes se sont exprimées au sein de notre communauté, comme en témoignent les premières réactions de nos collègues (Tribune dans Le Monde du 22 novembre) et les réactions qui se sont exprimées ces derniers jours au sein de nos instances (Conseil des composantes, Commission de la recherche, Conseil des relations internationales).</p>
<p>Cette multiplication par 16 des droits d’inscription représente en effet une forme d’exclusion et va à l’encontre du principe constitutionnel d’égalité et des conventions internationales qui interdisent les discriminations. Elle s’oppose au Droit à l’éducation, inscrit dans l’article 26 de la Déclaration universelle des droits de l’homme de 1948.</p>
<p>Si la précipitation et le flou dans la mise en place de cette mesure ne permettent pas d’en évaluer toutes les conséquences, une telle augmentation aura inévitablement un impact réel sur les étudiants confrontés à des difficultés économiques. Notre université connaîtra aussi une baisse d’attractivité d’autant plus conséquente qu’elle a noué des liens forts avec les pays de la francophonie et des Suds.</p>
<p>Pour notre université, riche de la variété de ses publics, de leur origine qu’elle soit géographique, sociale ou culturelle, à l’image de la population cosmopolite et multiculturelle de notre territoire, il n’est pas envisageable de mettre un prix à l’hospitalité et d’interdire l’accès de nos formations à tou.te.s ceux.celles qui y projettent leur espoir d’une vie meilleure.</p>
<p>L’équipe présidentielle</p>
</blockquote>
<p>Source: <a href="http://www2.univ-paris8.fr/sociologie/?p=8650">équipe de direction de l’Université Paris 8</a></p>
<h2 id="universite-de-bretagne-occidentale-tribune">Université de Bretagne occidentale (Tribune)<a class="headerlink" href="#universite-de-bretagne-occidentale-tribune" title="Permanent link">¶</a></h2>
<h3 id="president-de-luniversite">Président de l’université<a class="headerlink" href="#president-de-luniversite" title="Permanent link">¶</a></h3>
<p>La tribune est disponible à cette adresse: <a href="https://www.lemonde.fr/idees/article/2018/12/03/etudiants-etrangers-l-attractivite-par-le-prix-une-hypothese-tres-risquee_5391834_3232.html">Tribune du président de l’université de Bretagne occidentale</a></p>Kobo Aura H2O electronic reader hacking2018-01-08T00:00:00+01:002018-01-08T00:00:00+01:00Rémy Grünblatttag:remy.grunblatt.org,2018-01-08:/kobo-aura-h2o-electronic-reader-hacking.html<p>I recently bought a Kobo Aura H2O, and while it’s really good to read, I’m a little bit disappointed that I need an account to use the reader. Multiple blog posts like <a href="https://a3nm.net/blog/fnacbook_kobo_hacking.html">a3nm’s “fnacbook kobo hacking”</a> or <a href="https://www.mobileread.com/forums/showthread.php?t=281817">mobileread forum threads</a> explain how to avoid registration and tracking …</p><p>I recently bought a Kobo Aura H2O, and while it’s really good to read, I’m a little bit disappointed that I need an account to use the reader. Multiple blog posts like <a href="https://a3nm.net/blog/fnacbook_kobo_hacking.html">a3nm’s “fnacbook kobo hacking”</a> or <a href="https://www.mobileread.com/forums/showthread.php?t=281817">mobileread forum threads</a> explain how to avoid registration and tracking, but as they often concern specific hardware, software versions, and data is scattered around many different threads, I think this kind of “review” article may be useful.</p>
<h1 id="connecting-the-device-to-wifi">Connecting the device to WiFi<a class="headerlink" href="#connecting-the-device-to-wifi" title="Permanent link">¶</a></h1>
<p>After language selection, the home page of the Kobo is asking us if we want to configure the device using WiFi or without WiFi.</p>
<p>I chose the first option; the reasoning behind this step is to allow the Kobo to update itself to the last firmware verssion. </p>
<p>After this step, the Kobo will ask for credentials or prompt an account creation, which is what we want to avoid. To do this, we go back to the home screen and select the second option, to configure the Kobo without WiFi.</p>
<h1 id="mounting-the-device">Mounting the device<a class="headerlink" href="#mounting-the-device" title="Permanent link">¶</a></h1>
<p>Using the second option enables the device USB port, and allows us to mount one of the device partition:</p>
<div class="highlight"><pre><span></span><code><span class="n">usb</span><span class="w"> </span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="err">:</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">high</span><span class="o">-</span><span class="n">speed</span><span class="w"> </span><span class="n">USB</span><span class="w"> </span><span class="n">device</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="mi">24</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="n">xhci_hcd</span>
<span class="n">usb</span><span class="w"> </span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="err">:</span><span class="w"> </span><span class="k">New</span><span class="w"> </span><span class="n">USB</span><span class="w"> </span><span class="n">device</span><span class="w"> </span><span class="k">found</span><span class="p">,</span><span class="w"> </span><span class="n">idVendor</span><span class="o">=</span><span class="mi">2237</span><span class="p">,</span><span class="w"> </span><span class="n">idProduct</span><span class="o">=</span><span class="mi">4227</span><span class="p">,</span><span class="w"> </span><span class="n">bcdDevice</span><span class="o">=</span><span class="w"> </span><span class="mf">4.01</span>
<span class="n">usb</span><span class="w"> </span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="err">:</span><span class="w"> </span><span class="k">New</span><span class="w"> </span><span class="n">USB</span><span class="w"> </span><span class="n">device</span><span class="w"> </span><span class="nl">strings</span><span class="p">:</span><span class="w"> </span><span class="n">Mfr</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="n">Product</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="n">SerialNumber</span><span class="o">=</span><span class="mi">5</span>
<span class="n">usb</span><span class="w"> </span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="err">:</span><span class="w"> </span><span class="nl">Product</span><span class="p">:</span><span class="w"> </span><span class="n">eReader</span><span class="o">-</span><span class="mf">4.9.11311</span>
<span class="n">usb</span><span class="w"> </span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="err">:</span><span class="w"> </span><span class="nl">Manufacturer</span><span class="p">:</span><span class="w"> </span><span class="n">Kobo</span>
<span class="n">usb</span><span class="w"> </span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="err">:</span><span class="w"> </span><span class="nl">SerialNumber</span><span class="p">:</span><span class="w"> </span><span class="o">[</span><span class="n">REDACTED</span><span class="o">]</span>
<span class="n">usb</span><span class="o">-</span><span class="n">storage</span><span class="w"> </span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="err">:</span><span class="mf">1.0</span><span class="err">:</span><span class="w"> </span><span class="n">USB</span><span class="w"> </span><span class="n">Mass</span><span class="w"> </span><span class="n">Storage</span><span class="w"> </span><span class="n">device</span><span class="w"> </span><span class="n">detected</span>
<span class="n">scsi</span><span class="w"> </span><span class="nl">host3</span><span class="p">:</span><span class="w"> </span><span class="n">usb</span><span class="o">-</span><span class="n">storage</span><span class="w"> </span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="err">:</span><span class="mf">1.0</span>
<span class="n">scsi</span><span class="w"> </span><span class="mi">3</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="w"> </span><span class="n">Direct</span><span class="o">-</span><span class="n">Access</span><span class="w"> </span><span class="n">Linux</span><span class="w"> </span><span class="k">File</span><span class="o">-</span><span class="n">Stor</span><span class="w"> </span><span class="n">Gadget</span><span class="w"> </span><span class="mi">0401</span><span class="w"> </span><span class="nl">PQ</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="nl">ANSI</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span>
<span class="n">sd</span><span class="w"> </span><span class="mi">3</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="w"> </span><span class="nf">Power</span><span class="o">-</span><span class="k">on</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="n">device</span><span class="w"> </span><span class="n">reset</span><span class="w"> </span><span class="n">occurred</span>
<span class="n">sd</span><span class="w"> </span><span class="mi">3</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="w"> </span><span class="o">[</span><span class="n">sdb</span><span class="o">]</span><span class="w"> </span><span class="mi">14139389</span><span class="w"> </span><span class="mi">512</span><span class="o">-</span><span class="n">byte</span><span class="w"> </span><span class="n">logical</span><span class="w"> </span><span class="nl">blocks</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="mf">7.24</span><span class="w"> </span><span class="n">GB</span><span class="o">/</span><span class="mf">6.74</span><span class="w"> </span><span class="n">GiB</span><span class="p">)</span>
<span class="n">sd</span><span class="w"> </span><span class="mi">3</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="w"> </span><span class="o">[</span><span class="n">sdb</span><span class="o">]</span><span class="w"> </span><span class="k">Write</span><span class="w"> </span><span class="n">Protect</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="k">off</span>
<span class="n">sd</span><span class="w"> </span><span class="mi">3</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="w"> </span><span class="o">[</span><span class="n">sdb</span><span class="o">]</span><span class="w"> </span><span class="n">Mode</span><span class="w"> </span><span class="nl">Sense</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="n">f</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span>
<span class="n">sd</span><span class="w"> </span><span class="mi">3</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="mi">0</span><span class="err">:</span><span class="w"> </span><span class="o">[</span><span class="n">sdb</span><span class="o">]</span><span class="w"> </span><span class="k">Write</span><span class="w"> </span><span class="nl">cache</span><span class="p">:</span><span class="w"> </span><span class="n">enabled</span><span class="p">,</span><span class="w"> </span><span class="k">read</span><span class="w"> </span><span class="nl">cache</span><span class="p">:</span><span class="w"> </span><span class="n">enabled</span><span class="p">,</span><span class="w"> </span><span class="n">doesn</span><span class="err">'</span><span class="n">t</span><span class="w"> </span><span class="n">support</span><span class="w"> </span><span class="n">DPO</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="n">FUA</span>
</code></pre></div>
<p>We can mount the device directly (<code>/dev/sdb</code> in my case), as there are no partitions on the device.</p>
<h1 id="directory-structure">Directory Structure<a class="headerlink" href="#directory-structure" title="Permanent link">¶</a></h1>
<p>We can look at the directory structure of the device:</p>
<div class="highlight"><pre><span></span><code><span class="n">./</span>
<span class="n">├── .adobe-digital-editions/</span>
<span class="n">│ └── device.xml</span>
<span class="n">├── Digital Editions/</span>
<span class="n">│ ├── Annotations</span>
<span class="n">│ └── Manifest</span>
<span class="n">├── .kobo/</span>
<span class="n">│ ├── affiliate.conf</span>
<span class="n">│ ├── BookReader.sqlite</span>
<span class="n">│ ├── certificates/</span>
<span class="n">│ ├── device.salt.conf</span>
<span class="n">│ ├── dict/</span>
<span class="n">│ ├── kepub/</span>
<span class="n">│ ├── Kobo/</span>
<span class="n">│ │ ├── Analytics.conf</span>
<span class="n">│ │ └── Kobo eReader.conf</span>
<span class="n">│ ├── KoboReader.sqlite</span>
<span class="n">│ └── version</span>
<span class="n">└── .kobo-images/</span>
</code></pre></div>
<p>We find well-known files, such as the <code>KoboReader.sqlite</code> database, but also dubious ones: the <code>affiliate.conf</code>, <code>Analytics.conf</code>, and the <code>device.xml</code> file that has something to do with Adobe Digital Editions, which is a DRM system I obviouslyy won’t be using. The <code>BookReader.sqlite</code> file is also dubious: it’s an encrypted database.</p>
<h3 id="affiliateconf-clean">Affiliate.conf [<span style="color:green">Clean</span>]<a class="headerlink" href="#affiliateconf-clean" title="Permanent link">¶</a></h3>
<p>The <code>affiliate.conf</code> only contain the two following lines.</p>
<div class="highlight"><pre><span></span><code><span class="k">[General]</span>
<span class="na">affiliate</span><span class="o">=</span><span class="s">Kobo</span>
</code></pre></div>
<p>As no unique identifier is present, i’ll let it be.</p>
<h3 id="analyticsconf-detrimental">Analytics.conf [<span style="color:red">Detrimental</span>]<a class="headerlink" href="#analyticsconf-detrimental" title="Permanent link">¶</a></h3>
<p>The <code>Analytics.conf</code> contains an unique ID (redacted) and many lines related to google analytics using this ID:</p>
<div class="highlight"><pre><span></span><code><span class="k">[General]</span>
<span class="na">ClientID</span><span class="o">=</span><span class="s">REDACTED-REDA-CTED-REDA-CTEDREDACTED</span>
<span class="na">GAQueue</span><span class="o">=</span><span class="s">"@Variant(\0\0\0\x11\0\0\0\xf7https://ssl.google-analytics.com/collect?v=1&tid=UA-6177406-38&cid=redacted-reda-cted-reda-ctedredacted&uid=redacted-reda-cted-reda-ctedredacted&av=4.9.11311&an=nickel&sr=1080x1440&ul=fr-fr&t=event&ec=Light&ea=BrightnessAdjusted&el=MenuTapped&ev=0)", @ByteArray(), "@Variant(\0\0\0\x11\0\0\0\xf4https://ssl.google-analytics.com/collect?v=1&tid=UA-6177406-38&cid=redacted-reda-cted-reda-ctedredacted&uid=redacted-reda-cted-reda-ctedredacted&av=4.9.11311&an=nickel&sr=1080x1440&ul=fr-fr&t=event&ec=ReadingExperience&ea=DictionaryLookup&el=fr)", […]</span>
</code></pre></div>
<p>Many events seems tracked through the get parameters of the URLs: </p>
<div class="highlight"><pre><span></span><code>AdobeErrorEncountered
AutoColorToggled
BrightnessAdjusted
CreateBookmark
DictionaryLookup
FontSettings
HomeWidgetClicked
LeaveContent
MainNavOption
NaturalLightAdjusted
NewWifiNetwork
OpenContent
OpenReadingSettingsMenu
PluggedIn
ReadingSettings
SearchExecuted
StatusBarOption
TabSelected
TimeToUpdate
WifiToggle
</code></pre></div>
<p>The GAQueue stores Google-Analytics callbacks until the next time I connect the Kobo to the Internet. When empty, the file looks like this:</p>
<div class="highlight"><pre><span></span><code><span class="k">[General]</span>
<span class="na">ClientID</span><span class="o">=</span><span class="s">REDACTED-REDA-CTED-REDA-CTEDREDACTED</span>
<span class="na">GAQueue</span><span class="o">=</span><span class="s">@Invalid()</span>
</code></pre></div>
<h3 id="version-detrimental">Version [<span style="color:red">Detrimental</span>]<a class="headerlink" href="#version-detrimental" title="Permanent link">¶</a></h3>
<p>The <code>version</code> file is a csv (<em>comma separated values</em>) file containing the device serial number, as well as multiple version numbers:</p>
<div class="highlight"><pre><span></span><code>SERIAL_NUMBER, 4.1.15, 4.9.11311, 4.1.15, 4.1.15, 00000000-0000-0000-0000-000000000378
</code></pre></div>
<h3 id="devicesaltconf-detrimental">Device.salt.conf [<span style="color:red">Detrimental</span>]<a class="headerlink" href="#devicesaltconf-detrimental" title="Permanent link">¶</a></h3>
<p>The <code>device.salt.conf</code> file contains a salt, but this salt seems unique enough to be a tracking id:</p>
<div class="highlight"><pre><span></span><code><span class="k">[General]</span>
<span class="na">salt</span><span class="o">=</span><span class="s">@ByteArray(\xYY\xYY\bL\xYY\xYY\xYY\xYY\xYY\xYY\xYY\xYY\xYY\xYYZ\xYY)</span>
</code></pre></div>
<h3 id="koboreadersqlite-detrimental">KoboReader.sqlite [<span style="color:red">Detrimental</span>]<a class="headerlink" href="#koboreadersqlite-detrimental" title="Permanent link">¶</a></h3>
<p>The <code>KoboReader.sqlite</code> file is a sqlite3 database. It has the following tables:</p>
<div class="highlight"><pre><span></span><code>AbTest OverDriveCards WordList
Achievement OverDriveCheckoutBook content
Activity OverDriveLibrary content_keys
AnalyticsEvents Reviews content_settings
Authors Rules ratings
BookAuthors Shelf shortcover_page
Bookmark ShelfContent user
DbVersion SyncQueue volume_shortcovers
Dictionary Tab volume_tabs
Event Wishlist
</code></pre></div>
<p>Each of the table has many columns. For example, the user table has the following columns:</p>
<div class="highlight"><pre><span></span><code><span class="mf">0</span><span class="err">|</span><span class="n">UserID</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">1</span><span class="err">||</span><span class="mf">1</span>
<span class="mf">1</span><span class="err">|</span><span class="n">UserKey</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">1</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">2</span><span class="err">|</span><span class="n">UserDisplayName</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">3</span><span class="err">|</span><span class="n">UserEmail</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">4</span><span class="err">|</span><span class="n">___DeviceID</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">5</span><span class="err">|</span><span class="n">FacebookAuthToken</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">6</span><span class="err">|</span><span class="n">HasMadePurchase</span><span class="err">|</span><span class="n">BIT</span><span class="err">|</span><span class="mf">0</span><span class="err">|</span><span class="n">FALSE</span><span class="err">|</span><span class="mf">0</span>
<span class="mf">7</span><span class="err">|</span><span class="n">IsOneStoreAccount</span><span class="err">|</span><span class="n">BIT</span><span class="err">|</span><span class="mf">0</span><span class="err">|</span><span class="n">FALSE</span><span class="err">|</span><span class="mf">0</span>
<span class="mf">8</span><span class="err">|</span><span class="n">IsChildAccount</span><span class="err">|</span><span class="n">BIT</span><span class="err">|</span><span class="mf">0</span><span class="err">|</span><span class="n">FALSE</span><span class="err">|</span><span class="mf">0</span>
<span class="mf">9</span><span class="err">|</span><span class="n">RefreshToken</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">10</span><span class="err">|</span><span class="n">AuthToken</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">11</span><span class="err">|</span><span class="n">AuthType</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">12</span><span class="err">|</span><span class="n">Loyalty</span><span class="err">|</span><span class="n">BLOB</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">13</span><span class="err">|</span><span class="n">IsLibraryMigrated</span><span class="err">|</span><span class="n">BIT</span><span class="err">|</span><span class="mf">1</span><span class="err">|</span><span class="n">true</span><span class="err">|</span><span class="mf">0</span>
<span class="mf">14</span><span class="err">|</span><span class="n">SyncContinuationToken</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">15</span><span class="err">|</span><span class="n">Subscription</span><span class="err">|</span><span class="nb">INT</span><span class="err">|</span><span class="mf">1</span><span class="err">|</span><span class="mf">0</span><span class="err">|</span><span class="mf">0</span>
<span class="mf">16</span><span class="err">|</span><span class="n">LibrarySyncType</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">17</span><span class="err">|</span><span class="n">LibrarySyncTime</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
<span class="mf">18</span><span class="err">|</span><span class="n">SyncTokenAppVersion</span><span class="err">|</span><span class="n">TEXT</span><span class="err">|</span><span class="mf">0</span><span class="err">||</span><span class="mf">0</span>
</code></pre></div>
<p>The full schema of the database is <a href="https://remy.grunblatt.org/static/KoboReaderSchema.sql">available there</a>.</p>
<p>Looking at differences between an activated and not-yet activated device, we can discover the following:</p>
<ul>
<li>The events sent to google analytics are also stored in the AnalyticsEvent table;</li>
<li>The Achievement table is full of shitty achievements, related to the “Reading Life” gamification thing;</li>
<li>The AbTest table contains unique IDs and non-evocating names like <em>EPDHome2018</em>, <em>EPDStorefront2018</em> or <em>KoboPlusDiscoveryEPD</em>. Maybe Kobo is doing <a href="https://en.wikipedia.org/wiki/A/B_testing">A/B testing</a> on the users?</li>
<li>The User table contains the following default data: <code>2a362501-e2cf-41fd-88b1-47ade6d09da4|17314f8f-9d48-4ec2-8cbf-eda1e70b1127|demofinal@magtest.kobo.com|demofinal@magtest.kobo.com|a65c3a5eaebcf65fb184764bb99d2270cb71d8c8cd8bece3a7dcb271204f645a||false|false|false|||||false||0|||</code>;</li>
<li>The User table is used to detect if the Kobo has been connected // activated online.</li>
</ul>
<h2 id="bypassing-registration">Bypassing registration<a class="headerlink" href="#bypassing-registration" title="Permanent link">¶</a></h2>
<p>To bypass registration with an account, we can put fake data in the <code>KoboReader.sqlite</code> database. Yet filling everything mindlessly will not do; it will allow to bypass the registration, but you won’t be able to find your books after. As of today, the following works:</p>
<div class="highlight"><pre><span></span><code># echo "INSERT INTO user VALUES('ID','Masterkey','Rémy','nomail','',NULL,'false','false','false','RefreshToken','AuthToken','Bearer','','false','SyncContinuationToken',1,NULL,NULL,'4.9.11311');" | sqlite3 /mnt/.kobo/KoboReader.sqlite
</code></pre></div>
<p>A real SyncContinuationToken field is composed of base64 encoded, dot separated and encapsulated Json data:</p>
<div class="highlight"><pre><span></span><code><span class="s s-Atom">#</span> <span class="nv">Content</span> <span class="s s-Atom">of</span> <span class="s s-Atom">a</span> <span class="nv">SyncContinuationToken</span> <span class="s s-Atom">field</span> <span class="s s-Atom">in</span> <span class="s s-Atom">a</span> <span class="s s-Atom">real</span> <span class="nb">user</span>
<span class="s s-Atom">eyJ0eXAiOjEsInZlciI6bnVsbCwicHR5cCI6IlN5bmNUb2tlbiJ9</span><span class="p">.</span><span class="s s-Atom">eyJJbnRlcm5hbFN5bmNUb2tlbiI6ImV5SjBlWEFpT2pFc0luWmxjaUk2Ym5Wc2JDd2ljSFI1Y0NJNklrNWxlSFJUZVc1alZHOXJaVzRpZlEuZXlJa2RIbHdaU0k2SWs1bGVIUlRlVzVqVkc5clpXNGlMQ0pUZFdKelkzSnBjSFJwYjI1RmJuUnBkR3hsYldWdWRITWlPbTUxYkd3c0lrVnVkR2wwYkdWdFpXNTBjeUk2ZXlKVWFXMWxjM1JoYlhBaU9pSXlNREU0TFRBM0xUSTRWREUxT2pFd09qQXpXaUlzSWt4aGMzUlNaWFIxY201bFpFbGtJanB1ZFd4c0xDSk1ZWE4wVW1WMGRYSnVaV1JKWkhOSVlYTm9Jam90TmpVNU16QTJNVGM0ZlN3aVJHVnNaWFJsWkVWdWRHbDBiR1Z0Wlc1MGN5STZiblZzYkN3aVVtVmhaR2x1WjFOMFlYUmxjeUk2ZXlKVWFXMWxjM1JoYlhBaU9pSXlNREU0TFRBM0xUSTRWREUxT2pFd09qQXlXaUlzSWt4aGMzUlNaWFIxY201bFpFbGtJanB1ZFd4c0xDSk1ZWE4wVW1WMGRYSnVaV1JKWkhOSVlYTm9Jam93ZlN3aVZHRm5jeUk2ZXlKVWFXMWxjM1JoYlhBaU9pSXlNREU0TFRBM0xUSTRWREUxT2pFd09qQXpXaUlzSWt4aGMzUlNaWFIxY201bFpFbGtJanB1ZFd4c0xDSk1ZWE4wVW1WMGRYSnVaV1JKWkhOSVlYTm9Jam93ZlN3aVJHVnNaWFJsWkZSaFozTWlPbTUxYkd3c0lsQnliMlIxWTNSTlpYUmhaR0YwWVNJNmV5SlVhVzFsYzNSaGJYQWlPaUl5TURFNExUQTNMVEk0VkRBeU9qQXhPakkxTGpnMU15SXNJa3hoYzNSU1pYUjFjbTVsWkVsa0lqcHVkV3hzTENKTVlYTjBVbVYwZFhKdVpXUkpaSE5JWVhOb0lqb3dmU3dpU1hOR2RXeHNVM2x1WXlJNlptRnNjMlVzSWxCeVpYWnBiM1Z6VTNsdVkxUnBiV1VpT2lJeU1ERTRMVEE0TFRBeVZEQTRPalE0T2pJMUxqRXhPVGs0T1RaYUluMCIsIklzQ29udGludWF0aW9uVG9rZW4iOmZhbHNlfQ</span>
<span class="s s-Atom">#</span> <span class="s s-Atom">base64</span> <span class="s s-Atom">decode</span>
<span class="p">{</span><span class="s2">"typ"</span><span class="o">:</span><span class="mi">1</span><span class="p">,</span><span class="s2">"ver"</span><span class="o">:</span><span class="s s-Atom">null</span><span class="p">,</span><span class="s2">"ptyp"</span><span class="o">:</span><span class="s2">"SyncToken"</span><span class="p">}{</span><span class="s2">"InternalSyncToken"</span><span class="o">:</span><span class="s2">"eyJ0eXAiOjEsInZlciI6bnVsbCwicHR5cCI6Ik5leHRTeW5jVG9rZW4ifQ.eyIkdHlwZSI6Ik5leHRTeW5jVG9rZW4iLCJTdWJzY3JpcHRpb25FbnRpdGxlbWVudHMiOm51bGwsIkVudGl0bGVtZW50cyI6eyJUaW1lc3RhbXAiOiIyMDE4LTA3LTI4VDE1OjEwOjAzWiIsIkxhc3RSZXR1cm5lZElkIjpudWxsLCJMYXN0UmV0dXJuZWRJZHNIYXNoIjotNjU5MzA2MTc4fSwiRGVsZXRlZEVudGl0bGVtZW50cyI6bnVsbCwiUmVhZGluZ1N0YXRlcyI6eyJUaW1lc3RhbXAiOiIyMDE4LTA3LTI4VDE1OjEwOjAyWiIsIkxhc3RSZXR1cm5lZElkIjpudWxsLCJMYXN0UmV0dXJuZWRJZHNIYXNoIjowfSwiVGFncyI6eyJUaW1lc3RhbXAiOiIyMDE4LTA3LTI4VDE1OjEwOjAzWiIsIkxhc3RSZXR1cm5lZElkIjpudWxsLCJMYXN0UmV0dXJuZWRJZHNIYXNoIjowfSwiRGVsZXRlZFRhZ3MiOm51bGwsIlByb2R1Y3RNZXRhZGF0YSI6eyJUaW1lc3RhbXAiOiIyMDE4LTA3LTI4VDAyOjAxOjI1Ljg1MyIsIkxhc3RSZXR1cm5lZElkIjpudWxsLCJMYXN0UmV0dXJuZWRJZHNIYXNoIjowfSwiSXNGdWxsU3luYyI6ZmFsc2UsIlByZXZpb3VzU3luY1RpbWUiOiIyMDE4LTA4LTAyVDA4OjQ4OjI1LjExOTk4OTZaIn0"</span><span class="p">,</span><span class="s2">"IsContinuationToken"</span><span class="o">:</span><span class="s s-Atom">false</span><span class="p">}</span>
<span class="s s-Atom">#</span> <span class="s s-Atom">base64</span> <span class="s s-Atom">decode</span> <span class="s s-Atom">of</span> <span class="s s-Atom">the</span> <span class="nv">InternalSyncToken</span>
<span class="p">{</span><span class="s2">"typ"</span><span class="o">:</span><span class="mi">1</span><span class="p">,</span><span class="s2">"ver"</span><span class="o">:</span><span class="s s-Atom">null</span><span class="p">,</span><span class="s2">"ptyp"</span><span class="o">:</span><span class="s2">"NextSyncToken"</span><span class="p">}.{</span><span class="s2">"$type"</span><span class="o">:</span><span class="s2">"NextSyncToken"</span><span class="p">,</span><span class="s2">"SubscriptionEntitlements"</span><span class="o">:</span><span class="s s-Atom">null</span><span class="p">,</span><span class="s2">"Entitlements"</span><span class="o">:</span><span class="p">{</span><span class="s2">"Timestamp"</span><span class="o">:</span><span class="s2">"2018-07-28T15:10:03Z"</span><span class="p">,</span><span class="s2">"LastReturnedId"</span><span class="o">:</span><span class="s s-Atom">null</span><span class="p">,</span><span class="s2">"LastReturnedIdsHash"</span><span class="o">:-</span><span class="mi">659306178</span><span class="p">},</span><span class="s2">"DeletedEntitlements"</span><span class="o">:</span><span class="s s-Atom">null</span><span class="p">,</span><span class="s2">"ReadingStates"</span><span class="o">:</span><span class="p">{</span><span class="s2">"Timestamp"</span><span class="o">:</span><span class="s2">"2018-07-28T15:10:02Z"</span><span class="p">,</span><span class="s2">"LastReturnedId"</span><span class="o">:</span><span class="s s-Atom">null</span><span class="p">,</span><span class="s2">"LastReturnedIdsHash"</span><span class="o">:</span><span class="mi">0</span><span class="p">},</span><span class="s2">"Tags"</span><span class="o">:</span><span class="p">{</span><span class="s2">"Timestamp"</span><span class="o">:</span><span class="s2">"2018-07-28T15:10:03Z"</span><span class="p">,</span><span class="s2">"LastReturnedId"</span><span class="o">:</span><span class="s s-Atom">null</span><span class="p">,</span><span class="s2">"LastReturnedIdsHash"</span><span class="o">:</span><span class="mi">0</span><span class="p">},</span><span class="s2">"DeletedTags"</span><span class="o">:</span><span class="s s-Atom">null</span><span class="p">,</span><span class="s2">"ProductMetadata"</span><span class="o">:</span><span class="p">{</span><span class="s2">"Timestamp"</span><span class="o">:</span><span class="s2">"2018-07-28T02:01:25.853"</span><span class="p">,</span><span class="s2">"LastReturnedId"</span><span class="o">:</span><span class="s s-Atom">null</span><span class="p">,</span><span class="s2">"LastReturnedIdsHash"</span><span class="o">:</span><span class="mi">0</span><span class="p">},</span><span class="s2">"IsFullSync"</span><span class="o">:</span><span class="s s-Atom">false</span><span class="p">,</span><span class="s2">"PreviousSyncTime"</span><span class="o">:</span><span class="s2">"2018-08-02T08:48:25.1199896Z"</span><span class="p">}</span>
</code></pre></div>
<h2 id="preventing-communication-with-google-etc">Preventing communication with Google, etc.<a class="headerlink" href="#preventing-communication-with-google-etc" title="Permanent link">¶</a></h2>
<p>Updates for the Kobo are not signed, or even encrypted. By putting an archive named <code>KoboRoot.tgz</code> in the <code>.kobo</code> directory, on the partition of the Kobo (which is mounted internally as <code>/mnt/onboard</code>), we can update the Kobo, and for example modify the <code>/etc/hosts</code> file:</p>
<div class="highlight"><pre><span></span><code>mkdir ./etc
echo "0.0.0.0 baddomain.com" >> ./etc/hosts
tar czf KoboRoot.tgz ./etc/hosts
cp KoboRoot.tgz /mnt/.kobo/
</code></pre></div>
<p>Indeed, the content of the archive is extracted into the root of the Kobo system.
When unplugged, the Kobo will go through an update cycle, and the KoboRoot.tgz will be deleted.</p>
<p>To check with which domains the Kobo communicate, we can use tcpdump, wireshark or mitmproxy (the latter being more useful to access to actual data sent to http or https endpoints). Looking for dns queries when the Kobo is used in a classical way (i.e. no web bworsing), then we get (<code>192.168.12.214</code> being the ip address of the Kobo):</p>
<div class="highlight"><pre><span></span><code><span class="o">%</span><span class="w"> </span><span class="n">tshark</span><span class="w"> </span><span class="o">-</span><span class="n">r</span><span class="w"> </span><span class="n">dump</span><span class="o">.</span><span class="n">pcapng</span><span class="w"> </span><span class="o">-</span><span class="n">T</span><span class="w"> </span><span class="n">fields</span><span class="w"> </span><span class="o">-</span><span class="n">e</span><span class="w"> </span><span class="n">ip</span><span class="o">.</span><span class="n">src</span><span class="w"> </span><span class="o">-</span><span class="n">e</span><span class="w"> </span><span class="n">dns</span><span class="o">.</span><span class="n">qry</span><span class="o">.</span><span class="n">name</span><span class="w"> </span><span class="o">-</span><span class="mi">2</span><span class="w"> </span><span class="o">-</span><span class="n">R</span><span class="w"> </span><span class="s2">"dns.flags.response eq 0"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">sort</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">uniq</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">api</span><span class="o">.</span><span class="n">ipinfodb</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">api</span><span class="o">.</span><span class="n">kobobooks</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">auth</span><span class="o">.</span><span class="n">kobobooks</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">authorize</span><span class="o">.</span><span class="n">kobo</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">kbdownload1</span><span class="o">-</span><span class="n">a</span><span class="o">.</span><span class="n">akamaihd</span><span class="o">.</span><span class="n">net</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">kbimages1</span><span class="o">-</span><span class="n">a</span><span class="o">.</span><span class="n">akamaihd</span><span class="o">.</span><span class="n">net</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">mobile</span><span class="o">.</span><span class="n">kobobooks</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">pool</span><span class="o">.</span><span class="n">ntp</span><span class="o">.</span><span class="n">org</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">script</span><span class="o">.</span><span class="n">hotjar</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">social</span><span class="o">.</span><span class="n">kobobooks</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">ssl</span><span class="o">.</span><span class="n">google</span><span class="o">-</span><span class="n">analytics</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="k">static</span><span class="o">.</span><span class="n">hotjar</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">stats</span><span class="o">.</span><span class="n">g</span><span class="o">.</span><span class="n">doubleclick</span><span class="o">.</span><span class="n">net</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">storeapi</span><span class="o">.</span><span class="n">kobo</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">vars</span><span class="o">.</span><span class="n">hotjar</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">www</span><span class="o">.</span><span class="n">google</span><span class="o">-</span><span class="n">analytics</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">www</span><span class="o">.</span><span class="n">google</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">www</span><span class="o">.</span><span class="n">google</span><span class="o">.</span><span class="n">fr</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">www</span><span class="o">.</span><span class="n">googletagmanager</span><span class="o">.</span><span class="n">com</span>
<span class="mf">192.168</span><span class="o">.</span><span class="mf">12.214</span><span class="w"> </span><span class="n">www</span><span class="o">.</span><span class="n">msftncsi</span><span class="o">.</span><span class="n">com</span>
</code></pre></div>
<p>Using mitmproxy, we can check whether our assumptions about the tracked events were good. And they are: if you toggle your Wifi, google knows it. If you plug your reader, google knows it. If you do a dictionary lookup, if you adjust the brightness, if you tap the menu, google analytics knows it.</p>
<p>You sideload a book on your Kobo? Google knows it, and knows which book it is, because the ISBN-13 is sent:</p>
<p><img alt="Example of google receiving book sideload information through ISBN sending, in this case "The Art of Computer Programming" by Knuth" src="/images/kobo-google-1.png" title="Example of google receiving book sideload information through ISBN sending" /></p>
<p>You can disable those reports to google inside the “confidentiality” section, in the settings of the Kobo; this “feature” is at the end of the pages (it pretends it only share “features” you use on the device, but as seen on the previous screenshot, it also share what you read).</p>
<h1 id="resources">Resources<a class="headerlink" href="#resources" title="Permanent link">¶</a></h1>
<ul>
<li><a href="https://a3nm.net/blog/fnacbook_kobo_hacking.html">https://a3nm.net/blog/fnacbook_kobo_hacking.html</a></li>
<li><a href="https://www.mobileread.com/forums/showthread.php?t=162713">https://www.mobileread.com/forums/showthread.php?t=162713</a></li>
<li><a href="http://shallowsky.com/blog/tech/kobo-hacking.html">http://shallowsky.com/blog/tech/kobo-hacking.html</a></li>
<li><a href="https://www.graa.nl/articles/1760-H.html">https://www.graa.nl/articles/1760-H.html</a></li>
</ul>
<h1 id="more">More ?<a class="headerlink" href="#more" title="Permanent link">¶</a></h1>
<p>You have information about the Kobo Aura H2O you want to share? Email me at rémy@grünblatt.org (replace the accentuated characters with ther non-accentuated counterpart)</p>Mais avec qui communique l'application Izly?2017-07-22T00:00:00+02:002017-07-22T00:00:00+02:00Rémy Grünblatttag:remy.grunblatt.org,2017-07-22:/mais-avec-qui-communique-lapplication-izly.html<p>Il y a quelques semaines, j'ai eu la chance d'assister à plein de conférences intéressantes lors du festival <a href="https://passageenseine.fr">Pas Sage En Seine</a> dont les archives sont disponibles <a href="http://data.passageenseine.org/">en ligne</a>.</p>
<p>Parmis les conférences, celle de <a href="https://imirhil.fr/">Aeris</a> qui expliquait <a href="https://confs.imirhil.fr/20170629_pses_mitm/#1">« <em>comment powned une application bancaire en 30 minutes</em> »</a> m'a incité à regarder quelles …</p><p>Il y a quelques semaines, j'ai eu la chance d'assister à plein de conférences intéressantes lors du festival <a href="https://passageenseine.fr">Pas Sage En Seine</a> dont les archives sont disponibles <a href="http://data.passageenseine.org/">en ligne</a>.</p>
<p>Parmis les conférences, celle de <a href="https://imirhil.fr/">Aeris</a> qui expliquait <a href="https://confs.imirhil.fr/20170629_pses_mitm/#1">« <em>comment powned une application bancaire en 30 minutes</em> »</a> m'a incité à regarder quelles étaient les données envoyées par l'application android Izly, à des fins d'interoperabilité.</p>
<p>Pour rappel, Izly, c'est un système bancaire parallèle imposé par les CROUS aux étudiants, « <em>plus rapide, plus simple, plus sécurisé</em> » qui permet de payer son repas au restaurant universitaire. Je dis bien « <em>imposé</em> » aux étudiants, car il est bien souvent impossible de payer en monnaie sonnante et trébuchante (ou seulement certains jours de la semaine). Il devient quasi impossible de se passer de Izly, ce qui est problématique pour des raisons de vie privée. Je parle dans la suite de cet article de l'application android Izly: il reste bien sûr possible de recharger en ligne (moyennant le fait de filer ses coordonnées bancaires au service), sans utiliser de smartphones.</p>
<p>Bref, grâce à <a href="https://mitmproxy.org/">mitmproxy</a>, on peut étudier la manière dont l'application communique avec l'extérieur.</p>
<p><img alt="Example de requêtes envoyées par l'application Izly. Notons le peu de requêtes servant effectivement au service." src="./images/mitmproxy.png"><br/>
<em>Example de requêtes envoyées par l'application Izly. Notons le peu de requêtes servant effectivement au service.</em></p>
<p>L'application commence par communiquer avec le domaine <code>api.beaconforstore.com</code>. Cette communication s'effectue en deux étapes:</p>
<ul>
<li>
<p>Premièrement, une requête POST vers <code>https://api.beaconstore.com/api/v1/sdk/appInfos</code> qui contient le nom du téléphone, son modèle, sa version d'Android, ainsi que d'autres champs aux noms évocateurs: <code>"AdvertisingTrackingEnabled": 1,</code> ou encore <code>"sAdvertisingIdentifier": a5dd…</code>. </p>
</li>
<li>
<p>Une seconde requête POST vers <code>https://api.beaconforstore.com/api/v1/sdk/registerCustomer</code> contient quant à elle des variables comme la position GPS du téléphone (avec la latitude et la longitude, mais pas l'altitude), ou encore l'identifiant unique du téléphone.</p>
</li>
</ul>
<p>Le site web <a href="http://beaconforstore.com">http://beaconforstore.com</a> redirige actuellement vers le site web <a href="http://www.neer.by/">http://www.neer.by/</a> (qui ne supporte d'ailleurs pas les connections sécurisées), qui décrit le but du service: du « <em>Real life retargeting platform</em> ». En pratique, et le site illustre tout à fait ça, il s'agit de pister et d'espionner les mouvements physiques des utilisateurs. Ceci explique sûrement l'envoi de la position GPS du téléphone.</p>
<p><img alt="Screenshot de MITMProxy montrant la latitude et la longitude envoyées à beaconforstore" src="./images/MITM2.png"><br/>
<em>Screenshot de MITMProxy montrant la latitude et la longitude envoyées à beaconforstore</em></p>
<p>Dans un second temps, l'application communique avec l'API de Izly (bah oui, il faut bien que l'application serve à autre chose qu'à espionner les utilisateurs) pour l'établissement du service. Ça me semble assez classique, mais ça dépasse ici mon domaine de compétence.</p>
<p>L'application communique aussi avec le domaine <code>api.ad4push.com</code>, et envoie des données similaires aux données déjà envoyées, l'altitude et les données d'accélération en plus. J'ai donc le plaisir de vous annoncer que j'écris actuellement cet article à 413m au dessus du niveau de la mer. Est aussi envoyé le code postal de mon restaurant universitaire principal, mon CROUS de rattachement, et la date de validation des CGUs de Izly.</p>
<p>Enfin, l'application communique aussi avec <code>izly.maximiles.com</code> (code postal et crous de rattachement) (d'après Wikipedia, « <em>Maximiles est une société de fidélisation de client par un système de point sur internet</em> »).</p>
<p>Voilà donc avec qui l'application android izly communique.</p>
<p>Légalement, le CROUS s'assure avec des conditions d'utilisation leur permettant à peu près n'importe quoi. Ils précisent en effet que: « <em>Les données personnelles de l’Utilisateur sont principalement utilisées par S-MONEY pour les finalités suivantes : la conclusion et l’exécution du présent Contrat, en particulier les opérations de rechargement du compte de Monnaie électronique de l’Utilisateur, la prospection et l’animation commerciale, les études statistiques […]. Elles sont destinées, de même que celles qui seront recueillies ultérieurement, à S-MONEY, au Groupe BPCE, ainsi qu’à ses filiales directes et indirectes ou à ses partenaires commerciaux.</em> ». Pas certain que cette collecte soit par contre en accord avec le nouveau règlement européen pour la protection des données, le RGPD (règlement général sur la protection des données). En effet, le règlement précise que les données personnelles doivent être « <em>collectées pour des finalités déterminées, explicites et légitimes</em> », et « <em>la prospection et l'animation commerciale</em> » ou « <em>les études statistiques</em> » sont tout sauf des finalités précises.</p>
<p>Pour finir, une image tirée du <a href="https://www.ezeeworld.com/interview-pour-capital/">site de neerby</a> qui illustre le but suivi par cette entreprise. Sympa, pour une application de paiement!</p>
<p><img alt="" src="./images/neerby_interview_capital.jpg"></p>
<p>Ah, et aussi, cette magnifique interview du cofondateur d'EzeeWorld, à qui les données sont envoyées: <a href="http://www.ecranmobile.fr/Patrick-Chatanay-EzeeWorld-Neerby-est-une-plate-forme-de-retargeting-physique_a64003.html">http://www.ecranmobile.fr/Patrick-Chatanay-EzeeWorld-Neerby-est-une-plate-forme-de-retargeting-physique_a64003.html</a>:</p>
<p><em>« nous permet de connaître sa fréquentation (temps de présence, récurrence, …) et ses lieux de vie (lieu d'habitation, de travail, loisirs...) issus de milliers de points d'intérêt. »</em></p>
<p><em>« Concrètement, cela peut permettre à une marque d'envoyer un code promo à un client si elle le soupçonne de se rendre dans la boutique d'un concurrent »</em></p>
<p><em>« cibler des consommateurs correspondant à leurs cibles marketing et ainsi de concevoir de véritables stratégies cross device »</em></p>
</div>Quels sont les articles de wikipedia les plus édités par les parlementaires français ?2014-07-17T00:00:00+02:002014-07-17T00:00:00+02:00Rémy Grünblatt 🍃tag:remy.grunblatt.org,2014-07-17:/quels-sont-les-articles-de-wikipedia-les-plus-edites-par-les-parlementaires-francais.html<p><strong><em>21 mai 2020:</em></strong> Ajout de nouvelles IPs et mise à jour du code, migration de l'article vers le nouveau blog</p>
<p><strong><em>26 décembre 2016:</em></strong> Ajout du code en fin d'article</p>
<p><strong><em>29 juillet 2014:</em></strong> Ajout de précisions sur les plages ips utilisées: certaines appartiennent à la Présidence de la république, d'après le …</p><p><strong><em>21 mai 2020:</em></strong> Ajout de nouvelles IPs et mise à jour du code, migration de l'article vers le nouveau blog</p>
<p><strong><em>26 décembre 2016:</em></strong> Ajout du code en fin d'article</p>
<p><strong><em>29 juillet 2014:</em></strong> Ajout de précisions sur les plages ips utilisées: certaines appartiennent à la Présidence de la république, d'après le RIPE NCC (commande whois) et ajout d'une plage d'adresse ip pour le Sénat.</p>
<hr>
<p>Inspiré par l'article <a href="http://minimaxir.com/2014/07/caucus-needed/">« The Wikipedia Entries Which Are Most-Edited by Members of the U.S. Congress »</a>, j'ai eu envie de dresser un classement des pages de Wikipédia en version française les plus éditées anonymement (c'est-à-dire sans compte) par des adresses IP appartenant à l'assemblée nationale et/ou au sénat.</p>
<p>J'ai utilisé plusieurs plages d'adresses ip, plages trouvée sur un moteur de recherche, pour plusieurs centaines d'adresses:</p>
<ul>
<li>De 80.118.139.160 à 80.118.139.191 (Présidence de la République)</li>
<li>De 62.160.71.0 à 62.160.71.255 (Présidence de la République)</li>
<li>De 37.71.15.112 37.71.127 (Assemblée Nationale)</li>
<li>De 37.71.111.192 à 37.71.111.207 (Assemblée Nationale)</li>
<li>De 86.64.10.32 à 86.64.10.63 (Assemblée Nationale)</li>
<li>De 84.233.174.48 à 84.233.174.63 (Assemblée Nationale)</li>
<li>De 109.2.174.128 à 109.2.174.143 (Assemblée Nationale)</li>
<li>De 195.68.34.96 à 195.68.34.127 (Assemblée Nationale)</li>
<li>De 158.255.107.192 à 158.255.107.255 (Le Sénat)</li>
</ul>
<p>Il n'est pas garanti que ces ips appartiennent encore aux parlementaires, mais ce sont aussi les plages utilisées par le bot twitter <a href="https://twitter.com/wikiAssemblee">@wikiAssemblee</a> qui relaie en direct les modifications apportées à Wikipedia par ces ips. Il peut aussi s'agir d'éditions effectuées par des assistants, ou n'importe qui utilisant le réseau parlementaire, à relativiser donc.</p>
<p>Grâce à l'API mediawiki (<a href="https://fr.wikipedia.org/w/api.php">Wikipedia</a>) et à l'aide d'un script maison (globalement moche) écrit en python, on peut donc récupérer toutes les éditions effectuées sans compte depuis ces ips.</p>
<p>Ces données ont ensuite été mise en forme grâce à la bibliothèque d3.js, permettant la création de ce graphique (cliquez pour agrandir):</p>
<p><a href="/static/Parlement.html"><img alt="Texte alternatif" src="/images/Assemblée.jpg"></a></p>
<p>Chaque carré représente une édition pour l'article correspondant, et est coloré en rouge si on a affaire à une suppression de caractères (algébrique), ou en bleu si on a affaire à un ajout de caractères.
La teinte reflète la différence en nombre de caractères: plus c'est foncé, plus le nombre de caractères enlevé/ajouté est important.</p>
<p>Par ailleurs, un click sur chaque carré mène à la page récapitulative de l'édition en question, sur wikipedia.</p>
<p>Les résultats semblent cohérents avec ce que l'on pourrait attendre de parlementaires. On compte ~2000 éditions pour ~800 articles différents, dont beaucoup de corrections d'orthographe/de grammaire/de syntaxe.</p>
<p>Les données utilisées sont disponibles au format json dans le format retourné par l'api mediawiki <a href="/static/Parlement.json">à cette adresse</a>.</p>
<p>Le code utilisé pour générer ce fichier est reproduit ci-après. Même si il est crade, il a le mérite d'exister.</p>
<div class="highlight"><pre><span></span><code><span class="ch">#!/usr/bin/python3</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">requests</span>
<span class="n">user</span> <span class="o">=</span> <span class="s1">'Redacted'</span>
<span class="n">passwd</span> <span class="o">=</span> <span class="s1">'Redacted'</span>
<span class="n">baseurl</span> <span class="o">=</span> <span class="s1">'https://fr.wikipedia.org/w/'</span>
<span class="c1"># Présidence de la république</span>
<span class="n">prefix</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'62.160.71.'</span><span class="p">]</span>
<span class="n">prefix</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"80.118.139."</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">160</span><span class="p">,</span> <span class="mi">191</span><span class="p">)]</span>
<span class="c1"># Assemblée Nationale</span>
<span class="n">prefix</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"37.71.15."</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">112</span><span class="p">,</span> <span class="mi">127</span><span class="p">)]</span>
<span class="n">prefix</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"37.71.111."</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">192</span><span class="p">,</span> <span class="mi">207</span><span class="p">)]</span>
<span class="n">prefix</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"86.64.10."</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">32</span><span class="p">,</span> <span class="mi">63</span><span class="p">)]</span>
<span class="n">prefix</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"84.233.174."</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">48</span><span class="p">,</span> <span class="mi">63</span><span class="p">)]</span>
<span class="n">prefix</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"109.2.174."</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">128</span><span class="p">,</span> <span class="mi">143</span><span class="p">)]</span>
<span class="n">prefix</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"195.68.34."</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">96</span><span class="p">,</span><span class="mi">127</span><span class="p">)]</span>
<span class="c1"># Sénat</span>
<span class="n">prefix</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"158.255.107."</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">192</span><span class="p">,</span> <span class="mi">255</span><span class="p">)]</span>
<span class="n">results</span> <span class="o">=</span> <span class="p">{}</span>
<span class="c1"># Add to the hash table</span>
<span class="k">def</span> <span class="nf">addedit</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">urlid</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">,</span> <span class="n">table</span><span class="p">):</span>
<span class="k">if</span> <span class="n">title</span> <span class="ow">in</span> <span class="n">table</span><span class="p">:</span>
<span class="n">token</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">rev</span> <span class="ow">in</span> <span class="n">table</span><span class="p">[</span><span class="n">title</span><span class="p">][</span><span class="s1">'rev'</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">rev</span><span class="p">[</span><span class="s1">'urlid'</span><span class="p">]</span> <span class="o">==</span> <span class="n">urlid</span><span class="p">:</span> <span class="n">token</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">token</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">table</span><span class="p">[</span><span class="n">title</span><span class="p">][</span><span class="s1">'count'</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">table</span><span class="p">[</span><span class="n">title</span><span class="p">][</span><span class="s1">'rev'</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
<span class="s1">'ip'</span><span class="p">:</span> <span class="n">ip</span><span class="p">,</span>
<span class="s1">'urlid'</span><span class="p">:</span> <span class="n">urlid</span><span class="p">,</span>
<span class="s1">'size'</span><span class="p">:</span> <span class="n">size</span><span class="p">,</span>
<span class="s1">'timestamp'</span><span class="p">:</span> <span class="n">timestamp</span><span class="p">,</span>
<span class="s1">'id'</span><span class="p">:</span> <span class="mi">0</span>
<span class="p">})</span>
<span class="n">table</span><span class="p">[</span><span class="n">title</span><span class="p">][</span><span class="s1">'rev'</span><span class="p">]</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="s1">'urlid'</span><span class="p">])</span>
<span class="k">for</span> <span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">edit</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">table</span><span class="p">[</span><span class="n">title</span><span class="p">][</span><span class="s1">'rev'</span><span class="p">]):</span>
<span class="n">edit</span><span class="p">[</span><span class="s1">'id'</span><span class="p">]</span> <span class="o">=</span> <span class="n">index</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">else</span> <span class="p">:</span>
<span class="n">table</span><span class="p">[</span><span class="n">title</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="s1">'title'</span><span class="p">:</span> <span class="n">title</span><span class="p">,</span>
<span class="s1">'count'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="s1">'rev'</span><span class="p">:</span> <span class="p">[{</span>
<span class="s1">'ip'</span><span class="p">:</span> <span class="n">ip</span><span class="p">,</span>
<span class="s1">'urlid'</span><span class="p">:</span> <span class="n">urlid</span><span class="p">,</span>
<span class="s1">'size'</span><span class="p">:</span> <span class="n">size</span><span class="p">,</span>
<span class="s1">'timestamp'</span><span class="p">:</span> <span class="n">timestamp</span><span class="p">,</span>
<span class="s1">'id'</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">}]</span>
<span class="p">}</span>
<span class="c1">#Login request</span>
<span class="n">tokenRetrievalParameters</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">'action'</span><span class="p">:</span> <span class="s1">'query'</span><span class="p">,</span> <span class="s1">'meta'</span><span class="p">:</span> <span class="s1">'tokens'</span><span class="p">,</span> <span class="s1">'type'</span><span class="p">:</span> <span class="s1">'login'</span><span class="p">,</span> <span class="s1">'lgname'</span><span class="p">:</span> <span class="n">user</span><span class="p">,</span> <span class="s1">'format'</span><span class="p">:</span> <span class="s1">'json'</span> <span class="p">}</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Retrieval of login token…'</span><span class="p">)</span>
<span class="n">tokenRequest</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">baseurl</span> <span class="o">+</span> <span class="s1">'api.php'</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">tokenRetrievalParameters</span><span class="p">)</span>
<span class="n">token</span> <span class="o">=</span> <span class="n">tokenRequest</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s1">'query'</span><span class="p">][</span><span class="s1">'tokens'</span><span class="p">][</span><span class="s1">'logintoken'</span><span class="p">]</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Token retrieved: "</span> <span class="o">+</span> <span class="n">token</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Login…"</span><span class="p">)</span>
<span class="n">loginParameters</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">'action'</span><span class="p">:</span> <span class="s1">'login'</span><span class="p">,</span> <span class="s1">'lgname'</span><span class="p">:</span> <span class="n">user</span><span class="p">,</span> <span class="s1">'lgpassword'</span><span class="p">:</span> <span class="n">passwd</span><span class="p">,</span> <span class="s1">'lgtoken'</span><span class="p">:</span> <span class="n">token</span><span class="p">,</span> <span class="s1">'format'</span><span class="p">:</span> <span class="s1">'json'</span><span class="p">}</span>
<span class="n">loginRequest</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">baseurl</span> <span class="o">+</span> <span class="s1">'api.php'</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">loginParameters</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Logged in. Starting the requests!"</span><span class="p">)</span>
<span class="k">for</span> <span class="n">ips</span> <span class="ow">in</span> <span class="n">prefix</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Requesting edits for "</span> <span class="o">+</span> <span class="n">ips</span><span class="p">)</span>
<span class="n">editLogParameters</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'action'</span><span class="p">:</span> <span class="s1">'query'</span><span class="p">,</span> <span class="s1">'list'</span><span class="p">:</span> <span class="s1">'usercontribs'</span><span class="p">,</span> <span class="s1">'uclimit'</span><span class="p">:</span> <span class="s1">'499'</span><span class="p">,</span> <span class="s1">'format'</span><span class="p">:</span> <span class="s1">'json'</span><span class="p">,</span> <span class="s1">'ucprop'</span><span class="p">:</span> <span class="s1">'sizediff|ids|title|timestamp'</span><span class="p">,</span> <span class="s1">'ucuserprefix'</span><span class="p">:</span> <span class="n">ips</span><span class="p">}</span>
<span class="n">editLogRequest</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">baseurl</span> <span class="o">+</span> <span class="s1">'api.php'</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">editLogParameters</span><span class="p">,</span> <span class="n">cookies</span> <span class="o">=</span> <span class="n">loginRequest</span><span class="o">.</span><span class="n">cookies</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">editLogRequest</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s1">'query'</span><span class="p">][</span><span class="s1">'usercontribs'</span><span class="p">]))</span> <span class="o">+</span> <span class="s2">" edits…"</span><span class="p">)</span>
<span class="k">for</span> <span class="n">edit</span> <span class="ow">in</span> <span class="n">editLogRequest</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s1">'query'</span><span class="p">][</span><span class="s1">'usercontribs'</span><span class="p">]:</span>
<span class="n">addedit</span><span class="p">(</span><span class="n">edit</span><span class="p">[</span><span class="s1">'user'</span><span class="p">],</span> <span class="n">edit</span><span class="p">[</span><span class="s1">'title'</span><span class="p">],</span> <span class="n">edit</span><span class="p">[</span><span class="s1">'revid'</span><span class="p">],</span> <span class="n">edit</span><span class="p">[</span><span class="s1">'sizediff'</span><span class="p">],</span> <span class="n">edit</span><span class="p">[</span><span class="s1">'timestamp'</span><span class="p">],</span> <span class="n">results</span><span class="p">)</span>
<span class="k">while</span> <span class="s2">"continue"</span> <span class="ow">in</span> <span class="n">editLogRequest</span><span class="o">.</span><span class="n">json</span><span class="p">():</span>
<span class="n">editLogParameters</span><span class="p">[</span><span class="s1">'uccontinue'</span><span class="p">]</span> <span class="o">=</span> <span class="n">editLogRequest</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s1">'continue'</span><span class="p">][</span><span class="s1">'uccontinue'</span><span class="p">]</span>
<span class="n">editLogRequest</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">baseurl</span> <span class="o">+</span> <span class="s1">'api.php'</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">editLogParameters</span><span class="p">,</span> <span class="n">cookies</span> <span class="o">=</span> <span class="n">loginRequest</span><span class="o">.</span><span class="n">cookies</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">editLogRequest</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s1">'query'</span><span class="p">][</span><span class="s1">'usercontribs'</span><span class="p">]))</span> <span class="o">+</span> <span class="s2">" edits…"</span><span class="p">)</span>
<span class="k">for</span> <span class="n">edit</span> <span class="ow">in</span> <span class="n">editLogRequest</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s1">'query'</span><span class="p">][</span><span class="s1">'usercontribs'</span><span class="p">]:</span>
<span class="n">addedit</span><span class="p">(</span><span class="n">edit</span><span class="p">[</span><span class="s1">'user'</span><span class="p">],</span> <span class="n">edit</span><span class="p">[</span><span class="s1">'title'</span><span class="p">],</span> <span class="n">edit</span><span class="p">[</span><span class="s1">'revid'</span><span class="p">],</span> <span class="n">edit</span><span class="p">[</span><span class="s1">'sizediff'</span><span class="p">],</span> <span class="n">edit</span><span class="p">[</span><span class="s1">'timestamp'</span><span class="p">],</span> <span class="n">results</span><span class="p">)</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'output.json'</span><span class="p">,</span> <span class="s1">'wt'</span><span class="p">)</span> <span class="k">as</span> <span class="n">out</span><span class="p">:</span>
<span class="n">values</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">results</span><span class="o">.</span><span class="n">values</span><span class="p">(),</span> <span class="n">key</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="s1">'count'</span><span class="p">],</span> <span class="n">reverse</span> <span class="o">=</span> <span class="kc">True</span><span class="p">)</span>
<span class="n">indexed_values</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">values</span><span class="p">):</span>
<span class="k">for</span> <span class="n">rev</span> <span class="ow">in</span> <span class="n">val</span><span class="p">[</span><span class="s1">'rev'</span><span class="p">]:</span>
<span class="n">rev</span><span class="p">[</span><span class="s1">'parent_index'</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span>
<span class="n">indexed_values</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">indexed_values</span><span class="p">,</span> <span class="n">indent</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">separators</span> <span class="o">=</span> <span class="p">(</span><span class="s1">','</span><span class="p">,</span> <span class="s1">': '</span><span class="p">))</span>
<span class="n">out</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">res</span><span class="p">)</span>
<span class="n">out</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div>Using systemd-networkd with wpa_supplicant to manage wireless network configuration2014-01-06T00:00:00+01:002014-01-06T00:00:00+01:00Rémy Grünblatttag:remy.grunblatt.org,2014-01-06:/using-systemd-networkd-with-wpa_supplicant-to-manage-wireless-network-configuration.html<p>As of version 210, systemd now includes support for basic network configuration through udev and networkd. Systemd-networkd is a system daemon that manages network configuration. It detects and configures network devices as they appear, as well as creates virtual network devices.</p>
<p>There are a lot of tools for managing wireless …</p><p>As of version 210, systemd now includes support for basic network configuration through udev and networkd. Systemd-networkd is a system daemon that manages network configuration. It detects and configures network devices as they appear, as well as creates virtual network devices.</p>
<p>There are a lot of tools for managing wireless network (i.e. wifi) configuration for linux:
connman, netcfg, netifd, NetworkManager, WICD, wicked, etc…</p>
<p>They sometimes do a worse job than the underlying tools themselves will do when used directly, for example with roaming.
Here I’ll describe my network setup that uses wpa_supplicant and systemd-networkd and works seamlessly.</p>
<h2 id="systemd-networkd-configuration">Systemd-networkd configuration<a class="headerlink" href="#systemd-networkd-configuration" title="Permanent link">¶</a></h2>
<p>Systemd-networkd uses <code>/etc/system/network/</code> for configuration files. It is not intended to configure low-level settings of network interfaces as this remains udev’s job.</p>
<p>Any <code>.network</code> file present in <code>/etc/system/network/</code> will apply a network configuration for a matching device. I currently have two files in this directory, eth.network and wlp2s0.network. There structure is pretty self-explanatory:</p>
<p>–
<code>/etc/systemd/network/eth.network</code></p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="o">[</span>Match<span class="o">]</span>
<span class="c1"># Will match eth0, eth1, ethX…</span>
<span class="nv">Name</span><span class="o">=</span>eth*
<span class="o">[</span>Network<span class="o">]</span>
<span class="c1"># This will start DHCP on each interface whose name starts with eth</span>
<span class="nv">DHCP</span><span class="o">=</span>yes
</code></pre></div></td></tr></table></div>
<p>–
<code>/etc/systemd/network/wlp2s0.network</code></p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="o">[</span>Match<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>wlp2s0
<span class="o">[</span>Network<span class="o">]</span>
<span class="nv">DHCP</span><span class="o">=</span>yes
</code></pre></div></td></tr></table></div>
<p>Refer to systemd.network (5) for more informations.</p>
<h2 id="wpa_supplicant-configuration">wpa_supplicant configuration<a class="headerlink" href="#wpa_supplicant-configuration" title="Permanent link">¶</a></h2>
<p>Wpa_supplicant will be used for roaming and connection to wireless network. Here is my {basic,classic} configuration: </p>
<p>–
<code>/etc/wpa_supplicant/wpa_supplicant-wlp2s0.conf</code></p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nv">ctrl_interface</span><span class="o">=</span>/var/run/wpa_supplicant
<span class="nv">eapol_version</span><span class="o">=</span><span class="m">1</span>
<span class="nv">ap_scan</span><span class="o">=</span><span class="m">1</span>
<span class="nv">fast_reauth</span><span class="o">=</span><span class="m">1</span>
<span class="nv">network</span><span class="o">={</span>
<span class="w"> </span><span class="nv">ssid</span><span class="o">=</span><span class="s2">"Foobar1"</span>
<span class="w"> </span><span class="nv">psk</span><span class="o">=</span><span class="s2">"password1"</span>
<span class="w"> </span><span class="nv">priority</span><span class="o">=</span><span class="m">1</span>
<span class="o">}</span>
<span class="nv">network</span><span class="o">={</span>
<span class="w"> </span><span class="nv">ssid</span><span class="o">=</span><span class="s2">"Foobar2"</span>
<span class="w"> </span><span class="nv">psk</span><span class="o">=</span><span class="s2">"password2"</span>
<span class="w"> </span><span class="nv">priority</span><span class="o">=</span><span class="m">2</span>
<span class="o">}</span>
</code></pre></div></td></tr></table></div>
<p>I usually add new network to this file using this command: <code>wpa_passphrase <ESSID> <passphrase> >> wpa_supplicant-wlp2s0.conf</code></p>
<p>By enabling <code>systemd-networkd.service</code> and <code>wpa_supplicant@wpl2s0.service</code>, wpa_supplicant will automatically connect to any network available on the wlp2s0 interface, as configured in the <code>wpa_supplicant-wlp2s0.conf</code> file, bringing up the wlp2s0 interface. Since this interface is matched by the systemd-networkd configuration, the support for dhcpv4 will be enabled and this interface will get an ip. And if one wireless AP suddenly disappears, wpa_supplicant will handle the roaming.</p>
<p>By enabling <code>systemd-resolved.service</code>, systemd will automatically configure <code>/run/systemd/network/resolv.conf</code> when using DHCP instead of your <code>/etc/resolv.conf</code>. As stated in the man page of systemd-resolved, as /run/systemd/network/resolv.conf should not be used directly but only through a symlink from <code>/etc/resolv.conf</code>, I made a symlink.</p>
<p>It just works. And since you cannot use Archlinux without systemd nowadays, due to its <a href="http://boycottsystemd.org/">viral nature</a>, well, I’m using it.</p>
<h3 id="references">References:<a class="headerlink" href="#references" title="Permanent link">¶</a></h3>
<ul>
<li><a href="https://wiki.archlinux.org/index.php/Systemd-networkd">https://wiki.archlinux.org/index.php/Systemd-networkd</a></li>
<li><a href="https://coreos.com/blog/intro-to-systemd-networkd/">https://coreos.com/blog/intro-to-systemd-networkd/</a></li>
<li><a href="http://dabase.com/blog/Good_riddance_netctl/">http://dabase.com/blog/Good_riddance_netctl/</a></li>
</ul>