babel-tester/README.md

9.5 KiB

Babel Tester

Ce script permet de simuler un petit réseau de quelques nœuds et d'exécuter babeld afin d'étudier son comportement.

Le but est avant tout de modéliser le comportement d'un réseau dans le cas de pare-feux restrictifs, bloquant par exemple de gros traffics ou certains ports, et de réfléchir à une façon de calculer une route en tenant compte de ces comportements.

Pour cela, on utilise la notion de namespaces introduite dans la version 3.8 du noyau Linux, qui permet d'avoir des espaces séparés avec différentes configurations système, en particulier différentes configurations réseau. On construit donc différents namespaces permettant de simuler plusieurs routeurs avec différentes configurations au sein de sa même machine.

Démo

Dans cet exemple, on construit le réseau suivant :

                               EXT
                                |
                                |
                             +------+
                             |NŒUD 1|
                             +------+
                            /        \
                         1 /          \1
                          /            \
                         /              \
                 +------+      1,2       +------+
                 |NŒUD 2|----------------|NŒUD 3|
                 +------+                +------+
                         \              /
                          \            /
                          2\          /2
                            \        /
                             +------+
                             |NŒUD 4|
                             +------+

4 nœuds sont créés et connectés dans 2 sous-réseaux différents : le premier englobe les 3 premiers nœuds et le second les trois derniers. De plus, le premier nœud est connecté à la machine hôte qui sait router vers l'extérieur. Elle dispose d'une route par défaut vers la machine hôte.

On peut représenter plus en détails le réseau avec les différentes interfaces connectées et leurs IP :

                               EXT
                        0.0.0.0/0 (default)
                          ::/0 (default)
                                |
                                |
              +-----------------+
              |
              |
             eth0                                vde0
       172.16.43.152/24--------HÔTE-----------10.2.1.1/30
2a0c:700:3012:3:4000:ff:fe01:5243      2a0c:700:3012:3::ff:0/127
                                                  |
                                                  |
              +-----------------------------------+
              |
              |
             vde0                                vde1
          10.2.1.2/30---------NŒUD 1---------172.17.1.1/32-------+
   2a0c:700:3012:3::ff:1/127            2a0c:700:3012:3::1:1/128 |
                                                                 |
                                                                 |
                                                                 |
             vde2                                vde1            |
+-------172.17.2.2/32---------NŒUD 2---------172.17.1.2/32-------+
| 2a0c:700:3012:3::2:2/128              2a0c:700:3012:3::1:2/128 |
|                                                                |
|                                                                |
|                                                                |
|            vde2                                vde1            |
+-------172.17.2.3/32---------NŒUD 3---------172.17.1.3/32-------+
| 2a0c:700:3012:3::2:3/128              2a0c:700:3012:3::1:3/128
|              
|              
|              
|            vde2
+-------172.17.2.4/32---------NŒUD 4
  2a0c:700:3012:3::2:4/128

Les IPv6 de lien local n'ont pas été représentées, mais elles existent bien sûr sur chacune des interfaces, et ont leur pleine importance dans le calcul des routes.

Une fois les nœuds et interfaces configurés, babeld est lancé sur chacune des interfaces, afin de calculer les différentes routes. Le nœud 1 expose de plus les routes qu'il connaît pour les communiquer à ses voisins, via l'option redistribute metric 256.

Afin de modéliser les problèmes sur le réseau, un pare-feu peut-être installé sur le nœud 2 ou le nœud 3 afin d'intercepter une partie du trafic. Dans cet exemple, un pare-feu est présent bloquant toutes les requêtes de type 80/TCP.

Pour faciliter les communications avec l'extérieur, des règles de NAT en IPv4 sont définies au niveau de la machine hôte.

Lancer la démonstration

Le script est conçu pour être exécuté avec des dépendances minimales :

  • babeld
  • nftables (pour le pare-feu)
  • tmux (pour la gestion des namespaces)
  • vdeplug (>= 4.0) (pour la gestion des interfaces virtuelles)

Le script est testé sous Debian Bullseye et Arch Linux, le résultat n'est pas garanti sur d'autres distributions.

/!\ Les IP sont pour le moment hardcodées dans le script. Si en
IPv4 le NAT permet d'avoir une configuration plus ou moins
indépendante de votre réseau, vous devez avoir une bonne
configuration de routage vers l'extérieur en IPv6, par exemple
à l'aide d'une délégation de préfixe qui pointent vers la machine
hôte. Ici, les préfixes 2a0c:700:3012:3::1:0/112,
2a0c:700:3012:3::2:0/112 et 2a0c:700:3012:3::ff:0/112 sont
délégués.

La machine hôte doit ensuite connaître les routes en IPv4 et en IPv6 vers le reste du réseau en passant par le premier nœud. Cela pourrait se faire simplement en ajoutant la machine hôte au réseau babel, afin de connaître toutes les routes. Afin de limiter le réseau Babel aux namespaces virtuels, et de n'utiliser la machine hôte qu'en guise de passerelle entre le réseau Babel de test et le monde extérieur, le choix a été fait d'ajouter les routes vers le réseau Babel à la main, en IPv4 et en IPv6. Les routes de la machine hôte vers les nœuds virtuels sont gérés directement par le script, ne manque qu'à router les bons préfixes vers cette machine.

Vous devez ensuite configurer votre hôte pour router les paquets IPv4 et IPv6. Pour cela, créez si ce n'est pas déjà fait un fichier /etc/sysctl.d/99-forward.conf dans lequel vous rentrez les options :

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

La configuration peut être rechargée via sudo sysctl --system. Pour uniquement tester sans rendre la configuration persistante, executez simplement :

$ sudo sysctl -w net.ipv4.ip_forward=1
$ sudo sysctl -w net.ipv6.conf.all.forwarding=1

L'exemple peut désormais être lancé, en tant de root afin de pouvoir configurer la sortie vers l'extérieur :

$ sudo ./start.sh

Un terminal tmux va ensuite s'ouvrir. Dans l'onglet principal, vous serez dans le namespace principal, rien a changé. Une interface virtuelle vde0 a toutefois été ajoutée, permettant de communiquer avec les namespaces.

4 onglets tmux font sinon leur apparition, correspondant à chacun des namespaces. Leurs interfaces sont décrites selon le schéma présenté ci-dessus. Les IP sont ajoutées automatiquement par le script, manuellement. Afin de laisser babeld faire son travail, les IP sont volontairement mises dans un /32 ou un /128, afin de ne communiquer exclusivement par les IP de lien local. La configuration de babeld est montée dans /etc/babeld.conf, et le fichier de logs reste monté dans /var/log/babeld.log.

Une fois les namespaces créés et les interfaces configurées, babeld est lancé sur chacun des namespaces. Quelques secondes plus tard, les routes apparaîtront dans chacun des namespaces.

Pour mettre le trafic IPv4 de sortir, une règle NAT basique est appliquée au niveau de la machine hôte grâce à nftables, voir firewall/nat.conf.

Pour modéliser les restrictions au niveau du réseau, un pare-feu est également chargé au niveau des nœuds 2 et 3, interdisant le trafic HTTP uniquement (port 80/TCP). À terme, seul un seul des nœud bloquera le trafic, qui sera le nœud privilégié presque sûrement par Babel.

Pour tester, dans le namespace 4 :

$ ip r
default via 172.17.2.2 dev vde2 proto babel onlink 
10.2.1.0/30 via 172.17.2.2 dev vde2 proto babel onlink 
10.2.1.2 via 172.17.2.2 dev vde2 proto babel onlink 
172.17.1.1 via 172.17.2.2 dev vde2 proto babel onlink 
172.17.1.2 via 172.17.2.3 dev vde2 proto babel onlink 
172.17.1.3 via 172.17.2.3 dev vde2 proto babel onlink 
172.17.2.2 via 172.17.2.3 dev vde2 proto babel onlink 
172.17.2.3 via 172.17.2.3 dev vde2 proto babel onlink 

$ ping crans.org -c 1
PING  (185.230.79.10) 56(84) octets de données.
64 octets de hodaur.crans.org (185.230.79.10) : icmp_seq=1 ttl=52
temps=21.0 ms

--- statistiques ping  ---
1 paquets transmis, 1 reçus, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 21.001/21.001/21.001/0.000 ms

$ curl http://crans.org
curl: (7) Failed to connect to crans.org port 80: Connexion refusée

$ curl https://crans.org
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>

On constate donc que le namespace 4 sait sortir, en passant soit par le nœud 2 soit le nœud 3, peut effectuer par exemple des requêtes HTTPS mais pas de requête HTTP.