• chevron_right

      Ce que les Mages ont fait cette année

      Zatalyz · news.movim.eu / khaganat · Thursday, 18 June, 2020 - 11:41

    Une vision de la Krypte

    Voici la suite des aventures des valeureuses Rêveuses de Khaganat, embarquées dans l'édition 2020 de l'AG 2.0 (ça tombe bien pour un 2ème article de blog, non ?). Et cette fois-ci, les héroïnes sont nos Maj.

    Lire la suite...

    #khaganat #khanat #mmorpg #libre #jeuvideo #jeuxvideos #sysadmin #godot #ryzom #dokuwiki

    Voici un nouvel épisode de la saga des sysadmins sur Khaganat ! Car créer un univers, c'est des idées, du blabla, du code... mais aussi des serveurs derrière. Découvrez les coulisses dans notre dernier article de blog.

    Image idiote en CC0 pour que les gens cliquent, si vous ne la voyez pas, c

    #khaganat #khanat #mmorpg #libre #jeuvideo #jeuxvideos #sysadmin

    • At chevron_right

      Let's Encrypt sur HAProxy (Partie 2)

      raspbeguy · pubsub.gugod.fr / atomtest · Friday, 10 November, 2017 - 23:00 · 8 minutes

    Le fonctionnement de la Terre, avant qu'un certain Galilée y mette son grain de sel, a toujours déchaîné les passions des Hommes et a consommé beaucoup d'encre. Parmi les théories les plus folles, Terry Pratchett nous enseigne dans sa série de livres du Disque Monde que le monde repose sur le dos de...

    Le fonctionnement de la Terre, avant qu'un certain Galilée y mette son grain de sel, a toujours déchaîné les passions des Hommes et a consommé beaucoup d'encre. Parmi les théories les plus folles, Terry Pratchett nous enseigne dans sa série de livres du Disque Monde que le monde repose sur le dos de quatre gigantesques éléphants, eux-même reposant sur la carapace d'une tortue encore plus gigantesque appelée A'Tuin. Les quatre éléphants (Bérilia, Tubul, Ti-Phon l'Immense et Jérakine) se répartissent la charge que représente le poids du disque terrestre grâce à la rotation quotidienne de ce dernier. Si maintenant vous ne voyez pas le rapport entre une cosmologie impliquant des animaux au moins aussi grands que des continents capable de tenir en apnée pendant des milliards d'années et le sujet d'aujourd'hui, alors je ne sais plus quoi faire.

    Nous avons vu il y a quelques jours les principes de base d'un répartiteur de charge et exposé brièvement les concepts fondamentaux de HAProxy. Nous avons également mené une réflexion sur la manière de gérer un certificat sur une architecture avec répartiteur de charge et la voix du bon sens nous a susurré que le certificat devait être porté par HAProxy. Bon, mettons ça en pratique.

    Rangez vos affaires, sortez une feuille, interro surprise. Rappelez-moi ce qu'est le principe de base du protocole ACME. Et comme vous suivez bien et que vous buvez les paroles de l'instituteur comme un breton boit du cidre, vous saurez donc me répondre que l'agent de certification crée un challenge ACME en générant des fichiers de test auxquels le serveur ACME devra pouvoir accéder via HTTP, ces fichiers étant soit servis par l'agent via un serveur web intégré, soit mis à disposition du serveur de notre choix qui servira ces fichiers en statique. C'est en pratique presque toujours la deuxième solution qui est utilisée, sachant que justement, un serveur web tourne déjà sur les ports web standard (80 et 443). On ne veut pas d'interruption de service, non mais.

    Serveur statique

    Nous avons un petit problème ici. Les ports HTTP sont utilisés par HAProxy, qui n'est pas un serveur web, mais un répartiteur de charge. Souvenez-vous, il ne peut pas générer de lui même un flux web, pas même servir des fichiers statiques, il se contente de relayer des flux web créés par d'autres serveurs. Conclusion : il nous faut un serveur web tournant sur la machine hébergeant HAProxy capable de servir des fichiers statiques. L'idée, c'est qu'on va faire écouter ce serveur uniquement en local, et HAProxy se chargera de le propulser sur le réseau publique.

    On n'a que l'embarras du choix pour trouver un serveur web sachant servir du bon vieux statique. On pourrait choisir Nginx ou Lighttpd par exemple, mais comme nous sommes sur OpenBSD, le choix se portera sur le serveur web déjà préinstallé, communément appelé openhttpd.

    Première étape, il faut dire à OpenBSD d'activer le service.

    echo 'httpd_flags=""' >> /etc/rc.conf.local

    Ainsi on pourra démarrer le service, et il sera démarré à chaque démarrage de l'OS.

    Ensuite, il va nous falloir créer un dossier qui va accueillir les fichiers du challenge ACME. Comme le processus httpd est chrooté dans /var/www (sur OpenBSD, on appelle ça un jail), ce dossier sera donc /var/www/htdocs/webroot.

    La configuration de notre httpd sera on ne peut plus simple :

    server "default" { 
        listen on 127.0.0.1 port 1375 #ça fait "let's" en l33t
        root "/htdocs/webroot"
    }

    Démarrons le service :

    /etc/rc.d/httpd start

    Notre serveur statique est prêt.

    Configuration HAProxy

    Il faut dire à HAProxy de rediriger les requêtes ACME vers notre serveur statique fraîchement configuré.

    Pour ça, on va définir un backend dédié à Let's Encrypt, vers lequel seront redirigés tous les flux ACME reçus sur les frontends qui nous intéressent.

    backend letsencrypt-backend
            server letsencrypt 127.0.0.1:1375

    Propre. Syntaxe explicite, pas besoin d'expliquer je pense. Je fais juste remarquer qu'en plus de nommer le backend globalement, je donne un nom au serveur du backend même si ici il n'a aucune forme d'importance, il ne sera jamais appelé ailleurs dans le fichier, c'est néanmoins obligatoire sur HAProxy. Enfin, un nom clair est toujours profitable, car il est éventuellement utilisé dans ses logs, ses statistiques et il rend la lecture du fichier de conf plus facile.

    Le backend est prêt, c'est excellent, mais encore faut-il l'utiliser. Pour être exact, on ne va l'utiliser que si l'URL demandée correspond au chemin classique demandé par le validateur ACME, à savoir /.well-known/acme-challenge/. Reprenons l'exemple de la dernière fois, modifions-le de la sorte :

    frontend mon_super_site
        bind *:80
        mode http
    
        acl url-back-office path_dir /admin
        acl letsencrypt-acl path_beg /.well-known/acme-challenge/
    
        use_backend back-office if url-back-office
        use_backend letsencrypt-backend if letsencrypt-acl
        default_backend mes-frontaux
    
    backend back-office
        server backoffice 192.168.0.14:80
    
    backend mes-frontaux
        balance roundrobin
        server backoffice1 192.168.0.11:80
        server backoffice2 192.168.0.12:80
        server backoffice3 192.168.0.13:80
    
    backend letsencrypt-backend
        server letsencrypt 127.0.0.1:1375

    On a ajouté une ACL et une directive use_backend. Rappelez-vous, une ACL est tout simplement une condition, ici elle porte sur le chemin de l'URL. Rien de nouveau, on a déjà expliqué le concept.

    On recharge le schmilblick :

    /etc/rc.d/haproxy reload

    On est prêt à générer notre premier certificat. Mais on ne va pas le faire tout de suite. Comme vous vous en souvenez, HAProxy veut ses certificats sous une forme un peu spécifique, il nous faut donc traiter le certificat dès qu'il a été généré, et pour ça on va faire un peu de scripting. On pourrait déjà générer le certificat sans le script de post-traitement, mais si on faisait ça, on devrait ensuite éditer la configuration d'acme.sh et c'est un peu barbant, sachant que la commande qui génère le premier certificat génère également par magie la configuration associée pour les renouvellements. Donc ce serait stupide.

    Script de post traitement

    Rien de bien compliqué, je vous rassure. Le principe est simple : HAProxy n’accepte des certificats que sous la forme d'un fichier contenant la chaîne complète de certification et la clef privée, dans cet ordre.

    Le script est très simple. Vous pouvez bien entendu le mettre où bon bous semble, pour ma part j'ai décidé de le mettre dans /etc/haproxy/generate-ssl.sh.

    #!/bin/sh
    
    SITE=$1
    LE_CERT_LOCATION=/root/.acme.sh/$SITE
    HA_CERT_LOCATION=/etc/haproxy/ssl
    
    cat $LE_CERT_LOCATION/fullchain.cer $LE_CERT_LOCATION/$SITE.key > $HA_CERT_LOCATION/$SITE.haproxy.pem
    
    /etc/rc.d/haproxy reload

    LE_CERT_LOCATION représente l'endroit où seront générés les certificats par acme.sh (il s'agit ici de l'emplacement par défaut, mais vous pouvez changer ce chemin à condition d'utiliser l'option adéquate lors de la génération du premier certificat).

    HA_CERT_LOCATION est l'emplacement où seront créés les certificats au format HAProxy. D'ailleurs, n'oubliez pas de créer le dossier en question.

    Le script devra être appelé avec en paramètre le domaine complet principal du certificat. N'oubliez pas de le rendre exécutable.

    Génération du premier certificat

    On y est, maintenant on va enfin pouvoir générer ce satané certificat. Partons du principe que vous avez correctement installé acme.sh, le README du projet est très simple à suivre.

    acme.sh --issue -d mon-super-site.com -w /var/www/htdocs/webroot/ --renew-hook "/etc/haproxy/generate-ssl.sh mon-super-site.com" --debug

    Remarquez que vous pouvez générer un certificat couvrant plusieurs domaines à la fois, il suffit d'ajouter -d mon-domaine-secondaire.com entre le domaine principal et l'option -w. Remarquez l'option --renew-hook, elle permet d'appeler le script qu'on vient de définir à chaque fois qu'un renouvellement est effectué.

    Une fois la commande effectuée avec succès (ça peut prendre une minute ou deux), votre certificat est généré, il vous faut encore ajouter le certificat dans la configuration du frontend comme il suit :

    bind *:443 ssl cert /etc/haproxy/ssl/mon-super-site.com.haproxy.pem

    Comme il s'agit de la première génération et non d'un renouvellement, il est nécessaire d'appliquer le script à la main.

    /etc/haproxy/generate-ssl.sh mon-super-site.com

    Vérifiez, et pleurez de joie. Votre certificat est déployé et fonctionnel. C'est magnifique.

    Automatisation du renouvellement

    Ultime étape, celle qui fait prendre tout son sens à la révolution Let's Encrypt, celle qui fait qu'on peut oublier sans scrupule que tel ou tel site a un certificat proche de l'expiration, il s'agit du renouvellement automatique. Pas de subtilités, une simple ligne dans la crontab fait l'affaire. Et en plus, si je ne dis pas de bêtises, acme.sh s'occupe tout seul d'ajouter cette ligne.

    26 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

    La commande sera lancée tous les jours à minuit vingt-six, libre à vous de changer cet horaire. acme.sh sera assez intelligent pour savoir si votre certificat a besoin d'un coup de jeune ou non, donc rassurez vous, il n'y aura pas un renouvellement par jour.

    Conclusion

    Le protocole ACME peut s'appliquer à toutes les architectures web pour peu qu'on puisse traiter les requêtes du challenge correctement. À moins de disposer d'un stockage partagé (NSF, iSCSI, Samba...), il est indispensable que le challenge ACME soit créé par la machine capable de le traiter.

    Illustration : The Great A'Tuin par Paul Kidby

    • At chevron_right

      Let's Encrypt sur HAProxy (Partie 1)

      raspbeguy · pubsub.gugod.fr / atomtest · Sunday, 5 November, 2017 - 23:00 · 6 minutes

    Vous vous en souvenez peut-être, nous avions effectué un tutoriel Let's Encrypt quelques jours après sa mise en bêta publique. D'ailleurs, il mériterait un petit relooking, vu que quelques détails ont un peu changé, et que d'autres clients ACME ont vu le jour. Par exemple on a honteusement passé sou...

    Vous vous en souvenez peut-être, nous avions effectué un tutoriel Let's Encrypt quelques jours après sa mise en bêta publique. D'ailleurs, il mériterait un petit relooking, vu que quelques détails ont un peu changé, et que d'autres clients ACME ont vu le jour. Par exemple on a honteusement passé sous silence l'excellent acme.sh qui a le mérite de ne pas demander une ribambelle de dépendance en temps que simple script Bash. De plus, le client principal (dont le nom est désormais Certbot) a désormais implémenté des extensions Apache et Nginx qui fonctionnent (presque) comme on le souhaite, à savoir modifier tout seul les configurations des sites pour fonctionner avec Let's Encrypt. Cependant je reste plus enclin à utiliser la méthode manuelle.

    À l'époque, je vous parlais d'une infrastructure simple, à savoir un unique serveur frontal : c'est lui qui interceptait les requêtes et qui les traitait, point barre. L'infra d'un site avec une audience restreinte, car tout doit être traité par une unique machine. Bonjour l'indispo surprise.

    Parlons à présent d'une architecture un peu plus ambitieuse, le genre de topologie qu'on peut trouver en production pour des sociétés importantes (et les technophiles enthousiastes). Cette première partie sera dédiée à l'explication de cette mystérieuse architecture et à la présentation d'une manière de la mettre en œuvre. Dans une seconde partie, on apprendra à y déployer ses certificats Let's Encrypt.

    Souvent donc, on ne se contente pas d'un unique frontal, mais de plusieurs frontaux, sous la coupe d'un répartiteur de charge, (load-balancer en anglais) qui se chargera de réceptionner les requêtes des utilisateurs et de les distribuer aux frontaux, selon une stratégie définie. Cette architecture a quatre avantages :

    • On gagne en charge maximale supportée, donc en nombre de visiteurs.
    • Multiplier les frontaux amoindrit fortement les risques de crash du site, car en cas de panne d'un frontal, les autres frontaux se partagent le trafic.
    • La mise en production d'une nouvelle version d'un site web peut se faire sans aucune interruption de service : il suffit de déployer sur un frontal à la fois.
    • Les frontaux sont sur un réseau privés et non directement accessible sur le réseau global, donc la sécurité du site est renforcée.

    load-balancer

    On constate que le répartiteur de charge est un potentiel goulot d'étranglement et il nous faut donc un programme optimisé pour la haute disponibilité afin que le flux des requêtes ne soit pas le facteur limitant.

    Disons maintenant que l'on souhaite apposer un certificat sur cette architecture. Question à dix sesterces : qui parmi ces serveurs doit porter ce certificat ?

    Si on choisit de faire porter le certificat par les frontaux, cela signifie qu'il faut que tous les frontaux doivent le porter, et qu'il faudra déployer le certificat sur toutes ces machine à chaque renouvellement. Mais surtout, cela signifie que, le trafic étant chiffré jusqu'aux frontaux, le répartiteur de charge ne pourra pas prendre en compte le contenu de la requête dans sa stratégie de répartition, ce qui est fort pénalisant. En effet, il est coutume de configurer le répartiteur de charge pour distribuer certaines URL sur un pool de frontaux différent du pool normal, par exemple le back-office (la page d'administration et de saisie de contenu du site). Enfin dernier point, si vous vous souvenez du fonctionnement du protocole ACME comme décrit dans notre tutoriel, vous saurez que le certificat doit être généré sur la machine qui en fait la demande et qui répondra au challenge ACME. Ceci implique qu'un des frontaux doit être désigné pour la génération des certificat, et donc que le répartiteur de charge doit rediriger toutes les requêtes de type ACME vers ce frontal, ce qui est à la fois moche et justement impossible car notre répartiteur de charge ne peut pas comprendre ce qu'il redirige à cause du chiffrement.

    La solution la plus sensée, qui maintient également le plus l'isométrie des frontaux, est de faire porter le certificat par le répartiteur de charge.

    Zoomons alors sur cette fameuse machine, le répartiteur de charge. On va partir d'un socle OpenBSD. Pourquoi pas un Linux ? Parce qu'on utilise souvent la même machine pour la répartition de charge et pour le pare-feu, et qu'OpenBSD est le système de prédilection pour faire un routeur libre. Et en plus j'aime bien cet OS, ça change un peu les idées.

    Sur ce socle, on va utiliser le répartiteur de charge HAProxy. Les seules tâches de HAProxy sont de porter le certificat du ou des sites (on parle de SSL-offloading) et d'aiguiller le trafic web sur les frontaux. Il ne peut pas générer de flux web par lui-même, il peut seulement relayer une requête à un autre service. Et d'ailleurs il est très bon pour ça.

    HAProxy est organisé en frontends et en backends : un frontend est la façade présentée au monde extérieur qui va recevoir les requêtes des internautes. Un backend est un pool de serveurs frontaux qui va traiter la requête. HAProxy doit donc choisir sur quel backend envoyer une requête, mais il doit également gérer le pool de frontaux que représente ce backend.

    Prenons un exemple de configuration simple. On passera les directives globales HAProxy qui ne sont pas intéressantes et présentent peu de valeur ajoutée. Et bien entendu, on part du principe que vos frontaux sont configurés, écoutent sur des adresses locales et tout le toutim.

    frontend mon_super_site
        bind *:80
        mode http
    
        acl url-back-office path_dir /admin
    
        use_backend back-office if url-back-office
        default_backend mes-frontaux
    
    backend back-office
        server backoffice 192.168.0.14:80
    
    backend mes-frontaux
        balance roundrobin
        server backoffice 192.168.0.11:80
        server backoffice 192.168.0.12:80
        server backoffice 192.168.0.13:80

    Dans cette configuration, le frontend écoute sur toutes les adresses IP attribuées au serveur, sur le port 80 (donc pour le moment, uniquement du trafic en clair). Le mode HTTP signifie qu'on utilise ce frontend pour répartir du flux web, et non pas comme le mode TCP ou l'on redirige un flux TCP intouché.

    On a écrit une ACL, autrement dit une condition. Retenez cette notion car les ACL sont au cœur du principe de HAProxy. Ici notre ACL est vraie si le chemin de l'URL commence par /admin et fausse sinon. On utilisera donc le backendback-office si l'ACL est vraie et sinon, on utilisera le backend par défaut mes-frontaux.

    Le backendback-office est très simple car il ne comporte qu'un serveur. Le backendmes-frontaux comporte trois serveurs répartis en round-robin.

    Et voilà, vous avez un répartiteur de charge. Si vous avez un certificat SSL, vous pouvez ajouter une ligne au frontend :

    bind *:443 ssl cert /chemin/vers/mon/certificat.pem

    Sauf que ça ne marchera pas. En tout cas pas tant que vous aurez mis votre certificat sous la forme attendue par HAProxy, à savoir la clef privée et le certificat dans le même fichier. Nous verrons cela dans la seconde partie, qui vous expliquera également (et finalement) comment diable utiliser Let's Encrypt avec ce bidule. En tout cas, si vous êtes perspicace, vous vous doutez que ça tournera en partie autour des ACL, car il y a bien une raison pour laquelle c'est le seul élément en gras de l'article.

    (Source de l'image d'en-tête : Great A'tuin par Schiraki)