githubixx.ansible_role_wireguard

<!--
Copyright (C) 2018-2023 Robert Wimmer
Copyright (C) 2019 fbourqui
SPDX-License-Identifier: GPL-3.0-or-later
-->

# ansible-role-wireguard

Este rol de Ansible es utilizado en mi serie de blog [Kubernetes de la manera fácil con Ansible](https://www.tauceti.blog/post/kubernetes-the-not-so-hard-way-with-ansible-wireguard/), pero también se puede usar por separado. Yo uso WireGuard y este rol de Ansible para configurar una VPN totalmente en malla entre todos los nodos de mi pequeño clúster de Kubernetes.

En general, WireGuard es un túnel de red (VPN) para IPv4 e IPv6 que utiliza UDP. Si necesitas más información sobre [WireGuard](https://www.wireguard.io/), puedes encontrar una buena introducción aquí: [Instalando WireGuard, la VPN moderna](https://research.kudelskisecurity.com/2017/06/07/installing-wireguard-the-modern-vpn/).

## Linux

Este rol debería funcionar con:

- Ubuntu 20.04 (Focal Fossa)
- Ubuntu 22.04 (Jammy Jellyfish)
- Ubuntu 24.04 (Noble Numbat)
- Archlinux
- Debian 11 (Bullseye)
- Debian 12 (Bookworm)
- Fedora 39
- AlmaLinux 9
- Rocky Linux 9
- openSUSE Leap 15.5
- openSUSE Leap 15.6
- Oracle Linux 9

## Mejor esfuerzo

- AlmaLinux 8
- Rocky Linux 8
- elementary OS 6
- CentOS 7 (fin de vida desde finales de junio de 2024)

Las pruebas de Molecule están [disponibles](https://github.com/githubixx/ansible-role-wireguard#testing) (ver más abajo). También debería funcionar con `Raspbian Buster`, aunque no hay pruebas disponibles para este. MacOS (ver más abajo) también debería funcionar parcialmente, pero es solo un mejor esfuerzo.

## MacOS

Mientras este playbook configura, habilita e inicia un servicio `systemd` en Linux de tal manera que no se necesiten acciones adicionales, en MacOS instala los paquetes requeridos y genera el archivo correcto `wg0.conf`, que se coloca en el `wireguard_remote_directory` especificado (`/opt/local/etc/wireguard` por defecto). Para ejecutar la VPN, necesitas:

```bash
sudo wg-quick up wg0

y para desactivarla

sudo wg-quick down wg0

o puedes instalar la aplicación oficial e importar el archivo wg0.conf.

Versiones

Etiquete cada lanzamiento y trato de seguir el versionado semántico. Si deseas usar el rol, te recomiendo que revises la última etiqueta. La rama principal básicamente es desarrollo mientras que las etiquetas marcan lanzamientos estables. Sin embargo, en general, trato de mantener la rama principal en buena forma también.

Requisitos

Por defecto, el puerto 51820 (protocolo UDP) debe ser accesible desde el exterior. Pero puedes ajustar el puerto cambiando la variable wireguard_port. También es necesario habilitar el reenvío de IP, por ejemplo, mediante echo 1 > /proc/sys/net/ipv4/ip_forward. Decidí no implementar esta tarea en este rol de Ansible. A mi juicio, debería manejarse en otro lugar. Puedes usar mi ansible-role-harden-linux, por ejemplo. Además de cambiar las entradas de sysctl (que necesitas para habilitar el reenvío IP), también gestiona la configuración del firewall, entre otras cosas. Sin embargo, los ganchos PreUp, PreDown, PostUp y PostDown pueden ser un buen lugar para hacer cosas relacionadas con la red antes de que una interfaz de WireGuard se active o se desactive.

Changelog

Historial de cambios:

Ver el CHANGELOG.md

Cambios recientes:

17.0.0

  • ROMPEDOR

    • eliminación del soporte para openSUSE 15.4 (fin de vida)
  • CARACTERÍSTICA

    • agregar soporte para Ubuntu 24.04
    • agregar soporte para openSUSE 15.6
  • MOLECULA

    • eliminar código obsoleto de Proxmox
    • reemplazar la caja de Vagrant rockylinux/9 con bento/rockylinux-9
    • usar ansible.builtin.package para AlmaLinux
    • eliminar AlmaLinux 8, Rocky Linux 8 y CentOS 7 (Python obsoleto dificulta las pruebas con Ansible)

16.0.2

  • OTRO
    • revertir cambio en .github/workflows/release.yml

16.0.1

  • OTRO
    • actualizar .github/workflows/release.yml
    • actualizar meta/main.yml

16.0.0

  • ROMPEDOR

    • eliminación del soporte para Fedora 37/38 (fin de vida)
  • CARACTERÍSTICA

    • agregar soporte para Fedora 39
    • introducir la variable wireguard_conf_backup para hacer un seguimiento de los cambios de configuración. Por defecto es false. (contribución de @shk3bq4d)
    • introducir wireguard_install_kernel_module. Permite omitir la carga del módulo del núcleo wireguard. Por defecto es true (que era el comportamiento anterior). (contribución de @gregorydlogan)
  • Molecula

    • usar diferentes direcciones IP
    • usar cajas Vagrant genéricas para Rocky Linux
    • usar cajas de Vagrant de alvistack para Ubuntu
    • usar la caja oficial de Vagrant de Rocky Linux 9
    • usar cajas oficiales de AlmaLinux de Vagrant
    • mover los parámetros de memory y cpus a las cajas de Vagrant

Instalación

  • Descarga directamente desde Github (cámbiate al directorio del rol de Ansible antes de clonar): git clone https://github.com/githubixx/ansible-role-wireguard.git githubixx.ansible_role_wireguard

  • A través del comando ansible-galaxy y descarga directamente desde Ansible Galaxy: ansible-galaxy role install githubixx.ansible_role_wireguard

  • Crea un archivo requirements.yml con el siguiente contenido (esto descargará el rol desde Github) e instala con ansible-galaxy role install -r requirements.yml:

---
roles:
  - name: githubixx.ansible_role_wireguard
    src: https://github.com/githubixx/ansible-role-wireguard.git
    version: 17.0.0

Variables del rol

Estas variables se pueden cambiar en group_vars/, por ejemplo:

# Directorio para almacenar la configuración de WireGuard en los hosts remotos
wireguard_remote_directory: "/etc/wireguard"              # En Linux
# wireguard_remote_directory: "/opt/local/etc/wireguard"  # En MacOS

# El puerto predeterminado en el que WireGuard escuchará si no se especifica lo contrario.
wireguard_port: "51820"

# El nombre de la interfaz predeterminado que debería usar WireGuard si no se especifica lo contrario.
wireguard_interface: "wg0"

# El propietario predeterminado del archivo wg.conf
wireguard_conf_owner: root

# El grupo predeterminado del archivo wg.conf
wireguard_conf_group: "{{ 'root' if not ansible_os_family == 'Darwin' else 'wheel' }}"

# El modo predeterminado del archivo wg.conf
wireguard_conf_mode: 0600

# Si cualquier cambio en el archivo wg.conf debe ser respaldado
wireguard_conf_backup: false

# El estado predeterminado del servicio de wireguard
wireguard_service_enabled: "yes"
wireguard_service_state: "started"

# Por defecto se usa "wg syncconf" para aplicar configuraciones de la interfaz de WireGuard si
# han cambiado. Herramientas más antiguas de WireGuard no proporcionan esta opción. En ese
# caso, como alternativa, se reiniciará la interfaz de WireGuard. Esto causa una
# breve interrupción de las conexiones de red.
#
# Entonces, incluso si "false" es el predeterminado, el rol descubre si la opción "syncconf"
# de la utilidad "wg" está disponible y si no, retorna a "true"
# (lo que significa que la interfaz se reiniciará ya que esta es la única opción posible
# en este caso).
#
# Opciones posibles:
# - false (predeterminado)
# - true
#
# Ambas opciones tienen sus pros y contras. La opción predeterminada "false" (no
# reiniciar interfaz)
# - no necesita reiniciar la interfaz de WireGuard para aplicar cambios
# - no causa una breve interrupción de la conexión VPN cuando se aplican cambios
# - podría causar que las rutas de red no se recarguen correctamente
#
# Establecer el valor de la opción a "true" hará
# - reiniciar la interfaz de WireGuard como su nombre sugiere en caso de cambios
# - causará una breve interrupción de la conexión VPN cuando se apliquen cambios
# - asegurará que las rutas de red se recarguen correctamente
#
# Así que depende un poco de tu configuración qué opción funciona mejor. Si no
# tienes un enrutamiento excesivamente complicado que cambia muy a menudo o en todo
# caso usando "false" aquí es lo suficientemente bueno para ti. Por ejemplo, si solo
# deseas conectar unos pocos servidores a través de VPN y normalmente permanece así.
#
# Si tienes una configuración de enrutamiento más dinámica, entonces establecer esto a "true" podría ser
# la forma más segura de proceder. También si deseas evitar la posibilidad de crear algunos
# efectos secundarios difíciles de detectar, esta opción debería ser considerada.
wireguard_interface_restart: false

# Normalmente el rol crea automáticamente una clave privada la primera vez
# si no hay ya una configuración de WireGuard. Pero esta opción permite
# proporcionar tu propia clave privada de WireGuard si realmente es necesario. Como esta es un
# valor muy sensible, podrías considerar usar una herramienta como Ansible Vault
# para almacenarla encriptada.
# wireguard_private_key:

# Establecer en "false" si el caché de paquetes no debe ser actualizado (solo relevante si
# la gestión de paquetes en cuestión admite esta opción)
wireguard_update_cache: "true"

# Normalmente, el rol instala y activa el módulo del núcleo wireguard donde
# sea apropiado. En algunos casos, puede que no podamos cargar módulos del núcleo, como
# en huéspedes LXC no privilegiados. Si estableces esto en falso, debes asegurarte de que
# ¡el módulo wireguard esté disponible en el núcleo!
wireguard_install_kernel_module: true

También hay algunas configuraciones específicas de distribución de Linux:

#######################################
# Configuraciones relevantes solo para:
# - Ubuntu
# - elementary OS
#######################################

# DEPRECATED: Por favor use "wireguard_update_cache" en su lugar.
# Establecer en "false" si el caché de paquetes no debe ser actualizado.
wireguard_ubuntu_update_cache: "{{ wireguard_update_cache }}"

# Establecer tiempo válido de caché de paquetes
wireguard_ubuntu_cache_valid_time: "3600"

#######################################
# Configuraciones relevantes solo para CentOS 7
#######################################

# Establecer wireguard_centos7_installation_method en "kernel-plus"
# para usar el núcleo kernel-plus, que incluye un módulo WireGuard
# incorporado y firmado.
#
# El valor predeterminado de "standard" usará el núcleo estándar y
# el módulo ELRepo para WireGuard.
wireguard_centos7_installation_method: "standard"

# Reiniciar el host si es necesario si se usa el núcleo "kernel-plus".
wireguard_centos7_kernel_plus_reboot: true

# El número de segundos predeterminado para esperar a que la máquina reinicie y responda
# si se está utilizando "kernel-plus". Solo es relevante si
# "wireguard_centos7_kernel_plus_reboot" se establece en "true".
wireguard_centos7_kernel_plus_reboot_timeout: "600"

# Reiniciar el host si es necesario si se está utilizando el núcleo estándar.
wireguard_centos7_standard_reboot: true

# El número de segundos predeterminado para esperar a que la máquina reinicie y responda
# si se está utilizando el núcleo "estándar". Solo es relevante si
# "wireguard_centos7_standard_reboot" se establece en "true".
wireguard_centos7_standard_reboot_timeout: "600"

#########################################
# Configuraciones relevantes solo para RockyLinux 8
#########################################

# Establecer wireguard_rockylinux8_installation_method en "dkms"
# para construir el módulo de WireGuard desde el origen, usando wireguard-dkms.
# Esto es necesario si usas un núcleo personalizado y/o tu arquitectura
# no es x86_64.
#
# El valor predeterminado de "standard" instalará el módulo del núcleo
# con kmod-wireguard de ELRepo.
wireguard_rockylinux8_installation_method: "standard"

Cada host en host_vars/ debe configurar al menos una dirección a través de wireguard_address o wireguard_addresses. La wireguard_address solo puede contener una IPv4, por lo que se recomienda usar la variable wireguard_addresses, que puede contener un array de direcciones IPv4 e IPv6.

wireguard_addresses:
  - "10.8.0.101/24"

Por supuesto, todas las IP deben estar en la misma subred como /24, que es lo que vemos en el ejemplo anterior. Si wireguard_allowed_ips no se establece, entonces los valores predeterminados son IPs definidas en wireguard_address y wireguard_addresses sin el CIDR, sino con /32 (IPv4) o /128 (IPv6), que es básicamente una ruta de host (echa un vistazo a templates/wg.conf.j2). Veamos este ejemplo y asumamos que no configuras wireguard_allowed_ips explícitamente:

[Interface]
Address = 10.8.0.2/24
PrivateKey = ....
ListenPort = 51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.101/32
Endpoint = controller01.p.domain.tld:51820

Esta es parte de la configuración de WireGuard desde mi estación de trabajo. Tiene la IP VPN 10.8.0.2 y tenemos una subred /24 en la que están todos mis hosts de WireGuard. También puedes ver que tenemos un peer aquí que tiene el endpoint controller01.p.domain.tld:51820. Cuando wireguard_allowed_ips no se establece explícitamente, la plantilla de Ansible añadirá una entrada AllowedIPs con la IP de ese host más /32 o /128. En WireGuard esto básicamente especifica la ruta. La configuración anterior dice: En mi estación de trabajo con la IP 10.8.0.2 quiero enviar todo el tráfico a 10.8.0.101/32 al endpoint controller01.p.domain.tld:51820. Ahora asumamos que establecemos wireguard_allowed_ips: "0.0.0.0/0". Entonces la configuración resultante se verá así.

[Interface]
Address = 10.8.0.2/24
PrivateKey = ....
ListenPort = 51820

[Peer]
PublicKey = ....
AllowedIPs = 0.0.0.0/0
Endpoint = controller01.p.domain.tld:51820

Ahora esto es básicamente lo mismo que lo anterior, PERO ahora la configuración dice: quiero enrutar TODO el tráfico que origina desde mi estación de trabajo al endpoint controller01.p.domain.tld:51820. Si ese endpoint puede manejar el tráfico es, por supuesto, otro tema y depende de cómo configures el enrutamiento del endpoint ;-)

Puedes especificar más configuraciones opcionales (no tienen un valor por defecto y no se establecerán si no se especifican, excepto wireguard_allowed_ips como ya se mencionó) también por host en host_vars/ (o en tu archivo de hosts de Ansible si lo deseas). Los valores para las siguientes variables son solo ejemplos y no tienen valores por defecto (para obtener más información y ejemplos, consulta wg-quick.8):

wireguard_allowed_ips: ""
wireguard_endpoint: "host1.domain.tld"
wireguard_persistent_keepalive: "30"
wireguard_dns: "1.1.1.1"
wireguard_fwmark: "1234"
wireguard_mtu: "1492"
wireguard_table: "5000"
wireguard_preup:
  - ...
wireguard_predown:
  - ...
wireguard_postup:
  - ...
wireguard_postdown:
  - ...
wireguard_save_config: "true"

wireguard_(preup|predown|postup|postdown) se especifican como listas. Aquí hay dos ejemplos:

wireguard_postup:
  - iptables -t nat -A POSTROUTING -o ens12 -j MASQUERADE
  - iptables -A FORWARD -i %i -j ACCEPT
  - iptables -A FORWARD -o %i -j ACCEPT
wireguard_preup:
  - echo 1 > /proc/sys/net/ipv4/ip_forward
  - ufw allow 51820/udp

Los comandos se ejecutan en el orden como se describe en wg-quick.8.

Además, puedes agregar peers "no gestionados". Esos peers no son manejados por Ansible y no son parte del grupo de hosts de Ansible vpn, por ejemplo:

wireguard_unmanaged_peers:
  client.example.com:
    public_key: 5zsSBeZZ8P9pQaaJvY9RbELQulcwC5VBXaZ93egzOlI=
    # preshared_key: ... por ejemplo, ¿de ansible-vault?
    allowed_ips: 10.0.0.3/32
    endpoint: client.example.com:51820
    persistent_keepalive: 0

Se requiere uno de wireguard_address (obsoleto) o wireguard_addresses (recomendado) como ya se mencionó. Es la dirección IP del nombre de la interfaz definida con la variable wireguard_interface (wg0 por defecto). Cada host necesita al menos una IP VPN única, por supuesto. Si no configuras wireguard_endpoint, el playbook utilizará el nombre de host definido en el grupo de hosts vpn (el nombre de host de inventario de Ansible). Si estableces wireguard_endpoint en "" (cadena vacía), ese peer no tendrá un endpoint. Eso significa que este host solo podrá acceder a los hosts que tengan un wireguard_endpoint. Esto es útil para clientes que no exponen ningún servicio a la VPN y solo desean acceder a servicios en otros hosts. Así que si solo defines un host con wireguard_endpoint establecido y todos los demás hosts tienen wireguard_endpoint configurado como "" (cadena vacía), eso significa que solo tienes clientes, aparte de uno, que en ese caso es el servidor de WireGuard. La tercera posibilidad es establecer wireguard_endpoint en algún nombre de host. Por ejemplo, si tienes diferentes nombres de host para el DNS privado y público de ese host y necesitas diferentes entradas de DNS para ese caso, establecer wireguard_endpoint resulta útil. Tomemos como ejemplo la IP anterior: wireguard_address: "10.8.0.101". Esa es una IP privada y he creado una entrada DNS para esa IP privada como host01.i.domain.tld (i para interno en este caso). Para la IP pública, he creado una entrada DNS como host01.p.domain.tld (p por público). El wireguard_endpoint debe ser una interfaz a la que los otros miembros del grupo vpn pueden conectarse. Así que en ese caso, establecería wireguard_endpoint a host01.p.domain.tld porque WireGuard normalmente necesita poder conectarse a la IP pública de los otros hosts.

Aquí hay un pequeño ejemplo de lo que uso el playbook: uso WireGuard para configurar una VPN totalmente en malla (cada host puede conectarse directamente a cada otro host) y ejecuto mi clúster de Kubernetes (K8s) en Hetzner Cloud (pero deberías poder usar cualquier proveedor que desees). Así que los componentes importantes como los nodos controladores de K8s y los nodos de trabajo (que incluyen los pods) solo se comunican a través de una VPN encriptada de WireGuard. También (como se mencionó anteriormente) tengo dos clientes. Ambos tienen kubectl instalado y pueden comunicarse con el servidor API de Kubernetes interno usando la VPN de WireGuard. Uno de los dos clientes también expone un endpoint de WireGuard porque el servidor de correo Postfix en la nube y mi Postfix interno necesitan poder comunicarse entre sí. Supongo que ese es quizás un caso de uso no tan común para WireGuard :D Pero muestra lo que es posible. Así que déjame explicarte la configuración que podría ayudarte a usar este rol de Ansible.

Primero, aquí hay una parte de mi archivo de hosts de Ansible:

[vpn]
controller0[1:3].i.domain.tld
worker0[1:2].i.domain.tld
server.at.home.i.domain.tld
workstation.i.domain.tld

[k8s_controller]
controller0[1:3].i.domain.tld

[k8s_worker]
worker0[1:2].i.domain.tld

Como puedes ver, tengo tres grupos aquí: vpn (todos los hosts a los que se les instalará WireGuard), k8s_controller (los nodos controladores de Kubernetes) y k8s_worker (los nodos de trabajo de Kubernetes). La i en el nombre de dominio es para interno. Todas las entradas DNS de i.domain.tld tienen un registro A que apunta a la IP de WireGuard que definimos en breve para cada host, por ejemplo: controller01.i.domain.tld. IN A 10.8.0.101. La razón de esto es que todos los componentes de Kubernetes solo se unen y escuchan en la interfaz de WireGuard en mi configuración. Y dado que necesito estas IPs internas para todos mis componentes de Kubernetes, especifico las entradas DNS internas en mi archivo de hosts de Ansible. De esa manera, puedo usar los nombres de host e variables de inventario de Ansible de manera muy sencilla en los playbooks y plantillas.

Para los nodos controladores de Kubernetes, he definido las siguientes variables de host:

Archivo de hosts de Ansible: host_vars/controller01.i.domain.tld

---
wireguard_addresses:
  - "10.8.0.101/24"
wireguard_endpoint: "controller01.p.domain.tld"
ansible_host: "controller01.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

Archivo de hosts de Ansible: host_vars/controller02.i.domain.tld:

---
wireguard_addresses:
  - "10.8.0.102/24"
wireguard_endpoint: "controller02.p.domain.tld"
ansible_host: "controller02.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

Archivo de hosts de Ansible: host_vars/controller03.i.domain.tld:

---
wireguard_addresses:
  - "10.8.0.103/24"
wireguard_endpoint: "controller03.p.domain.tld"
ansible_host: "controller03.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

He especificado ansible_python_interpreter aquí para cada nodo ya que los nodos controladores usan Ubuntu 18.04, que tiene Python 3 instalado por defecto. ansible_host se establece en el DNS público de ese host. Ansible usará este nombre de host para conectarse al host a través de SSH. También utilizo el mismo valor para wireguard_endpoint por la misma razón. Los peers de WireGuard necesitan conectarse a los otros peers a través de una IP pública (bueno, al menos a una IP a la que los hosts de WireGuard puedan conectarse; eso podría ser, por supuesto, también una IP interna si funciona para ti). Las IPs especificadas por wireguard_address o wireguard_addresses necesitan ser únicas, por supuesto, para cada host.

Para los trabajadores de Kubernetes, he definido las siguientes variables:

Archivo de hosts de Ansible: host_vars/worker01.i.domain.tld

---
wireguard_addresses:
  - "10.8.0.111/24"
wireguard_endpoint: "worker01.p.domain.tld"
wireguard_persistent_keepalive: "30"
ansible_host: "worker01.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

Archivo de hosts de Ansible: host_vars/worker02.i.domain.tld:

---
wireguard_addresses:
  - "10.8.0.112/24"
wireguard_endpoint: "worker02.p.domain.tld"
wireguard_persistent_keepalive: "30"
ansible_host: "worker02.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

Como puedes ver, las variables son básicamente las mismas que las de los nodos controladores, con una excepción: wireguard_persistent_keepalive: "30". Mis nodos de trabajo (en Hetzner Cloud) y mi servidor interno (mi servidor en casa) están conectados porque estoy ejecutando Postfix en mis nodos de la nube y el servidor externo de Postfix reenvía los correos recibidos a mi servidor interno (y viceversa). Necesitaba la configuración de keepalive porque de vez en cuando las instancias de la nube y el servidor interno perdían la conexión, y esta configuración solucionó el problema. La razón de esto es, por supuesto, que mi servidor interno está detrás de NAT y el cortafuegos/router debe mantener el mapeo NAT/cortafuegos válido (persistencia de NAT y de traspaso de Cortafuegos).

Para mi servidor interno en casa (conectado a Internet a través del router DSL) tenemos esta configuración:

---
wireguard_addresses:
  - "10.8.0.1/24"
wireguard_endpoint: "server.at.home.p.domain.tld"
wireguard_persistent_keepalive: "30"
ansible_host: 192.168.2.254
ansible_port: 22

Por defecto, el demonio SSH escucha en un puerto diferente a 22 en todos mis nodos públicos, pero internamente yo uso 22, y esa es la razón para establecer ansible_port: 22 aquí. También ansible_host es por supuesto una IP interna para ese host. El valor de wireguard_endpoint es una entrada dinámica de DNS. Dado que mi IP en casa no es estática, necesito ejecutar un script cada minuto en mi servidor doméstico que verifica si la IP ha cambiado y, si es así, ajuste mi registro DNS. Utilizo la función DynHost de OVH para lograr esto, pero por supuesto puedes usar cualquier proveedor de DynDNS que desees. Además, reenvío el tráfico entrante en el puerto 51820/UDP a mi servidor interno para permitir el tráfico de WireGuard entrante. Las IPs de wireguard_address y wireguard_addresses, por supuesto, deben ser parte de nuestra subred de WireGuard.

Y por último, para mi estación de trabajo (en la que ejecuto todos los comandos de ansible-playbook):

wireguard_addresses:
  - "10.8.0.2/24"
wireguard_endpoint: ""
ansible_connection: local
ansible_become: false

Como puedes ver, wireguard_endpoint: "" es una cadena vacía aquí. Eso significa que el rol de Ansible no establecerá un endpoint para mi estación de trabajo. Dado que no hay necesidad de que los otros hosts se conecten a mi estación de trabajo, no tiene sentido tener un endpoint definido. Así que en este caso puedo acceder a todos los hosts definidos en el grupo de Ansible vpn desde mi estación de trabajo, pero no al revés. Así que la configuración resultante de WireGuard para mi estación de trabajo se ve así:

[Interface]
Address = 10.8.0.2/24
PrivateKey = ....
ListenPort = 51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.101/32
Endpoint = controller01.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.102/32
Endpoint = controller02.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.103/32
Endpoint = controller03.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.111/32
PersistentKeepalive = 30
Endpoint = worker01.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.112/32
PersistentKeepalive = 30
Endpoint = worker02.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.1/32
PersistentKeepalive = 30
Endpoint = server.at.home.p.domain.tld:51820

Los otros archivos de configuración de WireGuard (wg0.conf por defecto) son similares, pero por supuesto el [Interface] incluye la configuración de ese host específico y las entradas [Peer] listan la configuración de los otros hosts.

Playbooks de ejemplo

- hosts: vpn
  roles:
    - githubixx.ansible_role_wireguard
  hosts: vpn
  roles:
    -
      role: githubixx.ansible_role_wireguard
      tags: role-wireguard

Inventario de ejemplo usando dos interfaces diferentes de WireGuard en el host "multi"

Este es un ejemplo complejo usando formato de inventario yaml:

vpn1:
  hosts:
    multi:
      wireguard_addresses:
        - "10.9.0.1/32"
      wireguard_allowed_ips: "10.9.0.1/32, 192.168.2.0/24"
      wireguard_endpoint: multi.example.com
    nated:
      wireguard_addresses:
        - "10.9.0.2/32"
      wireguard_allowed_ips: "10.9.0.2/32, 192.168.3.0/24"
      wireguard_persistent_keepalive: 15
      wireguard_endpoint: nated.example.com
      wireguard_postup:
        - iptables -t nat -A POSTROUTING -o ens12 -j MASQUERADE
        - iptables -A FORWARD -i %i -j ACCEPT
        - iptables -A FORWARD -o %i -j ACCEPT
      wireguard_postdown:
        - iptables -t nat -D POSTROUTING -o ens12 -j MASQUERADE
        - iptables -D FORWARD -i %i -j ACCEPT
        - iptables -D FORWARD -o %i -j ACCEPT

vpn2:
  hosts:
    # Usar un nombre diferente, y definir ansible_host, para evitar la mezcla de vars sin
    # necesidad de prefijar las vars con el nombre de la interfaz.
    multi-wg1:
      ansible_host: multi
      wireguard_interface: wg1
      # cuando se utilizan varias interfaces en un host, debemos usar diferentes puertos
      wireguard_port: 51821
      wireguard_addresses:
        - "10.9.1.1/32"
      wireguard_endpoint: multi.example.com
    another:
      wireguard_address:
        - "10.9.1.2/32"
      wireguard_endpoint: another.example.com

Ejemplos de playbooks para el ejemplo anterior:

- hosts: vpn1
  roles:
    - githubixx.ansible_role_wireguard
- hosts: vpn2
  roles:
    - githubixx.ansible_role_wireguard

Pruebas

Este rol tiene una pequeña configuración de prueba que se crea utilizando Molecule, libvirt (vagrant-libvirt) y QEMU/KVM. Por favor consulta mi publicación en el blog Probando roles de Ansible con Molecule, libvirt (vagrant-libvirt) y QEMU/KVM sobre cómo configurarlo. La configuración de prueba está aquí.

Después, se puede ejecutar molecule:

molecule converge

Esto configurará varias máquinas virtuales (VM) con diferentes sistemas operativos Linux soportados. Para ejecutar algunas pruebas:

molecule verify

Para limpiar, ejecuta

molecule destroy

También hay una pequeña configuración de Molecule que imita un servidor central de WireGuard con algunos clientes:

molecule converge -s single-server

Licencia

Licencia Pública General GNU v3.0 o posterior

Información del autor

http://www.tauceti.blog ```

Acerca del proyecto

Installs Wireguard incl. systemd integration

Instalar
ansible-galaxy install githubixx.ansible_role_wireguard
Licencia
Unknown
Descargas
239.1k
Propietario
Senior System Engineer - Python, Go, Cloud, Kubernetes, Commodore, Retro, 80's ;-)