Yo Portafolio Blog

Como lidiar con CGNAT y exponer tus aplicaciones locales usando Cloudflare Tunnels

Ariel Aguirre
Diagrama de Cloudflare Tunnels

Muchas veces nos encontramos en la situación de ser clientes de un proveedor de internet (ISP) que debido a la escasez de IPv4 (guiño), tiene >1000 clientes detrás de una sola IP pública, es decir el ISP usa Carrier Grade NAT (CGNAT), por lo que abrir puertos de tu router resulta una tarea imposible. pain in cgnat

Por suerte tenemos varias opciones para acceder a nuestros servicios locales si estamos detrás de una CGNAT, como usar un VPS (Servidor Virtual Privado) de un proveedor como AWS, Google Cloud, Linode, etc. Para redirigir tu trafico mediante esa IP publica o mediante una VPN. Sin embargo el servicio puede llegar a ser costoso a largo plazo, sin mencionar que no todos los planes básicos ofrecen tráfico ilimitado.

En esta ocasión vamos a utilizar una forma bastante práctica para los entusiastas que no quieren usar un VPS de los proveedores mas populares como Google Cloud, AWS, entre otros.

Estoy hablando de Clouflare Tunnels , un servicio que permite exponer nuestros servicios locales a través de internet sin necesidad de una IP publica.

Como funciona:

Diagrama de funcionamiento

Cloudflared es un cliente que establece conexiones salientes entre los recursos de nuestro servidor local y la red global de Cloudflare. Dicho cliente esta disponible para macOS, Linux, imagen de Docker y windows.

Los requisitos para usar CT son:

  • Dominio (Cualquier dominio, de preferencia adquirido en cloudflare)
  • Cliente (Linux, Windows, macOS)

Utilizaremos CT para exponer nuestro servidor de VaultWarden, un servidor alternativo y de código abierto del gestor de contraseñas Bitwarden

Registro en Cloudflare

Página de registro

Vamos a registrarnos con Google, Apple o con correo electrónico.

Cloudflare Dashboard

Dashboard de Cloudflare

Compra de dominio

Creación del tunnel

Hay dos formas de crear túneles, a través de la dashboard de cloudflare o mediante la API.

Dashboard

API

Paso 1: Crear un API TOKEN

Dirigirse a User API Tokens, en el dashoard de Cloudflare: API TOKENS DASHBOARD

Crear API TOKEN con los siguientes permisos:

TipoItemPermiso
AccountCloudflare TunnelEdit
ZoneDNSEdit

Seleccionamos “Custom token”: alt text

Asignamos los permisos necesarios:

alt text

Continuar y crear:

alt text

Token creado:

alt text

Probando el token con CURL:

#!/bin/bash
# Petición para probar token generado con CURL
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
  -H "Authorization: Bearer TU_TOKEN_AQUI" \
  -H "Content-Type:application/json"

Response:

{
  "result": { "id": "cd8b1ee8831fe5f17207d680301994a7", "status": "active" },
  "success": true,
  "errors": [],
  "messages": [
    {
      "code": 10000,
      "message": "This API Token is valid and active",
      "type": null
    }
  ]
}

Todo correcto. Una vez tengamos el token podemos empezar a crear los tuneles.

Paso 2: Crear un tunnel

Haremos una petición de tipo POST al endpoint de Cloudflare:

Parametros requeridos:

#!/bin/bash
# Petición para crear el tunnel
curl 'https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/cfd_tunnel' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--data '{
  "name": "api-tunnel",
  "config_src": "cloudflare"
}'

Response:

{
  "success": true,
  "errors": [],
  "messages": [],
  "result": {
    "id": "[REDACTED_TUNNEL_ID]",
    "account_tag": "[REDACTED_ACCOUNT_TAG]",
    "created_at": "2025-04-15T23:43:04.876882Z",
    "deleted_at": null,
    "name": "api-tunnel",
    "connections": [],
    "conns_active_at": null,
    "conns_inactive_at": "2025-04-15T23:43:04.876882Z",
    "tun_type": "cfd_tunnel",
    "metadata": {},
    "status": "inactive",
    "remote_config": true,
    "credentials_file": {
      "AccountTag": "[REDACTED_ACCOUNT_TAG]",
      "TunnelID": "[REDACTED_TUNNEL_ID]",
      "TunnelName": "api-tunnel",
      "TunnelSecret": "[REDACTED_SECRET]"
    },
    "token": "[REDACTED_TOKEN]"
  }
}

Importante copiar el token y result->id. Son necesarios para configurar el tunnel.

Paso 3: Conectar nuestra red privada al tunnel

Creamos una ruta para el tunel:

Parámetros requeridos:

  • $ACCOUNT_ID
  • $CLOUDFLARE_API_TOKEN
  • $TUNNEL_ID
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/teamnet/routes \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--data '{
  "network": "172.16.0.0/16", #La misma que nuestra red interna
  "tunnel_id": '$TUNNEL_ID',
  "comment": "Ruta de ejemplo a red privada"
}'

Response:

{
  "result": null,
  "success": false,
  "errors": [
    {
      "code": 7003,
      "message": "Could not route to /client/v4/accounts/df84a7ab8eec86cb474e9bc6d88c5d3/teamnet/routes, perhaps your object identifier is invalid?"
    }
  ],
  "messages": []
}

Posibles problemas y restricciones

  • El ISP bloquea rangos de IP de Cloudflare: Últimamente algunos proveedores, debido a la piratería, sobre todo de retransmisión de partidos de fútbol. En su afán de combatir la piratería han tomado la desesperada acción de bloquear rangos de IP completos. Dejando fuera de linea no solo los sitios piratas sino todo tipo de servicio que esté detrás de Cloudflare.
  • Cloudflare en su plan básico no acepta subidas de más de 100 MB, personalmente he tenido problemas al usar Immich