Mettre en place son propre serveur Minitel, partie 2

Je poursuis donc avec un autre billet à propos de la mise en place d'un serveur Minitel, un sujet que j'avais déjà traité en détail dans un billet précédent.

Dans ce billet-là, je n'avais traité que du système d'exploitation Linux et lorsque j'avais tenté l'expérience à nouveau sous FreeBSD, je me suis rendu compte que la mise en place d'un tel serveur était radicalement différente par rapport à Linux et que ces différences justifiaient selon moi un nouveau billet. J’en profiterai également pour ajouter quelques informations sommaires à propos de la gestion des ports série.

Schéma de principe
Schéma de principe du montage (rappel de mon billet précédent).

La principale différence par rapport à Linux est la façon dont le serveur attend des appels entrants au moyen du modem branché dessus : sous Linux, il est en effet nécessaire d'utiliser mgetty(1) du fait des limitations des autres « getty » qu'on peut trouver installés par défaut sous Linux. Le résultat est une série d’immondes bidouilles.

Sous FreeBSD, nul besoin d'installer quoi que ce soit : avec les outils du système de base et une bonne configuration de son modem, on peut obtenir un résultat propre et fonctionnel. En particulier, on obtient un écran de login sans erreurs de parité.

J'ai aussi été contraint de changer mon Olitec Self Memory Pro pour un US Robotics Sportster Flash (pour une poignée d'euros sur Leboncoin) car mon Olitec ne parvenait pas toujours à terminer le handshake lorsque je l'appelais. J'ai eu d'excellents résultats avec ce modem US Robotics. La gamme Courier de chez US Robotics était à une époque utilisée par les fournisseurs d'accès à Internet, mais un modem de cette gamme coûte aux alentours de 200 € sur eBay.

Les signaux importants d'un port série

L'écrasante majorité des modems externes communiquent avec leur hôte à l'aide d'une liaison série RS-232 (que ce soit encapsulé par USB ou non). L'interface RS-232 PC, comme on le sait, utilise des connecteurs DB-9 (9 broches). Ce qui paraît un peu moins évident, en revanche, c’est qu’un modem nécessite une signalisation assez spécifique pour fonctionner correctement dans notre configuration.

En terminologie RS-232, les périphériques peuvent assumer l'un des deux rôles suivants : le Data Terminal Equipment ou DTE d'une part et le Data Circuit-terminating Equipment ou DCE d'autre part. En règle générale, on relie toujours un DTE à un DCE (ou l'inverse) à l'aide d'un câble série.

Généralement, les modems sont des DCE et les équipements qui y sont connectés (comme un PC) sont donc des DTE.

Le brochage d'un connecteur DB-9 n'est pas non plus le même selon le rôle (DTE ou DCE) du périphérique.  La figure ci-dessous illustre le brochage DB-9 côté DTE.

Brochage DB-9 côté DTE
Brochage DB-9 côté DTE (source db9-pinout.com)

Parmi ces signaux, les plus importants pour nous sont :

  • TD (resp. RD) pour la transmission (resp. réception) de données proprement dite ;
  • DCD (« détection de porteuse de données »), qui est mis au niveau haut lorsque le modem a reçu un appel entrant, a terminé le handshake avec le modem distant et a établi une connexion ; concrètement, cela correspond au moment où la lettre C en haut à droite de l'écran du Minitel devient fixe. Le signal DCD repasse au niveau bas lorsque l'un des modems raccroche ;
  • DTR (« terminal de données prêt ») est mis au niveau haut par le DTE pour signaler au DCE qu'il est prêt. En cours d'une communication, si ce signal passe au niveau bas, alors le modem raccroche.

Ces signaux sont utilisés de la manière suivante dans notre configuration :

  1. Le serveur FreeBSD ouvre le port série et passe DTR au niveau haut ;
  2. Un utilisateur compose le numéro du modem, qui décroche et débute le handshake (dont le début correspond au son strident au bout de la ligne). L'utilisateur appuie sur Connexion/Fin sur le Minitel pour poursuivre le handshake.
  3. Une fois le handshake terminé (i.e. la connexion établie), le modem met DCD au niveau haut.
  4. Le serveur FreeBSD réagit à la montée de DCD et affiche l'invite de login UNIX, ou tout autre programme éventuellement configuré.

S'y ajoutent éventuellement les signaux DSR, RTS et CTS servant au contrôle de flux matériel.

Contrairement à ce qu'on pourrait croire, le signal RI (« indication de sonnerie ») ne nous intéresse pas. Dans notre configuration, le modem décroche automatiquement à la réception d'un appel, établit la connexion puis signale à l'aide de DCD le moment où le serveur doit démarrer getty(1) sur la ligne.

On peut désormais rentrer dans le vif du sujet. Il est en effet nécessaire de configurer à la fois le modem et le serveur FreeBSD.

Configuration du modem

La plupart des modems comprennent un jeu de commandes dit « jeu de commandes Hayes » (de l'entreprise qui l'a introduit pour la première fois). Ces commandes permettent notamment de configurer un modem pour être autonome et si placer dans un mode « réponse automatique ».

Tout d'abord, sur la machine FreeBSD, ouvrir le port série en 1 200 bauds, parité paire (cuaU0 dénotant un port série USB) :

# cu -e -s 1200 -l /dev/cuaU0

Une fois la connexion établie, saisir les deux commandes :

AT&F1E0M0Q1&N2 S0=1 S7=30 S13=1 S27=16
AT&W0

Taper ensuite ~. pour se déconnecter. Le modem est alors configuré.

La première commande, qui peut paraître absconse au premier abord, se décompose de la manière suivante :

AT
  &F1         Charger configuration usine (préréglage 1)
  E0          Désactiver l'écho local des commandes
  M0          Désactiver le haut-parleur
  Q1          Désactiver les messages d'état
  &N2         Vitesse 1 200 baud
  S0=1        Décrocher automatiquement à la 1ère sonnerie
  S7=30       Abandonner le handshake après 30 s
  S13=1       Réinitialiser le modem à la chute du signal DTR
  S27=16      Activer le mode « fallback » V.23

AT
  &W0         Sauvegarder la configuration dans le registre 0

À noter que ces deux commandes sont spécifiques à ce modèle particulier de modem et qu'il faudra impérativement consulter la documentation de votre modem pour constituer une commande qui fasse la même chose que celle montrée ci-dessus.

Le mode « fallback » V.23, qui est spécifique au modem que j'utilise, semble nécessaire pour que celui-ci fonctionne avec un Minitel en face. Tous les autres paramètres sont nécessaires pour des raisons de confort (par exemple parce que je n'ai pas envie d'entendre les bruits du handshake) ou exigés par FreeBSD (par exemple la réinitialisation à la chute de DTR). Enfin, on sauvegarde ces paramètres pour qu'ils soient chargés à l'allumage du modem et à chaque réinitialisation.

Configuration de FreeBSD

Avant de poursuivre, il faut noter que FreeBSD gère les ports série un peu différemment par rapport à Linux. FreeBSD crée deux fichiers de périphérique par port série : un périphérique « /dev/cuaX » et un périphérique « /dev/ttyX ». Le périphérique « tty » bloque tant que le signal DTR est au niveau bas ; en revanche, le périphérique « cua » ne tient pas compte de ce signal. Autrement dit : on ouvre un périphérique « tty » lorsque nous attendons une connexion d'un modem externe et le périphérique « cua » lorsque nous sommes nous-mêmes à l'origine d'une connexion.

En outre, et comme je l’avais déjà dit précédemment, contrairement à Linux où il fallait compiler une version patchée de mgetty pour espérer un fonctionnement à peu près correct, ici il n'y a besoin que de quelques ajouts dans deux fichiers de configuration.

Pour commencer, le getty(1) de FreeBSD intègre sa propre base de données « à la termcap », ce qui permet d'expliquer à getty qu'un Minitel est une drôle de bestiole nécessitant 1 200 bauds, 7 bits de données, parité paire, 1 bit d'arrêt, derrière un modem. C'est dans le fichier /etc/gettydefs (cf. gettydefs(5)) que ça se passe et il suffit d'ajouter la section suivante :

#
# Entries for Minitel communicating through their built-in modems
#

minitel.dialup|Minitel through dialup:\
        :hw:ec:ep:rw:sp#1200:

Le fichier permet même de définir un « auto-login » ou un programme de login alternatif. Enfin, dans /etc/ttys (cf. ttys(5)), ajouter :

# Minitel (par modem)
ttyU0   "/usr/libexec/getty minitel.dialup"     minitel on      insecure

Bien entendu, substituez dans le premier champ le vrai nom de votre port série. Ce sera ttyu0 pour le premier port série (l'équivalent de ttyS0 sous Linux) ou ttyU0 pour le premier port série USB (l'équivalent de ttyUSB0 sous Linux). Enfin, appliquez les changements en tapant la commande init q en tant que root).

Si tout se passe bien, les LEDs « AA » (réponse automatique), « TR » (terminal prêt) et « CS » (prêt à envoyer) seront allumés. Testez ensuite en suivant les instructions que j'ai déjà détaillés avant et vous aurez normalement une invite de connexion. Testez donc votre login et votre mot de passe !

Conclusion

Je suis agréablement surpris de voir que grâce à FreeBSD, il est encore plus facile de mettre en place le nécessaire pour héberger des serveurs Minitel. Mais outre la possibilité de monter un tel serveur, c'est en réalité une sorte de point d'accès qu'on met en place. Il suffit alors de substituer le programme de son choix à login(1) sur la ligne série concernée.

Bien que ce sujet semble susciter encore un peu d'intérêt parmi les bidouilleurs de tous les âges, je doute cependant qu'un serveur Minitel recevrait aujourd'hui beaucoup d'appels. Mais parfois, ce n'est pas toujours pour l'utilité pratique qu'on bidouille mais simplement pour la pure prouesse technique.

Posté par x0r à 4 commentaires • Tags : hack minitel FreeBSD modem

L'IPv6 par Orange : premières impressions

Mise à jour du 4 mars 2016 : ajout d'une capture tcpdump d'un paquet RA de la Livebox.

Mise à jour du 7 mars 2016 : ajout de quelques détails sur les changements de préfixes IPv6.

Cela fait maintenant quelques mois qu'une mise à jour du firmware de la Livebox fournit une vraie connectivité IPv6 à ses clients.

Capture d'écran de
l'interface d'administration
Hé oui, cette fois, ça marche !

Chez moi, cette bascule a eu lieu le 25 novembre 2015 en pleine nuit. Ce passage à IPv6, qu’on nous avait promis depuis quelque temps, a introduit un certain nombre de changements techniques dans la connectivité à Internet, que je détaillerai également dans ce billet.

Avant de poursuivre, je souhaite souligner que les observations décrites ci-après ont été faites avec la version SG30_sip-fr-5.15.8.1 du firmware.

Des adresses IPv4 enfin fixes !

Tout d'abord, ce nouveau firmware initie une connexion sur le VLAN 832 et non plus sur le VLAN 835. On perd de plus le PPPoE ; du point de vue de la box, elle dialogue directement par Ethernet.

Cela a eu une autre conséquence, et non des moindres : l'adresse IPv4 est désormais fixe. Finies, donc, les déconnexions hebdomadaires qui faisaient changer d'adresse IPv4 et cassaient IRC et les jeux en ligne. Cette adresse IPv4 reste fixe même après plus de cinquante jours d'uptime de la box et un redémarrage de celle-ci.

Et peut-être bientôt aussi les préfixes IPv6

Bien que les adresses IPv4 soient désormais fixes, on ne peut malheureusement pas en dire autant pour les préfixes IPv6. Ce qui est, encore une fois, particulièrement gênant pour les utilisateurs envisageant de mettre en place des serveurs derrière leurs Livebox, à moins d'utiliser un mécanisme de DNS dynamique similaire à ce que j'avais déjà évoqué auparavant.

Cependant, il semblerait que ces changements de préfixes se font de plus en plus rares. Il est donc probable que les préfixes IPv6 seront fixes eux aussi. Seul le temps nous le dira.

Heureusement, lors d'une bascule d'un préfixe à l'autre, l'ancien préfixe reste encore valable pendant quelque temps, contrairement à un changement d'adresse IPv4 qui casse tout.

Quoi qu'il en soit, Orange fournit un préfixe de 56 bits à chaque client (ce qui ouvre normalement la possibilité de le segmenter en 256 réseaux /64), mais mes tests montrent qu'il n'est pas encore possible d'exploiter l'entièreté de cet espace d'adressage.

Par exemple, la capture d'écran ci-dessus montre que je dispose du préfixe 2a01:cb04:d5:9500::/56. Mais en réalité, la Livebox ne routera que le préfixe 2a01:cb04:d5:9500::/64, ce qui ne correspond qu'à 1/256e de l'espace d'adressage qu'Orange fournit.

De surcroît, bien que mon routeur OpenWRT implémente la délégation de préfixes telle que décrite dans la RFC 3633, cela ne semble pas encore être le cas de la box. C'est bien dommage, car cette fonction est indispensable pour pouvoir profiter de son /56 comme il se doit. J'aurais bien aimé isoler mes machines dans un sous-réseau de préfixe 2a01:cb04:d5:9501::/64 (par exemple) où toutes les connexions entrantes seraient bloquées par défaut, et d'avoir un autre préfixe pour ma DMZ.

En conclusion, pour le moment, ça ne marchera que chez les clients qui ont une architecture réseau à la « madame Michu », c'est-à-dire ceux qui n'ont pas d'autre routeur que leur Livebox.

Dissection

La Livebox semble embarquer son propre petit serveur DHCPv6, car la configuration des clients IPv6 sur le réseau se fait en « stateful » (voir à ce sujet la RFC 3315).

Ci-dessous, un paquet ICMPv6 Router Advertisement tel qu'envoyé par le box.

13:45:29.529976 IP6 (class 0xc0, hlim 255, next-header ICMPv6 (58)
payload length: 104) fe80::7e03:d8ff:fec0:4120 > ff02::1:
[icmp6 sum ok] ICMP6, router advertisement, length 104
        hop limit 64, Flags [other stateful], pref high, router
    lifetime 180s, reachable time 0s, retrans time 0s
          prefix info option (3), length 32 (4): 2a01:cb04:5b3:8700::/64,
      Flags [onlink, auto], valid time 900s, pref. time 300s
            0x0000:  40c0 0000 0384 0000 012c 0000 0000 2a01
            0x0010:  cb04 05b3 8700 0000 0000 0000 0000
          rdnss option (25), length 24 (3):  lifetime 60s, addr: fe80::7e03:d8ff:fec0:4120
            0x0000:  0000 0000 003c fe80 0000 0000 0000 7e03
            0x0010:  d8ff fec0 4120
          dnssl option (31), length 16 (2):  lifetime 60s, domain(s): home.
            0x0000:  0000 0000 003c 0468 6f6d 6500 0000
          mtu option (5), length 8 (1):  1500
            0x0000:  0000 0000 05dc
          source link-address option (1), length 8 (1): 7c:03:d8:c0:41:20
            0x0000:  7c03 d8c0 4120

Conclusion

Il était largement temps que les FAI français passent à l'IPv6, et c'est une excellente nouvelle de voir qu'Orange emboîte le pas lui aussi. Mais certains aspects de la mise en œuvre de ce protocole chez Orange me fait encore froncer un peu les sourcils, et pour les raisons que j'ai citées dans ce billet, je ne suis pas encore en mesure de passer tout mon réseau interne en IPv6. J'attends cependant avec impatience la résolution du problème de la délégation de préfixes.

Je suis conscient que j'aurais également pu utiliser ndppd comme je l'avais fait pour Free, mais je considère que je ne devrais pas avoir à faire ce genre de « hacks » quand on est censé disposer d'un /56.

Enfin, une autre possibilité aurait été de substituer un routeur différent à la box, mais c'est une option que je ne peux envisager car j'utilise beaucoup la ligne téléphonique. Mes efforts consistant à ne plus dépendre de l'interface FXS de la box m'avaient d'ailleurs apporté quelques ennuis.

Comment j'ai cassé moncompteformation.gouv.fr

Je commencerai par dédicacer ce premier billet de l'année aux intrépides qui estiment pouvoir coder eux-mêmes leur algorithme de validation syntaxique d'adresses e-mail sans lire le sacro-saint RFC 2822, le document définissant ce qu'est une adresse e-mail valable.

Ceux qui ont vu mes informations de contact sur mon blog se sont sûrement aperçus que j'utilise un caractère inhabituel dans mon adresse mail : le signe « plus ».

Pour moi, cela me sert à créer des « alias » ad hoc, qui sont automatiquement redirigés vers mon adresse principale sans avoir à toucher à un quelconque fichier de configuration de Postfix. Ces alias me servent ensuite à trier mes mails plus efficacement (y compris pour les mettre directement à la poubelle lorsqu'un organisme abuse de mes coordonnées pour m'envoyer du spam).

Il m'est ensuite bien plus facile de créer des règles de tri fondées sur l'adresse e-mail du destinataire (ce destinataire étant l'un de ces nombreux alias) plutôt que sur des critères moins fiables. Certains fournisseurs, comme GMail, proposent également la même fonctionnalité.

RFC 2822, une lecture indispensable

La RFC 2822 (§ 3.2.4) donne la liste des caractères acceptables dans une adresse e-mail, mis à part le "@" qui sert de séparateur : tout caractère alphanumérique, mais aussi les symboles "!", "#", "$", "%", "&", "'" (apostrophe), "*", "+", "-", "/", "=", "?", "^", "_", "`" (backtick), "{", "|", "}", "~". Le point est aussi accepté, sauf en début ou en fin de chaîne de caractère.

Cela signifie donc qu'une adresse comme « !&'}.|`?@example.com » est tout à fait valable et que tous ceux qui rejettent cette adresse e-mail violent la RFC 2822. Je dispose d'une liste croissante de sociétés, dont des FAI (voyez l'ironie) et des banques, qui rejettent mes adresses contenant juste un « plus ». C'est consternant, car des bibliothèques faisant cette validation syntaxique cor­rec­tement existent déjà et qu'il est donc parfaitement inutile de réinventer une roue carrée.

Un petit plus qui casse tout

Maintenant que j'ai fait cette petite parenthèse sur tous les caractères qu'on peut mettre dans une adresse mail, revenons au sujet. L'histoire remonte à l'an dernier. À cause d'un mauvais algorithme de validation d'adresses e-mail et d'une ribambelle d'autres bugs, j'ai en effet réussi à "casser" le site moncompteformation.gouv.fr d'une façon que je n'aurais jamais cru possible.

J'ai voulu créer mon compte en remplissant le formulaire, où l'on demande : numéro de Sécurité sociale, nom, prénom, adresse e-mail et d'autres joyeusetés. Ce faisant, j'ai pris soin de saisir une adresse e-mail avec comme partie utilisateur « x0r+cpf ».

Je valide. Le formulaire passe. Mon adresse e-mail est acceptée et on me laisse donc passer à l'étape suivante, qui consiste à choisir un mot de passe. Je valide. Et là, erreur : impossible de créer le compte car mon adresse e-mail n'est pas valable.

Je me demande pourquoi cette validation ne s'est pas faite directement après avoir soumis le premier formulaire. Je reviens donc en arrière, en maugréant et en ajoutant un alias à la main dans la configuration Postfix ; je substitue alors un point au caractère plus dans mon adresse, ce qui devrait théoriquement passer.

Et là, nouvelle erreur : il existe déjà un compte avec ce numéro de Sécurité sociale.

Pourtant, c'est impossible : on m'avait pourtant dit que le compte ne pouvait pas être créé car « x0r+cpf » n'était pas valable. Je n'ai même pas reçu d'e-mail de confirmation. Il y avait bien eu un mail, en fait, d'après les logs de Postfix, mais il a dû se faire manger par SpamAssassin : un collègue m'a confirmé que le mail de confirmation était envoyé depuis une machine sans reverse DNS, ce qui va à l'encontre des bonnes pratiques. Étant donné que les spammeurs envoient souvent leurs spams depuis des machines sans reverse DNS, ce genre de messages finira dans les dossiers « Spams » à coup sûr chez beaucoup de monde.

Conclusion : je me retrouve avec un compte à moitié créé, auquel je n'ai pas accès car le mot de passe n'a jamais pu être défini pour ce compte. La base de données utilisant visiblement le numéro de Sécurité sociale comme clé primaire, il m'était impossible de recommencer.

La valse des analyseurs syntaxiques en mousse

La page de contact du site donne l'adresse e-mail du webmaster, que je m'empresse de contacter afin de lui expliquer les faits que je viens d'évoquer, et que je me retrouve du coup avec un compte inexploitable. En pensant que la plupart des clients e-mail de nos jours géreraient mon adresse correctement, je mets « x0r+cpf » dans le champ From. J'envoie.

Mes logs Postfix montrent ensuite que quelqu'un, ou un robot, a alors essayé d'envoyer un message à... « cpf ».

Non seulement ils valident mal les adresses, non seulement leurs machines n'ont pas de reverse DNS, mais quelqu'un ou quelque chose parvenait encore, en 2015, à mal extraire l'adresse e-mail du champ "From" d'un mail. L'e-mail tel qu'on le connaît existe pourtant depuis 1982.

Je crée donc encore un alias pour que les messages adressés à l'utilisateur « cpf » ne finissent pas à la cyber-poubelle, et je renvoie un deuxième mail pour informer le webmaster du dysfonctionnement. Même adresse From que le mail précédent, et même réponse sur la mauvaise adresse : c'était en fait un mail de confirmation envoyé par un robot d'une plate-forme d'e-mails destinée aux entreprises.

Enfin, à mon premier mail, je reçois en réponse un message à côté de la plaque me conseillant de faire des choses que j'avais déjà essayées : à savoir, m'inscrire, réinitialiser mon mot de passe, et ainsi de suite. J'avais pourtant déjà dit que j'avais essayé tout cela avant d'envoyer mon mail au webmaster.

En fin de compte, c'est seulement en décrochant le bon vieux téléphone (ou un téléphone IP chez moi, donc pas vraiment "bon vieux", certes) et en appelant le support technique que j'ai plus ou moins réussi à résoudre le problème : mon interlocutrice a su défaire cette tentative de création de compte qui avait échoué, puis tout a fini par rentrer dans l'ordre. Mais malheureusement sans caractère plus dans l'adresse e-mail.

Conclusion

Ce genre de situations montre bien ce à quoi peut aboutir plusieurs « petits » problèmes, qui, mis bout à bout, entraînent des résultats potentiellement catastrophiques :

  • un algorithme de validation syntaxique d'adresses e-mail non conforme à la RFC 2822 ;
  • une configuration de zone DNS non conforme aux bonnes pratiques (i.e. enregistrements PTR manquants pour les serveurs mail sortants) ;
  • un processus de création de compte non atomique ;
  • enfin, une plateforme e-mail de support technique buguée.

Ce qui me choque est surtout le fait que la création de compte ne soit pas atomique. L'atomicité signifie qu'à la fin, on a soit un compte parfaitement créé, soit rien du tout. Je vois d'ailleurs mal comment quelque chose d'aussi simple que l'ajout d'un seul tuple dans une seule table peut échouer de manière aussi catastrophique.

En fin de compte, si on dit que le développement informatique est le BTP des temps modernes, j'ai bien peur qu'on finira par être entouré de châteaux de cartes. Y compris dans le service public.

Posté par x0r à 7 commentaires • Tags : web site borken bugs rfc2822

Let's Encrypt : premières impressions

Avertissement : j'ai écrit ce billet à une époque où le service était uniquement disponible en béta fermée sur inscription. Beaucoup de choses ont sûrement évolué depuis.

Lorsqu'on met en place un site Web et qu'on souhaite servir son site en HTTPS, il faut tout d'abord obtenir un certificat SSL auprès d'une autorité de certification.

Ces certificats SSL sont généralement payants, pour des raisons diverses et variées. Il existe quelques autorités de certification gratuites mais de qualité très variable. Les AC gratuites ne sont en outre pas toujours reconnues par la plupart des navigateurs et ainsi, sans configuration spécifique côté client, un tel certificat peut entraîner l'affichage d'une alerte de sécurité. Alertes qui sont conçues pour faire peur, et pour une bonne raison.

Jusqu'à maintenant, il y avait CACert et StartSSL. Le premier fonctionne bien mais n'est pas reconnu. Le second se targue d'être reconnu, mais mes mauvaises expériences chez eux ne m'incitent pas à les recommander. Mais une troisième AC gratuite, reconnue et particulièrement prometteuse va bientôt voir le jour : Let's Encrypt.

Let's Encrypt est en effet une nouvelle autorité de certification SSL qui fournit gratuitement des certificats DV (Domain Validation). Cerise sur le gâteau, cette autorité de certification est reconnue par la plupart des navigateurs.

Il y a deux semaines, j'ai donc reçu dans ma boîte mail une invitation à la béta fermée de Let's Encrypt.

E-mail reçu de la part
de Let's Encrypt
Un e-mail que j'ai attendu avec impatience.

L'occasion parfaite pour, en guise de test, générer un certificat et une clé privée SSL par le biais de leur service pour x0r.fr. L'expérience est une réussite et je suis sûr que cette autorité de certification finira par modifier en profondeur le marché des certificats SSL.

J'expliquerai succinctement l'intérêt qu'a pour des blogueurs comme moi le fait de servir du HTTPS, avant de montrer comment j'ai mis en œuvre les outils de Let's Encrypt sous FreeBSD pour générer mon certificat SSL.

Pourquoi tout le monde devrait (en théorie) servir du HTTPS

Il fut un temps où l'on estimait que servir son site en HTTPS n'était utile que lorsqu'il y avait un vrai impératif de confidentialité, comme par exemple sur un site marchand où on est amené à saisir des informations sensibles (numéros de carte bleue, etc.). Mais ça, c'était en 1997.

Il ne faut pas oublier les autres avantages du HTTPS, qui sont entre autres la protection de la vie privée de l'utilisateur et la protection de l'intégrité des pages Web.

Par exemple, aux États-Unis, un fournisseur d'accès à Internet proposait des connexions Wi-Fi gratuites. Cependant ce FAI injectait des publicités dans les pages visitées par les utilisateurs. Ces publicités injectées étaient placées de telle manière qu'elles semblaient provenir du site Web lui-même.

Rien n'empêcherait non plus un fournisseur d'accès à lancer un petit tcpdump et à enregistrer tous les paquets ayant comme port de destination 80, afin de logguer les sites consultés par chaque utilisateur.

En fin de compte, servir du HTTPS ne signifie en rien qu'on a forcément quelque chose à cacher ; il est aussi utile pour se protéger des intermédiaires techniques parfois peu scrupuleux. Et il paraît absurde de nos jours de vouloir restreindre cette protection à ceux qui seraient prêts à mettre des dizaines voire centaines d'euros par an pour cela. Dans un Web universel, le HTTPS devrait donc être accessible à tous, tant consommateurs que producteur de contenus.

Mise en œuvre de Let's Encrypt

Un des buts de Let's Encrypt est d'automatiser le plus possible les tâches de génération de clés publiques et privées d'une part et la génération de la requête de certification d'autre part. Avouons-le, qui s'est rappelé de la ligne de commandes d'openssl(1) du premier coup ?

Pour cela, l'autorité de certification fournit un programme, letsencrypt, qui se charge de gérer de façon automatisée les certificats.

Les certificats de Let's Encrypt étant des certificats DV (Domain Validation), dont la seule garantie est de « prouver » qu'ils ont été distribués au propriétaire légitime du domaine, le programme letsencrypt se charge aussi d'apporter la preuve que le demandeur du certificat contrôle bien le nom de domaine qu'il demande.

Le serveur d'authentification effectue pour cela une authentification par défi-réponse : le défi est un chemin (relatif à la racine du domaine) généré au hasard et supposé ne pas exister auparavant. La réponse est une chaîne de caractères qui doit être servie au format MIME text/plain par le serveur HTTP en réponse à un GET sur l'URL du défi.

Par défaut, letsencrypt veut ouvrir les ports 80 et 443 et écouter sur ces ports pour effectuer la validation par défi-réponse. Ceci est généralement impossible ; après tout, la plupart des gens qui souhaitent mettre en œuvre HTTPS ont déjà leur site en HTTP uniquement, et vraisemblablement un Apache, lighttpd ou nginx qui écoute sur ces deux ports. Il existe heureusement deux solutions : une manuelle, l'autre automatique. Les deux nécessitent cependant de modifier les fichiers de configuration du serveur Web ; je ne montrerai ici que nginx car je n'ai pas testé d'autres configurations.

Première installation et mise en œuvre de letsencrypt-auto

Note importante : le logiciel évolue assez rapidement ; aussi les bugs exhibés dans ce paragraphe pour­raient être résolus depuis, de nouveaux bugs pourraient s'être glissés depuis et le fonctionnement et les messages affichés à l'écran peuvant différer de ce qui est transcrit ici.

Mise à jour du 12 janvier 2016 : sous FreeBSD, le logiciel est désormais disponible dans la collection des ports FreeBSD. Le port s'appelle security/py-letsencrypt et le package pkgng s'appelle py27-letsencrypt. Installez-le par ce biais, c'est plus propre.

L'installation de letsencrypt et de ses dépendances commence par le clonage du dépôt Github.

# git clone 'https://github.com/letsencrypt/letsencrypt.git'
# cd letsencrypt/

Sa première mise en place devait normalement être faite par la commande ci-dessous, mais qui ne fonctionnait pas au moment de mes essais :

# ./letsencrypt-auto --debug
Bootstrapping dependencies for FreeBSD...
./letsencrypt-auto: : Permission denied

Pour obtenir le même résultat, il a fallu que j'enchaîne les deux commandes :

# sh bootstrap/freebsd.sh
# sh -x ./letsencrypt-auto --debug

Authentification manuelle

Lors de mes premiers essais, j'ai uniquement trouvé la méthode manuelle. Celle-ci s'invoque de la manière suivante :

# ./letsencrypt-auto --server https://acme-v01.api.letsencrypt.org/directory -a manual certonly

L'outil affiche pas mal de texte avant d'imprimer ceci à l'écran :

Make sure your web server displays the following content at
http://example.com/.well-known/acme-challenge/N5_Uft_vn0XL0sGfsYsvNCfEzWkm77iHTlmY-hPBT6A before continuing:

N5_Uft_vn0XL0sGfsYsvNCfEzWkm77iHTlmY-hPBT6A.G_2TWMVNdOlzHIUDK_XG9n_c8Bkk3yrAiwb-U-HSNxM

Content-Type header MUST be set to text/plain.

(snip)

Press ENTER to continue

On modifie ensuite la configuration nginx pour ajouter la clause suivante :

location /.well-known/acme-challenge/N5_Uft_vn0XL0sGfsYsvNCfEzWkm77iHTlmY-hPBT6A {
    default_type 'text/plain';
    return 200 'N5_Uft_vn0XL0sGfsYsvNCfEzWkm77iHTlmY-hPBT6A.G_2TWMVNdOlzHIUDK_XG9n_c8Bkk3yrAiwb-U-HSNxM';
}

On reload nginx et on appuie sur ENTRÉE. Si tout se passe bien, on obtient le message suivant :

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will expire
   on 2016-02-04. To obtain a new version of the certificate in the
   future, simply run Let's Encrypt again.

Renouvellement automatique

Mise à jour du 12 janvier 2016 : l'option --accept-dev-preview a été remplacée par --accept-tos depuis la béta ouverte.

Les certificats fournis par Let's Encrypt ne sont valables que 90 jours. Cette durée de validité est très courte et semble prendre à contrepied la politique de la plupart des autorités de certification, qui proposent des certificats valables entre 6 mois et 2 ans.

Lorsqu'on administre qu'un seul site Web, ce n'est pas très fastidieux de devoir modifier seulement quatre lignes de configuration nginx tous les deux à trois mois. Mais à partir de deux, ça devient vite peu pratique.

Heureusement, la tâche de renouvellement se prête bien à l'automatisation, moyennant deux modi­fi­cations. La première est d'utiliser letsencrypt avec l'option -a webroot au lieu de -a manual. Cela demande à letsencrypt de faire l'authentification par challenge-response en plaçant un fichier adéquat dans le sous-répertoire .well-known/acme-challenge dans l'emplacement de son choix. La deuxième est de modifier la configuration de nginx pour servir le contenu des fichiers de ce sous-répertoire.

Ces informations (ainsi que le gist de renchap) me permettent de faire le script shell de renouvellement, dont voici le listing.

#!/bin/sh

LETSENCRYPT="/root/.local/share/letsencrypt/bin/letsencrypt"
DIR="/tmp/letsencrypt-auto"
DOMAINS="-d example.com -d www.example.com"

mkdir -p "${DIR}" && \
${LETSENCRYPT} certonly \
    --agree-tos --renew -a webroot --webroot-path "${DIR}" \
    --server https://acme-v01.api.letsencrypt.org/directory ${DOMAINS} && \
service nginx reload

J'associe ce script avec un fichier de configuration nginx que j'ai appelé letsencrypt.conf, dont voici le contenu :

location '/.well-known/acme-challenge' {
    default_type "text/plain";
    root /tmp/letsencrypt-auto;
}

Enfin, j'inclus ce fichier de configuration à l'aide d'un include 'letsencrypt.conf'; dans la configuration de chacun de mes vhosts.

J'ai pu vérifier que ce script renouvelle bien le certificat pour x0r.fr avec comme nom alternatif www.x0r.fr.

Lorsqu'on a plusieurs sites Web sur la même machine, il faudra lancer ce script plusieurs fois (une fois par site) afin de générer des certificats (et donc des clés privées) différents par site.

Place au test

Après avoir mis en place les certificats et adapté ma configuration nginx, mon site réussit haut la main le test SSL de SSL Labs. Il ne reste plus qu'à mettre en place HSTS pour avoir la note A+.

Résultat du test
 de SSL Labs
Enfin ! Ça fait du bien d'avoir une note autre que « T » sur ce test.

Conclusion

L'approche de Let's Encrypt tranche radicalement avec les habitudes des autres autorités de certification SSL que j'ai pu connaître. Le fait qu'il s'agisse d'un système entièrement automatisé, la faible durée de vie des certificats, la gratuité et le fait que l'autorité de certification soit reconnue dans la plupart des navigateurs en font quelque chose d'unique.

Let's Encrypt n'aurait à mon avis pas pu exister sans le contexte des écoutes en masse par la NSA qui ont été révélées par Edward Snowden, ni sans les problématiques du respect de la vie privée ou de la neutralité des réseaux. Il s'agissait là de donner la possibilité à n'importe qui de déployer du HTTPS facilement. Ce pari me semble bien parti pour être réussi.

Posté par x0r à 7 commentaires • Tags : linux nginx letsencrypt https ssl

monrer.fr : Quelques nouvelles et projets futurs

Cela fait certes un bon moment que je n'ai pas écrit de billet sur monrer.fr. Il faut avouer que le site Web n'a connu que peu de dysfonctionnements (de ce que j'ai pu voir, en tout cas). J'ai eu peu de temps également cette année pour le faire réellement évoluer. Il n'y a pas non plus eu de grands bouleversements côté SNCF et Open Data de manière générale.

Je pense malgré tout qu'un petit billet à propos de ce petit site est le bienvenu, histoire quand même de traiter les quelques évolutions que j'ai faites et ce que j'envisage dans l'avenir.

Un exercice de responsive design

Jusqu'à récemment, je faisais encore partie des quelques réfractaires qui ne voyait pas l'utilité d'un smartphone. Mais j'ai fini par craquer, entre autres à cause de la mauvaise qualité de construction de mon précédent téléphone.

J'ai cependant fait l'acquisition d'un smartphone durant l'été dernier, et cela a été l'occasion pour moi de reprendre le design du site. Il avait en effet un grand besoin d'être refait en « responsive design », c'est-à-dire être capable de s'adapter dynamiquement en fonction de la largeur de l'écran. Ainsi, le site devient (à peu près) utilisable sur un smartphone.

Ce n'est pas encore parfait à mon goût, mais étant donné que je partais d'assez loin, c'est toujours mieux que rien.

Ce que donne monrer.fr sur mobile.
Ce que donne monrer.fr sur mobile désormais.

Les quotas d'appels d'API

Rappelons cependant que les horaires temps réel de la SNCF sont fournis par une API Open Data que le site Web interroge dès qu'un visiteur demande de voir les horaires d'une gare particulière. Or l'accès à cette API est limité à 20 appels par minute, ce qui impose de mettre en œuvre des dispositifs afin de pouvoir assurer un service de qualité pour le plus de monde possible.

Pour m'assurer de cela, j'utilise depuis un moment un outil me permettant de surveiller l'utilisation de mon quota d'appels API, dont voici un exemple.

Statistique d'appels d'API sur
monrer.fr
En orange clair, le nombre d'appels d'API que j'aurais envoyé à la SNCF si je n'avais aucune mise en cache (cf. infra). En orange foncé, le nombre d'appels d'API que j'effectue réellement. Le maximum de 140 requêtes reçues correspond grosso modo à 28 utilisateurs simultanés.

Les mesures techniques que j'ai mises en place consistent principalement en des mécanismes de mise en cache assez agressives mais qui donnent jusqu'à maintenant pleinement satisfaction. Je vais les détailler dans la section qui suit.

Mécanismes de mise en cache

La principale mesure technique, qui m'a permis jusqu'à maintenant de faire le maximum avec cette API, consiste à mettre en cache les résultats affichés sur le site. Ainsi, lorsque n personnes demandent simultanément la même gare, le site effectue une requête API SNCF pour la première personne, effectue les calculs de retard et autres traitements avant affichage, puis met en cache le résultat côté serveur. Ainsi, les n – 1 autres utilisateurs reçoivent une copie de ce qui a été mis en cache pour le premier. Étant donné que l'affichage de monrer.fr est rafraîchi toutes les 12 secondes, cela permet de servir n personnes en n'utilisant que 5 appels API par minute au lieu de 5n.

Cette première mesure technique permet donc de passer de 4 utilisateurs simultanés à un nombre illimité d'utilisateurs consultant au maximum 4 gares différentes.

La seconde mesure technique permet, pour un nombre n d'utilisateurs consultant une gare, de passer de 5 appels à un seul appel API par minute. En effet j'ai constaté que la SNCF met à jour les horaires temps réel une fois par minute. Afin de garder les données les plus fraîches possibles, je sollicite toujours l'API 5 fois par minute tant que les données renvoyées ne changent pas, puis je passe à 1 appel par minute dès la première différence. Autrement dit, le temps d'expiration du cache passe de 12 à 60 secondes.

Ce second mécanisme me permet donc de passer de 4 consultations de gares différentes simultanées à un nombre variant entre 4 et 20 sans pour autant trop perdre en délai.

Horaires temps réel du RER A et B : hélas pas pour tout de suite

Étant donné que les grands absents des horaires temps réel Open Data restent toujours ceux du RER A et B, j'ai contacté la RATP il y a un peu plus d'un mois pour savoir où en était une éventuelle mise à disposition. On m'a répondu que cela faisait partie de leurs souhaits mais qu'il ne leur était pas encore permis de le faire. J'espère bien entendu pouvoir vous faire profiter de ces horaires temps réel dès qu'ils sont disponibles et j'espère également pouvoir être au premier rang comme lorsque la SNCF était en train de mettre le système en place il y a deux ans.

Je dispose néanmoins des horaires théoriques pour ces deux lignes du RER, mais il m'est donc impossible pour le moment d'afficher les heures de passage prévus de chaque train, compte tenu de leur éventuel retard.

En conclusion : vous êtes de plus en plus nombreux…

Depuis le début du mois de septembre, vous êtes de plus en plus nombreux à utiliser ce site ; si bien que les dépassements de quota sont parfois quotidiens (cf. supra). Le principal symptôme est que le site n'affiche que les horaires théoriques de temps à autres.

J'ai essayé plusieurs fois de contacter le responsable Open Data Transilien (j'en profite pour le saluer au passage) afin de discuter d'un éventuel assouplissement de ce quota pour moi, mais je n'ai hélas reçu aucune réponse.

Je me retrouve maintenant face à une multitude d'options pour que monrer.fr puisse continuer à croître et à être utile pour le plus de gens possibles tout en limitant les abus. Ce que je voyais initialement comme un jouet semble plaire à d'autres et je vois cela comme un encouragement pour continuer.

Posté par x0r à 31 commentaires • Tags : monrer transilien sncf open data ratp