Aller au contenu
Sécurité medium

Serveur VPN WireGuard sur Linux : installation et configuration

16 min de lecture

Ce guide monte un serveur VPN WireGuard complet sur Linux : vous générez les clés, écrivez le fichier wg0.conf, activez le routage NAT, connectez un premier client et validez le handshake. Il s'adresse aux administrateurs débutants à intermédiaires qui veulent un tunnel chiffré pour accéder à distance à un serveur ou un réseau privé, sans dépendre d'un service tiers. Vous repartez avec une configuration fonctionnelle, durcie (clé pré-partagée, pare-feu), et une méthode de dépannage quand le tunnel refuse de monter. Toutes les commandes ont été déroulées sur un lab réel.

  • Installer WireGuard depuis les dépôts signés de votre distribution.
  • Générer les paires de clés avec les bonnes permissions.
  • Configurer un serveur (wg0.conf, IP forwarding, NAT) et un client.
  • Valider le tunnel en lisant wg show et différencier full tunnel et split tunnel.
  • Durcir l'installation et diagnostiquer un handshake ou un MTU récalcitrant.

WireGuard fonctionne dans le noyau Linux (module intégré depuis la version 5.6). Vous avez besoin de :

  • un serveur Linux avec une IP publique joignable (VPS, machine exposée) et un accès sudo ;
  • un client Linux pour ce guide (la config est identique sur les autres OS, seul l'outil change) ;
  • la possibilité d'ouvrir un port UDP (par défaut 51820) sur le pare-feu et, le cas échéant, la box ou le Security Group cloud ;
  • un noyau récent : la commande lsmod | grep wireguard ou modinfo wireguard confirme la présence du module.

WireGuard est un protocole de VPN créé par Jason A. Donenfeld, intégré au noyau Linux, réputé pour sa simplicité (quelques milliers de lignes de code auditables) et ses performances supérieures à OpenVPN. Il chiffre le trafic avec de la cryptographie moderne (Curve25519 pour l'échange de clés, ChaCha20-Poly1305 pour le chiffrement, BLAKE2s pour le hachage) et fonctionne exclusivement en UDP.

Son modèle mental tient en une phrase : chaque machine possède une paire de clés, et deux machines communiquent dès qu'elles connaissent mutuellement leur clé publique. Il n'y a pas de notion de « client » et « serveur » dans le protocole : ce sont des pairs (peers). On parle de serveur simplement parce qu'une machine a une IP fixe, écoute sur un port et route le trafic des autres.

Les paquets proviennent des dépôts officiels et signés de votre distribution. Aucun script curl | sh n'est nécessaire, et il vaut mieux l'éviter pour un composant réseau privilégié.

Fenêtre de terminal
sudo apt update
sudo apt install wireguard

Le méta-paquet wireguard tire wireguard-tools (les commandes wg et wg-quick) et le module adapté à votre noyau. Sur Debian antérieure à Bullseye, activez d'abord les backports.

Vérifiez la version installée. Elle dépend de la distribution : les dépôts stables embarquent souvent une version plus ancienne que l'amont, ce qui est normal et sans danger, wireguard-tools évoluant très peu.

Fenêtre de terminal
wg --version
# wireguard-tools v1.0.20210914 - https://git.zx2c4.com/wireguard-tools/

Une clé privée ne doit jamais être lisible par d'autres comptes. On fixe donc un umask restrictif avant de générer quoi que ce soit, pour que les fichiers créés soient en permissions 600.

Fenêtre de terminal
umask 077
wg genkey | tee serveur.key | wg pubkey > serveur.pub
  • wg genkey produit une clé privée aléatoire en base64.
  • wg pubkey en dérive la clé publique correspondante.
  • tee enregistre la clé privée tout en la passant à wg pubkey.

Répétez l'opération pour le client (client.key / client.pub). Générez enfin une clé pré-partagée, une couche de chiffrement symétrique supplémentaire partagée par les deux pairs :

Fenêtre de terminal
wg genpsk > tunnel.psk

Le serveur se décrit dans /etc/wireguard/wg0.conf, un fichier au format INI. La section [Interface] décrit la machine locale, chaque section [Peer] décrit un pair autorisé.

# /etc/wireguard/wg0.conf (serveur)
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <CLE_PRIVEE_SERVEUR>
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = <CLE_PUBLIQUE_CLIENT>
PresharedKey = <CLE_PARTAGEE>
AllowedIPs = 10.10.0.2/32

Chaque directive a un rôle précis :

  • Address : l'IP du serveur dans le réseau privé du tunnel (ici 10.10.0.0/24). Choisissez une plage peu commune (évitez 192.168.0.0/24 ou 192.168.1.0/24, qui entrent en collision avec les box domestiques de vos clients).
  • ListenPort : le port UDP d'écoute.
  • PrivateKey : la clé privée du serveur.
  • PostUp / PostDown : des commandes exécutées à la montée et à la descente de l'interface. Ici elles autorisent le forwarding et activent le NAT (masquerade) pour que le trafic des clients ressorte vers Internet ou le LAN. Le jeton %i est remplacé par le nom d'interface (wg0). Remplacez eth0 par votre interface réseau publique (ip route get 1.1.1.1 vous la donne).
  • AllowedIPs côté serveur : les IP que ce pair a le droit d'utiliser. Pour un client unique, on met son /32.

Le NAT ne fonctionne que si le noyau route entre interfaces. Activez l'IP forwarding de façon persistante :

Fenêtre de terminal
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

Le client déclare le serveur comme pair et pointe vers son Endpoint (l'IP publique et le port du serveur).

# /etc/wireguard/wg0.conf (client)
[Interface]
Address = 10.10.0.2/24
PrivateKey = <CLE_PRIVEE_CLIENT>
[Peer]
PublicKey = <CLE_PUBLIQUE_SERVEUR>
PresharedKey = <CLE_PARTAGEE>
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25

Deux directives méritent attention :

  • Endpoint : l'adresse publique du serveur. Un client peut se déplacer sans la préciser côté serveur, WireGuard apprend son adresse au premier paquet valide.
  • PersistentKeepalive = 25 : le client envoie un petit paquet toutes les 25 secondes pour garder ouvert le mapping de son NAT. Sans lui, un client derrière une box devient injoignable après quelques dizaines de secondes d'inactivité. On ne le met que sur le pair réellement derrière un NAT.

Montez le tunnel des deux côtés avec wg-quick, qui lit le fichier et crée l'interface :

Fenêtre de terminal
sudo wg-quick up wg0
# [#] ip link add wg0 type wireguard
# [#] wg setconf wg0 /dev/fd/63
# [#] ip -4 address add 10.10.0.1/24 dev wg0
# [#] ip link set mtu 1420 up dev wg0

Vérifiez l'état avec wg show. La ligne décisive est latest handshake : si elle est renseignée, le tunnel chiffré est établi.

Fenêtre de terminal
sudo wg show
# interface: wg0
# public key: DoqtUJ4HD1prS9UbOBE8C4D7a/Yz6uq2tVKCy/B09wc=
# listening port: 51820
# peer: DVJfOZZrLnpgnUPf9laBkAOvDixxU+yE+mHwbInD/gQ=
# endpoint: 203.0.113.50:41466
# allowed ips: 10.10.0.2/32
# latest handshake: 2 seconds ago
# transfer: 660 B received, 476 B sent

Un ping à travers le tunnel confirme la connectivité :

Fenêtre de terminal
ping -c 3 10.10.0.1
# 3 packets transmitted, 3 received, 0% packet loss

Pour lancer le tunnel au démarrage, activez l'unité systemd fournie par le paquet :

Fenêtre de terminal
sudo systemctl enable --now wg-quick@wg0

Côté client, la directive AllowedIPs joue un double rôle : elle sert à la fois de table de routage (quel trafic entre dans le tunnel) et de filtre (quel trafic est accepté en retour). Sa valeur change tout :

Valeur d'AllowedIPsComportementUsage
10.10.0.0/24Split tunnel : seul le réseau du VPN passe par le tunnelAccéder à un serveur ou un LAN distant
0.0.0.0/0, ::/0Full tunnel : tout le trafic passe par le VPNMasquer son IP, sortir via le serveur

WireGuard est sûr par conception, mais l'installation par défaut ne bloque rien. Quelques mesures complètent la configuration :

  • Clé pré-partagée : déjà en place dans ce guide via PresharedKey, elle ajoute une couche symétrique qui renforce la résistance aux attaques futures, y compris post-quantiques.
  • Pare-feu : n'ouvrez que le port d'écoute UDP. Sur le serveur, autorisez 51820/udp en entrée. Ouvrir le port (chaîne INPUT) et autoriser le routage (chaîne FORWARD) sont deux choses distinctes : les deux sont nécessaires pour un serveur passerelle.
  • Fuites DNS : en full tunnel, ajoutez une directive DNS = côté client pour forcer le résolveur, et vérifiez qu'aucune requête ne s'échappe hors du tunnel.
  • Moindre privilège : le répertoire /etc/wireguard doit rester en 700 et les fichiers de config en 600. Ne versionnez jamais une clé privée.

La plupart des problèmes se diagnostiquent en quelques minutes avec la bonne méthode. Commencez toujours par confirmer, au tcpdump, que les paquets arrivent côté serveur : cela sépare un problème de réseau ou de pare-feu d'un problème de configuration.

Fenêtre de terminal
sudo tcpdump -ni eth0 udp port 51820
# IP 203.0.113.50.47059 > 203.0.113.10.51820: UDP, length 148
# IP 203.0.113.10.51820 > 203.0.113.50.47059: UDP, length 92

Un paquet de 148 octets (initiation du handshake) suivi d'une réponse de 92 octets signe un échange réussi. Si vous ne voyez que des paquets sortants sans réponse, le problème est en amont du serveur (port fermé, mauvaise IP).

SymptômeCause probableCorrectif
latest handshake reste videClés inversées, ou clé mal copiéeVérifier que la PublicKey d'un pair est bien la clé publique de l'autre
Aucun paquet au tcpdump serveurPort UDP fermé, mauvais EndpointOuvrir 51820/udp, corriger l'IP publique
Handshake OK mais rien ne routeip_forward désactivé, NAT absentActiver net.ipv4.ip_forward, vérifier le masquerade
SSH gèle, HTTPS charge à moitiéMTU trop grand (PPPoE, 4G)Baisser le MTU de wg0 (voir ci-dessous)
Tunnel meurt après 30 s d'inactivitéClient derrière NAT sans keepaliveAjouter PersistentKeepalive = 25 côté client
Handshake rejeté malgré tout bonHorloges désynchroniséesVérifier NTP des deux côtés

Le MTU est le piège le plus vicieux : le tunnel semble marcher (ping, DNS, petites pages), mais les gros paquets sont silencieusement jetés. WireGuard ajoute environ 60 à 80 octets d'en-tête, d'où un MTU par défaut de 1420. Sur une connexion PPPoE ou mobile, descendez à 1412, et en dernier recours à 1280 (le minimum garanti sur tout chemin) :

Fenêtre de terminal
sudo ip link set mtu 1280 dev wg0

Si le blocage disparaît, fixez la valeur dans wg0.conf avec la directive MTU.

Ce montage est parfait pour quelques machines. Mais gérer les clés à la main, déclarer chaque pair chez chaque autre et router entre sites devient vite pénible dès que le nombre de nœuds grandit. C'est le moment de passer à une surcouche qui automatise WireGuard.

Ces outils reposent tous sur WireGuard et ajoutent un control plane : distribution automatique des clés, découverte des pairs, traversée de NAT et contrôle d'accès. Vous gardez le moteur que vous venez d'apprendre, sans la corvée d'administration.

  • WireGuard vit dans le noyau Linux, chiffre en ChaCha20-Poly1305 et fonctionne en UDP uniquement.
  • Le modèle est pair à pair : chaque machine a une clé privée, et deux pairs se parlent dès qu'ils connaissent leur clé publique mutuelle.
  • Un serveur passerelle a besoin de trois choses : IP forwarding, NAT (masquerade) et le port UDP ouvert.
  • AllowedIPs décide du split tunnel (/24) ou du full tunnel (0.0.0.0/0) et sert aussi de filtre : attention aux plages qui se chevauchent.
  • PersistentKeepalive = 25 garde vivant un pair derrière un NAT.
  • Diagnostic : tcpdump d'abord (les paquets arrivent-ils ?), puis clés, port, AllowedIPs, et enfin le MTU pour les blocages partiels.
  • Au-delà de quelques nœuds, une surcouche mesh (Tailscale, NetBird) automatise la gestion des clés et des pairs.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn