githubixx.ansible_role_wireguard
ansible-role-wireguard
Ce rôle Ansible est utilisé dans ma série de blogs Kubernetes the not so hard way with Ansible, mais peut bien sûr être utilisé de manière autonome. J'utilise WireGuard et ce rôle Ansible pour configurer un VPN entièrement maillé entre tous les nœuds de mon petit cluster Kubernetes.
En général, WireGuard est un tunnel réseau (VPN) pour IPv4 et IPv6 qui utilise UDP. Si vous avez besoin de plus d'informations sur WireGuard, vous pouvez trouver une bonne introduction ici : Installing WireGuard, the Modern VPN.
Linux
Ce rôle devrait fonctionner avec :
- 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
Meilleur effort
- AlmaLinux 8
- Rocky Linux 8
- elementary OS 6
- CentOS 7 (fin de vie depuis fin juin 2024)
Des tests avec Molecule sont disponibles (voir plus bas). Cela devrait également fonctionner avec Raspbian Buster
, mais pour celui-ci, il n'y a pas de test disponible. MacOS (voir ci-dessous) devrait également fonctionner partiellement, mais est uniquement un meilleur effort.
MacOS
Alors que ce playbook configure, active et démarre un service systemd
sur Linux de manière à ce qu'aucune action supplémentaire ne soit nécessaire, sur MacOS, il installe les paquets requis et génère simplement le bon fichier wg0.conf
, qui est ensuite placé dans le répertoire wireguard_remote_directory
spécifié (/opt/local/etc/wireguard
par défaut). Pour faire fonctionner le VPN, vous devez alors faire :
sudo wg-quick up wg0
et pour le désactiver :
sudo wg-quick down wg0
ou vous pouvez installer l'application officielle et importer le fichier wg0.conf
.
Versions
Je tague chaque version et j'essaie de rester avec semantic versioning. Si vous souhaitez utiliser le rôle, je recommande de vérifier le dernier tag. La branche master est essentiellement le développement tandis que les tags marquent des versions stables. Mais en général, j'essaie aussi de garder la branche master en bon état.
Exigences
Par défaut, le port 51820
(protocole UDP) doit être accessible de l'extérieur. Mais vous pouvez ajuster le port en changeant la variable wireguard_port
. De plus, le transfert de paquets doit être activé, par exemple via echo 1 > /proc/sys/net/ipv4/ip_forward
. J'ai décidé de ne pas implémenter cette tâche dans ce rôle Ansible. À mon avis, cela devrait être géré ailleurs. Vous pouvez utiliser mon ansible-role-harden-linux par exemple. En plus de modifier les entrées sysctl (qui nécessitent l'activation du transfert IP), il gère également les paramètres de pare-feu parmi d'autres choses. Néanmoins, les hooks PreUp
, PreDown
, PostUp
et PostDown
peuvent être un bon endroit pour effectuer certaines actions liées au réseau avant qu'une interface WireGuard ne soit activée ou désactivée.
Journal des modifications
Historique des modifications :
Voir l'HISTORIQUE COMPLET
Modifications récentes :
17.0.0
BREAKING
- suppression du support pour
openSUSE 15.4
(fin de vie)
- suppression du support pour
FEATURE
- ajout du support pour
Ubuntu 24.04
- ajout du support pour
openSUSE 15.6
- ajout du support pour
MOLECULE
- suppression du code
Proxmox
obsolète - remplacement de la boîte Vagrant
rockylinux/9
parbento/rockylinux-9
- utilisation de
ansible.builtin.package
pour AlmaLinux - suppression de
AlmaLinux 8
,Rocky Linux 8
etCentOS 7
(Python obsolète rend les tests difficiles avec Ansible)
- suppression du code
16.0.2
- AUTRE
- retour en arrière d'un changement dans
.github/workflows/release.yml
- retour en arrière d'un changement dans
16.0.1
- AUTRE
- mise à jour de
.github/workflows/release.yml
- mise à jour de
meta/main.yml
- mise à jour de
16.0.0
BREAKING
- suppression du support pour Fedora 37/38 (fin de vie)
FEATURE
- ajout du support pour Fedora 39
- introduction de la variable
wireguard_conf_backup
pour garder une trace des changements de configuration. Par défaut àfalse
. (contribution de @shk3bq4d) - introduction de
wireguard_install_kernel_module
. Permet de sauter le chargement du module noyauwireguard
. Par défaut àtrue
(comportement précédent). (contribution de @gregorydlogan)
Molecule
- utilisation d'adresses IP différentes
- utilisation de boîtes Vagrant génériques pour Rocky Linux
- utilisation de boîtes Vagrant
alvistack
pour Ubuntu - utilisation de la boîte Vagrant officielle Rocky Linux 9
- utilisation de boîtes Vagrant officielles AlmaLinux
- déplacement des paramètres
memory
etcpus
vers les boîtes Vagrant
Installation
Téléchargez directement depuis Github (changez dans le répertoire du rôle Ansible avant de cloner) :
git clone https://github.com/githubixx/ansible-role-wireguard.git githubixx.ansible_role_wireguard
Via la commande
ansible-galaxy
, et téléchargez directement depuis Ansible Galaxy :ansible-galaxy role install githubixx.ansible_role_wireguard
Créez un fichier
requirements.yml
avec le contenu suivant (cela téléchargera le rôle depuis Github) et installez avec :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 de rôle
Ces variables peuvent être modifiées dans group_vars/
par exemple :
# Répertoire pour stocker la configuration de WireGuard sur les hôtes distants
wireguard_remote_directory: "/etc/wireguard" # Sur Linux
# wireguard_remote_directory: "/opt/local/etc/wireguard" # Sur MacOS
# Le port par défaut sur lequel WireGuard écoutera s'il n'est pas précisé autrement.
wireguard_port: "51820"
# Le nom de l'interface par défaut que WireGuard doit utiliser s'il n'est pas précisé autrement.
wireguard_interface: "wg0"
# Le propriétaire par défaut du fichier wg.conf
wireguard_conf_owner: root
# Le groupe par défaut du fichier wg.conf
wireguard_conf_group: "{{ 'root' if not ansible_os_family == 'Darwin' else 'wheel' }}"
# Le mode par défaut du fichier wg.conf
wireguard_conf_mode: 0600
# Si un changement dans le fichier wg.conf doit être sauvegardé
wireguard_conf_backup: false
# L'état par défaut du service wireguard
wireguard_service_enabled: "yes"
wireguard_service_state: "started"
# Par défaut, "wg syncconf" est utilisé pour appliquer les paramètres de l'interface WireGuard s'ils ont changé. Les outils WireGuard plus anciens ne fournissent pas cette option. Dans ce cas, par mesure de secours, l'interface WireGuard sera redémarrée. Cela entraîne une courte interruption des connexions réseau.
#
# Donc, même si "false" est l'option par défaut, le rôle détermine si l'option "syncconf" de l'outil "wg" est disponible et, si ce n'est pas le cas, revient à "true" (ce qui signifie que l'interface sera redémarrée car c'est la seule option possible dans ce cas).
#
# Options possibles :
# - false (par défaut)
# - true
#
# Les deux options ont leurs avantages et inconvénients. L'option par défaut "false" (ne pas redémarrer l'interface)
# - ne nécessite pas de redémarrer l'interface WireGuard pour appliquer des modifications
# - ne cause pas une courte interruption de la connexion VPN lorsque des modifications sont apportées
# - peut entraîner un rechargement incorrect des routes réseau
#
# En définissant la valeur de l'option sur "true", cela
# - redémarre l'interface WireGuard comme son nom l'indique en cas de changements
# - entraîne une courte interruption de la connexion VPN lorsque des modifications sont apportées
# - garantit que les routes réseau sont correctement rechargées
#
# Ainsi, cela dépend un peu de votre configuration laquelle option fonctionne le mieux. Si vous
# n'avez pas une routage trop compliqué qui change très souvent ou pas du tout
# utiliser "false" ici est probablement suffisant pour vous. Par exemple, si vous voulez simplement
# connecter quelques serveurs via VPN et que cela reste normalement ainsi.
#
# Si vous avez une configuration de routage plus dynamique, alors définir cela sur "true" pourrait être
# le moyen le plus sûr. De plus, si vous voulez éviter la possibilité de créer certains
# effets secondaires difficiles à détecter, cette option doit être considérée.
wireguard_interface_restart: false
# Normalement, le rôle crée automatiquement une clé privée la toute première fois
# s'il n'y a pas déjà une configuration WireGuard. Mais cette option permet
# de fournir votre propre clé privée WireGuard si vraiment nécessaire. Comme cela est bien sûr
# une valeur très sensible, vous pourriez envisager un outil comme Ansible Vault
# pour la stocker de manière chiffrée.
# wireguard_private_key:
# Réglez sur "false" si le cache des paquets ne doit pas être mis à jour (uniquement pertinent si
# le gestionnaire de paquets en question prend en charge cette option)
wireguard_update_cache: "true"
# Normalement, le rôle installe et active le module noyau wireguard où
# approprié. Dans certains cas, nous pourrions ne pas être en mesure de charger des modules noyaux, comme
# les invités LXC non privilégiés. Si vous définissez ceci sur false, vous devez vous assurer
# que le module wireguard est disponible dans le noyau !
wireguard_install_kernel_module: true
Il existe également quelques paramètres spécifiques à la distribution Linux :
#######################################
# Paramètres uniquement pertinents pour :
# - Ubuntu
# - elementary OS
#######################################
# DÉPRÉCIÉ : Veuillez utiliser "wireguard_update_cache" à la place.
# Réglez sur "false" si le cache des paquets ne doit pas être mis à jour.
wireguard_ubuntu_update_cache: "{{ wireguard_update_cache }}"
# Définit le temps de validité du cache des paquets
wireguard_ubuntu_cache_valid_time: "3600"
#######################################
# Paramètres uniquement pertinents pour CentOS 7
#######################################
# Définir wireguard_centos7_installation_method sur "kernel-plus"
# pour utiliser le noyau kernel-plus, qui inclut un module WireGuard intégré
# et signé.
#
# Le paramètre par défaut de "standard" utilisera le noyau standard et
# le module ELRepo pour WireGuard.
wireguard_centos7_installation_method: "standard"
# Redémarrer l'hôte si nécessaire si le noyau "kernel-plus" est utilisé
wireguard_centos7_kernel_plus_reboot: true
# Les secondes par défaut à attendre pour que la machine redémarre et réponde
# si "kernel-plus" est utilisé. Ne concerne que si
# "wireguard_centos7_kernel_plus_reboot" est défini sur "true".
wireguard_centos7_kernel_plus_reboot_timeout: "600"
# Redémarrer l'hôte si nécessaire si le noyau standard est utilisé
wireguard_centos7_standard_reboot: true
# Les secondes par défaut à attendre pour que la machine redémarre et réponde
# si le noyau "standard" est utilisé. Ne concerne que si
# "wireguard_centos7_standard_reboot" est défini sur "true".
wireguard_centos7_standard_reboot_timeout: "600"
#########################################
# Paramètres uniquement pertinents pour RockyLinux 8
#########################################
# Définir wireguard_rockylinux8_installation_method sur "dkms"
# pour construire le module WireGuard à partir de la source, avec wireguard-dkms.
# Cela est requis si vous utilisez un noyau personnalisé et/ou votre architecture
# n'est pas x86_64.
#
# Le paramètre par défaut de "standard" installera le module noyau
# avec kmod-wireguard d'ELRepo.
wireguard_rockylinux8_installation_method: "standard"
Chaque hôte dans host_vars/
doit configurer au moins une adresse via wireguard_address
ou wireguard_addresses
. L'option wireguard_address
ne peut contenir qu'un seul IPv4, il est donc recommandé d'utiliser la variable wireguard_addresses
qui peut contenir un tableau d'adresses IPv4 et IPv6.
wireguard_addresses:
- "10.8.0.101/24"
Bien sûr, tous les IP doivent être dans le même sous-réseau comme /24
que nous voyons dans l'exemple ci-dessus. Si wireguard_allowed_ips
n'est pas défini, alors les valeurs par défaut sont les IPs définies dans wireguard_address
et wireguard_addresses
sans le CIDR mais au lieu avec /32
(IPv4) ou /128
(IPv6) qui est基本iquement une route d'hôte (regardez templates/wg.conf.j2
). Voyons cet exemple en supposant que vous ne définissez pas wireguard_allowed_ips
explicitement :
[Interface]
Address = 10.8.0.2/24
PrivateKey = ....
ListenPort = 51820
[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.101/32
Endpoint = controller01.p.domain.tld:51820
Ceci est une partie de la configuration de WireGuard de ma workstation. Il a l'IP VPN 10.8.0.2
et nous avons un sous-réseau /24
dans lequel se trouvent tous mes hôtes WireGuard. Vous pouvez également voir que nous avons un pair ici qui a l'endpoint controller01.p.domain.tld:51820
. Lorsque wireguard_allowed_ips
n'est pas défini explicitement, le modèle Ansible ajoutera une entrée AllowedIPs
avec l'IP de cet hôte plus /32
ou /128
. Dans WireGuard, cela spécifie essentiellement le routage. La configuration ci-dessus dit : Sur ma workstation avec l'IP 10.8.0.2
, je veux envoyer tout le trafic à 10.8.0.101/32
à l'endpoint controller01.p.domain.tld:51820
. Maintenant, supposons que nous définissons wireguard_allowed_ips: "0.0.0.0/0"
. Alors la configuration résultante ressemble à ceci.
[Interface]
Address = 10.8.0.2/24
PrivateKey = ....
ListenPort = 51820
[Peer]
PublicKey = ....
AllowedIPs = 0.0.0.0/0
Endpoint = controller01.p.domain.tld:51820
Maintenant, c'est essentiellement la même chose que ci-dessus MAIS maintenant la configuration dit : Je veux acheminer TOUS le trafic provenant de ma workstation vers l'endpoint controller01.p.domain.tld:51820
. Si cet endpoint peut gérer le trafic est bien sûr une autre question et c'est à vous de décider comment vous configurez le routage de l'endpoint ;-)
Vous pouvez spécifier d'autres réglages optionnels (ils n'ont pas de valeur par défaut et ne seront pas définis s'ils ne sont pas spécifiés en plus de wireguard_allowed_ips
comme déjà mentionné) également par hôte dans host_vars/
(ou dans votre fichier d'hôtes Ansible si vous le souhaitez). Les valeurs pour les variables suivantes sont juste des exemples et n'ont pas de valeurs par défaut (pour plus d'informations et d'exemples, voir 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)
sont spécifiés comme des listes. Voici deux exemples :
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
Les commandes sont exécutées dans l'ordre, comme décrit dans wg-quick.8.
En outre, vous pouvez ajouter des pairs "non gérés". Ces pairs ne sont pas gérés par Ansible et ne font pas partie du groupe d'hôtes vpn
, par exemple :
wireguard_unmanaged_peers:
client.example.com:
public_key: 5zsSBeZZ8P9pQaaJvY9RbELQulcwC5VBXaZ93egzOlI=
# clé_partagée: ... par exemple à partir d'ansible-vault ?
allowed_ips: 10.0.0.3/32
endpoint: client.example.com:51820
persistent_keepalive: 0
L'une de wireguard_address
(déprécié) ou wireguard_addresses
(recommandé) est requise comme déjà mentionné. Ce sont les IPs du nom d'interface défini avec la variable wireguard_interface
(wg0 par défaut). Chaque hôte a bien sûr besoin d'au moins une IP VPN unique. Si vous ne définissez pas wireguard_endpoint
, le playbook utilisera le nom d'hôte défini dans le groupe d'hôtes vpn
(le nom d'hôte d'inventaire Ansible). Si vous définissez wireguard_endpoint
sur ""
(chaîne vide), ce pair n'aura pas d'endpoint. Cela signifie que cet hôte ne peut accéder qu'aux hôtes qui ont un wireguard_endpoint
. C'est utile pour les clients qui n'exposent aucun service au VPN et qui veulent uniquement accéder à des services sur d'autres hôtes. Donc, si vous définissez uniquement un hôte avec wireguard_endpoint
défini et tous les autres hôtes ont wireguard_endpoint
défini sur ""
(chaîne vide), cela signifie en gros que vous avez uniquement des clients à part un qui, dans ce cas, est le serveur WireGuard. La troisième possibilité est de définir wireguard_endpoint
sur un nom d'hôte. Par exemple, si vous avez différents noms d'hôtes pour les DNS privés et publics de cet hôte et avez besoin de différentes entrées DNS pour cela, définir wireguard_endpoint
devient pratique. Prenons par exemple l'IP ci-dessus : wireguard_address: "10.8.0.101"
. C'est une IP privée et j'ai créé une entrée DNS pour cette IP privée comme host01.i.domain.tld
(i
pour interne dans ce cas). Pour l'IP publique, j'ai créé une entrée DNS comme host01.p.domain.tld
(p
pour public). Le wireguard_endpoint
doit être une interface à laquelle les autres membres du groupe vpn
peuvent se connecter. Donc, dans ce cas, je définirais wireguard_endpoint
sur host01.p.domain.tld
parce que WireGuard a normalement besoin de pouvoir se connecter à l'IP publique des autres hôtes.
Voici un petit exemple de ce pourquoi j'utilise le playbook : J'utilise WireGuard pour configurer un VPN entièrement maillé (chaque hôte peut se connecter directement à chaque autre hôte) et exécuter mon cluster Kubernetes (K8s) chez Hetzner Cloud (mais vous devriez pouvoir utiliser n'importe quel hébergeur que vous souhaitez). Donc, les composants importants comme le contrôleur K8s et les nœuds de travail (qui incluent les pods) ne communiquent que via un VPN WireGuard chiffré. De plus (comme déjà mentionné), j'ai deux clients. Les deux ont kubectl
installé et peuvent parler au serveur API Kubernetes interne en utilisant le VPN WireGuard. L'un des deux clients expose également un endpoint WireGuard parce que le serveur de messagerie Postfix dans le cloud et mon Postfix interne doivent pouvoir communiquer entre eux. Je suppose que c'est peut-être un cas d'utilisation peu courant pour WireGuard :D Mais cela montre ce qui est possible. Alors laissez-moi expliquer la configuration qui pourrait vous aider à utiliser ce rôle Ansible.
Tout d'abord, voici une partie de mon fichier d'hôtes 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
Comme vous pouvez le voir, j'ai trois groupes ici : vpn
(tous les hôtes sur lesquels WireGuard sera installé), k8s_controller
(les nœuds de contrôle Kubernetes) et k8s_worker
(les nœuds de travail Kubernetes). Le i
dans le nom de domaine est pour interne
. Tous les enregistrements DNS i.domain.tld
ont un enregistrement A
qui pointe vers l'IP WireGuard que nous définirons bientôt pour chaque hôte, par exemple : controller01.i.domain.tld. IN A 10.8.0.101
. La raison en est que tous les composants Kubernetes ne se lient et n'écoutent que sur l'interface WireGuard dans ma configuration. Et puisque j'ai besoin de ces IP internes pour tous mes composants Kubernetes, je spécifie les entrées DNS internes dans mon fichier d'hôtes Ansible. Cela me permet d'utiliser facilement les noms d'hôtes et les variables d'inventaire Ansible dans les playbooks et templates.
Pour les nœuds de contrôleur Kubernetes, j'ai défini les variables d'hôtes suivantes :
Fichier d'hôtes 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
Fichier d'hôtes 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
Fichier d'hôtes 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
J'ai spécifié ansible_python_interpreter
ici pour chaque nœud, car les nœuds de contrôleur utilisent Ubuntu 18.04 qui a Python 3 installé par défaut. ansible_host
est défini sur le DNS public de cet hôte. Ansible utilisera ce nom pour se connecter à l'hôte via SSH. J'utilise également la même valeur pour wireguard_endpoint
pour la même raison. Les pairs WireGuard doivent se connecter aux autres pairs via une IP publique (eh bien, en tout cas une IP à laquelle les hôtes WireGuard peuvent se connecter - cela pourrait également être une IP interne si cela fonctionne pour vous). Les IP spécifiées par wireguard_address
ou wireguard_addresses
doivent bien sûr être uniques pour chaque hôte.
Pour les nœuds de travail Kubernetes, j'ai défini les variables suivantes :
Fichier d'hôtes 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
Fichier d'hôtes 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
Comme vous pouvez le voir, les variables sont en gros les mêmes que celles des nœuds de contrôleur, à une exception près : wireguard_persistent_keepalive: "30"
. Mes nœuds de travail (chez Hetzner Cloud) et mon serveur interne (mon serveur à domicile) sont connectés car j'exécute Postfix sur mes nœuds cloud et le serveur Postfix externe transfère les e-mails reçus à mon serveur interne (et vice versa). J'avais besoin de ce paramètre de keepsalive parce que de temps en temps, les instances du cloud et le serveur interne perdaient la connexion et ce paramètre a résolu le problème. Cela est bien sûr dû au fait que mon serveur interne est derrière un NAT et le pare-feu / routeur doit garder la correspondance NAT / pare-feu valide (persistence NAT et traversée de pare-feu).
Pour mon serveur interne à la maison (connecté via un routeur DSL à Internet), nous avons cette configuration :
---
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
Par défaut, le démon SSH écoute sur un port différent de 22 sur tous mes nœuds publics, mais en interne j'utilise 22
, et c'est la raison pour laquelle je définis ansible_port: 22
ici. De plus, ansible_host
est bien sûr une IP interne pour cet hôte. La valeur de wireguard_endpoint
est une entrée DNS dynamique. Comme mon IP à la maison n'est pas statique, j'ai besoin d'exécuter un script chaque minute sur mon serveur à la maison qui vérifie si l'IP a changé et, si c'est le cas, ajuste mon enregistrement DNS. J'utilise la fonction DynHost d'OVH pour réaliser cela, mais vous pouvez utiliser un fournisseur DynDNS de votre choix bien sûr. De plus, je redirige le trafic entrant sur le port 51820/UDP
vers mon serveur interne pour permettre le trafic WireGuard entrant. Les IPs de wireguard_address
et wireguard_addresses
doivent bien sûr faire partie de notre sous-réseau WireGuard.
Et enfin, pour ma workstation (sur laquelle j'exécute toutes les commandes ansible-playbook
) :
wireguard_addresses:
- "10.8.0.2/24"
wireguard_endpoint: ""
ansible_connection: local
ansible_become: false
Comme vous pouvez le voir, wireguard_endpoint: ""
est une chaîne vide ici. Cela signifie que le rôle Ansible ne définira pas d'endpoint pour ma workstation. Comme il n'est pas nécessaire que les autres hôtes se connectent à ma workstation, il n'est pas logique d'avoir un endpoint défini. Ainsi, dans ce cas, je peux accéder à tous les hôtes définis dans le groupe Ansible vpn
depuis ma workstation, mais pas l'inverse. Donc, la configuration WireGuard résultante pour ma workstation ressemble à ceci :
[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
Les autres fichiers de configuration WireGuard (wg0.conf
par défaut) ressemblent à peu près au même modèle, mais bien sûr [Interface]
comprend la configuration de cet hôte spécifique et les entrées [Peer]
répertorient la configuration des autres hôtes.
Exemples de Playbooks
- hosts: vpn
roles:
- githubixx.ansible_role_wireguard
hosts: vpn
roles:
-
role: githubixx.ansible_role_wireguard
tags: role-wireguard
Exemple d'inventaire utilisant deux interfaces WireGuard différentes sur l'hôte "multi"
Ceci est un exemple complexe utilisant le format d'inventaire 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:
# Utiliser un nom différent, et définir ansible_host, pour éviter un mélange des vars sans
# devoir préfixer les vars avec le nom de l'interface.
multi-wg1:
ansible_host: multi
wireguard_interface: wg1
# lorsque vous utilisez plusieurs interfaces sur un hôte, nous devons utiliser des ports différents
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
Playbooks d'exemple pour l'exemple ci-dessus :
- hosts: vpn1
roles:
- githubixx.ansible_role_wireguard
- hosts: vpn2
roles:
- githubixx.ansible_role_wireguard
Tests
Ce rôle a un petit environnement de test qui est créé à l'aide de Molecule, libvirt (vagrant-libvirt) et QEMU/KVM. Veuillez consulter mon article de blog Testing Ansible roles with Molecule, libvirt (vagrant-libvirt) and QEMU/KVM pour savoir comment configurer. La configuration de test est ici.
Ensuite, on peut exécuter molecule :
molecule converge
Cela mettra en place plusieurs machines virtuelles (VM) avec différents systèmes d'exploitation Linux pris en charge. Pour exécuter quelques tests :
molecule verify
Pour nettoyer, exécutez
molecule destroy
Il existe également une petite configuration Molecule qui imite un serveur WireGuard central avec quelques clients :
molecule converge -s single-server
Licence
Licence publique générale GNU v3.0 ou ultérieure
Informations sur l'auteur
Installs Wireguard incl. systemd integration
ansible-galaxy install githubixx.ansible_role_wireguard