WireGuard est un VPN moderne, ultra-performant et d’une remarquable simplicité de configuration. Comparé à OpenVPN ou IPSec, il se distingue par une base de code minimaliste (moins de 4 000 lignes), une cryptographie d’état de l’art et des performances proches du niveau noyau. Sous Debian 13 Trixie, WireGuard est intégré nativement dans le noyau Linux 6.x : aucun module supplémentaire n’est nécessaire.
Dans cet article, nous allons mettre en place un serveur WireGuard sur Debian 13, configurer un premier client, puis voir comment ajouter de nouveaux clients facilement, y compris à chaud sans redémarrer le service.
Schéma de notre infrastructure
Voici l’architecture que nous allons construire :
- Serveur WireGuard : Debian 13, IP publique
X.X.X.X, port UDP51820, adresse VPN10.8.0.1/24 - Client 1 : adresse VPN
10.8.0.2/32 - Client 2 : adresse VPN
10.8.0.3/32 - Client N : adresse VPN
10.8.0.N/32
Le sous-réseau VPN utilisé est 10.8.0.0/24. Chaque client dispose d’une IP fixe assignée par le serveur.
Prérequis
- Un serveur sous Debian 13 Trixie avec une IP publique
- Un port UDP ouvert sur le pare-feu : 51820/UDP
- Accès root sur le serveur
- Les clients peuvent tourner sous Linux, Windows, macOS, Android ou iOS
Installation de WireGuard sur le serveur
Sur Debian 13, le module WireGuard est inclus dans le noyau. Il suffit d’installer les outils en espace utilisateur :
apt update && apt install -y wireguard wireguard-tools
Génération des clés du serveur
WireGuard utilise une paire de clés asymmétriques (Curve25519) pour chaque pair. On commence par générer les clés du serveur :
# Se placer dans le répertoire de configuration WireGuard cd /etc/wireguard # Générer la clé privée du serveur (droits restreints) umask 077 wg genkey | tee server_private.key | wg pubkey > server_public.key # Afficher les clés générées echo "Clé privée serveur :" && cat server_private.key echo "Clé publique serveur :" && cat server_public.key
Le fichier server_private.key ne doit jamais quitter le serveur et doit rester lisible uniquement par root (ce que le umask 077 garantit).
Configuration du serveur
On crée le fichier de configuration de l’interface WireGuard. L’interface sera nommée wg0 :
Contenu du fichier /etc/wireguard/wg0.conf :
[Interface] # Clé privée du serveur PrivateKey = VOTRE_CLE_PRIVEE_SERVEUR # Adresse IP du serveur dans le tunnel VPN Address = 10.8.0.1/24 # Port UDP d'écoute ListenPort = 51820 # Activer le routage (adapter ens192 selon votre interface) PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens192 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens192 -j MASQUERADE
Pour renseigner la clé privée automatiquement :
# Injecter la clé privée réelle dans le fichier de configuration PRIVKEY=$(cat /etc/wireguard/server_private.key) sed -i "s|VOTRE_CLE_PRIVEE_SERVEUR|$PRIVKEY|" /etc/wireguard/wg0.conf # Sécuriser le fichier de configuration chmod 600 /etc/wireguard/wg0.conf
Pour connaître le nom de votre interface réseau publique (celle à renseigner dans PostUp/PostDown) :
ip route | grep default # Exemple de retour : default via 192.168.1.1 dev ens192 proto dhcp # Ici l'interface est ens192
Activation du routage IP
Pour que le serveur puisse router les paquets entre le tunnel VPN et le réseau public, il faut activer le forwarding IPv4.
⚠️ Point important pour Debian 13 Trixie : sous Debian 13, les nouvelles interfaces réseau créées après le boot héritent de la valeur conf.default.forwarding et non de conf.all.forwarding. Il faut donc positionner les deux variables pour que le forwarding fonctionne correctement :
# Créer un fichier sysctl dédié à WireGuard printf 'net.ipv4.ip_forward = 1\nnet.ipv4.conf.all.forwarding = 1\nnet.ipv4.conf.default.forwarding = 1\n' > /etc/sysctl.d/99-wireguard.conf # Appliquer immédiatement sans redémarrer sysctl -p /etc/sysctl.d/99-wireguard.conf
Démarrage du serveur WireGuard
# Activer et démarrer l'interface WireGuard systemctl enable --now wg-quick@wg0 # Vérifier que l'interface est montée ip a show wg0 # Vérifier l'état WireGuard wg show
Le serveur est maintenant opérationnel. Il écoute sur le port 51820/UDP et attend des connexions de clients.
Configuration du premier client
Génération des clés du client
Les opérations de génération de clés peuvent se faire sur le serveur (plus pratique) ou directement sur la machine cliente. Dans les deux cas, la clé privée du client ne doit jamais transiter en clair.
# Sur le serveur, créer un répertoire pour les clés clients mkdir -p /etc/wireguard/clients/client1 cd /etc/wireguard/clients/client1 # Générer la paire de clés du client 1 umask 077 wg genkey | tee client1_private.key | wg pubkey > client1_public.key echo "Clé privée client1 :" && cat client1_private.key echo "Clé publique client1 :" && cat client1_public.key
Ajout du client dans la configuration serveur
On ajoute un bloc [Peer] dans /etc/wireguard/wg0.conf pour déclarer le client :
Ajouter à la fin de /etc/wireguard/wg0.conf le bloc suivant (en remplaçant par la clé publique réelle du client) :
[Peer] # Client 1 PublicKey = CLE_PUBLIQUE_CLIENT1 AllowedIPs = 10.8.0.2/32
# Pour automatiser avec la clé générée, utiliser wg set (voir section ajout clients) : wg set wg0 peer $(cat /etc/wireguard/clients/client1/client1_public.key) allowed-ips 10.8.0.2/32 wg-quick save wg0
Le champ AllowedIPs côté serveur indique quelle adresse IP est autorisée à se connecter avec cette clé publique. En mettant /32, on restreint à une seule adresse.
Fichier de configuration du client
Créer le fichier wg0.conf suivant sur la machine cliente (Linux). Pour les autres OS, les champs sont identiques — seule la méthode d’installation du fichier diffère.
# Générer le fichier de config client1 automatiquement SERVER_PUBKEY=$(cat /etc/wireguard/server_public.key) CLIENT_PRIVKEY=$(cat /etc/wireguard/clients/client1/client1_private.key) CONF=/etc/wireguard/clients/client1/wg0-client1.conf
Contenu du fichier wg0-client1.conf à copier sur la machine cliente :
[Interface] PrivateKey = CLE_PRIVEE_CLIENT1 Address = 10.8.0.2/32 DNS = 1.1.1.1 [Peer] # Clé publique du serveur PublicKey = CLE_PUBLIQUE_SERVEUR # IP publique du serveur et port d'écoute Endpoint = X.X.X.X:51820 # Tout le trafic passe par le VPN # Pour le sous-réseau VPN uniquement : AllowedIPs = 10.8.0.0/24 AllowedIPs = 0.0.0.0/0 # Maintenir la connexion (utile derrière un NAT) PersistentKeepalive = 25
# Créer le fichier de config en remplaçant les clés réelles : # (utiliser le contenu affiché ci-dessus comme modèle) chmod 600 /etc/wireguard/clients/client1/wg0-client1.conf nano /etc/wireguard/clients/client1/wg0-client1.conf
Adapter X.X.X.X avec l’adresse IP publique réelle du serveur.
Rechargement de la configuration serveur
Après avoir ajouté le bloc [Peer] dans wg0.conf, on peut recharger la configuration à chaud sans couper les connexions existantes :
# Recharger la configuration sans couper le service wg-quick strip wg0 > /tmp/wg0.strip && wg syncconf wg0 /tmp/wg0.strip && rm -f /tmp/wg0.strip # Vérifier que le nouveau pair est bien enregistré wg show
Activation du client (Linux)
# Copier le fichier de configuration sur la machine cliente # (transmettre le fichier de manière sécurisée, par ex. via SCP ou stockage chiffré) scp /etc/wireguard/clients/client1/wg0-client1.conf user@client1:/etc/wireguard/wg0.conf # Sur la machine cliente, démarrer WireGuard systemctl enable --now wg-quick@wg0 # Vérifier la connexion wg show ping 10.8.0.1
Test de la connexion
# Depuis le client : tester la connectivité avec le serveur VPN ping 10.8.0.1 # Depuis le serveur : vérifier que le client est visible wg show # La section "latest handshake" doit afficher un timestamp récent # Vérifier le routage (si AllowedIPs = 0.0.0.0/0) curl ifconfig.me # Doit retourner l'IP publique du serveur VPN
Ajouter des clients supplémentaires
L’un des grands avantages de WireGuard est la facilité d’ajout de nouveaux clients, même à chaud.
Méthode 1 : modification du fichier de configuration (recommandée)
C’est la méthode la plus propre car elle garantit que la configuration persiste au redémarrage.
# Générer les clés du client 2 mkdir -p /etc/wireguard/clients/client2 cd /etc/wireguard/clients/client2 umask 077 wg genkey | tee client2_private.key | wg pubkey > client2_public.key
Ajouter à la fin de /etc/wireguard/wg0.conf :
[Peer] # Client 2 PublicKey = CLE_PUBLIQUE_CLIENT2 AllowedIPs = 10.8.0.3/32
# Puis recharger à chaud la configuration du serveur wg-quick strip wg0 > /tmp/wg0.strip && wg syncconf wg0 /tmp/wg0.strip && rm -f /tmp/wg0.strip # Vérifier wg show
Générer ensuite le fichier de configuration client2 avec l’adresse 10.8.0.3/32 de la même façon que pour client1.
Méthode 2 : ajout à chaud avec wg set (sans modifier wg0.conf)
Cette méthode est utile pour des tests rapides ou des scripts, mais elle n’est pas persistante au redémarrage du service.
# Ajouter un pair à chaud directement dans l'interface wg0 wg set wg0 peer CLE_PUBLIQUE_CLIENT3 allowed-ips 10.8.0.4/32 # Vérifier wg show wg0 # Si on veut persister cette modification dans wg0.conf : wg-quick save wg0
⚠️ wg-quick save wg0 écrase complètement wg0.conf avec l’état actuel de l’interface. À utiliser avec précaution si des commentaires ou une mise en forme personnalisée sont présents dans le fichier.
Script de génération de client (tout-en-un)
Voici un script pratique pour automatiser la création d’un nouveau client :
#!/bin/bash
# add-wg-client.sh NOM_CLIENT IP_VPN IP_SERVEUR
# Exemple : ./add-wg-client.sh client3 10.8.0.4 203.0.113.10
CLIENT_NAME=$1
CLIENT_IP=$2
SERVER_PUBLIC_IP=$3
WG_DIR="/etc/wireguard"
CLIENT_DIR="$WG_DIR/clients/$CLIENT_NAME"
if [ -z "$CLIENT_NAME" ] || [ -z "$CLIENT_IP" ] || [ -z "$SERVER_PUBLIC_IP" ]; then
echo "Usage: $0 NOM_CLIENT IP_VPN IP_SERVEUR"
exit 1
fi
mkdir -p "$CLIENT_DIR"
umask 077
# Generer les cles
wg genkey | tee "$CLIENT_DIR/${CLIENT_NAME}_private.key" | wg pubkey > "$CLIENT_DIR/${CLIENT_NAME}_public.key"
CLIENT_PRIVKEY=$(cat "$CLIENT_DIR/${CLIENT_NAME}_private.key")
CLIENT_PUBKEY=$(cat "$CLIENT_DIR/${CLIENT_NAME}_public.key")
SERVER_PUBKEY=$(cat "$WG_DIR/server_public.key")
# Generer le fichier de config client section par section
# (utilise des variables pour les noms de section WireGuard)
S_IFACE=Interface
S_PEER=Peer
{
echo "[$S_IFACE]"
echo "PrivateKey = $CLIENT_PRIVKEY"
echo "Address = $CLIENT_IP/32"
echo "DNS = 1.1.1.1"
echo ""
echo "[$S_PEER]"
echo "PublicKey = $SERVER_PUBKEY"
echo "Endpoint = $SERVER_PUBLIC_IP:51820"
echo "AllowedIPs = 0.0.0.0/0"
echo "PersistentKeepalive = 25"
} > "$CLIENT_DIR/wg0-${CLIENT_NAME}.conf"
# Ajouter le pair dans la config serveur via wg set (propre et sans edition de fichier)
wg set wg0 peer "$CLIENT_PUBKEY" allowed-ips "$CLIENT_IP/32"
wg-quick save wg0
# Recharger
wg-quick strip wg0 > /tmp/wg0.strip && wg syncconf wg0 /tmp/wg0.strip && rm -f /tmp/wg0.strip
echo "[OK] Client $CLIENT_NAME ajoute avec l'IP $CLIENT_IP"
echo "Fichier de config : $CLIENT_DIR/wg0-${CLIENT_NAME}.conf"
Supprimer un client
Pour révoquer l’accès d’un client, il suffit de supprimer son bloc [Peer] du fichier wg0.conf, puis de recharger la configuration :
# Editer wg0.conf et supprimer le bloc Peer du client a revoquer nano /etc/wireguard/wg0.conf # Recharger à chaud wg-quick strip wg0 > /tmp/wg0.strip && wg syncconf wg0 /tmp/wg0.strip && rm -f /tmp/wg0.strip # Vérifier que le client est bien absent wg show
Ou bien, pour retirer un pair à chaud immédiatement (puis éditer le fichier) :
# Retirer un pair à chaud (remplacer par la clé publique réelle du client) wg set wg0 peer CLE_PUBLIQUE_CLIENT remove # Puis nettoyer wg0.conf pour la persistance nano /etc/wireguard/wg0.conf
Commandes de diagnostic utiles
# Afficher l'état complet de WireGuard (tous les pairs, handshakes, trafic) wg show # Afficher uniquement l'interface wg0 wg show wg0 # Afficher les IPs autorisées pour chaque pair wg show wg0 allowed-ips # Afficher les derniers handshakes (0 = jamais connecté) wg show wg0 latest-handshakes # Afficher le trafic par pair (octets reçus / envoyés) wg show wg0 transfer # Lister les routes actives ip route show table all | grep wg0 # Vérifier les logs systemd de wg-quick journalctl -u wg-quick@wg0 -f # Vérifier que le port UDP 51820 est bien écouté ss -ulnp | grep 51820
Configuration du pare-feu (nftables)
Si vous utilisez nftables sur Debian 13 (recommandé plutôt qu’iptables), voici les règles à ajouter pour autoriser le trafic WireGuard. Les règles PostUp/PostDown du fichier wg0.conf utilisent iptables, qui reste fonctionnel sous Debian 13 via iptables-legacy ou le backend nftables.
Si vous gérez votre pare-feu entièrement via nftables, voici un exemple de règles à intégrer dans votre /etc/nftables.conf :
# Dans la table inet filter :
# Autoriser le trafic entrant sur le port WireGuard
add rule inet filter input udp dport 51820 accept
# Autoriser le forwarding depuis/vers wg0
add rule inet filter forward iif wg0 accept
add rule inet filter forward oif wg0 accept
# Dans la table ip nat, ajouter le masquerading :
add table ip nat
add chain ip nat postrouting { type nat hook postrouting priority 100; }
add rule ip nat postrouting oif ens192 masquerade
# Appliquer
nft -f /etc/nftables.conf
Dans ce cas, retirer les lignes PostUp et PostDown du fichier wg0.conf pour éviter les doublons.
Clients non-Linux : Windows, macOS, Android, iOS
WireGuard dispose de clients officiels pour tous les systèmes d’exploitation :
- Windows : télécharger le client sur wireguard.com/install, importer le fichier
.confgénéré - macOS : disponible sur le Mac App Store, même procédure d’import du fichier
.conf - Android / iOS : app officielle WireGuard sur Play Store / App Store. On peut générer un QR code à partir du fichier de configuration pour faciliter l’import :
# Installer qrencode sur le serveur apt install -y qrencode # Générer le QR code d'un fichier de config client cat /etc/wireguard/clients/client1/wg0-client1.conf | qrencode -t ansiutf8 # Ou le sauvegarder en image PNG cat /etc/wireguard/clients/client1/wg0-client1.conf | qrencode -o /tmp/client1-qr.png
Scanner le QR code depuis l’application WireGuard mobile pour importer la configuration directement.
Récapitulatif de la structure des fichiers
/etc/wireguard/
├── wg0.conf # Config principale du serveur
├── server_private.key # Clé privée serveur (600, root only)
├── server_public.key # Clé publique serveur
└── clients/
├── client1/
│ ├── client1_private.key # Clé privée client1
│ ├── client1_public.key # Clé publique client1
│ └── wg0-client1.conf # Fichier de config à transférer au client
└── client2/
├── client2_private.key
├── client2_public.key
└── wg0-client2.conf
Conclusion
WireGuard est aujourd’hui l’une des solutions VPN les plus simples et les plus performantes disponibles sous Linux. Son intégration native dans le noyau Debian 13, sa configuration minimaliste et sa capacité à ajouter ou révoquer des clients à chaud en font un outil de choix pour tous les usages : accès distant sécurisé, interconnexion de sites, accès à un cloud privé…
Le point clé à retenir sur Debian 13 est la double configuration du forwarding IPv4 (conf.all.forwarding et conf.default.forwarding) pour éviter que les nouvelles interfaces réseau ne bloquent le routage après le boot.
