Auteur/autrice : hl0dwig

  • springbok.social

    springbok.social

    Sur mon temps libre j’essaie d’apprendre le Rust. Totalement en dilettante, je suis les tutoriels officiels du livre en ligne qui a d’ailleurs été traduit en Français, ce qui ne gâche rien !

    Et pour me motiver à apprendre ce nouveau langage pour moi, je me suis aussi trouvé un petit projet qui a pour objectif de créer ce que j’appelle un « Moteur du Fediverse bas niveau »… ou rien d’autre qu’une application qui implémentera le protocole ActivityPub, mais sans devenir une énième brique à empiler sur d’autres logiciels !

    L’idée, très expérimentale & sans prétention, c’est de comprendre les rouages à bas niveau d’une application capable de converser sur le Fediverse. Je trouverais ça ultra cool de maîtriser très concrètement les requêtes réseau et leur interprétation par l’application elle-même, sans déléguer ses tâches à d’autres applications interconnectées entre elles.

    Est-ce que ça donnera quelque chose d’exécutable un jour ? J’espère. Est-ce que ça sera utilisable et utilisé par quelqu’un d’autre que moi ? ça j’en doute fort, en tout cas ce n’est pas l’objectif. Ici j’ai juste envie d’apprendre, d’essayer, de comprendre et si en plus à la fin ça marche, alors tant mieux :p

    Et puisqu’un projet de geek informatique n’existe pas s’il n’a pas son nom de domaine, il me fallait bien trouver un nom à mon projet ! Et j’ai choisi « springbok.social » en hommage à la race d’antilope sauteuse africaine que je trouve vraiment trop belle <3 En plus elle est très rapide, j’image que mon appli le sera aussi :p Dans le monde du Fediverse j’ai l’impression qu’il y a une tradition d’associer un animal totem aux projets, alors j’y prends part avec plaisir et je remercie @hikarion aka @marun pour son boulot autour du logo dont je suis fier <3


  • Liseuse Vivlio piégée

    C’était bien…

    L’année dernière je m’étais offert une liseuse, de la marque française vivlio.fr. Cocorico j’étais content, en plus elle était sous Linux, et je voulais vraiment encourager toutes les initiatives aux couleurs de notre drapeau.

    J’ai lu pas moins de 10 livres l’année dernière, c’est très peu pour les lecteurs assidus, pour moi j’étais pas loin de ma promesse personnelle d’en lire au moins 1 par mois <3

    C’était pratique, elle avait des boutons physiques, pour moi c’était un vrai critère important pour tourner les pages. On pouvait éteindre complètement le rétro-éclairage, c’était important pour moi aussi. Et puis tout était synchronisé entre la librairie Vivlio, le lecteur en ligne, la liseuse… bref une très belle expérience.

    Mais je n’avais pas vu le poteau rose !

    …jusqu’à l’accident !

    Fin d’année dernière je casse mon écran, et dois donc faire un choix pour me rééquiper. Et j’en profite pour m’offrir la version Color sur le marchand Cultura. Je lance la liseuse et entre mes identifiants pour retrouver ma bibliothèque, et là c’est le drame : « Ce couple email et mot de passe est inconnu ».

    Au départ je ne comprends pas, je prends soin de tout vérifier, mon email, mon mot de passe, je teste ma connexion depuis mon ordinateur, tout fonctionne nickel mais la tablette refuse de se connecter. Je soupçonne un défaut sur celle que j’ai reçue jusqu’à ce que mes yeux tiltent sur un détail des instructions pour se connecter : « Connectez vous avec votre compte Cultura ».

    PANIQUE A BORD ! Je me suis fais avoir comme un bleu ! Les liseuses vendues chez Cultura ne peuvent pas se connecter à d’autres librairies ni à d’autres bibliothèques d’eBooks que celles de Cultura… le stress m’envahit et je me retiens de tout balancer.

    Je décide d’être raisonnable, j’ouvre un ticket au support de Vivlio pour leur demander s’il existe une manipulation pour pouvoir déverrouiller la liseuse…

    Et je décide de télécharger tous mes eBooks de mon ancienne bibliothèque de Vivlio pour tout importer dans la bibliothèque de Cultura. Et là nouvelle surprise : mes eBooks n’étaient pas au format EPUB, je suis en train de télécharger des fichiers .acsm qui sont associés à des identifiants ADOBE j’sais pas quoi… je ne vais pas plus loin, je reset la tablette et demande un retour et remboursement à Cultura.

    J’attends toujours une réponse et mettrai à jour mon article pour vous tenir au courant. on m’a répondu le 19/01 :

    […] En achetant votre liseuse chez Cultura, la librairie intégrée dans votre liseuse sera automatiquement celle de Cultura.

    Vous ne pourrez malheureusement pas retrouver vos livres achetés chez Vivlio directement dans votre liseuse.

    Rassurez-vous, vous pouvez parfaitement transférer vos livres achetés auprès d’autres librairies en procédant à un transfert manuel via câble USB. 
    Vous trouverez toutes les informations en suivant cette procédure !
     
    Si vos livres sont protégés par la DRM Adobe, il vous faudra passer par le logiciel Adobe Digital Édition pour les transférer sur votre liseuse.
    Pour découvrir la manipulation à effectuer, je vous invite à lire l’article suivant.[…]

    Laurine (Vivlio)

    Colère noire

    C’EST INACCEPTABLE et je me sens tellement bête ! J’ai été berné par du marketing greenwashé et bleuwashé, ça m’insupporte qu’en 2023 les entreprises se sentent obligées de verrouiller leurs clients pour les garder. Mais putain, faites du bon boulot, du bon matos, on sera fidèle ! Pas besoin de nous emmerder avec des DRM à la con, des formats propriétaires, et des parcours clients de mes couilles.

    (j’ai prévenu je suis énervé)

    De toute façon j’avais pris la décision de ne plus acheter de liseuse et de revenir au format papier. De privilégier autant que possible les livres de secondes mains, et d’en profiter pour faire circuler mes bouquins. Et pour les quelques livres numériques, essais, distributions d’indépendants & co… je les lirai s’ils sont au format EPUB sur mon smartphone ou mon ordinateur, voilà tout.

    N’achetez pas du Vivlio, ou alors achetez mais gueulez auprès du support pour qu’un jour peut-être on arrête de nous vendre du matériel bridé, car non seulement c’est chiant, mais c’est anti-écologique, je suis tellement dégoûté.


  • Sauvegarde PostgreSQL

    Évidemment qu’on fait des sauvegardes ! Le Raid1 c’est cool, mais ce n’est pour autant pas une sauvegarde, c’est un bon moyen d’assurer une redondance matérielle, si un disque foire, l’autre est là. Mais on fait comment pour récupérer un état stable des données de la veille si un incident intervient par exemple ? Bah on restaure une sauvegarde bien sûr. Encore mieux si celle-ci est régulière et stockée sur un autre disque ! C’est ce qu’on fait chez g33ks.coffee.

    Pré-requis

    Pour comprendre cet article tu dois déjà :

    • Savoir ce qu’est un script sous Linux
    • Avoir une base de données PostgreSQL
    • Comprendre le fonctionnement de Crontab

    Script

    Il en existe des outils pour faire de la sauvegarde automatique, distribuée, dans le cloud & co… mais ici on est #smallWeb, fait maison, à la mano et avec des solutions simples et à taille humaine. Ainsi en plus des 2 disques de 1 To montés en Raid1, on a un disque dédié de 4 To uniquement pour les sauvegardes. Et bien sûr on automatise la tâche et pour se faire rien de mieux que son propre petit script bash comme celui que j’ai écrit :

    #Script de sauvegarde de la base PostgreSQL
    #
    #L'idée étant de garder un historique de 6 jours.
    #Le script est lancé quotidiennement à 3h du matin via une tâche cron.
    
    #toBeDeleted prend la valeur de la date il y a 6 jours dans le format ddmmyy
    #today prend la valeur de la date du jour dans le format ddmmyy
    toBeDeleted=$(date -d "$date -6 days" +"%d%m%y")
    today=$(date '+%d%m%y')
    
    #suppression de la sauvegarde d'il y a  6 jours
    rm -rf /backup/daily_db_backup/$toBeDeleted
    
    #création du répertoire pour la sauvegarde du jour
    mkdir /backup/daily_db_backup/$today
    
    #lancement de la sauvegarde du jour
    pg_basebackup -D /backup/daily_db_backup/$today -Ft -z

    J’utilise pg_basebackup sur les bons conseils de @kedare puisque cette commande permet de faire une sauvegarde « physique » de la base. Non seulement son contenu, mais aussi toute la structure et sa configuration. En cas de besoin on pourra donc reconstruire entièrement la base de données.

    Cron

    Une fois le script créé, placé dans le dossier $HOME de mon user « postgres », et autorisé à être exécuté (chmod +x obpdb.sh) , je vais ajouté un ligne dans crontab de façon à ce que le script soit lancé automatiquement tous les matins à 3h :

    crontab -e

    Les 2 dernières lignes ressemblent alors à :

    # m h  dom mon dow   command
    0 3 * * * ~/obpdb.sh

    Vérification

    Bien sûr on vérifie au préalable que le script fonctionne bien et de temps en temps je liste le contenu de mon dossier de sauvegarde pour voir s’il a la tête voulue comme ici, on voit que tout fonctionne bien :

    postgres@g33ks:~$ ls -l /backup/daily_db_backup/
    total 24
    drwxrwxr-x 2 postgres postgres 4096 Jul 25 03:02 250723
    drwxrwxr-x 2 postgres postgres 4096 Jul 26 03:02 260723
    drwxrwxr-x 2 postgres postgres 4096 Jul 27 03:02 270723
    drwxrwxr-x 2 postgres postgres 4096 Jul 28 03:02 280723
    drwxrwxr-x 2 postgres postgres 4096 Jul 29 03:03 290723
    drwxrwxr-x 2 postgres postgres 4096 Jul 30 03:02 300723
    postgres@g33ks:~$ 

    Et pourvu qu’on en ait jamais besoin surtout :p


  • kombucha NGINX pour Mastodon & Nextcloud en reverse-proxy

    Je vous passe ma levure utilisée pour générer la configuration de mes différents domaines qui sont gérées par ma passerelle NGINX. C’est un peu comme ça que j’imagine ces fameux fichiers de config. On en trouve sur internet gérés depuis des lustres par d’autres, qu’on s’approprie, qu’on infuse à notre tour sur nos serveurs, et qu’on passe au voisin :p

    Pré-requis

    • Savoir installer un serveur Ubuntu
    • Savoir configurer son réseau local et le NAT de son routeur
    • Savoir configurer NGINX un minimum

    Ma config

    À la maison, ma Livebox laisse passer les connexions entrantes des ports 80, 443, 22 et 2222 uniquement. Les 2 premiers pour la partie web, les 2 suivants pour les connexions SSH de mes 2 serveurs.

    Un premier serveur, que j’ai nommé « maman serveur » reçoit toutes les connexions entrantes sur les ports 80 et 443. NGINX va se charger de distribuer les appels au bon endroit :

    • Mastodon, herbergé localement sur le serveur mère
    • Nextcloud, herbergé sur un autre serveur fille

    J’ai donc 2 fichiers de configuration, chacun va gérer un domaine dédié g33ks.coffee pour le premier et nextcloud.loicrobert.fr pour le second.

    Mastodon

    Ici mon fichier de configuration que j’ai trouvé en ligne et adapté à mes besoins. Modifie <domaine-vers-mastodon> avec ton domaine.

    Attention dans ma configuration j’ai modifié l’adresse du dossier root pour quelle pointe vers l’emplacement personnalisé de mon dossier system de Mastodon pour les médias des membres notamment !

    map $http_upgrade $connection_upgrade {
      default upgrade;
      ''      close;
    }
    
    upstream backend {
        server 127.0.0.1:3000 fail_timeout=0;
    }
    
    upstream streaming {
        server 127.0.0.1:4000 fail_timeout=0;
    }
    
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g;
    
    server {
        if ($host = g33ks.coffee) {
            return 301 https://$host$request_uri;
        } # managed by Certbot
    
    
      listen 80;
      listen [::]:80;
      server_name <domaine-vers-mastodon>;
      root /home/mastodon/live/public;
      location /.well-known/acme-challenge/ { allow all; }
      location / { return 301 https://$host$request_uri; }
    
    
    }
    
    server {
      listen 443 ssl http2;
      listen [::]:443 ssl http2;
      server_name <domaine-vers-mastodon>;
    
      ssl_protocols TLSv1.2 TLSv1.3;
      ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
      ssl_prefer_server_ciphers on;
      ssl_session_cache shared:SSL:10m;
      ssl_session_tickets off;
    
      # Uncomment these lines once you acquire a certificate:
        ssl_certificate /etc/letsencrypt/live/<domaine-vers-mastodon>-0001/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/<domaine-vers-mastodon>-0001/privkey.pem; # managed by Certbot
    
      keepalive_timeout    70;
      sendfile             on;
      client_max_body_size 80m;
    
      root /home/mastodon/live/public;
    
      gzip on;
      gzip_disable "msie6";
      gzip_vary on;
      gzip_proxied any;
      gzip_comp_level 6;
      gzip_buffers 16 8k;
      gzip_http_version 1.1;
      gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;
    
      location / {
        try_files $uri @proxy;
      }
    
      # If Docker is used for deployment and Rails serves static files,
      # then needed must replace line `try_files $uri =404;` with `try_files $uri @proxy;`.
      location = /sw.js {
        add_header Cache-Control "public, max-age=604800, must-revalidate";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
        try_files $uri =404;
      }
    
      location ~ ^/assets/ {
        add_header Cache-Control "public, max-age=2419200, must-revalidate";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
        try_files $uri =404;
      }
    
      location ~ ^/avatars/ {
        add_header Cache-Control "public, max-age=2419200, must-revalidate";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
        try_files $uri =404;
      }
    
      location ~ ^/emoji/ {
        add_header Cache-Control "public, max-age=2419200, must-revalidate";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
        try_files $uri =404;
      }
    
      location ~ ^/headers/ {
        add_header Cache-Control "public, max-age=2419200, must-revalidate";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
        try_files $uri =404;
      }
    
      location ~ ^/packs/ {
        add_header Cache-Control "public, max-age=2419200, must-revalidate";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
        try_files $uri =404;
      }
    
      location ~ ^/shortcuts/ {
        add_header Cache-Control "public, max-age=2419200, must-revalidate";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
        try_files $uri =404;
      }
    
      location ~ ^/sounds/ {
        add_header Cache-Control "public, max-age=2419200, must-revalidate";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
        try_files $uri =404;
      }
    
      location ~ ^/system/ {
        root /data/mastodon;
        add_header Cache-Control "public, max-age=2419200, immutable";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
        try_files $uri =404;
      }
    
      location ^~ /api/v1/streaming {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Proxy "";
    
        proxy_pass http://streaming;
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
    
        tcp_nodelay on;
      }
    
      location @proxy {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Proxy "";
        proxy_pass_header Server;
    
        proxy_pass http://backend;
        proxy_buffering on;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    
        proxy_cache CACHE;
        proxy_cache_valid 200 7d;
        proxy_cache_valid 410 24h;
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
        add_header X-Cached $upstream_cache_status;
    
        tcp_nodelay on;
      }
    
      error_page 404 500 501 502 503 504 /500.html;
      add_header Content-Security-Policy "default-src 'none'; form-action 'none'";
    
    }

    Nextcloud

    Ci-dessous mon fichier de configuration que j’ai trouvé en ligne et adapté à ma sauce. Notamment tu devras modifier <domaine-vers-nextcloud> avec ton propre domaine, ainsi qu’adapter le proxy pass vers <adresse-ip-locale-serveur> avec l’adresse IP de ton serveur connecté à ton réseau local.

    Attention cette config fonctionne si tu as au préalable installé ton Nextcloud via l’image Docker officielle configurée de façon à être derrière un proxy.

     server {
    
     listen       443 ssl;
     server_name  <domaine-vers-nextcloud>;
        ssl_certificate /etc/letsencrypt/live/<domaine>-0001/fullchain.pem; # managed by Certbot
       # managed by certbot on host machine
        ssl_certificate_key /etc/letsencrypt/live/<domaine>-0001/privkey.pem; # managed by Certbot
     # managed by certbot on host machine
    
     
     # static files
     location ^~ /browser {
       resolver localhost;
       proxy_pass http://<ip-locale-du-serveur>:11000$request_uri;
       proxy_set_header Host $http_host;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Port $server_port;
       proxy_set_header X-Forwarded-Scheme $scheme;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header Accept-Encoding "";
    
       client_body_buffer_size 512k;
       client_max_body_size 0;
     
       # Websocket
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection $connection_upgrade;
     
       proxy_read_timeout 36000s; 
    }
    
     # WOPI discovery URL
     location ^~ /hosting/discovery {
       resolver localhost;
       proxy_pass http://<ip-locale-du-serveur>:11000$request_uri;
       proxy_set_header Host $http_host;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Port $server_port;
       proxy_set_header X-Forwarded-Scheme $scheme;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header Accept-Encoding "";
    
       client_body_buffer_size 512k;
       client_max_body_size 0;
     
       # Websocket
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection $connection_upgrade;
     
       proxy_read_timeout 36000s; 
     }
    
     # Capabilities
     location ^~ /hosting/capabilities {
       resolver localhost;
       proxy_pass http://<ip-locale-du-serveur>:11000$request_uri;
       proxy_set_header Host $http_host;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Port $server_port;
       proxy_set_header X-Forwarded-Scheme $scheme;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header Accept-Encoding "";
    
       client_body_buffer_size 512k;
       client_max_body_size 0;
     
       # Websocket
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection $connection_upgrade;
     
       proxy_read_timeout 36000s; 
     }
    
     # main websocket
     location ~ ^/cool/(.*)/ws$ {
       resolver localhost;
       proxy_pass http://<ip-locale-du-serveur>:11000$request_uri;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Port $server_port;
       proxy_set_header X-Forwarded-Scheme $scheme;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header Accept-Encoding "";
    
       client_body_buffer_size 512k;
       client_max_body_size 0;
     
       # Websocket
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection $connection_upgrade;
     
       proxy_read_timeout 36000s;
     }
    
     # download, presentation and image upload
     location ~ ^/(c|l)ool {
       resolver localhost;
       proxy_pass http://<ip-locale-du-serveur>:11000$request_uri;
       proxy_set_header Host $http_host;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Port $server_port;
       proxy_set_header X-Forwarded-Scheme $scheme;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header Accept-Encoding "";
    
       client_body_buffer_size 512k;
       client_max_body_size 0;
     
       # Websocket
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection $connection_upgrade;
     
       proxy_read_timeout 36000s;
     }
    
     # Admin Console websocket
     location ^~ /cool/adminws {
       resolver localhost;
       proxy_pass http://<ip-locale-du-serveur>:11000$request_uri;
       proxy_set_header Host $host;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Port $server_port;
       proxy_set_header X-Forwarded-Scheme $scheme;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header Accept-Encoding "";
    
       client_body_buffer_size 512k;
       client_max_body_size 0;
    
       # Websocket
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection $connection_upgrade;
     
       proxy_read_timeout 36000s;
     }
    
    location / {
            resolver localhost; # Note: you need to set a valid dns resolver here or use 127.0.0.1 />
            proxy_pass http://<ip-locale-du-serveur>:11000$request_uri; # Note: you need to change localhost t>
    
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Port $server_port;
            proxy_set_header X-Forwarded-Scheme $scheme;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Accept-Encoding "";
            proxy_set_header Host $host;
    
            client_body_buffer_size 512k;
            proxy_read_timeout 86400s;
            client_max_body_size 0;
    
            # Websocket
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    
    
    
    }

    Enjoy 😉


  • connexion SSH & petit piège Ubuntu

    Une fois mon nouveau serveur perso installé, sous Ubuntu 22.04.2 LTS, j’ai évidemment cherché à restreindre l’accès SSH en interdisant la connexion via mot de passe. Simple comme bonjour pour des administrateurs éclairés, et pourtant c’était sans compter sur un petit piège nouveauté !

    Pré-requis

    • Savoir installer un serveur Ubuntu
    • Avoir installé & activé OpenSSH
    • Comprendre les commandes de bases UNIX
    • Savoir éditer les fichiers de configuration dans la console, avec nano par exemple

    De quoi je parle ?

    Dès lors que t’as installé ton nouveau serveur, tu as très vite envie de le ranger dans un coin, sans clavier, sans souris, sans écran et tu veux l’administrer depuis un autre ordinateur via la console. Grâce au serveur OpenSSH installé et démarré, tu pourras t’y connecté depuis un client SSH via la console de ton UNIX préféré (si tu utilises Windows tu peux déjà arrêter de lire mon blog hein ^_^). Classiquement tu y accéderas via la commande classique dont voici un exemple :

    ssh hl0dwig@192.168.1.20

    De base, ton serveur SSH demandera alors le mot de passe du compte, ici celui de « hl0dwig » pour t’y connecter et c’est terminé. Sauf que, si tu veux pouvoir administrer ton serveur en dehors de ton réseau local, tu auras envie de l’exposer à internet, d’ouvrir le port 22 et de rediriger toutes les requêtes de connexion SSH à ton serveur pour que tu puisses y accéder toi-même depuis internet. Ou alors ton serveur est déjà hébergé quelque part sur internet, donc tu as d’autant plus envie de sécuriser son accès !

    Évidemment on a pas envie que ce soit facile pour n’importe qui d’accéder à ta console depuis internet, donc un simple mot de passe pour protéger ta connexion SSH, c’est un peu léger, on va préférer une authentification par clef RSA ! (PS: pense aussi à installer et activer Fail2Ban qui bannira les IP de gens malicieux qui tenteront de se connecter à ta console)

    Pour se faire, c’est simple, tu génères une clef unique sur les postes depuis lesquel tu veux administrer ton serveur. Tu lances une commande toute simple :

    ssh-keygen

    Cela aura pour effet de créer ce qu’il te faut sur ton poste pour l’identifier de façon unique. Tu dois maintenant copier la clef publique générée et la mettre au bon endroit sur ton serveur de façon à ce qu’il sache que ce poste peut s’y connecter. La commande pour faire ça :

    ssh-copy-id hl0dwig@192.168.1.20

    Concrètement ça ajoutera ta clef au bon endroit sur ton serveur de façon ultra simplifiée (dans le fichier ~/.ssh/authorized_keys). Maintenant il faut dire au serveur d’interdire toute tentative de connexion par mot de passe !

    ssh hl0dwig@192.168.1.20
    nano /etc/ssh/ssh_config

    On cherche les 2 lignes suivantes :

    # To disable tunneled clear text passwords, change to no here!
    #PasswordAuthentication yes

    On édite pour décommenter la ligne et passer à « no » :

    # To disable tunneled clear text passwords, change to no here!
    PasswordAuthentication no

    Et là on redémarre le serveur SSH :

    sudo systemctl restart sshd
    exit

    A partir de maintenant il ne sera plus possible de se connecter à ton serveur sans avoir au préalable ajouter une clef RSA au serveur. Tu peux le vérifier en passant l’option -v en t’y connectant :

    ssh hl0dwig@192.168.1.20 -v

    Tu y verras une ligne :

    debug1: Authentications that can continue: publickey

    Mais il y a un piège

    Si comme moi tu as installé la toute dernière version d’Ubuntu Server, tu auras une surprise ! Malgré la modification dans le fichier principal de configuration du serveur SSH tu auras :

    debug1: Authentications that can continue: publickey,password

    La surprise vient d’un sous fichier de configuration bien rangé dans un sous dossier qui est lu par ton serveur SSH, et j’imagine qu’il a été ajouté pour prévenir les pertes d’accès intempestives aux serveurs distants sur VPS :p Jette un oeil à :

    sudo nano /etc/ssh/sshd_config.d/50-cloud-init.conf

    Tu vas trouver une ligne connue à modifier, tu redémarres une nouvelle fois le serveur SSH, et maintenant tout roule ma poule !