implementer la gestion des ip public... #31

Open
opened 2026-05-23 20:46:57 +00:00 by nicolas.boufideline · 3 comments

Synthèse — architecture réseau opérateur de VMs

Le design retenu

Un plan underlay hiérarchique en eBGP, et un plan overlay EVPN-VXLAN en iBGP, indépendants l'un de l'autre.

L'espace public est ancré aux routeurs de bordure, qui en sont la gateway. Chaque subnet public est un VNI L2 étendu jusqu'aux hosts, y compris entre DC — ce qui permet à n'importe quelle VM d'obtenir n'importe quelle IP du pool, où qu'elle tourne. C'est le besoin structurant que tu as confirmé comme non négociable.

Plan d'ASN :

Élément ASN global Sessions
Bordures AS public eBGP transit natif, local-as overlay vers les RR
Backbone privé, un par DC eBGP underlay
Cluster privé, un par cluster/DC eBGP underlay, local-as overlay vers les RR (VTEP)
Hosts — iBGP overlay
RR ASN overlay iBGP, clients = hosts, bordures, clusters

Le sens du local-as compte : ASN global = ASN public sur les bordures, artifice sur les sessions internes. Les sessions exposées à Internet restent natives, donc AS_PATH, ROA et objets IRR cohérents sans manipulation. À valider en lab que local-as produit bien une session iBGP sur tes versions exactes — certaines plateformes déterminent le type de session avant d'appliquer local-as, ce qui casserait la préservation du next-hop et donc l'EVPN.

Ce qui a été tranché en chemin

Ta question initiale — trop de routes ? Non, et structurellement pas. Les subnets publics ne remontent pas vers la bordure, ils sont dessus : vers Internet, seuls les agrégats sortent. Découper un /19 en /24 ou en /28 ne change rien au routage. Ce qui scale, c'est le nombre de VMs (une type-2 MAC + une MAC/IP + une entrée ARP par VM), pas le nombre de subnets.

Keepalived → gateway anycast. Même IP et même MAC de bridge sur les deux bordures, avec advertise-default-gw. Tu évites le trombonnement de bascule, le MAC mobility à chaque événement, et surtout le risque qu'une VM cliente émette du VRRP en priorité 255 et devienne la gateway du subnet. La sélection du VTEP côté host est déterministe, donc sans ESI tu auras probablement une seule bordure utilisée — bascule propre, mais pas de répartition. À vérifier avec bridge fdb show.

iBGP + RR plutôt qu'eBGP pour l'EVPN. Ta config précédente était déjà en iBGP (remote-as = ASN local). L'eBGP pour l'EVPN reste faisable mais expose deux pièges silencieux : les route targets auto-dérivés en AS:VNI qui ne concordent plus quand les ASN diffèrent, et le next-hop qui doit rester celui du VTEP d'origine.

RR : deux VIP Pacemaker sur deux groupes de trois. Ton montage corrigé répond à l'objection — aucun événement unique ne casse les deux sessions. Je reste convaincu que six loopbacks fixes seraient plus simples (pas de fencing, pas de split-brain, pas d'ordonnancement VIP/FRR, et les six nœuds vérifiés en continu), mais c'est viable si le fencing est réel et testé, les groupes séparés physiquement, et l'ordre VIP→FRR explicite ou ip_nonlocal_bind posé.

Multi-DC. eBGP entre DC pour l'underlay, mais l'overlay reste un domaine iBGP unique traversant tous les DC. Conséquence contre-intuitive à documenter : on lit un ASN par DC et on en déduit que les DC sont isolés — c'est vrai pour l'underlay, faux pour l'EVPN.

Les points opérationnels à ne pas rater

  • gc_thresh1/2/3 remontés sur les gateways, sinon pertes ARP intermittentes sans trace dans les logs
  • ttl 64 sur les interfaces VXLAN — l'underlay fait trois sauts
  • MTU underlay ≥ 1600, idéalement 9000
  • rp_filter=0, l'asymétrie entrée/sortie est la norme
  • nolearning + neigh_suppress on : le plan de contrôle EVPN est la seule source de vérité MAC
  • Route blackhole vers l'agrégat, pour ne jamais faire flapper l'annonce Internet
  • route-map en deny par défaut sur les sessions transit, plus maximum-prefix

Les risques ouverts

Aucune fonction à état sur les bordures. Le chemin retour est indépendant du chemin aller, une bordure ne voit qu'une moitié de chaque flux. Pas de NAT, pas de firewall stateful, pas de conntrack. Si tu en as besoin, ça vit sur l'hyperviseur.

Isolation intra-subnet public. Un /24 public est un domaine de broadcast partagé entre clients différents : ARP spoofing et interception entre voisins. Il faut qu'une VM ne puisse joindre que la MAC de la gateway — ARP suppression sur le VTEP hyperviseur plus binding MAC/IP par port virtuel. À concevoir maintenant, le rétrofit sur un plan public en production est douloureux.

BCP38 au port virtuel. La bordure ne peut pas distinguer une VM qui usurpe l'IP d'une autre dans le même VNI. L'anti-spoofing n'a de valeur qu'à l'hyperviseur, sur le couple MAC/IP alloué.

maximum-prefix sur les sessions clients des RR. Un host qui part en boucle et injecte des type-2 en masse sature les deux RR actifs simultanément et emporte l'overlay des deux DC. Aucune redondance de RR ne protège de ça. C'est le scénario que je testerais en priorité.

Domaine de défaillance L2 inter-DC. Tu l'as accepté explicitement, mais il doit figurer dans le dossier d'architecture comme un risque assumé et non comme un oubli.

🛡️ Garde-fou Voltalis

  • Niveau : Enterprise Product
  • Risques repérés : infrastructure exposée à Internet ; domaine de défaillance L2 étendu à plusieurs DC ; plan de contrôle EVPN global sans frontière de DC ; isolation inter-clients sur subnet public partagé ; anti-spoofing impossible en bordure ; RR sur cluster Pacemaker avec risque de split-brain ; filtrage BGP transit dont une erreur transforme l'AS en transit ouvert
  • Comité IA : requis — architecture structurante cadrée avec assistance IA
  • Avant déploiement : revue de sécurité formelle sur le plan d'adressage, la politique de filtrage BGP et l'isolation tenants ; validation en lab de local-as/iBGP, du comportement anycast gateway et du fencing Pacemaker sur tes versions exactes ; aucune configuration à appliquer en production sans revue humaine. Versionner sur le GitLab vibecoding et tracer l'usage de l'IA dans le cadrage.

Si un arbitrage reste ambigu — notamment le stretch L2 inter-DC — Samy Denno pour le Comité IA, ou securite@voltalis.com pour la revue sécurité.

# Synthèse — architecture réseau opérateur de VMs ## Le design retenu Un plan **underlay** hiérarchique en eBGP, et un plan **overlay** EVPN-VXLAN en iBGP, indépendants l'un de l'autre. L'espace public est ancré aux routeurs de bordure, qui en sont la gateway. Chaque subnet public est un VNI L2 étendu jusqu'aux hosts, y compris entre DC — ce qui permet à n'importe quelle VM d'obtenir n'importe quelle IP du pool, où qu'elle tourne. C'est le besoin structurant que tu as confirmé comme non négociable. **Plan d'ASN :** | Élément | ASN global | Sessions | |---|---|---| | Bordures | AS public | eBGP transit natif, `local-as` overlay vers les RR | | Backbone | privé, un par DC | eBGP underlay | | Cluster | privé, un par cluster/DC | eBGP underlay, `local-as` overlay vers les RR (VTEP) | | Hosts | — | iBGP overlay | | RR | ASN overlay | iBGP, clients = hosts, bordures, clusters | Le sens du `local-as` compte : ASN global = ASN public sur les bordures, artifice sur les sessions internes. Les sessions exposées à Internet restent natives, donc AS_PATH, ROA et objets IRR cohérents sans manipulation. À valider en lab que `local-as` produit bien une session iBGP sur tes versions exactes — certaines plateformes déterminent le type de session avant d'appliquer `local-as`, ce qui casserait la préservation du next-hop et donc l'EVPN. ## Ce qui a été tranché en chemin **Ta question initiale — trop de routes ?** Non, et structurellement pas. Les subnets publics ne remontent pas vers la bordure, ils sont dessus : vers Internet, seuls les agrégats sortent. Découper un /19 en /24 ou en /28 ne change rien au routage. Ce qui scale, c'est le nombre de VMs (une type-2 MAC + une MAC/IP + une entrée ARP par VM), pas le nombre de subnets. **Keepalived → gateway anycast.** Même IP et même MAC de bridge sur les deux bordures, avec `advertise-default-gw`. Tu évites le trombonnement de bascule, le MAC mobility à chaque événement, et surtout le risque qu'une VM cliente émette du VRRP en priorité 255 et devienne la gateway du subnet. La sélection du VTEP côté host est déterministe, donc sans ESI tu auras probablement une seule bordure utilisée — bascule propre, mais pas de répartition. À vérifier avec `bridge fdb show`. **iBGP + RR plutôt qu'eBGP pour l'EVPN.** Ta config précédente était déjà en iBGP (`remote-as` = ASN local). L'eBGP pour l'EVPN reste faisable mais expose deux pièges silencieux : les route targets auto-dérivés en `AS:VNI` qui ne concordent plus quand les ASN diffèrent, et le next-hop qui doit rester celui du VTEP d'origine. **RR : deux VIP Pacemaker sur deux groupes de trois.** Ton montage corrigé répond à l'objection — aucun événement unique ne casse les deux sessions. Je reste convaincu que six loopbacks fixes seraient plus simples (pas de fencing, pas de split-brain, pas d'ordonnancement VIP/FRR, et les six nœuds vérifiés en continu), mais c'est viable si le fencing est réel et testé, les groupes séparés physiquement, et l'ordre VIP→FRR explicite ou `ip_nonlocal_bind` posé. **Multi-DC.** eBGP entre DC pour l'underlay, mais l'overlay reste un domaine iBGP unique traversant tous les DC. Conséquence contre-intuitive à documenter : on lit un ASN par DC et on en déduit que les DC sont isolés — c'est vrai pour l'underlay, faux pour l'EVPN. ## Les points opérationnels à ne pas rater - `gc_thresh1/2/3` remontés sur les gateways, sinon pertes ARP intermittentes sans trace dans les logs - `ttl 64` sur les interfaces VXLAN — l'underlay fait trois sauts - MTU underlay ≥ 1600, idéalement 9000 - `rp_filter=0`, l'asymétrie entrée/sortie est la norme - `nolearning` + `neigh_suppress on` : le plan de contrôle EVPN est la seule source de vérité MAC - Route `blackhole` vers l'agrégat, pour ne jamais faire flapper l'annonce Internet - `route-map` en deny par défaut sur les sessions transit, plus `maximum-prefix` ## Les risques ouverts **Aucune fonction à état sur les bordures.** Le chemin retour est indépendant du chemin aller, une bordure ne voit qu'une moitié de chaque flux. Pas de NAT, pas de firewall stateful, pas de conntrack. Si tu en as besoin, ça vit sur l'hyperviseur. **Isolation intra-subnet public.** Un /24 public est un domaine de broadcast partagé entre clients différents : ARP spoofing et interception entre voisins. Il faut qu'une VM ne puisse joindre que la MAC de la gateway — ARP suppression sur le VTEP hyperviseur plus binding MAC/IP par port virtuel. À concevoir maintenant, le rétrofit sur un plan public en production est douloureux. **BCP38 au port virtuel.** La bordure ne peut pas distinguer une VM qui usurpe l'IP d'une autre dans le même VNI. L'anti-spoofing n'a de valeur qu'à l'hyperviseur, sur le couple MAC/IP alloué. **`maximum-prefix` sur les sessions clients des RR.** Un host qui part en boucle et injecte des type-2 en masse sature les deux RR actifs simultanément et emporte l'overlay des deux DC. Aucune redondance de RR ne protège de ça. C'est le scénario que je testerais en priorité. **Domaine de défaillance L2 inter-DC.** Tu l'as accepté explicitement, mais il doit figurer dans le dossier d'architecture comme un risque assumé et non comme un oubli. 🛡️ **Garde-fou Voltalis** - Niveau : Enterprise Product - Risques repérés : infrastructure exposée à Internet ; domaine de défaillance L2 étendu à plusieurs DC ; plan de contrôle EVPN global sans frontière de DC ; isolation inter-clients sur subnet public partagé ; anti-spoofing impossible en bordure ; RR sur cluster Pacemaker avec risque de split-brain ; filtrage BGP transit dont une erreur transforme l'AS en transit ouvert - Comité IA : requis — architecture structurante cadrée avec assistance IA - Avant déploiement : revue de sécurité formelle sur le plan d'adressage, la politique de filtrage BGP et l'isolation tenants ; validation en lab de `local-as`/iBGP, du comportement anycast gateway et du fencing Pacemaker sur tes versions exactes ; aucune configuration à appliquer en production sans revue humaine. Versionner sur le [GitLab vibecoding](https://vibelab.voltalis.com/) et tracer l'usage de l'IA dans le cadrage. Si un arbitrage reste ambigu — notamment le stretch L2 inter-DC — Samy Denno pour le Comité IA, ou securite@voltalis.com pour la revue sécurité.
Author
Owner

Une première brique a été posée pendant le travail sur #34, côté DHCP et API uniquement. Rien de l'architecture décrite ici n'est entamé ; il s'agit seulement de rendre le routage exprimable.

Ce qui existe déjà

  • Champ gateway optionnel sur POST /subnets, stocké en subnet/<name>/gateway, exposé dans la réponse. Non validé par l'agent : joignabilité et cohérence avec le CIDR relèvent de l'appelant.
  • default_route change de sens : une route par défaut est désormais toujours annoncée, et ce drapeau ne choisit que son next-hop — interface_ip par défaut, sinon la gateway fournie ou celle déduite de l'host.
  • La route vers le CIDR du VPC garde interface_ip comme next-hop dans tous les modes sauf bridge. C'est la contrainte structurante pour les IP publiques : le trafic vers les plages internes ne doit jamais sortir par la gateway publique.
  • Mode public_ip accepté par l'API et par la sélection des routes DHCP. La mise en place réseau côté host n'existe pas : créer un tel subnet échoue explicitement sur host network setup is not implemented yet, plutôt que de laisser une ressource à moitié configurée.
  • La logique de routage est isolée dans une fonction pure (dhcpRouting), testée pour les quatre combinaisons mode × default_route × gateway, y compris public_ip.

Reste entièrement à faire : veth, adressage, NAT, et tout le plan underlay/overlay décrit dans ce ticket.

Une première brique a été posée pendant le travail sur #34, côté DHCP et API uniquement. Rien de l'architecture décrite ici n'est entamé ; il s'agit seulement de rendre le routage exprimable. **Ce qui existe déjà** - Champ `gateway` optionnel sur `POST /subnets`, stocké en `subnet/<name>/gateway`, exposé dans la réponse. Non validé par l'agent : joignabilité et cohérence avec le CIDR relèvent de l'appelant. - `default_route` change de sens : une route par défaut est désormais **toujours** annoncée, et ce drapeau ne choisit que son next-hop — `interface_ip` par défaut, sinon la `gateway` fournie ou celle déduite de l'host. - **La route vers le CIDR du VPC garde `interface_ip` comme next-hop dans tous les modes sauf `bridge`.** C'est la contrainte structurante pour les IP publiques : le trafic vers les plages internes ne doit jamais sortir par la gateway publique. - Mode `public_ip` accepté par l'API et par la sélection des routes DHCP. **La mise en place réseau côté host n'existe pas** : créer un tel subnet échoue explicitement sur `host network setup is not implemented yet`, plutôt que de laisser une ressource à moitié configurée. - La logique de routage est isolée dans une fonction pure (`dhcpRouting`), testée pour les quatre combinaisons mode × `default_route` × `gateway`, y compris `public_ip`. **Reste entièrement à faire** : veth, adressage, NAT, et tout le plan underlay/overlay décrit dans ce ticket.
Author
Owner

top

top
Author
Owner

Vérification en lab #50 — 2026-10-04

La vérification restante du champ gateway (prévue à la main sur lab3) est faite sur le lab
multi-nœud de #50, scénario s2-gateway, release 0.2.0rc003, guests Debian 12
(systemd-networkd) :

Subnet Route par défaut Route vers le CIDR du VPC /32 vers les métadonnées
sans default_route via interface_ip via interface_ip via interface_ip
default_route: true, gateway fournie via la gateway via interface_ip (pas via la gateway) via interface_ip
sans default_route, après suppression et recréation du subnet via interface_ip via interface_ip via interface_ip

22 vérifications sur 22. Le mode public_ip lui-même n'est pas testé : sa mise en place côté hôte
n'existe pas encore (cf. commentaire précédent).

## Vérification en lab #50 — 2026-10-04 La vérification restante du champ `gateway` (prévue à la main sur lab3) est faite sur le lab multi-nœud de #50, scénario `s2-gateway`, release `0.2.0rc003`, guests Debian 12 (systemd-networkd) : | Subnet | Route par défaut | Route vers le CIDR du VPC | `/32` vers les métadonnées | |---|---|---|---| | sans `default_route` | via `interface_ip` | via `interface_ip` | via `interface_ip` | | `default_route: true`, `gateway` fournie | **via la `gateway`** | via `interface_ip` (pas via la gateway) | via `interface_ip` | | sans `default_route`, après suppression et recréation du subnet | via `interface_ip` | via `interface_ip` | via `interface_ip` | 22 vérifications sur 22. Le mode `public_ip` lui-même n'est pas testé : sa mise en place côté hôte n'existe pas encore (cf. commentaire précédent).
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
syonad/two#31
No description provided.