frontière : le prochain saut dérive du transit, il n'est plus saisi
`opnsense_prochain_saut` quitte le panneau Intrants. Il dérive du réseau de transit de l'underlay — la `passerelle` du réseau portant `passerelle_sortie`. Un seul bloc alimente les deux devis : 10.0.4.1 est le SVI côté switch ET le prochain saut des routes tenants côté frontière ; 10.0.4.2 est la route par défaut du switch. Le saisir en doublon rouvrait la possibilité de deux valeurs contradictoires pour un seul lien — le mode de panne qu'on venait de fermer pour les réseaux d'administration. Le devis frontière expose le bloc `transit` (JSON compris) et cesse de réclamer en section 0 les routes que `devis-reseau` émet désormais : il dit lesquelles sont déjà émises, ou signale l'absence de transit déclaré. Sans underlay, le marqueur revient — le repli reste explicite. Preuves : 24 OK, 0 échec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
3698152b6a
commit
069e549160
4 changed files with 75 additions and 6 deletions
19
CHANGELOG.md
19
CHANGELOG.md
|
|
@ -1,5 +1,24 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 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
|
||||
transit de l'underlay (la `passerelle` du réseau portant `passerelle_sortie`).
|
||||
|
||||
Un seul bloc de six lignes alimente désormais les deux devis : `10.0.4.1` devient le SVI
|
||||
côté switch **et** le prochain saut des routes tenants côté frontière ; `10.0.4.2` devient
|
||||
la route par défaut du switch. Le saisir en doublon dans le panneau rouvrait la possibilité
|
||||
de deux valeurs contradictoires pour un seul lien — précisément le mode de panne qu'on venait
|
||||
de fermer pour les réseaux d'administration.
|
||||
|
||||
Le devis frontière gagne au passage un bloc `transit` (JSON compris) et cesse de réclamer en
|
||||
section 0 des routes que `make devis-reseau` émet maintenant : il dit lesquelles sont **déjà
|
||||
émises**, ou signale l'absence de transit déclaré. Sans underlay, le marqueur
|
||||
`<PROCHAIN-SAUT-SWITCH>` revient — le repli reste explicite.
|
||||
|
||||
Reste un seul intrant à figer au câblage : `opnsense_if_transit`, le nom de l'interface qui
|
||||
porte le VLAN 40 sur le boîtier — la seule valeur que rien ne peut deviner.
|
||||
|
||||
## 2026-08-01 — le lien de transit et les deux routes (la boucle est fermée)
|
||||
|
||||
### Ajouté — réseau de transit dans l'underlay (clé `passerelle_sortie`)
|
||||
|
|
|
|||
|
|
@ -77,6 +77,12 @@ Un `/29` plutôt qu'un `/30` : pendant une transition, deux pare-feux cohabitent
|
|||
et un `/30` n'offre que deux adresses. `make underlay` (**preuve P23**) refuse une sortie hors
|
||||
du lien, confondue avec le SVI, sans SVI, ou déclarée deux fois.
|
||||
|
||||
Ce seul bloc alimente **les deux devis** : le `passerelle` (`10.0.4.1`) devient le SVI côté
|
||||
switch *et* le prochain saut des routes tenants côté frontière ; le `passerelle_sortie`
|
||||
(`10.0.4.2`) devient la route par défaut du switch. Le prochain saut n'est donc **pas** un
|
||||
intrant du panneau — le saisir en doublon rouvrirait la possibilité de deux valeurs
|
||||
contradictoires pour un seul et même lien.
|
||||
|
||||
### Les deux routes, et pourquoi il en faut deux
|
||||
|
||||
`make devis-reseau` émet alors, en section 5 :
|
||||
|
|
@ -155,9 +161,10 @@ ansible-vault edit instance/inventories/principal/group_vars/all/vault.yml
|
|||
## 6. Ce qui reste ouvert
|
||||
|
||||
- **Le câblage** — le lien de transit est *décidé* (VLAN 40, `10.0.4.0/29`) et le devis
|
||||
switch émet déjà son SVI et ses routes. Restent à figer, une fois le boîtier raccordé, les
|
||||
deux intrants côté frontière : `opnsense_if_transit` (l'interface qui porte le VLAN 40) et
|
||||
`opnsense_prochain_saut` (`10.0.4.1`).
|
||||
switch émet déjà son SVI et ses routes. Reste à figer, une fois le boîtier raccordé, un
|
||||
seul intrant : `opnsense_if_transit`, le nom de l'interface qui porte le VLAN 40 sur le
|
||||
boîtier — la seule valeur que rien ne peut deviner. Le prochain saut, lui, **dérive** du
|
||||
transit (voir §4).
|
||||
- **Le second VPN** — pendant la transition, le VPN d'administration actuel (pfSense) reste
|
||||
en service et OPNsense en montera un second. Son sous-réseau devra être **ajouté à
|
||||
`nftables_admin_ssh`**, sans quoi il sera muet de la même façon.
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ from resoudre_flux import ( # noqa: E402
|
|||
_sources_admin_ssh,
|
||||
)
|
||||
from devis_reseau import decouvrir, prefixe # noqa: E402
|
||||
# Le lien de transit (et donc le prochain saut) vit dans l'underlay : il est PARTAGE
|
||||
# par tous les tenants, il ne peut deriver d'aucun index. Source unique, pas un intrant.
|
||||
import underlay as underlay_mod # noqa: E402
|
||||
|
||||
# Marqueurs de repli, tant que les intrants de frontiere ne sont pas renseignes
|
||||
# (meme idiome que devis_reseau). Le panneau « Intrants de base » du GUI les ecrit
|
||||
|
|
@ -70,6 +73,22 @@ def _ou_marqueur(intrants: dict, cle: str, marqueur: str) -> str:
|
|||
valeur = str(intrants.get(cle) or "").strip()
|
||||
return valeur or marqueur
|
||||
|
||||
|
||||
def transit_underlay() -> dict | None:
|
||||
"""Le reseau de transit declare dans l'underlay, ou None."""
|
||||
return underlay_mod.reseau_transit(underlay_mod.charger())
|
||||
|
||||
|
||||
def prochain_saut(transit: dict | None) -> str:
|
||||
"""Prochain saut des routes tenants = le SVI du switch sur le lien de transit.
|
||||
|
||||
DERIVE, jamais saisi : c'est le meme lien que celui d'ou `devis_reseau` tire la
|
||||
route par defaut et les routes de retour. Le declarer deux fois (une fois ici, une
|
||||
fois dans l'underlay) ouvrirait la porte a deux valeurs contradictoires — c'est
|
||||
exactement le mode de panne qu'on ferme. Marqueur tant qu'aucun transit n'existe.
|
||||
"""
|
||||
return str((transit or {}).get("passerelle") or "").strip() or PROCHAIN_SAUT
|
||||
|
||||
# Le socle est porte par TOUS les hotes : sa destination n'est pas une poignee
|
||||
# de machines mais le supernet du tenant. Evite un alias de 14 adresses.
|
||||
ROLE_SOCLE = "serveur_debian"
|
||||
|
|
@ -177,7 +196,8 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
|||
})
|
||||
|
||||
intrants = intrants_frontiere()
|
||||
saut = _ou_marqueur(intrants, "opnsense_prochain_saut", PROCHAIN_SAUT)
|
||||
transit = transit_underlay()
|
||||
saut = prochain_saut(transit)
|
||||
routes = [
|
||||
{
|
||||
"reseau": supernet_de(n["index"]),
|
||||
|
|
@ -198,6 +218,13 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
|||
"routes": routes,
|
||||
"regles": regles,
|
||||
"admin": admin,
|
||||
"transit": {
|
||||
"nom": (transit or {}).get("nom"),
|
||||
"vlan": (transit or {}).get("vlan"),
|
||||
"sous_reseau": (transit or {}).get("sous_reseau"),
|
||||
"svi_switch": saut,
|
||||
"adresse_frontiere": (transit or {}).get("passerelle_sortie"),
|
||||
} if transit else None,
|
||||
"reciproque_switch": [
|
||||
f"ip route {cidr} -> {saut} (retour vers l'administration)"
|
||||
for cidr in admin
|
||||
|
|
@ -214,17 +241,31 @@ def rendre(devis: dict) -> str:
|
|||
"# Les passerelles de zone restent sur les switches L3 : aucun SVI ici.",
|
||||
"# ============================================================",
|
||||
"",
|
||||
"## 0. Prerequis reciproques — A FAIRE SUR LES SWITCHES",
|
||||
"## 0. Prerequis reciproques — COTE SWITCHES",
|
||||
"# Sans ces routes de retour, le trafic part mais ne revient pas : la",
|
||||
"# reponse sort par une autre interface et le pare-feu la jette (hors etat).",
|
||||
]
|
||||
out += [f"# {r}" for r in devis["reciproque_switch"]] or ["# (aucun reseau d'administration declare)"]
|
||||
tr = devis.get("transit")
|
||||
if tr:
|
||||
out.append(f"# DEJA EMIS par `make devis-reseau` (section 5), derive du transit"
|
||||
f" '{tr['nom']}' de l'underlay.")
|
||||
else:
|
||||
out.append("# A EMETTRE : aucun reseau de transit n'est declare dans underlay.yml")
|
||||
out.append("# (cle `passerelle_sortie`). Sans lui, ni sortie ni retour ne sont derivables.")
|
||||
out += [
|
||||
"",
|
||||
"## 1. Interfaces",
|
||||
f"# Gestion : {devis['api_url'] or '(intrant opnsense_api_url a renseigner)'}",
|
||||
f"# WAN : {devis['if_wan']}",
|
||||
f"# TRANSIT : {devis['if_transit']} (trunk 802.1Q vers les switches)",
|
||||
]
|
||||
if tr:
|
||||
out += [
|
||||
f"# lien '{tr['nom']}' {tr['sous_reseau']} — VLAN {tr['vlan']} a etiqueter",
|
||||
f"# switch {tr['svi_switch']} <-> frontiere {tr['adresse_frontiere']}",
|
||||
]
|
||||
out += [
|
||||
"",
|
||||
"## 2. Routes statiques (vers les supernets tenants)",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -115,7 +115,9 @@ INTRANTS_SCHEMA = [
|
|||
("opnsense_api_verifier_certs", "frontiere", "defaut", "Frontière", "Valider le certificat TLS de la frontière", "bool"),
|
||||
("opnsense_if_wan", "frontiere", "defaut", "Frontière", "Interface WAN", "str"),
|
||||
("opnsense_if_transit", "frontiere", "defaut", "Frontière", "Interface/trunk vers les switches (transit)", "str"),
|
||||
("opnsense_prochain_saut", "frontiere", "defaut", "Frontière", "IP du switch L3 qui porte les SVI (prochain saut des routes tenants)", "str"),
|
||||
# `opnsense_prochain_saut` n'est PLUS un intrant : il derive du reseau de transit de
|
||||
# l'underlay (`passerelle` du reseau portant `passerelle_sortie`). Le saisir ici en
|
||||
# doublon ouvrirait la porte a deux valeurs contradictoires pour un seul lien.
|
||||
]
|
||||
# Cles secretes : interdites a l'ecriture par le GUI (garde-fou).
|
||||
INTRANTS_CLES_INTERDITES = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue