SDN : un puits sur le supernet du tenant dans son propre VRF
« Je ne trouve pas ca normal » — l'exploitant avait raison. Pendant deux jours nous avons attribue ce comportement a l'anti-usurpation de la frontiere, et je l'avais consigne comme tel. Mesure depuis DEUX points de vue : depuis le poste, quatre connexions sur quatre s'etablissaient ; depuis l'interieur du tenant, le comportement etait correct partout ou un VNet existe. L'anomalie ne touchait que les portions de supernet sans VNet. Cause : vrf_t17 portait les six /24 et un defaut, RIEN pour le reste du /16. Une adresse non attribuee sortait du VRF, atteignait la frontiere, revenait a l'hyperviseur dans la table PRINCIPALE — pas dans le VRF — et repartait vers 192.168.11.254, la passerelle du reseau d'ADMINISTRATION. strophe_frr pose desormais un puits sur le supernet du tenant, moins specifique que ses /24 donc invisible au trafic legitime. Derive du seed. Verifie : depuis le tenant, 10.27.99.99 et 10.27.18.99 refusees, 10.27.18.21 etablie. Une machine du tenant ne peut plus atteindre le reseau de gestion par une faute de frappe. Reste, sans arbitrage : depuis le VLAN d'administration le connect() reussit encore, ce trafic n'entrant jamais dans le VRF. Deux remedes possibles, dont l'un touche la table qui porte l'administration des hyperviseurs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
91d9bd19f4
commit
78f2f7fd6f
2 changed files with 65 additions and 1 deletions
48
CHANGELOG.md
48
CHANGELOG.md
|
|
@ -1,5 +1,53 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-08-09 — Le `connect()` qui « ne prouvait rien » n'était pas de l'anti-usurpation
|
||||
|
||||
L'exploitant : « je ne trouve pas ça normal ». Il avait raison, et pendant deux jours nous
|
||||
avons tous les deux attribué ce comportement à une fonction d'anti-usurpation de la
|
||||
frontière — moi le premier, et je l'avais même consigné comme tel.
|
||||
|
||||
**Mesuré, pas raconté.** Depuis le poste, quatre connexions sur quatre s'établissaient, y
|
||||
compris vers une adresse où aucune machine n'existe. Mais vers des réseaux hors du tenant,
|
||||
tout était refusé — donc rien n'interceptait globalement. Et **depuis l'intérieur du
|
||||
tenant**, le comportement était correct partout où un VNet existe : hôte absent → refusé,
|
||||
port fermé → refusé. L'anomalie ne touchait que les portions de supernet **non couvertes
|
||||
par un VNet**.
|
||||
|
||||
**La cause était une route manquante, pas un pare-feu.**
|
||||
|
||||
```
|
||||
vrf_t17 : les six /24 des VNets, puis default -> 10.0.4.1
|
||||
RIEN pour le reste de 10.27.0.0/16
|
||||
```
|
||||
|
||||
Une adresse non attribuée sortait donc du VRF par le défaut, atteignait la frontière, qui
|
||||
la renvoyait à l'hyperviseur — où elle arrivait dans la table **principale**, pas dans le
|
||||
VRF, et repartait vers `192.168.11.254`, la passerelle du réseau d'**administration**.
|
||||
`ip route get 10.27.99.99` le disait en une ligne.
|
||||
|
||||
**Corrigé où le dépôt a la main** : `strophe_frr` pose désormais, dans chaque VRF, un puits
|
||||
sur le supernet du tenant — **moins spécifique** que les `/24` de ses VNets, donc invisible
|
||||
au trafic légitime. Dérivé du seed, comme tout le reste.
|
||||
|
||||
```
|
||||
depuis le tenant, apres : 10.27.99.99 refusee 10.27.18.99 refusee 10.27.18.21 ETABLIE
|
||||
```
|
||||
|
||||
**Une machine du tenant ne peut plus atteindre le réseau de gestion par une faute de
|
||||
frappe.** C'était le vrai risque, et il est fermé.
|
||||
|
||||
**Ce qui reste, et que je ne corrige pas sans arbitrage.** Depuis le VLAN d'administration,
|
||||
le `connect()` réussit encore : ce trafic n'entre jamais dans le VRF. OPNsense route tout
|
||||
`10.27.0.0/16` vers l'hyperviseur, dont la table principale ne connaît que les six `/24`.
|
||||
Deux remèdes possibles — un puits symétrique dans la table principale, ou n'annoncer à la
|
||||
frontière que les `/24` réellement attribués. Le premier touche la table qui porte
|
||||
l'administration des hyperviseurs ; ce n'est pas un geste à faire de sa propre initiative.
|
||||
|
||||
**La leçon dépasse la route.** Nous avons expliqué pendant deux jours un symptôme par une
|
||||
cause plausible et fausse, et cette explication est entrée dans la documentation. Ce qui l'a
|
||||
défaite n'est pas un raisonnement plus fin : c'est d'avoir mesuré depuis **deux points de
|
||||
vue différents**. Un seul point de vue donne une histoire cohérente — souvent la mauvaise.
|
||||
|
||||
## 2026-08-09 — Le wiki rattrape ce que la reconstruction a appris
|
||||
|
||||
Le wiki datait du 3 août — six jours avant tout ce qui précède. Vérifié avant d'y toucher :
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ import yaml
|
|||
RACINE = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(RACINE / "scripts"))
|
||||
|
||||
from inventory_rules import passerelle_de, sous_reseau_de, vlan_de # noqa: E402
|
||||
from inventory_rules import passerelle_de, sous_reseau_de, supernet_de, vlan_de # noqa: E402
|
||||
from devis_reseau import decouvrir # noqa: E402
|
||||
import underlay as underlay_mod # noqa: E402
|
||||
|
||||
|
|
@ -139,6 +139,7 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
|||
blocs.append({
|
||||
"tenant": nom_instance,
|
||||
"index": index,
|
||||
"supernet": supernet_de(index),
|
||||
"zone": zone_de(index),
|
||||
"vrf_vxlan": index,
|
||||
"mtu": mtu,
|
||||
|
|
@ -185,6 +186,21 @@ def strophe_frr(devis: dict) -> str:
|
|||
for b in devis["zones"]:
|
||||
lignes += [f"vrf vrf_{b['zone']}",
|
||||
f" ip route 0.0.0.0/0 {devis['frontiere']} nexthop-vrf default",
|
||||
# PUITS sur le supernet du tenant, MOINS SPECIFIQUE que les /24 de ses
|
||||
# VNets : le trafic legitime ne le voit jamais, tout le reste s'y arrete.
|
||||
#
|
||||
# Sans lui, une adresse non attribuee du supernet ne trouve aucune route
|
||||
# locale, sort par le defaut, atteint la frontiere qui la renvoie a
|
||||
# l'hyperviseur — ou elle arrive dans la table PRINCIPALE, pas dans le
|
||||
# VRF, et repart vers la passerelle du reseau d'ADMINISTRATION. Mesure du
|
||||
# 2026-08-09 : `ip route get 10.27.99.99` rend `via 192.168.11.254`.
|
||||
#
|
||||
# Deux consequences. Le trafic d'un tenant pouvait atteindre le reseau de
|
||||
# gestion par une simple faute de frappe. Et `connect()` reussissait vers
|
||||
# n'importe quelle adresse inexistante du supernet — ce qui a longtemps
|
||||
# passe pour de l'anti-usurpation de la frontiere, alors que c'etait une
|
||||
# route manquante ici.
|
||||
f" ip route {b['supernet']} blackhole",
|
||||
"exit-vrf"]
|
||||
return "\n".join(lignes) + "\n"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue