Toutes les ressources

Guide pratique · Traefik

Traefik sert le mauvais certificat : vérifier le SNI, les routeurs et ACME

Votre nom d’hôte pointe vers Traefik, mais le navigateur reçoit un certificat par défaut ou prévu pour un autre nom. Commencez par une nouvelle connexion TLS. Le certificat est choisi avant le routage HTTP. Une règle Host correcte ne prouve donc pas, à elle seule, que le certificat attendu est disponible.

Ce guide concerne Traefik v3 lorsqu’il termine la connexion HTTPS, avec des exemples Docker Compose et file provider. Remplacez example.com, 192.0.2.10, les chemins et les noms de services par les vôtres. Les commandes supposent Linux, Bash, OpenSSL et GNU timeout. Contrôlez uniquement les points de terminaison que vous gérez ou êtes autorisé à examiner. La démonstration locale a été testée avec Traefik 3.7.16.

1. Examiner le certificat avec le bon SNI

Exécutez la sonde depuis l’extérieur du réseau d’hébergement. Conservez le nom d’hôte dans -servername même si -connect utilise une adresse IP. Relevez l’empreinte SHA-256, l’émetteur, les dates de validité et les noms Subject Alternative Name. Cette commande affiche un certificat ; elle ne valide ni la confiance dans la chaîne ni la correspondance du nom d’hôte.

set -o pipefail
timeout 10 openssl s_client -connect example.com:443 \
  -servername example.com </dev/null |
  openssl x509 -noout -sha256 -fingerprint \
    -issuer -dates -ext subjectAltName

Un certificat par défaut peut indiquer qu’aucun certificat chargé ne correspond au SNI, ou que le client n’a pas envoyé de SNI. Si le contrôle strict du SNI est activé, Traefik peut refuser cette connexion. Si aucun certificat ne s’affiche, examinez l’erreur de connexion. Ajouter un en-tête HTTP Host ne change pas le certificat déjà choisi pendant la négociation TLS.

2. Vérifier le routeur HTTPS et son resolver de certificats

Pour une application Docker dont Traefik gère les certificats ACME, examinez les labels du conteneur applicatif en cours d’exécution. Le routeur doit utiliser le bon point d’entrée et activer TLS. La valeur certresolver doit désigner un resolver existant, sauf si celui-ci est hérité du point d’entrée. Ces labels sont un extrait à adapter à une application existante ; ils ne configurent ni son port de destination ni le provider Docker.

labels:
  - "traefik.http.routers.app.rule=Host(`example.com`)"
  - "traefik.http.routers.app.entrypoints=websecure"
  - "traefik.http.routers.app.tls=true"
  - "traefik.http.routers.app.tls.certresolver=letsencrypt"

Le resolver se déclare dans la configuration statique de Traefik. L’exemple de challenge HTTP ci-dessous déclare aussi les points d’entrée. Adaptez l’adresse de contact et le chemin du stockage persistant. Pour ce challenge, le port public 80 doit atteindre le point d’entrée web. Si vous utilisez une validation DNS ou un autre challenge, conservez la configuration correspondante.

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"
certificatesResolvers:
  letsencrypt:
    acme:
      email: [email protected]
      storage: /data/acme.json
      httpChallenge:
        entryPoint: web

Déclarer un resolver ne l’associe pas automatiquement à tous les routeurs. Une modification de la configuration statique demande un redémarrage de Traefik ; la configuration fournie par un provider peut être actualisée dynamiquement. Vérifiez la configuration active et les erreurs avant de redémarrer. Une règle HTTP Host peut fournir les noms à demander à ACME, tandis que le SNI sert à choisir le certificat présenté à chaque connexion TLS.

3. Distinguer un échec ACME d’un problème de sélection

Si Traefik obtient lui-même les certificats, consultez ses journaux récents. Dans cet exemple Compose, le service s’appelle traefik. Recherchez un resolver inconnu, un challenge échoué, un émetteur de test ou une erreur de droits sur le stockage. Traitez l’erreur signalée avant de demander à nouveau un certificat.

docker compose logs --since=30m traefik

Le fichier acme.json configuré contient des clés privées et les données du compte ACME. Gardez-le confidentiel, persistant lors du remplacement des conteneurs et accessible à Traefik avec les droits requis (600). Ne le supprimez pas pour tenter de réparer le problème et ne le partagez pas entre des instances Traefik actives simultanément. Un journal d’émission réussie atteste l’émission, pas le certificat servi par chaque adresse publique.

4. Pour les certificats sur fichiers, vérifier les chemins chargés

Suivez cette branche si un autre outil émet les certificats. Examinez tls.certificates dans la configuration dynamique par fichiers et vérifiez que certFile et keyFile existent à ces chemins dans le conteneur Traefik. Le certificat doit couvrir le nom demandé et correspondre à sa clé privée. L’exemple ci-dessous est un extrait de configuration dynamique, pas une installation Traefik complète.

tls:
  certificates:
    - certFile: /certs/example.com/fullchain.pem
      keyFile: /certs/example.com/privkey.pem

Activez le file provider avec watch: true dans la configuration statique. Pour que les notifications de fichiers fonctionnent avec un montage bind, montez le répertoire parent. La démonstration modifie la configuration dynamique pour désigner une nouvelle paire certificat/clé, puis remplace atomiquement le fichier de configuration. Après un renouvellement, vérifiez que Traefik a bien chargé la mise à jour ; remplacer un fichier sur disque ne prouve pas que le certificat servi a changé.

5. Reproduire un certificat par défaut en local

Le script téléchargeable lance Traefik sur 127.0.0.1 avec un port attribué automatiquement. Il crée des certificats autosignés pour fallback.test, unrelated.test et renewal.test. Au départ, seuls le certificat unrelated et celui de secours sont configurés. La sonde renewal.test reçoit celui de secours. Le script charge ensuite le bon certificat via le file provider et vérifie une nouvelle connexion, sans redémarrer Traefik.

Télécharger et examiner la démonstration Traefik

Prérequis : Linux, Bash, OpenSSL, GNU timeout et un moteur Docker local. Docker peut télécharger l’image épinglée. Lisez le script, puis lancez bash traefik-certificate-selection.sh. BEFORE montre l’empreinte de secours ; CONTROL montre le certificat unrelated sélectionné par son SNI ; AFTER montre le bon certificat. NO_SNI conserve le certificat de secours. Le script vérifie les empreintes et l’absence de changement de l’heure de démarrage du conteneur. Il supprime les clés temporaires et le conteneur à la sortie. Ce test porte sur la sélection et le chargement dynamique, pas sur l’émission ou le renouvellement ACME.

6. Contrôler les accès publics, puis surveiller

Testez chaque adresse publique pertinente en conservant le nom d’hôte comme SNI. Remplacez l’adresse d’exemple ci-dessous ; pour IPv6, utilisez [adresse]:443. Un CDN peut terminer TLS avant Traefik et présenter son propre certificat. Avec le passthrough TLS d’un routeur TCP, c’est le serveur en aval qui présente le certificat. Vérifiez le composant qui termine chaque connexion. Plusieurs instances, les chemins IPv4/IPv6 ou les négociations RSA/ECDSA peuvent donner des observations différentes.

set -o pipefail
timeout 10 openssl s_client -connect 192.0.2.10:443 \
  -servername example.com </dev/null |
  openssl x509 -noout -sha256 -fingerprint \
    -issuer -dates -ext subjectAltName

Nocert observe périodiquement les certificats servis par les points de terminaison TLS accessibles et évalue les règles d’alerte d’expiration lors d’un cycle quotidien. Vérifiez le point de terminaison et la date d’observation, puis configurez les destinataires des alertes. Cette surveillance complète la sonde externe immédiate. Nocert ne configure pas votre resolver Traefik, ne renouvelle pas les certificats et ne garantit pas que chaque visiteur reçoive le même certificat.

Sources techniques