Pourquoi ce projet existe
Dans un futur pas si lointain, je prévois de voyager dans un pays où l’accès à internet peut devenir... orienté. Les outils sur lesquels je compte normalement (outils de travail, services Google, même des applications basiques) peuvent soudainement devenir lents, peu fiables, voire carrément bloqués.
Au début, j’ai fait comme tout le monde : essayer quelques applications VPN populaires en espérant que ça marche. Et oui… ça marchait parfois. D’autres fois, c’était ralenti, ça coupait aléatoirement, ou c’était comme jouer à la roulette avec « est-ce que ça va se connecter aujourd’hui ? »
Ce projet a donc commencé avec un objectif très pratique : je voulais quelque chose de fiable, sous mon contrôle, et facile à reconstruire si (quand) c’est ciblé ou que ça casse (parce que ça finit toujours par casser). Mais je voulais aussi que ce soit une pièce de portfolio propre, quelque chose qui montre que je peux livrer un système de bout en bout avec une automatisation correcte, de bonnes pratiques de sécurité, et de la documentation, pas juste un script qui « marche sur mon laptop ».
En bref : il ne s’agissait pas d’inventer un nouveau VPN. Il s’agissait de construire une configuration solide et reproductible que je peux posséder, comprendre et faire évoluer.
Architecture en un coup d’œil
Toute la stack est dans le code :
(Diagramme d’architecture ici.)
Reality check : le problème de la poule et de l’œuf
Avant que Terraform puisse « tout gérer », certaines choses doivent exister d’abord. On ne peut pas utiliser l’automatisation pour créer l’automatisation.
J’amorce donc quelques pièces manuellement, puis je les importe dans l’état Terraform (peut-être un peu trop pour être honnête 😅, mais parfois je privilégie la vitesse et l’itération plutôt qu’un one-shot parfait, et tout finit terraformé en fin de journée) :
Confession : j’ai fait plus de « clic d’abord, import ensuite » que ce que je recommanderais dans un monde parfait. Quand on debug l’IAM, la Console est plus rapide que des cycles plan/apply sans fin. Une fois que ça marche, c’est importé et ça redevient ennuyeux.
Intentions d’infrastructure
Mon objectif était de garder le pipeline ennuyeux-dans-le-bon-sens : privilèges minimaux, passages de relais propres, et zéro fuite de secrets dans les logs.
Plutôt qu’une seule identité CI ultra-puissante, chaque étape du pipeline a son propre compte de service :
| Trigger | Compte de Service | Périmètre |
|---|---|---|
| ci-lint | cb-ci-lint | Scans de sécurité uniquement |
| im-preview | cb-im-preview | Plans Terraform |
| im-apply | cb-im-apply | Application des changements |
| fleet-reconcile | cb-fleet-reconcile | Déploiement sur VPS |
Quelques choix de sécurité dont je suis assez fier :
Chaque PR passe par des vérifications automatisées : formatage/validation Terraform, linting, scanners de sécurité, linting de scripts shell et détection de secrets. Si une vérification échoue, la PR n’est pas mergée.
Choix de protocole & VPS
J’ai écarté WireGuard et IKEv2 parce que leurs handshakes sont plus faciles à détecter pour le DPI.
Reality adopte une approche différente : il n’encapsule pas le trafic VPN dans du TLS de manière suspecte. Il usurpe une vraie session TLS :
Un détail pratique : les shortIds. Chaque VPS a ses propres shortIds, et j’en garde 2 à 3 par serveur pour pouvoir faire tourner les clients si l’un est repéré, sans toucher à la config serveur.
Si vous devinez mon IP serveur sans un shortId valide, vous atterrissez simplement sur le site leurre. Le VPN ne se révèle jamais.
Le choix du fournisseur compte aussi. Avant de louer quoi que ce soit, je teste l’accessibilité depuis le pays de destination (j’ai utilisé des vérifications looking-glass via globalping) car la réputation et le routage peuvent faire toute la différence.

Configuration côté client
Une fois que Terraform applique et que le fleet reconciler s’exécute, chaque VPS écrit l’URL de connexion client sur le disque. Je me connecte en SSH et la récupère :
Puis je la colle dans mes clients :
Mon test de vérification est simple : connecter le client, puis vérifier l’IP de sortie :

Voir une IP de Singapour dans le navigateur pendant que le client Happ est actif est mon test de vérification que le trafic passe bien par le VPS.
Plus important encore, le flux est invisible. Le handshake TLS ressemble à Chrome communiquant avec un site légitime, donc le DPI a peu de raisons de l’examiner. Si j’ai besoin de faire tourner le shortId ou de regénérer des clés, le pipeline fait le gros du travail : mes clients n’ont qu’à coller un nouveau lien VLESS.
Monitoring & logging (pour ne pas naviguer à l’aveugle)
Je voulais suffisamment d’observabilité pour débugger les problèmes, sans construire accidentellement un système de surveillance pour moi-même.
Le coût estimé de logging est pratiquement nul (moins de ~0,10 €/mois).
Lire le détail technique
Si vous voulez voir le layout Terraform, les triggers Cloud Build, l’inventaire de la flotte et les templates/scripts Xray, tout est documenté dans le repo, incluant les étapes de bootstrap pour que je puisse ré-importer les ressources proprement la prochaine fois que j’en ai besoin.
github.com/scottsantinho/vless-reality-gcp
