Ce tutoriel relie un serveur hébergé (un VPS sous Rocky Linux) au réseau de la maison par un tunnel WireGuard. À la fin, le serveur joint les machines de la maison, la maison joint le serveur, et seul un port UDP est exposé sur Internet. C’est la base de nombreux usages : sauvegardes envoyées vers un NAS, supervision d’un serveur public depuis la maison, accès à des services qu’on ne veut surtout pas publier.
Chaque ligne de configuration est expliquée, ainsi que les vérifications à faire et les pannes les plus fréquentes. Les adresses sont des exemples ; adaptez-les à votre plan d’adressage.
Pourquoi WireGuard
WireGuard tient en quelques milliers de lignes de code dans le noyau Linux, contre des centaines de milliers pour OpenVPN ou IPsec. Il n’offre aucun choix d’algorithme : la cryptographie est fixée (Curve25519, ChaCha20-Poly1305, BLAKE2s), ce qui supprime une source entière d’erreurs de configuration. Il est sans état apparent : pas de session à négocier à la main, une poignée de main renouvelée automatiquement toutes les deux minutes environ, et un tunnel qui survit aux changements d’adresse d’un des pairs. Enfin, il est silencieux : un paquet qui n’est pas authentifié par une clé connue ne reçoit aucune réponse, le port semble fermé à un balayage.
Les notions à avoir en tête
- Une paire de clés par extrémité. La clé privée reste sur la machine ; la clé publique sert d’identité auprès de l’autre côté. Il n’y a ni utilisateur ni mot de passe ;
- Des pairs, pas un client et un serveur. Chaque côté déclare l’autre comme pair. Ce qui ressemble à un « serveur » est simplement le pair qui a une adresse fixe et attend qu’on l’appelle ;
- Le routage par clé. La directive
AllowedIPsassocie des réseaux à un pair. Un paquet destiné à ces réseaux part chiffré vers ce pair ; un paquet reçu de ce pair n’est accepté que si son adresse source appartient à ces réseaux ; - UDP uniquement. Tout passe dans un seul port UDP, ce qui traverse bien les traductions d’adresses des box.
Le plan d’adressage
| Élément | Valeur | Rôle |
|---|---|---|
| Réseau du tunnel | 10.99.0.0/24 | adresses internes au tunnel, une par extrémité |
| Routeur (tunnel) | 10.99.0.2 | côté maison, derrière la box |
| Serveur (tunnel) | 10.99.0.3 | le VPS |
| Réseau de la maison | 192.168.10.0/24 | ce que le serveur doit pouvoir joindre |
| Serveur (public) | 203.0.113.25 | adresse publique fixe du VPS, port UDP 51820 |
Choisissez un réseau de tunnel qui n’existe nulle part ailleurs chez vous, ni chez l’hébergeur : un chevauchement d’adresses produit des pannes très difficiles à comprendre.
Prérequis
- un serveur Rocky Linux 9 ou 10 avec une adresse IPv4 publique fixe et un accès root ;
- un routeur à la maison qui sait faire du WireGuard (RouterOS 7 de MikroTik, OpenWrt, pfSense, OPNsense…), ou à défaut une machine Linux allumée en permanence ;
- un accès console au serveur chez l’hébergeur, au cas où une erreur de pare-feu couperait SSH.
Étape 1 : installer les outils
Le module noyau fait partie de Rocky Linux depuis la version 9. Il ne manque que les outils en espace utilisateur, wg et wg-quick :
dnf install wireguard-tools
modprobe wireguard
lsmod | grep wireguard # le module est chargé
Étape 2 : générer les clés
umask 077
cd /etc/wireguard
wg genkey | tee server.key | wg pubkey > server.pub
wg genpsk > maison.psk # clé partagée, facultative mais recommandée
cat server.pub
Le umask 077 garantit que les fichiers sont créés lisibles par root seulement, sans fenêtre pendant laquelle un autre utilisateur pourrait les lire. La clé partagée (preshared key) ajoute une couche de chiffrement symétrique par-dessus l’échange de clés : elle ne remplace rien, mais protège le trafic enregistré aujourd’hui contre un futur ordinateur quantique capable de casser Curve25519. Elle doit être identique des deux côtés et ne circuler que par un canal sûr.
Faites de même sur le routeur, et notez sa clé publique. Les clés privées n’apparaissent jamais dans un fichier versionné en clair : placez-les dans un coffre à secrets (Vault, OpenBao, Ansible Vault) si vous automatisez le déploiement.
Étape 3 : écrire /etc/wireguard/wg0.conf
[Interface]
Address = 10.99.0.3/24
ListenPort = 51820
PrivateKey = <clé privée du serveur>
MTU = 1420
SaveConfig = false
[Peer]
# routeur de la maison
PublicKey = <clé publique du routeur>
PresharedKey = <clé partagée>
AllowedIPs = 192.168.10.0/24, 10.99.0.0/24
PersistentKeepalive = 25
La section [Interface]
- Address : l’adresse du serveur dans le tunnel. Le masque
/24fait créer parwg-quickune route vers tout le réseau du tunnel, utile si d’autres serveurs rejoignent le même tunnel plus tard ; - ListenPort : le port UDP d’écoute. 51820 est la convention, rien n’oblige à l’utiliser ;
- PrivateKey : le contenu de
server.key. Une variante consiste à ne pas l’écrire dans le fichier et à la charger parPostUp = wg set %i private-key /etc/wireguard/server.key; - MTU = 1420 : la taille maximale des paquets dans le tunnel. WireGuard ajoute 60 octets d’en-tête en IPv4 (80 en IPv6) ; 1420 laisse la place sur un lien Ethernet classique à 1500. Si la box de la maison utilise PPPoE (MTU 1492), descendez à 1412, voire 1380 en cas de doute ;
- SaveConfig = false : empêche
wg-quickde réécrire le fichier à l’arrêt avec l’état courant, ce qui effacerait vos commentaires et pourrait y figer une modification faite à la main pour un test.
La section [Peer]
- PublicKey : l’identité du routeur ;
- PresharedKey : la clé partagée générée plus haut ;
- AllowedIPs : la directive la plus importante, et la plus mal comprise. Elle sert à la fois de table de routage (les paquets vers
192.168.10.0/24et10.99.0.0/24partent vers ce pair) et de filtre (un paquet reçu de ce pair dont la source n’est pas dans ces réseaux est jeté). On n’y met pas0.0.0.0/0: seul le trafic destiné à la maison passe par le tunnel, le reste du trafic du serveur sort normalement. C’est ce qu’on appelle un tunnel partagé (split tunnel) ; - pas d’Endpoint : le serveur ne sait pas où joindre la maison, dont l’adresse publique peut changer. C’est le routeur qui l’appelle ; le serveur apprend son adresse à la première poignée de main et la met à jour s’il change ;
- PersistentKeepalive = 25 : un petit paquet toutes les 25 secondes. Indispensable côté routeur, car la box oublie une traduction d’adresses UDP inactive au bout de 30 à 120 secondes et le serveur ne pourrait plus joindre la maison. Côté serveur, c’est sans inconvénient et cela garde le tunnel actif dans les deux sens.
Étape 4 : le côté maison
Le routeur déclare le serveur comme pair, avec cette fois un Endpoint : l’adresse publique du VPS. Ses AllowedIPs pour ce pair se limitent à l’adresse du serveur dans le tunnel. Exemple sur un MikroTik sous RouterOS 7 :
/interface wireguard add name=wg-servers listen-port=13231 private-key="<clé privée du routeur>"
/ip address add address=10.99.0.2/24 interface=wg-servers
/interface wireguard peers add interface=wg-servers \
public-key="<clé publique du serveur>" preshared-key="<clé partagée>" \
endpoint-address=203.0.113.25 endpoint-port=51820 \
allowed-address=10.99.0.3/32 persistent-keepalive=25s
Il faut aussi autoriser, dans le pare-feu du routeur, le trafic entre l’interface WireGuard et le réseau local (chaîne forward), et le placer avant les règles de blocage génériques. Une règle courante qui rejette les adresses privées (« bogons ») doit ne s’appliquer qu’à l’interface côté Internet : sinon elle rejette le réseau du tunnel lui-même.
Étape 5 : le pare-feu du serveur
firewall-cmd --permanent --add-port=51820/udp
# rattacher wg0 à une zone : 'trusted' pour tout autoriser depuis la maison,
# ou une zone dédiée qui n'ouvre que le nécessaire (SSH, exporteurs…)
firewall-cmd --permanent --new-zone=wireguard
firewall-cmd --permanent --zone=wireguard --add-interface=wg0
firewall-cmd --permanent --zone=wireguard --add-service=ssh
firewall-cmd --reload
Une zone dédiée est plus prudente que trusted : si une machine de la maison était compromise, elle ne verrait du serveur que les services que vous avez choisis. Le serveur n’a pas besoin de faire suivre des paquets entre réseaux (net.ipv4.ip_forward peut rester à 0) puisqu’il n’est qu’une extrémité.
Étape 6 : démarrer
systemctl enable --now wg-quick@wg0
wg-quick crée l’interface wg0, lui donne son adresse, charge la configuration WireGuard et ajoute les routes déduites d’AllowedIPs. Le service se relance au démarrage. Pour appliquer une modification du fichier sans couper le tunnel : wg syncconf wg0 <(wg-quick strip wg0).
Étape 7 : vérifier, dans l’ordre
wg show wg0
# peer: <clé publique du routeur>
# endpoint: 198.51.100.7:13231
# allowed ips: 192.168.10.0/24, 10.99.0.0/24
# latest handshake: 41 seconds ago
# transfer: 1.20 MiB received, 3.45 MiB sent
- latest handshake de moins de deux minutes : les clés et le port UDP sont bons ;
- endpoint renseigné : le serveur connaît l’adresse actuelle de la maison ;
- transfer qui augmente dans les deux sens : du trafic circule.
ip route get 192.168.10.20 # doit répondre « dev wg0 »
ping -c3 10.99.0.2 # le routeur dans le tunnel
ping -c3 192.168.10.20 # une machine de la maison
ssh admin@192.168.10.20 # une vraie connexion TCP
# depuis une machine de la maison, dans l'autre sens :
ssh root@10.99.0.3
Ne vous arrêtez pas au ping. Un pare-feu peut accepter l’ICMP tôt dans sa chaîne et rejeter les nouvelles connexions TCP plus loin : le ping passe, rien d’autre. Testez une vraie connexion, dans les deux sens.
Les pannes les plus fréquentes
Aucune poignée de main
Le port UDP est fermé (chez l’hébergeur ou dans firewalld), les clés publiques sont inversées, ou le routeur a une mauvaise adresse d’Endpoint. tcpdump -ni eth0 udp port 51820 sur le serveur montre si les paquets du routeur arrivent : s’ils arrivent sans réponse, c’est une clé ; s’ils n’arrivent pas, c’est le réseau.
Poignée de main, mais aucun trafic
Les AllowedIPs ne correspondent pas des deux côtés : le routeur envoie des paquets dont la source n’est pas dans la liste du serveur, qui les jette sans bruit. Ou la route de retour manque côté maison.
Le ping passe, le TCP non
Une règle de pare-feu traite l’ICMP à part. Le cas typique est une liste d’adresses « bogons » contenant 10.0.0.0/8 et appliquée à toutes les interfaces : elle rejette le réseau du tunnel dans la chaîne forward. Limitez-la à l’interface Internet.
Les petits échanges passent, les gros transferts se figent
Un problème de MTU. Les paquets pleins dépassent la taille permise quelque part sur le chemin et sont perdus. Testez avec ping -M do -s 1372 192.168.10.20 en augmentant la taille jusqu’à l’échec, puis baissez le MTU du tunnel en conséquence des deux côtés.
Tout marche, puis plus rien au bout d’un moment
Le PersistentKeepalive manque côté routeur, et la box a oublié la traduction d’adresses. Ou l’adresse publique de la maison a changé et le serveur ne l’a pas encore apprise : c’est au routeur de relancer la poignée de main, ce que le keepalive fait tout seul.
Les noms des machines de la maison ne se résolvent pas
Le tunnel transporte des adresses, pas des noms. Pour résoudre nas.maison.lan depuis le serveur, faites passer uniquement ce domaine par le serveur DNS de la maison, par exemple avec le greffon dnsmasq de NetworkManager, plutôt que de remplacer tout le DNS du serveur.
Entretenir le tunnel
- Changer de clés sans perdre l’accès : ajoutez d’abord la nouvelle clé publique du serveur comme second pair sur le routeur, basculez le serveur sur sa nouvelle clé, vérifiez la poignée de main, puis retirez l’ancien pair. Ne modifiez jamais les deux côtés à l’aveugle depuis l’extérieur ;
- Ajouter un second serveur : nouvelle adresse dans le tunnel (
10.99.0.4), nouveau pair sur le routeur avecallowed-address=10.99.0.4/32. Chaque adresse ne doit apparaître que dans un seul pair, sinon le routage devient imprévisible ; - Surveiller : l’âge de la dernière poignée de main est le meilleur indicateur. Au-delà de trois minutes, le tunnel est tombé. Un script qui lit
wg show wg0 latest-handshakeset publie la valeur pour Prometheus, ou une simple sonde depuis la maison, suffit ; - Modifier un routeur à distance : activez son mode sans échec (Safe Mode sur RouterOS) avant toute modification. Si la session est perdue, le routeur annule tout ce qui a été fait depuis.
Pour aller plus loin
Le même tunnel peut transporter la supervision (Prometheus qui interroge les exporteurs du serveur), les sauvegardes (rsync vers un compte enfermé dans un répertoire du NAS) et l’administration (SSH limité à l’interface du tunnel). Une fois le tunnel en place, beaucoup de ports qu’on aurait été tenté d’ouvrir sur Internet n’ont plus besoin de l’être.
Ce billet fait partie d’une série de tutoriels d’administration système (tag « pas à pas »).
Série « Pas à pas », tutoriel 5/57. · ← Tutoriel précédent · Tutoriel suivant → (à paraître le 1/11) · English version