Après les précédents articles consacrés à Cloudflare et à sa mise en place, nous allons poursuivre avec l’authentification mTLS.
Qu’est-ce que l’authentification mTLS ?
L’authentification mTLS (Mutual TLS) est une extension du protocole TLS classique dans laquelle le client et le serveur présentent chacun un certificat afin de s’authentifier mutuellement.
Contrairement au HTTPS standard, où seul le serveur est authentifié auprès du client, le mTLS ajoute une vérification du client par le serveur. Cela permet de garantir que seules des entités autorisées peuvent accéder à une ressource.
Ce mécanisme est particulièrement utilisé pour :
- sécuriser des API internes,
- protéger des endpoints sensibles (metrics, administration, etc.),
- mettre en place une authentification forte entre services (machine-to-machine).
Contexte
Dans mon cas, j’ai plusieurs services qui exposent des métriques que je souhaite scraper depuis mon NAS afin de les visualiser dans Grafana.
Les applications tournant sur plusieurs ports, j’utilise Apache comme reverse proxy.
Afin de ne pas exposer ces métriques publiquement, j’avais mis en place une authentification par certificat, fonctionnelle avant la migration vers Cloudflare.
Avant cette migration, Prometheus et Apache communiquaient directement et s’échangeaient leurs certificats afin de s’authentifier mutuellement.
Passage à Cloudflare
Une fois basculé sous Cloudflare, l’architecture évolue légèrement :
- une authentification mTLS est mise en place entre Prometheus et Cloudflare,
- l’authentification de Cloudflare auprès de mon serveur web est déléguée à une chaîne de certificats (Authenticated Origin Pulls).
Cette partie ayant déjà été détaillée dans un précédent article, nous allons ici nous concentrer sur la mise en place du mTLS entre une application (Prometheus) et Cloudflare.
Je ne me suis pas compliqué la tâche avec du BYOC (Bring Your Own Certificate) et j’ai utilisé les certificats clients fournis par Cloudflare.
Il suffit de définir le périmètre (le ou les domaines concernés) pour lesquels ce certificat sera valide.

Ensuite, il faut mettre en place une règle de sécurité afin de forcer l’authentification mTLS sur le ou les endpoints concernés.

Une fois cette configuration appliquée, le domaine n’est plus accessible directement sans authentification : toute requête doit présenter un certificat valide.
Configuration côté Prometheus
Côté Prometheus, j’ai récupéré la clé privée et le certificat (format PEM) afin de les intégrer dans la configuration du scraper.
scrape_configs:
# crowdsec
- job_name: "crowdsec_axanar"
scrape_interval: 60s
metrics_path: /crowdsec
scheme: https
tls_config:
cert_file: ../tls/cloudflared.pem
key_file: ../tls/cloudflared.key
static_configs:
- targets: ["metrics.domain.ltd"]
labels:
host: "server.domain.ltd"
network: "domain.ltd"
type: "server"
container: "no"
relabel_configs:
- source_labels: [__name__]
regex: "(.*)"
replacement: "crowdsec"
target_label: job
# node_exporter
- job_name: "node_exporter_axanar"
scheme: https
tls_config:
cert_file: ../tls/cloudflared.pem
key_file: ../tls/cloudflared.key
static_configs:
- targets: ["metrics.domain.ltd"]
labels:
host: "server.domain.ltd"
network: "domain.ltd"
type: "server"
container: "no"
relabel_configs:
- source_labels: [__name__]
regex: "(.*)"
replacement: "node_exporter"
target_label: job
# postfix
- job_name: "postfix_axanar"
scrape_interval: 60s
metrics_path: /postfix
scheme: https
tls_config:
cert_file: ../tls/cloudflared.pem
key_file: ../tls/cloudflared.key
static_configs:
- targets: ["metrics.domain.ltd"]
labels:
host: "server.domain.ltd"
network: "domain.ltd"
type: "server"
container: "no"
relabel_configs:
- source_labels: [__name__]
regex: "(.*)"
replacement: "postfix"
target_label: job
Résultat
À présent, j’ai un accès à mes métriques depuis mon NAS, sécurisé par une authentification mutuelle.
Seuls les clients disposant d’un certificat valide peuvent interroger les endpoints exposés, ce qui réduit fortement la surface d’attaque.







