Cloudflare Tunnel a fondo: publica servicios sin abrir puertos ni exponer tu IP
Cómo funciona Cloudflare Tunnel y cloudflared: conexiones solo salientes, túneles gestionados desde el panel o en local, reglas ingress, Quick Tunnels, límites y seguridad con Access. Con una configuración de ingress validada con cloudflared.
Contenido
Publicar en internet algo que corre en tu casa o en un servidor privado siempre ha tenido el mismo peaje: abrir puertos en el router, pelearte con la IP dinámica, exponer tu IP pública y confiar en que nadie encuentre el servicio antes de que lo protejas. Y si estás detrás de un CG-NAT de tu operador, ni siquiera puedes.
Cloudflare Tunnel le da la vuelta. Instalas un pequeño programa, cloudflared, en la máquina o la red donde está el servicio, y es él quien abre conexiones salientes hacia Cloudflare. Cuando alguien visita app.tudominio.com, Cloudflare le manda la petición por ese túnel. No abres ningún puerto de entrada, tu IP no aparece en el DNS y el tráfico pasa por la caché, el WAF y la protección DDoS como cualquier otro sitio proxied.
En este artículo vemos cómo funciona, los dos tipos de túnel, las reglas ingress, los Quick Tunnels sin cuenta, los límites y cómo cerrarlo con Access. Con una configuración real validada con cloudflared.
cloudflared 2026.9.3 el 3 de octubre de 2026 y he validado de verdad la configuración ingress de este artículo con sus comandos ingress validate e ingress rule, que funcionan sin conexión. No he llegado a abrir un túnel funcionando: el Quick Tunnel obtuvo su URL de trycloudflare.com, pero mi entorno de pruebas bloquea el tráfico UDP de QUIC y no lo repetí por HTTP/2. Los túneles con nombre, el enrutado DNS y Access tampoco están probados: necesitan cuenta y dominio. Todo lo demás sale de la documentación oficial, revisada ese mismo día.Cómo funciona
- Instalas
cloudflareden tu servidor, en una Raspberry Pi o en un contenedor de tu red. cloudflaredabre conexiones salientes y cifradas (con criptografía post-cuántica) hacia Cloudflare. Cada túnel mantiene cuatro conexiones de larga duración a dos centros de datos distintos, para tener redundancia.- Asocias nombres públicos (
app.ejemplo.com) a servicios locales (http://localhost:8080). - Cuando llega una visita, Cloudflare aplica caché y seguridad y envía la petición por el túnel;
cloudflaredla entrega al servicio local.

Además de HTTP y HTTPS, un túnel puede llevar SSH, RDP, TCP arbitrario y sockets Unix. Para esos protocolos el cliente suele necesitar cloudflared también, o usar el acceso desde el navegador que ofrece Access.
Tunnel está disponible en todos los planes, también en el gratuito. Para publicar aplicaciones con un nombre propio necesitas una cuenta y un dominio en Cloudflare. Si tu red tiene un cortafuegos de salida restrictivo, comprueba que puede llegar a Cloudflare por el puerto 7844.
Dos formas de gestionar un túnel
- Gestionado desde el panel (o la API). Creas el túnel en Networking > Tunnels, el panel te da un comando de instalación con un token y las rutas se definen allí. Es lo que recomienda la documentación para empezar: en cinco minutos lo tienes.
- Gestionado en local. Creas el túnel con
cloudflared tunnel create, que genera un fichero de credenciales, y defines las rutas en unconfig.yml. Útil si quieres versionar la configuración con el resto de tu infraestructura.
El flujo en local sería este (no lo he probado):
cloudflared tunnel login # autoriza cloudflared con tu cuenta
cloudflared tunnel create homelab # crea el túnel y su fichero de credenciales
cloudflared tunnel route dns homelab app.ejemplo.com # CNAME app → el túnel
cloudflared tunnel run homelab # arranca usando ~/.cloudflared/config.ymlReglas ingress
En un túnel gestionado en local, el config.yml lista las reglas ingress. Cada petición se compara con las reglas de arriba abajo; gana la primera que coincide, por hostname, por path (expresión regular) o por ambos. La última regla debe capturarlo todo.
# ~/.cloudflared/config.yml de un túnel gestionado en local
tunnel: 6ff42ae2-765d-4adf-8112-31c55c1551ef
credentials-file: /home/yo/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
ingress:
# La API, solo las rutas /api/*, a un servicio en el puerto 3000
- hostname: app.ejemplo.com
path: ^/api/
service: http://localhost:3000
# El resto de app.ejemplo.com, al frontend
- hostname: app.ejemplo.com
service: http://localhost:5173
# Grafana en el homelab, en otra máquina de la red local
- hostname: grafana.ejemplo.com
service: http://192.168.1.20:3000
# SSH (el cliente necesita cloudflared o el acceso por navegador de Access)
- hostname: ssh.ejemplo.com
service: ssh://localhost:22
# Regla final obligatoria: todo lo demás, 404
- service: http_status:404Y aquí la parte que sí he podido probar. cloudflared valida el fichero y te dice qué regla se aplicaría a una URL, sin conectarse a nada:
$ cloudflared tunnel --config config.yml ingress validate
Validating rules from config.yml
OK
$ cloudflared tunnel --config config.yml ingress rule https://app.ejemplo.com/api/usuarios
Using rules from config.yml
Matched rule #0
hostname: app.ejemplo.com
path: ^/api/
service: http://localhost:3000
$ cloudflared tunnel --config config.yml ingress rule https://app.ejemplo.com/login
Using rules from config.yml
Matched rule #1
hostname: app.ejemplo.com
service: http://localhost:5173
$ cloudflared tunnel --config config.yml ingress rule https://grafana.ejemplo.com/
Using rules from config.yml
Matched rule #2
hostname: grafana.ejemplo.com
service: http://192.168.1.20:3000
$ cloudflared tunnel --config config.yml ingress rule https://otro.ejemplo.com/
Using rules from config.yml
Matched rule #4
service: http_status:404Si quitas la regla final, la validación falla:
$ cloudflared tunnel --config sin-final.yml ingress validate # sin la regla final
Validating rules from sin-final.yml
Validation failed: The last ingress rule must match all URLs (i.e. it should not have a hostname or path filter)Dos detalles de la documentación. cloudflared usa path para elegir la regla, pero envía la ruta completa al servicio: /api/usuarios llega como /api/usuarios, no como /usuarios. Y los comodines (*.ejemplo.com) funcionan en hostname, pero no en mitad del nombre.
Quick Tunnels: sin cuenta y sin dominio
Para enseñar algo un rato, no hace falta ni cuenta:
cloudflared tunnel --url http://localhost:8080cloudflared imprime una URL aleatoria de trycloudflare.com y cualquiera que la tenga puede entrar. En mi prueba, la URL se generó en unos seis segundos. Además, puedes restringir quién entra con --allowed-mail: el visitante recibe un código de un solo uso por correo (puedes repetir el parámetro o usar '*@ejemplo.com').
Sus límites, según la documentación:
- sin garantía de disponibilidad, solo para pruebas;
- 200 peticiones en vuelo como máximo; las demás reciben un 429;
- no soportan Server-Sent Events;
- la URL cambia cada vez que lo arrancas.
Límites
| Concepto | Límite |
|---|---|
Túneles cloudflared por cuenta | 1000 |
| Réplicas activas por túnel | 25 |
| Conexiones por réplica | 4, a 2 centros de datos |
Las réplicas son varias instancias de cloudflared con el mismo túnel en máquinas distintas: si una cae, el tráfico sigue por las demás.
Cerrar el túnel con Access
Un túnel solo cambia por dónde entra el tráfico; no decide quién entra. Si publicas Grafana, Home Assistant o un panel de administración, ponle delante una aplicación de Cloudflare Access: antes de llegar al túnel, el visitante tendrá que identificarse (con Google, GitHub, un código por correo…) y cumplir tus políticas. Lo cuento en el artículo sobre Zero Trust. Y el mismo mecanismo, con un token de servicio, es el que usa Hyperdrive para llegar a una base de datos privada.
Errores comunes (y cómo evitarlos)
- Olvidar la regla final. El fichero no valida. Termina siempre con
service: http_status:404. - Orden de las reglas. Una regla general antes que una específica se lo queda todo. Pon primero las de
path. - Esperar que
pathrecorte la ruta. No lo hace; si tu servicio espera otra ruta, reescríbela con una regla de Cloudflare o en un proxy local. - Publicar sin Access. Cualquier panel de administración necesita autenticación.
- Origen HTTPS con certificado propio. Si el servicio local usa HTTPS con un certificado autofirmado,
cloudflaredno podrá verificarlo (la opción de origennoTLSVerifyviene desactivada por defecto). Usa un certificado válido, configura las opciones de origen o usa HTTP en local. - Una sola réplica en producción. Si esa máquina se reinicia, el sitio cae. Usa al menos dos.
- Usar Quick Tunnels en producción. No tienen garantía, la URL cambia y no soportan SSE.
- Dejar el puerto abierto «por si acaso». El sentido del túnel es no tener puertos de entrada. Ciérralos en el router y haz que el origen escuche solo en local.
Cuándo usar Tunnel (y cuándo no)
Úsalo para publicar servicios de un homelab o de una red privada, para servidores detrás de CG-NAT, para quitarle la IP pública a un origen y que solo se llegue a él a través de Cloudflare, y para enseñar un desarrollo local un rato con un Quick Tunnel.
No es la herramienta para tráfico UDP de juegos o VoIP hacia el público, ni para mover grandes volúmenes de vídeo que no quieres que pasen por Cloudflare. Y si lo que quieres es que tus dispositivos lleguen a toda tu red privada como con una VPN, el túnel es solo una pieza: necesitas también el cliente de Cloudflare One, que vemos en el artículo de Zero Trust.
Sigue leyendo
- Cloudflare a fondo: la visión general de la plataforma.
- Cloudflare Zero Trust a fondo: Access, Gateway y el cliente de Cloudflare One.
- Cloudflare DNS a fondo: los CNAME que apuntan al túnel.
- Cloudflare WAF y protección DDoS a fondo: la seguridad que se aplica antes del túnel.
- Cloudflare Hyperdrive a fondo: bases de datos privadas a través de un túnel.