From 0d64d284026b305498c427603e22c0367bfebf53 Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Sat, 1 Aug 2026 19:52:50 -0400 Subject: [PATCH] =?UTF-8?q?devis=20switch=20:=20le=20port=20vers=20la=20fr?= =?UTF-8?q?onti=C3=A8re,=20et=20l'ordre=20d'application?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deux omissions que le devis faisait porter à l'opérateur. Le VLAN de transit était étiqueté sur le trunk ``, et aucune interface vers le pare-feu n'était émise. Les hyperviseurs n'ont pas d'interface sur le transit, et le pare-feu n'a rien à faire des VLAN tenants — il route vers eux, il ne les étiquette pas. Le transit sort du trunk Proxmox et prend son propre port (section 4b), dérivé de l'underlay. Les routes de la section 5 déplacent la sortie du switch, y compris celle de ses propres réponses. Tant que la frontière ne répond pas, elles coupent l'accès d'administration AU SWITCH LUI-MÊME — le mécanisme qui a rendu une VM muette le 2026-07-29, appliqué à l'équipement depuis lequel on travaille. Le devis les crachait à la suite des autres comme si elles étaient équivalentes ; il énonce maintenant les préalables et l'ordre. Sans transit déclaré, les deux sections s'affichent en clair comme manquantes plutôt que de disparaître. Preuves : 24 OK, 0 échec. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 20 ++++++++++++++++++++ docs/frontiere-opnsense.md | 11 +++++++++++ scripts/devis_reseau.py | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c057b62..41860e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # CHANGELOG — Set-OPS +## 2026-08-01 (suite 2) — le port vers la frontière, et l'ordre d'application + +### Ajouté — section 4b : le port du switch vers la frontière +Le devis étiquetait le VLAN de transit sur le trunk `` et n'émettait +aucune interface vers le pare-feu. Deux erreurs en une : les hyperviseurs n'ont pas +d'interface sur le transit, et le pare-feu n'a rien à faire des VLAN tenants — il route vers +eux, il ne les étiquette pas. Le VLAN de transit sort donc du trunk Proxmox et prend son +propre port, dérivé du transit déclaré. + +### Ajouté — avertissement d'ordre en tête de la section 5 +Les routes de la section 5 déplacent la sortie du switch, **y compris celle de ses propres +réponses**. Tant que l'adresse de la frontière ne répond pas, elles coupent l'accès +d'administration au switch lui-même — le mécanisme qui a rendu une VM muette le 2026-07-29, +appliqué cette fois à l'équipement depuis lequel on travaille. + +Le devis crachait ces lignes à la suite des autres comme si elles étaient équivalentes. +Il énonce désormais les préalables (boîtier câblé, adressé, joignable depuis le switch, +session console ouverte) — inacceptable autrement pour un outil censé être exploitable sans +IA. + ## 2026-08-01 (suite) — le prochain saut dérive du transit `opnsense_prochain_saut` n'est plus un intrant du panneau : il **dérive** du réseau de diff --git a/docs/frontiere-opnsense.md b/docs/frontiere-opnsense.md index 84f3b5e..5cb81f3 100644 --- a/docs/frontiere-opnsense.md +++ b/docs/frontiere-opnsense.md @@ -95,6 +95,17 @@ ip route 192.168.255.0 255.255.255.0 10.0.4.2 # retour (nftables_admin_ssh) **L'aller** est la sortie générale : sans elle, aucun hôte de la flotte n'atteint quoi que ce soit hors de sa zone. +### L'ordre d'application, qui n'est pas indifférent + +Les sections 0 à 4b du devis switch sont sûres et posables à tout moment. **La section 5 ne +l'est pas.** Ces routes déplacent la sortie du switch — y compris celle de ses propres +réponses — vers l'adresse de la frontière. Tant que cette adresse ne répond pas, elles +coupent l'accès d'administration **au switch lui-même**. + +C'est le même mécanisme que le piège ci-dessous, mais appliqué à l'équipement depuis lequel +on travaille. Préalables, rappelés dans le devis : boîtier câblé, adressé sur le lien de +transit, joignable depuis le switch, et une session console ouverte pendant l'opération. + **Le retour** est le piège proprement dit. Un paquet d'administration entre par la frontière et atteint la VM ; la réponse part de la VM vers sa passerelle — un SVI **de switch**. Si le switch n'a pas de route vers le réseau d'administration, ou s'il l'atteint par un autre chemin diff --git a/scripts/devis_reseau.py b/scripts/devis_reseau.py index 700de7b..8a729f1 100644 --- a/scripts/devis_reseau.py +++ b/scripts/devis_reseau.py @@ -82,6 +82,26 @@ def section_underlay(underlay: dict | None) -> list[str]: return out +def section_frontiere(transit: dict | None) -> list[str]: + """Port du switch vers le pare-feu de bordure. Porte le VLAN de transit, et lui seul. + + Distinct du trunk vers Proxmox : les hyperviseurs n'ont aucune interface sur le + transit, et le pare-feu n'a rien a faire des VLAN tenants — il route vers eux, il + ne les etiquette pas. + """ + if not transit: + return ["! ----- 4b. Port vers la frontiere -----", + "! Aucun reseau de transit declare dans underlay.yml (cle 'passerelle_sortie')."] + return [ + "! ----- 4b. Port vers la frontiere nord/sud -----", + f"! Porte le seul VLAN {transit['vlan']} ({transit['nom']}). En lien dedie,", + f"! remplacer par : switchport access vlan {transit['vlan']}.", + "interface ", + " switchport mode trunk", + f" switchport trunk allowed vlan add {transit['vlan']}", + ] + + def section_routes(underlay: dict | None) -> list[str]: """Routes du switch vers la frontiere nord/sud. Vide si aucun transit declare. @@ -104,6 +124,14 @@ def section_routes(underlay: dict | None) -> list[str]: "!"] sortie = transit["passerelle_sortie"] out = ["! ----- 5. Routes vers la frontiere nord/sud -----", + "! /!\\ A APPLIQUER EN DERNIER, ET SEULEMENT UNE FOIS LA FRONTIERE VIVANTE.", + f"! Ces routes deplacent la sortie du switch — y compris celle de ses propres", + f"! reponses — vers {sortie}. Tant que cette adresse ne repond pas, elles", + "! coupent l'acces d'administration AU SWITCH LUI-MEME.", + "! Prealables : boitier cable, adresse sur le lien de transit, et joignable", + f"! depuis le switch (ping {sortie} depuis Vlan{transit['vlan']}).", + "! Garder une session console ouverte pendant l'operation.", + "!", f"! Transit '{transit['nom']}' (VLAN {transit['vlan']}) : SVI {transit['passerelle']}" f" <-> frontiere {sortie}", "! Aller : sortie generale de la flotte.", @@ -189,7 +217,11 @@ def generer(tenants: list[tuple[str, str, dict]], dialecte: str | None = None) - out += remarque(dialecte, "Reste (Internet / inter-tenant controle) -> passerelle OPNsense") out.append(f" permit ip {reseau} {m} any") out += ["!", "! ----- 4. Trunk vers Proxmox + inter-switch (a adapter) -----"] - vlans_underlay = [str(r["vlan"]) for r in underlay_mod.reseaux(underlay)] + transit = underlay_mod.reseau_transit(underlay) + # Le VLAN de transit ne va PAS vers Proxmox : aucun hyperviseur n'a d'interface + # dessus. Il sort par le port de la frontiere (ci-dessous), et lui seul. + vlans_underlay = [str(r["vlan"]) for r in underlay_mod.reseaux(underlay) + if not (transit and r["vlan"] == transit["vlan"])] vlans_tenants = [ str(vlan_de(n["index"], zone)) for _, _, n in tenants @@ -199,6 +231,7 @@ def generer(tenants: list[tuple[str, str, dict]], dialecte: str | None = None) - out.append("interface ") out.append(" switchport mode trunk") out.append(f" switchport trunk allowed vlan add {vlans}") + out += ["!"] + section_frontiere(transit) out += ["!"] + section_routes(underlay) out += ["end", "write memory"] return "\n".join(out)