WireGuard
WireGuard est un protocle de réseau privé virtuel (VPN) libre et open source conçu pour établir des communications sécurisées entre des équipements connectés à un réseau IP. Développé par Jason A. Donenfeld et publié pour la première fois en 2015, il a été conçu pour offrir une alternative moderne aux protocoles VPN traditionnels tels qu'OpenVPN et IPsec, en mettant l'accent sur la simplicité, les performances et la sécurité.
Source : Wikipedia
Principes
WireGuard fonctionne au niveau de la couche réseau et encapsule les paquets IP dans des datagrammes UDP. Chaque pair possède une paire de clés cryptographiques composée d'une clé privée et d'une clé publique.
Contrairement à de nombreux protocoles VPN traditionnels, WireGuard ne repose pas sur une infrastructure de certificats x.509 ni sur une autorité de certification. L'authentification des pairs est réalisée à l'aide de leurs clés publiques, qui sont configurés manuellement ou distribués par un système de gestion externe.
Chaque pair est également associé à une liste de préfixes IP autorisées (AllowedIPs). Cette information sert à la fois de politique de routage et de mécanisme de contrôle d'accès, en déterminant quelles addresses IP peuvent être atteintes via chaque tunnel.
Créer un tunnel entre deux réseaux distants
Contexte et architecture
- Serveur VPN (VPS OVH qui s'appellera
DEBIAN13-OVH) : possède une IP publique fixe, c'est lui qui écoute sur le port UDP ouvert. C'est le point central du tunnel. - Client (machine Debian à la maison qui s'appellera
DEBIAN13-LAB) : se connecte au VPS, pas d'ouverture de port nécessaire côté box/routeur. - Réseau overlay WireGuard : 10.10.0.0/24 (à adapter selon vos plages déjà utilisées, ex. Tailscale en 100.64.0.0/10).
Le serveur WireGuard (DEBIAN13-OVH) ouvrira le port 51820 en UDP (règles de pare-feu à faire).
| Rôle | Machine | IP publique | IP WireGuard |
|---|---|---|---|
| Serveur | VPS OVH | 11.22.33.44 | 10.10.0.1/24 |
| Client 1 | Debian maison | dynamique/fixe | 10.10.0.2/24 |
Installer WireGuard sur nos deux machines
sudo apt install wireguardGénérer les paires de clés
Sur DEBIAN13-OVH et DEBIAN13-LAB, on génère une paire clé privée / clé publique. Le dossier /etc/wireguard doit rester en 600.
cd /etc/wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickeyLa clé publique de chaque machine sera à communiquer à l'autre pour établir la relation de confiance. La clé privée, elle, ne quitte jamais sa machine.
Configurer le serveur DEBIAN13-OVH
/etc/wireguard/wg0.conf :
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <clé_privée_DEBIAN13-OVH>
SaveConfig = false
PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# DEBIAN13-LAB
PublicKey = <clé_publique_DEBIAN13-LAB>
AllowedIPs = 10.10.0.2/32Remplacer
eth0par le nom réel de l'interface publique (ip a).
Ouvrir le port côté OVH
Deux niveaux de pare-feu à traiter :
- Firewall réseau OVH (manager OVH) : ouvrir le port UDP 51820 en entrée sur
11.22.33.44. - Pare-feu local :
sudo ufw allow 51820/udpActiver le forwarding IP de façon persistante
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -pConfigurer le client DEBIAN13-LAB
/etc/wireguard/wg0.conf :
[Interface]
Address = 10.10.0.2/24
PrivateKey = <clé_privée_DEBIAN13-LAB>
[Peer]
# DEBIAN13-OVH
PublicKey = <clé_publique_DEBIAN13-OVH>
Endpoint = 11.22.33.44:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25PersistentKeepalive est indispensable ici : DEBIAN13-LAB est derrière un NAT/box, ce paramètre maintient le mapping NAT ouvert vis-à-vis du serveur.
Démarrer le tunnel
Sur les deux machines :
sudo systemctl enable --now wg-quick@wg0
sudo wg showVérifier la connectivité
# Depuis DEBIAN13-LAB
ping 10.10.0.1
# Depuis DEBIAN13-OVH
ping 10.10.0.2Un ping réussi dans les deux sens confirme que le tunnel est opérationnel.
Ajouter un noeud au tunnel
Exemple : intégration d'un troisième noeud, DEBIAN13-PI (Raspberry Pi), en 10.10.0.3.
Sur le nouveau noeud
cd /etc/wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey/etc/wireguard/wg0.conf :
[Interface]
Address = 10.10.0.3/24
PrivateKey = <clé_privée_DEBIAN13-PI>
[Peer]
# DEBIAN13-OVH
PublicKey = <clé_publique_DEBIAN13-OVH>
Endpoint = 11.22.33.44:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25Sur DEBIAN13-OVH
Ajouter un bloc [Peer] dans wg0.conf :
[Peer]
# DEBIAN13-PI
PublicKey = <clé_publique_DEBIAN13-PI>
AllowedIPs = 10.10.0.3/32Recharger la config sans couper le tunnel existant :
sudo wg syncconf wg0 <(wg-quick strip wg0)Alternative à chaud, sans toucher au fichier dans l'immédiat (à reporter ensuite dans wg0.conf pour survivre à un redémarrage) :
sudo wg set wg0 peer <clé_publique_DEBIAN13-PI> allowed-ips 10.10.0.3/32Démarrer le tunnel sur le nouveau noeud
sudo systemctl enable --now wg-quick@wg0Supprimer un noeud du tunnel
Sur DEBIAN13-OVH
À chaud, sans redémarrer l'interface :
sudo wg set wg0 peer <clé_publique_du_noeud_à_retirer> removeDe façon persistante, supprimer le bloc [Peer] correspondant dans wg0.conf, puis :
sudo wg syncconf wg0 <(wg-quick strip wg0)Sur le noeud retiré
sudo systemctl disable --now wg-quick@wg0
sudo rm /etc/wireguard/wg0.confSi le noeud ne doit plus jamais rejoindre le tunnel, supprimer également privatekey et publickey.
Faire rejoindre un routeur TP-Link Omada ER605 au tunnel
Le ER605 intègre un client/serveur WireGuard natif, mais uniquement à partir des hardware versions V2 et V2.60 — la V1 ne le supporte pas et n'affichera même pas le menu correspondant. Vérifier sa version sur l'étiquette sous le boîtier ou dans Overview de l'interface web avant de commencer.
Contrairement aux noeuds précédents, le ER605 est un routeur passerelle : il ne rejoint pas le tunnel comme un simple hôte, mais comme une porte d'entrée vers tout un réseau LAN placé derrière lui (192.168.50.0/24 dans cet exemple). Il sera nommé ER605-LAB et prendra l'IP 10.10.0.4/32 sur l'overlay.
| Rôle | Machine | IP publique | IP WireGuard | Réseau annexe |
|---|---|---|---|---|
| Routeur | ER605-LAB | dynamique/fixe | 10.10.0.4/32 | 192.168.50.0/24 |
Configurer l'interface WireGuard sur le ER605 (mode standalone)
Dans l'interface web du routeur :
- Aller dans VPN > WireGuard, cliquer sur Add pour créer l'interface locale.
- Renseigner :
- Name :
ER605-LAB - MTU :
1420(valeur par défaut recommandée) - Local IP Address :
10.10.0.4/32 - Listen Port : laisser vide ou par défaut, ce champ ne sert que si le ER605 doit lui-même écouter des connexions entrantes, ce qui n'est pas le cas ici (il est client de
DEBIAN13-OVH). - Private Key / Public Key : générées automatiquement par l'interface — copier la clé publique affichée, elle sera nécessaire côté serveur.
- Name :
Ajouter le peer DEBIAN13-OVH côté ER605
Toujours dans VPN > WireGuard, section Peers, cliquer sur Add :
- Interface :
ER605-LAB(celle créée à l'étape précédente) - Public Key : clé publique de
DEBIAN13-OVH - Endpoint :
11.22.33.44 - Endpoint Port :
51820 - Allowed Address :
10.10.0.0/24(accès à l'ensemble de l'overlay) - Persistent Keepalive :
25
Ajouter le peer ER605-LAB côté DEBIAN13-OVH
Dans /etc/wireguard/wg0.conf sur le serveur :
[Peer]
# ER605-LAB
PublicKey = <clé_publique_ER605-LAB>
AllowedIPs = 10.10.0.4/32, 192.168.50.0/24L'ajout de 192.168.50.0/24 dans AllowedIPs est ce qui permet à DEBIAN13-OVH (et donc, si le routage est autorisé, aux autres noeuds du tunnel) de joindre les machines du réseau local derrière le ER605, et pas uniquement le routeur lui-même.
Recharger la configuration sans couper le tunnel :
sudo wg syncconf wg0 <(wg-quick strip wg0)Activer le routage côté ER605
Pour que le LAN 192.168.50.0/24 soit effectivement accessible via le tunnel, vérifier que :
- L'interface WireGuard est bien activée (Status: Enable).
- Une route est présente (automatiquement ajoutée par Omada dans la majorité des cas) faisant passer le trafic vers
10.10.0.0/24par l'interfaceER605-LAB. - Si des ACL inter-VLAN sont en place sur le ER605, s'assurer qu'elles n'interceptent pas le trafic destiné au tunnel avant qu'il n'atteigne l'interface WireGuard.
Vérification
# Depuis DEBIAN13-OVH
ping 10.10.0.4
ping 192.168.50.1 # ex. IP LAN du ER605Depuis l'interface web du ER605, VPN > WireGuard affiche l'état du handshake et le volume de données échangées avec DEBIAN13-OVH, équivalent à wg show côté Linux.
Si l'infrastructure évolue vers plusieurs sites Omada, la configuration Site-to-Site WireGuard via le contrôleur Omada SDN (Settings > VPN > WireGuard) permet de gérer les peers de façon centralisée plutôt que routeur par routeur — à envisager si un deuxième ER605 ou une autre passerelle Omada rejoint le tunnel.
Automatiser la rotation des clés (optionnel)
Faire tourner régulièrement les paires de clés réduit la fenêtre d'exposition en cas de compromission silencieuse d'un noeud. Le principe : régénérer une nouvelle paire de clés sur le noeud concerné, puis mettre à jour uniquement son bloc [Peer] côté serveur, sans toucher aux autres pairs ni couper le tunnel global.
Exemple de script rotate-wg-key.sh à exécuter sur un noeud (ex. DEBIAN13-LAB) :
#!/usr/bin/env bash
set -euo pipefail
WG_DIR="/etc/wireguard"
OLD_PUBKEY=$(cat "$WG_DIR/publickey")
cd "$WG_DIR"
umask 077
wg genkey | tee privatekey.new | wg pubkey > publickey.new
NEW_PUBKEY=$(cat publickey.new)
# Met à jour l'interface locale à chaud
sudo wg set wg0 private-key <(cat privatekey.new)
mv privatekey.new privatekey
mv publickey.new publickey
echo "Ancienne clé publique : $OLD_PUBKEY"
echo "Nouvelle clé publique : $NEW_PUBKEY"
echo "-> à reporter manuellement (ou via Ansible) sur DEBIAN13-OVH"Ce script peut être déclenché via un timer systemd (rotate-wg-key.timer, par exemple tous les 90 jours). La contrainte principale reste la synchronisation : le serveur doit connaître la nouvelle clé publique avant que l'ancienne ne soit invalidée localement, sous peine de coupure du tunnel pour ce noeud. C'est cette contrainte qui rend l'intégration Ansible (section suivante) particulièrement pertinente : elle permet de pousser la nouvelle clé publique sur DEBIAN13-OVH de façon coordonnée et traçable.
Intégration dans un playbook Ansible
L'objectif est de gérer la configuration WireGuard de façon déclarative : génération des clés si absentes, templating du fichier wg0.conf, et rechargement du service — le tout de manière idempotente et reproductible sur l'ensemble des noeuds.
Arborescence du rôle
roles/wireguard/
├── defaults/
│ └── main.yml
├── tasks/
│ └── main.yml
├── templates/
│ └── wg0.conf.j2
└── handlers/
└── main.ymldefaults/main.yml
wg_interface: wg0
wg_port: 51820
wg_address: "10.10.0.2/24"
wg_peers: [] # liste des peers à injecter, définie par host_varstasks/main.yml
---
- name: Installer WireGuard
apt:
name: wireguard
state: present
update_cache: true
- name: Vérifier la présence d'une clé privée existante
stat:
path: /etc/wireguard/privatekey
register: wg_privkey_stat
- name: Générer la paire de clés si absente
shell: |
umask 077
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
when: not wg_privkey_stat.stat.exists
- name: Lire la clé privée générée
slurp:
src: /etc/wireguard/privatekey
register: wg_privkey_raw
- name: Lire la clé publique générée
slurp:
src: /etc/wireguard/publickey
register: wg_pubkey_raw
- name: Déployer la configuration wg0.conf
template:
src: wg0.conf.j2
dest: "/etc/wireguard/{{ wg_interface }}.conf"
owner: root
group: root
mode: "0600"
notify: Recharger WireGuard
- name: Activer et démarrer le service
systemd:
name: "wg-quick@{{ wg_interface }}"
enabled: true
state: startedtemplates/wg0.conf.j2
[Interface]
Address = {{ wg_address }}
{% if wg_port is defined %}
ListenPort = {{ wg_port }}
{% endif %}
PrivateKey = {{ wg_privkey_raw.content | b64decode | trim }}
{% for peer in wg_peers %}
[Peer]
# {{ peer.name }}
PublicKey = {{ peer.public_key }}
AllowedIPs = {{ peer.allowed_ips }}
{% if peer.endpoint is defined %}
Endpoint = {{ peer.endpoint }}
{% endif %}
{% if peer.persistent_keepalive is defined %}
PersistentKeepalive = {{ peer.persistent_keepalive }}
{% endif %}
{% endfor %}handlers/main.yml
---
- name: Recharger WireGuard
shell: "wg syncconf {{ wg_interface }} <(wg-quick strip {{ wg_interface }})"
args:
executable: /bin/bashDéclaration des peers par hôte (host_vars/debian13-ovh.yml)
wg_address: "10.10.0.1/24"
wg_peers:
- name: DEBIAN13-LAB
public_key: "<clé_publique_DEBIAN13-LAB>"
allowed_ips: "10.10.0.2/32"
- name: DEBIAN13-PI
public_key: "<clé_publique_DEBIAN13-PI>"
allowed_ips: "10.10.0.3/32"L'ajout ou la suppression d'un noeud revient alors à modifier wg_peers dans le host_vars du serveur puis à relancer le playbook — le handler Recharger WireGuard se charge d'appliquer la nouvelle configuration sans interrompre les pairs déjà connectés.
