Introduction : Le problème de l'exposition des services auto-hébergés
Quiconque a déjà tenté d'héberger un service web chez soi ou derrière un réseau d'entreprise connaît le casse-tête : ouvrir des ports sur le routeur, configurer le port forwarding, obtenir une adresse IP publique fixe, gérer les certificats SSL, se protéger contre les attaques DDoS, et prier pour que le FAI ne bloque pas les ports 80 et 443. Sans oublier le problème croissant du CGNAT (Carrier-Grade NAT), où votre FAI ne vous attribue même pas d'IP publique dédiée.
Cloudflare Tunnel (anciennement Argo Tunnel) résout tous ces problèmes d'un seul coup. Ce service gratuit permet d'exposer vos services locaux sur Internet de manière sécurisée, sans ouvrir le moindre port sur votre pare-feu. C'est une véritable révolution pour les homelabs, les développeurs et les petites entreprises.
Architecture en un coup d'œil

Dans cet article complet, nous allons explorer Cloudflare Tunnel en profondeur : son fonctionnement, son installation, sa configuration avancée, son intégration avec Cloudflare Access (Zero Trust), et sa comparaison avec les alternatives comme Tailscale Funnel, ngrok et frp.
Qu'est-ce que Cloudflare Tunnel ?
Le concept
Cloudflare Tunnel est un service qui crée un tunnel chiffré sortant depuis votre serveur vers le réseau edge de Cloudflare. Au lieu d'ouvrir des ports entrants sur votre pare-feu (ce qui expose votre réseau), c'est votre serveur qui initie la connexion vers Cloudflare. Le trafic des visiteurs arrive sur Cloudflare, traverse le tunnel chiffré, et atteint votre service local.
Le principe est simple mais puissant :
- Vous installez cloudflared (le daemon client) sur votre serveur local
- cloudflared établit une connexion sortante chiffrée (QUIC/HTTP2) vers les datacenters Cloudflare les plus proches
- Vous configurez des règles de routage (ingress rules) qui associent des noms de domaine à vos services locaux
- Cloudflare gère le DNS, le SSL/TLS, la protection DDoS et le reverse proxy
- Les visiteurs accèdent à vos services via votre nom de domaine, sans jamais connaître votre IP
Pourquoi c'est révolutionnaire
Cloudflare Tunnel change fondamentalement la donne pour plusieurs raisons :
- Pas de port forwarding : aucun port à ouvrir sur votre routeur ou pare-feu
- Pas d'IP publique nécessaire : fonctionne même derrière un CGNAT, un réseau d'entreprise ou un VPN
- HTTPS automatique : Cloudflare gère les certificats SSL/TLS pour vous, gratuitement
- Protection DDoS : le trafic passe par le réseau Cloudflare qui filtre les attaques
- IP masquée : votre adresse IP réelle n'est jamais exposée aux visiteurs
- DNS automatique : les enregistrements DNS CNAME sont créés automatiquement
- Gratuit : le service de base est entièrement gratuit, sans limitation de bande passante
- Zero Trust : intégration native avec Cloudflare Access pour ajouter de l'authentification
Architecture technique
Techniquement, cloudflared maintient quatre connexions persistantes vers au moins deux datacenters Cloudflare différents. Cela assure la haute disponibilité : si un datacenter a un problème, le trafic est automatiquement basculé. Les connexions utilisent le protocole QUIC (avec fallback HTTP/2) pour des performances optimales.
Le tunnel fonctionne en mode "named tunnel", ce qui signifie que chaque tunnel a un identifiant unique (UUID) et peut être associé à plusieurs noms de domaine et services. Un seul tunnel peut exposer des dizaines de services différents grâce aux ingress rules.
Prérequis
Créer un compte Cloudflare (gratuit)
Avant tout, vous avez besoin d'un compte Cloudflare et d'un nom de domaine géré par Cloudflare :
- Rendez-vous sur dash.cloudflare.com/sign-up et créez un compte gratuit
- Ajoutez votre nom de domaine à Cloudflare en suivant l'assistant
- Modifiez les nameservers de votre domaine chez votre registrar pour pointer vers ceux de Cloudflare
- Attendez la propagation DNS (quelques minutes à quelques heures)
Le plan Free de Cloudflare est largement suffisant pour utiliser les tunnels. Il n'y a pas de limite de bande passante sur les tunnels, même sur le plan gratuit.
Prérequis serveur
- Un serveur (physique, VM, Raspberry Pi, NAS...) avec un accès Internet sortant
- Les services que vous souhaitez exposer doivent être accessibles localement (ex:
http://localhost:8080) - Docker (optionnel mais recommandé) ou accès root pour l'installation native
Installer cloudflared
Installation sur Linux (Debian/Ubuntu)
# Méthode 1 : Via le dépôt APT officiel de Cloudflare
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | \
sudo tee /usr/share/keyrings/cloudflare-main.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt update
sudo apt install -y cloudflared
# Vérifier l'installation
cloudflared --version
# cloudflared version 2025.x.x# Méthode 2 : Téléchargement direct du binaire
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \
-o cloudflared
chmod +x cloudflared
sudo mv cloudflared /usr/local/bin/
# Pour ARM64 (Raspberry Pi 4/5)
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64 \
-o cloudflaredInstallation sur macOS
# Via Homebrew
brew install cloudflared
# Vérifier
cloudflared --versionInstallation via Docker
# Utiliser l'image officielle
docker pull cloudflare/cloudflared:latest
# Vérifier
docker run --rm cloudflare/cloudflared:latest --versionCréer un tunnel : méthode CLI
Étape 1 : Authentification
La première étape consiste à authentifier cloudflared avec votre compte Cloudflare :
# Lancer l'authentification
cloudflared tunnel loginCette commande ouvre votre navigateur sur une page Cloudflare où vous devez sélectionner le domaine à utiliser. Une fois autorisé, un fichier de certificat (cert.pem) est téléchargé dans ~/.cloudflared/. Ce certificat permet à cloudflared de gérer les tunnels et les DNS pour ce domaine.
Étape 2 : Créer le tunnel
# Créer un tunnel nommé
cloudflared tunnel create mon-homelab
# Résultat :
# Tunnel credentials written to /home/user/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json
# Created tunnel mon-homelab with id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# Lister les tunnels existants
cloudflared tunnel list
# Résultat :
# ID NAME CREATED CONNECTIONS
# xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx mon-homelab 2025-01-15T10:30:00Z Notez l'UUID du tunnel (le long identifiant) : vous en aurez besoin pour la configuration.
Étape 3 : Configurer les routes DNS
# Associer un sous-domaine au tunnel
cloudflared tunnel route dns mon-homelab app.mondomaine.fr
# Cela crée automatiquement un enregistrement DNS CNAME :
# app.mondomaine.fr -> xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.cfargotunnel.com
# Vous pouvez ajouter plusieurs sous-domaines
cloudflared tunnel route dns mon-homelab grafana.mondomaine.fr
cloudflared tunnel route dns mon-homelab portainer.mondomaine.fr
cloudflared tunnel route dns mon-homelab wiki.mondomaine.frÉtape 4 : Créer le fichier de configuration
Créez le fichier de configuration ~/.cloudflared/config.yml :
# ~/.cloudflared/config.yml
tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /home/user/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json
# Configuration du protocole
protocol: quic
# Métriques Prometheus (optionnel)
metrics: 0.0.0.0:2000
# Règles de routage (ingress rules)
ingress:
# Application web principale
- hostname: app.mondomaine.fr
service: http://localhost:8080
# Grafana
- hostname: grafana.mondomaine.fr
service: http://localhost:3000
# Portainer
- hostname: portainer.mondomaine.fr
service: https://localhost:9443
originRequest:
noTLSVerify: true
# Wiki.js
- hostname: wiki.mondomaine.fr
service: http://localhost:3001
# Serveur SSH (accès via cloudflared côté client)
- hostname: ssh.mondomaine.fr
service: ssh://localhost:22
# Règle par défaut (obligatoire, doit être la dernière)
- service: http_status:404Étape 5 : Lancer le tunnel
# Lancer le tunnel manuellement (pour tester)
cloudflared tunnel run mon-homelab
# Vous devriez voir des logs indiquant les connexions aux datacenters
# INF Connection established connIndex=0 location=CDG
# INF Connection established connIndex=1 location=CDG
# INF Connection established connIndex=2 location=MRS
# INF Connection established connIndex=3 location=MRSVos services sont maintenant accessibles sur Internet via vos sous-domaines, avec HTTPS automatique et protection DDoS, sans aucun port ouvert sur votre réseau.
Créer un tunnel : méthode Dashboard (Zero Trust)
Cloudflare propose également une méthode entièrement graphique via le dashboard Zero Trust, idéale pour ceux qui préfèrent éviter la ligne de commande :
- Connectez-vous au dashboard Cloudflare
- Accédez à Zero Trust (menu latéral) puis Networks > Tunnels
- Cliquez sur "Create a tunnel"
- Choisissez "Cloudflared" comme connecteur
- Donnez un nom au tunnel
- Cloudflare vous donne une commande d'installation avec un token intégré
# Commande fournie par le dashboard (exemple)
# Le token contient toute la configuration nécessaire
cloudflared service install eyJhIjoixxxxxxxxxx...
# Ou avec Docker
docker run -d --name cloudflared --restart always \
cloudflare/cloudflared:latest \
tunnel --no-autoupdate run \
--token eyJhIjoixxxxxxxxxx...L'avantage de la méthode Dashboard est que la configuration des ingress rules se fait directement dans l'interface web, sous l'onglet "Public Hostnames" du tunnel. Vous ajoutez vos sous-domaines et les services correspondants via des formulaires, sans toucher à un fichier YAML.
Cette méthode est aussi appelée "remotely-managed tunnel" car la configuration est stockée côté Cloudflare plutôt que localement. C'est pratique pour gérer plusieurs tunnels ou pour des environnements où vous ne voulez pas maintenir de fichiers de configuration.
Configuration YAML avancée
Ingress rules détaillées
Les ingress rules sont le coeur de la configuration de cloudflared. Voici une configuration avancée avec toutes les options disponibles :
# ~/.cloudflared/config.yml - Configuration avancée complète
tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /home/user/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json
# Protocole de connexion vers Cloudflare
protocol: quic
# Nombre de connexions redondantes (défaut: 4)
# edge-connections: 4
# Endpoint des métriques Prometheus
metrics: 0.0.0.0:2000
# Intervalle de heartbeat
# heartbeat-interval: 5s
# Grace period avant arrêt
grace-period: 30s
# Logs
loglevel: info
# logfile: /var/log/cloudflared/tunnel.log
# log-directory: /var/log/cloudflared/
# Configuration originRequest globale (appliquée à toutes les règles)
originRequest:
connectTimeout: 30s
tlsTimeout: 10s
tcpKeepAlive: 30s
noHappyEyeballs: false
keepAliveConnections: 100
keepAliveTimeout: 90s
httpHostHeader: ""
originServerName: ""
# Règles de routage
ingress:
# Application avec headers personnalisés
- hostname: app.mondomaine.fr
service: http://localhost:8080
originRequest:
httpHostHeader: app.internal
connectTimeout: 10s
# Application avec path routing (sous-chemins)
- hostname: api.mondomaine.fr
path: /v1/.*
service: http://localhost:8081
- hostname: api.mondomaine.fr
path: /v2/.*
service: http://localhost:8082
# Service HTTPS local avec certificat auto-signé
- hostname: secure.mondomaine.fr
service: https://localhost:9443
originRequest:
noTLSVerify: true # Ignorer la vérification du certificat local
originServerName: secure.local # SNI pour le service local
# Service sur un autre serveur du réseau local
- hostname: nas.mondomaine.fr
service: http://192.168.1.100:5000
# WebSocket (détecté automatiquement, mais peut être forcé)
- hostname: ws.mondomaine.fr
service: http://localhost:3030
# TCP brut (ex: base de données, service custom)
- hostname: db.mondomaine.fr
service: tcp://localhost:5432
# SSH
- hostname: ssh.mondomaine.fr
service: ssh://localhost:22
# RDP (Remote Desktop)
- hostname: rdp.mondomaine.fr
service: rdp://localhost:3389
# Wildcard (tous les sous-domaines non spécifiés)
- hostname: "*.dev.mondomaine.fr"
service: http://localhost:8888
# Règle par défaut (OBLIGATOIRE, toujours en dernier)
- service: http_status:404Validation de la configuration
# Valider la syntaxe du fichier de configuration
cloudflared tunnel ingress validate
# Tester quelle règle matcherait une URL donnée
cloudflared tunnel ingress rule https://app.mondomaine.fr
# Using rules from config file
# Matched rule #0: hostname=app.mondomaine.fr service=http://localhost:8080
cloudflared tunnel ingress rule https://inconnu.mondomaine.fr
# Matched rule #N (catch-all): service=http_status:404Cloudflare Access : Zero Trust Authentication
Pourquoi ajouter de l'authentification ?
Cloudflare Tunnel expose vos services sur Internet public. Même si vos services ont leur propre authentification, il est fortement recommandé d'ajouter une couche d'authentification supplémentaire devant les services sensibles. C'est le rôle de Cloudflare Access, le composant Zero Trust de Cloudflare.
Cloudflare Access agit comme un reverse proxy d'authentification : avant même que le trafic atteigne votre service, l'utilisateur doit s'authentifier. Si l'authentification échoue, le trafic est bloqué au niveau de Cloudflare et n'atteint jamais votre serveur.
Configurer Cloudflare Access
La configuration se fait dans le dashboard Cloudflare Zero Trust :
- Accédez à Zero Trust > Access > Applications
- Cliquez sur "Add an application"
- Choisissez "Self-hosted"
- Configurez l'application :
- Application name : ex. "Portainer"
- Session duration : durée de validité de la session (ex: 24h)
- Application domain :
portainer.mondomaine.fr
- Créez une policy d'accès (voir ci-dessous)
Méthodes d'authentification
Cloudflare Access supporte de nombreux Identity Providers (IdP) comme sources d'authentification :
- GitHub : connexion via votre compte GitHub (idéal pour les développeurs)
- Google : connexion via Google Workspace ou un compte Google personnel
- Microsoft / Azure AD : pour les environnements entreprise Microsoft
- Okta, OneLogin : fournisseurs d'identité d'entreprise
- SAML 2.0 : tout fournisseur SAML (Authentik, Keycloak...)
- OpenID Connect (OIDC) : tout fournisseur OIDC
- One-Time PIN (OTP) : code envoyé par email, sans IdP externe nécessaire
L'option OTP par email est particulièrement intéressante car elle ne nécessite aucun fournisseur d'identité tiers. L'utilisateur entre son email, reçoit un code par email, et accède au service. Simple et efficace.
Configurer GitHub comme Identity Provider
- Créez une OAuth App sur GitHub : github.com/settings/developers
- Callback URL :
https://VOTRE_TEAM.cloudflareaccess.com/cdn-cgi/access/callback - Notez le Client ID et Client Secret
- Dans le dashboard Zero Trust : Settings > Authentication > Add new provider > GitHub
- Entrez le Client ID et Client Secret
Créer des policies d'accès
Les policies déterminent qui peut accéder à vos applications. Quelques exemples :
- Email spécifique : seuls certains emails peuvent accéder (ex:
admin@mondomaine.fr) - Domaine email : tous les utilisateurs avec un email
@mondomaine.fr - Groupe GitHub : membres d'une organisation ou équipe GitHub spécifique
- Pays : restreindre l'accès à certains pays
- Plage IP : autoriser des plages IP spécifiques
- Combinaisons : toutes ces règles peuvent être combinées avec AND/OR
Exemple de policy pour un service d'administration :
- Rule 1 (Allow) : Email dans la liste
[admin@mondomaine.fr, ops@mondomaine.fr] - Rule 2 (Allow) : Membre de l'organisation GitHub
mon-org - Rule 3 (Block) : Pays non dans
[FR, BE, CH, CA]
Bypass pour les services publics
Certains services doivent rester publics (site web, blog, API publique). Pour ceux-là, vous pouvez soit ne pas créer de policy Access, soit créer une policy avec l'action "Bypass" pour tout le monde.
Installer cloudflared comme service systemd
Pour que le tunnel démarre automatiquement au boot et se relance en cas de crash :
# Méthode 1 : Installation automatique du service
sudo cloudflared service install
# Cela copie la configuration dans /etc/cloudflared/config.yml
# et crée un service systemd
# Démarrer le service
sudo systemctl start cloudflared
sudo systemctl enable cloudflared
# Vérifier le statut
sudo systemctl status cloudflared# Méthode 2 : Création manuelle du service systemd
sudo tee /etc/systemd/system/cloudflared.service > /dev/null <<'EOF'
[Unit]
Description=cloudflared tunnel
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
TimeoutStartSec=0
RestartSec=5s
Restart=on-failure
User=cloudflared
Group=cloudflared
ExecStart=/usr/local/bin/cloudflared tunnel --config /etc/cloudflared/config.yml run
ExecStop=/bin/kill -SIGTERM $MAINPID
# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/var/log/cloudflared
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
# Créer l'utilisateur système
sudo useradd -r -s /usr/sbin/nologin cloudflared
sudo mkdir -p /etc/cloudflared /var/log/cloudflared
sudo cp ~/.cloudflared/config.yml /etc/cloudflared/
sudo cp ~/.cloudflared/*.json /etc/cloudflared/
sudo cp ~/.cloudflared/cert.pem /etc/cloudflared/
sudo chown -R cloudflared:cloudflared /etc/cloudflared /var/log/cloudflared
# Mettre à jour le credentials-file dans config.yml
sudo sed -i 's|/home/user/.cloudflared/|/etc/cloudflared/|g' /etc/cloudflared/config.yml
# Activer et démarrer
sudo systemctl daemon-reload
sudo systemctl enable --now cloudflared
sudo systemctl status cloudflaredDéploiement avec Docker
Docker Compose avec configuration locale
# docker-compose.yml pour cloudflared
version: "3.8"
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: always
command: tunnel --config /etc/cloudflared/config.yml run
volumes:
- ./cloudflared/config.yml:/etc/cloudflared/config.yml:ro
- ./cloudflared/credentials.json:/etc/cloudflared/credentials.json:ro
networks:
- tunnel-network
# Si vos services sont dans d'autres réseaux Docker,
# ajoutez ce conteneur à ces réseaux aussi
# Exemple de service exposé via le tunnel
nginx:
image: nginx:alpine
container_name: mon-site
restart: always
networks:
- tunnel-network
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: always
volumes:
- grafana-data:/var/lib/grafana
networks:
- tunnel-network
volumes:
grafana-data:
networks:
tunnel-network:
driver: bridgeEt la configuration cloudflared associée :
# ./cloudflared/config.yml
tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /etc/cloudflared/credentials.json
protocol: quic
metrics: 0.0.0.0:2000
ingress:
- hostname: site.mondomaine.fr
service: http://mon-site:80
- hostname: grafana.mondomaine.fr
service: http://grafana:3000
- service: http_status:404Notez que dans un environnement Docker, les noms de service Docker (ex: mon-site, grafana) remplacent localhost dans les URLs des services.
Docker avec token (remotely-managed)
La méthode la plus simple avec Docker est d'utiliser un token depuis le dashboard :
# docker-compose.yml - Méthode par token
version: "3.8"
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: always
command: tunnel --no-autoupdate run --token ${CLOUDFLARED_TOKEN}
environment:
- CLOUDFLARED_TOKEN=${CLOUDFLARED_TOKEN}
network_mode: host # Pour accéder aux services sur localhost
# Alternative : sans network_mode host, connectez-vous
# aux services via les noms de conteneurs Docker# Créer un fichier .env avec le token
echo "CLOUDFLARED_TOKEN=eyJhIjoixxxxxxxxxx..." > .env
# Lancer
docker compose up -dCas d'usage détaillés
Homelab : exposer vos services maison
C'est le cas d'usage le plus populaire. Vous avez un homelab avec plusieurs services (Jellyfin, Home Assistant, Nextcloud, Vaultwarden...) et vous voulez y accéder depuis l'extérieur sans ouvrir de ports sur votre box Internet.
# Configuration homelab typique
tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /etc/cloudflared/credentials.json
ingress:
# Media server
- hostname: media.mondomaine.fr
service: http://192.168.1.50:8096 # Jellyfin
# Domotique
- hostname: home.mondomaine.fr
service: http://192.168.1.51:8123 # Home Assistant
# Cloud personnel
- hostname: cloud.mondomaine.fr
service: http://192.168.1.52:80 # Nextcloud
# Gestionnaire de mots de passe
- hostname: vault.mondomaine.fr
service: http://192.168.1.53:8080 # Vaultwarden
# Monitoring
- hostname: monitor.mondomaine.fr
service: http://192.168.1.50:3000 # Grafana
# Administration Docker
- hostname: docker.mondomaine.fr
service: https://192.168.1.50:9443 # Portainer
originRequest:
noTLSVerify: true
- service: http_status:404Serveur derrière NAT/CGNAT
De plus en plus de FAI utilisent le CGNAT (Carrier-Grade NAT), ce qui signifie que vous n'avez pas d'IP publique dédiée. Impossible dans ce cas de faire du port forwarding classique. Cloudflare Tunnel est la solution parfaite : puisque la connexion est sortante, le CGNAT n'a aucun impact.
C'est aussi le cas pour les connexions 4G/5G (Free, Orange, SFR...) qui sont systématiquement derrière un CGNAT. Vous pouvez héberger un serveur sur une connexion 4G et l'exposer via Cloudflare Tunnel sans aucun problème.
Développement : partager un service local
Pendant le développement, vous pouvez créer un tunnel temporaire (Quick Tunnel) pour partager un service local sans aucune configuration :
# Tunnel rapide sans configuration (URL aléatoire *.trycloudflare.com)
cloudflared tunnel --url http://localhost:3000
# Résultat :
# Your quick Tunnel has been created! Visit it at:
# https://random-words-here.trycloudflare.comC'est l'équivalent de ngrok, mais gratuit et sans limitation de durée.
Accès SSH via le navigateur
Cloudflare Tunnel permet d'accéder à SSH via le navigateur grâce à Cloudflare Access :
- Configurez le service SSH dans vos ingress rules (
service: ssh://localhost:22) - Dans le dashboard Zero Trust, créez une application Access de type "SSH"
- Activez le "Browser rendering"
- Les utilisateurs autorisés peuvent ouvrir un terminal SSH directement dans leur navigateur
Alternativement, pour un accès SSH en ligne de commande sans port ouvert :
# Côté client : configurer SSH pour passer par cloudflared
# Ajoutez dans ~/.ssh/config :
Host ssh.mondomaine.fr
ProxyCommand cloudflared access ssh --hostname %h
# Puis connectez-vous normalement
ssh user@ssh.mondomaine.frDNS automatique et HTTPS
DNS automatique
Lorsque vous créez des routes DNS pour votre tunnel (soit via la CLI, soit via le dashboard), Cloudflare crée automatiquement des enregistrements CNAME pointant vers UUID.cfargotunnel.com. Vous n'avez rien à configurer manuellement dans la zone DNS.
Ces enregistrements sont automatiquement proxiés par Cloudflare (icône orange dans le dashboard DNS), ce qui signifie que votre IP réelle n'apparaît jamais dans les requêtes DNS.
HTTPS automatique
Cloudflare gère automatiquement les certificats SSL/TLS pour tous les sous-domaines exposés via le tunnel. Les visiteurs accèdent à vos services en HTTPS sans que vous ayez à configurer Let's Encrypt, renouveler des certificats ou gérer quoi que ce soit.
Le chiffrement fonctionne en deux couches :
- Visiteur <-> Cloudflare : HTTPS avec le certificat Cloudflare (Universal SSL)
- Cloudflare <-> votre serveur : connexion chiffrée via le tunnel QUIC/HTTP2
Même si votre service local tourne en HTTP simple (sans SSL), la connexion est chiffrée de bout en bout grâce au tunnel.
Performances et optimisations
Latence
Cloudflare Tunnel ajoute une latence minimale car le trafic passe par le datacenter Cloudflare le plus proche de l'utilisateur. Avec plus de 300 datacenters dans le monde, la latence ajoutée est généralement de quelques millisecondes seulement. Dans certains cas, le tunnel peut même améliorer les performances grâce au CDN de Cloudflare et aux optimisations réseau.
Optimisations possibles
- Cache : activez le cache Cloudflare pour les assets statiques (images, CSS, JS)
- Compression : Cloudflare compresse automatiquement les réponses (Brotli, Gzip)
- HTTP/3 : activez HTTP/3 (QUIC) dans les paramètres du domaine pour les visiteurs
- Argo Smart Routing (payant) : optimise le routage du trafic via le réseau Cloudflare pour réduire la latence
- Tiered Cache : réduit les requêtes vers votre origine en utilisant les datacenters Cloudflare comme cache intermédiaire
Bande passante
Sur le plan gratuit, il n'y a pas de limite de bande passante officielle pour les tunnels. Cependant, Cloudflare interdit explicitement d'utiliser ses services comme CDN pour du contenu multimédia non-HTML (les Terms of Service section 2.8 ont été assouplis mais gardez une utilisation raisonnable). Pour du streaming vidéo intensif, considérez Cloudflare Stream (payant) ou servez les médias directement.
Limites du Free Tier
Bien que Cloudflare Tunnel soit très généreux sur le plan gratuit, il y a quelques limitations à connaître :
- Cloudflare Access : 50 utilisateurs gratuits maximum sur le plan Free. Au-delà, il faut passer au plan Teams/Zero Trust payant.
- Pas de load balancing : un tunnel pointe vers un seul serveur. Le load balancing entre plusieurs origines nécessite le plan payant.
- Pas d'Argo Smart Routing : l'optimisation du routage réseau est payante (environ 5$/mois + 0.10$/Go).
- Upload limité : les uploads via le plan gratuit sont limités à 100 Mo par requête (300 Mo sur le plan Pro).
- WebSocket : supporté, mais les connexions très longues peuvent être coupées après un timeout.
- Dépendance à Cloudflare : si Cloudflare a une panne globale (rare), vos services deviennent inaccessibles. C'est le compromis de la centralisation.
- Terms of Service : l'utilisation doit respecter les conditions d'utilisation de Cloudflare. Le proxy de contenu vidéo ou audio en streaming massif peut poser problème.
Comparaison avec les alternatives
| Critère | Cloudflare Tunnel | Tailscale Funnel | ngrok | frp |
|---|---|---|---|---|
| Type | Service cloud (Cloudflare) | Mesh VPN + exposition | SaaS tunnel | Auto-hébergé |
| Prix | Gratuit (illimité) | Gratuit (limité) | Freemium (limité) | Gratuit (open-source) |
| Domaine personnalisé | Oui (votre domaine) | Non (*.ts.net) | Payant | Oui (votre domaine) |
| HTTPS automatique | Oui | Oui | Oui | Manuel (Let's Encrypt) |
| Protection DDoS | Oui (Cloudflare) | Non | Non | Non |
| CDN/Cache | Oui | Non | Non | Non |
| Zero Trust / Auth | Oui (Cloudflare Access) | Oui (Tailscale ACL) | Oui (ngrok Edge) | Non natif |
| IP masquée | Oui | Oui | Oui | Non (IP du VPS visible) |
| Multi-services | Oui (ingress rules) | Limité | Payant | Oui |
| Serveur requis | Non | Non | Non | Oui (VPS avec IP publique) |
| Open-source | Client seulement | Client seulement | Non | Oui (client + serveur) |
| Bande passante | Illimitée | Limitée (plan gratuit) | Limitée (plan gratuit) | Limitée par votre VPS |
| Dépendance tierce | Cloudflare | Tailscale | ngrok | Aucune |
| TCP/UDP arbitraire | Oui (TCP via WARP) | Oui | Oui (payant) | Oui |
| SSH navigateur | Oui | Non | Non | Non |
Quand choisir Cloudflare Tunnel ?
- Vous voulez exposer des services web (HTTP/HTTPS) avec un domaine personnalisé
- Vous êtes derrière un CGNAT ou un réseau restreint
- Vous voulez une protection DDoS et un CDN gratuits
- Vous avez besoin d'authentification Zero Trust devant vos services
- Vous ne voulez pas maintenir de VPS supplémentaire
Quand choisir une alternative ?
- Tailscale Funnel : si vous utilisez déjà Tailscale pour votre VPN mesh et avez des besoins simples d'exposition
- ngrok : pour du développement ponctuel et des démos rapides (Quick Tunnel de Cloudflare est une bonne alternative gratuite)
- frp : si vous refusez toute dépendance à un service tiers et préférez tout auto-héberger (nécessite un VPS avec IP publique)
- WireGuard + reverse proxy : si vous voulez un contrôle total sur chaque composant de l'infrastructure
Bonnes pratiques de sécurité
Principe du moindre privilège
- N'exposez que ce qui est nécessaire : si un service n'a pas besoin d'être accessible depuis Internet, ne le mettez pas dans les ingress rules
- Utilisez Cloudflare Access pour tous les services d'administration (Portainer, Grafana admin, phpMyAdmin...)
- Restreignez par email ou domaine : n'autorisez que les utilisateurs spécifiques qui ont besoin d'accès
- Activez l'authentification multi-facteurs quand c'est possible via votre IdP
Sécurité réseau
# Bloquer tout trafic entrant non nécessaire sur votre serveur
# Puisque le tunnel est une connexion sortante, vous n'avez
# besoin d'aucun port entrant ouvert
# UFW (Uncomplicated Firewall)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh # Gardez SSH en direct comme accès de secours
sudo ufw enable
# Vérifier les règles
sudo ufw status verboseMonitoring et alertes
# Surveiller les connexions du tunnel
cloudflared tunnel info mon-homelab
# Vérifier les métriques Prometheus
curl -s http://localhost:2000/metrics | grep cloudflared
# Cloudflare fournit aussi des analytics dans le dashboard :
# Zero Trust > Analytics > Access
# Zero Trust > Networks > Tunnels > votre tunnel > AnalyticsRotation des credentials
# Régénérer le token d'un tunnel (via dashboard recommandé)
# Cela invalidera l'ancien token
# Supprimer un tunnel qui n'est plus utilisé
cloudflared tunnel delete ancien-tunnel
# Lister les connexions actives
cloudflared tunnel info mon-homelabDépannage courant
Le tunnel ne se connecte pas
# Vérifier la connectivité sortante
# cloudflared a besoin de se connecter à Cloudflare sur les ports 443 et 7844 (QUIC)
curl -v https://api.cloudflare.com/cdn-cgi/trace
# Vérifier les logs
sudo journalctl -u cloudflared -f
# Tester avec un protocole de fallback si QUIC est bloqué
# Dans config.yml, changez :
# protocol: http2502 Bad Gateway
# Cette erreur signifie que cloudflared ne peut pas atteindre votre service local
# 1. Vérifiez que le service est en cours d'exécution
curl -v http://localhost:8080
# 2. Si cloudflared est dans Docker, assurez-vous qu'il est
# dans le même réseau Docker que vos services
docker network inspect tunnel-network
# 3. Vérifiez que vous utilisez le bon nom d'hôte
# Dans Docker : utilisez le nom du conteneur, pas localhost
# Hors Docker : utilisez localhost ou l'IP du serveurCertificat SSL invalide vers l'origine
# Si votre service local utilise HTTPS avec un certificat auto-signé
# Ajoutez noTLSVerify dans les originRequest
ingress:
- hostname: secure.mondomaine.fr
service: https://localhost:9443
originRequest:
noTLSVerify: trueAutomatisation et Infrastructure as Code
Pour les environnements plus avancés, Cloudflare Tunnel peut être géré via Terraform avec le provider Cloudflare :
# Exemple conceptuel Terraform
# provider "cloudflare" { ... }
# resource "cloudflare_tunnel" "homelab" { ... }
# resource "cloudflare_tunnel_config" "homelab" { ... }
# resource "cloudflare_record" "tunnel_dns" { ... }
# L'API Cloudflare permet aussi l'automatisation via scripts
# Documentation : https://developers.cloudflare.com/api/Conclusion
Cloudflare Tunnel est un game-changer pour l'auto-hébergement. En supprimant le besoin d'ouvrir des ports, d'avoir une IP publique fixe et de gérer des certificats SSL, il rend l'exposition de services locaux accessible à tous, même aux utilisateurs derrière un CGNAT ou un réseau d'entreprise restrictif.
Les avantages sont considérables : gratuit, sécurisé (pas de ports ouverts, IP masquée), performant (CDN Cloudflare, protection DDoS), et simple à configurer (un fichier YAML et quelques commandes). L'intégration avec Cloudflare Access ajoute une couche Zero Trust qui protège vos services sans effort supplémentaire.
Le compromis principal est la dépendance à Cloudflare. Votre trafic transite par leur infrastructure, et si Cloudflare tombe en panne (ce qui est extrêmement rare), vos services deviennent inaccessibles. Pour la grande majorité des cas d'usage (homelab, petites entreprises, développeurs), ce compromis est largement acceptable au vu des avantages.
En 2025-2026, avec la généralisation du CGNAT et la montée en puissance de l'auto-hébergement, Cloudflare Tunnel s'impose comme un outil incontournable dans la boîte à outils de tout administrateur système et de tout passionné de homelab.
Ressources utiles :
Documentation officielle : developers.cloudflare.com/cloudflare-one/connections/connect-networks
Dashboard Zero Trust : one.dash.cloudflare.com
GitHub cloudflared : github.com/cloudflare/cloudflared
Communauté Cloudflare : community.cloudflare.com
Blog Cloudflare : blog.cloudflare.com