WireGuard s’est imposé en quelques années comme l’un des protocoles VPN les plus modernes et les plus performants disponibles sur Linux. Intégré directement dans le noyau Linux depuis la version 5.6, il repose sur une cryptographie d’état de l’art (Curve25519, ChaCha20, Poly1305) et une surface d’attaque volontairement réduite. Là où OpenVPN ou IPsec nécessitent des dizaines de milliers de lignes de code, WireGuard en compte moins de 4 000, ce qui facilite considérablement son audit et sa maintenance.
Si la configuration d’un serveur WireGuard classique en mode hub-and-spoke est bien documentée, la topologie mesh (ou maillée) est souvent moins abordée. Dans une architecture mesh, chaque serveur communique directement avec tous les autres sans passer par un nœud central. Cette approche élimine le point de défaillance unique, réduit la latence entre pairs et s’adapte idéalement aux infrastructures multi-datacenter, aux clusters Kubernetes, ou à tout environnement où plusieurs serveurs doivent dialoguer de manière sécurisée et redondante.
Dans ce guide, nous allons monter un VPN mesh WireGuard entre trois serveurs Linux (Debian 12 / Ubuntu 22.04+), en configurant chaque nœud pour qu’il communique directement avec les deux autres via un réseau privé chiffré de bout en bout. Toutes les opérations sont réalisables sur n’importe quelle distribution disposant de WireGuard dans ses dépôts.
Prérequis et topologie réseau
Pour ce tutoriel, nous utilisons trois serveurs disposant chacun d’une adresse IP publique (ou accessible entre eux sur le port UDP 51820). Voici la topologie retenue :
| Nœud | Hostname | IP publique | IP VPN (wg0) |
|---|---|---|---|
| Serveur 1 | srv1 | 203.0.113.1 | 10.10.0.1/24 |
| Serveur 2 | srv2 | 203.0.113.2 | 10.10.0.2/24 |
| Serveur 3 | srv3 | 203.0.113.3 | 10.10.0.3/24 |
Chaque serveur sera à la fois client et serveur WireGuard. L’ensemble des nœuds partage le sous-réseau privé 10.10.0.0/24. Le port UDP 51820 doit être ouvert en entrée sur chaque machine.
Installation de WireGuard
Sur Debian 12 et Ubuntu 22.04+, WireGuard est disponible dans les dépôts officiels :
sudo apt update && sudo apt install -y wireguard wireguard-tools
Sur CentOS/Rocky Linux 8+ :
sudo dnf install -y epel-release
sudo dnf install -y wireguard-tools
Vérifiez que le module kernel est disponible :
modinfo wireguard
Génération des paires de clés
Chaque nœud doit disposer de sa propre paire de clés cryptographiques. WireGuard utilise des clés Curve25519 encodées en base64. Sur chacun des trois serveurs, exécutez :
# Générer clé privée et dériver la clé publique
wg genkey | sudo tee /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
# Sécuriser la clé privée
sudo chmod 600 /etc/wireguard/private.key
# Afficher les clés (à noter précieusement)
echo "Clé privée : $(sudo cat /etc/wireguard/private.key)"
echo "Clé publique : $(sudo cat /etc/wireguard/public.key)"
Notez les clés publiques de chaque nœud — elles seront échangées entre les pairs. La clé privée ne quitte jamais le serveur qui l’a générée.
Activation du routage IP
Pour que les paquets soient bien transmis entre interfaces réseau, le forwarding IPv4 doit être activé sur chaque nœud :
# Activer immédiatement
sudo sysctl -w net.ipv4.ip_forward=1
# Rendre permanent
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf
Configuration des fichiers wg0.conf
Chaque serveur dispose d’un fichier /etc/wireguard/wg0.conf. La section [Interface] décrit le nœud local, et chaque section [Peer] décrit un pair distant. Notez que dans un mesh, chaque nœud liste tous les autres comme pairs.
Configuration de srv1 (10.10.0.1)
sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <CLÉ_PRIVÉE_SRV1>
# Règles de pare-feu (optionnel mais recommandé)
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# srv2
PublicKey = <CLÉ_PUBLIQUE_SRV2>
Endpoint = 203.0.113.2:51820
AllowedIPs = 10.10.0.2/32
PersistentKeepalive = 25
[Peer]
# srv3
PublicKey = <CLÉ_PUBLIQUE_SRV3>
Endpoint = 203.0.113.3:51820
AllowedIPs = 10.10.0.3/32
PersistentKeepalive = 25
Configuration de srv2 (10.10.0.2)
[Interface]
Address = 10.10.0.2/24
ListenPort = 51820
PrivateKey = <CLÉ_PRIVÉE_SRV2>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# srv1
PublicKey = <CLÉ_PUBLIQUE_SRV1>
Endpoint = 203.0.113.1:51820
AllowedIPs = 10.10.0.1/32
PersistentKeepalive = 25
[Peer]
# srv3
PublicKey = <CLÉ_PUBLIQUE_SRV3>
Endpoint = 203.0.113.3:51820
AllowedIPs = 10.10.0.3/32
PersistentKeepalive = 25
Configuration de srv3 (10.10.0.3)
[Interface]
Address = 10.10.0.3/24
ListenPort = 51820
PrivateKey = <CLÉ_PRIVÉE_SRV3>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# srv1
PublicKey = <CLÉ_PUBLIQUE_SRV1>
Endpoint = 203.0.113.1:51820
AllowedIPs = 10.10.0.1/32
PersistentKeepalive = 25
[Peer]
# srv2
PublicKey = <CLÉ_PUBLIQUE_SRV2>
Endpoint = 203.0.113.2:51820
AllowedIPs = 10.10.0.2/32
PersistentKeepalive = 25
Point important sur AllowedIPs : dans un mesh strict, on utilise /32 pour chaque pair afin que le trafic entre pairs ne transite pas par un nœud intermédiaire. Si vous souhaitez que srv1 serve de passerelle pour un sous-réseau derrière srv2 (par exemple 192.168.10.0/24), ajoutez ce CIDR dans l’AllowedIPs du pair correspondant.
Démarrage et activation du service
Sur chaque nœud, démarrez l’interface WireGuard et activez-la au démarrage du système :
# Démarrer l'interface
sudo wg-quick up wg0
# Activer le démarrage automatique
sudo systemctl enable wg-quick@wg0
# Vérifier le statut
sudo systemctl status wg-quick@wg0
Pour appliquer une modification de configuration sans interrompre le service :
sudo wg syncconf wg0 <(sudo wg-quick strip wg0)
Vérification de la connectivité mesh
Après le démarrage sur les trois nœuds, vérifiez l’état du tunnel avec wg show :
sudo wg show wg0
La sortie doit afficher chaque pair avec sa dernière poignée de main (latest handshake) et le volume de données échangées :
interface: wg0
public key: <CLÉ_PUBLIQUE_SRV1>
private key: (hidden)
listening port: 51820
peer: <CLÉ_PUBLIQUE_SRV2>
endpoint: 203.0.113.2:51820
allowed ips: 10.10.0.2/32
latest handshake: 3 seconds ago
transfer: 1.23 KiB received, 856 B sent
peer: <CLÉ_PUBLIQUE_SRV3>
endpoint: 203.0.113.3:51820
allowed ips: 10.10.0.3/32
latest handshake: 5 seconds ago
transfer: 980 B received, 744 B sent
Testez ensuite la connectivité directe entre tous les nœuds :
# Depuis srv1
ping -c 3 10.10.0.2 # vers srv2
ping -c 3 10.10.0.3 # vers srv3
# Mesurer la latence chiffrée
ping -c 10 10.10.0.2
Automatisation avec wg-meshconf
Pour des topologies comportant de nombreux nœuds (5, 10 ou plus), la configuration manuelle devient fastidieuse et source d’erreurs. L’outil wg-meshconf génère automatiquement tous les fichiers de configuration :
# Installation via pip
pip3 install wg-meshconf
# Créer la base de données de nœuds
wg-meshconf addpeer srv1 --address 10.10.0.1/24 --endpoint 203.0.113.1 --listenport 51820
wg-meshconf addpeer srv2 --address 10.10.0.2/24 --endpoint 203.0.113.2 --listenport 51820
wg-meshconf addpeer srv3 --address 10.10.0.3/24 --endpoint 203.0.113.3 --listenport 51820
# Générer tous les fichiers wg0.conf
wg-meshconf genconfig
Les fichiers générés sont prêts à être copiés sur chaque nœud via scp ou Ansible.
Bonnes pratiques et sécurité
- Permissions des fichiers : Le fichier
wg0.confcontient la clé privée — protégez-le avecchmod 600 /etc/wireguard/wg0.conf. - Pare-feu : Ouvrez uniquement le port UDP 51820. Bloquez tout autre accès non nécessaire sur l’interface
wg0. - PersistentKeepalive : La valeur 25 secondes est un bon compromis pour traverser les NAT sans surcharger le réseau. Désactivez-la si vos serveurs ont des IPs publiques statiques directement accessibles.
- Rotation des clés : Planifiez une rotation régulière des paires de clés (tous les 90 jours par exemple) pour limiter l’exposition en cas de compromission.
- Monitoring : Intégrez
wg show --jsonà votre stack de supervision (Prometheus + node-exporter ou Zabbix) pour alerter en cas de perte de handshake.
Dépannage rapide
# Vérifier que le port est ouvert
sudo ss -ulnp | grep 51820
# Voir les logs kernel WireGuard
sudo dmesg | grep wireguard
# Tester la résolution de route
ip route get 10.10.0.2
# Redémarrer proprement l'interface
sudo wg-quick down wg0 && sudo wg-quick up wg0
À lire également
- Serveur VPN WireGuard sous Linux — mise en place d’un serveur WireGuard classique hub-and-spoke
- Sécurité Linux — Firewall iptables et nftables — maîtriser les règles de filtrage réseau pour sécuriser vos interfaces WireGuard
- Ansible : automatiser la gestion de serveurs Linux — déployer et synchroniser les configurations WireGuard sur tout votre parc
- Authentification par clé publique SSH — sécuriser l’accès SSH sur vos nœuds VPN