Monter un VPN WireGuard pour ses accès distants
Serveur, pairs, clés, routage et poste mobile : comment monter un accès distant WireGuard qui tient la route, et ce qu'il faut comprendre avant de coller une configuration trouvée sur Internet.
On monte un VPN WireGuard pour deux raisons quand on gère l’informatique d’une PME : avoir un accès distant qui ne dépende pas du contrat de support d’un pare-feu, et un tunnel qui se rétablit tout seul quand le portable passe du wifi de la maison à la 4G du train.
Il fait les deux, avec une configuration qui tient sur un écran. C’est aussi son piège : comme c’est court, on la copie d’un tutoriel sans comprendre quelle ligne fait quoi, et on obtient un tunnel qui monte mais ne route rien — ou pire, qui capture tout le trafic d’un poste en télétravail sans que personne l’ait décidé.
Prérequis
Section intitulée « Prérequis »- Une machine Linux joignable depuis Internet. Un petit gabarit suffit : WireGuard vit dans le noyau.
- Un port UDP ouvert en entrée, en général
51820/udp. Pas de repli TCP, WireGuard n’existe qu’en UDP. - Un nom DNS public, par exemple
vpn.example.com. Jamais une adresse IP en dur dans les profils : le jour où l’opérateur la change, vous redistribuez trente fichiers. - Un plan d’adressage libre pour le tunnel, sans conflit avec aucun réseau utilisateur. C’est le point
qu’on oublie : si vous prenez
192.168.1.0/24, tous ceux dont la box est en192.168.1.xseront hors jeu. - Aucun autre client VPN déjà installé sur les postes concernés : deux piles VPN, c’est deux tables de routage qui se disputent la passerelle par défaut.
Comprendre le modèle avant de configurer
Section intitulée « Comprendre le modèle avant de configurer »WireGuard n’a ni serveur ni client au sens strict : il n’y a que des pairs, chacun connaissant la clé publique des autres. Ce qu’on appelle le serveur est le pair qui a une adresse fixe et n’initie jamais la connexion.
| Notion | Ce que c’est | L’erreur classique |
|---|---|---|
| Couple de clés | Une clé privée qui ne quitte jamais la machine, une clé publique qu’on distribue | Générer les clés du poste sur le serveur, puis les envoyer par mail |
AllowedIPs |
Les réseaux joignables par ce pair — à la fois une route et un filtre | Mettre 0.0.0.0/0 partout « parce que ça marche » |
Endpoint |
Où joindre le pair distant. Renseigné côté client, appris côté serveur | Une IP publique en dur au lieu d’un nom DNS |
Retenez surtout AllowedIPs. Côté client, c’est ce qui part dans le tunnel ; côté serveur, ce qui est
autorisé à en sortir pour ce pair. La même directive fait table de routage et contrôle d’accès : élégant, et
déroutant la première fois.
Générer les clés proprement
Section intitulée « Générer les clés proprement »Une clé privée se génère sur la machine qui l’utilisera et n’en bouge pas.
umask 077wg genkey | tee serveur.key | wg pubkey > serveur.pubwg genkey | tee poste-01.key | wg pubkey > poste-01.pubwg genpsk > poste-01.psk # clé pré-partagée, optionnelleConfigurer le serveur
Section intitulée « Configurer le serveur »La configuration native tient dans un fichier. Sachez l’écrire même si vous passez ensuite par une interface graphique : le jour où ça ne marche pas, c’est ce fichier que vous lirez.
[Interface]Address = 10.66.66.1/24ListenPort = 51820PrivateKey = <clé privée du serveur># Masque le tunnel derrière l'adresse du serveur ; PostDown fait l'inverse avec -DPostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
[Peer]# Poste portable 01PublicKey = <clé publique du poste 01>PresharedKey = <clé pré-partagée du poste 01>AllowedIPs = 10.66.66.2/32Un pair, un bloc [Peer], une adresse en /32. Verbeux et voulu : vous savez qui a le droit d’entrer, et
vous révoquez en supprimant cinq lignes. Le routage IP doit ensuite être activé, sinon le tunnel monte et
s’arrête là :
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-wireguard.confsudo sysctl --systemsudo systemctl enable --now wg-quick@wg0sudo wg showwg show est votre tableau de bord : pairs, adresse source, volumes, date du dernier échange (latest handshake). Un pair sans échange récent n’est pas connecté, quoi qu’affiche l’icône sur le poste.
Passer par une interface d’administration en conteneur
Section intitulée « Passer par une interface d’administration en conteneur »À la dixième demande du mois, éditer le fichier à la main lasse. Une interface web comme wg-easy, en
conteneur, génère les pairs et sort un QR code prêt à scanner. Le wg0.conf continue d’exister derrière.
services: wg-easy: image: ghcr.io/wg-easy/wg-easy environment: - WG_HOST=vpn.example.com - WG_DEFAULT_DNS=192.0.2.10,192.0.2.11 - PASSWORD_HASH=<empreinte bcrypt du mot de passe d'administration> - WG_PORT=51820 - PORT=51821 volumes: - ./wireguard:/etc/wireguard ports: - "51820:51820/udp" restart: unless-stopped cap_add: - NET_ADMIN - SYS_MODULE sysctls: - net.ipv4.ip_forward=1 - net.ipv4.conf.all.src_valid_mark=1Le mot de passe n’est pas stocké en clair : l’interface attend une empreinte bcrypt, produite localement
avec le module bcrypt de Python. Dans un fichier Compose, les $ de l’empreinte doivent être doublés ($$),
sinon Compose les prend pour des variables et le mot de passe ne fonctionne jamais.
Le port de l’interface web n’est pas publié : seul 51820/udp l’est, et un reverse proxy publie
l’administration en HTTPS.
server { server_name vpn.example.com; location / { proxy_pass http://wg-easy:51821/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; }}Les en-têtes Upgrade et Connection ne sont pas décoratifs : sans eux, les statistiques temps réel restent
figées, parce qu’elles passent par un WebSocket. Et si vous pouvez réserver cette console au réseau interne,
faites-le : une administration de VPN publiée sur Internet est une cible.
Décider du routage : tunnel complet ou partiel
Section intitulée « Décider du routage : tunnel complet ou partiel »La vraie décision de conception, à prendre avant de distribuer le premier profil. Tunnel partiel
(AllowedIPs = 10.0.0.0/8) : seuls les réseaux internes passent par le VPN, c’est rapide et économe sur le
lien du site. Tunnel complet (AllowedIPs = 0.0.0.0/0) : tout passe par le VPN, Internet compris —
nécessaire si le filtrage de l’entreprise doit s’appliquer en télétravail, à condition que le lien encaisse.
Le DNS suit la même logique : sur un tunnel partiel, la plage des résolveurs internes doit figurer dans
AllowedIPs, sinon le poste interroge un serveur qu’il ne sait pas joindre.
[Interface]Address = 10.66.66.2/32PrivateKey = <clé privée du poste>DNS = 192.0.2.10, 192.0.2.11
[Peer]PublicKey = <clé publique du serveur>PresharedKey = <clé pré-partagée>Endpoint = vpn.example.com:51820AllowedIPs = 10.0.0.0/8, 10.66.66.0/24PersistentKeepalive = 25PersistentKeepalive = 25 maintient ouverte la traduction d’adresses du routeur d’en face. Sans lui, un poste
derrière une box devient injoignable depuis le site après quelques minutes.
Le cas du poste mobile
Section intitulée « Le cas du poste mobile »Le pair le plus simple à déclarer, et le plus difficile à faire adopter.
Distribuez un QR code, pas un fichier. L’application mobile importe un profil en le scannant à l’écran : cinq secondes, aucune pièce jointe à retrouver, aucune clé qui traîne dans la galerie photo.
Un profil par appareil, jamais partagé, nommé d’après l’appareil (« portable atelier 2 »). Le même couple de clés sur deux appareils provoque des déconnexions permanentes : le serveur ne mémorise qu’un point de terminaison par pair.
Prévoyez le DNS. C’est le premier point de friction : le tunnel affiche « connecté » mais l’intranet ne
s’ouvre pas, parce que le système a gardé le résolveur de l’opérateur. Poussez les résolveurs internes et
testez avec un nom, pas avec un ping d’adresse IP.
Rendez la connexion accessible en un geste : raccourci d’écran d’accueil ou activation à la demande. Si l’utilisateur doit ouvrir une application et basculer un interrupteur, il ne le fera pas — il vous appellera.
Vérifier que ça marche vraiment
Section intitulée « Vérifier que ça marche vraiment »- Le handshake, avec
sudo wg show. Pas delatest handshakerécent ? Le problème est en amont : port UDP fermé, redirection absente sur le routeur, ou nom DNS qui pointe ailleurs. - Le ping dans le tunnel. S’il passe mais que rien d’autre ne passe, regardez
AllowedIPset le routage du site. - Le retour. Les équipements internes doivent savoir revenir vers la plage du tunnel : route statique,
ou masquage derrière l’adresse du serveur comme dans le
PostUpplus haut. - Un nom, pas une adresse. Le dernier test se fait sur un nom interne : c’est lui qui attrape les problèmes de DNS.
Dernier point : WireGuard authentifie des clés, pas des utilisateurs. Ni annuaire, ni second facteur, ni
expiration. Un poste volé garde l’accès jusqu’à la suppression de son [Peer] : tenez la liste des pairs et
de leurs propriétaires, et mettez la révocation dans votre procédure de départ.