Aller au contenu
TAAF-OPS --:-- UTC

TP3 — Interconnexion : deux archipels, un tunnel

Conception d'architecture Ingénieurs · ESIROI IPsec site-à-site · fiche d'interconnexion · épreuve du destroy · bonus console · ~6 h

Depuis le TP0, une note traînait en fin d’axe C : les autres archipels existent. Aujourd’hui ils ont un visage : un autre groupe, avec sa base, son plan d’adressage, son AD, son Nextcloud. Votre mission commune : relier vos deux bases par un tunnel chiffré, à travers un réseau qui n’appartient à aucune des deux.

C’est le format réel d’une interconnexion entre deux organisations : personne ne « configure le VPN » tout seul — deux équipes négocient un document, puis chacune configure son côté, et le tunnel ne monte que si les deux configurations se répondent exactement. Le désaccord de paramètres est le mode d’échec normal de l’exercice — c’est pour ça qu’on négocie par écrit d’abord.

Qui fait quoi au TP3. Le tunnel est l’affaire du Membre A, mais chacun a sa part de preuves à produire :

MembreCe qu’il fait au TP3Ce qu’il apporte au rapport
A, réseauBranche l’adaptateur transit, négocie la fiche avec le A d’en face, monte le tunnel IPsec, écrit les règles sur l’interface IPsec et sur le transitFiche remplie, Status Overview, tcpdump ESP, règle « seuls IKE et ESP »
B, frontSi le service partagé est Nextcloud : l’ouvre au voisin (ligne de matrice, compte), ou le consomme chez lui ; débranche pour la preuve inverseCapture du service consommé à travers le tunnel, capture lien coupé
C, identité et donnéesVérifie que l’AD et PostgreSQL restent hors d’atteinte du voisin ; rejoue la procédure AD et le vagrant up de TAAF-DB-001 à l’épreuve du destroyBalayage du voisin vers z-services qui tombe, check-vm.sh de la DB reconstruite
D, SOCSi le service partagé est la remontée croisée : reçoit les refus du voisin dans Loki ; sinon requête les refus liés au tunnelRequête LogQL montrant le trafic du voisin, balayage « le reste tombe »

Tous : chacun détruit et reconstruit sa VM à l’épreuve finale (§6), et vérifie que le balayage avant/après est identique.


D’abord les deux pare-feu se mettent d’accord sur comment se parler, ensuite sur quel trafic protéger.

sequenceDiagram
  participant A as OPNsense — base G3
  participant B as OPNsense — base G7
  Note over A,B: Phase 1 (IKE_SA) — ouvrir un canal de négociation sécurisé
  A->>B: Propositions (IKEv2, AES-256, SHA-256, DH 14) + authentification PSK
  B->>A: Accord + échange Diffie-Hellman
  Note over A,B: secret partagé calculé, jamais transmis
  Note over A,B: Phase 2 (CHILD_SA) — quel trafic passe dans le tunnel
  A->>B: sélecteurs : 10.3.0.0/16 ⟷ 10.7.0.0/16 (ESP)
  B->>A: Accord — sélecteurs en miroir
  Note over A,B: Tunnel établi — le trafic circule chiffré (ESP)

Un tunnel qui ne monte pas, c’est presque toujours un désaccord : propositions différentes (« no proposal chosen »), sélecteurs qui ne sont pas en miroir, ou réseaux qui se chevauchent. Les trois se préviennent sur la fiche, pas dans les logs.


La 4ᵉ carte entre en jeu : em3 (opt4), pontée sur la seconde carte physique du poste du Membre A, VM éteinte. Le premier RJ45 du poste porte déjà le trunk des zones : le transit passe par un adaptateur USB vers RJ45, à demander à l’enseignant. Selon la salle : les deux adaptateurs des deux postes A sur des ports access d’un VLAN transit dédié du switch managé (jamais un VLAN de zone), ou un câble RJ45 direct entre les deux adaptateurs, avec un adressage statique convenu à deux.

Ajoutez la carte (VBoxManage modifyvm, puis comptez les adaptateurs, le dépassement est silencieux) ou recréez la VM câblée d’un bloc avec create-opnsense-vm.sh --trunk <carte> --transit. Attention, --force détruit le disque : exportez d’abord votre config.xml. Vous avez le réflexe depuis le TP1, c’est lui qu’on teste.

Assignez, adressez, et traitez cette patte comme le réseau le plus hostile de votre architecture : vous ne le maîtrisez pas, il n’a droit à rien par défaut. Seuls les deux protocoles du tunnel y entrent, et seulement depuis votre pair.

Indice : ce qui doit entrer sur le transit

IKE négocie sur UDP, ESP n’est pas du TCP ni de l’UDP mais un protocole IP à part entière ; s’il y a un NAT sur le chemin, tout bascule sur un second port UDP. Trois lignes de règles, pas une de plus, avec votre pair comme seule source.

Preuve E9 : le ping du pare-feu d’en face répond sur le transit. Le lien existe ; il n’est pas encore digne de confiance.


La fiche d’interconnexion, la pièce centrale du chapitre

Section intitulée « La fiche d’interconnexion, la pièce centrale du chapitre »

Remplissez-la à deux, avant toute configuration (gabarit : fiche-interconnexion-ipsec.csv) : identités des pairs, adresses de transit, propositions Phase 1 (IKEv2, AES-256, SHA-256, DH 14, non négociables ici), sélecteurs Phase 2 en miroir et groupe PFS identique, mode d’échange de la PSK. Trois correspondances obligatoires : propositions identiques, sélecteurs en miroir exact, réseaux disjoints.

Puis chacun configure son OPNsense, fiche en main : chaque champ de votre configuration doit correspondre à la ligne d’en face. Le tunnel ne monte que si les deux côtés se répondent exactement ; le désaccord est le mode d’échec normal, et les journaux d’OPNsense vous diront à quelle phase.

Indice : où ça se configure

Dans OPNsense, la configuration IPsec moderne se fait par connexions : une connexion porte les pairs, les propositions et l’authentification ; elle contient un ou plusieurs enfants qui portent les sélecteurs. La PSK se déclare à part, indexée par l’identité des pairs. Une connexion peut démarrer d’elle-même ou attendre le premier paquet : ce choix change la réponse à la question « le tunnel remonte-t-il seul ».

Preuve E10 : VPN ▸ IPsec ▸ Status Overview : Phase 1 ESTABLISHED, Phase 2 INSTALLED des deux côtés ; et la preuve que ça chiffre : un tcpdump sur le transit pendant un ping inter-bases montre de l’ESP, pas vos ICMP en clair.


5. Palier E11 : le tunnel n’est pas un boulevard

Section intitulée « 5. Palier E11 : le tunnel n’est pas un boulevard »

Un tunnel monté autorise… rien, tant que vos matrices ne le disent pas. Décidez à deux ce que vos bases s’offrent mutuellement : un service, pas tout. Un document partagé, une surveillance croisée, une copie de sauvegarde ; c’est à vous de choisir, et de le justifier comme au TP0.

Déclarez ce flux dans les deux matrices (source, destination, port, justification, comme toujours), et vérifiez l’inverse : tout le reste de l’autre base doit tomber en filtered à travers le tunnel. Votre AD, en particulier, n’a rien à offrir au voisin.

Indice : où vivent les règles du tunnel

Le trafic qui sort d’un tunnel arrive sur une interface à part, celle d’IPsec, qui a son propre onglet de règles et le même default-deny que les autres. Rien n’y passe tant que vous ne l’avez pas écrit ; une règle trop large y ouvre tout le sélecteur.

Preuve E11 : le service choisi répond à travers le tunnel ; un flux non déclaré (leur z-services, votre Grafana…) tombe. Puis la preuve inverse : coupez le lien (débranchez, ou désactivez le tunnel) : le service de l’autre base devient injoignable, et vos deux SI continuent de fonctionner localement. Une base australe survit à la coupure : c’était le cahier des charges du TP0, le voilà prouvé.


6. Palier E12 — L’épreuve du destroy : la fin du module

Section intitulée « 6. Palier E12 — L’épreuve du destroy : la fin du module »

Votre base tient. Reste à prouver qu’elle survivrait à celui qui l’a montée — une panne en hiver austral, six mois sans technicien, un hivernant qui réinstalle depuis votre dépôt :

Fenêtre de terminal
# 1. La référence — le balayage bash de l'E4 (TP1), rejoué ici
DB=10.G.10.30
for p in 22 389 5432; do
timeout 2 bash -c "</dev/tcp/$DB/$p" 2>/dev/null \
&& echo "$p ouvert" || echo "$p bloqué"
done
# 2. Détruire et rebâtir depuis le dépôt
vagrant destroy -f
vagrant up # votre Vagrantfile + provisioning
# OPNsense : réimport du config.xml (Restore), réinjection des secrets
# 3. Sur CHAQUE VM reconstruite : l'état est-il bon ?
../check-vm.sh
# 4. La preuve : le même balayage repasse, à l'identique

Si le second balayage rend le même résultat, port par port — et que check-vm.sh passe sur chaque VM — sans une retouche manuelle non documentée, votre infrastructure est reproductible, et c’est une propriété de sécurité : la configuration exacte, celle que vous avez pensée et prouvée, revient à l’identique après sinistre. Si vous devez « juste retoucher un truc à la main », ce truc-là est précisément ce qui manque dans votre dépôt.

(L’AD Windows se réinstalle à la main — comme OPNsense : c’est votre procédure versionnée qui le rend reconstructible, pas un script. La reproductibilité a plusieurs formes : du code quand c’est possible, une procédure testée quand c’est le prix du composant.)

Preuve E12 : les deux balayages bash, avant/après, identiques port par port ; check-vm.sh au vert sur chaque VM reconstruite ; et un dépôt sans aucun secret (git grep -iE "password|psk|secret" ne rend rien de sensible ; un secret commité est un critère éliminatoire).


7. Le rapport : chapitre TP3, le dernier du module

Section intitulée « 7. Le rapport : chapitre TP3, le dernier du module »

Le chapitre TP3 de votre rapport de réalisation clôt le document. Le TP se fait à deux groupes, mais chaque groupe rend son rapport : la fiche est commune, tout le reste vient de votre côté du tunnel, vos SA, vos SPI, vos logs, vos captures sur votre OPNsense. Les preuves à coller, chacune légendée, hostname et date lisibles :

  1. La fiche d’interconnexion remplie : telle que négociée à deux, PSK masquée, avec la date de la négociation (antérieure à vos captures de configuration).
  2. Le transit vérifié : le ping du pare-feu d’en face sur le transit, et la règle qui n’y laisse entrer qu’IKE et ESP.
  3. Le tunnel monté, de votre côté : VPN ▸ IPsec ▸ Status Overview : Phase 1 ESTABLISHED, Phase 2 INSTALLED, avec vos SPI entrants/sortants visibles.
  4. Le chiffrement prouvé : votre tcpdump sur le transit pendant un ping inter-bases : de l’ESP, pas d’ICMP.
  5. Le service consommé à travers : capture depuis votre base d’un service de la base voisine (ou l’inverse, selon ce que vous avez négocié) ; et le balayage montrant que le reste tombe.
  6. La preuve inverse : lien coupé : le service distant injoignable, un service local qui répond toujours.
  7. Les deux matrices amendées : la vôtre, et la ligne correspondante du voisin.
  8. L’épreuve du destroy : vos balayages avant/après reconstruction côte à côte, check-vm.sh au vert sur chaque VM reconstruite, et la sortie de git grep -iE "password|psk|secret" sur votre dépôt, commentée : aucune valeur sensible (les balises <password> hachées du config.xml et les noms de variables de .env.example sont normaux).

De la plus facile à la plus difficile. Chaque réponse cite une valeur relevée dans vos captures, celles de votre côté du tunnel. Barème : le rapport.

● Facile : relever, nommer, constater

  1. Q1 : Relevez sur votre Status Overview les états de Phase 1 et Phase 2, les adresses de transit des deux pairs, et votre sélecteur local.
  2. Q2 : Recopiez trois lignes de votre tcpdump sur le transit pendant un ping inter-bases : quel protocole apparaît, et pourquoi pas l’ICMP ?
  3. Q3 : Quel service offrez-vous au groupe voisin, lequel consommez-vous chez lui ? Donnez la ligne de matrice correspondante des deux côtés.

●● Moyen : expliquer, justifier, relier

  1. Q4 : Expliquez les deux phases IKE avec les paramètres de votre fiche : ce que la Phase 1 protège, ce que la Phase 2 décide, et laquelle des deux échoue quand les sélecteurs ne sont pas en miroir.
  2. Q5 : Pourquoi « Block private networks » doit-elle être décochée sur le transit, et pourquoi cette case est-elle utile sur un vrai WAN ? Quelle règle avez-vous écrite à la place pour que seuls IKE et ESP entrent ?
  3. Q6 : Pourquoi une PSK et pas vos CA ? Décrivez le problème d’amorçage, puis ce que vous feriez pour passer aux certificats une fois le tunnel monté, et ce qui change à l’expiration d’un certificat en hiver austral.
  4. Q7 : Lien coupé : décrivez ce que vous avez observé côté service distant et côté services locaux, captures à l’appui. À la reconnexion, le tunnel remonte-t-il seul ? Qu’est-ce qui se resynchronise, dans quel ordre ?

●●● Difficile : arbitrer, prouver, généraliser

  1. Q8 : « Le tunnel n’est pas un boulevard » : montrez avec votre balayage à travers le tunnel qu’un flux non déclaré tombe. Puis supposez la base voisine compromise : jusqu’où l’attaquant va-t-il chez vous, et quelle ligne de votre matrice l’arrête ? Votre annuaire est-il hors d’atteinte, prouvez-le.
  2. Q9 : L’épreuve du destroy : commentez vos balayages avant/après reconstruction. Qu’avez-vous dû retoucher à la main ? Pour chaque retouche, dites comment vous l’avez fait rentrer dans le dépôt, ou pourquoi c’est impossible (AD Windows, secrets) et ce qui, alors, rend la base reconstructible.
  3. Q10 : Votre base et sa voisine sont deux archipels. Demain, une troisième base, puis le siège. Avec votre plan d’adressage et votre fiche, dites ce qui passe à l’échelle tel quel, ce qui ne passe pas (PSK par binôme, sélecteurs, DNS, confiance), et l’architecture que vous proposeriez, en la justifiant contre le coût d’exploitation d’une base isolée six mois.
CritèreCe qu’on vérifie
La négociation a précédé la configurationLa fiche est remplie, cohérente, antérieure aux configs ; les trois correspondances tiennent.
Le transit est traité en hostileSeuls IKE/ESP y entrent ; « Block private networks » décoché en connaissance de cause.
Le tunnel est monté et chiffréSA établies des deux côtés, ESP au tcpdump.
Le tunnel n’est pas un boulevardLe service déclaré passe, tout le reste tombe — dans les deux sens.
La dépendance est prouvéeLien coupé : le service distant tombe, les deux bases vivent localement.
L’épreuve du destroy passeBalayage bash identique avant/après reconstruction, check-vm.sh au vert sur chaque VM, dépôt sans secrets.

Hors barème des dix questions. Réservé aux groupes dont le tunnel est monté et prouvé. Vous codez un petit service web qui montre, en un coup d’œil, l’état du lien entre vos deux bases. Le langage et la stack sont libres. Ce qui est jugé n’est pas le code, c’est l’architecture dans laquelle vous le posez.

Une seule page, rafraîchie toutes les 30 secondes, sans authentification côté page (elle n’est consultée que depuis mgmt) :

BlocContenuSource
État du tunnelPhase 1 (ESTABLISHED ou non), Phase 2 (INSTALLED ou non), SPI entrant et sortant, adresse du pair, date du dernier changement d’étatAPI OPNsense, module IPsec (/api/ipsec/sessions/searchPhase1 et searchPhase2)
Trafic du voisinNombre de paquets acceptés et refusés venant de 10.G'.0.0/16 sur la dernière heure, et les cinq derniers refus (heure, source, destination, port)API Loki (/loki/api/v1/query_range) sur les journaux du pare-feu déjà poussés par Alloy
Service partagéLe service que vous offrez au voisin répond-il (vert) ou non (rouge), testé depuis la console par une connexion TCP sur le port déclaréTest direct depuis le serveur de la console
Dernière ruptureDepuis quand le tunnel est monté, et la durée de la dernière coupure observéeCalculé par la console à partir de ses propres relevés, conservés en mémoire ou dans un fichier

Pas de graphiques, pas de base de données, pas de comptes utilisateurs, pas d’action sur le pare-feu. Elle lit, elle n’agit pas. Grafana fait déjà les courbes ; la console répond à une seule question : le lien avec l’archipel voisin est-il sain, maintenant ?

Contraintes d’architecture, et c’est là qu’on vous attend

Section intitulée « Contraintes d’architecture, et c’est là qu’on vous attend »
  1. Un serveur, un navigateur. Le navigateur ne parle qu’à votre serveur. C’est le serveur qui interroge OPNsense et Loki : aucune clé d’API, aucune adresse interne ne transite jusqu’au navigateur. Justifiez ce choix dans le rapport en une phrase.
  2. Une clé d’API OPNsense dédiée, créée pour la console, avec le minimum de droits (lecture du statut IPsec, rien d’autre). Elle vit dans un fichier d’environnement non commité. Dites ce que peut faire un attaquant qui la vole.
  3. Une zone à choisir. En z-soc, la console lit Loki en local mais doit sortir vers OPNsense, ce qui entame « rien ne sort du SOC ». En mgmt, elle est hors du SI segmenté et doit entrer dans z-soc pour lire Loki. Choisissez, et écrivez ce que le choix coûte.
  4. Deux lignes de matrice au minimum, datées et justifiées comme les autres : console → OPNsense (port de l’API, 443), console → Loki (3100), plus le test TCP vers le service partagé. Rien d’autre ne s’ouvre.
  5. Le schéma de la base est mis à jour avec la console, dans la zone choisie.

Une section « Bonus » en fin de chapitre TP3 : le schéma mis à jour, les lignes de matrice ajoutées, une capture de la console tunnel monté, une capture tunnel coupé, et la réponse à une question : si la console est compromise, jusqu’où va l’attaquant ? Pas de code dans le rapport, au plus l’extrait de 20 lignes qui interroge l’API OPNsense.