> ## Content Index
> Fetch the complete content index at: https://blog.devutilites.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Cloudflare Tunnel a fondo: publica servicios sin abrir puertos ni exponer tu IP
- URL: https://blog.devutilites.com/cloudflare-tunnel-a-fondo/
- Published: 2026-10-03T03:14:01.000Z
- Updated: 2026-10-03T03:14:01.000Z
- Description: 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.
- Author: Luis Collantes
- Tags: Cloudflare, DevOps

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`.

🧪

**He instalado `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

1. Instalas `cloudflared` en tu servidor, en una Raspberry Pi o en un contenedor de tu red.
2. `cloudflared` abre 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.
3. Asocias nombres públicos (`app.ejemplo.com`) a servicios locales (`http://localhost:8080`).
4. Cuando llega una visita, Cloudflare aplica caché y seguridad y envía la petición por el túnel; `cloudflared` la entrega al servicio local.

![Esquema de Cloudflare Tunnel: el visitante entra por Cloudflare, donde se aplican DNS, WAF y Access; las peticiones viajan por conexiones salientes que cloudflared abrió desde la red privada; cloudflared las entrega a los servicios locales; el router no tiene puertos abiertos](https://blog.devutilites.com/content/images/2026/10/cf-tunnel-esquema.png)

Las conexiones las abre cloudflared desde dentro. Desde fuera no hay nada que escanear. Diagrama: devutilites.

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 un `config.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):

```bash
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.yml
```

## Reglas 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**.

```yaml
# ~/.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:404
```

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

```text
$ 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:404
```

Si quitas la regla final, la validación falla:

```text
$ 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:

```bash
cloudflared tunnel --url http://localhost:8080
```

`cloudflared` 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](https://blog.devutilites.com/cloudflare-zero-trust-a-fondo/). Y el mismo mecanismo, con un token de servicio, es el que usa [Hyperdrive para llegar a una base de datos privada](https://blog.devutilites.com/cloudflare-hyperdrive-a-fondo/).

⚠️

**Tunnel no sustituye a la autenticación.** Un servicio publicado con un túnel y sin Access es tan público como si hubieras abierto el puerto, solo que sin exponer tu IP.

## 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 `path` recorte 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, `cloudflared` no podrá verificarlo (la opción de origen `noTLSVerify` viene 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](https://blog.devutilites.com/cloudflare-zero-trust-a-fondo/).

## Sigue leyendo

- [Cloudflare a fondo](https://blog.devutilites.com/cloudflare-a-fondo/): la visión general de la plataforma.
- [Cloudflare Zero Trust a fondo](https://blog.devutilites.com/cloudflare-zero-trust-a-fondo/): Access, Gateway y el cliente de Cloudflare One.
- [Cloudflare DNS a fondo](https://blog.devutilites.com/cloudflare-dns-a-fondo/): los CNAME que apuntan al túnel.
- [Cloudflare WAF y protección DDoS a fondo](https://blog.devutilites.com/cloudflare-waf-ddos-a-fondo/): la seguridad que se aplica antes del túnel.
- [Cloudflare Hyperdrive a fondo](https://blog.devutilites.com/cloudflare-hyperdrive-a-fondo/): bases de datos privadas a través de un túnel.