Derrière un Cloudflare Tunnel
Un Cloudflare Tunnel connecte l’origine vers l’extérieur : cloudflared appelle
Cloudflare, et Cloudflare renvoie les requêtes par cette connexion. Rien n’écoute
sur un port public, le bord termine le TLS, et l’origine voit du HTTP en clair sur
la boucle locale. Cette page met cela en place et corrige la première chose qui
va de travers : toutes les requêtes journalisées en 127.0.0.1.
🧾 Avant de commencer
Section intitulée « 🧾 Avant de commencer »- Le domaine dans un compte Cloudflare, avec Zero Trust disponible.
cloudflaredsur la même machine que Pingclair, et Pingclair qui sert le site (Servir un site statique).- Soit le tableau de bord (Zero Trust → Networks → Tunnels), soit un jeton d’API
avec Cloudflare Tunnel: Write et DNS: Edit sur la zone. Les exemples
utilisent l’API, avec
$CF_TOKEN,$ACCOUNTet$ZONE.
🌐 Créer le tunnel
Section intitulée « 🌐 Créer le tunnel »curl -s -X POST -H "Authorization: Bearer $CF_TOKEN" -H 'Content-Type: application/json' \ --data '{"name":"docs-origin","config_src":"cloudflare"}' \ "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT/cfd_tunnel"{"success":true,"result":{"id":"bc6869fa-19cf-4780-b95b-f11be77eb329","name":"docs-origin", …}}config_src: cloudflare rend le tunnel géré à distance : ses règles d’ingress
vivent dans Cloudflare et sont poussées par l’API, donc rien n’a besoin d’être
écrit à côté du connecteur.
Le justificatif du connecteur s’obtient par un appel séparé :
curl -s -H "Authorization: Bearer $CF_TOKEN" \ "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT/cfd_tunnel/$TUNNEL_ID/token"Ce jeton est un secret : c’est lui qui permet à une machine de rejoindre le tunnel. Traitez-le comme un mot de passe et changez-le s’il fuit.
🔌 Connecter la machine
Section intitulée « 🔌 Connecter la machine »curl -fsSL -o /tmp/cloudflared.deb \ https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.debsudo dpkg -i /tmp/cloudflared.debsudo cloudflared service install "$TUNNEL_TOKEN"INF Linux service for cloudflared installed successfullyLe connecteur enregistre quatre connexions vers les points Cloudflare les plus proches, en QUIC par défaut :
INF Registered tunnel connection connIndex=2 … location=pdx02 protocol=quicINF Registered tunnel connection connIndex=3 … location=sea10 protocol=quic🌍 Router un nom d’hôte
Section intitulée « 🌍 Router un nom d’hôte »Les règles d’ingress décident quel nom atteint quel service d’origine :
curl -s -X PUT -H "Authorization: Bearer $CF_TOKEN" -H 'Content-Type: application/json' \ --data '{"config":{"ingress":[ {"hostname":"tunnel-test.pingclair.com","service":"http://127.0.0.1:80"}, {"service":"http_status:404"}]}}' \ "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT/cfd_tunnel/$TUNNEL_ID/configurations"La dernière règle est le fourre-tout : un nom inconnu obtient 404 plutôt que le
site par défaut.
Ensuite, pointez le nom vers le tunnel, proxy activé :
curl -s -X POST -H "Authorization: Bearer $CF_TOKEN" -H 'Content-Type: application/json' \ --data '{"type":"CNAME","name":"tunnel-test.pingclair.com","content":"'$TUNNEL_ID'.cfargotunnel.com","proxied":true,"ttl":60}' \ "https://api.cloudflare.com/client/v4/zones/$ZONE/dns_records"Depuis n’importe où :
curl -I https://tunnel-test.pingclair.com/HTTP/2 200content-type: text/html; charset=utf-8accept-ranges: bytesserver: cloudflareserver: cloudflare est le bord qui répond ; l’origine a été atteinte par le
tunnel, sans ouvrir aucun port.
🎯 Que l’origine voie le client
Section intitulée « 🎯 Que l’origine voie le client »Par défaut, chaque requête arrive du connecteur sur la boucle locale : le journal d’accès ne dit alors rien de qui était le client.
📝 Access … host="tunnel-test.pingclair.com" status=200 remote_ip=127.0.0.1 user_agent="curl/8.7.1"trusted_proxies indique à Pingclair quels pairs peuvent affirmer l’adresse du
client. Le connecteur tourne sur la même machine : la boucle locale suffit.
{ admin 127.0.0.1:2019 trusted_proxies 127.0.0.1/32}
http://:80 { root * /srv/site file_server}Mesuré, la même requête avant et après l’option :
remote_ip=127.0.0.1 # avantremote_ip=16.162.199.171 # après : le client qui a lancé la requêteC’est aussi ce réglage qui donne un sens à la limitation par IP et aux règles par IP derrière un tunnel. Il est établi au démarrage : le changer demande un redémarrage, pas un rechargement (ce que signifie un rechargement).
⚠️ Quand cela ne marche pas
Section intitulée « ⚠️ Quand cela ne marche pas »HTTP/2 530avecerror code: 1033. Le tunnel n’a pas de connecteur.systemctl is-active cloudflaredsur l’origine le dit ; les requêtes répondent200quelques secondes après l’enregistrement du connecteur.- Une requête atteint un autre site, ou
404. Les règles d’ingress sont évaluées dans l’ordre et finissent par le fourre-tout ; vérifiez l’orthographe du nom dans la règle avant d’accuser le DNS. 502depuis le bord. Le connecteur est là, mais le service d’origine a refusé la connexion : Pingclair n’écoute pas sur le port de la règle.- Le journal d’accès dit toujours
127.0.0.1.trusted_proxiesmanque, comme ci-dessus. - Le nom ne résout pas. L’enregistrement doit être un CNAME proxifié vers
<tunnel-id>.cfargotunnel.com; un enregistrement en nuage gris contourne le tunnel. - Le jeton du connecteur a fuité. Supprimez les jetons du tunnel et réinstallez le service avec le nouveau ; l’ancien n’est de toute façon pas récupérable par l’API.
🧭 Étapes suivantes
Section intitulée « 🧭 Étapes suivantes »- Servir un site statique : l’origine que ces exemples visent.
- TLS : ce qui se règle : ce que l’origine peut faire des certificats quand le bord ne termine pas.
- Exécution comme service : l’unité sur l’origine, et la
sémantique de rechargement que la note sur
trusted_proxiesrappelle.
