Cloudflare Tunnel : Exposez vos Services sans Ouvrir de Ports

Cloudflare Tunnel expose vos services sans ouvrir de ports ni avoir d'IP publique. Configuration, Zero Trust Access, ingress rules et comparatif ngrok/frp.

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

Diagramme - Cloudflare Tunnel : Exposez vos Services sans Ouvrir de Ports

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 :

  1. Vous installez cloudflared (le daemon client) sur votre serveur local
  2. cloudflared établit une connexion sortante chiffrée (QUIC/HTTP2) vers les datacenters Cloudflare les plus proches
  3. Vous configurez des règles de routage (ingress rules) qui associent des noms de domaine à vos services locaux
  4. Cloudflare gère le DNS, le SSL/TLS, la protection DDoS et le reverse proxy
  5. 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 :

  1. Rendez-vous sur dash.cloudflare.com/sign-up et créez un compte gratuit
  2. Ajoutez votre nom de domaine à Cloudflare en suivant l'assistant
  3. Modifiez les nameservers de votre domaine chez votre registrar pour pointer vers ceux de Cloudflare
  4. 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 cloudflared

Installation sur macOS

# Via Homebrew
brew install cloudflared

# Vérifier
cloudflared --version

Installation via Docker

# Utiliser l'image officielle
docker pull cloudflare/cloudflared:latest

# Vérifier
docker run --rm cloudflare/cloudflared:latest --version

Cré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 login

Cette 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=MRS

Vos 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 :

  1. Connectez-vous au dashboard Cloudflare
  2. Accédez à Zero Trust (menu latéral) puis Networks > Tunnels
  3. Cliquez sur "Create a tunnel"
  4. Choisissez "Cloudflared" comme connecteur
  5. Donnez un nom au tunnel
  6. 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:404

Validation 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:404

Cloudflare 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 :

  1. Accédez à Zero Trust > Access > Applications
  2. Cliquez sur "Add an application"
  3. Choisissez "Self-hosted"
  4. Configurez l'application :
    • Application name : ex. "Portainer"
    • Session duration : durée de validité de la session (ex: 24h)
    • Application domain : portainer.mondomaine.fr
  5. 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

  1. Créez une OAuth App sur GitHub : github.com/settings/developers
  2. Callback URL : https://VOTRE_TEAM.cloudflareaccess.com/cdn-cgi/access/callback
  3. Notez le Client ID et Client Secret
  4. Dans le dashboard Zero Trust : Settings > Authentication > Add new provider > GitHub
  5. 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 cloudflared

Dé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: bridge

Et 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:404

Notez 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 -d

Cas 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:404

Serveur 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.com

C'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 :

  1. Configurez le service SSH dans vos ingress rules (service: ssh://localhost:22)
  2. Dans le dashboard Zero Trust, créez une application Access de type "SSH"
  3. Activez le "Browser rendering"
  4. 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.fr

DNS 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 verbose

Monitoring 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 > Analytics

Rotation 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-homelab

Dé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: http2

502 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 serveur

Certificat 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: true

Automatisation 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
Vous vous êtes abonné avec succès à CodeClan
Parfait ! Ensuite, complétez le paiement pour obtenir un accès complet à tout le contenu premium.
Erreur ! Impossible de s'inscrire. Lien invalide.
Bienvenue ! Vous vous êtes connecté avec succès.
Erreur ! Impossible de se connecter. Veuillez réessayer.
Succès ! Votre compte est entièrement activé, vous avez maintenant accès à tout le contenu.
Erreur ! Le paiement Stripe a échoué.
Succès ! Vos informations de facturation sont mises à jour.
Erreur ! La mise à jour des informations de facturation a échoué.