Cloudflare Tunnel : exposez sans ouvrir de port

Cloudflare Tunnel : exposez sans ouvrir de port

Cloudflare Tunnel (anciennement Argo Tunnel) cree une connexion sortante chiffree entre votre serveur et Cloudflare. Plus besoin de port ouvert, d'IP publique ou de VPN. Ideal pour les homelab, ou pour cacher l'IP origin d'un serveur en production.

Introduction

Cloudflare Tunnel :

  • Connexion sortante du serveur vers Cloudflare (pas d'inbound)
  • TLS automatique (cert Cloudflare)
  • Pas besoin d'IP publique
  • Cache l'IP origin (anti-DDoS, anti-scraping)
  • Acces Zero Trust (auth via Google, GitHub, etc.)
  • Gratuit jusqu'a 50 utilisateurs
  • Fonctionne meme derriere NAT / firewall stricte

Cas d'usage :

  • Heberger un Plex, NextCloud, Home Assistant chez soi
  • Exposer un VPS interne sans ouvrir le firewall
  • Cacher l'IP d'un VPS de production
  • Acces SSH securise sans port 22 ouvert

Prerequis

  • Compte Cloudflare gratuit
  • Domaine sur Cloudflare (les DNS doivent etre geres par CF)
  • VPS / serveur avec Linux

Etape 1 : Installer cloudflared

curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb
cloudflared --version

Etape 2 : Login Cloudflare

cloudflared tunnel login

Une URL s'affiche. Ouvrez-la dans un navigateur, authentifiez-vous sur Cloudflare et selectionnez votre domaine.

Un certificat est telecharge dans ~/.cloudflared/cert.pem.

Etape 3 : Creer un tunnel

cloudflared tunnel create monsite

Sortie :

Tunnel credentials written to /root/.cloudflared/abc123-def456-ghi789.json
Created tunnel monsite with id abc123-def456-ghi789

Notez l'UUID.

Etape 4 : Configuration du tunnel

~/.cloudflared/config.yml :

tunnel: abc123-def456-ghi789
credentials-file: /root/.cloudflared/abc123-def456-ghi789.json

ingress:
  - hostname: app.votre-domaine.fr
    service: http://localhost:8080
  
  - hostname: api.votre-domaine.fr
    service: http://localhost:3000
  
  - hostname: ssh.votre-domaine.fr
    service: ssh://localhost:22
  
  # Catch-all obligatoire en dernier
  - service: http_status:404

Etape 5 : DNS Cloudflare

Creez les CNAMEs qui pointent vers le tunnel :

cloudflared tunnel route dns monsite app.votre-domaine.fr
cloudflared tunnel route dns monsite api.votre-domaine.fr
cloudflared tunnel route dns monsite ssh.votre-domaine.fr

Verifiez dans le dashboard DNS Cloudflare : les CNAMEs sont crees, proxied (cloud orange).

Etape 6 : Demarrer le tunnel

cloudflared tunnel run monsite

Le tunnel se connecte a Cloudflare. Visitez https://app.votre-domaine.fr : votre app locale est exposee, en HTTPS, sans port ouvert.

Etape 7 : Service systemd

Pour demarrage automatique :

sudo cloudflared service install
sudo systemctl enable --now cloudflared
sudo systemctl status cloudflared

Etape 8 : Acces SSH via tunnel

Sur le client, ajoutez dans ~/.ssh/config :

Host ssh.votre-domaine.fr
    HostName ssh.votre-domaine.fr
    User root
    ProxyCommand cloudflared access ssh --hostname %h

Et installez cloudflared localement aussi. Maintenant :

ssh ssh.votre-domaine.fr

Premier essai : un navigateur s'ouvre pour auth Cloudflare Zero Trust.

Etape 9 : Zero Trust Access

Pour proteger un endpoint avec authentification SSO :

Dashboard Cloudflare > Zero Trust > Access > Applications > Add an application > Self-hosted.

Configurez :

  • Application name : Monsite Admin
  • Session duration : 24h
  • Application domain : app.votre-domaine.fr
  • Identity providers : Google / GitHub / Email OTP

Ajoutez une policy :

  • Action : Allow
  • Rules : Emails ending in @verycloud.fr

Maintenant, https://app.votre-domaine.fr demande un login SSO avant d'acceder a votre app. Pratique pour exposer un Grafana, Portainer, etc.

Etape 10 : Multiple services sur un seul tunnel

config.yml :

tunnel: abc123
credentials-file: /root/.cloudflared/abc123.json

ingress:
  # Web apps
  - hostname: app.votre-domaine.fr
    service: http://localhost:8080
  
  - hostname: blog.votre-domaine.fr
    service: http://localhost:8081
    originRequest:
      noTLSVerify: true
  
  # WebSocket
  - hostname: ws.votre-domaine.fr
    service: ws://localhost:9000
  
  # SSH
  - hostname: ssh.votre-domaine.fr
    service: ssh://localhost:22
  
  # RDP
  - hostname: rdp.votre-domaine.fr
    service: rdp://localhost:3389
  
  # Generic TCP
  - hostname: db.votre-domaine.fr
    service: tcp://localhost:5432
  
  # Catch-all
  - service: http_status:404

Reload :

sudo systemctl restart cloudflared

Etape 11 : Connecter une appli locale en short-form

Pour des tests rapides, pas besoin de creer un tunnel :

cloudflared tunnel --url http://localhost:8000

Genere une URL *.trycloudflare.com temporaire. Utile pour debug / demo.

Etape 12 : Monitoring et metrics

Cloudflared expose ses metriques sur localhost :

sudo cloudflared service install

Ajoutez dans /etc/cloudflared/config.yml :

metrics: 0.0.0.0:9090
sudo systemctl restart cloudflared
curl http://localhost:9090/metrics

Integrez dans Prometheus pour suivre la latence, les requetes, les erreurs.

Depannage

"tunnel not found"

Verifiez l'UUID dans config.yml matche bien :

cloudflared tunnel list

Erreur 1033 / 1034 sur le domaine

Le tunnel n'est pas connecte. Verifiez :

sudo systemctl status cloudflared
sudo journalctl -u cloudflared -f

"Failed to dial origin"

Le service local n'ecoute pas, ou pas sur le bon port. Verifiez :

sudo ss -tunlp | grep 8080
curl http://localhost:8080

Latence elevee

Cloudflare Tunnel ajoute un saut. Pour optimiser, choisissez la datacenter Cloudflare la plus proche :

ingress:
  - hostname: app.votre-domaine.fr
    service: http://localhost:8080
    originRequest:
      keepAliveTimeout: 30s
      connectTimeout: 10s

WebSocket qui ferme

Activez --upgrade websocket ou configurez :

originRequest:
  noHappyEyeballs: true

Commandes utiles

# Login
cloudflared tunnel login

# Tunnels
cloudflared tunnel list
cloudflared tunnel create nom
cloudflared tunnel delete nom
cloudflared tunnel info nom

# Run
cloudflared tunnel run nom
cloudflared tunnel run --config /chemin/config.yml nom

# Quick tunnel (ephemere)
cloudflared tunnel --url http://localhost:8000

# DNS routing
cloudflared tunnel route dns nom-tunnel sous.domaine.fr

# Service systemd
sudo cloudflared service install
sudo cloudflared service uninstall
sudo systemctl restart cloudflared
sudo journalctl -u cloudflared -f

# SSH proxy
cloudflared access ssh --hostname ssh.votre-domaine.fr

Conclusion

Cloudflare Tunnel vous donne :

  • Exposition securisee sans port ouvert
  • TLS auto et IP origin cachee
  • Zero Trust avec SSO
  • Gratuit pour la plupart des usages

Limites :

  • Vous dependez de Cloudflare (DNS + tunnel)
  • Latence ajoutee
  • Limites de bande passante sur le plan gratuit

Pour aller plus loin :

  • Combinez avec Cloudflare Access pour de l'auth SSO
  • Pour SSH, regardez Cloudflare Tunnel + browser-based SSH
  • Pour des alternatives self-hosted : Tailscale Funnel, frp, Wireguard + reverse proxy

Ressources

Join our Discord community server

For any questions, suggestions, or just to chat with the community, join us on Discord!

900+Members