Accès distant : sortir le VPN du pare-feu, d'OpenVPN à WireGuard
L'ancien VPN, hébergé sur le pare-feu, se dégradait au-delà de trois connexions : je l'ai remplacé par WireGuard et Firezone sur une machine virtuelle dédiée, sans couper l'ancien service pendant la bascule.
En bref
OpenVPN tournait sur le pare-feu : au-delà de trois connexions simultanées, sessions coupées et mémoire saturée, alors que six personnes en avaient besoin.
J'ai déplacé l'accès distant sur une VM Debian dédiée, avec WireGuard et le portail Firezone, en gardant OpenVPN en secours pendant la bascule.
Un accès se crée en 2 min au lieu de 15 et se révoque en un clic ; le pare-feu ne fait plus que rediriger un port. Test extérieur : 55 ms, 0 % de perte.
Contexte
Six utilisateurs se connectaient à distance pour atteindre les partages du NAS, le bureau à distance et les applications métier. Le serveur OpenVPN tournait sur le pare-feu pfSense lui-même. Au-delà de trois connexions simultanées, les sessions tombaient et la mémoire du pare-feu saturait. Chaque coupure devenait un ticket.
La cause tenait à l'architecture : OpenVPN chiffre en espace utilisateur, sur la machine qui assure déjà le filtrage et le NAT de toute l'entreprise. Ce projet prolonge mes premiers déploiements d'accès distant, faits poste par poste (ci-dessous).
Avant : FortiClient, puis Splashtop
Mon premier accès distant date de 2024, sur l'ancien pare-feu FortiGate. Mon travail se situait côté postes : FortiClient installé depuis un partage interne, en mode « VPN seulement », avec deux profils, VPN SSL et IPsec en secours. Je les ai testés câble débranché, depuis le partage 4G d'un téléphone, puis j'ai écrit une procédure illustrée pour équiper les postes suivants.


Le VPN passait mes tests mais décevait à l'usage dans notre contexte : connexions qui tombaient, client délicat à paramétrer, demandes de support régulières. L'entreprise a adopté Splashtop, un accès poste à poste avec double authentification, où l'ordinateur distant n'entre plus dans le réseau. J'en ai retenu qu'on ne juge pas un service depuis son propre poste, et qu'on mesure avant de conclure : je n'avais gardé aucun chiffre avant et après.
Après le remplacement du FortiGate par pfSense, fin 2024, le VPN est revenu sous la forme d'un serveur OpenVPN sur le nouveau pare-feu. C'est lui que ce projet remplace.
Ce que j'ai fait
- Choisir WireGuard, et Firezone pour le gérerWireGuard tourne dans le noyau Linux, en quelques milliers de lignes de code, avec des paires de clés au lieu de certificats. Firezone y ajoute ce qui manque : liste d'utilisateurs, dernières connexions, révocation en un clic.
- Monter une VM minimaleDebian 13 sans interface graphique (2 vCPU, 2 Go de RAM), Firezone en trois conteneurs Docker : l'application, sa base PostgreSQL et Caddy pour le HTTPS. Le portail n'est joignable que depuis le réseau interne, télémétrie désactivée.
- Lire avant d'exécuterLe script d'installation officiel exigeait « v2 » dans la version de Docker Compose, alors que la version installée, plus récente, est compatible. J'ai assoupli ce test, sans toucher au reste du script.
- Adapter les profils clientsSeul le trafic vers le réseau local passe dans le tunnel (split tunnel), les noms internes sont résolus par les contrôleurs de domaine, et le point de terminaison est l'adresse publique de l'entreprise.
- Basculer sans coupureJ'ajoute l'utilisateur et son appareil dans le portail ; il installe le client officiel, importe le fichier et clique sur « Activer ». OpenVPN reste disponible en secours jusqu'à la fin de la bascule.
Voir les détails techniques
| Critère | OpenVPN (existant) | WireGuard (cible) |
|---|---|---|
| Exécution | Espace utilisateur | Module du noyau Linux |
| Authentification | Certificats X.509 | Paires de clés publique et privée |
| Taille du code | Plusieurs centaines de milliers de lignes | Quelques milliers de lignes |
| Hébergement | Sur le pare-feu | VM dédiée sur Hyper-V |
Bash · installation de Firezone
# Le script d'installation est téléchargé, lu, puis seulement exécuté
curl -fsSL <URL du script officiel> -o install.sh
# Il exigeait « v2 » dans la version de Docker Compose (la version installée est plus récente)
sed -i 's/$dc version | grep -q "v2"/$dc version | grep -qE "v[2-9]"/' install.sh
bash install.sh
| Paramètre client | Valeur par défaut | Valeur appliquée | Pourquoi |
|---|---|---|---|
| Adresses autorisées (AllowedIPs) | 0.0.0.0/0, ::/0 | Réseau local de l'entreprise | Split tunnel : la navigation Internet reste sur la connexion de l'utilisateur |
| Serveurs DNS | 1.1.1.1, 1.0.0.1 | Contrôleurs de domaine | Résoudre les noms internes |
| Point de terminaison | Adresse privée de la VM | Adresse publique de l'entreprise | Sans cela, les fichiers générés pointent vers une adresse injoignable depuis Internet |
La VM résout les noms, mais apt n'atteint aucun dépôt. Après le passage en adresse fixe, ip route show montrait une passerelle par défaut pointant vers un contrôleur de domaine : il répondait au DNS, mais rien ne sortait. Passerelle corrigée vers le switch cœur, /etc/resolv.conf rempli, IPv6 désactivé sur un réseau uniquement en IPv4.
Le portail répond « 502 Bad Gateway ». Firezone démarrait avant que PostgreSQL accepte les connexions : le fichier docker-compose ne conditionnait pas l'un à l'autre. Démarrage en séquence, la base d'abord.
Bash · démarrage séquencé
docker compose down
docker compose up -d postgres && sleep 15 && docker compose up -d firezone caddy
docker compose ps && docker logs firezone-firezone-1 --tail 10
Créer et révoquer un accès. Firezone génère la paire de clés, attribue une adresse dans le réseau du tunnel et produit un QR code pour les mobiles ou un fichier .conf pour les postes. Supprimer l'appareil ou désactiver l'utilisateur coupe le tunnel immédiatement. Avec l'ancien service, chaque accès demandait un certificat généré dans pfSense, l'export et l'envoi manuel d'une archive, et des droits d'administration sur le pare-feu de production.

L'incident
Depuis l'extérieur, aucune connexion n'aboutit
La redirection de port et la règle du pare-feu étaient correctes, mais une capture de paquets sur l'interface WAN ne montrait aucune trame entrante.
L'adresse publique est portée par l'équipement de l'opérateur, qui ne livre au pare-feu qu'une adresse privée : le trafic traverse deux NAT. J'ai ajouté une redirection chez l'opérateur, vers le WAN du pare-feu, qui redirige ensuite vers la VM.
Résultats
Test de bout en bout depuis l'extérieur, sur une connexion résidentielle : tunnel établi en quelques secondes, ping d'un contrôleur de domaine à 55 ms sans perte, lecteur du NAS monté avec les identifiants du domaine, session de bureau à distance ouverte sur un serveur interne, droits NTFS appliqués normalement.

Une limite existait déjà avec OpenVPN : les noms courts ne se résolvaient pas, le client Windows ne gérant pas le suffixe de recherche DNS ; il fallait utiliser les noms complets.
Un premier utilisateur était migré et se connectait sans intervention ; les autres suivaient, OpenVPN en secours. La tenue à six connexions simultanées et la mémoire du pare-feu n'ont donc pas été mesurées. Ce VPN a ensuite servi à ouvrir un accès encadré au prestataire du portail B2B en DMZ.
Ce que j'améliorerais
- Sur un prochain VPN, je prévoirais dès le départ une authentification à deux facteurs et des droits par utilisateur : le champ AllowedIPs règle le routage, il ne contrôle pas l'accès. Le filtrage se fait côté serveur, par utilisateur ou par groupe.
- Faire générer la paire de clés sur le poste de l'utilisateur, pour que la clé privée ne le quitte jamais et qu'aucun fichier de configuration complet n'ait à circuler.
- Appliquer la même règle à toutes les installations, Docker compris : télécharger, lire, puis exécuter, ou passer par le dépôt APT signé de l'éditeur plutôt que par
curl … | sh.