Let's Encrypt : Certificats TLS automatises avec DNS-01 et TSIG

Rôle dans l'architecture

Les certificats TLS sécurisent tous les services exposés du homelab. Le renouvellement est entièrement automatisé par le défi DNS-01 : le client ACME prouve la propriété du domaine en créant un enregistrement TXT dans la zone, que l'autorité vient vérifier.

Flux de renouvellement

sequenceDiagram
    actor Admin
    participant Certbot as Client ACME
    participant BIND9 as Resolveur DNS
    participant LE as Autorite de certification
    participant HAP as Terminaison TLS
    Admin->>Certbot: demande de certificat
    activate Certbot
    Certbot->>BIND9: nsupdate signe TSIG
    Note over BIND9: cree l enregistrement de defi
    Certbot->>LE: demande de validation
    activate LE
    LE->>BIND9: interrogation TXT du defi
    BIND9-->>LE: reponse
    LE-->>Certbot: certificat delivre
    deactivate LE
    Certbot->>BIND9: nsupdate supprime le defi
    Certbot->>HAP: depot du fichier PEM
    deactivate Certbot

Pourquoi DNS-01 plutôt que HTTP-01

Le défi HTTP-01 exige que le serveur web soit joignable depuis Internet sur le port 80. Dans une architecture à plusieurs couches — terminaison TLS, routage applicatif, pare-feu applicatif, backend — il faudrait ouvrir un chemin ACME à travers chacune d'elles, et le maintenir ouvert.

Le défi DNS-01 déplace le problème là où il est déjà résolu : seul le serveur DNS doit être joignable depuis l'extérieur, ce qui est le cas par construction. Aucune couche HTTP n'a besoin de connaître ACME.

Une politique de mise à jour restreinte au défi

La zone publique n'autorise les mises à jour dynamiques que sur les enregistrements de défi, et pour aucun autre nom :

zone "jbsky.fr" {
    type master;
    file "/etc/bind/db.jbsky.fr";
    update-policy {
        grant tsig-key name _acme-challenge.jbsky.fr. TXT;
        grant tsig-key name _acme-challenge.www.jbsky.fr. TXT;
        grant tsig-key name _acme-challenge.mail.jbsky.fr. TXT;
        grant tsig-key name _acme-challenge.home.jbsky.fr. TXT;
    };
};

C'est le point qui limite les dégâts en cas de fuite de la clé : elle ne permet d'écrire que des enregistrements de défi, pas de détourner un nom de service.

L'interaction avec les vues, qui n'est pas évidente

Le résolveur est en split-horizon : il sert une vue différente selon le sous-réseau du client. Une mise à jour signée arrivant du réseau interne tomberait donc dans une vue qui n'a pas la politique de mise à jour, et se verait refusée.

La parade tient dans la sélection des clients : les vues par sous-réseau excluent explicitement les requêtes signées, ce qui fait tomber toute mise à jour signée dans la vue publique — la seule qui sait quoi en faire. L'architecture de vues est détaillée dans le DNS split-horizon.

Une clé de signature éphémère

flowchart LR
    gen["Generation<br/>cle aleatoire"] --> val["Validation<br/>configuration et zones"]
    val --> dep["Deploiement<br/>cote resolveur"]
    dep --> inj["Injection<br/>cote client ACME"]
    style gen fill:#4a9,color:#fff
    style inj fill:#e74,color:#fff

La clé de signature est régénérée à chaque exécution du pipeline et n'est jamais stockée dans le dépôt. Elle est déposée en même temps des deux côtés — le résolveur qui l'accepte, le client qui l'utilise.

La conséquence opérationnelle vaut d'être dite : en cas de suspicion de compromission, il n'y a pas de procédure de rotation à écrire, un simple déclenchement du pipeline remplace la clé. La rotation n'est pas une opération exceptionnelle, c'est le fonctionnement normal.

Le fichier journal des mises à jour dynamiques

Une zone qui reçoit des mises à jour dynamiques s'accompagne d'un fichier journal posé à côté d'elle. Il fait partie de l'état de la zone, pas des artefacts temporaires.

Le synchroniser en même temps que la zone est donc obligatoire : l'exclure laisse le résolveur avec une zone et un journal qui décrivent deux instants différents, et la mise à jour suivante échoue.

L'ordre d'ajout d'un domaine n'est pas commutatif

C'est le piège qui coûte le plus cher, parce qu'il ne casse pas le nouveau domaine — il casse tous les autres.

La terminaison TLS refuse catégoriquement de démarrer si un fichier PEM référencé dans sa liste de certificats n'existe pas. Ajouter la référence avant d'avoir produit le certificat met donc l'ensemble des sites hors ligne, pas seulement celui qu'on ajoutait.

flowchart TB
    A["DNS : enregistrement et autorisation de defi"] --> B["Declarer le domaine cote client ACME"]
    B --> C["Deployer la configuration"]
    C --> D["Generer le certificat"]
    D --> E{"Le PEM existe-t-il vraiment ?"}
    E -->|"Non"| D
    E -->|"Oui"| F["Seulement alors : referencer dans la terminaison TLS"]
    F --> G["Deployer"]
    style E fill:#f90,color:#fff
    style F fill:#4a9,color:#fff

La vérification du losange n'est pas une précaution de style : c'est la seule étape qui empêche une panne globale à partir d'un ajout anodin.

Certificats gérés

Certificat Domaines Renouvellement
principal le domaine racine, le www et le service de messagerie 1er et 15 du mois
domotique le sous-domaine de la domotique 8 et 22 du mois

Les dates sont décalées volontairement : deux renouvellements qui échoueraient pour la même raison ne tombent pas le même jour, ce qui laisse une fenêtre pour s'en apercevoir.


Liens

Articles connexes