11

Simplifica el acceso a redes privadas: conecta GitHub Actions y AWS con Cloudflare Tunnels

15979Puntos

hace 3 meses

Soy Fernando Muñoz, Cloud Engineer en Platzi, certificado en GitHub Actions y AWS Solutions Architect Associate. Hoy quiero que descubras cómo puedes transformar tu flujo de trabajo al utilizar Cloudflare Tunnels, una tecnología que proporciona una forma simple y segura de interconectar redes.

En este blog, te guiaré paso a paso para conectar GitHub Actions a redes privadas de AWS de manera segura y eficiente. Sin embargo, los Tunnels de Cloudflare van mucho más allá y no se limitan a estos dos únicos proveedores, ya que te permiten conectar prácticamente con cualquier proveedor de la nube actual e incluso puedes conectar con tu red local.

¿Qué conocimientos previos necesitas para este blog?

Para aprovechar al máximo el contenido de este blog, es importante contar con conocimientos en las siguientes áreas:

  • VPC y subredes en AWS: comprender cómo funcionan las redes virtuales y las subredes en AWS es crucial para configurar conexiones seguras y eficientes.
  • Estructura de flujos de GitHub Actions: estar familiarizado con la organización y ejecución de flujos de trabajo en GitHub Actions permitirá integrar y automatizar procesos de manera efectiva.

Si aún no dominas estos temas, te recomiendo explorar los siguientes cursos para fortalecer tus habilidades:

Estos cursos te proporcionarán una base sólida para seguir adelante con confianza y sacar el máximo provecho de las tecnologías que exploraremos en este blog.

Hicimos una versión en video del blog por si prefieres escuchar la explicación o usarlo como podcast.

¿Qué es Cloudflare Tunnel?

Déjame darte una breve introducción:

Es una solución de software que protege tus servidores web de ataques directos al crear un túnel cifrado entre tu servidor de origen y el centro de datos más cercano de Cloudflare, sin necesidad de abrir puertos públicos.

Esto asegura que las direcciones IP de tus servidores permanezcan ocultas, bloqueando ataques DDoS y brechas de datos. A diferencia de métodos tradicionales como las listas de control de acceso (ACLs) o los túneles GRE, Cloudflare Tunnel es más rápido, seguro y fácil de configurar, proporcionando una protección integral y eficiente para aplicaciones en cualquier infraestructura, ya sea en la nube pública, privada o incluso en dispositivos locales.
Pasted image 20240819005153.png
Tunnel | Zero Trust App Connector | Cloudflare

Hablemos del problema: cómo conectar los Runners de GitHub con una red privada de AWS

Pasted image 20240819000912.png

Imagina dos mundos separados: por un lado, la red donde operan los GitHub Actions Runners, y por otro, nuestra red privada en AWS. Estos dos mundos no se conocen ni tienen un camino para comunicarse. Nuestra misión es crear un puente, o mejor dicho, un túnel que permita a los Runners de GitHub interactuar con los recursos privados de AWS.

Para ser más claros, en AWS tengo dos instancias de EC2 dentro de subredes privadas, donde, por ejemplo, no tengo IP pública, sino solo IP privada. Y además en AWS, tengo un EKS.

CleanShot 2024-08-21 at 2 .40.46.png
CleanShot 2024-08-21 at 2 .55.09.png

Si yo intentara hacer ping o SSH a esa máquina en este momento, fallaría porque no hay nada que permita conectarlas entre sí. Debería aparecer un mensaje de error del tipo Connection timed out o similar.

CleanShot 2024-08-21 at 2 .49.00.png

O, por ejemplo, ¿qué pasa si tenemos un EKS desplegado y queremos interactuar con él desde GitHub Actions?
CleanShot 2024-08-21 at 2 .53.41.png

Como vemos, en ambos casos los Actions nos devuelven un error debido a que no pueden alcanzar esa red privada.

Ahora, podrías preguntarte: ‘Fernando, ¿por qué no simplemente usar GitHub Self-Hosted Runners?’ Y… es una opción válida. Sin embargo, como en todo en ingeniería de software, la elección depende de tus necesidades específicas.

Por qué usar Cloudflare Tunnel

Aquí te explico por qué Cloudflare Tunnel puede ser una opción más ventajosa:

  • Simplicidad de Configuración: Cloudflare Tunnel es fácil de configurar y mantener, sin la carga de gestionar infraestructura adicional, a diferencia de los Self-Hosted Runners, cuya gestión recae completamente en ti.
  • Seguridad Mejorada: Ofrece una capa adicional de seguridad al cifrar el tráfico y mantener los recursos internos protegidos de la exposición a Internet.
  • Escalabilidad: No necesitas preocuparte por escalar la infraestructura de los Runners, ya que GitHub se encarga de ello, permitiendo un escalado automático según la demanda.
  • Costos Operativos: Se eliminan los costos de mantener y operar servidores adicionales para los Self-Hosted Runners.

Nuestro objetivo es claro:

  • Informar a GitHub de que existe un camino seguro hacia ciertos recursos.
  • Utilizar Cloudflare Tunnel como ese camino privado.
  • Hacer visible nuestra red de AWS en este mapa de conexiones.
Pasted image 20240819002505.png

Para lograrlo, introduciremos dos conceptos clave:

  • Cloudflare WARP: un cliente que protege dispositivos enviando tráfico de manera segura a la red global de Cloudflare, permitiendo el acceso a orígenes privados detrás de los Tunnels para tráfico de Capa 4 sin comandos adicionales.
  • cloudflared: un cliente de línea de comandos para Cloudflare Tunnel que enruta el tráfico desde la red de Cloudflare hacia tus servidores de origen, manteniendo tu infraestructura segura y cerrada.

Entonces, procederemos a:

  1. Configurar nuestro Cloudflare Tunnel.
  2. Instalar cloudflared en AWS para abrir un camino desde nuestra red privada hacia el Tunnel.
  3. Configurar WARP en GitHub Actions para acceder al Tunnel y descubrir las redes privadas disponibles.

¡Manos a la obra! Primero haremos todas las configuraciones necesarias en nuestra cuenta de Cloudflare.

Cómo configurar Cloudflare Tunnel

Ahora, vamos a crear el Tunnel y dejarlo listo para recibir conexiones.

  1. Dentro de la sección de Zero Trust de tu cuenta de Cloudflare, nos dirigiremos a la parte de Networks/Tunnels y haremos clic en Add Tunnel.
    CleanShot 2024-08-20 at 9 .04.03.png

  2. En Tunnel type, seleccionaremos cloudflared, le pondremos el nombre de nuestra preferencia al túnel y haremos clic en el botón “Save tunnel”.
    CleanShot 2024-08-20 at 9 .06.58.png

CleanShot 2024-08-20 at 9 .07.24.png
  1. Una vez guardado el túnel, aparecerán unas instrucciones para instalar y ejecutar el conector. No te preocupes por esto, ya que aparecerán siempre que intentes modificar el túnel. Básicamente, son los comandos para instalar y el token para ejecutar Cloudflare apuntando a nuestro túnel. Hacemos clic en el botón “Next”.
CleanShot 2024-08-20 at 9 .08.52.png
  1. En esta última parte de la configuración del túnel, vamos a indicar a qué red privada deseamos crear la conexión. Entonces, hacemos clic en la pestaña que se llama Private Networks y colocaremos el CIDR de nuestra VPC de AWS. Hacemos clic en “Save tunnel”.
CleanShot 2024-08-20 at 9 .11.32.png
  1. En este punto ya tenemos nuestro túnel creado, pero en estado “Inactive” porque todavía no hay ningún cloudflared conectándose a él. Tu túnel debería verse así.
CleanShot 2024-08-20 at 9 .13.26.png

Configuración del Access Group y Service Token en Cloudflare

En esta sección configuraremos ¿Quién? y ¿Cómo? pueden conectarse a nuestra cuenta de Cloudflare.

  1. Siempre dentro de la sección de Zero Trust de nuestra cuenta de Cloudflare, nos dirigimos al apartado de Access/Service Auth y hacemos clic en Create Service Token."
CleanShot 2024-08-20 at 9 .20.17.png
  1. Escogemos un nombre para nuestro Service Token y una duración (fecha en la que expirará y será necesario renovarlo). Hacemos clic en Generate Token.
CleanShot 2024-08-20 at 9 .21.22.png
  1. Se nos mostrarán los detalles del Token, que consisten en un Header and client ID y un Header and client secret. Estos datos son muy sensibles, por lo cual debes resguardarlos en lugares muy seguros. Hacemos clic en el botón Save. Se nos mostrará el resumen de todos los tokens de nuestra cuenta.
CleanShot 2024-08-20 at 9 .22.54.png
CleanShot 2024-08-20 at 9 .25.40.png
  1. Ahora nos moveremos a la sección Access/Access Group y haremos clic en el botón Add a group.
CleanShot 2024-08-20 at 9 .26.30.png
  1. Escogeremos un nombre para nuestro nuevo grupo y en la parte de Define group criteria seleccionaremos en el Selector el valor de Service Token y en su Value buscaremos el nombre del Service Token que acabamos de crear. Haremos clic en el botón Save.
CleanShot 2024-08-20 at 9 .28.43.png
  1. Se nos mostrará el resumen de los Access Groups que tengamos en nuestra cuenta, donde veremos un campo llamado Group ID. Copiaremos este ID y lo tendremos a mano.
CleanShot 2024-08-20 at 9 .29.35.png

Configuración del enrolamiento al cliente WARP de Cloudflare

En esta sección nos centraremos en cómo alguien o algo puede unirse a nuestra cuenta de Cloudflare mediante el cliente WARP.

  1. Siempre dentro de Zero Trust de Cloudflare, nos moveremos a la sección de Settings y buscaremos la opción de WARP Client. Luego, haremos clic en el botón Manage en la sección de Device enrollment.
CleanShot 2024-08-20 at 9 .33.40.png
CleanShot 2024-08-20 at 9 .41.31.png
  1. Ahora, dentro de Rules, crearemos una nueva regla haciendo clic en Add a rule.
CleanShot 2024-08-20 at 9 .42.41.png
  1. Aquí le pondremos un nombre a esta nueva regla y en Rule Action seleccionaremos Service Auth. En Selector escogeremos Service Token y en el Value el token que generamos previamente. Finalmente, asignaremos esta nueva política al Access Group que creamos anteriormente. Haremos clic en el botón Save.
CleanShot 2024-08-20 at 9 .45.07.png
  1. Se nos mostrará el resumen de las políticas del cliente WARP de nuestra cuenta.
CleanShot 2024-08-20 at 9 .45.56.png

Configuración del comportamiento del cliente WARP de Cloudflare

En esta sección nos centraremos en la creación de un perfil para el cliente WARP y en asegurarnos de que todos los usuarios que cumplan los criterios utilicen el túnel y realicen el split del tráfico indicado.

  1. Siempre dentro de la sección Zero Trust de Cloudflare, nos dirigiremos a Settings y buscaremos la opción WARP Client.
CleanShot 2024-08-20 at 9 .33.40 (1).png
  1. Buscaremos la sección que se llama Device settings y haremos clic en el botón Create profile.
CleanShot 2024-08-20 at 9 .34.37.png
  1. Aquí configuraremos el nombre de este nuevo perfil y determinaremos qué usuarios entrarán dentro de este perfil. En la sección Build an expression, seleccionaremos User group IDs en Selector, in en Operator y colocaremos el Group ID que obtuvimos en pasos previos en Value. Podemos dejar todos los demás campos como están (o modificarlos según tus necesidades) y al final de la página, haremos clic en el botón Create profile.
CleanShot 2024-08-20 at 9 .38.03.png
  1. Ahora que nuestro perfil ha sido creado, podemos configurar qué tráfico queremos enviar a nuestro túnel y cuál no. Esto es para evitar que en las computadoras otros servicios y aplicaciones se vean afectados por nuestro cliente WARP y se comporten erróneamente. Para ello, hacemos clic en el botón Configure dentro de nuestro perfil.
CleanShot 2024-08-20 at 9 .49.17.png
  1. Se nos mostrarán todas las opciones configurables dentro del perfil, buscaremos la sección Split Tunnels, por defecto esta en Exclude IPs and domains, daremos click en Manage.

Por cierto es más fácil usar el modo Include IPs and domaians , pero te dejo de tarea investigar como se utiliza esta opción.

CleanShot 2024-08-20 at 9 .49.45.png
  1. Dado el modo Exclude, aparecerá una lista previa de direcciones que el cliente WARP evitará para no generar conflictos con otras aplicaciones y, de esta manera, garantizar que solamente el tráfico legítimo que queremos que viaje por el cliente WARP y, por ende, por nuestro túnel de Cloudflare, lo haga.

Es importante leer esta documentación de Cloudflare para entender cómo funciona: Change Split Tunnels mode by Cloudflare

En mi caso, mi VPC tiene el CIDR como 10.0.0.0/16 y mis subredes se ven así:

3 subnets privadas:

  • private-1: 10.0.48.0/20
  • private-2: 10.0.64.0/20
  • private-3: 10.0.80.0/20

3 subnets públicas:

  • public-1: 10.0.0.0/20
  • public-2: 10.0.16.0/20
  • public-3: 10.0.32.0/20

Dato geek: el bloque 10.0.0.0 (prefijo 10/8) es un bloque de direcciones IP privadas definido por la RFC 1918, que abarca desde 10.0.0.0 hasta 10.255.255.255. Es uno de los rangos de IPs comúnmente utilizado en redes privadas. https://www.rfc-es.org/rfc/rfc1918-es.txt

Entonces, dado que nuestra VPC utiliza el rango 10.0.0.0/16, vamos a eliminar el rango 10.0.0.0/8 que ya estaba agregado previamente en nuestro Split Tunnel.

CleanShot 2024-08-20 at 10 .04.56.png

Ahora, excluiremos los rangos que no estamos utilizando explícitamente en nuestras subredes. Esto es para evitar que ese tráfico viaje por nuestro WARP y así no afecte a servicios o aplicaciones que no deberían pasar por aquí.

En mi caso serían:

10.0.96.0/1910.0.128.0/17

¿Cómo calculamos esto?

a. Identificar el rango total de la VPC; en mi caso, 10.0.0.0/16, con IPs disponibles desde 10.0.0.0 hasta 10.0.255.255.
b. Ordenar las subredes por su dirección de inicio.

10.0.0.0/20 (10.0.0.0 - 10.0.15.255)
10.0.16.0/20 (10.0.16.0 - 10.0.31.255)
10.0.32.0/20 (10.0.32.0 - 10.0.47.255)
10.0.48.0/20 (10.0.48.0 - 10.0.63.255)
10.0.64.0/20 (10.0.64.0 - 10.0.79.255)
10.0.80.0/20 (10.0.80.0 - 10.0.95.255)

c. Identificar si tenemos huecos, que en este caso no tenemos. Pero un hueco sería, por ejemplo, tener una subred 10.0.0.0/20 que cubre de 10.0.0.0 a 10.0.15.255 y que nuestra siguiente subred sea 10.0.32.0/20, que cubre de 10.0.32.0 a 10.0.47.255, entonces no tenemos ninguna subred que cubra de 10.0.16.0 a 10.0.31.255.

d. Todos esos huecos son los rangos que no utilizamos; los transformamos a notación CIDR y obtendríamos 10.0.16.0/20.

e. En mi caso, no estoy usando el rango de 10.0.96.0 a 10.0.255.255, de ahí es donde aparecen los CIDR 10.0.96.0/19 y 10.0.128.0/17.

  1. Una vez agregados esos CIDR que queremos excluir de nuestro túnel, y que deseamos que nuestro cliente WARP no considere, casi hemos terminado.
CleanShot 2024-08-20 at 10 .29.37.png

¡De momento, felicidades! Hemos terminado de configurar todo lo necesario dentro de nuestra cuenta de Cloudflare. Ahora solo nos falta configurar el cloudflared en una instancia dentro de nuestra cuenta de AWS y configurar el warp-cli en GitHub Actions.

Configuración de cloudflared en nuestra VPC de AWS

  1. Desde una instancia pública, nos conectamos a la instancia privada donde queremos instalar nuestro daemon cloudflared.
CleanShot 2024-08-21 at 3 .02.36.png
  1. Ahora seguiremos una serie de comandos para instalar cloudflared en esta instancia privada. En mi caso, para las EC2 con Amazon Linux, los comandos son los siguientes: 
    Puedes ver los comandos para otros OS aquí: Download and install cloudflared
curl -fsSL https://pkg.cloudflare.com/cloudflared-ascii.repo | sudo tee /etc/yum.repos.d/cloudflared.repo
sudo yum update
sudo yum install cloudflared
CleanShot 2024-08-21 at 3 .06.48.png
  1. Una vez instalado cloudflared, podemos verificar su instalación con el comando cloudflared version.
CleanShot 2024-08-21 at 3 .07.08.png
  1. Ahora solo faltaría hacer join de este daemon a nuestro túnel de CF. Para ello, dentro de nuestra cuenta de Cloudflare en la sección de Zero Trust, vamos a editar el túnel que creamos y copiamos el código que aparece en el apartado If you already have cloudflared installed on your machine.
CleanShot 2024-08-21 at 3 .13.33.png
  1. Ejecutamos ese código en nuestra EC2 donde hemos instalado cloudflared.
CleanShot 2024-08-21 at 3 .15.22.png
  1. Y listo, ya nuestro túnel debe aparecer con un estado Healthy. Esto indica que hemos completado uno de los caminos de nuestro túnel. Ese daemon sirve como conector para nuestro túnel e indica a qué dirección llevarnos para descubrir esos recursos privados.
CleanShot 2024-08-21 at 3 .16.48.png

Configuración del warp-cli en GitHub Actions

Bien, ahora por fin vamos a ver el resultado de todo nuestro trabajo. Como último paso en las ejecuciones de GitHub Actions, tenemos que configurar el warp-cli para que nuestro Runner pueda interactuar con los recursos privados de AWS. Primero desglosaré por partes el action para explicar algunas cosas.

  1. Instalación de warp-cli
      - name: Install CF WARP
        run: |
          curl https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
          echo "deb [arch=amd64 signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list
          sudo apt-getupdate && sudo apt-getinstall cloudflare-warp
  1. Generamos un archivo mdm.xml dentro del directorio /var/lib/cloudflare-warp, con el contenido que nos generó el Service Token que creamos al inicio. Donde:

    • organization corresponde al nombre de nuestra organización en Zero Trust.
    • auth_client_id es el CF-Access-Client-Id que nos generó el Service Token.
    • auth_client_secret es el CF-Access-Client-Secret que nos generó el Service Token.

    Guardé esos valores dentro de GitHub como secretos.

      - name: Generate mdm.xml file in /var/lib/cloudflare-warprun: |
          sudo mkdir -p /var/lib/cloudflare-warp
          echo '
          organization${{ secrets.ORGANIZATION }}auth_client_id${{ secrets.AUTH_CLIENT_ID }}auth_client_secret${{ secrets.AUTH_CLIENT_SECRET }}' | sudo tee /var/lib/cloudflare-warp/mdm.xml
          sudo chmod 777 /var/lib/cloudflare-warp/mdm.xml
  1. Reiniciamos el servicio de warp y hacemos una pausa de 5 segundos para garantizar que el servicio esté habilitado antes de continuar con los siguientes pasos del action.
      - name: Restart cloudflare-warp service
        run: sudo systemctl restart warp-svc.service && sleep 5
  1. Procedemos a indicarle al warp que se conecte e inicie sesión. Esto debería devolvernos un éxito.
      - name: warp-cli connect
        run: warp-cli --accept-tos connect && sleep20
  1. Ya en este punto deberíamos poder ver dentro de la lista de dispositivos en Cloudflare Zero Trust, nuestro runner. Esto indica que nuestro **warp-cli **se conectó correctamente a nuestra cuenta y, por ende, puede utilizar nuestro túnel.
CleanShot 2024-08-21 at 4 .32.53.png
CleanShot 2024-08-21 at 4 .30.55.png
  1. Genial, ahora solo nos falta indicarle a la tabla de rutas de la máquina del Runner de Action que todo el tráfico que intente dirigirse a nuestra CIDR de la VPC de AWS, debe salir por el WARP. Para lograr esto, ejecutamos el siguiente comando.
      - name: Set route ip        run: sudo ip route add CIDR_DE_TU_VPC dev CloudflareWARP
  1. Y listo, ya en este punto nuestro GitHub Actions debería poder interactuar con los recursos privados de nuestra cuenta de AWS. Veamos cómo se comportan ahora los dos casos que planteamos al inicio de este blog.

Conexión SSH a una EC2

CleanShot 2024-08-21 at 5 .19.44.png

Conexión al EKS

CleanShot 2024-08-21 at 5 .43.09.png
  1. Como último paso, es muy recomendable ejecutar los siguientes comandos para desconectar el WARP y limpiar todos los recursos que hemos creado con claves privadas.
      - name: warp-cli disconnect
        if: always()
        run: warp-cli --accept-tos disconnect

      - name: Delete cloudflare-warp folder
        if: always()
        run: |
          sudo rm -rf /var/lib/cloudflare-warp

¿Qué aprendiste después de leer este blog?

Hemos terminado y me gustaría darte los puntos concretos de lo que hemos logrado:

  • De Cloudflare, aprendiste a utilizar Zero Trust creando un Service Token y un Access Group.
  • Creaste tu primer Cloudflare Tunnel y aprendiste cómo configurar el enrolamiento de Cloudflare WARP.
  • Configuraste cloudflared en una instancia privada para darle acceso al túnel a una red privada.
  • Viste el flujo de un GitHub Actions para instalar y autenticar el WARP CLI de Cloudflare.

Sigue al pendiente del blog de Platzi; próximamente habrá un nuevo artículo como este de Engineering by Platzi. Pero mientras tanto, también puedes leer este otro blog: Cloudflare Pages: Cómo construimos una librería para hacer despliegues

Comparte el artículo si te pareció útil y crees que a alguien más le podría servir; y por supuesto, nos encantaría leerte en los comentarios.

Fernando Andres
Fernando Andres
fernandomunoz

15979Puntos

hace 3 meses

Todas sus entradas
Escribe tu comentario
+ 2