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 UDP 51820, adresse VPN 10.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 = 1nnet.ipv4.conf.all.forwarding = 1nnet.ipv4.conf.default.forwarding = 1n' > /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 .conf gé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.