Informations :
Dates
- Publish : : Wednesday 28 june 2023
- Modification : Wednesday 20 september 2023
- 364 views
Share :
NdM : 2023/07/09 - Mise à jour (ajout d'information et 2 scripts en fin d'article).
NdM : 2023/08/08 - Modification du script pour vérfier la validité de nos certificats SSL et exemple de mise à jour des champs d'enregistrement TLSA (DANE).
NdM : 2023/09/20 : Modification des scripts "acme-certif-date_verification.bash
" et "acme-certif-frontend.bash
"
Je vais vous expliquer comment créer des certificats SSL/TLS Let's Encrypt en utilisant votre serveur DNS pour créer/valider et mettre à jour vos certificats internationalement.
Let's Encrypt est une autorité de certification qui fournit des certificats gratuits X.509 pour le protocole cryptographique TLS au moyen d'un processus automatisé.
Pré-requis : un serveur DNS authoritaire que vous administrez ; où nous allons activer le moyen de faire des mise à jour dynamique (si cela n'est pas déjà fait).
- Une documentation que j'ai écris : Configuration BIND9 Masters et Slaves
- Je vais utiliser la commande
nsupdate
pour mettre à jour dynamiquement mon server DNS, lors de la création et des mises à jours des certificats.
nsupdate
permet de mettre à jour des "zones" DNS sur votre serveur autoritaire.
- Je vais utiliser l'utilitaire acme.sh pour communiquer avec Let's Encrypt.
acme.sh
permet de créer des certificats SSL/TLS, et permet de mettre à jour vos certificats sur l'AC (l'Authorité de Certifications) Let's Encrypt pour que vos certifats SSL/TLS restent valident dans le monde entier.
Installer acme.sh
un des utilitaires de Let's Encrypt
Je choisis d'installer acme.sh
sur mon container "web" (je vous dis pourquoi, bientôt).
Pour l'installation c'est simple :
Script avec 10 lignes
001root@web:~ # git clone https://github.com/acmesh-official/acme.sh.git
002cd acme.sh
003./acme.sh --install \
004--home ~/acme \
005--config-home ~/acme/data \
006--cert-home ~/acme/mycerts \
007--accountemail "admin@mydomain.tld" \
008--accountkey ~/acme/myaccount.key \
009--accountconf ~/acme/myaccount.conf \
010--useragent "Mozilla/5.0 (compatible; Linux 4.19.0-8-amd64; x86_64) MYACME.Bot/YOUR-CREW (20221002)."
Les options de configuration d'installation sous les suivantes :
--home
est un répertoire personnalisé dans lequel installer acme.sh. Par défaut, il s'installe dans~/.acme.sh
--config-home
est un dossier inscriptible, acme.sh y écrira tous les fichiers (y compris cert/keys, configs). Par défaut, c'est dans--home
--cert-home
est un répertoire personnalisé pour enregistrer les certificats que vous émettez. Par défaut, il est enregistré dans--config-home
.--accountemail
est l'e-mail utilisé pour enregistrer un compte sur Let's Encrypt, vous recevrez un e-mail d'avis de renouvellement ici.--accountkey
est le fichier qui enregistre la clé privée de votre compte. Par défaut, il est enregistré dans--config-home
.--user-agent
est la valeur d'en-tête de l'agent utilisateur utilisée pour envoyer à Let's Encrypt.--nocron
installeracme.sh
sans cronjob
Qui me crée dans mon répertoire /root
le répertoire acme/
Script avec 12 lignes
001root@web:~ # ls -la acme/
002total 260
003drwx------ 6 root root 4096 juin 10 00:20 .
004drwx------ 15 root root 12288 juin 26 16:05 ..
005-rwxr-xr-x 1 root root 220762 juin 10 00:20 acme.sh
006-rw-r--r-- 1 root root 142 nov. 27 2022 acme.sh.env
007drwx------ 26 root root 4096 juin 17 15:46 data
008drwxr-xr-x 2 root root 4096 juin 10 00:20 deploy
009drwxr-xr-x 2 root root 4096 juin 10 00:20 dnsapi
010-rw-r--r-- 1 root root 591 juin 26 00:51 myaccount.conf
011-rw------- 1 root root 1675 nov. 27 2022 myaccount.key
012drwxr-xr-x 2 root root 4096 juin 10 00:20 notify
Ci-dessous le contenu du fichier /root/acme/myaccount.conf
Script avec 16 lignes
001LOG_FILE="/root/acme/data/acme.sh.log"
002LOG_LEVEL=1
003 004AUTO_UPGRADE='1'
005 006#NO_TIMESTAMP=1
007 008ACCOUNT_KEY_PATH='/root/acme/myaccount.key'
009ACCOUNT_EMAIL='admin+acme@mydomain.tld'
010UPGRADE_HASH='b7caf7a0165yuaeiyaeuicfksmlka06bb32025066d'
011USER_AGENT='Mozilla/5.0 (compatible; Linux 4.19.0-8-amd64; x86_64) MYACME.Bot/ZW3B (20221127).'
012SAVED_NSUPDATE_SERVER='dns.ipv10.net'
013SAVED_NSUPDATE_SERVER_PORT=''
014SAVED_NSUPDATE_KEY='/root/nsupdate/Knsupdate-key-zone.+157+09852.private'
015SAVED_NSUPDATE_ZONE=''
016USER_PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/local/openldap/bin'
Avant de pouvoir créer un certificat, il faut configurer "une" zone de notre serveur DNS pour qu'il accepte les mises à jour dynamique - si vous ne connaissez pas vous allez aimer.
J'ajoute la ligne de la tâche planifiée (que j'ai transformé -- j'ai ajouté "une attente (sleep
) avec un nombre (-n1
) aléatoire (shuf
fle) entre 0
et une heure (3600
sec)" à minuit heure locale, pour ne pas surcharger les serveurs Let's Encrypt tous les jours à la même seconde).
Script avec 3 lignes
001root@web:~ # crontab -l
002[....]
00300 00 * * * sleep $(shuf -i 0-3600 -n1) ; "/root/acme"/acme.sh --cron --home "/root/acme" --config-home "/root/acme/data" > /dev/null
Configurer une zone DNS, nous disons "example.com" pour les mises à jour dynamique par nsupdate
Dans le fichier name.conf.local
ajouter à une zone l'option allow-update
avec la clef tsig
:
Par exemple : /etc/bind/named.conf.local
Script avec 12 lignes
001[...]
002zone "example.com" {
003type master;
004# file "/etc/bind/masters/example.com.hosts";
005file "/etc/bind/masters/example.com.hosts.signed";
006 007allow-transfer { key "ns-ldap"; };
008allow-update { key "nsupdate-key-zone"; };
009 010notify yes;
011};
012[...]
Pour créer la clef tsig
de mise à jour dynamique :
Depuis le serveur DNS dans le répertoire correspondant à l'emplacement de clefs key-directory
que nous avons configué dans les "options" du fichier /etc/bind/named.conf.options
:
Script avec 1 ligne
001root@dns:/etc/bind/keys # tsig-keygen -a hmac-sha512 nsupdate-key-zone
Il faut passer les clefs à l'utilisateur "bind".
Qui nous créait 2 fichiers :
Script avec 3 lignes
001root@dns:/etc/bind/keys # ls -l Knsupdate-key-zone.+157+09852.*
002-rw-r--r-- 1 bind bind 123 nov. 17 2022 Knsupdate-key-zone.+157+09852.key
003-rw------- 1 bind bind 229 nov. 17 2022 Knsupdate-key-zone.+157+09852.private
Maintenant il faut envoyer sur le serveur Web la clef pour pouvoir utiliser nsupdate
depuis notre serveur Web.
J'oubliais, il faut autoriser le serveur Web à faire des mises à jour. Pour cela, dans un des fichiers de "bind" ajouter :
Par exemple dans /etc/bind/named.conf
:
Script avec 7 lignes
001[...]
002# WEB.SERVER (IPv6)
003server 2607:5300:60:9389:15:1:a:10 {
004transfer-format many-answers;
005keys { "nsupdate-key-zone"; };
006};
007[...]
Pour transférer la clef dans le répertoire nsupdate/
de l'utilisateur "root" du serveur "web" vous pouvez utiliser la commande :
Script avec 1 ligne
001root@dns:/etc/bind/keys # scp /etc/bind/keys/Knsupdate-key-zone.+157+09852.private root@web:/root/nsupdate/
Nous allons pouvoir créer et mettre à jour nos certificats SSL/TLS Let's Encrypt avec acme.sh
.
Créons un certificat Let's Encrypt pour notre zone / nom de domaine "example.com"
Depuis le serveur Web, là où nous avons installer acme.sh
, créons un certificat.
Script avec 1 ligne
001root@web:~ # acme.sh --install-cert --domain example.com
Ca va nous créait un répertoire ici :
Script avec 4 lignes
001root@web:~ # ls -l /root/acme/data/example.com
002total 8
003drwxr-xr-x 2 root root 4096 juin 17 15:45 backup
004-rw-r--r-- 1 root root 98 juin 17 15:45 example.com.conf
Ensuite, vous pouvez envoyer la commande comme çà (nul besoin d'envoyer les variable d'environnement NSUPDATE_SERVER
et NSUPDATE_KEY
) :
Script avec 80 lignes
001root@web:~ # NSUPDATE_SERVER="dns.ipv10.net" NSUPDATE_KEY="/root/nsupdate/Knsupdate-key-zone.+157+09852.private" acme.sh --issue -k ec-384 -d example.com -d '*.example.com ' --dns dns_nsupdate --server letsencrypt
002[dimanche 27 novembre 2022, 18:41:37 (UTC+0100)] Using CA: https://acme-v02.api.letsencrypt.org/directory
003[dimanche 27 novembre 2022, 18:41:37 (UTC+0100)] Creating domain key
004[dimanche 27 novembre 2022, 18:41:37 (UTC+0100)] The domain key is here: /root/acme/data/example.com_ecc/example.com.key
005[dimanche 27 novembre 2022, 18:41:37 (UTC+0100)] Multi domain='DNS:example.com,DNS:*.example.com'
006[dimanche 27 novembre 2022, 18:41:37 (UTC+0100)] Getting domain auth token for each domain
007[dimanche 27 novembre 2022, 18:41:39 (UTC+0100)] Getting webroot for domain='example.com'
008[dimanche 27 novembre 2022, 18:41:39 (UTC+0100)] Getting webroot for domain='*.example.com'
009[dimanche 27 novembre 2022, 18:41:39 (UTC+0100)] Adding txt value: cFXIej611Rh8iar4hJiJfus85uHSk9FIhEWllDCrrQ4 for domain: _acme-challenge.example.com
010[dimanche 27 novembre 2022, 18:41:39 (UTC+0100)] adding _acme-challenge.example.com. 60 in txt "cFXIej611Rh8iar4hJiJfus85uHSk9FIhEWllDCrrQ4"
011[dimanche 27 novembre 2022, 18:41:39 (UTC+0100)] The txt record is added: Success.
012[dimanche 27 novembre 2022, 18:41:39 (UTC+0100)] Adding txt value: C8vU4Sgg0UythPJfeudNr9dvEl8D6eULaBHDRgKHESs for domain: _acme-challenge.example.com
013[dimanche 27 novembre 2022, 18:41:39 (UTC+0100)] adding _acme-challenge.example.com. 60 in txt "C8vU4Sgg0UythPJfeudNr9dvEl8D6eULaBHDRgKHESs"
014[dimanche 27 novembre 2022, 18:41:39 (UTC+0100)] The txt record is added: Success.
015[dimanche 27 novembre 2022, 18:41:39 (UTC+0100)] Let's check each DNS record now. Sleep 20 seconds first.
016[dimanche 27 novembre 2022, 18:42:00 (UTC+0100)] You can use '--dnssleep' to disable public dns checks.
017[dimanche 27 novembre 2022, 18:42:00 (UTC+0100)] See: https://github.com/acmesh-official/acme.sh/wiki/dnscheck
018[dimanche 27 novembre 2022, 18:42:00 (UTC+0100)] Checking example.com for _acme-challenge.example.com
019[dimanche 27 novembre 2022, 18:42:01 (UTC+0100)] Not valid yet, let's wait 10 seconds and check next one.
020[dimanche 27 novembre 2022, 18:42:12 (UTC+0100)] Checking example.com for _acme-challenge.example.com
021[dimanche 27 novembre 2022, 18:42:12 (UTC+0100)] Domain example.com '_acme-challenge.example.com' success.
022[dimanche 27 novembre 2022, 18:42:12 (UTC+0100)] Let's wait 10 seconds and check again.
023[dimanche 27 novembre 2022, 18:42:24 (UTC+0100)] You can use '--dnssleep' to disable public dns checks.
024[dimanche 27 novembre 2022, 18:42:24 (UTC+0100)] See: https://github.com/acmesh-official/acme.sh/wiki/dnscheck
025[dimanche 27 novembre 2022, 18:42:24 (UTC+0100)] Checking example.com for _acme-challenge.example.com
026[dimanche 27 novembre 2022, 18:42:24 (UTC+0100)] Domain example.com '_acme-challenge.example.com' success.
027[dimanche 27 novembre 2022, 18:42:24 (UTC+0100)] Checking example.com for _acme-challenge.example.com
028[dimanche 27 novembre 2022, 18:42:24 (UTC+0100)] Already success, continue next one.
029[dimanche 27 novembre 2022, 18:42:24 (UTC+0100)] All success, let's return
030[dimanche 27 novembre 2022, 18:42:24 (UTC+0100)] Verifying: example.com
031[dimanche 27 novembre 2022, 18:42:24 (UTC+0100)] Pending, The CA is processing your order, please just wait. (1/30)
032[dimanche 27 novembre 2022, 18:42:27 (UTC+0100)] Success
033[dimanche 27 novembre 2022, 18:42:27 (UTC+0100)] Verifying: *.example.com
034[dimanche 27 novembre 2022, 18:42:28 (UTC+0100)] Pending, The CA is processing your order, please just wait. (1/30)
035[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] Success
036[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] Removing DNS records.
037[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] Removing txt: cFXIej611Rh8iar4hJiJfus85uHSk9FIhEWllDCrrQ4 for domain: _acme-challenge.example.com
038[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] removing _acme-challenge.example.com. txt
039[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] Removed: Success
040[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] Removing txt: C8vU4Sgg0UythPJfeudNr9dvEl8D6eULaBHDRgKHESs for domain: _acme-challenge.example.com
041[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] removing _acme-challenge.example.com. txt
042[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] Removed: Success
043[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] Verify finished, start to sign.
044[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] Lets finalize the order.
045[dimanche 27 novembre 2022, 18:42:32 (UTC+0100)] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/844254157/148100921877'
046[dimanche 27 novembre 2022, 18:42:33 (UTC+0100)] Downloading cert.
047[dimanche 27 novembre 2022, 18:42:33 (UTC+0100)] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/039018fe4ff377bae8ffa5414587248b87ba'
048[dimanche 27 novembre 2022, 18:42:33 (UTC+0100)] Cert success.
049-----BEGIN CERTIFICATE-----
050MIIEcDCCA1igAwIBAgISA5AY/k/zd7ro/6VBRYcki4e6MA0GCSqGSIb3DQEBCwUA
051MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
052EwJSMzAeFw0yMjExMjcxNjQyMzNaFw0yMzAyMjUxNjQyMzJaMBIxEDAOBgNVBAMT
053B3p3M2IudHYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATyBsggIW81ICHMZRSZC7+z
054eT4vehWp+8/DjzzYVOXTbVXfoYT0OK7FG1bFe6w9K5RHjo6oAXDsaRYILUDpPxwd
055Ds/EDBx4a0FLlLhF5TRak2E4J0yWWcjTTzHSSaJWR+OjggJMMIICSDAOBgNVHQ8B
056Af8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB
057/wQCMAAwHQYDVR0OBBYEFN/cg8rD30RVvd5cFNjYTqnrvdBQMB8GA1UdIwQYMBaA
058FBQusxe3WFbLrlAJQOYfr52LFMLGMFUGCCsGAQUFBwEBBEkwRzAhBggrBgEFBQcw
059AYYVaHR0cDovL3IzLm8ubGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRwOi8vcjMu
060aS5sZW5jci5vcmcvMB0GA1UdEQQWMBSCCSouenczYi50doIHenczYi50djBMBgNV
061HSAERTBDMAgGBmeBDAECATA3BgsrBgEEAYLfEwEBATAoMCYGCCsGAQUFBwIBFhpo
062dHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCCAQMGCisGAQQB1nkCBAIEgfQEgfEA
0637wB2AHoyjFTYty22IOo44FIe6YQWcDIThU070ivBOlejUutSAAABhLou/8IAAAQD
064AEcwRQIgBwly1igZHpDTzGGpd01WNVxrqRYH00LcCvLA7x4IXdgCIQDnkhdkMW+S
065pbrbHQ4Uqv8pBrVXnL2nLgkyImUWGHU76AB1AK33vvp8/xDIi509nB4+GGq0Zyld
066z7EMJMqFhjTr3IKKAAABhLou/9AAAAQDAEYwRAIgEMQsh2lYmTLkKpDDyEQuCnsO
067nA6/vnZVgdJcDE74HkwCIF/rhY/n0ZH6LL4yICj63JZzdJThnIq9zNjj03PlhraL
068MA0GCSqGSIkjldqdjql133qjdqljdlàç212dGGGxZGJXQ+sgKkxYBY5O2lxhvTgp
069V9mOr0HABBYJomGmlJ3o9/BZ6aADnQ40W8B8xnh5PlaDi0rNQ3gBhwLn4tZB+NfK
070KQDLpPIGqRrsdfACnkiu4GoiFkBBJY+HkgatAWdlRrlTlM8AkZNrX1kzg8u3jQY1
071SVVJ8g4qjbYWdCaUe8r/EMILX9bL4LvNtvW4gvQsNWVF2E7GbzawK153j1aP8gLl
072kCjTWyLOIWA1nhhoKKadcIYgmYG7GF3VMXceprrBPIMmRPRrCfRGErqVhxK3hvc8
0732uiyN3YDbpOHClnVe9PYjJZIVSswSXwYZKZkkRkAQKLgDTCs
074-----END CERTIFICATE-----
075[dimanche 27 novembre 2022, 18:42:33 (UTC+0100)] Your cert is in: /root/acme/data/example.com_ecc/example.com.cer
076[dimanche 27 novembre 2022, 18:42:33 (UTC+0100)] Your cert key is in: /root/acme/data/example.com_ecc/example.com.key
077[dimanche 27 novembre 2022, 18:42:33 (UTC+0100)] The intermediate CA cert is in: /root/acme/data/example.com_ecc/ca.cer
078[dimanche 27 novembre 2022, 18:42:33 (UTC+0100)] And the full chain certs is there: /root/acme/data/example.com_ecc/fullchain.cer
079Vous avez du nouveau courrier dans /var/mail/root
080root@web:~ #
À ce moment là, nous avons un certificat pour notre nom de domaine "example.com" et tous ces sous domaines "*.example.com"
Ce n'est pas forcement nécessaire, vous pouvez créer un certificat en plus pour "ftp.example.com" ; à vous de voir - ce permet d'avoir un/des certificats pour chaque machine, type de service.
TODO Note de Moi-même : Il y a des "get options" à la commande acme.sh
comme --reloadcmd
et --renew-hook
. À tester, pour mettre à jour les champs TLSA (DANE).
Créer un certificat pour un "alias de domaine"
Pour faire un certificat Let's Encrypt pour le domaine "domain.com" qui est un DNAME (alias de domaine) de "other_domain.com" la commande serait :
Script avec 1 ligne
001root@web:~ # acme.sh --issue -k ec-384 -d domain.com -d '*.domain.com' --domain-alias other_domain.com --dns dns_nsupdate --server letsencrypt
Pour faire un certificat Let's Encrypt pour le domaine "domain.com" et tous ses sous-domaine "*.domain.com" ainsi que "other_domain.com" et tous ses sous-domaine "*.other_domain.com" et que "other_domain.com" est un alias de nom de domaine de "domain.com" (--challenge-alias domain.com
)
Script avec 1 ligne
001root@web:~ # acme.sh --issue -k ec-384 -d domain.com -d '*.domain.com' --challenge-alias domain.com -d other_domain.com -d '*.other_domain.com' --dns dns_nsupdate --server letsencrypt --force
Pour vous donner un exemple d'alias de domaine → lab3w.com est un alias de domaine de lab3w.fr :
Script avec 6 lignes
001root@web:~ # host www.lab3w.com
002lab3w.com has DNAME record lab3w.fr.
003www.lab3w.com is an alias for www.lab3w.fr.
004www.lab3w.fr is an alias for web.lab3w.fr.
005web.lab3w.fr has address 158.69.126.137
006web.lab3w.fr has IPv6 address 2607:5300:60:9389:15:1:0:1
J'utilise l'algorithme de sécurité de courbes elliptiques (ec) d'une valeur de 384 bits.
Vous pouvez utiliser :
-k ec-256
Ou d'autres algorithme moins récents.
Configurer les certificats Let's Encrypt à votre serveur Web Apache :
Ajouter votre certificat SSL à votre site Web HTTPS "*.example.com:443"
Script avec 20 lignes
001<IfModule mod_ssl.c>
002<VirtualHost [2607:5300:0060:9389:0015:0001:000a:0010]:443 10.101.150.10:443>
003 004ServerName example.com
005ServerAlias *.example.com
006007
SSLEngine On
008 009# SSLProtocol -all +SSLv2
010# SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
011# SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
012013
SSLCertificateFile /root/acme/data/example.com_ecc/example.com.cer
014SSLCertificateKeyFile /root/acme/data/example.com_ecc/example.com.key
015SSLCACertificateFile /root/acme/data/example.com_ecc/ca.cer
016017
[...]
018019
</VirtualHost>
020</IfModule>
SSL configuration serveur Web :
- Exemple d'intégration d'un certificat SSL sur des serveurs Web moz://a SSL Configuration Generator
Informations, scripts sur certificats SSL/TLS :
Je vous ajoute 2 scripts (vraiment à l'arache, çà peut aider) :
- Un pour tester la validité de certificats SSL, en ressortant la signature numérique du certificat et celle de la Ressource Records (l'enregistrement) TLSA (DANE).
- Et l'autre pour envoyer/déployer ses certificats SSL sur d'autres machines
1. Vérifier la date d'expiration d'un certificats SSL/TLS :
On créait un fichier : vim /root/acme-certif-date_verification.bash
Script avec 102 lignes
001#!/bin/bash
002#-----------------------------------
003# Checking certificates SSL date expiration
004#-----------------------------------
005# Author : O.Romain.Jaillet-ramey (orj AT lab3w DOT fr)
006# Date created : 20221201
007# Date modified : 20230920
008#-----------------------------------
009 010dir_certs="/root/acme/data/"
011#dir_certs="/etc/ssl/letsencrypt/"
012 013domains="lab3w.fr zw3b.fr zw3b.tv zw3b.site zw3b.net zw3b.blog zw3b.eu ipv10.net"
014#domains="lab3w.lan"
015 016#------------------------------------------------------------------------------------------------------
017for domain in ${domains}; do
018# command checking certificat SSL externe
019# expiryDate="$(echo $(date -d "$(echo | openssl s_client -servername ${domain} -connect ${domain}:443 -verify_quiet | openssl x509 -enddate -noout | awk -F= '{print $2}')"))"
020# command checking certificat SSL local
021expiryDate="$(echo $(date -d "$(echo | openssl x509 -in ${dir_certs}${domain}_ecc/${domain}.cer -enddate -noout | awk -F= '{print $2}')"))"
022 023# command checking certificat SSL externe
024# expiryDays=$(( ($(date -d "$(echo | openssl s_client -servername ${domain} -connect ${domain}:443 -verify_quiet | openssl x509 -enddate -noout | awk -F= '{print $2}')" '+%s') - $(date '+%s')) / 86400 ))
025# command checking certificat SSL local
026expiryDays=$(( ($(date -d "$(echo | openssl x509 -in ${dir_certs}${domain}_ecc/${domain}.cer -enddate -noout | awk -F= '{print $2}')" '+%s') - $(date '+%s')) / 86400 ))
027 028renewDay=$(($expiryDays - 30))
029 030# command checking certificat SSL externe
031# subjectAltName=$(echo | openssl s_client -servername ${domain} -connect ${domain}:443 -verify_quiet | openssl x509 -noout -ext subjectAltName -noout | grep DNS | tr -d [:blank:])
032# command checking certificat SSL local
033subjectAltName=$(echo | openssl x509 -noout -ext subjectAltName -in ${dir_certs}${domain}_ecc/${domain}.cer | grep DNS | tr -d [:blank:])
034 035signature_certif=$(openssl x509 -noout -fingerprint -sha256 < ${dir_certs}${domain}_ecc/${domain}.cer | tr -d : | cut -d"=" -f2)
036signature_ondns=$(dig TLSA _443._tcp.${domain} @dns.google +short | awk {'print $4$5'})
037038
old="$IFS"
039IFS=","
040tab=( $subjectAltName )
041IFS="$old"
042 043echo "#-----------------------------------"
044echo "Domain : ${domain}"
045echo "#----------"
046echo ""
047echo "Certificats SSL expiration date : ${expiryDate}"
048echo "Certificats SSL expiration days : ${expiryDays}"
049# echo "Subject Alt Names : ${subjectAltName}"
050echo ""
051echo "Subject Alt Names :"
052echo " \ "
053for (( i=0 ; i<${#tab[*]} ; i++ )) ; do
054echo " +→ "${tab[$i]}
055done
056echo ""
057echo "Certificat Signature check :"
058echo " \ "
059echo " +-" ${signature_certif} "→ Certificat signature"
060if [ -n "${signature_ondns}" ]
061then
062echo " +-" ${signature_ondns} "→ Signature on DNS RR TLSA"
063fi
064if [ -z "${signature_ondns}" ]
065then
066echo " \ "
067echo " +-→ NO DNS RR TLSA (DANE) on Cerfificat Signature."
068fi
069if [ "${signature_certif}" = "${signature_ondns}" ]
070then
071echo " \ "
072echo " +-→ DNS RR TLSA (DANE) on Cerfificat Signature - OK"
073fi
074if [ "${signature_certif}" != "${signature_ondns}" ] && [ -n "${signature_ondns}" ]
075then
076echo " \ "
077echo " +-→ DNS RR TLSA (DANE) on Cerfificat Signature - NO OK"
078echo " \ "
079echo " +-→ Update your DNS RR TLSA (DANE) with "nsupdate" command"
080echo " |"
081echo " | ; example"
082echo " | server dns.ipv10.net"
083echo " | zone ${domain}"
084 085for (( i=0 ; i<${#tab[*]} ; i++ )) ; do
086ntab[$i]=$(echo ${tab[$i]} | awk 'BEGIN { FS = ":" }; { if($2 !~ /\*/ ) print $2 }')
087if [ "${ntab[$i]}" != "" ]
088then
089echo " | update del _443._tcp.${ntab[$i]}. 3600 TLSA"
090echo " | update add _443._tcp.${ntab[$i]}. 3600 TLSA 3 0 1 ${signature_certif}"
091fi
092done
093 094echo " | send"
095echo " +------------------------------------"
096fi
097 098echo ""
099 100done
101 102echo "#-----------------------------------"
Donner les droits d'executer à l'utilisateur "chmod u+x /root/acme-certif-date_verification.bash
" ;
puis lancer le script "/root/acme-certif-date_verification.bash
".
Vous retournera quelque chose comme çà :
Script avec 172 lignes
001root@web:~ # /root/acme-certif-date_verification.bash
002#-----------------------------------
003Domain : lab3w.fr
004#----------
005 006Certificats SSL expiration date : samedi 23 septembre 2023, 23:51:07 (UTC+0200)
007Certificats SSL expiration days : 46
008 009Subject Alt Names :
010\
011+→ DNS:*.lab3w.com
012+→ DNS:*.lab3w.fr
013+→ DNS:lab3w.com
014+→ DNS:lab3w.fr
015 016Certificat Signature check :
017\
018+- ECFFB8AEA0FF53484F21294E4F69C39CF34F4D7390CAAC66B8C8B0A50657EA50 → Certificat signature
019+- ECFFB8AEA0FF53484F21294E4F69C39CF34F4D7390CAAC66B8C8B0A50657EA50 → Signature on DNS RR TLSA
020\
021+-→ DNS RR TLSA (DANE) on Cerfificat Signature - OK
022 023#-----------------------------------
024Domain : zw3b.fr
025#----------
026 027Certificats SSL expiration date : vendredi 22 septembre 2023, 23:23:36 (UTC+0200)
028Certificats SSL expiration days : 45
029 030Subject Alt Names :
031\
032+→ DNS:api.zw3b.fr
033+→ DNS:howto.zw3b.fr
034+→ DNS:mailing.zw3b.fr
035+→ DNS:radio.zw3b.fr
036+→ DNS:www.zw3b.fr
037+→ DNS:zw3b.fr
038 039Certificat Signature check :
040\
041+- C1A68D384582BC4A88EC7DB3492678B1B6A6E088036FD90306F4F47AF5B7332D → Certificat signature
042+- C1A68D384582BC4A88EC7DB3492678B1B6A6E088036FD90306F4F47AF5B7332D → Signature on DNS RR TLSA
043\
044+-→ DNS RR TLSA (DANE) on Cerfificat Signature - OK
045 046#-----------------------------------
047Domain : zw3b.tv
048#----------
049 050Certificats SSL expiration date : vendredi 22 septembre 2023, 23:24:59 (UTC+0200)
051Certificats SSL expiration days : 45
052 053Subject Alt Names :
054\
055+→ DNS:www.zw3b.tv
056+→ DNS:zw3b.tv
057 058Certificat Signature check :
059\
060+- 742D5E938E928F0E7F9A87811E0CFE1BE399005E2B2CAC1BBB42971E656C25A3 → Certificat signature
061+- 742D5E938E928F0E7F9A87811E0CFE1BE399005E2B2CAC1BBB42971E656C25A3 → Signature on DNS RR TLSA
062\
063+-→ DNS RR TLSA (DANE) on Cerfificat Signature - OK
064 065#-----------------------------------
066Domain : zw3b.site
067#----------
068 069Certificats SSL expiration date : vendredi 20 octobre 2023, 23:33:51 (UTC+0200)
070Certificats SSL expiration days : 73
071 072Subject Alt Names :
073\
074+→ DNS:*.zw3b.site
075+→ DNS:zw3b.site
076 077Certificat Signature check :
078\
079+- C894DD1ACD81BF4613E69927FB0F7539018165182BA2C4B5587D33A8C9D1E411 → Certificat signature
080+- C894DD1ACD81BF4613E69927FB0F7539018165182BA2C4B5587D33A8C9D1E411 → Signature on DNS RR TLSA
081\
082+-→ DNS RR TLSA (DANE) on Cerfificat Signature - OK
083 084#-----------------------------------
085Domain : zw3b.net
086#----------
087 088Certificats SSL expiration date : vendredi 22 septembre 2023, 23:24:08 (UTC+0200)
089Certificats SSL expiration days : 45
090 091Subject Alt Names :
092\
093+→ DNS:www.zw3b.net
094+→ DNS:zw3b.net
095 096Certificat Signature check :
097\
098+- 992DB6977A23A379BA0378335C26E0855CAA4DEF20D9BC986EE947C6FA9719C9 → Certificat signature
099+- 992DB6977A23A379BA0378335C26E0855CAA4DEF20D9BC986EE947C6FA9719C9 → Signature on DNS RR TLSA
100\
101+-→ DNS RR TLSA (DANE) on Cerfificat Signature - OK
102 103#-----------------------------------
104Domain : zw3b.blog
105#----------
106 107Certificats SSL expiration date : samedi 23 septembre 2023, 23:51:42 (UTC+0200)
108Certificats SSL expiration days : 46
109 110Subject Alt Names :
111\
112+→ DNS:*.zw3b.blog
113+→ DNS:zw3b.blog
114 115Certificat Signature check :
116\
117+- 13B178DBE595C90AF7B461C115B5B2E323AC6403CACB2BA1F62345669DF47F25 → Certificat signature
118+- 13B178DBE595C90AF7B461C115B5B2E323AC6403CACB2BA1F62345669DF47F25 → Signature on DNS RR TLSA
119\
120+-→ DNS RR TLSA (DANE) on Cerfificat Signature - OK
121 122#-----------------------------------
123Domain : zw3b.eu
124#----------
125 126Certificats SSL expiration date : mercredi 25 octobre 2023, 23:15:21 (UTC+0200)
127Certificats SSL expiration days : 78
128 129Subject Alt Names :
130\
131+→ DNS:*.zw3b.eu
132+→ DNS:zw3b.eu
133 134Certificat Signature check :
135\
136+- 76B2ABF86AD5D7002B03BAE2C7474E42E6ECA5DC4625BCABFBF9577165784274 → Certificat signature
137+- 122DB6977A23A379BA0378335C26E0855CAA4DEF20D9BC986EE947C6FA9719D7 → Signature on DNS RR TLSA
138\
139+-→ DNS RR TLSA (DANE) on Cerfificat Signature - NO OK
140\
141+-→ Update your DNS RR TLSA (DANE) with "nsupdate" command
142|
143| ; example
144| server dns.ipv10.net
145| zone zw3b.eu
146| update del _443._tcp.zw3b.eu. 3600 TLSA
147| update add _443._tcp.zw3b.eu. 3600 IN TLSA 3 0 1 76B2ABF86AD5D7002B03BAE2C7474E42E6ECA5DC4625BCABFBF9577165784274
148| send
149+------------------------------------
150 151#-----------------------------------
152Domain : ipv10.net
153#----------
154 155Certificats SSL expiration date : samedi 23 septembre 2023, 23:49:51 (UTC+0200)
156Certificats SSL expiration days : 46
157 158Subject Alt Names :
159\
160+→ DNS:*.ipv01.net
161+→ DNS:*.ipv10.net
162+→ DNS:ipv01.net
163+→ DNS:ipv10.net
164 165Certificat Signature check :
166\
167+- 924CACB8AB876888A3F07BDC9B6B6C39235502161991EECE5EC945174E91E07C → Certificat signature
168\
169+-→ NO DNS RR TLSA (DANE) on Cerfificat Signature.
170 171#-----------------------------------
172
C'est juste pour information (on n'a pas besoin forcement de ce script), çà peut nous servir.
Vous remarquerez que je vous parle des RR (Ressources Recors DNS) TLSA du protocole/mécanisme DANE (DNS - based Authentication of Named Entities) qui s'appuie sur le DNS pour authentifier des entités applicatives.
Par exemple pour les applications Web, vous pouvez utiliser "DNSSEC/DANE Validator " ; plugin Firefox qui vous permet de vérifier l'existence et la validité des enregistrements DNSSEC et TLSA liés aux noms de domaine.
Donc, normalement si vous avez suivis la procédure du dessus, acme.sh [...] --dns dns_nsupdate
met à jour nos certificats SSL/TLS Let's Encrypt tous les 60 jours, 30 jours avant l'expiration (le certificat en valide 90 jours) (AUTO_UPGRADE='1'
dans /root/acme/myaccount.conf
).
Par contre, si vous avez besoin de déployer vos certificats SSL/TLS sur vos proxy, load balancer frontaux, clusters ou autres serveurs (HTTP, FTP etc.), ci-dessous un exemple.
2. Déployer vos certificats SSL/TLS sur d'autres serveurs :
Si vous avez besoin d'utiliser vos certificats sur d'autres machines.
Ci-dessous un script RSYNC pour envoyer vos certificats sur d'autres machines serveurs.
On créait un fichier : root@web:~ # vim /root/acme-certif-frontend.bash
Script avec 204 lignes
001#!/bin/bash
002#-----------------------------------
003# RSYNC script for tranfert SSL/TLS certificats files modified on others servers
004#-----------------------------------
005# Author : O.Romain.Jaillet-ramey (orj AT lab3w DOT fr)
006# Date created : 20221201
007# Date modified : 20230920
008#-----------------------------------
009 010#------------------------------------------------------------------------------------------------------
011# Authentification par certicats (sans humain)
012#-----
013auth=`find /tmp -user $LOGNAME -type s -name "*agent*" -print 2>/dev/null`
014SSH_AUTH_SOCK=$auth
015export SSH_AUTH_SOCK
016#------------------------------------------------------------------------------------------------------
017 018#------------------------------------------------------------------------------------------------------
019# Config
020#-----
021 022dir="/root/acme/data/"
023#files_extension=".cer .key"
024 025#------------------------------------------------------------------------------------------------------
026# Files/Dir of certicats Domains to check with rsync
027# ${dir}${domain}_ecc/
028#-----
029 030domains="lab3w.fr zw3b.fr zw3b.tv zw3b.site zw3b.net zw3b.blog zw3b.eu ipv10.net"
031#domains="lab3w.lan"
032 033#------------------------------------------------------------------------------------------------------
034# Remote servers on which SSL certificates are needed
035#-----
036rservers="lb1.lab3w.lan lb2.lab3w.lan server.lab3w.com"
037 038rdir="/etc/ssl/letsencrypt/"
039ruser="root"
040rkey=".ssh/id_ecdsa"
041rport="22"
042 043#------------------------------------------------------------------------------------------------------
044# texts
045#-----
046 047text_file=()
048text_file_ca=()
049text_server=()
050 051#------------------------------------------------------------------------------------------------------
052# script
053#-----
054 055for rserver in ${rservers}; do
056 057text_status=()
058text_status_ca=()
059text_domain=()
060 061text_files=()
062 063text_server=("${rserver}")
064 065#------------------------------------------------------------------------------------------------------
066# script authenfication
067#-----
068 069if ! ssh -p ${rport} -i ${rkey} ${ruser}@${rserver} "test pwd"; then
070echo "Authentication failed !"
071echo "Exit !"
072exit 2
073fi
074 075#------------------------------------------------------------------------------------------------------
076 077echo "#------------------------------------------------"
078echo "SERVER : ${rserver}"
079echo ""
080 081#------------------------------------------------------------------------------------------------------
082# script RSYNC
083#-----
084 085for domain in ${domains}; do
086 087text_files=("${domain}")
088 089if ! ssh -p ${rport} -i ${rkey} ${ruser}@${rserver} "test -x ${rdir}${domain}_ecc"; then
090# echo "The remote directory "${rdir}${domain}_ecc" do not exist"
091# echo "Create directory"
092ssh -p ${rport} -i ${rkey} ${ruser}@${rserver} "mkdir -p ${rdir}${domain}_ecc"
093 094if ! ssh -p ${rport} -i ${rkey} ${ruser}@${rserver} "test -x ${rdir}${domain}_ecc"; then
095# echo "The remote directory "${rdir}${domain}_ecc" could not be created or has bad permissions."
096# echo "Exit !"
097exit 2
098fi
099 100# echo "Remote directory "${rdir}${domain}_ecc" OK !"
101# echo ""
102fi
103 104# for ext in ${files_extension}; do
105# output=$(rsync -a --info=NAME -e "ssh -i ${rkey}" ${dir}${domain}_ecc/${domain}${ext} ${ruser}@${rserver}:${rdir}${domain}_ecc/${domain}${ext})
106output=$(rsync -a --info=NAME -e "ssh -i ${rkey}" ${dir}${domain}_ecc/ ${ruser}@${rserver}:${rdir}${domain}_ecc/)
107if [ "output_${output}" = "output_" ]; then
108text_status+=( "$(printf "%dn" $?)" )
109text_domain+=( "${domain}" )
110text_file+=( "${dir}${domain}_ecc/${output}" )
111 112else
113text_status+=(150)
114text_domain+=( "${domain}" )
115text_file+=( "${dir}${domain}_ecc/${output}" )
116 117# text_files+=( "${domain}", "${dir}${domain}_ecc/${output}" )
118 119fi
120# rsync -a -e "ssh -i ${rkey}" ${dir}${domain}_ecc/ca.cer ${ruser}@${rserver}:${rdir}${domain}_ecc/ca.cer
121# status_ca+=( "$(printf "%dn" $?)" )
122# done
123done # files
124 125 126#done # rservers
127 128#------------------------------------------------------------------------------------------------------
129# Restart servers
130#----
131 132restart_server=0
133 134msg=""
135i=0
136for code in "${text_status[@]}"; do
137 138# msg+="# MSG $i : ${file_cert[$i]}n"
139 140# echo "Code : ${code}"
141if [ ${code} -eq 150 ]; then
142 143msg+="#------------------------n"
144msg+="# Server : ${text_server}n"
145msg+="# Domain : ${text_domain[$i]}n"
146msg+="# Files : ${text_file[$i]} is modified (status : ${text_status[$i]})n"
147 148# for file in "${text_files[${text_domain[$i]}]}"; do
149# msg+="# File : ${file} is modifiedn"
150# done
151 152msg+="#------------------------n"
153 154restart_server=1
155fi
156 157i=$((${i} + 1))
158done
159 160if [ "_$msg" != "_" ]; then
161echo -e $msg
162fi
163 164 165if [ ${restart_server} -eq 1 ]; then
166 167for code in "${text_server[@]}"; do
168 169# nodes servers
170ssh -p ${rport} -i ${rkey} ${ruser}@${rserver} "/etc/init.d/apache2 reload"
171 172echo "#--→ Server Apache ${rserver} reloading"
173 174done
175 176else
177echo "#--→ Server Apache ${rserver} do not reloading (no update certificat)"
178fi
179 180echo ""
181echo "#------------------------------------------------"
182echo ""
183 184done # rservers
185 186#------------------------------------------------------------------------------------------------------
187 188echo "SERVER : LOCAL"
189echo ""
190if [ ${restart_server} -eq 1 ]; then
191 192# local server
193/etc/init.d/apache2 reload
194echo "#--→ Server Apache LOCAL reloading"
195 196else
197echo "#--→ Server Apache LOCAL do not reloading (no update certificat)"
198fi
199 200echo ""
201echo "#------------------------------------------------"
202echo ""
203 204#------------------------------------------------------------------------------------------------------
Pour les lignes "10 à 16" du script ci-dessus "l'authentification avec une paire de clefs", j'ai écris une documentation ici : SSH - SCP par certificats .
Pour lancer la mise à jour par rsync
(qui enverra les fichiers (seulement s'ils ont changés) sur les autres serveurs) :
Script avec 1 ligne
001root@web:~ # /root/acme-certif-frontend.bash
La commande envoie les fichiers modifiés sur les autres serveurs et redémare les serveurs Web Apache.
Il faut faire une tâche planifiée tous les jours à l'heure que vous voulez pour rester à jour niveau certificats SSL/TLS.
Par exemple mes tâches planifiées pour ce service ressemble à çà :
Script avec 4 lignes
001root@web:~ # crontab -l
002# Lets Encrypt (ACME)
00300 00 * * * sleep $(shuf -i 0-3600 -n1) ; "/root/acme"/acme.sh --cron --home "/root/acme" --config-home "/root/acme/data" ; /root/acme-certif-frontend.bash | mail -s "[ZW3B][DNSSEC] Acme + Rsync" "email_1@domain.fr,email_2@domain.fr" > /dev/null
00401 00 * * * /root/acme-certif-date_verification.bash | mail -s "[ZW3B][DNSSEC] Date Verification" "email_1@domain.fr,email_2@domain.fr" 1>>/var/log/syslog 2>/dev/null 2>&1
Il manque toujours la mise à jour des champs TLSA du protocole/mécanisme DANE, mais avec cela on a nos sites Web valident et sécurisés et les certificats SSL/TLS transférés et mis à jour sur vos frontaux et sur les autres machines.
TODO Note de Moi-même du 2023/08/08 : Si, vous avez configuré vos champs TLSA du protocole/mécanisme DANE (DNS - based Authentication of Named Entities) qui s'appuie sur le DNS pour authentifier des entités applicatives ; il faut/faudra mettre à jour les RR (Ressource Records) TLSA chaque fois que le certificat TLS/SSL (Let's Encrypt) est mis à jour, renouvelé par acme.sh
(tout le 60 jours).
On va donc utiliser "nsupdate
" pour mettre à jour dynamiquement les champs d'enregistrement (RR) TLSA (DANE).
Je vous "pose" un exemple :
Script avec 25 lignes
001root@web:~ # vim /root/nsupdate-zw3b_fr.nsupdate
002;
003server dns.ipv10.net
004zone zw3b.fr
005;----------------------
006; UPDATE DANE
007; openssl x509 -noout -fingerprint -sha256 < /root/acme/data/zw3b.fr_ecc/zw3b.fr.cer | tr -d :
008; dig TLSA _443._tcp.zw3b.fr @dns.google +short
009; ------
010;
011update del _443._tcp.zw3b.fr. 3600 TLSA
012update add _443._tcp.zw3b.fr. 3600 IN TLSA 3 0 1 C1A68D384582BC4A88EC7DB3492678B1B6A6E088036FD90306F4F47AF5B7332D
013update del _443._tcp.www.zw3b.fr. 3600 TLSA
014update add _443._tcp.www.zw3b.fr. 3600 IN TLSA 3 0 1 C1A68D384582BC4A88EC7DB3492678B1B6A6E088036FD90306F4F47AF5B7332D
015update del _443._tcp.api.zw3b.fr. 3600 TLSA
016update add _443._tcp.api.zw3b.fr. 3600 IN TLSA 3 0 1 C1A68D384582BC4A88EC7DB3492678B1B6A6E088036FD90306F4F47AF5B7332D
017update del _443._tcp.howto.zw3b.fr. 3600 TLSA
018update add _443._tcp.howto.zw3b.fr. 3600 IN TLSA 3 0 1 C1A68D384582BC4A88EC7DB3492678B1B6A6E088036FD90306F4F47AF5B7332D
019update del _443._tcp.radio.zw3b.fr. 3600 TLSA
020update add _443._tcp.radio.zw3b.fr. 3600 IN TLSA 3 0 1 C1A68D384582BC4A88EC7DB3492678B1B6A6E088036FD90306F4F47AF5B7332D
021update del _443._tcp.mailing.zw3b.fr. 3600 TLSA
022update add _443._tcp.mailing.zw3b.fr. 3600 IN TLSA 3 0 1 C1A68D384582BC4A88EC7DB3492678B1B6A6E088036FD90306F4F47AF5B7332D
023;
024send
025;
Et on lance la commande, avec la clef autorisée (allow-update { key "nsupdate-key-zone"; };
), pour mettre à jour notre zone DNS.
Script avec 1 ligne
001root@web:~ # nsupdate -k /root/Knsupdate-key-zone.+157+09852.private /root/nsupdate-zw3b_fr.nsupdate
TODO : Il faut, donc "assembler tout çà" ou le faire sois-même en ligne de commande chaque fois que le certificat TLS/SSL Let's Encrypt change.
En passant dans le script :/root/acme-certif-date_verification.bash
; il faut vérifier que toutes les entitées (sous-domaine, ports, protocoles) "Suject Alt name" soient bien signées DANE et non pas seulement, sur le nom domainedomain.tld
entcp
sur le port443
.
Le principe du protocole de sécurité DANE (DNS-based Authentication of Named Entities ).
Bon courage.
Salutations,
Romain
WikipediA : Transport Layer Security
La Transport Layer Security (TLS) ou « Sécurité de la couche de transport », et son prédécesseur la Secure Sockets Layer (SSL) ou « Couche de sockets sécurisée »1, sont des protocoles de sécurisation des échanges par réseau informatique, notamment par Internet.
La TLS (ou SSL) fonctionne suivant un mode client-serveur. Il permet de satisfaire les objectifs de sécurité suivants :
- l'authentification du serveur ;
- la confidentialité des données échangées (ou session chiffrée) ;
- l'intégrité des données échangées ;
WikipediA - OpenSSL supporte un grand nombre d'Algorithmes :
- types de chiffrement : Advanced Encryption Standard (AES)
- types de cryptographie à clé publique :
Informations sur DigiCert : Qu'est-ce que SSL, TLS et HTTPS ?
Si vous utilisez un serveur DNS externes gèré par un hébergeur de nom de domaine, ci-dessous la documentation :
Acme.sh
: DNS-API-Dev-Guide
Wiki official acme.sh
:
Cyberciti.biz : How to issue Let’s Encrypt wildcard certificate with acme.sh and Cloudflare DNS