Wiseflat, un serveur conteneurisé pour vos projets personnels

Posté par  . Édité par ZeroHeure, patrick_g, palm123 et Davy Defaud. Modéré par ZeroHeure. Licence CC By‑SA.
24
16
mai
2018
Administration système

Wiseflat est un projet permettant d’héberger ses applications Web dans des conteneurs LXC sur un (ou plusieurs) Raspberry Pi.

C’est une alternative à docker CE avec du LXC (car, en tant qu’administrateur système, je trouve ça plus pratique d’avoir un accès SSH dans mes conteneurs).

Wiseflat est donc une boîte à outils permettant d’installer des micro‐services clef en main « production ready », afin de se focaliser sur ce qu’on a réellement besoin de faire.

Plus de détails dans la suite de la dépêche.

Sommaire

API

J’héberge une API proposant du contenu dédié à la domotique :

  • météo ;
  • calendrier ;
  • géolocalisation ;
  • heartbeat, un service de vérification de joignabilité fait sur mon API, si votre serveur ne répond pas vous serez notifié par courriel ;
  • cron, pour planifier des jobs HTTP dans le cloud ;
  • etc.

Ainsi que du contenu autour de la sécurité et du filtrage réseau pour protéger son réseau local et/ou ses serveurs sur Internet :

  • badips : des listes d’adresses IP considérées comme malveillantes, à bloquer sur son pare‐feu (ou au niveau de son serveur mandataire inversé — reverse proxy — nginx, Traefik ou HAproxy) — ces adresses IP sont issues des différentes listes communautaires, enrichies avec mes propres mécanismes de défense sur mes serveurs ;
  • ipblocks : des blocs d’adresses IP par pays pour restreindre l’accès uniquement à son territoire (je n’ai pas de copain en Chine) ;
  • baddomains : des listes communautaires de nom de domaines dangereux à ajouter à son serveur DNS pour les rendre non routables (filoutage, malware, publicité, pistage, etc.).

Il reste encore des coquilles, donc n’hésitez pas à me prévenir si les services gérés par l’API ne fonctionnent pas comme il faut. :-)

Côté utilisateur

L’installation et les mises à jour de votre serveur se font grâce à un projet Ansible hébergé sur GitHub. Le projet est fourni avec des playbooks1 permettant :

  • d’ajouter des micro‐services pré‐configurés pour simplifier le déploiement et la prise en main par l’utilisateur (la création manuelle de conteneurs LXC est bien entendu possible) ;
  • d’exploiter les données de l’API dans ses scénarios divers et variés de domotique ;
  • de garantir la sécurité de son réseau local en bloquant les menaces présentes sur Internet.

Voici un exemple de Raspberry Pi et de ses petits micro‐services :

pi@home-wiseflat:~ $ lxc list
+----------------+---------+------------------------+------+------------+-----------+
|      NAME      |  STATE  |          IPV4          | IPV6 |    TYPE    | SNAPSHOTS |
+----------------+---------+------------------------+------+------------+-----------+
| home-blog      | RUNNING | 192.168.1.198 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+
| home-cms       | RUNNING | 192.168.1.115 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+
| home-dnsmasq   | RUNNING | 192.168.1.110 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+
| home-domoticz  | RUNNING | 192.168.1.200 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+
| home-homebridge| RUNNING | 192.168.1.246 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+
| home-jeedom    | RUNNING | 192.168.1.138 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+
| home-messenger | RUNNING | 192.168.1.104 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+
| home-mqtt      | RUNNING | 192.168.1.247 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+
| home-nodered   | RUNNING | 192.168.1.245 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+
| home-xpl       | RUNNING | 192.168.1.243 (eth0)   |      | PERSISTENT | 0         |
+----------------+---------+------------------------+------+------------+-----------+

Le serveur dnsmasq est configuré pour récupérer via un cron les listes des domaines dangereux. Il suffit de configurer sur son service DHCP ce serveur DNS pour les résolutions de noms de domaine.

Étant un fan de Node.js, la plupart des micro‐services que j’ai choisis font tourner des instances Node.js basées sur Total.js, un super cadriciel.

Futur

Même si je propose des images LXC préconfigurées, je compte partager des playbooks Ansible pour installer des applications Web pratiques telles que :

  • Nextcloud (avec SQLite par défaut) ;
  • wallabag et autres lecteurs de flux RSS ;
  • WordPress (même si j’évite d’installer mariadb/mysql-server sur mes Raspberry Pi, on parle bien de « micro‐service ») ;
  • searx, comme alternative à Google ;
  • Gitea ou Gogs, pour gérer ses projets Git ;
  • PeerTube (même si c’est en Docker et que ça fonctionne avec PostgreSQL) ;
  • Standard Notes ;
  • OpenVPN, pour que tout un chacun puisse monter des tunnels de réseau privé virtuel (VPN) avec ses copains.

J’aimerais bien mettre du dynamisme dans ce genre d’infrastructure à la manière de Kubernetes, un serveur mandataire inverse (reverse proxy) en frontal, comme Traefik, qui irait chercher ses domaines dans un key‐value store (etcd) et générerait automatiquement les certificats SSL/TLS Let’s Encrypt. L’ajout d’une découverte du service (service discovery) basée sur du DNS serait aussi un plus, ce qui permettrait d’avoir un (ou plusieurs) petits serveurs pour prendre en charge une infrastructure de production peu chère.

Contribuer

N’importe qui peut participer au projet de différentes manières via GitHub :

  • faire évoluer le projet Ansible de construction du serveur ;
  • proposer des playbook Ansible pour construire des micro‐services.

  1. un playbook Ansible est une sorte de mégascript qui va automatiser des tâches de manière séquentielle. 

Aller plus loin

  • # API

    Posté par  (site web personnel) . Évalué à 2.

    Sympa les APIs. J'ai des trucs bizarres sur les 'count', il faut donner des arguments ? Exemple

    https://api.wiseflat.com/badip/count/bycountry

    m'affiche {"status":"success","message":"done","value":""}

    J'aime beacoup la liste d'ip et de 'bad hosts', tu peux donner tes sources ? Et c'est quoi "
    mes propres mécanismes de défense sur mes serveurs" ? fail2ban ou equivalent ?

    Pour ton container dnsmasq, tu dis qu'il recupere les badhosts, mais il en fait quoi ? Il empeche ces noms de resoudre ? Il renvoie une erreur ? une ip bidon ?

    • [^] # Re: API

      Posté par  . Évalué à 2. Dernière modification le 16 mai 2018 à 21:47.

      ah oui, c'est une coquille, un problème de cache… Je viens de corriger.
      https://api.wiseflat.com/badip/count/bycountry

      {"status":"success","message":"done","value":[{"country":"AR","number":25245,"percentage":"2.73","timestamp":1526491461},{"country":"AT","number":1007,"percentage":"0.11","timestamp":1526491461},{"country":"AU","number":3650,"percentage":"0.39","timestamp":1526491461},{"country":"BD","number":1142,"percentage":"0.12","timestamp":1526491461},{"country":"BE","number":1004,"percentage":"0.11","timestamp":1526491461},{"country":"BG","number":3550,"percentage":"0.38","timestamp":1526491461},
      ...

      Ces stats sont mises à jour régulièrement. L'intérêt pour moi est simplement de voir l'évolution des menaces de manière globale dans des dashboard de supervision.

      Les listes d'IP proviennent de:
      - badips.com
      - maltrail sur mes serveurs
      - de tous les reject iptables des pare-feux de mes serveurs
      - des logs nginx/apache

      Les listes des domaines malveillants :
      - de maltrail

      J'agrège tout ça et je construis mes statistiques et mes listes. Ces listes sont réutilisées pour protéger mes serveurs.

      La liste d'IPs va dans des règles ipset sur mes pare-feux ou alors dans nginx/haproxy, ça dépend du besoin

      La liste de domaines malveillants est chargée dans dnsmasq. Elle est lu comme un fichier /etc/hosts (0.0.0.0 badomain.com). Ce qui rend le domaine non routable. Mes ordis et serveurs interrogent ce service dns local pour les résolutions de nom de domaines, ce qui fait que toutes les pages web contenant des liens qui pointent vers de la pub/tracking (ne serait-ce que ça, sans parler de site malveillants) sont bloqués… Et tout le monde en profite sur le LAN.

      • [^] # Re: API

        Posté par  (site web personnel) . Évalué à 1.

        Euh, mais, euh !!!
        Il y a "github.com" dans https://api.wiseflat.com/baddomain/list


        0.0.0.0 githcdtkjxoi.com
        0.0.0.0 githjprgxtuyu.info
        0.0.0.0 githsatformalisticirekb.com
        0.0.0.0 github.com
        0.0.0.0 gitillaabettingk.com
        0.0.0.0 gitinge.com
        0.0.0.0 gitivinskycattederi

        • [^] # Re: API

          Posté par  . Évalué à 2. Dernière modification le 16 mai 2018 à 23:25.

          LOL ! Merci de ta vigilance !

          Voici ce que me sort le fichier maltrail :

          $ grep github.com trails.csv
          github.com/jwinterm/monerospelunker/releases/download/0.1,malware,malwarepatrol.net
          github.com/fireice-uk/xmr-stak/releases/download/2.4.3,malware,malwarepatrol.net
          github.com/jayddee/cpuminer-opt/files/1899884,malware,malwarepatrol.net
          github.com/secwiki/windows-kernel-exploits/raw/master/cve-2017-0213,malware,malwarepatrol.net
          github.com/macchky/cpuminer/releases/download/v2.6.0,malware,malwarepatrol.net
          github.com/d35m0nd142/lfisuite/raw/master,malware,malwarepatrol.net
          ....
          

          Ces projets ont été suspectés par la communauté. Je ne récupère que le domaine racine dans mon listing :-)
          Du coup, faut que je fasse une whitelist… Mais ça va être compliqué vu le nombre d'entrée dans le fichier de maltrail

          wc -l trails.csv
          1188025 trails.csv
          

          Comment faire… La liste est fournie dans l'état, il faudrait peut être faire une suppression des domaines que tu considères comme valide :

          $ sed -i '/github.com/d' baddomain.txt
          $ grep github.com baddomain.txt
          $
          

          J'avoue, la sécurité est un peu violente…

          • [^] # Re: API

            Posté par  (site web personnel) . Évalué à 5.

            Si ta liste fournit des URL complètes, tu ne peux clairement pas bloquer par domaine.

            C'est aussi simple que ça.

            • [^] # Re: API

              Posté par  . Évalué à 1.

              En même temps, si une page d'un site est piraté, il vaut mieux éviter d'aller sur le site, c'est plus prudent
              Je vais faire des whitelists, je pense. Ce sera dans une des évolutions de l'API…

              • [^] # Re: API

                Posté par  (site web personnel) . Évalué à 0.

                Tu peux faire ça pour un projet perso. Pas vraiment pour un projet que tu publies et que tu souhaites utilisable par d'autres.

                Chaque pays va avoir ces sites du genre etc. Maintenir une whitelist, ça semble un peu illusoire.

                • [^] # Re: API

                  Posté par  . Évalué à 2.

                  Voilà comme je résous le problème, avec un playbook ansible :

                  - hosts: home-dnsmasq
                    become: true
                    tasks:
                  
                      - name: Baddomain - Get all domains
                        get_url:
                          url: https://api.wiseflat.com/baddomain/list
                          dest: /etc/blacklist.dnsmasq
                          mode: 0644
                  
                      - name: remove whitelist domains from blacklist.dnsmasq
                        shell: sed -i '/{{ item }}/d' /etc/blacklist.dnsmasq
                        with_items: "{{ api_baddomains_whitelist }}"
                  
                      - name: Reload dnsmasq service
                        service:
                          name: dnsmasq
                          state: reloaded

                  Ca se traduit par un run ansible :

                  ➜  wiseflat-project git:(master) ✗ ansible-playbook play/tasks/api-baddomains.yml
                  
                  PLAY [home-dnsmasq] *********************************************************************************
                  
                  TASK [Gathering Facts] ******************************************************************************
                  ok: [home-dnsmasq]
                  
                  TASK [Baddomain - Get all domains] ******************************************************************
                  changed: [home-dnsmasq]
                  
                  TASK [remove whitelist domains from blacklist.dnsmasq] **********************************************
                  changed: [home-dnsmasq] => (item=github.com)
                  
                  TASK [Reload dnsmasq service] ***********************************************************************
                  changed: [home-dnsmasq]
                  
                  PLAY RECAP ******************************************************************************************
                  home-dnsmasq               : ok=4    changed=3    unreachable=0    failed=0
                  
                  • Je m'adapte en fonction des données renvoyées par l'API.
                  • Je forge mes playbooks d'exploitation pour m'adapter à la situation
                  • La sécurité reste optimale par défaut et je l'assouplie si j'ai besoin

                  Je réponds à une autre question concernant l'utilité d'avoir un accès SSH dans ses containers. Je ne me connecte jamais sur le porte-container pour faire du lxc-attach.

                  J'ai rajouté cette fonctionnalité dans le projet ansible. Le commit est sur GitHub

        • [^] # Re: API

          Posté par  (site web personnel) . Évalué à 1.

          Erm.. il y a aussi "free.fr", c'est beaucoup, mais alors beaucoup, trop vaste !

          • [^] # Re: API

            Posté par  (site web personnel) . Évalué à 1. Dernière modification le 19 mai 2018 à 16:25.

            Oui, globalement si son outil lui remonte des URL complètes, il ne faut pas les utiliser pour filtrer des domaines.

            Le seul moyen d'exploiter ces entrées correctement est de mettre en place un proxy filtrant qui bloque ces URL.

  • # Docker CE, LXC, ssh ??

    Posté par  . Évalué à 8.

    C'est une alternative à docker CE avec du LXC (car en tant qu'adminsys je trouve ça plus pratique d'avoir un accès SSH dans mes containers).

    Je m'interroge: quel besoin d'avoir un accès ssh dans les containers LXC que tu proposes, qui, de par leur finalité, n'interagissent avec aucun autre utilisateurs réels que root, alors que lxc-attach permet d'accéder aux containers sans rajouter de services supplémentaires à maintenir ?

    • [^] # Re: Docker CE, LXC, ssh ??

      Posté par  . Évalué à 2.

      Le bidouilleur qui a des serveurs linux a dans tous les cas besoin de s'y connecter en SSH. Il n'y pas d'autre façon de faire des choses sur son serveur. Sauf si l'on confie cette tâche à un script ou un outil d'automatisation.

      Ce qu'offre LXC, c'est simplement un cloisonnement complet de tes containers hébergés sur ton porte-container. Tu n'utilises les commandes LXC que pour en créer un nouveau, en faire un snapshot, le supprimer, etc. Mais une fois que ton container obtient une IP via le DHCP sur ton LAN, tu te connectes en SSH directement dedans pour faire ta tambouille et tu fais abstraction de la solution de containérisation qu'il y a dessous. C'est comme dans VMware, promox, openstack. Tu te connectes rarement sur le serveur hôte. Tu attaques son API ou son interface d'administration. C'est ce que tu fais avec les commandes lxc tu attaques l'API LXD.

      Docker est un outil qui aide les développeurs à mettre en production des applications, LXC ne répond pas tout à fait au même besoin et dans mon cas, je préfère cette approche à celle de docker. Je la trouve plus naturelle. Mais c'est un choix très personnel…

      J'espère avoir répondu à ta question

      • [^] # Re: Docker CE, LXC, ssh ??

        Posté par  . Évalué à 10.

        Je fais une autre utilisation de LXC
        Je ne mets jamais mes containers LXC en frontal comme tu sembles le faire: ils sont tous sur un sous-réseau dédié et seuls les services devant être accessibles sont NATés depuis le firewall du porte-container.
        Ma logique derrière cela c'est de permettre de ne pas exposer certains containers tels que les bases de données.

        En conséquence, je me connecte en ssh au porte container pour accéder ensuite aux containers via lxc-attach.
        Multiplier les serveurs ssh et donc augmenter la surface d'attaque et le nombre de service à maintenir ne me convient pas.

        • [^] # Re: Docker CE, LXC, ssh ??

          Posté par  . Évalué à 2.

          +1 Pierre Maziere

          Sécurité
          En frontal du web, on limite au maximum tout ce qui est service accessible. On n'autorise en général qu'une seule porte sur une adresse ip d'administration spécifique(ici le client ssh en écoute) et après une connexion réussie on permet de rebondir sur les autres conteneurs internes accessible uniquement via réseau local.

          Les accès web eux sont réalisés à partir d'une autre IP qui va router les requêtes http vers les bons containers grâce à un reverse proxy. Pas besoin de configurer de NAT ou autre car les conteneurs ne sont pas censés être accessibles depuis l'extérieur du réseau et ne sont pas censés pouvoir accéder à internet en dehors des réponses aux requêtes http. En utilisant un reverse proxy, tu vas grandement simplifié ta gestion des menaces car tu auras qu'un seul point d'entrée côté http à contrôler: ton reverse proxy. Parefeu devant et tu es tranquille.

          Les conteneurs ne pouvant accéder à internet, tu n'as pas à te préocuper de tout ce qui est blocage d'ip ou d'empêcher les résolutions à leurs niveaux. Certains cas de figurent nécessitent d'autoriser un accès à internet à ces conteneurs. Dans le cas où tu dois le faire, si tu veux vraiment être sécurisé, je te conseille de fonctionner par white list et non par black list.

          Je vois pas trop l'intérêt de bloquer les ips malveillantes. En théorie tes services sont suffisament bien configurés pour ne pas avoir craindre quelque chose du bot lambda. Et si ce n'est pas un bot lambda, ce n'est pas les ips présentes dans ces listes qui te protégerons. De plus, les blocages par ips sont consommateurs de performances, au niveau actuelle de mes connaissances, un fail2ban est amplement suffisant.

          Autre chose, en général, le NAT, c'est le mal. Dans un réseau que l'on maitrise pleinement et sans contrainte d'existant, il est préférable de faire du routage simple.

          Services
          Pour Nextcloud, j'avais fais des tests avec sqlite, celui-ci était bien moins performant que mysql/mariadb et cela se ressentait dans la navigation sur l'application.

          Conclusion
          L'initiative est bonne mais je ne la recommenderai pas forcément pour quelqu'un qui veut une infra solide. Soit on a les compétences techniques, et le temps et on le fait sois-même très proprement (ça prends des mois voir des années), soit on ne les as pas forcément et on part sur Yunohost ou assimilé.

          En espérant que mon commentaire t'ai apporté des informations utiles. Si tu veux en savoir plus sur l'installation de certains services et la configuration de certaines briques de sécurité, tu peux consulter mon blog. https://blog.mirabellette.eu/

          • [^] # Re: Docker CE, LXC, ssh ??

            Posté par  . Évalué à 1. Dernière modification le 17 mai 2018 à 08:09.

            Salut Mirabellette
            Je ne suis pas tout à fait d'accord sur tous les points mais encore une fois ce n'est qu'un avis très personnel. C'est un projet domotique, ne l'oublie pas…

            Concernant la configuration réseau

            Si j'ai choisi cette config, c'est parce qu'il s'agit d'un serveur qui tourne sur un lan privé, qui contient en théorie, déjà un DHCP fourni par la box de ton FAI. Tu ne DéNate pas les ports SSH de tous tes containers pour les exposer sur internet, tu ne le fais que pour un, qui contient tes mécanismes de protection (reverse proxy, bastion ssh, …) ! J'espère que tu fais confiance à ce qu'il se passe sur ton LAN :-)

            Pour avoir eu des vlan sur mon réseau privé, c'est pénible à la longue, justement à cause des DNAT à faire sur ton parfeu. C'est une configuration de base, c'est sûr qu'elle ne convient pas à tout le monde.

            En domotique il existe des bus de communication qui diffuse en Broadcast des messages provenant de passerelles applicatives. Les DNAT ca devient vite pénible pour le coup. Y a pas que du web dans le projet.

            Concernant la sécurité

            Je n'ai pas imposé de cadre, l'API propose du contenu, à toi de l'utiliser à ta façon et suivant ton contexte si cela t'intéresse…

            Merci !

            • [^] # Re: Docker CE, LXC, ssh ??

              Posté par  . Évalué à 1.

              Tu fais bien de le rappeler, j'avais un peu zappé cet aspect.

              Comme l'a dit Pierre Maziere, tu ne devrais pas avoir de service ssh qui tourne sur tes containers à partir du moment où tu utilises lxc-attach pour y accéder via le bastion. Tu ne dois accéder qu'à ton bastion qui lui est accessible en ssh, ton baston peut être accessible par un conteneur, pourquoi pas. Après, si ton conteneur plante, adieu l'accès au bastion.

              Le fait qu'un des éléments de ton infrastructure est une box fournit par ton FAI rends pénible l'administration de ton réseau et le rends potentiellement moins sûr. Tous n'ont pas cette contrainte.

              Je ne comprends pas ta remarque sur la confiance que j'accorderai au LAN. Si tu as qu'un port ssh d'ouvert sur ta machine et un port 443, tu n'as à contrôler que ces accès et le vecteur risque est quand même beaucoup plus faible que tout internet qui écoute à ta porte. Le risque est différent, ici c'est un accès physique non voulue au réseau. De mémoire, tu peux mettre en place des filtrage mac sur ta box. Pas le top du top mais toujours une première sécurité. Après le risque est normalement très faible que quelqu'un se connecte à ton LAN. Si on parle d'un WLAN, il faut ton code wifi.

              Si j'étais toi, j'isolerai le tout sur un réseau spécifique avec un routeur spécifique et une seule sortie vers la box puis vers internet. Cela t'éviterait de devoir mélanger la gestion de ton LAN maison et de ton Lan domotique et te faciliterai la gestion de ton réseau.

              Avec plaisir :)

              • [^] # Re: Docker CE, LXC, ssh ??

                Posté par  (site web personnel) . Évalué à 2.

                autre avantage de LCX c ets que l no peu faire touner les conteneur en mode non privilegié, donc avec un subuid, cela deplace l id root du contenur vers id=100000 (0 dans le conteneur) par exemple).

                docker il ne me semble pas que ca soit possible.
                c est possible avec systemd-nspawn et lxc/lsxd.

                ensuite je rebondit sur la partie réseau,
                il y a des choix sympa, comme l utilisation des vxlan, ou des netns pour isoler les sous-réseau et de lancer des dnsmasq pour les ip dedans, ce qui de plus te donne la résolution dns par subzone

                explications
                https://vincent.bernat.im/fr/blog/2017-vxlan-linux

                l utilisation d openvswitch peut aussi tres sympa dans ce cas (couple OVS/OVN) ce qui permettrais en plus de passer en multi host avec des tunnels intra plateforme de conteneur

                et pour les namespace netns (ip netns)
                https://blogs.igalia.com/dpino/2016/04/10/network-namespaces/

                Enjoy :)

  • # Différence avec ProxMox VE ?

    Posté par  . Évalué à 2. Dernière modification le 17 mai 2018 à 11:16.

    Bonjour,

    N'étant pas propriétaire d'un raspberry, je ne compte pas tester Wiseflat.
    Cependant cela me fait ardemment penser à ProxMox VE en version light.

    Y a-t-il un apport autre que les API comparé à un ProxMox + Ansible ?

  • # problème d'archi

    Posté par  . Évalué à -2.

    "car, en tant qu’administrateur système, je trouve ça plus pratique d’avoir un accès SSH dans mes conteneurs"

    Si tu as besoin de faire du ssh dans ton conteneur c'est que l'archi n'est pas bonne.

  • # KV store & Service discovery

    Posté par  . Évalué à -1.

    un key‐value store (etcd) […]. L’ajout d’une découverte du service (service discovery) basée sur du DNS serait aussi un plus

    Pour ça moi j'irai chercher du côté de Consul plutôt que etcd.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.