Le problème : Vous devez publier « un seul service interne » pour quelques utilisateurs distants. L’équipe réseau dit « mettez-le derrière le VPN ». Quelqu’un d’autre dit « faites juste un transfert de port ». La suite, vous la connaissez : votre VPN devient la porte dérobée la plus coûteuse au monde — assez large pour les mouvements latéraux, les attaques par force brute et les fuites de données accidentelles.
Ce guide de terrain s’adresse aux personnes qui exploitent des systèmes réels : comment combiner l’accès VPN et le transfert de ports sans transformer votre réseau privé en un périmètre mou et perméable. Nous serons concrets sur le routage, le NAT, les pare-feu, l’identité, la journalisation et les modes de défaillance. Et nous le ferons avec des commandes que vous pouvez exécuter aujourd’hui.
Le modèle mental : le VPN est un réseau, pas une cape magique
Un VPN n’est pas de la « sécurité ». Un VPN est un ensemble de chemins réseau et de décisions de confiance. Lorsque vous accordez l’accès VPN à un appareil, vous lui donnez la possibilité d’envoyer des paquets dans votre environnement. Tout le reste, ce sont des détails : routage, chiffrement, authentification, filtrage, observabilité, et la vérité irréversible qu’un client compromis est maintenant « à l’intérieur » de ce que vous exposez.
Le transfert de port semble être un compromis propre : « On va transférer le port 443 depuis la passerelle VPN vers un service interne. Seuls les utilisateurs VPN peuvent y accéder. Fini. » Le problème est que le transfert n’est rarement le seul changement effectué. Les environnements s’accumulent : une route pratique ici, un trou de pare-feu « temporaire » là, un AllowedIPs sur WireGuard trop large parce que quelqu’un en avait marre de déboguer. Six mois plus tard, plus personne ne se souvient pourquoi la passerelle VPN peut atteindre la moitié des sous-réseaux privés.
Voici la ligne de base opinionnée :
- Préférez l’exposition au niveau applicatif plutôt qu’au niveau réseau. Un proxy inverse avec authentification vaut mieux qu’une simple connectivité L3 brute.
- Préférez des listes blanches explicites plutôt que la confiance implicite. « Sur le VPN » n’est pas une liste blanche.
- Préférez un rayon d’impact étroit plutôt que des astuces de transfert sophistiquées. Si vous ne pouvez pas expliquer le routage en deux minutes, vous ne pourrez pas l’exploiter à 3 h du matin.
VPN + transfert de ports peut être sûr. Mais seulement si vous le traitez comme si vous construisiez un mini réseau edge à l’intérieur de votre entreprise : moindre privilège, flux bien définis et frontières strictes.
Faits et contexte historique qui expliquent les erreurs courantes avec les VPN
Ce ne sont pas des anecdotes. Ils expliquent pourquoi les « correctifs VPN rapides » continuent d’introduire des risques en production.
- Les VPN ont popularisé la sécurité « coquille dure, centre mou ». Les premiers VPN d’entreprise supposaient un LAN interne de confiance ; une fois connecté, vous étiez essentiellement « à l’intérieur ». Ce modèle a mal vieilli.
- Le NAT est devenu la couverture de sécurité par défaut dans les années 2000.Le NAT n’a jamais été conçu comme un pare-feu, mais il a conditionné les opérateurs à assimiler « non routable publiquement » et « sûr ».
- IPsec a été conçu d’abord pour site-à-site.Beaucoup de déploiements IPsec supposent des réseaux stables et des sous-réseaux clairs ; forcer un accès client ad hoc mène à une prolifération de politiques désordonnées.
- OpenVPN a normalisé les « push routes » vers les clients.C’est pratique—et dangereusement simple de pousser un accès large (ou des réglages DNS) sans mesurer l’étendue.
- WireGuard évite délibérément les fonctions de « politique ».C’est rapide et simple, mais cela signifie que vous devez implémenter le contrôle d’accès dans les pare-feu et le routage, et non dans le protocole VPN.
- Le hairpin NAT existe parce que les vrais utilisateurs font des choses étranges.Les gens bookmarkent des noms publics et les réutilisent en interne ; si vous ne prévoyez pas le trafic hairpin, vous déboguerez des fantômes.
- Le transfert de ports est plus ancien que le cloud.C’est un bidouillage d’administrateur classique de l’époque des petits routeurs de bureau. Ça marche—jusqu’à ce que vous ayez besoin d’auditabilité et de segmentation.
- Zero Trust n’a pas tué les VPN ; il les a recontextualisés.Les meilleurs VPN modernes ressemblent à un transport contrôlé plus une politique consciente de l’identité, pas à un tunnel vers le royaume.
L’histoire laisse des habitudes. Votre travail est de briser celles qui transforment « accès distant » en « compromission distante ».
Modèles plus sûrs pour exposer des services via VPN
Modèle A : Proxy inverse sur le bord VPN (recommandé)
Placez un proxy inverse (nginx, HAProxy, Envoy, Caddy—choisissez) sur la passerelle VPN ou un hôte « edge VPN » dédié. Terminez TLS là. Exigez une authentification forte (mTLS, OIDC, SSO). Forwardez vers les services internes sur les réseaux privés. Le VPN fournit le transport ; le proxy fournit l’identité et la politique.
Pourquoi c’est bien :
- L’exposition du service se fait au niveau applicatif ; vous pouvez appliquer des règles par chemin/par hôte.
- Vous pouvez journaliser les requêtes, limiter le débit et bloquer les absurdités évidentes.
- Vous pouvez attacher l’accès à une seule destination interne au lieu d’ouvrir le routage vers un sous-réseau.
Modèle B : Transfert de port vers une seule IP:port interne, avec ancrage par pare-feu
Si vous devez transférer du TCP/UDP brut, faites-le de manière étroite. Verrouillez le port transféré sur une seule destination interne, puis verrouillez le pare-feu pour que seuls les IPs clients VPN (ou une liste d’autorisation plus petite) puissent atteindre ce port sur la passerelle.
C’est là que les opérateurs deviennent négligents : ils implémentent du DNAT mais oublient les règles de filtrage. DNAT sans filtrage est un système de « politique par accident ».
Modèle C : Utilisez un bastion / hôte de saut pour les protocoles d’administration
L’accès admin (SSH, RDP, consoles de base de données) doit passer par un hôte de saut, pas par des transferts de ports aléatoires. Un bon bastion vous apporte :
- Authentification par utilisateur et journaux de session.
- Un point d’étranglement unique pour le durcissement et la surveillance.
- Un endroit pour appliquer la MFA sans réinventer la roue.
Modèle D : Tunnel fractionné avec routes explicites, pas « tout via le VPN »
Les VPN en tunnel complet sont corrects quand vous les gérez bien, mais ils élargissent le rayon d’impact quand ce n’est pas le cas. Le tunnel fractionné avec routage explicite vers ce dont les utilisateurs ont besoin réduit le risque et la charge de support (moins de tickets « le VPN a tué mon Zoom »).
Modèle E : N’exposez pas du tout le service — répliquez-le
Pour certaines charges, l’exposition la plus sûre est l’absence d’exposition. Répliquez des données en lecture seule vers un service DMZ, ou publiez via une API dédiée qui applique l’autorisation. C’est l’architecture « ennuyeuse » qui évite les transferts astucieux.
Vérification réaliste : si votre plan dépend de « personne ne scannera ce port parce qu’il est sur le VPN », vous avez construit un système de sécurité basé sur l’espoir et des colsons.
Modèle de menace : comment VPN + transfert de ports tourne mal
1) Mouvement latéral depuis un client compromis
Le client VPN est généralement l’environnement le moins contrôlé que vous possédiez : ordinateurs personnels, appareils mobiles, machines de sous-traitants. Si l’un est compromis et dispose d’une large visibilité via le VPN, un attaquant obtient la capacité de scanner l’interne, dérober des identifiants et pivoter. Le transfert de ports peut amplifier cela en rendant les services internes plus faciles à atteindre via une passerelle unique connue.
2) Règles « temporaires » qui deviennent permanentes
Les règles de transfert et les exceptions de pare-feu ont une demi-vie plus longue que votre patience. Si vous n’avez ni automatisation ni revue, les exceptions vivent indéfiniment. Et elles s’accumulent.
3) Décalage d’authentification : accès réseau vs accès applicatif
Un VPN authentifie un appareil ou un utilisateur au réseau. Votre application authentifie des utilisateurs (ou ne le fait pas). Si vous exposez un service qui suppose « LAN = confiance », vous avez téléporté cette supposition sur chaque client VPN.
4) Confusion DNS et surprises liées à l’hébergement virtuel basé sur le nom
Les utilisateurs atteignent le service par un nom public ; votre transfert ou proxy inverse dépend de SNI/Host headers ; quelqu’un teste par IP ; soudain ça marche pour certains clients et pas pour d’autres. La conception DNS compte ici plus que vous ne le souhaitez.
5) MTU et bugs de fragmentation qui n’apparaissent qu’en production
L’encapsulation VPN réduit la MTU effective. Certains chemins bloquent l’ICMP « Fragmentation Needed », et alors les handshakes TLS se bloquent mystérieusement. Le trafic transféré hérite de ces problèmes.
6) Routes mal délimitées (AllowedIPs, push routes, ou routes statiques)
C’est le classique. Vous vouliez autoriser l’accès à 10.20.30.40:443. Quelqu’un pousse 10.20.0.0/16 « pour la commodité ». Votre VPN vient de devenir un réseau d’entreprise fantôme.
Blague #1 : Le NAT, c’est comme le film bulle : ça vous donne l’impression d’être en sécurité, mais si vous sautez du toit vous aurez quand même une mauvaise journée.
Principe opérationnel : traitez la passerelle VPN comme un edge internet
Même si seuls des « utilisateurs de confiance » se connectent, exploitez la passerelle VPN comme si elle était exposée à du trafic adversaire :
- Système durci, paquets minimaux installés.
- Pare-feu strict avec défaut deny.
- Journaux structurés envoyés hors hôte.
- Limitation de débit quand c’est possible.
- Configuration gérée comme du code ; changements revus.
Tâches pratiques avec commandes : vérifier, restreindre, forwarder, observer
Ces tâches sont écrites pour des passerelles VPN basées sur Linux. Les commandes supposent que vous avez root ou sudo. Pour chacune : ce que vous exécutez, ce que signifie la sortie, et quelle décision prendre.
Tâche 1 : Confirmer l’état du forwarding IP (parce que « forwarding » n’est pas un ressenti)
cr0x@server:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
Sens : le kernel ne transférera pas les paquets IPv4 entre interfaces. Les règles DNAT peuvent encore réécrire, mais le routage ne permettra pas au trafic de passer comme attendu.
Décision : Si c’est une passerelle VPN censée router/forwarder, mettez-le à 1 et persistez le réglage. Si elle n’est pas censée router, laissez à 0 et reconsidérez votre conception.
Tâche 2 : Vérifier la MTU effective de l’interface VPN (tueur silencieux pour TLS)
cr0x@server:~$ ip link show dev wg0
5: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/none
Sens : WireGuard met souvent 1420 en MTU par défaut ; votre réseau sous-jacent peut nécessiter moins. Si vous voyez MTU 1500 et que vous tunnelisez sur PPPoE/LTE, attendez-vous à des problèmes.
Décision : Si vous avez des accrochages intermittents, testez avec une MTU plus petite (par exemple 1380) et vérifiez avec le sondage PMTU (Tâche 11).
Tâche 3 : Vérifier quelles routes la passerelle utilisera pour atteindre le service interne
cr0x@server:~$ ip route get 10.20.30.40
10.20.30.40 via 10.20.0.1 dev eth1 src 10.20.0.10 uid 0
cache
Sens : la passerelle enverra le trafic vers 10.20.30.40 via 10.20.0.1 sur eth1 en utilisant la source 10.20.0.10.
Décision : Si la route pointe vers la mauvaise interface, corrigez le routage avant de toucher au NAT. Les règles DNAT ne peuvent pas sauver un mauvais routage.
Tâche 4 : Confirmer que le service écoute réellement sur l’hôte interne
cr0x@server:~$ ss -lntp | head
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=911,fd=3))
LISTEN 0 512 10.20.30.40:443 0.0.0.0:* users:(("nginx",pid=1220,fd=6))
Sens : nginx écoute sur 10.20.30.40:443. Parfait. S’il n’écoutait que sur 127.0.0.1, le transfert vers lui échouerait à moins que vous ne forwardiez aussi sur cet hôte.
Décision : Si l’écoute n’est pas à l’adresse attendue, corrigez l’adresse de bind du service avant de déboguer le réseau.
Tâche 5 : Valider la politique par défaut du pare-feu (si tout est ACCEPT, vous jouez à pile ou face)
cr0x@server:~$ sudo iptables -S | head -n 12
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N VPN_IN
-N VPN_FWD
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i wg0 -j VPN_IN
-A FORWARD -i wg0 -j VPN_FWD
Sens : deny par défaut pour INPUT et FORWARD, avec chaînes dédiées pour le VPN. C’est la posture souhaitable sur une passerelle.
Décision : Si INPUT/FORWARD sont ACCEPT par défaut, planifiez une migration contrôlée vers default deny. Commencez par ajouter des autorisations explicites, puis basculez les politiques pendant une fenêtre de maintenance.
Tâche 6 : Créer un DNAT de port étroit (IP VPN:8443 → interne 10.20.30.40:443)
cr0x@server:~$ sudo iptables -t nat -A PREROUTING -i wg0 -p tcp --dport 8443 -j DNAT --to-destination 10.20.30.40:443
cr0x@server:~$ sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp -d 10.20.30.40 --dport 443 -j MASQUERADE
cr0x@server:~$ sudo iptables -A FORWARD -i wg0 -o eth1 -p tcp -d 10.20.30.40 --dport 443 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
cr0x@server:~$ sudo iptables -A FORWARD -i eth1 -o wg0 -p tcp -s 10.20.30.40 --sport 443 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Sens : PREROUTING change la destination pour le trafic arrivant via le VPN. POSTROUTING fait du masquerading pour que l’hôte interne réponde via la passerelle même s’il ne connaît pas les sous-réseaux clients VPN.
Décision : Préférez le routage sans masquerade quand c’est possible (plus propre, préserve l’IP client), mais si vous ne pouvez pas ajouter de routes sur l’hôte/le réseau interne, MASQUERADE est pragmatique. Documentez-le : ça impacte la journalisation et les traces d’audit.
Tâche 7 : Restreindre qui peut utiliser le transfert (liste d’autorisation du sous-réseau client VPN ou IPs spécifiques)
cr0x@server:~$ sudo iptables -I FORWARD 1 -i wg0 -p tcp -s 10.66.0.0/24 -d 10.20.30.40 --dport 443 -j ACCEPT
cr0x@server:~$ sudo iptables -I FORWARD 2 -i wg0 -p tcp -d 10.20.30.40 --dport 443 -j DROP
Sens : seuls les clients de 10.66.0.0/24 peuvent atteindre le service interne ; les autres sont bloqués même si le DNAT se produit.
Décision : Resserrez davantage quand vous le pouvez : IPs clients individuelles, pas des sous-réseaux entiers. Si vous avez besoin de « certains utilisateurs oui, certains non », cessez de compter uniquement sur des politiques basées sur IP et ajoutez une authentification applicative.
Tâche 8 : Confirmer que les compteurs NAT et filter s’incrémentent (prouver que le trafic atteint vos règles)
cr0x@server:~$ sudo iptables -t nat -L PREROUTING -n -v | head
Chain PREROUTING (policy ACCEPT 120 packets, 9200 bytes)
pkts bytes target prot opt in out source destination
12 720 DNAT tcp -- wg0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8443 to:10.20.30.40:443
Sens : les compteurs pkts/bytes indiquent si votre règle est utilisée. Zéro au compteur signifie que votre trafic n’arrive pas sur wg0, n’est pas TCP, ou ne correspond pas au dport 8443.
Décision : Si les compteurs restent à zéro pendant un test, arrêtez de deviner et tracez le chemin : sélection d’interface, routage côté client, et si le client est réellement sur le VPN.
Tâche 9 : Vérifier les AllowedIPs du peer WireGuard (le bug classique d’accès trop large)
cr0x@server:~$ sudo wg show wg0
interface: wg0
public key: 8qGk...redacted
listening port: 51820
peer: 7n9H...redacted
endpoint: 203.0.113.50:53122
allowed ips: 10.66.0.10/32
latest handshake: 1 minute, 2 seconds ago
transfer: 188.22 KiB received, 412.91 KiB sent
Sens : ce pair est autorisé à émettre seulement depuis 10.66.0.10/32. Bien. Si vous voyez « 0.0.0.0/0 » ou un grand sous-réseau privé, vous avez accordé bien plus de reachabilité que vous ne le pensez.
Décision : Gardez AllowedIPs serrés côté serveur. Utilisez quand même des règles pare-feu. Traitez AllowedIPs comme une première barrière, pas comme la seule barrière.
Tâche 10 : Capturer des paquets pour prouver où ils meurent (tcpdump : le sérum de vérité)
cr0x@server:~$ sudo tcpdump -ni wg0 tcp port 8443 -c 5
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wg0, link-type RAW (Raw IP), snapshot length 262144 bytes
12:04:11.112233 IP 10.66.0.10.51512 > 10.66.0.1.8443: Flags [S], seq 39192812, win 64240, options [mss 1360,sackOK,TS val 9911 ecr 0,nop,wscale 7], length 0
12:04:12.113244 IP 10.66.0.10.51512 > 10.66.0.1.8443: Flags [S], seq 39192812, win 64240, options [mss 1360,sackOK,TS val 10911 ecr 0,nop,wscale 7], length 0
Sens : les paquets SYN atteignent la passerelle. Si vous ne voyez pas de SYN-ACK en retour, la passerelle ne forwarde pas correctement, l’hôte interne n’est pas joignable, ou le trafic de retour est cassé.
Décision : Lancez une seconde capture sur eth1 : tcpdump -ni eth1 host 10.20.30.40 and tcp port 443. Si vous voyez des SYN sur wg0 mais rien sur eth1, le NAT/filtre/routage sur la passerelle est en cause.
Tâche 11 : Tester le PMTU depuis la perspective d’un client VPN
cr0x@server:~$ ping -M do -s 1372 -c 3 10.66.0.1
PING 10.66.0.1 (10.66.0.1) 1372(1400) bytes of data.
1380 bytes from 10.66.0.1: icmp_seq=1 ttl=64 time=32.1 ms
1380 bytes from 10.66.0.1: icmp_seq=2 ttl=64 time=31.8 ms
1380 bytes from 10.66.0.1: icmp_seq=3 ttl=64 time=32.5 ms
--- 10.66.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
Sens : le chemin supporte au moins des paquets de 1400 octets sans fragmentation. Si cela échoue, réduisez la MTU sur wg0 et/ou corrigez le blocage ICMP en amont.
Décision : Si vous déboguez « certains HTTPS fonctionnent, gros uploads échouent », la MTU est un suspect principal. Réparez cela avant d’accuser TLS.
Tâche 12 : Vérifier le filtrage du chemin inverse (rp_filter) lors du routage entre interfaces
cr0x@server:~$ sysctl net.ipv4.conf.all.rp_filter
net.ipv4.conf.all.rp_filter = 1
Sens : rp_filter strict peut dropper des paquets quand un routage asymétrique se produit (commun avec VPN et interfaces multiples).
Décision : Sur une passerelle VPN effectuant forwarding/NAT, réglez rp_filter à 0 ou 2 (laxiste) selon votre conception. Faites-le délibérément ; documentez pourquoi.
Tâche 13 : Confirmer la pression sur la table conntrack (le forwarding meurt sous charge)
cr0x@server:~$ sudo conntrack -S
cpu=0 found=1287 invalid=4 ignore=0 insert=4218 insert_failed=0 drop=0 early_drop=0 error=0 search_restart=0
Sens : insert_failed et drop indiquent une exhaustion ou pression sur conntrack. Même une « petite » passerelle VPN peut tomber en panne quand tout le monde se reconnecte après des pertes Wi‑Fi.
Décision : Si les drops augmentent, augmentez les limites conntrack, réduisez les règles à état quand c’est sûr, ou scalez les passerelles. Et arrêtez d’utiliser la passerelle VPN comme une box NAT tout usage.
Tâche 14 : Confirmer qui est connecté et à quel point récemment (parce que des clients fantômes existent)
cr0x@server:~$ sudo wg show wg0 latest-handshakes
7n9H...redacted 1735292801
j2Qa...redacted 0
Sens : un handshake « 0 » signifie que le pair ne s’est jamais connecté depuis que l’interface est up (ou que les clés ont été tournées). Les timestamps epoch peuvent être convertis en temps humain.
Décision : Si des utilisateurs affirment « le VPN est connecté » mais que vous ne voyez pas de handshake, vous déboguez le client, la traversée NAT ou un mismatch de clés — pas le transfert de port.
Tâche 15 : Valider la journalisation du trafic refusé (si vous ne voyez pas les drops, vous ne pouvez pas l’exploiter)
cr0x@server:~$ sudo iptables -A FORWARD -i wg0 -j LOG --log-prefix "VPN-FWD-DROP " --log-level 4
cr0x@server:~$ sudo iptables -A FORWARD -i wg0 -j DROP
cr0x@server:~$ sudo journalctl -k -n 3
Dec 27 12:08:01 vpn-gw kernel: VPN-FWD-DROP IN=wg0 OUT=eth1 SRC=10.66.0.50 DST=10.20.30.40 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=51422 DF PROTO=TCP SPT=51580 DPT=443 WINDOW=64240 RES=0x00 SYN URGP=0
Sens : le log kernel montre ce qui a été drop : qui (SRC), quoi (DST/DPT), et où il a essayé d’aller (interface OUT).
Décision : Si vous activez la journalisation, limitez-la en taux. Sinon un hôte bruyant transformera vos logs en déni de portefeuille.
Tâche 16 : Test rapide « est-ce que ça marche » depuis un client VPN : curl avec SNI/Host conservés
cr0x@server:~$ curl -vk https://10.66.0.1:8443/health
* Trying 10.66.0.1:8443...
* Connected to 10.66.0.1 (10.66.0.1) port 8443
> GET /health HTTP/1.1
> Host: 10.66.0.1:8443
> User-Agent: curl/7.81.0
> Accept: */*
< HTTP/1.1 200 OK
< Content-Type: text/plain
ok
Sens : la connexion TCP a réussi et vous avez reçu un HTTP 200. Si vous obtenez des alertes TLS, vous atteignez peut-être le mauvais hôte virtuel ou il y a un mismatch de nom de certificat.
Décision : Pour les services basés sur le nom, testez avec le vrai hostname via --resolve et SNI approprié, ou utilisez un proxy inverse qui termine TLS de manière cohérente.
Blague #2 : Le transfert de ports, c’est comme « juste une exception de plus » en finance — tout le monde s’accorde que c’est minime jusqu’à ce qu’on les additionne.
Trois mini-histoires d’entreprise issues du terrain
Mini-histoire 1 : L’incident causé par une mauvaise hypothèse (« les utilisateurs VPN sont de confiance »)
Une entreprise de taille moyenne exploitait un VPN pour employés distants et sous-traitants. Le profil VPN était partagé via un portail interne ; l’authentification était « suffisamment forte » et l’équipe réseau considérait les clients VPN comme équivalents au site. Lorsqu’un nouveau portail d’administration interne devait être accessible à distance, ils l’ont transféré depuis la passerelle VPN vers le serveur d’app. Aucune authentification supplémentaire. « C’est interne. »
Des mois plus tard, l’ordinateur portable d’un sous-traitant a été compromis via une extension de navigateur qui n’avait rien à faire sur une machine de travail. L’attaquant n’a pas eu besoin d’un zero-day contre le VPN. Ils ont simplement attendu que le sous-traitant se connecte, puis ont scanné l’espace d’adresses accessible via le client VPN. Le portail admin transféré était trivial à trouver : port ouvert, chemin prévisible, et il faisait confiance aux en-têtes « LAN ».
L’attaquant a utilisé le portail pour créer un compte avec des permissions élevées, puis a pivoté vers d’autres systèmes en utilisant des identifiants mis en cache que le portail pouvait atteindre. La faille n’était pas « le VPN ». La faille était l’hypothèse que la localisation réseau implique l’identité.
La correction n’a pas été héroïque. Ils ont ajouté une authentification applicative, exigé la MFA pour les fonctions admin, resserré les AllowedIPs du VPN et remplacé l’accès large « sous-traitant » par un accès par service via un proxy inverse. Le changement le plus efficace a été culturel : tout ce qui était joignable depuis le VPN a été traité comme s’il était exposé à Internet, avec logs et limitation de débit.
Mini-histoire 2 : L’optimisation qui s’est retournée contre eux (MASQUERADE partout)
Une autre organisation voulait éviter de toucher au routage interne. L’équipe VPN a décidé de MASQUERADE tout le trafic des clients VPN en entrant dans le réseau interne. Ça a marché immédiatement : aucun changement sur les routeurs internes, aucun changement sur les serveurs legacy, et les tickets helpdesk ont chuté.
Puis la sécurité a demandé un audit : « Quel utilisateur a accédé à l’app finance mardi dernier ? » Les logs de l’app ne montraient que l’IP de la passerelle VPN. Tous les utilisateurs étaient identiques. L’équipe a essayé de compenser en augmentant la journalisation sur la passerelle, mais maintenant ils avaient deux problèmes : des logs immenses et toujours pas assez de contexte au niveau applicatif.
Un autre échec est apparu silencieusement : des limites de débit sur certains services internes ont été déclenchées inopinément. Du point de vue du service, tout le trafic venait d’un seul hôte. Le service a commencé à brider la passerelle, et soudain « le VPN est lent » est devenu une plainte quotidienne. Ils avaient optimisé pour éviter des changements de routage — et s’étaient optimisés dans un problème d’observabilité et d’équité.
Le rollback a été partiel. Ils ont conservé MASQUERADE uniquement pour le sous-réseau legacy incapable de recevoir des routes. Pour le reste, ils ont ajouté des routes afin que les services internes voient les vraies IPs clients. Le proxy inverse devant les apps sensibles a aussi injecté l’identité utilisateur authentifiée dans des en-têtes (avec validation stricte) pour que les audits redeviennent sensés.
Mini-histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise (default deny + revue des changements)
Une entreprise réputée pour être « lente » avait une habitude qui paraissait agaçante jusqu’au jour où elle n’a pas été : chaque changement au pare-feu de la passerelle VPN était fait via un dépôt, revu par des pairs et déployé par automatisation. Leur pare-feu de passerelle était en default deny. Leurs transferts de ports étaient explicites, et chacun avait une référence de ticket dans un commentaire.
Un après-midi, un développeur a demandé un transfert rapide pour qu’un fournisseur atteigne un webhook de staging. Un opérateur pressé a ouvert une règle — sur le mauvais port — et a poussé. La pipeline de déploiement l’a attrapé parce que les tests unitaires pour la politique du pare-feu vérifiaient que seuls des ports de destination approuvés existaient pour cette classe de service. Le changement a été rejeté avant d’arriver en production.
L’opérateur a corrigé la règle et a réessayé. Cette fois, ça a passé et a été déployé, et le fournisseur a obtenu l’accès. Deux semaines plus tard, un scanner automatisé du côté du fournisseur a mal fonctionné et a frappé l’endpoint de manière agressive. Les métriques de la passerelle ont montré le pic ; les limites par défaut du proxy inverse l’ont absorbé ; et les logs du pare-feu ont rendu évident quel service transféré faisait du bruit.
Pas d’héroïsme. Pas de cellule de crise. Juste un contrôle de changement discipliné, default deny et instrumentation. L’équipe « lente » a livré plus vite parce qu’elle ne passait pas sa vie à corriger des erreurs évitables.
Citation fiabilité (idée paraphrasée) : John Allspaw a souligné que les incidents proviennent d’interactions systèmes, pas d’« erreur humaine », et que l’apprentissage vaut mieux que le blâme.
Playbook de diagnostic rapide
Voici le flux « ne perdez pas une heure ». L’objectif est de trouver le goulet d’étranglement — routage, pare-feu, NAT, service ou MTU — en le moins d’étapes possible.
Première étape : prouver que le client est réellement sur le VPN et cible la bonne chose
- Sur la passerelle : vérifiez le handshake (
wg show wg0) et les paquets récents sur wg0 (tcpdump -ni wg0). - Sur le client : confirmez la route vers l’adresse/port de transfert VPN (côté client
ip route get). - S’il n’y a pas de handshake ou pas de paquets : ce n’est pas un problème de transfert de port. C’est la configuration client, les clés, ou la traversée NAT.
Deuxième étape : vérifier que le point de décision de forwarding (DNAT + filter) est atteint
- Vérifiez les compteurs NAT :
iptables -t nat -L PREROUTING -n -v. - Vérifiez les compteurs/logs FORWARD :
iptables -L FORWARD -n -vet les logs kernel pour les drops. - Si les compteurs ne bougent pas : mauvaise interface, mauvais port, mauvais protocole, ou le trafic n’arrive pas.
Troisième étape : vérifier le chemin de retour (l’échec le plus courant « ça marche à moitié »)
- Capturez sur l’interface interne : le trafic quitte-t-il la passerelle vers le service ?
- Capturez sur le retour : les réponses reviennent-elles ?
- Si les réponses ne reviennent pas : route de retour manquante vers le sous-réseau client VPN, rp_filter qui droppe, ou problème d’état conntrack.
Quatrième étape : vérifier la MTU si les symptômes sont « connexion OK, transferts bloqués »
- Exécutez des tests PMTU (Tâche 11).
- Cherchez les blocages de handshake TLS, les hangs sur gros envois, ou des comportements incohérents selon les réseaux.
Cinquième étape : vérifier la capacité et les tables d’état
- Les drops de conntrack, la saturation CPU, ou la mise en file d’attente sur la passerelle peuvent imiter des « problèmes réseau ».
- Commencez par :
conntrack -S,top, et les compteurs d’erreur d’interface (ip -s link).
Erreurs courantes (symptôme → cause racine → correctif)
1) « Ça marche pour moi sur le Wi‑Fi, échoue sur mobile »
Symptôme : certains clients se connectent, d’autres bloquent sur TLS ou gros transferts.
Cause racine : MTU trop élevée pour certains chemins ; ICMP fragmentation needed bloqué ; overhead d’encapsulation VPN pousse les paquets au‑delà de la limite.
Correctif : réduisez la MTU de l’interface VPN (WireGuard : définir MTU=1380), assurez-vous que l’ICMP est autorisé, validez avec des pings PMTU et des transferts réels.
2) « Le port est ouvert sur la passerelle mais le service est injoignable »
Symptôme : SYN arrive sur l’interface VPN ; pas de réponse ; les compteurs NAT s’incrémentent mais le service interne ne voit jamais le trafic.
Cause racine : la chaîne FORWARD droppe le trafic ; règle manquante pour les connexions NEW ; mauvaise interface dans la règle pare-feu ; ou IP forwarding désactivé.
Correctif : activez net.ipv4.ip_forward=1, ajoutez un allow FORWARD explicite avec conntrack state, et validez avec compteurs et tcpdump sur les deux interfaces.
3) « Ça forwarde, mais le service interne logue seulement l’IP de la passerelle »
Symptôme : les traces applicatives montrent une seule IP client (la passerelle).
Cause racine : MASQUERADE/SNAT masque l’IP client pour éviter d’ajouter des routes.
Correctif : ajoutez des routes appropriées pour que le service puisse répondre aux sous‑réseaux clients VPN sans SNAT, ou terminez au niveau du proxy inverse qui peut transmettre l’identité authentifiée (et la consigner).
4) « Le forwarding fonctionne un temps, puis meurt sous charge »
Symptôme : drops intermittents, nouvelles connexions échouent, connexions existantes ralentissent.
Cause racine : exhaustion de la table conntrack ou CPU saturé sur la passerelle ; trop de règles à état ; journalisation agressive.
Correctif : dimensionnez les limites conntrack, réduisez la journalisation ou limitez-la en taux, scalez la passerelle, et évitez de transformer la passerelle VPN en appliance NAT multi-usages.
5) « L’utilisateur peut atteindre bien plus que prévu »
Symptôme : un client VPN peut scanner des sous‑réseaux internes ou atteindre des services non liés.
Cause racine : AllowedIPs/push routes trop larges ; règles FORWARD permissives ; politiques par défaut ACCEPT.
Correctif : resserrez les AllowedIPs, implémentez default deny sur FORWARD, ajoutez des règles allow par destination, et testez depuis le client avec des scans explicites de ce qui devrait être bloqué.
6) « Le DNS par nom fonctionne en interne mais pas via le VPN (ou vice versa) »
Symptôme : par IP ça marche ; par nom ça échoue ; ou seuls certains utilisateurs résolvent la bonne adresse.
Cause racine : DNS fractionné non configuré ; le client utilise un DNS public ; le service requiert SNI/Host header ; hairpin NAT non géré.
Correctif : fournissez un DNS via le VPN, utilisez des noms cohérents, et préférez la terminaison par proxy inverse où le comportement TLS/SNI est déterministe.
Listes de contrôle / plan pas à pas
Plan pas à pas : exposer un service HTTPS interne aux utilisateurs VPN en toute sécurité
- Décidez du modèle d’exposition. Si c’est HTTP(S) côté utilisateur, utilisez un proxy inverse à l’edge VPN. Si c’est un protocole brut, envisagez un bastion plutôt qu’un transfert de port.
- Définissez l’audience minimale. Utilisateurs spécifiques, appareils, ou un petit sous‑réseau client VPN. Écrivez‑le avant de toucher à iptables.
- Définissez la destination minimale. Une seule IP:port interne, pas un sous‑réseau.
- Verrouillez la posture de la passerelle. Default deny sur INPUT et FORWARD. Allow established/related. Autorisez seulement le port VPN inbound depuis l’interface exposée à Internet.
- Implémentez le forwarding avec des règles de filtrage explicites. Le DNAT seul n’est pas une politique. Ajoutez des règles FORWARD qui correspondent exactement à ce que vous voulez.
- Décidez SNAT vs retour routé. Préférez le retour routé (préserver l’IP client). Utilisez SNAT seulement si nécessaire, et enregistrez les implications d’audit.
- Appliquez l’authentification applicative. Si votre app suppose « LAN = confiance », corrigez l’app ou placez‑la derrière quelque chose qui applique l’identité.
- Instrumentez les points d’étranglement. Compteurs pare‑feu, logs kernel de drops (limités en taux), métriques de handshake VPN, et logs de requêtes sur le proxy.
- Testez les modes de panne. Depuis un client VPN : testez l’accès autorisé, l’accès bloqué, et les destinations « ne doivent pas router ».
- Opérationnalisez le changement. Mettez les configs pare‑feu/VPN en contrôle de version, exigez une revue, et assurez‑vous qu’un rollback est documenté.
Checklist sécurité : « ne transformez pas le VPN en trou »
- AllowedIPs/push routes sont minimaux par peer.
- Politique FORWARD en DROP ; allows explicites existent pour chaque service exposé.
- Pas de forwarding du VPN vers « tout le réseau interne » sauf justification et segmentation.
- Protocoles admin passent par bastion ; pas de forwards RDP/SSH aléatoires.
- Journalisation pour : connexions VPN, drops pare‑feu, et accès aux services exposés.
- Limites de débit sur les endpoints exposés (préférer proxy).
- Rotation des clés et révocation des identifiants pratiquées, pas théoriques.
Checklist fiabilité : garder le débogage possible
- Un schéma montrant interfaces, sous‑réseaux et sens de flux.
- Un endroit unique pour vérifier « l’utilisateur est-il connecté » (handshake).
- Points de capture packet identifiés (interface wg, interface interne).
- Décisions MTU documentées.
- Contrôle de changement : qui a modifié quoi, quand et pourquoi.
FAQ
1) Mettre un service « derrière le VPN » est‑il automatiquement sûr ?
Non. Cela change l’audience de « l’internet » à « toute personne pouvant s’authentifier au VPN (ou compromettre un client VPN) ». Vous avez toujours besoin d’authentification applicative, de segmentation et de journalisation.
2) Dois‑je utiliser le transfert de ports ou un proxy inverse ?
Proxy inverse pour HTTP(S) presque à chaque fois. Le transfert de ports est acceptable pour des protocoles restreints et bien compris, mais il est plus difficile à authentifier et à observer proprement.
3) Quelle est la plus grande erreur avec l’exposition WireGuard ?
AllowedIPs trop larges et la supposition qu’il remplace la politique de pare‑feu. WireGuard est volontairement minimal ; vous devez appliquer l’accès via le routage et les règles pare‑feu.
4) Puis‑je éviter SNAT/MASQUERADE et toujours faire fonctionner le forwarding ?
Oui, si le service interne (ou sa gateway par défaut) a une route de retour vers le sous‑réseau client VPN via la passerelle VPN. C’est la conception propre. SNAT est le raccourci avec des compromis d’audit.
5) Comment empêcher les sous‑traitants de scanner tout le réseau une fois sur le VPN ?
Donnez‑leur un accès par service : AllowedIPs serrés, default deny sur FORWARD, et règles allow explicites uniquement pour les services dont ils ont besoin. Pour les apps web, placez‑les derrière un proxy inverse authentifié.
6) Tunnel fractionné vs tunnel complet : que choisir ?
Le tunnel fractionné réduit le rayon d’impact et les douleurs de support, mais exige une bonne hygiène de routage. Le tunnel complet centralise le contrôle d’e sortie mais augmente la dépendance au VPN et rend les pannes plus bruyantes. Choisissez selon votre modèle de menace et votre maturité opérationnelle.
7) Pourquoi « SYN atteint la passerelle » ne garantit‑il pas que le service est joignable ?
Parce que le DNAT peut se produire mais la chaîne FORWARD peut dropper, le forwarding IP peut être désactivé, la passerelle peut mal router, ou le trafic de retour peut ne pas savoir comment revenir.
8) Comment rendre cela auditable ?
Préférez des conceptions routées afin que les services internes voient les vraies IPs clients. Utilisez un proxy inverse qui logge l’identité utilisateur authentifiée. Centralisez les logs hors de la passerelle. Ne comptez pas sur les logs NAT comme seul trace d’audit.
9) Ai‑je besoin de hairpin NAT ?
Seulement si les clients VPN utilisent un nom public qui résout vers une IP publique qui boucle via la même passerelle. Si vous contrôlez le DNS, le split DNS est généralement plus propre que les hacks hairpin NAT.
10) Quelle est la bonne façon de déployer des changements sans casser tout le monde ?
Mettez les règles en staging avec compteurs et journalisation d’abord, testez avec un peer pilote, puis étendez. Utilisez la config comme code et un plan de rollback. La passerelle n’est pas l’endroit pour des « déploiements cowboy ».
Conclusion : prochaines étapes que vous pouvez livrer
VPN plus transfert de ports n’est pas intrinsèquement imprudent. Il devient imprudent lorsque vous laissez « sur le VPN » remplacer une vraie politique, ou lorsque vous traitez le transfert comme une case à cocher de routeur au lieu d’un service edge en production.
Faites ceci ensuite :
- Choisissez un modèle d’exposition par service : proxy inverse pour HTTP(S), bastion pour l’administration, transfert étroit uniquement si nécessaire.
- Resserrez la reachabilité : AllowedIPs minimaux, FORWARD en default deny, règles explicites par destination.
- Décidez volontairement SNAT vs retour routé, et documentez les implications d’audit.
- Ajoutez de la visibilité : compteurs, logs de drops (limités en taux), monitoring des handshakes, et logs de requêtes.
- Pratiquez le playbook de diagnostic rapide une fois quand vous n’êtes pas en train d’éteindre un incendie.
Si vous ne pouvez pas expliquer qui peut atteindre quoi, via quelle interface, et pourquoi le trafic de retour revient correctement — continuez à travailler. Ce n’est pas du perfectionnisme. C’est exploiter un réseau sans transformer votre VPN en générateur d’incidents.