ACL de switch : les tenants n'atteignent plus la fabric physique
L'ACL d'isolation bloquait l'autre tenant, puis se terminait par `permit ip <tenant> any`. Ce `any` autorisait 10.27.x -> 10.0.0.0/24 : le management des switches, celui de Proxmox et l'OOB/IPMI, plus iSCSI et Ceph. Une VM compromise atteignait la console physique des hyperviseurs. Le commentaire du générateur disait « Reste -> passerelle OPNsense », ce qui est faux pour l'underlay : ce trafic est routé LOCALEMENT par le switch et ne passe jamais par la frontière, donc elle ne le filtre jamais. Un `deny` par sous-réseau underlay est désormais émis avant le `permit` final, dérivé de underlay.yml, dialecte respecté (masque normal ou wildcard). Vérifié qu'aucun flux du registre ne vise l'underlay : rien de déclaré ne casse. Sans underlay déclaré, l'ACL retrouve sa forme d'avant. Consigné en §6 : le registre n'a pas de mot-clé `underlay` (un besoin légitime, superviser l'hyperviseur, ne pourrait pas être déclaré), et le devis émet un jeu unique de SVI pour trois switches sans MLAG. Preuves : 24 OK, 0 échec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
0d64d28402
commit
7b2ba07ffc
3 changed files with 45 additions and 0 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
|
@ -1,5 +1,26 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-08-01 (suite 3) — les tenants n'atteignent plus l'underlay
|
||||
|
||||
### Corrigé — ACL de switch : `deny` vers la fabric physique
|
||||
L'ACL d'isolation bloquait l'autre tenant, puis se terminait par `permit ip <tenant> any`.
|
||||
Ce `any` autorisait `10.27.x` → `10.0.0.0/24` : le management des switches, celui de Proxmox
|
||||
et l'**OOB/IPMI**, plus les réseaux iSCSI et Ceph. Une VM compromise atteignait la console
|
||||
physique des hyperviseurs.
|
||||
|
||||
Le commentaire du générateur disait « Reste → passerelle OPNsense », mais c'est faux pour
|
||||
l'underlay : ce trafic est routé **localement** par le switch et ne passe jamais par la
|
||||
frontière, donc il n'est jamais filtré par elle.
|
||||
|
||||
`devis_reseau.py` émet désormais un `deny` par sous-réseau underlay avant le `permit` final,
|
||||
dérivé de `underlay.yml` — dialecte respecté (masque normal ou wildcard). Aucun flux du
|
||||
registre ne vise l'underlay : le blocage ne casse rien de déclaré.
|
||||
|
||||
Deux limites consignées dans `docs/frontiere-opnsense.md` §6 : le registre des flux n'a pas
|
||||
de mot-clé `underlay`, donc un besoin légitime (superviser l'hyperviseur) ne pourrait pas
|
||||
être déclaré ; et `devis_reseau.py` émet un jeu unique de SVI pour trois switches sans MLAG,
|
||||
ce qui reste une décision d'architecture ouverte.
|
||||
|
||||
## 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
|
||||
|
|
|
|||
|
|
@ -23,6 +23,13 @@ Conséquence assumée : l'isolation inter-zone repose sur les ACL de switch, moi
|
|||
que le registre des flux. Le zéro-confiance est-ouest reste porté par les nftables d'hôte et
|
||||
le TLS mutuel — pas par le pare-feu de bordure.
|
||||
|
||||
Corollaire, qui n'est pas anodin : **le trafic d'un tenant vers l'underlay est routé
|
||||
localement par le switch et ne passe jamais par la frontière.** Il n'est donc jamais filtré
|
||||
par elle. Sans précaution, le `permit ip <tenant> any` final de l'ACL laisserait une VM
|
||||
atteindre le management des switches, celui de Proxmox et l'OOB/IPMI. `make devis-reseau`
|
||||
émet pour cette raison un `deny` par sous-réseau underlay **avant** le `permit` final,
|
||||
dérivé de `underlay.yml`.
|
||||
|
||||
## 2. Ce que la frontière décide (et pourquoi rien n'est saisi à la main)
|
||||
|
||||
Le registre des flux distingue les pairs par **mot-clé**. Or `resoudre_flux.py` **saute
|
||||
|
|
@ -181,6 +188,14 @@ ansible-vault edit instance/inventories/principal/group_vars/all/vault.yml
|
|||
`nftables_admin_ssh`**, sans quoi il sera muet de la même façon.
|
||||
- **L'application par l'API** — `--json` produit la structure ; le client d'application reste
|
||||
à écrire.
|
||||
- **Pas de mot-clé `underlay` dans le registre des flux** — l'underlay est aujourd'hui
|
||||
interdit en bloc aux tenants. Si un besoin légitime apparaît (superviser l'hyperviseur
|
||||
depuis `obs-01`, par exemple), il ne peut pas être *déclaré* : il faudrait ajouter un pair
|
||||
`underlay` au registre plutôt qu'une exception manuelle dans l'ACL.
|
||||
- **Trois switches, un seul devis** — `devis_reseau.py` émet un jeu unique de SVI sans
|
||||
désigner le switch qui les porte. Sans MLAG, il reste à trancher entre « un seul routeur,
|
||||
les deux autres en L2 pur » et « SVI répliqués en VRRP ». Appliquer le devis tel quel sur
|
||||
les trois créerait des conflits d'adresses.
|
||||
- **La sortie générale** (mises à jour apt, ACME) n'est pas déclarée dans le registre : les
|
||||
hôtes sortent aujourd'hui parce que la politique `output` des nftables est `accept` et que
|
||||
l'ACL de switch se termine par `permit ip <tenant> any`. À trancher : la déclarer
|
||||
|
|
|
|||
|
|
@ -214,6 +214,15 @@ def generer(tenants: list[tuple[str, str, dict]], dialecte: str | None = None) -
|
|||
a_reseau, a_m = masque_acl(supernet_de(autre["index"]), dialecte)
|
||||
out += remarque(dialecte, f"Bloquer le tenant {autre_nom}")
|
||||
out.append(f" deny ip {reseau} {m} {a_reseau} {a_m}")
|
||||
# L'underlay est la fabric physique : mgmt des switches, mgmt Proxmox, OOB/IPMI,
|
||||
# iSCSI, Ceph. Le trafic d'un tenant vers ces reseaux est route LOCALEMENT par le
|
||||
# switch : il ne passe jamais par la frontiere, donc il n'est jamais filtre. Sans
|
||||
# ce deny, le `permit any` final l'autorise — une VM atteindrait la console
|
||||
# physique des hyperviseurs. Aucun flux du registre ne vise l'underlay.
|
||||
for r in underlay_mod.reseaux(underlay):
|
||||
u_reseau, u_m = masque_acl(r["sous_reseau"], dialecte)
|
||||
out += remarque(dialecte, f"Bloquer l'underlay {r['nom']} (fabric physique)")
|
||||
out.append(f" deny ip {reseau} {m} {u_reseau} {u_m}")
|
||||
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) -----"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue