papanito.cloudflared

Rol de Ansible "papanito.cloudflared"

Rol de Ansible Calidad de Ansible Rol de Ansible Problemas en GitHub Pull requests en GitHub

Esta rol de Ansible descarga e instala cloudflared en el host y opcionalmente instala argo-tunnel como un servicio.

Cambios importantes en la versión 3.0.0

Este es un cambio importante para reflejar el nuevo comportamiento de túneles nombrados

La rol debería encargarse de la limpieza si usaste la rol antes de la versión 3.0.0. Sin embargo, tienes que actualizar la configuración (variables) en tu proyecto de Ansible. He renombrado las variables, en general prefijadas con cf_, para hacerlas únicas para la rol. Si no son únicas, puede suceder que las variables con el mismo nombre en diferentes roles tengan efectos secundarios no deseados.

Cloudflared y conexión de aplicaciones a túneles

Según 1, para crear y gestionar Túneles, primero debes:

  1. Descargar e instalar cloudflared en tu máquina
  2. Autenticar cloudflared

Una vez que cloudflared ha sido instalado y autenticado, el proceso para poner en marcha tu primer Túnel incluye 3 pasos generales:

  1. Crear un Túnel
  2. Dirigir el tráfico a tu Túnel
  3. Ejecutar tu Túnel

Los pasos 4-5 se ejecutan una vez por Túnel, normalmente por un administrador, y el Paso 6 se ejecuta cada vez que se va a iniciar el Túnel, normalmente por el propietario del Túnel (quien puede ser diferente del administrador).

¿Qué hace la rol?

La rol tiene en realidad dos propósitos:

Instalación del daemon en el lado del servidor

La rol solo se encarga de configurar el servicio en los nodos, es decir, pasos 1, 2, 4 y 5 de arriba, porque

Crear túneles y habilitar el enrutamiento es una tarea que debe realizar un administrador y no la rol 1

Puedes configurar uno o múltiples [túneles nombrados] así como [un único servicio]; incluso así, con [túneles nombrados] usualmente solo necesitas un daemon. La rol efectivamente realiza los siguientes pasos:

  1. Descargar e instalar el binario según downloads

  2. Instalar/configurar el daemon - ver Autenticar el daemon

  3. Para [túneles nombrados] se crea un [archivo de credenciales] en {{ cf_credentials_dir }}/{{ tunnel_id }}.json, similar a esto

    {"AccountTag":"{{ account_tag }}","TunnelSecret":"{{ tunnel_secret }}","TunnelID":"{{ tunnel_id }}","TunnelName":"{{ cf_tunnels.key }}"}
    
  4. Para cada clave en cf_tunnels, crear una configuración de túnel en /etc/cloudflare

    El archivo se llama {{ tunnel }}.yml y contendrá la configuración mínima, que es la siguiente:

    túneles nombrados

    tunnel: {{ cf_tunnels.key }}
    credentials-file: {{ cf_credentials_dir }}/{{ tunnel_id }}.json
    ingress:
      {{ item.value.ingress }}
    

    un solo servicio

    hostname: {{ hostname }}
    url: {{ url }}
    

    Se configuran parámetros adicionales mediante parámetros de configuración del túnel

  5. Dependiendo de tu sistema de inicio - controlado por cf_init_system - la rol realiza lo siguiente

    • Systemd

      Crear una [plantilla de unidad de systemd] cloudflared@{{ tunnel }}.service y comenzar una instancia para cada servicio en la lista de cf_tunnels

      cloudflared tunnel --config {{ tunnel }}.yml
      
    • Sistemas Init-V

      1. Instalar servicio cloudflared en /etc/init.d/{{ systemd_filename }}-{{ tunnel_name }}
      2. Vincular el script de detención a /etc/init.d/{{ systemd_filename }}-{{ tunnel_name }}
      3. Vincular el script de inicio a /etc/init.d/{{ systemd_filename }}-{{ tunnel_name }}
  6. Si usas [túneles nombrados], la rol también creará una [ruta dns].

Configuración del cliente SSH

Desde donde accesas a tus nodos a través de ssh, que está proxiedo por cloudflared, necesitas seguir [guía de ssh-cliente]. Tienes que añadir lo siguiente

Host xxx.mycompany.com
  ProxyCommand /usr/bin/cloudflared access ssh --hostname %h

Puedes lograr esta configuración si habilitas cf_ssh_client_config. Además, también necesitas especificar cf_ssh_client_config_group. Así que asumamos que tu inventario se ve de la siguiente manera:

all:
  children:
    servers:
      hosts:
        host001:
        host002:

Si especificas cf_ssh_client_config_group: servers, obtendrás una entrada para host001 y host002.

Requisitos

ninguno

Variables de la rol

Parámetros de instalación y desinstalación

Los siguientes parámetros controlan la instalación y/o desinstalación:

Parámetro Descripción Valor por defecto
cf_download_baseurl URL base para los binarios de cloudflare https://github.com/cloudflare/cloudflared/releases/latest/download/
cf_install_only Establecer a true si solo deseas instalar el binario sin configuración ni inicio de sesión false
cf_ssh_client_config Establecer a true si deseas configurar la configuración del proxy para tu [guía de ssh-cliente] false
cf_ssh_client_config_group Nombre del grupo de inventario para el cual se creará la configuración del proxy ssh ``
cf_force_install Establecer a true si deseas reinstalar cloudflared. Por defecto, se asume que cloudflared se está ejecutando como un servicio y se actualiza automáticamente. false
cf_remove_unused_tunnel Elimina túneles cf_tunnels no utilizados, es decir, cf_tunnels que se están ejecutando pero no están listados en cf_tunnels. false
cf_remove_setup_certificate Eliminar cert.pem después de instalar el servicio false
cf_credential_file_base Carpeta donde se colocan los archivos de credenciales /root/.cloudflared/
cf_config_dir Carpeta donde se colocan los archivos de configuración de cloudflare /etc/cloudflared
cf_os_package_enable Usar el sistema de empaquetado del SO y el repositorio de paquetes de Cloudflare (actualmente solo Debian/Ubuntu) false
cf_repository_key_url Si cf_os_package_enable es verdadero, URL de la clave GPG para el repositorio apt https://pkg.cloudflare.com/pubkey.gpg
cf_repository_key_install_path Si cf_os_package_enable es verdadero, ruta donde instalar la clave GPG para el repositorio apt /usr/share/keyrings/cloudflare-main.gpg
cf_repository Si cf_os_package_enable es verdadero, URL para el repositorio apt de Cloudflare deb [signed-by={{ cf_repository_key_install_path }}] https://pkg.cloudflare.com/cloudflared {{ ansible_distribution_release }} main
cf_binary_name Nombre del binario del daemon de cloudflare - cambia solo si sabes lo que estás haciendo cloudflared

Parámetros del servicio Cloudflared

Estos son los parámetros requeridos para crear el servicio del sistema:

Parámetro Descripción Valor por defecto
cf_init_system Definir qué servicio de inicio usar. Los valores posibles son systemd e initv systemd
cf_systemd_user Usuario para el servicio systemd en caso de cf_init_system: systemd root
cf_systemd_group Grupo para el servicio systemd en caso de cf_init_system: systemd root
cf_cert_location Ubicación del certificado que se debe copiar - ver Autenticar el daemon -
cf_cert_content Contenido del certificado que se debe copiar - ver Autenticar el daemon -
cf_tunnels [Obligatorio] Lista de servicios de túnel, cada uno definiendo parámetros de Cloudflare -
cf_sysctl_buffer_size_increase Aumentar el tamaño del buffer UDP recibido permitido por el SO (no BSD) - más detalles false

Se recomienda usar [túneles nombrados] para cf_tunnels, lo que requiere parámetros de túnel nombrado de Cloudflare, pero también puedes usar parámetros de túnel heredados de Cloudflare.

Parámetros de túnel nombrado de Cloudflare

  ...
    cf_tunnels:
      test:
        routes:
          dns:
            - "{{ inventory_hostname }}"
          cidr:
            - "192.168.42.0/24"
          lb:
            - hostname: website.mycompany.com
              poolname: bzh-west1.website.mycompany.com
        account_tag:  !vault....
        tunnel_secret: !vault....
        tunnel_id: !vault....
        ingress:
          - hostname: website.mycompany.com
            service: http://localhost:1313
          - hostname: hello.mycompany.com
            service: hello_world
          - hostname: ssh.mycompany.com
            service: ssh://localhost:22
          - service: http_status:404

La clave del túnel debe coincidir con la de tunnel_id.

Parámetro Descripción Valor por defecto
account_tag [Obligatorio] Etiqueta de cuenta del [archivo de credenciales] generado al crear un túnel -
tunnel_secret [Obligatorio] Secreto del túnel del [archivo de credenciales] generado al crear un túnel -
tunnel_id [Obligatorio] ID del túnel del [archivo de credenciales] generado al crear un túnel -
ingress [Obligatorio] [reglas de ingreso] para el túnel -
routes Lista de rutas que deben ser creadas. En este momento permite una lista para las rutas dns (ver ejemplo arriba) -

Rutas

DNS

Las rutas dns esperan una lista de CNAME que se deben crear como se describe aquí. Si el CNAME ya existe, la tarea se omitirá pero no se lanzará ningún error. Además, solo agrega CNAME, no un FQDN, ya que el FQDN es determinado por cloudflared.

Red Privada

Las rutas de red privada esperan una lista de CIDR que se deben crear como se describe aquí. El playbook recorre la lista para ejecutar cloudflared tunnel route ip add {{ cf_cidr_entry }} {{ cf_tunnel.key }}. Si el CIDR ya existe, se lanzará un error pero se ignorará.

Balanceador de Carga

Las rutas lb esperan una lista de balanceadores de carga existentes de cloudflared (más su grupo) para enrutarse a través del túnel como se describe aquí. El playbook recorre la lista para ejecutar cloudflared tunnel route lb {{ cf_tunnel.key }} {{ cf_lb_entry.host_name }} {{ cf_lb_entry.pool_name }}. Si el túnel ya está vinculado al grupo, se lanzará un error ignorado.

Parámetros de servicio único de Cloudflare

Al igual que con versiones anteriores de estas roles, puedes usar el estilo de configuración de servicio único.

Si necesitas enviar tráfico solo a un servicio local, puedes hacerlo usando el archivo de configuración. Como alternativa, puedes configurar la configuración de servicio único.

cf_tunnels:
  ssh:
    hostname: xxx
    url: ssh.mycompany.com
Parámetro Descripción Valor por defecto
hostname [Obligatorio] Nombre o único -
url [Obligatorio] URL a la que conectarse config e.g. ssh://localhost:22 o https://localhost:443 -

Parámetros de configuración del túnel

Estos se utilizan para configurar los parámetros por servicio cloudflared. Aún puedes configurar Configuración por regla para túneles nombrados como parte del ingress bajo cf_tunnels.

Parámetro Descripción Valor por defecto
autoupdate_freq Frecuencia de actualización automática - ver documentación 24h
edge_ip_version Especifica la versión de dirección IP (IPv4 o IPv6) utilizada para establecer una conexión entre cloudflared y la red global de Cloudflare. Los valores disponibles son auto, 4, y 6 auto
edge_bind_address Especifica la dirección IP de salida utilizada para establecer una conexión entre cloudflared y la red global de Cloudflare -
grace_period Cuando cloudflared recibe SIGINT/SIGTERM dejará de aceptar nuevas solicitudes, esperará a que se terminen las solicitudes en curso y luego se apagará. Esperar las solicitudes en curso tendrá un tiempo de espera después de este período de gracia, o cuando se reciba una segunda señal SIGTERM/SIGINT 30s
metrics Dirección para consultar métricas de uso - ver documentación localhost:
metrics_update_freq Frecuencia para actualizar métricas del túnel - ver documentación 5s
no_autoupdate Deshabilitar la verificación periódica de actualizaciones, reiniciando el servidor con la nueva versión - ver documentación false
no_chunked_encoding Desactiva la codificación de transferencia fragmentada; útil si estás ejecutando un servidor WSGI - ver documentación false
no_tls_verify Desactiva la verificación TLS del certificado presentado por tu origen. Aceptará cualquier certificado del origen - ver documentación -
origin_server_name Nombre de host que cloudflared debería esperar de tu certificado de servidor de origen - ver documentación -
origin_ca_pool Ruta al CA para el certificado de tu origen. Esta opción debe usarse solo si tu certificado no está firmado por Cloudflare - ver documentación -
protocol Especifica el protocolo a utilizar para el túnel - ver documentación auto
logfile Habilita la escritura de un archivo de registro para cloudflared - aún registrará en el journal true
loglevel Especifica la verbosidad del registro. El valor predeterminado "info" no es ruidoso, pero puedes desear ejecutarlo con "warn" en producción - ver documentación info
region Te permite elegir las regiones a las que se establecen las conexiones. Omite o deja vacío para conectar a la región global. Configura --region=us para enrutear todas las conexiones a través de las regiones 1 y 2 de EE.UU. -
retries Número máximo de reintentos para errores de conexión/protocolo. Los reintentos usan retroceso exponencial (reintentando en 1, 2, 4, 8, 16 segundos por defecto), así que no se recomienda aumentar este valor significativamente - ver documentación 5
tag Etiquetas personalizadas utilizadas para identificar este túnel, en formato KEY=VALUE - ver documentación -
token Asocia la instancia de cloudflared con un túnel específico. El token del túnel se muestra en el panel cuando creas el túnel por primera vez. También puedes recuperar el token usando la API -
transport_loglevel Especifica la verbosidad de los registros para el transporte entre cloudflared y el borde de Cloudflare. Los niveles disponibles son: trace, debug, info, warn, error, fatal, panic. Cualquier valor por debajo de "warn" produce una salida sustancial y solo debe usarse para depurar problemas de rendimiento de bajo nivel y peculiaridades de protocolo - ver documentación info
warp_routing Permitir a los usuarios conectarse a servicios internos utilizando WARP, más detalles ver warp-routing false

Dependencias

ninguna

Ejemplos de Playbooks

El siguiente ejemplo instala un servicio único para un túnel ssh para cada servidor.

- hosts: servers
  vars:
    cf_systemd_user: root
    cf_systemd_group: root
    cf_cert_location: /home/papanito/cert.pem
    services:
      ssh:
        hostname: "{{ inventory_hostname }}.mycompany.com"
        url: ssh://localhost:22
  roles:
    - papanito.cloudflared

El siguiente ejemplo instala un [túnel nombrado] servidores con una entrada a {{ inventory_hostname }}.mycompany.com para ssh y un [hola mundo] si accedes a hello-{{ inventory_hostname }}.mycompany.com a través del navegador.

- hosts: servers
  remote_user: ansible
  become: true
  vars:
    cf_cert_location: /home/papanito/.cloudflared/cert.mycompany.com.pem
    cf_tunnels:
      test:
        account_tag: !vault...
        tunnel_secret: !vault...
        tunnel_id: !vault...
        routes:
          dns:
          - "{{ inventory_hostname }}"
          - "hello-{{ inventory_hostname }}"
        ingress:
        - hostname: "hello-{{ inventory_hostname }}.mycompany.com"
          service: hello_world
        - hostname: "{{ inventory_hostname }}.mycompany.com"
          service: ssh://localhost:22
        - service: http_status:404
  roles:
    - papanito.cloudflared

El siguiente ejemplo simplemente descarga cloudflared en tu máquina local y configura el archivo ssh-config:

- hosts: localhost
  remote_user: papanito # tu usuario local con permisos de administrador
  vars:
    cf_install_only: true
    cf_ssh_client_config: true
    cf_ssh_client_config_group: servers
  roles:
    - papanito.cloudflared

Prueba

ansible-playbook tests/test.yml -i tests/inventory

Información Adicional

Autenticación del daemon

Según authenticate-the-cloudflare-daemon, al autenticar el daemon, se abrirá una ventana del navegador o, si esto no es posible, se deberá colocar el enlace manualmente. Durante este tiempo el daemon espera. No pude idear una solución para automatizar este comportamiento, así que propuse la siguiente implementación.

  • Si no se especifica nada, entonces ansible llama a cloudflared login y continuará cuando la autenticación esté lista - esto tiene sentido si usas la rol para instalar el daemon localmente en tu máquina y donde tienes una ventana del navegador.

  • Si cf_cert_location, el certificado se copia de efectivamente desde cf_cert_location, o si cf_cert_content está definido, el certificado se crea directamente desde el valor almacenado en él. Así que podrías iniciar sesión una vez en cloudflare desde tu nodo maestro (donde ejecutas ansible) o desde una ubicación remota.

    Puedes cifrar el cert.pem con ansible vault y almacenarlo en un lugar seguro.

Referencias:

  • downloads - instrucciones de descarga de cloudflared
  • ssh-guide - conexiones ssh con cloudflared
  • cli-args - argumentos de línea de comandos
  • config - El formato del archivo de configuración usa sintaxis YAML

Licencia

Este es Software Libre, lanzado bajo los términos de la licencia Apache v2.

Información del Autor

Escrito por Papanito - Gitlab / Github

Acerca del proyecto

Ansible role do install and run cloudflare argo tunnel

Instalar
ansible-galaxy install papanito.cloudflared
Licencia
apache-2.0
Descargas
2.3k
Propietario
A passionate DevOps Engineer from Switzerland, father of five and husband of the most beautiful and most amazing woman in the world.