Pour que Traefik sache à qui il parle, il faut vérifier une identité dans chaque sens : exiger un certificat du client avec une option TLS clientAuth, et contrôler celui du backend avec un serversTransport qui désigne l'autorité de certification attendue. Cette leçon s'adresse à qui publie déjà un service derrière Traefik 3.7 et veut qu'une route sensible n'accepte que des appelants identifiés, au lieu de faire confiance à tout ce qui arrive et à tout ce qui répond. Elle apprend aussi à ne pas confondre une identité (qui est cet appelant) et une autorisation (ce qu'il a le droit de faire). Les noms d'options viennent de la documentation de Traefik 3.7 ; les comportements décrits viennent du lab de la formation et d'une lecture du code, sur Traefik 3.7.15.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »La leçon part d'un Traefik qui chiffre sans rien vérifier et arrive à un Traefik dont chaque refus est prouvé.
- Distinguer une identité d'une autorisation, et l'authentification du serveur de celle du client.
- Exiger un certificat client valide sur une route avec
clientAuth. - Faire vérifier le certificat d'un backend avec un
serversTransport. - Expliquer pourquoi
insecureSkipVerifydésactive la preuve au lieu de réparer l'erreur. - Restreindre la confiance accordée aux en-têtes
X-Forwarded-Forau seul proxy amont. - Prouver un refus par le code HTTP et le code de sortie de
curl, et renouveler une autorité sans couper les accès.
Prérequis
Section intitulée « Prérequis »Cette leçon traite des identités, pas de l'obtention du certificat du serveur ni de la protection par mot de passe, déjà couvertes ailleurs.
- Savoir écrire une route dans un fichier dynamique : Traefik avec le fournisseur fichier et Construire et vérifier des règles de routage.
- Connaître le certificat du serveur et son émission : Traefik et HTTPS automatique. La leçon ne redit pas ACME.
- Connaître les autres protections d'un point d'entrée, authentification par mot de passe, en-têtes et limitation de débit : Protéger le point d'entrée Traefik.
- Savoir lire un certificat avec
openssl: Diagnostic TLS. - Pour le lab : le poste fourni, avec Docker, et un accès
sudo.
Qu'est-ce qu'une identité, et en quoi diffère-t-elle d'une autorisation ?
Section intitulée « Qu'est-ce qu'une identité, et en quoi diffère-t-elle d'une autorisation ? »Une identité répond à la question « qui es-tu ? », une autorisation à la question « as-tu le droit de faire cela ? », et un certificat ne prouve que la première. Un certificat est un document numérique qui lie un nom à une clé cryptographique. Il est signé par une autorité de certification (CA, Certificate Authority), dont la signature garantit ce lien. Celui qui reçoit un certificat contrôle la chaîne (le certificat a-t-il été signé par une autorité que je me suis choisie comme référence ?), la date de validité, et que son interlocuteur détient bien la clé privée associée.
Si ces contrôles passent, le receveur connaît l'identité de son interlocuteur. Il ne sait pas encore ce qu'il doit lui permettre, car l'autorisation est une autre décision. Pensez au badge d'un immeuble : un badge authentique prouve que vous êtes salarié, il n'ouvre pas pour autant la salle des serveurs. Chez Traefik, un certificat client signé par la bonne autorité fait admettre la connexion ; ce que son porteur peut ensuite demander se décide ailleurs, dans le routage, dans les protections de la route et dans l'application.
Deux mécanismes distincts se cachent derrière le mot « TLS ». L'authentification du serveur est celle de tout HTTPS : le client vérifie le certificat du serveur. L'authentification du client est l'inverse : le serveur exige un certificat et le vérifie. Quand les deux ont lieu, on parle de mTLS (mutual TLS, authentification mutuelle). Chaque sens a son propre certificat, sa propre autorité et sa propre configuration : régler l'un ne règle pas l'autre.
Quelles sont les deux directions de vérification derrière Traefik ?
Section intitulée « Quelles sont les deux directions de vérification derrière Traefik ? »Traefik tient deux connexions TLS indépendantes, une avec le client et une avec le backend, et chacune a sa vérification, dans un sens différent. Côté client, Traefik est le serveur : il peut exiger un certificat de l'appelant, avec une option TLS. Côté backend, Traefik est le client : il peut vérifier le certificat que le backend lui présente, avec un serversTransport, le bloc de configuration qui décrit comment Traefik se connecte aux serveurs d'un service.
Le schéma ci-dessous place les deux sens côte à côte. Regardez les deux encadrés mis en avant : ce sont les deux endroits de la configuration où se décident les vérifications de certificat. Les flèches pointillées montrent comment un refus se manifeste : pendant la poignée de main TLS (l'échange initial qui établit la connexion chiffrée) pour le client, par une réponse d'erreur de Traefik pour le backend.
Une troisième question n'est pas une affaire de certificat mais de confiance : qui croire quand une requête annonce son adresse d'origine dans un en-tête X-Forwarded-For ? Elle concerne aussi une identité, celle que l'appelant annonce, mais par un autre mécanisme : l'adresse source de la connexion, pas un certificat. Le trajet complet d'une requête est décrit dans Publier un service web.
Comment exiger un certificat client sur une route ?
Section intitulée « Comment exiger un certificat client sur une route ? »On déclare dans la configuration dynamique une option TLS dont la section clientAuth désigne l'autorité des clients (caFiles) et le niveau d'exigence (clientAuthType: RequireAndVerifyClientCert), puis on la rattache au router (la règle de routage qui oriente les requêtes vers un service). Le fichier de caFiles doit contenir les seules autorités qui signent les certificats clients : ni celle du certificat serveur, ni celle des backends. C'est une règle de prudence, pas une contrainte de Traefik : les mélanger fabriquerait une chaîne de confiance que personne n'a décidée.
Voici la forme de l'option et de son rattachement au router, avec des noms neutres. Cet extrait n'a pas été rejoué tel quel pour cette page : c'est le lab qui en fait mesurer le comportement.
tls: options: clients-internes: clientAuth: caFiles: - /etc/traefik/pki/ca-clients.crt clientAuthType: RequireAndVerifyClientCert
http: routers: facturation: rule: Host(`facturation.corp.test`) entryPoints: - websecure tls: options: clients-internes@file service: facturationLe niveau d'exigence est le réglage qui trompe. La documentation de Traefik 3.7 définit cinq valeurs pour clientAuthType, et une seule remplit toutes les conditions d'un vrai contrôle :
| Valeur | Ce que Traefik fait |
|---|---|
NoClientCert | Ignore tout certificat client |
RequestClientCert | Demande un certificat, continue s'il n'y en a pas |
RequireAnyClientCert | Exige un certificat, sans vérifier qui l'a signé |
VerifyClientCertIfGiven | Vérifie le certificat s'il y en a un, continue sinon |
RequireAndVerifyClientCert | Exige un certificat signé par une autorité de caFiles |
Le piège est que caFiles peut être présent sans rien exiger : avec NoClientCert, la configuration ressemble à du mTLS et laisse entrer tout le monde. RequireAnyClientCert est à peine meilleur : il exige un certificat, mais un certificat fabriqué par n'importe qui passe, donc l'identité n'est pas prouvée. Seule RequireAndVerifyClientCert refuse les trois cas qui doivent l'être : l'absence de certificat, une autorité étrangère et un certificat expiré, ce que le test du lab contrôle. VerifyClientCertIfGiven convient à une route ouverte à tous qui reconnaît ceux qui se présentent, sans rien accorder de sensible.
Pourquoi un certificat client valide ne donne-t-il pas tous les droits ?
Section intitulée « Pourquoi un certificat client valide ne donne-t-il pas tous les droits ? »Parce que la vérification répond seulement « cette connexion vient d'un porteur reconnu », et que la décision d'accès se prend à un autre niveau. Deux illustrations le montrent. La première vient du lab : un reverse proxy (un serveur placé devant Traefik, qui relaie les requêtes) se présente avec son propre certificat client, signé par la même autorité que celui d'un utilisateur. Les deux sont admis, mais Traefik croit l'adresse annoncée par le proxy et non celle annoncée par un utilisateur direct. Cette différence se décide sur l'adresse source de la connexion (le réglage trustedIPs, expliqué plus bas), pas sur le certificat : deux identités vérifiées, mais des autorisations différentes.
La seconde est la portée. Une option TLS s'applique aux routers qui la référencent, et tout porteur d'un certificat de cette autorité atteint toutes ces routes. Si deux populations ne doivent pas se mélanger, par exemple l'exploitation et un partenaire externe, elles ne partagent ni autorité ni option : on déclare une option par population. Ce choix est un jugement de conception, pas une règle de Traefik.
Pour les autres niveaux de décision, comme le filtrage d'adresse, l'authentification déléguée ou la limitation de débit, Protéger le point d'entrée Traefik les décrit. Le principe du mTLS entre services est présenté dans mTLS pod-to-pod.
Comment Traefik vérifie-t-il le certificat d'un backend ?
Section intitulée « Comment Traefik vérifie-t-il le certificat d'un backend ? »On déclare un serversTransport qui désigne l'autorité du backend dans rootCAs, et on le référence dans le service, dont les serveurs sont joints en https://. Sans cela, Traefik peut parler TLS à son backend sans jamais contrôler à qui. Voici la forme du transport et de sa référence dans le service, avec des noms neutres : cet extrait n'a pas été rejoué tel quel pour cette page.
http: serversTransports: verif-facturation: rootCAs: - /etc/traefik/pki/ca-backends.crt serverName: facturation.corp.test services: facturation: loadBalancer: serversTransport: verif-facturation servers: - url: https://facturation.interne:8443Les deux options ont chacune un rôle. D'après la documentation de Traefik 3.7, rootCAs est l'ensemble des autorités à utiliser pour vérifier les certificats des serveurs, et serverName configure le nom utilisé comme SNI (Server Name Indication, le nom d'hôte que le client annonce au début de la poignée de main pour que le serveur choisisse le bon certificat).
Le nom compte autant que l'autorité. Absent, serverName laisse Traefik comparer le nom du certificat à l'hôte de l'URL du backend. Posé, il remplace cet hôte : sur Traefik 3.7.15, un serverName différent du nom du certificat fait échouer la connexion amont. L'option sert donc quand le nom de l'adresse du backend n'est pas celui que porte son certificat ; dans le lab, l'adresse porte déjà le nom de son certificat, ce qui la rend superflue.
Une autre précision vient du code de Traefik 3.7.15 : dès que rootCAs est renseigné, Traefik ne fait confiance qu'aux autorités listées, et les autorités du système ne s'y ajoutent pas. Sans rootCAs, ce sont elles qui servent : c'est le comportement par défaut.
Le fichier de rootCAs suit la même prudence que celui des clients : une autorité par rôle, ici celle des backends et non celle des clients. Un serversTransport s'applique à tous les services qui le référencent : un transport par famille de backends évite qu'une autorité acceptée pour l'un le soit aussi pour l'autre.
La vérification se prouve par un refus. Le lab place derrière une seconde route un backend dont le certificat est signé par une autorité sans rapport. Interroger le bon backend ne montre rien, puisque la réponse est un succès avec ou sans contrôle : le test qui compte est celui du mauvais backend, qui doit échouer.
Pourquoi insecureSkipVerify n'est-il pas une correction ?
Section intitulée « Pourquoi insecureSkipVerify n'est-il pas une correction ? »insecureSkipVerify: true supprime la vérification de la chaîne et du nom du backend : la liaison reste chiffrée, mais Traefik ne sait plus à qui il parle. La documentation de Traefik 3.7 décrit cette option comme celle qui contrôle si la chaîne de certificats du serveur et son nom d'hôte sont vérifiés ; sa valeur par défaut est false. Passer à true est le réflexe quand une connexion vers un backend échoue sur une erreur de certificat, et c'est un mauvais réflexe : l'erreur disparaît parce que la preuve disparaît.
Voici le contre-exemple, tel qu'on le rencontre dans une configuration héritée :
# ❌ À éviter : le certificat du backend n'est plus jamais regardéhttp: serversTransports: verif-facturation: insecureSkipVerify: trueAvec cette ligne, un backend qui présente le mauvais certificat reçoit le trafic et répond comme le bon. Aucune erreur ne s'affiche, ce qui est le vrai danger : une chaîne de confiance débranchée ressemble à une chaîne qui fonctionne. Même constat avec HAProxy dans Vérifier l'identité du backend et de la source, où verify none joue le même rôle.
La démarche correcte est de chercher pourquoi la vérification échoue. Trois causes fréquentes se vérifient avec openssl : l'autorité de rootCAs n'est pas celle qui a signé le backend, le nom du certificat ne correspond pas au nom visé, ou le certificat est expiré.
openssl verify -CAfile ca-backends.crt backend.crtopenssl x509 -in backend.crt -noout -subject -issuer -dates -ext subjectAltNameLa première commande doit répondre OK si l'autorité signe bien le certificat. La seconde affiche l'émetteur, les dates de validité et les noms que le certificat déclare (le champ subjectAltName, la liste des noms pour lesquels il est valable). L'option -ext de openssl x509 demande OpenSSL 1.1.1 ou plus récent ; les deux commandes ont été rejouées avec OpenSSL 3.0.13. Corrigez la cause trouvée dans le serversTransport, jamais en retirant le contrôle.
Comment empêcher un appelant direct de forger son adresse ?
Section intitulée « Comment empêcher un appelant direct de forger son adresse ? »On limite forwardedHeaders.trustedIPs du point d'entrée à l'adresse du seul proxy amont, de sorte que Traefik n'accorde aucun crédit aux en-têtes X-Forwarded-* envoyés par un autre appelant. Quand un proxy est placé devant Traefik, l'adresse source vue par Traefik est celle du proxy ; celle du vrai client voyage dans l'en-tête X-Forwarded-For. Mais un en-tête est du texte : un appelant qui contacte Traefik directement peut y écrire n'importe quelle adresse, et l'application derrière, qui lit cet en-tête pour décider (journal, filtrage, quotas), croirait une identité inventée.
Les deux réglages se posent sur le point d'entrée, donc dans la configuration statique (lue une seule fois au démarrage, à la différence de la configuration dynamique, rechargée à chaud). D'après la documentation de Traefik 3.7, trustedIPs liste les adresses ou plages depuis lesquelles Traefik fait confiance à ces en-têtes, et insecure les croit toujours, ce que la documentation recommande de réserver aux tests.
entryPoints: websecure: address: ":8443" forwardedHeaders: trustedIPs: - "10.0.0.10/32" # le proxy amont, et lui seulL'erreur classique est 0.0.0.0/0 (toutes les adresses IPv4) dans trustedIPs : elle fait confiance à tout appelant IPv4, un effet proche de insecure: true. Cette plage ne couvre pas les adresses IPv6 natives, qui demandent ::/0 pour le même effet ; la nuance n'excuse pas l'erreur. Une plage trop large, un sous-réseau entier quand un seul hôte relaie, relève du même défaut. Le changement exige un redémarrage de Traefik, parce que la configuration statique n'est lue qu'au démarrage.
La vérification a deux faces, et la seconde est celle qu'on oublie. Une requête directe qui porte un X-Forwarded-For forgé doit arriver au backend sans l'adresse forgée ; une requête relayée par le proxy autorisé doit toujours atteindre le backend. Sans la seconde mesure, supprimer le proxy passerait pour un durcissement. Le lab contrôle les deux avec un backend témoin qui renvoie ce qu'il a reçu, pas avec la configuration de Traefik.
Comment renouveler les certificats sans couper les accès ?
Section intitulée « Comment renouveler les certificats sans couper les accès ? »On remplace une autorité par étapes, parce que caFiles accepte une liste : l'ancienne et la nouvelle cohabitent le temps de réémettre les certificats, puis l'ancienne est retirée. Un certificat expire (ceux du lab sont émis pour 30 jours, hors le certificat expiré à dessein), et une autorité peut aussi être remplacée. Un renouvellement qui met tout le monde dehors est une panne ; celui qui honore encore l'ancienne autorité une fois terminé n'a rien retiré. Les deux se mesurent.
La séquence que je recommande est un jugement de méthode, pas une obligation de Traefik : ajouter la nouvelle autorité à côté de l'ancienne, réémettre les certificats clients, vérifier qu'un certificat signé par la nouvelle est accepté, puis retirer l'ancienne et vérifier qu'un certificat qu'elle avait signé est refusé. Le test du lab fait une variante plus brutale : il remplace l'autorité d'un coup, constate que le certificat de la nouvelle passe et que celui de l'ancienne est refusé, puis restaure l'état d'origine.
Un détail de mise en œuvre, vérifié dans le code et par un essai sur Traefik 3.7.15 : le fournisseur fichier surveille le répertoire de configuration dynamique et les fichiers qu'il contient, pas le fichier d'autorité cité par son chemin. Remplacer le fichier d'autorité seul ne change rien : l'ancienne autorité reste honorée et la nouvelle refusée, tant que rien n'est modifié dans le répertoire surveillé. Pour que Traefik relise l'autorité remplacée, le test modifie le fichier de routes surveillé, ce qui force la relecture. L'automatisation de l'émission des certificats internes relève d'une autorité de gestion comme Vault PKI.
Comment prouver qu'un refus est un vrai refus ?
Section intitulée « Comment prouver qu'un refus est un vrai refus ? »Un refus se prouve avec deux valeurs : le code HTTP et le code de sortie de curl, parce que plusieurs situations sans rapport donnent « autre chose que 200 ». Un code différent de 200 peut signifier un refus TLS (ce qu'on cherche), un 404 renvoyé par Traefik (la route n'existe pas, le contrôle n'a jamais eu lieu) ou 000 (aucune réponse : service éteint, fichier de certificat illisible). Le test du lab écarte ces causes une à une.
curl -k -s -o /dev/null -w '%{http_code}\n' --max-time 5 \ --cert client.crt --key client.key \ https://facturation.corp.test:8443/ ; echo "curl : $?"L'option -k ne concerne que le certificat auto-signé du serveur de Traefik, un autre contrôle que ceux de la leçon. Lisez les deux lignes. Avec un certificat valide, 200 et curl : 0 : le contrôle laisse passer ce qu'il doit laisser passer, et cette mesure sert d'ancrage, sans elle un service éteint passerait pour un refus partout. Sans certificat, avec celui d'une autre autorité ou avec un certificat expiré, le refus se produit pendant la poignée de main : curl sort avec un code d'erreur non nul, sans réponse HTTP applicative (55 ou 56 dans nos essais sur Traefik 3.7.15 : avec TLS 1.3, le client ne voit l'alerte du serveur qu'en lisant la réponse). Si curl sort à 0 avec un 403 ou un 404, la connexion TLS a abouti : le certificat a été accepté, ce n'est pas un refus de certificat.
Pour le backend, la preuve est différente : le mauvais backend doit faire répondre Traefik par une erreur 5xx. Un 404 ne prouve rien (la requête n'a pas atteint le backend), et un 200 signifie que la vérification est encore désactivée. Lire la réponse de Traefik pour distinguer un 502 d'un 504 est décrit dans Dépanner un point d'entrée Traefik.
Mettre en pratique
Section intitulée « Mettre en pratique »Le lab part d'un Traefik mal réglé en trois points : l'option TLS référence l'autorité des clients mais n'exige aucun certificat, le transport vers le backend a la vérification désactivée, et le point d'entrée croit les en-têtes de n'importe quelle adresse. Vous corrigez la configuration dynamique et la configuration statique, puis la validation mesure quatre choses : un certificat client valide passe alors que l'absence de certificat, une autorité étrangère et un certificat expiré sont refusés pendant la poignée de main ; le backend au mauvais certificat fait répondre Traefik en 5xx pendant que le bon répond 200 ; un X-Forwarded-For forgé n'atteint pas le backend alors que le proxy amont autorisé continue de passer ; un renouvellement de l'autorité des clients accepte la nouvelle et refuse l'ancienne.
À retenir
Section intitulée « À retenir »Une vérification d'identité se prouve par ses refus, pas par la présence d'une option dans un fichier.
- Un certificat prouve une identité ; l'autorisation se décide ailleurs, et deux porteurs valides peuvent avoir des droits différents.
- L'authentification du serveur et celle du client sont deux mécanismes séparés, chacun avec son certificat et son autorité.
- Le client se vérifie avec une option TLS :
clientAuth,caFilesetclientAuthType: RequireAndVerifyClientCert.NoClientCertne demande rien etRequireAnyClientCertne vérifie pas le signataire. - Le backend se vérifie avec un
serversTransport:rootCAsdésigne l'autorité attendue,serverNamele nom annoncé en SNI. insecureSkipVerify: trueretire la preuve au lieu de réparer l'erreur : cherchez l'autorité, le nom ou la date en cause.forwardedHeaders.trustedIPsse limite à l'adresse du proxy amont ; la configuration statique impose un redémarrage.- Un refus se prouve par le code HTTP et par le code de sortie de
curl, avec un cas valide en ancrage. - Un renouvellement d'autorité se mesure dans les deux sens : la nouvelle autorité passe, l'ancienne est refusée.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Huit questions vérifient que vous savez choisir la bonne vérification pour chaque sens, reconnaître une configuration qui ne vérifie rien et prouver un refus.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : Observer Traefik avec les journaux et métriques
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications