Christophe Casalegno

StackX SSL : génération de certificats SSL / TLS let’s encrypt en bash sous Linux

Bonjour à tous, lors de ma dernière vidéo, je partageais avec vous, dans le cadre d’un petit livecoding bash, la création d’un outil permettant de générer des certificats SSL / TLS Let’s Encrypt, tout en effectuant au préalable plusieurs vérifications au niveau des enregistrements DNS notamment.

C’était un besoin interne, et j’en ai donc profité pour enregistrer ce moment.

Pour eux qui veulent consulter la vidéo, je vous la mets juste en dessous. Durant la première partie, je vous explique également et partiellement le fonctionnement interne technique de l’entreprise, dans le cadre de ce produit (StackX : une pile LAMP semi-autonome full managée).

Vous êtes nombreux à m’avoir écrit pour savoir si j’allais mettre le script à disposition, et c’est maintenant chose faite. Je lui ai cependant apporté un certain nombre d’améliorations qui ne figuraient pas dans le script d’origine et notamment :

– Vérification si les arguments attendus sont bien passés au script et valides.
– Le support multi-ip avec la possibilité de mixer IPv4 & IPv6.
– Un peu de couleur.
– Une sortie plus efficace et lisible pouvant être au besoin directement communiquée au client.
– Beaucoup de commentaires en français pour que vous puissiez facilement comprendre et modifier le script
– La mise sous licence libre GPL 3.0

Quelques éléments de contexte :

J’ai écrit cet outil pour un besoin interne correspondant à des configurations données. Il peut donc ne pas matcher avec votre besoin.

J’utilise notamment mod_alias pour avoir un webroot fixe pour la vérification. Voici la configuration correspondante à placer dans le fichier /etc/apache2/mods-available/alias.conf si vous souhaitez utiliser cette fonctionnalité :


        Alias /.well-known "/home/letsencrypt/.well-known"
        <Directory "/home/letsencrypt">
                Options FollowSymlinks
                AllowOverride None
                Require all granted
        </Directory>

Le script est disponible en téléchargement ici : sxssl.sh ou directement depuis la page contributions.

Enjoy, et bonne fin de week-end !

Vous pouvez me suivre sur : Telegram | YouTube | Twitter | Facebook | LinkedIn | Twitch

4 Commentaires

  1. Chalut pitit scarabée,

    je t’écris ici parce que YT refuse (évidemment) mon commentaire sur ta dernière vidéo : « blacklister des ips et des réseaux sous linux » et parce que je bloque tellement de truc chez gogol que je n’ai même pas accès au bouton OK du captcha pour dévoiler ton adresse e-mail.

    Il y visiblement un problème dans ta RE IPv4 d’origine parce qu’elle autorise le blacklisting de l’adresse IP 255.255.255.255 , ce qui susceptible de provoquer un souci – de même, elle autorise des IP inexistantes, par exemple : 999.255.255.255

    Si le but est de permettre n’importe quelle adresse IP excepté : 0.0.0.0, x.x.x.0 et 255.255.255.255, soit : [ 1.0.0.1 – 255.255.255..254 ], alors la RE est différente :

    IP= »$1″
    REGEX=’^(([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4])$’

    if [[ « $IP » =~ $REGEX ]]
    then
    echo « Mon adresse IP : $IP qu’elle est bonne \o/ »
    else
    echo « NAN, veux pas, a pas bon ! »
    fi

    Pour ce qui est d’IPv6, j’ai une looongue string de test prenant tous les cas en compte qui traîne dans un fichier, mais comme je ne n’utilise pas IPv6… ça vient d’une discussion avec de très bonnes critiques sur la chose, donc ça doit faire le taf correctement :

    REGEX_IPv6='(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))’

    et ce que le type expliquait :

    # ‘(
    # ([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}| # 1:2:3:4:5:6:7:8
    # ([0-9a-fA-F]{1,4}:){1,7}:| # 1:: 1:2:3:4:5:6:7::
    # ([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}| # 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8
    # ([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}| # 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8
    # ([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}| # 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8
    # ([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}| # 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8
    # ([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}| # 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8
    # [0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})| # 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
    # :((:[0-9a-fA-F]{1,4}){1,7}|:)| # ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::
    # fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}| # fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index)
    # ::(ffff(:0{1,4}){0,1}:){0,1}
    # ((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}
    # (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])| # ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
    # ([0-9a-fA-F]{1,4}:){1,4}:
    # ((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}
    # (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]) # 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
    # )’

    Note que pour les fichiers blacklist et unblacklist tu pourrais également utiliser la syntaxe d’iptables-persistent dans chaque fichier.

    Voilà, my 2¢

    Jean-Yves

    • Hello et merci, je regarderai ça, j’utilise plusieurs regex différents en fonction des scripts. J’ignore aussi lequel est le plus à jour, toutefois, je veux pouvoir continuer de bloquer 0.0.0.0 au besoin (on peut shutdown l’interface réseau, mais j’ai quelques cas particuliers ou ça m’arrive, même s’il est vrai que je peux toujours lancer iptables en manuel pour ça). Là, c’est une version pour les techs pas pour les clients, car il y a plein de moyens de contourner en utilisant une adresse réseau qui va elle-même contenir une ip à bloquer, il faut sinon s’assurer ensuite de réautoriser automatiquement les ips, etc.

      Pour mon adresse email : brain@christophe-casalegno.com
      Et sinon je suis facile à joindre via Telegram. Merci pour tout, je regarderai ça un peu plus tard.

    • Il doit y avoir une petite coquille dans la regex ipv6 :

      10:15:30-brain@mcp:~$ bash -xv ipv6.sh a.a.a.3
      #!/bin/bash

      REGEX_IPv6='(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))’
      + REGEX_IPv6='(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))’

      if [[ $1 =~ $REGEX_IPV6 ]]
      then
      echo « Mon adresse IP : $1 qu’elle est bonne »
      else
      echo « NAN, veux pas, a pas bon ! »
      fi
      + [[ a.a.a.3 =~  » ]]
      + echo ‘Mon adresse IP : a.a.a.3 qu’elle est bonne’
      Mon adresse IP : a.a.a.3 qu’elle est bonne

      10:15:39-brain@mcp:~$ host free.fr
      free.fr has address 212.27.48.10
      free.fr has IPv6 address 2a01:e0c:1::1
      free.fr mail is handled by 20 mx2.free.fr.
      free.fr mail is handled by 10 mx1.free.fr.
      10:16:27-brain@mcp:~$ bash -xv ipv6.sh 2a01:e0c:1::1
      #!/bin/bash

      REGEX_IPv6='(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))’
      + REGEX_IPv6='(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))’

      if [[ $1 =~ $REGEX_IPV6 ]]
      then
      echo « Mon adresse IP : $1 qu’elle est bonne »
      else
      echo « NAN, veux pas, a pas bon ! »
      fi
      + [[ 2a01:e0c:1::1 =~  » ]]
      + echo ‘Mon adresse IP : 2a01:e0c:1::1 qu’elle est bonne’
      Mon adresse IP : 2a01:e0c:1::1 qu’elle est bonne

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *