Phase 6 (bonus) : bird-lab, BGP+BFD entre namespaces (rtnetlink/Bird)
- Topologie en étoile : racine (AS 65000) en transit entre bird-a (AS 65010) et bird-b (AS 65011), namespaces créés par tripoli-netctl (Phase 4). Chaque feuille origine une route factice, jamais installée dans la table de routage réelle (export none partout) - labo pédagogique, ne pilote aucun trafic de production. - Vérifié en conditions réelles : sessions BGP Established dans les deux sens, route de bird-b vue par bird-a avec next-hop = racine (transit confirmé, pas un peering direct), sessions BFD Up (200ms/200ms), coupure de lien détectée en < 5ms. - Découverte : les namespaces n'ont aucun pare-feu propre, mais ufw côté racine bloquait le retour des paquets BFD (chaque bout envoie indépendamment, conntrack ne le reconnaît pas comme un flux BGP/TCP existant) - même schéma que Caddy -> tripoli-edge en Phase 2. Règle ufw ajoutée par run.sh, retirée par teardown.sh : rien de permanent. - Pas de service systemd : labo lancé, vérifié, puis proprement démonté (processus Bird, namespaces et règle ufw temporaire tous supprimés). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
db306433d5
commit
7802c59931
7 changed files with 269 additions and 1 deletions
|
|
@ -33,7 +33,7 @@ tenté, non simulé.
|
||||||
| `tripoli-api` (Rust, Phase 3) | Fait et déployé en prod — `tripoli-api/`, auth par session (Argon2), upload/download, PostgreSQL dédié (Docker), vérifié via `https://tripoli.cloud/api/...` |
|
| `tripoli-api` (Rust, Phase 3) | Fait et déployé en prod — `tripoli-api/`, auth par session (Argon2), upload/download, PostgreSQL dédié (Docker), vérifié via `https://tripoli.cloud/api/...` |
|
||||||
| `tripoli-netctl` (Rust, Phase 4) | Fait — `tripoli-netctl/`, labo pédagogique (netns + veth via `rtnetlink`), testé sur le serveur (création, ping traversant la veth, destruction propre), **volontairement pas branché sur le trafic de prod** |
|
| `tripoli-netctl` (Rust, Phase 4) | Fait — `tripoli-netctl/`, labo pédagogique (netns + veth via `rtnetlink`), testé sur le serveur (création, ping traversant la veth, destruction propre), **volontairement pas branché sur le trafic de prod** |
|
||||||
| Observabilité (Phase 5) | Fait — pas de stack dédiée (réutilise le Prometheus/Grafana partagé existant), scrape tripoli-edge + alertes (down, disque) + dashboard versionné (`monitoring/`), vérifié via l'API Prometheus/Grafana |
|
| Observabilité (Phase 5) | Fait — pas de stack dédiée (réutilise le Prometheus/Grafana partagé existant), scrape tripoli-edge + alertes (down, disque) + dashboard versionné (`monitoring/`), vérifié via l'API Prometheus/Grafana |
|
||||||
| Bird/BGP (Phase 6, bonus) | Pas commencé |
|
| Bird/BGP (Phase 6, bonus) | Fait — `bird-lab/`, BGP+BFD entre 2 namespaces via la racine en transit (AS 65000/65010/65011), vérifié (sessions Established, BFD Up, propagation de route, détection de panne sur coupure de lien), puis proprement démonté |
|
||||||
|
|
||||||
## Dépôt
|
## Dépôt
|
||||||
|
|
||||||
|
|
|
||||||
82
bird-lab/README.md
Normal file
82
bird-lab/README.md
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
# bird-lab (Phase 6, bonus)
|
||||||
|
|
||||||
|
Labo pédagogique un-seul-poste : BGP + BFD entre les network namespaces
|
||||||
|
créés par `tripoli-netctl` (Phase 4). **Ne pilote aucun trafic de
|
||||||
|
production** - tripoli-edge et tripoli-api continuent de tourner
|
||||||
|
nativement sur l'hôte, dans le namespace racine, complètement en dehors
|
||||||
|
de ce labo. Rien de ce qui est appris ici n'est installé dans la table
|
||||||
|
de routage réelle du noyau (`export none;` dans chaque config Bird).
|
||||||
|
|
||||||
|
## Topologie
|
||||||
|
|
||||||
|
Une étoile, pas un maillage complet : le namespace racine (AS 65000)
|
||||||
|
sert de transit entre deux namespaces "feuilles" qui ne se parlent
|
||||||
|
jamais directement.
|
||||||
|
|
||||||
|
```
|
||||||
|
namespace bird-a (AS 65010) namespace bird-b (AS 65011)
|
||||||
|
origine 10.99.10.0/24 origine 10.99.11.0/24
|
||||||
|
10.200.10.2 10.200.11.2
|
||||||
|
| |
|
||||||
|
| veth (tripoli-netctl) | veth (tripoli-netctl)
|
||||||
|
| |
|
||||||
|
10.200.10.1 10.200.11.1
|
||||||
|
+---------------------------------------------+
|
||||||
|
| namespace racine (AS 65000) |
|
||||||
|
| BGP+BFD vers bird-a BGP+BFD vers bird-b |
|
||||||
|
+---------------------------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
Chaque namespace "feuille" origine une route factice
|
||||||
|
(`10.99.1x.0/24 blackhole`, juste pour avoir quelque chose de concret à
|
||||||
|
observer traverser le labo) ; le namespace racine la réapprend par BGP
|
||||||
|
et la réexporte vers l'autre feuille - démontrant un vrai comportement
|
||||||
|
de transit eBGP, pas un simple peering point à point.
|
||||||
|
|
||||||
|
## Ce qui a été vérifié
|
||||||
|
|
||||||
|
- **Sessions BGP établies** dans les deux sens (`Established`) après
|
||||||
|
démarrage des trois instances Bird.
|
||||||
|
- **Propagation de route à travers le transit** : `bird-a` voit
|
||||||
|
`10.99.11.0/24` appris via `AS65011i` avec next-hop `10.200.10.1`
|
||||||
|
(l'adresse du namespace racine, pas celle de bird-b - la route a bien
|
||||||
|
transité par le hub) ; symétriquement pour `bird-b`.
|
||||||
|
- **Sessions BFD `Up`**, intervalle 200ms.
|
||||||
|
- **Détection de panne** : `ip link set tv-birdah down` fait passer la
|
||||||
|
session BGP correspondante en `Idle` en moins de 5ms - avant même que
|
||||||
|
le timer BFD (600ms-1s) n'ait eu besoin de se déclencher, Bird réagit
|
||||||
|
à l'événement netlink d'interface directement. Le vrai apport de BFD
|
||||||
|
se voit sur une panne "silencieuse" (lien physique up, mais plus de
|
||||||
|
paquets) - non isolé précisément dans cette passe, faute de temps ;
|
||||||
|
la mécanique (sessions BFD `Up`, intervalles sous la seconde) est en
|
||||||
|
place et vérifiée, la détection de ce cas précis reste à chronométrer
|
||||||
|
séparément.
|
||||||
|
|
||||||
|
## Découverte : ufw bloque le retour BFD
|
||||||
|
|
||||||
|
Les namespaces `bird-a`/`bird-b` n'ont aucune règle de pare-feu (leur
|
||||||
|
netfilter est vierge - seul le namespace racine a `ufw`). Pourtant,
|
||||||
|
leurs paquets BFD sortants se faisaient bloquer en arrivant côté racine :
|
||||||
|
contrairement à BGP (TCP, donc suivi par conntrack - le retour d'une
|
||||||
|
connexion initiée est autorisé automatiquement), chaque bout de BFD
|
||||||
|
envoie indépendamment depuis son propre port éphémère vers le port 3784
|
||||||
|
de l'autre. Du point de vue de conntrack côté racine, le paquet BFD émis
|
||||||
|
par `bird-a` n'est le retour d'aucun flux connu : `ufw` le traite comme
|
||||||
|
une connexion entrante neuve et le rejette par défaut. Il a fallu une
|
||||||
|
règle explicite (`ufw allow from 10.200.0.0/16 to any port 3784 proto
|
||||||
|
udp`), ajoutée par `run.sh` et retirée par `teardown.sh` - exactement le
|
||||||
|
même schéma que la règle ajoutée en Phase 2 pour laisser Caddy joindre
|
||||||
|
tripoli-edge.
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./run.sh # crée les namespaces, démarre Bird, affiche l'état
|
||||||
|
sudo ./teardown.sh # arrête tout, détruit les namespaces, retire la règle ufw temporaire
|
||||||
|
```
|
||||||
|
|
||||||
|
Volontairement pas de service systemd permanent : faire tourner ce labo
|
||||||
|
en continu sur un serveur de production partagé n'apporterait rien de
|
||||||
|
plus pédagogiquement, juste de la RAM utilisée pour rien. Vérifié dans
|
||||||
|
cette session, puis proprement démonté (namespaces, processus Bird et
|
||||||
|
règle ufw temporaire tous supprimés).
|
||||||
35
bird-lab/config/bird-a.conf
Normal file
35
bird-lab/config/bird-a.conf
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
router id 10.200.10.2;
|
||||||
|
log "/var/log/bird-lab/bird-a.log" all;
|
||||||
|
|
||||||
|
protocol device {
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol kernel {
|
||||||
|
ipv4 {
|
||||||
|
export none;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
# Réseau fictif "originé" par ce namespace, pour avoir quelque chose de
|
||||||
|
# concret à observer traverser le labo par BGP.
|
||||||
|
protocol static local_net {
|
||||||
|
ipv4;
|
||||||
|
route 10.99.10.0/24 blackhole;
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol bfd {
|
||||||
|
interface "*" {
|
||||||
|
min rx interval 200ms;
|
||||||
|
min tx interval 200ms;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol bgp to_root {
|
||||||
|
local 10.200.10.2 as 65010;
|
||||||
|
neighbor 10.200.10.1 as 65000;
|
||||||
|
bfd on;
|
||||||
|
ipv4 {
|
||||||
|
import all;
|
||||||
|
export all;
|
||||||
|
};
|
||||||
|
}
|
||||||
33
bird-lab/config/bird-b.conf
Normal file
33
bird-lab/config/bird-b.conf
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
router id 10.200.11.2;
|
||||||
|
log "/var/log/bird-lab/bird-b.log" all;
|
||||||
|
|
||||||
|
protocol device {
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol kernel {
|
||||||
|
ipv4 {
|
||||||
|
export none;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol static local_net {
|
||||||
|
ipv4;
|
||||||
|
route 10.99.11.0/24 blackhole;
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol bfd {
|
||||||
|
interface "*" {
|
||||||
|
min rx interval 200ms;
|
||||||
|
min tx interval 200ms;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol bgp to_root {
|
||||||
|
local 10.200.11.2 as 65011;
|
||||||
|
neighbor 10.200.11.1 as 65000;
|
||||||
|
bfd on;
|
||||||
|
ipv4 {
|
||||||
|
import all;
|
||||||
|
export all;
|
||||||
|
};
|
||||||
|
}
|
||||||
45
bird-lab/config/root.conf
Normal file
45
bird-lab/config/root.conf
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
router id 10.200.10.1;
|
||||||
|
log "/var/log/bird-lab/root.log" all;
|
||||||
|
|
||||||
|
protocol device {
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol direct {
|
||||||
|
interface "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rien n'est installé dans la table de routage réelle du noyau : ce
|
||||||
|
# labo ne doit rien changer au routage effectif de la machine qui sert
|
||||||
|
# tripoli-edge/tripoli-api en production.
|
||||||
|
protocol kernel {
|
||||||
|
ipv4 {
|
||||||
|
export none;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol bfd {
|
||||||
|
interface "*" {
|
||||||
|
min rx interval 200ms;
|
||||||
|
min tx interval 200ms;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol bgp bird_a {
|
||||||
|
local 10.200.10.1 as 65000;
|
||||||
|
neighbor 10.200.10.2 as 65010;
|
||||||
|
bfd on;
|
||||||
|
ipv4 {
|
||||||
|
import all;
|
||||||
|
export all;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol bgp bird_b {
|
||||||
|
local 10.200.11.1 as 65000;
|
||||||
|
neighbor 10.200.11.2 as 65011;
|
||||||
|
bfd on;
|
||||||
|
ipv4 {
|
||||||
|
import all;
|
||||||
|
export all;
|
||||||
|
};
|
||||||
|
}
|
||||||
47
bird-lab/run.sh
Executable file
47
bird-lab/run.sh
Executable file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Labo BGP/BFD un-seul-poste : deux namespaces (bird-a, bird-b) créés par
|
||||||
|
# tripoli-netctl, chacun relié au namespace racine, trois instances Bird
|
||||||
|
# qui échangent des routes par BGP avec BFD pour la détection rapide de
|
||||||
|
# panne. Racine = AS 65000, transit entre bird-a (AS 65010) et bird-b
|
||||||
|
# (AS 65011) - une topologie en étoile, pas un maillage complet.
|
||||||
|
#
|
||||||
|
# À exécuter en root. Ne touche à AUCUN service de production : les
|
||||||
|
# routes échangées ici ne sont jamais installées dans la table de
|
||||||
|
# routage réelle du noyau (voir `export none;` dans chaque config).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
NETCTL=/opt/tripoli-src/target/debug/tripoli-netctl
|
||||||
|
CONFIG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/config" && pwd)"
|
||||||
|
|
||||||
|
mkdir -p /var/log/bird-lab /run/bird-lab /etc/bird-lab
|
||||||
|
cp "$CONFIG_DIR"/*.conf /etc/bird-lab/
|
||||||
|
|
||||||
|
echo "--- création des namespaces (tripoli-netctl) ---"
|
||||||
|
"$NETCTL" create bird-a --subnet-id 10
|
||||||
|
"$NETCTL" create bird-b --subnet-id 11
|
||||||
|
|
||||||
|
# Les namespaces bird-a/bird-b n'ont aucun pare-feu (netfilter y est
|
||||||
|
# vierge - seul le namespace racine a une politique ufw), mais leurs
|
||||||
|
# paquets BFD, une fois arrivés côté racine, ne sont PAS reconnus comme
|
||||||
|
# le retour d'une connexion existante par conntrack (chaque bout envoie
|
||||||
|
# sur son propre port éphémère, ce n'est pas un flux TCP bidirectionnel
|
||||||
|
# comme BGP) : ufw les bloque par défaut, exactement comme il avait
|
||||||
|
# fallu une règle dédiée pour laisser Caddy joindre tripoli-edge en
|
||||||
|
# Phase 2. Règle temporaire, retirée par teardown.sh.
|
||||||
|
ufw allow from 10.200.0.0/16 to any port 3784 proto udp comment 'bird-lab : BFD (labo, temporaire)'
|
||||||
|
|
||||||
|
echo "--- démarrage des instances Bird ---"
|
||||||
|
bird -c /etc/bird-lab/root.conf -s /run/bird-lab/root.ctl
|
||||||
|
ip netns exec bird-a bird -c /etc/bird-lab/bird-a.conf -s /run/bird-lab/bird-a.ctl
|
||||||
|
ip netns exec bird-b bird -c /etc/bird-lab/bird-b.conf -s /run/bird-lab/bird-b.ctl
|
||||||
|
|
||||||
|
sleep 3
|
||||||
|
echo "--- sessions BGP (racine) ---"
|
||||||
|
birdc -s /run/bird-lab/root.ctl show protocols all bird_a
|
||||||
|
birdc -s /run/bird-lab/root.ctl show protocols all bird_b
|
||||||
|
|
||||||
|
echo "--- routes vues par bird-a (doit inclure 10.99.11.0/24, apprise via la racine) ---"
|
||||||
|
birdc -s /run/bird-lab/bird-a.ctl show route
|
||||||
|
|
||||||
|
echo "--- routes vues par bird-b (doit inclure 10.99.10.0/24, apprise via la racine) ---"
|
||||||
|
birdc -s /run/bird-lab/bird-b.ctl show route
|
||||||
26
bird-lab/teardown.sh
Executable file
26
bird-lab/teardown.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Arrête les trois instances Bird et détruit les namespaces du labo.
|
||||||
|
# Volontairement pas de service systemd permanent pour ce labo : le
|
||||||
|
# faire tourner en continu sur un serveur de production partagé n'aurait
|
||||||
|
# aucune valeur pédagogique de plus, juste de la RAM utilisée pour rien.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
NETCTL=/opt/tripoli-src/target/debug/tripoli-netctl
|
||||||
|
|
||||||
|
for ctl in root bird-a bird-b; do
|
||||||
|
if [ -S "/run/bird-lab/$ctl.ctl" ]; then
|
||||||
|
birdc -s "/run/bird-lab/$ctl.ctl" down || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
pkill -f "bird -c /etc/bird-lab" || true
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
"$NETCTL" destroy bird-a || true
|
||||||
|
"$NETCTL" destroy bird-b || true
|
||||||
|
|
||||||
|
ufw delete allow from 10.200.0.0/16 to any port 3784 proto udp || true
|
||||||
|
|
||||||
|
rm -rf /run/bird-lab
|
||||||
|
echo "labo BGP/BFD arrêté et nettoyé"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue