Contents
- Aperçu
- Préparation pour les participant.e.s
- Théorie, concepts et information
- Exercices
- Rétrospective
- Information complémentaire
Note : il est possible que les machines construites avec Vagrant ne correspondent pas au diagramme présenté ici.
Aperçu
Le but de cette formation c'est de s'assurer que les participant.e.s peuvent manipuler les commandes de base par rapport à la configuration du routage d'un serveur linux, et de solidifier quelques concepts de base qui permettent de mieux comprendre ce que les configurations signifient.
Formations préalables
Il n'est pas nécessaire d'avoir suivi d'autres formations pour suivre celle-ci. On présume simplement que les participant.e.s sont à l'aise à utiliser la ligne de commande.
Temps estimé
Selon les connaissances préalables des participant.e.s: de 1h à 2h
Objectifs
On vise dans cette formation à discuter seulement du routage "simple" où on configure des routes manuellement sur une machine linux. En effet, on veut comprendre durant cette session les fondements de l'idée de routage.
- Comprendre comment les réseaux sont structurés et subdivisés sur Internet et comment on calcule le "numéro du réseau" et les adresses dans ce réseau
- Comprendre comment un réseau peut parler à un autre (à l'aide de routes!)
- utiliser les commandes qui permettent la configuration de base et la visualisation du routage
ip addr
ip route
traceroute / mtr
- utiliser des outils pour tester et visualiser le trafic réseau
ping - vérifier qu'un host est rejoignable
bmon - voir le débit réseau en terme de nombres de paquets par seconde et de qté de données par seconde
iftop - autre outil pour voir le débit réseau. la présentation montre des barres de trafic par combinaison d'IP et port destination
tcpdump - outil qui permet de voir une trace de tous les paquets réseau qui passent par une interface réseau
Préparation pour les participant.e.s
Demander à tous.tes les participant.e.s de faire une préparation des outils nécessaires avant la formation: ça accélère la formation puisqu'on peut commencer les exercices directement.
Notez qu'on peut reproduire le setup d'exercices ailleurs dans l'absence des outils si quelques personnes n'ont pas accès au "control-repository" puppet de Koumbit, mais il faudra à ce moment là préparer une façon de reproduire la topologie de réseaux:
rtr0 est une VM interposée entre deux réseaux différents
rtr_client et rtr_upstream0 sont chacune une machine connectée à un des deux sous-réseau (différent pour chaque).
- les adresses IP des VMs sont pré-configurées
aucune configuration de routage n'est faite: donc au début des exercices on s'attend à ce que rtr_client ne soit pas capable de rejoindre rtr_upstream0 et de même dans le sens inverse.
Outils nécessaires pour rouler les exercices de la formation: dans le control-repository puppet, on vise utiliser les VMs (rtr_client, rtr0, et rtr_upstream0) déjà décrites dans le fichier Vagrantfile qu'on démarera à l'aide de vagrant et libvirt avec KVM comme outil de virtualisation (commandes plus bas). Voir Vagrant pour la mise en place du setup de machines virtuelles.
A faire pour se préparer aux exercices:
- démarer les VMs:
vagrant up --no-provision rtr_client
vagrant up --no-provision rtr0
vagrant up --no-provision rtr_upstream0
sur chaque VM, se connecter en ssh avec vagrant ssh $nom_de_vm puis:
installer les outils nécessaires: sudo apt update; sudo apt install tmux tcpdump iperf oping bmon netcat iftop mtr-tiny
retirer la route par défaut insérée par vagrant: sudo ip r del default via 192.168.121.1 dev eth0
Important: les commandes de préparation plus haut doivent être relancées si vous faites un shutdown des VMs ou encore si vous les détruisez. Donc 10 à 15 minutes avant la formation, assurez-vous de relancer les commandes plus haut si c'est nécessaire.
Si vos VMs restent "up" tout le long jusqu'au début de la formation, ce ne sera pas nécessaire de les relancer.
Faites la préparation un ou plusieurs jours avant la formation: ça vous assure que vous aurez trois VMs configurées correctement pour commencer les exercices et du temps pour débugger le setup si vagrant ou d'autre chose ne fonctionne pas bien.
En fait, rien ne vous empêche de commencer les exercices par vous-même avant la formation!
Si vous avez commencé les exercices avant la formation et que vous voulez revenir au point de départ pour suivre les exercices en même temps que tout le monde durant la formation, un truc c'est de faire vagrant shutdown des trois VMs, et relancer les commandes de préparation plus haut juste avant la formation.
NB: pendant les exercices sur les VMs vagrant du control repository puppet: on ne veut pas utiliser les hostnames des machines pour les tests: vagrant nous joue un tour, le snoro -- on veut utiliser les IPs directes qui correspondent aux interfaces de la topologie de test.
NB: quand vous utilisez tcpdump dans les VMs, pensez à toujours utiliser les paramètres -i ethX pour être sur la bonne interface réseau (déterminer le X selon l'output des commandes qu'on utilisera pendant les exercices)
NB: l'interface par défaut, eth0, sur les VMs c'est l'interface de "contrôle" de vagrant, ce qui n'est pas utile pour nos tests. On veut donc ignorer eth0.
NB: durant les exercices, vous pouvez utiliser tmux sur les VMs pour pouvoir avoir tcpdump qui continue de rouler en permanence (p-e deux tcpdump sur deux interfaces réseau différentes!) et continuer de pouvoir lancer des commandes pour changer la configuration.
Théorie, concepts et information
On prend de 30 minutes à 1h pour parler des objectifs suivant et expliquer quelques concepts plus "théoriques":
TL;DR le routage c'est:
- routage == transmission de paquets d'un sous-réseau à un autre
si on veut communiquer avec une adresse qui est dans le même sous-réseau que nous, on peut alors communiquer directement (donc pas besoin de routage) -- on est sur le même réseau local.
dès qu'on veut parler à une adresse IP qui n'est pas dans le même sous-réseau que nous, on ne s'adresse plus à un réseau local et il faut alors absolument passer par l'entremise d'un routeur (e.g. pour "router"/transmettre nos communications vers une autre sous-réseau)
- Le routage simple n'est généralement pas géré par un "service" comme apache ou mysql, mais plutôt par le kernel Linux directement
- une route, c'est en fait une structure d'information qui dit au kernel où envoyer des paquets pour pouvoir rejoindre certains réseaux.
- trois types de routes:
route par défaut: comment rejoindre tous les réseaux pour lesquels il n'existe pas de route statique sur la machine
route pour un réseau local: on peut simplement envoyer qqch sur le fil réseau et directement rejoindre une autre machine qui est dans ce sous-réseau. par contre il faut que le kernel sache sur quelle interface réseau envoyer le trafic, et donc ça nous prend une route pour indiquer ça au kernel.
route vers un réseau qui n'est pas local: si on veut rejoindre un réseau qui n'est pas local (donc pas rejoignable directement sur le fil branché dans notre interface réseau), on doit absolument passer par un routeur
Le modèle OSI
Le modèle OSI est un modèle conceptuel utilisé pour représenter différentes couches d'opération dans "la stack réseau". Dans les deux images qui suivent, l'ordinateur envoyeur est à gauche et l'ordinateur destinataire est à droite.
pour encore plus de détails sur le modèle OSI et les différents protocoles réseaux correspondant aux différents niveaux du modèle: https://www.osi-model.com/session-layer/
Pour transmettre des donneés sur le réseau, on doit traverser les niveaux en descendant vers les niveaux plus bas (donc de plus en plus proche du monde physique). A la réception, on doit faire le chemin inverse:
- L'application, au niveau 7, créé un paquet de données
- Le paquet est envoyé au niveau 6, ce niveau ajoute un peu d'information autour du paquet (l'encapsule)
- Le paquet est passé au niveau 5 et un peu plus d'information est ajoutée (le paquet se fait encapsuler encore plus)
- Le même processus continue comme ça jusqu'au niveau 1 où les données sont encodées de la bonne façon pour passer à travers le médium présentement branché sur l'ordinateur (e.g. impulsions électriques sur un fil ethernet, impulsions de lumières sur une fibre optique, etc)
- Les données sont alors transmises sur le médium réseau (le fil mauve-rose en dessous)
- Le paquet arrive alors à l'ordinateur destinataire au niveau 1 et les données sont décodées selon le médium connecté
- Le paquet est transmis au niveau 2 où les informations qui y avaient été ajoutées (entre autres l'adresse MAC) pourront être utilisées pour déterminer si la machine est réellement la destinataire à l'intérieur du réseau local
- Si la machine décide que le paquet lui est bien destiné, le paquet est envoyé au niveau 3 où l'information ajoutée à ce niveau (entre autres l'adresse IP) permettrat de déterminer si c'est un paquet traversant des réseaux qui est bel et bien à destination de la machine destinataire
- Le paquet est ensuite acheminé au niveau 4 où les informations sont reconsituées et mises en ordre
- Le processus continue ainsi jusqu'au niveau 7 où l'application destinataire reçoit les informations qui avaient été envoyée par l'application envoyeure.
Le routage s'intéresse surtout au niveau 3 (et le niveau 4 va souvent main dans la main avec le concept)!
- les protocoles les plus communs du niveau 3: ipv4, ipv6
- concept: avoir une adresse unique à travers les différents réseaux interconnectés pour une machine et savoir comment rejoindre cette adresse
- les protocoles importants du niveau 4: tcp, udp
concept: couper les données trop grandes en plus petits blocs appelés paquets, tcp seulement: établir une session pour conserver l'ordre des données, et s'assurer que toutes les données sont bien arrivées à destination
Adressage IP: les segments de réseaux, sous-réseaux et netmask/préfixe CIDR
Un sous-réseau c'est simplement une façon "mathématique" de diviser la plage des adresses internet (IP) en blocs plus petits qu'on peut ensuite attribuer à différents organismes/compagnies/bâtisses/racks/autres qui ont besoin d'une présence sur Internet.
Pourquoi on peut/veut prendre certaines décisions de segmenter des réseaux? (même si p-e on considère dans certains cas que ça reste "nos adresses")
Quelques exemples:
- isoler certaines machines de certaines autres
- avoir un segment de réseau qui permet le lien vers d'autres réseaux (e.g. nos fournisseurs d'accès à Internet au centre de données nous attribuent un petit sous-réseau qui contient seulement deux adresses IP et qui permet à notre routeur de parler à leur routeur sans communiquer avec l'équipement des autres clients)
- réduire la taille du "réseau local" pour éviter qu'il n'y ait trop de bruit sur le réseau (ce qui réduirait possiblement la capacité maximale de bande passante et qui pourrait également potentiellement créer des fuites d'informations sensibles!)
louer une partie de nos adresses à un client -- c'est exactement le rôle des RIR, mais d'autres le font aussi à leur tour comme par exemple eStruXture pour rendre une plage d'adresses IPs disponibles à un client de leur centre de données.
Koumbit a également subdivisé son bloc d'adresses IPs en plus petits sous-réseaux pour appliquer plusieurs des exemples plus haut. Notre documentation pour cette subdivision est dans la page AllocationIp.
Chaque subdivision possible utilise un bit de subdivision "à gauche" du nombre représentant l'adresse IP: on divise donc les adresses en deux à chaque sub-division.
Ce qui représente la subdivision des adresses IP s'appelle le netmask (masque de sous-réseau).
Le netmask est utilisé dans une opération ET bit-par-bit avec l'adresse IP (e.g. netmask AND adresse IP) pour calculer c'est quoi la partie "sous-réseau" d'une adresse.
Un netmask est toujours représenté par un nombre de bits à 1 consécutifs à partir de "la gauche" (donc en terme de nombre binaire, "les valeurs les plus grandes" qui sont à un). Les bits à droite de ce nombre sont toujours à 0. Vu qu'on fait une opération ET binaire entre le netmask et l'adresse IP, le netmask sert donc à déterminer quels bits de l'adresse IP sont conservés pour connaître le numéro du réseau.
par exemple le netmask 255.255.255.192 est représenté par le nombre binaire 11111111.11111111.11111111.11000000. Donc, 26 bits "à gauche" à un, et 6 bits "à droite" à 0.
si on applique ce netmask à l'adresse 199.58.83.129, l'opération ET binaire forcera les 6 bits à droite de l'adresse à 0, pour donner le numéro de sous-réseau 199.58.83.128
- donc, dans ce sous-réseau on a 6 bits à droite pour représenter des adresses de machines. alors on a 64 nombres possibles
on a toujours besoin de réserver deux des adresses, dans les nombres d'adresses, qui ne pourront pas être utilisées pour des machines, ce qui veut dire qu'en pratique dans notre sous-réseau en exemple, on n'a en fait que 62 adresses possibles à assigner à des machines:
une adresse (celle qui ne contient que des 0) pour la représentation machine du "sous-réseau" (c'est exactement ce qu'on a calculé plus haut avec notre opération ET binaire)
une adresse (celle qui ne contient que des 1) pour les broadcasts.
Comme un netmask représente en fait simplement un nombre avec un certain nombre de bits à gauche à 1, une notation plus courte a été développée: la notation de préfixe CIDR. Avec la notation de préfixe CIDR, on note une adresse, un "/", puis le nombre de "bits à gauche" contenus dans le netmask.
pour l'exemple plus haut, on pourrait représenter les deux informations comme: 199.58.83.129/26
- les préfixes CIDR sont plus faciles à retenir et plus rapides à écrire, donc on a tendance à utiliser cette notation là plutôt que les netmasks.
- Il existe cependant encore beaucoup de vieux devices réseau et de vieux logiciels qui utilisent encore les netmasks. C'est donc important de connaître les deux notations différentes
ipcalc-ng peut aider à mieux comprendre et à calculer plus rapidement quand on a besoin de le faire. Malheureusement l'outil ne calcule pas les sous-réseaux IPv6.
lancer ipcalc-ng 199.58.83.129/26 et inspecter les informations que ça donne à l'écran. la ligne "wildcard" n'est pas super intéressante pour la formation.
- c'est également possible de spécifier à la commande le netmask avec la notation netmask et non CIDR pour obtenir la même information (ça vous montrera également combien de bits de netmask ça contient pour pouvoir facilement transformer un netmask en notation CIDR.
par exemple: ipcalc-ng 199.58.83.129/255.255.255.192
Exercices
Le restant du temps de formation sera passé à expérimenter avec les commandes dans les trois VMs pour bien ancrer les concepts.
Quelle est la topologie réelle du réseau ?
Bon, l'image dans la section "Préparation pour les participant.e.s" donne la topologie désirée. Mais est-ce que notre réseau a vraiment cette topologie ? Comme on le sait, la documentation n'est pas toujours à jour ... Quoi faire si on doit déterminer la topologie d'un réseau pour lequel nous n'avons pas de documentation ?
C'est justement le cas avec nos machines sur Vagrant, qui ont présentement une structure différente de ce qu'elles devraient avoir ...
Quelles sont les adresses IP et les sous-réseaux de nos machines ?
La première étape est d'avoir un portrait de nos machines. On va donc faire ip a sur chaque machine :
- Le loopback ne nous intéresse pas. C'est ce qu'on appelle souvent le "localhost" et est par défaut 127.0.0.1 et sert pour des tests, ou pour des communications d'un service sur le serveur à un autre sur le même serveur.
- Si vous êtes sur Vagrant, ignorez le eth0, qui est utilisé par vagrant pour gérer ses machines.
Prenons l'affiche pour une interface dans mon cas de "rtr_client", l'interface eth1 :
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:c4:3d:78 brd ff:ff:ff:ff:ff:ff altname enp0s6 altname ens6 inet 10.0.0.95/24 brd 10.0.0.255 scope global eth1 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:fec4:3d78/64 scope link valid_lft forever preferred_lft forever
On note que cette interface possède l'adresse IP (avec préfixe CIRD) suivant : 10.0.0.95/24. Cela veut dire :
- Pour l'interface réseau eth1 de rtr_client, l'adresse IP qui lui a été attribuée est 10.0.0.95.
En faisant ipcalc 10.0.0.95/24 on peut voir que :
- L'identifiant du sous-réseau est 10.0.0.0
- L'adresse IP minimale du sous-réseau est 10.0.0.1
- L'adresse IP maximale du sous-réseau est 10.0.0.254
- L'adresse IP de broadcast est 10.0.0.255
Cela veut dire que mon "rtr_client", à travers son interface eth1, pourra communiquer avec d'autres machines qui ont une adresse IP allant de 10.0.0.1 à 10.0.0.255
Donc, si je fais le résumé pour mes trois machines, j'ai la situation suivante :
- rtr_client :
- eth1 : 10.0.0.95/24 : peut communiquer sur les machines de 10.0.0.1 à 10.0.0.254
- eth3 : 10.1.0.95/24 : peut communiquer sur les machines de 10.1.0.1 à 10.1.0.254
- rtr0 :
- eth1 : 10.0.0.96/24 : peut communiquer sur les machines de 10.0.0.1 à 10.0.0.254
- eth2 : 10.10.0.100/24 : peut communiquer sur les machines de 10.10.0.1 à 10.10.0.254
- eth3 : 10.1.1.2/24 : peut communiquer sur les machines de 10.1.1.1 à 10.1.1.254
- rtr_upstream0 :
- eth1 : 10.10.0.101/24 : peut communiquer sur les machines de 10.10.0.1 à 10.10.0.254
- eth2 : 10.51.0.127/24 : peut communiquer sur les machines de 10.51.0.1 à 10.51.0.254
- eth3 : 10.0.0.222/24 : peut communiquer sur les machines de 10.0.0.1 à 10.0.0.254
On peut déjà avoir une idée quelle machine peut parler avec laquelle, mais est-on sûrEs que c'est bien le cas ?
Avec qui nos machines peuvent-elles communiquer ?
À première vue, on aurait l'impression que "rtr_client - eth1" peut communiquer avec "rtr0 - eth1". Les deux utilisent après tout le même sous-réseau.
Il faut cependant se rappeler que ces adresses ne sont pas adresses IP publiques qui ne changent pas, mais des adresses IP privées, qu'on peut utiliser à l'interne un peu comme on veut. On pourait ainsi avoir deux réseaux complètement indépendant et qui utilisent le même sous-réseau. Ça serait stupide : on essaie le plus possible d'éviter ce genre de confusion, et si on a deux réseaux indépendants, on essaie d'utiliser des plages d'IPs différentes pour que ça soit relativement évident pour la personne qui lit la configuration de comprendre si on parle, par exemple, d'un réseau indépendant Alpha, ou d'un réseau indépendant Beta, etc.
Les plages d'IPs qui sont privées sont les suivantes :
- 10.0.0.0 à 10.255.255.255
- 172.16.0.0 à 172.31.255.255
- 192.168.0.0 à 192.168.255.255
Donc ce sont les adresses qu'il faut se méfier.
Bon, à partir d'une machine, on pourrait faire un ping vers une autre machine, mais une question reste ouverte : Est-ce que le ping a été rerouté avant d'atteindre sa destination ou bien est-ce qu'une connexion directe existe entre les deux machines ? On a effacé une route au début de cette formation, mais est-ce qu'il y en auraient d'autres par hasard ?
À partir de rtr_client, essayons de pinger rtr0. Il n'y a qu'une possibilité qui peut fonctionner. Il n'y a qu'un sous-réseau sur lequel eth1 et eth2 se trouvent ensembles, soit le sous réseau allant de 10.0.0.1 à 10.0.0.254.
- Du eth1 (10.0.0.95) de rtr_client, on essaie d'atteindre le eth1 (10.0.0.96) de rtr0
Donc, de rtr_client, je peux essayer ping 10.0.0.96 (l'adresse IP de rtr 0 sur son eth1). Ça a l'air de fonctionner : les pings passent et je reçoit les réponses. Mais est-ce bien rtr0 qui répond ?
On peut le voir en allant sur rtr0 et en entrant la commande tcpdump -i eth1 host 10.0.0.96 (où 10.0.0.96 est l'adresse IP que rtr0 possède pour son interface eth1) : cette commande va écouter le traffic d'eth1 sur rtr0, mais en filtrant pour avoir uniquement celles qui sont destinées à 10.0.0.96, ou qui sortent de cette adresse IP.
Mais est-ce que la connexion a vraiment été directe, ou bien est-ce que le packet ping est passé par une autre machine entre les deux ? Deux commandes peuvent répondre à notre question :
ping -R 10.0.0.96 qui va afficher la route suivie par les paquets ping.
ping -r 10.0.0.96 qui contourne les règles de routage et envoie directement à la machine demandée. Si cette machine n'est pas dans ce sous-réseau, une erreur se produit.
Qu'aurait-on pu faire si deux interfaces avaient la même plage d'adresse IP ? Aurait-il été possible de forcer le ping à utiliser l'une ou l'autre des interfaces réseaux ? Oui, la commande ping -I eth1 10.0.0.96 permet de force le paquet ping à sortir de eth1.
En faisant le même travail sur les interfaces de nos machines, on se rend compte que la topologie du réseau est bien différente de ce que la documentation nous disait ! Dans mon cas, j'ai donc la topologie suivante (j'ai donné des noms arbitraires aux sous-réseaux) :
- Sous-réseau "Alpha" : 10.0.0.0/24
rtr_client <-> eth1 (10.0.0.95) <-> sous-réseau "Alpha" <-> eth1 (10.0.0.96) <-> rtr0
rtr_client <-> eth1 (10.0.0.96) <-> sous-réseau "Alpha" <-> eth1 (10.0.0.222) <-> rtr_upstream0
rtr0 <-> eth1 (10.0.0.96) <-> sous-réseau "Alpha" <-> eth1 (10.0.0.222) <-> rtr_upstream0
- Sous-réseau "Beta" : 10.1.0.0/24
rtr_client <-> eth3 (10.1.0.95) <-> sous-réseau "Beta" <-> (personne)
- Sous-réseau "Gamma" : 10.10.0.0/24
rtr0 <-> eth2 (10.10.0.100) <-> sous-réseau "Gamma" <-> eth1 (10.10.0.101) <-> rtr_upstream0
- sous-réseau "Omega" : 10.51.0.0/24
rtr_upstream <-> eth2 (10.51.0.127) <-> sous-réseau "Omega" <-> (personne)
On note que les trois machines sont sur le sous-réseau "Alpha" et peuvent communiquer entres elles sans routeur intermédiaire. Nous allons quand même garder cette topologie, parce qu'il est quand même intéressant de voir la différence entre une communication directe (à travers le sous-réseau "Alpha") et une communication indirecte à travers un routeur (passer du sous-réseau "Alpha" vers le sous-réseau "Gamma").
De rtr_client (eth1, 10.0.0.96), nous aimerions donc rejoindre l'adresse IP 10.10.0.101 (eth1) de rtr_upstream0. Or, cette adresse n'est pas dans notre sous-réseau "Alpha", qui est limité de 10.0.0.1 à 10.0.0.254. Pour atteindre 10.10.0.101, il faudra donc passer à travers un routeur qui a accès au sous-réseau "Gamma", donc à travers rtr0.
Rejoindre un réseau local
Sur rtr_client, lister les routes connues par le kernel:
ip r
On a déjà plusieurs routes (une par interface-réseau) ! On va ignorer celle sur eth0, celle de Vagrant. Ces routes sont des routes statiques pour un réseau local qui ont été ajoutées automatiquement quand l'adresse IP de l'interface a été configurée.
En effet, quand on configure une adresse IP sur une interface réseau on spécifie toujours l'adresse et son netmask. Donc on peut présumer qu'il est possible de rejoindre d'autres adresses IP dans le même sous-réseau si on communique via l'interface réseau à laquelle on vient de configurer l'adresse IP.
Sur rtr_upstream0:
Lancer tcpdump (voir commande complète en dessous -- laisser rouler pour le restant des exercices) pour voir les paquets réseau qui arrivent de rtr0 vers rtr_upstream0 (i.e. penser à sélectionner la bonne interface réseau avec -i ethX)
pour éviter de voir trop d'information en même temps, on veut généralement filtrer ce que tcpdump affiche. un filtre simple qu'on peut donner à tcpdump pour nos exercices c'est de seulement afficher les paquets réseau destinés à l'IP de rtr_upstream0: host $ip_upstream0
# remplacer ethX par le bon nom d'interface réseau: tcpdump -i ethX host $ip_upstream0
Dans mon cas, rtr0 et rtr_upstream0 peuvent communiquer à travers deux canaux différents. Notre objectif est d'éventuellement passer des paquets du 10.0.0.96 (eth1, rtr_client, sous-réseau "Alpha") vers le 10.10.0.101 (eth1, rtr_upstream0, sous-réseau "Gamma"), donc, sur rtr_upstream0, on veut écouter à travers l'interface branchée sur le sous-réseau "Gamma". Dans mon cas, cela donne donc tcpdump -i eth1 host 10.10.0.101
Sur rtr0:
lancer deux tcpdump (laisser rouler pour le restant des exercices -- utilisez les notes à l'exemple précédent pour déterminer l'interface et le filtrage nécessaires)
en choisissant l'interface réseau qui a l'IP $ip_rtr0 pour vérifier ce qui vient de rtr_client
en choisissant l'interface réseau qui a une IP très semblable à celle de rtr_upstream0 pour vérifier qu'est-ce qui sort de rtr0 pour se rendre vers rtr_upstream0
Dans mon cas, il faut donc les deux tcpdump suivants :
tcpdump -i eth1 host 10.0.0.96 qui va écouter la communication sur le sous-réseau "Alpha", mais filtré pour uniquement ce qui entre ou sort de rtr0
tcpdump -i eth2 host 10.10.0.100 qui va écouter la communication sur le sous-réseau "Gamma", mais filtré pour uniquement ce qui entre ou sort de rtr0
Sur rtr_client:
Utiliser traceroute pour vérifier le chemin qu'on prend pour se rendre de rtr_client vers rtr_upstream0
- On ne peut pas s'y rendre!
C'est normal: l'adresse ne correspond à pas une route connue (donc ce n'est pas dans un réseau local) et le routage n'est pas encore configuré
- On ne peut pas s'y rendre!
Dans mon cas, sur rtr_client :
si j'essaie de rejoindre rtr0 avec la commande traceroute 10.0.0.96 j'obtiens une réponse. Cette adresse est sur le sous-réseau, et la route par défaut permet de rejoindre cette adresse.
si j'essaie de rejoindre rtr_upstream0 avec la commande traceroute 10.10.0.101, j'obtiens un message comme quoi l'adresse n'est pas rejoignable. En effet, il n'y a pas de route encore.
Sur rtr0:
lancer un ping vers $ip_upstream0 - constater ce qui se passe dans tcpdump
- ici, ça marche en tout cas.
à chaque nouveau ping, on peut voir deux paquets dans tcpdump: un de rtr0 vers rtr_upstream0 et un autre dans la direction inverse.
Rejoindre un réseau distant via une route par défaut
Sur rtr_client:
lancer un ping (laisser rouler pour le restant des exercices) à partir de rtr_client pour tenter de rejoindre $ip_upstream0
on peut forcer la commande à se ré-exécuter à toutes les 2s avec watch -n 2 ping 10.10.0.101
on n'obtient présentement pas de réponse, mais en laissant rouler le ping on pourra voir quand les réponses commenceront à revenir vers rtr_client
- ajouter une route, toujours sur rtr_client:
sudo ip r add default via 10.0.0.96 dev eth1 notez qu'on met ici l'adresse de l'interface-réseau utilisée par rtr0.
vous venez d'ajouter une route par défaut
Comme rtr_client n'a qu'une seule route qui est statique pour un réseau local, rtr_client ne sait pas comment rejoindre le sous-réseau dans lequel l'adresse IP de rtr_upstream0 se trouve (rappelez-vous le premier message d'erreur dans le tout premier traceroute: Network unreachable -- c'est ce que ça indique: il n'y a aucune route qui peut s'appliquer et donc le réseau n'est pas connu/rejoignable).
La route par défaut va indiquer à rtr_client que rtr0, son gateway, lui sait comment retransmettre l'information au bon sous-réseau. L'adresse gateway assignée au routeur est celle indiquée dans la commande ip précédente, celle qui suit le paramètre via (et est donc ici 10.0.0.96) et celle-ci doit être dans le même sous-réseau que rtr_client.
Mais ça ne règle pas le problème ... essentiellement parce que rtr0 ne sait pas trop quoi faire avec les paquets reçus.
Sur rtr0:
avec les tcpdump lancés plus tôt, vérifier que les paquets rentrent sur rtr0 à partir de rtr_client
Sur rtr_upstream0:
avec tcpdump constater que les paquets ne se rendent pas sur rtr_upstream0 - on a un problème à débugger à l'aide les prochaines commandes
Sur rtr0:
Oups! avec le tcpdump en direction de rtr_upstream0 on constate que les paquets qui arrivent de rtr_client ne sortent pas vers rtr_upstream0!
C'est normal: il nous manque une configuration pour que rtr0 fasse le relais des paquets pour rtr_client
Sur rtr0:
permettre aux paquets reçus de rtr_client d'être retransmis au bon endroit (IP forwarding, ce qui permet à rtr0 de retransmettre les paquets vers les réseaux connus):
sudo sysctl -w net.ipv4.ip_forward=1
sur les trois tcpdump: constater que les paquets de ping qui partent de rtr_client passent à travers rtr0 et se rendent maintenant jusqu'à rtr_upstream0, mais qu'aucune réponse ne peut sortir de rtr_upstream0 en direction de rtr_client
Avec la commande sysctl plus haut, la configuration disparaîtra lors d'un reboot. Pour que le IP forwarding soit permanent, on doit ajouter la même option de configuration dans le fichier /etc/sysctl.conf
Si vous voulez jouer à détruire la configuration plus tard pour constater les dégats et débugger à l'aide de tcpdump, mtr et autres commandes, vous pouvez retirer la configuration de IP forwarding avec la commande: sudo sysctl -w net.ipv4.ip_forward=0
Voir note en encadré après les exercices par rapport au IP forwarding pour plus d'information et un exercice complémentaire qu'on peut faire après les exercices de la formation.
Rejoindre un réseau distant sans route par défaut
Sur rtr_upstream0:
Ajouter une route pour permettre de rejoindre rtr_client:
ifdown eth3 : on va fermer eth3 sur rtr_upstream0 parce que sinon on recevra un message d'erreur comme quoi on est déjà capable de rejoindre le sous-réseau, pourquoi faire une route ? On pourra toujours faire plus tard un ifup eth3 pour remettre l'interface réseau en fonction.
sudo ip r add 10.0.0.0/24 via 10.10.0.100 dev eth1 où 10.0.0.0/24 est le sous-réseau "Alpha" qu'on cherche à rejoindre et 10.10.0.100 est l'adresse IP de rtr0 sur le sous-réseau "Gamma".
vous venez d'ajouter une route statique qui n'est pas "locale".
A noter: le paramètre `via $IP` a la même fonction que pour la route par défaut: faire passer le trafic réseau par un routeur à l'adresse IP spécifiée. Dans notre cas ici, on doit passer par `rtr0` avant de pouvoir rejoindre le sous-réseau dans lequel `rtr_client` se trouve.
La différence entre une route par défaut et une route comme celle qu'on vient d'ajouter c'est simplement que le (ou les) réseau(x) à rejoindre est beaucoup plus spécifique et restreint: on défini la route dans l'exemple ici seulement pour un sous-réseau (sous-réseau "Alpha" 10.0.0.0/24) alors que la route par défaut défini une route pour tous les sous-réseaux (default).
NB: on aurait pu encore utiliser une route par défaut dans ce cas-ci, mais l'exercice était différent pour permettre de configurer une route d'un type différent.
Les routes par défaut son généralement seulement utilisées sur les "machines finales" (les feuilles de l'arbre du réseau?). Ici, rtr_upstream0 est supposé être conceptuellement le routeur d'un fournisseur d'accès réseau à Internet et donc ce routeur là en pratique n'utiliserait pas une route par défaut (e.g.: tenter de rejoindre "tout ce qui n'a pas de route définie" en envoyant le trafic réseau vers rtr0 n'aurait pas vraiment de sens puisqu'Internet est dans l'autre sens!)
Sur rtr_client:
- constater que ping reçoit finalement ses réponses
aussi, dans les trois tcpdump: on voit maintenant bien passer les paquets dans les deux directions et à tous les niveaux du chemin entre rtr_client et rtr_upstream0
Utiliser traceroute (ou mtr) à nouveau à partir de rtr_client pour voir le chemin qu'on prend pour se rendre de rtr_client vers rtr_upstream0
- traceroute (et mtr) sert à identifier quels routeurs ont doit traverser pour se rendre jusqu'à une certaine destination.
- C'est une bonne façon de voir où dans le monde (ou simplement à l'intérieur d'une bâtisse) nos paquets se promènent
- On peut grâce à cette information déterminer s'il y a des problèmes de routage.
- par exemple si on ne se rend pas à destination, on peut voir lequel est le dernier routeur dans le chemin
- on peut voir si le routage est tout croche si on prend des chemins improbables. par exemple, nous avons déjà vu le trafic entre les deux centres de données de Koumbit, qui sont tous les deux sur l'île de Montréal, se rendre jusqu'à New York City ou encore pire jusqu'à San Diego -- nos fournisseurs réseau avaient des problèmes dans leur infrastructure pour que ça se produise!
- si nos paquets n'arrivent pas à destination parce qu'ils tournent en rond, on peut facilement identifier quels routeurs se renvoient les paquets un à l'autre
Visualiser les transferts et des flux de paquets pour différents protocoles
Maintenant qu'on a du routage complètement fonctionnel, on peut trouver de l'information un peu plus détaillée sur les transferts d'information par le réseau.
Faire un test de bandwidth entre rtr_client et rtr_upstream0:
sur rtr0, lancer bmon pour observer l'utilisation de bande passante (laisser rouler jusqu'à la fin de la liste de points):
bmon -p eth1 -b
sur rtr_upstream0 faire écouter l'outil de test de bandwidth pour des connexions
iperf -s
ensuite sur rtr_client, lancer un transfert vers rtr_uptream0:
iperf -c $ip_upstream0
- le transfert peut être relancé plusieurs fois pour pouvoir voir des choses dans les commandes suivantes.
sur rtr0: constater dans bmon la bosse de trafic qui passe par la machine pendant le test
sur rtr0: visualuser quelles IPs et avec quels ports le trafic réseau traverse rtr0
iftop -P -i eth1
Etablir des connexions de différents protocoles à partir de rtr_client vers rtr_upstream0:
Quand on appelle les commandes qui suivent, on peut regarder ce qui se passe dans tcpdump pour identifier quelques informations utiles du trafic réseau:
- adresse source, adresse destination
- port source, port destination
- type de paquet
- constater comment une connexion TCP est établie (e.g. lancer une connexion TCP avec nc et voir ce qui passe par tcpdump)
- SYN, ACK, SYN+ACK, ensuite donnés
pour mieux comprendre les lettres des "flags" des paquets, voir la section TCP Packets de la man page de tcpdump
ssh -- ici on veut voir à quoi ressemble le "handshake" TCP de début de connexion, et aussi la fermeture de connexion
curl -- ici, on veut voir ce qui arrive quand on demande qqch qui n'écoute pas sur le réseau (e.g. pas de serveur http sur rtr_upstream0)
nc -- répéter la première expérience mais avec un autre port
on peut utiliser une commande sur rtr_upstream0 pour trouver quels ports sont ouverts sur le réseau: ss -plunt
plusieurs protocoles, comme HTTP et FTP, s'attendent à recevoir du texte de la part des clients. avec nc, on peut envoyer du texte aux ports des serveurs et voir ensuite les réponses textuelles que le serveur nous envoie.
NB: la configuration de "IP Forwarding" n'est utile que dans les cas où on veut retransmettre vers un réseau qui est "local" à la machine qui fait le "forwarding".
Dans notre exemple, rtr0 touche aux/a une présence dans les deux réseau locaux qui communiquent avec rtr_client et rtr_upstream0 directement
mais l'option ne serait pas utile si on voulait rejoindre qqch qui serait dans un réseau "plus loin" que rtr_upstream0
si on conceptualise rtr_upstream0 comme étant EstruXture, on ne pourrait pas utiliser du IP forwarding sur rtr0 pour passer par EstruXture et ensuite rejoindre une machine plus loin sur Internet
- donc l'exemple donné dans les exercice ne correspond pas à une configuration réelle dans notre centre de données. C'était simplement un exemple pour vous permettre de voir toutes les façons possibles de faire traverser les paquets réseau vers d'autres sous-réseaux.
L'IP forwarding est un raccourci qui permet le pont entre deux (ou plus) réseaux qui sont tous rattachés à un même routeur sans avoir besoin de définir une route pour chaque cas possible (dans les deux directions).
- ça pourrait donc par exemple être utile sur les routeurs de Koumbit pour simplifier la gestion du pont entre les différents VLANs (donc la communication entre sous-réseaux de Koumbit mais à l'intérieur de notre réseau).
- Voir dans la section "Informations complémentaires" pour plus d'information sur ce que c'est qu'un VLAN et à quoi ça sert.
Exercice complémentaire:
Sur rtr_client:
lancer un ping vers l'adresse IP de rtr_upstream0 qui n'est connectée à rien (conceptuellement, c'est un client sur internet derrière l'upstream0) et constater que les paquets ne sortent pas de rtr0
comme décrit plus haut, rtr0 ne sait pas où envoyer ces paquets avec seulement l'IP forwarding parce que ce n'est pas un "réseau local" pour rtr0.
on devra donc ajouter une route statique qui n'est pas locale sur rtr0 pour que les paquets puisssent se rendre à destination. Cet exercice est laissé aux lectrices.eurs -- voir l'exemple de route ajoutée à rtr_upstream0 pour une inspiration.
Rétrospective
Pendant un maximum de 15 minutes, les participant.e.s sont invité.e.s à partager les éléments qui ont bien ou moins bien fonctionnés et les idées qui pourraient survenir pour des manières d'améliorer le processus.
Quelques éléments qui peuvent faire partie de la rétrospective, dépendant de la grosseur du projet ou de la formation:
- Sommaire collectif (e.g. résumé rapide en termes que tout le collectif peut comprendre)
Pas trop utile pour les projets vraiment simples ou les formations.
- Chronologie des événements marquant pour le projet
Surtout utile pour les projet qui se sont étalés sur plusieurs jours ou plus ou bien quand beaucoup de choses se sont produites simultanément, ce qui a rendu la compréhension des influences de chaque événement complexe.
- Les bons coups -- qu'est-ce qui a bien fonctionné et qu'on veut tenter de reproduire
- Les problèmes
- échecs -- avec l'aide de la chronologie (si elle a été faite), tenter de situer les échecs dans un contexte selon ce qui était connu des participant.e.s aux moments qui ont mené à l'échec
- problèmes techniques
- manques de ressources
- perturbations externes
- Une liste d'actions à court et/ou à plus long terme pour améliorer les choses telles que soulignées pendant les points précédents
- Transférer les actions dans redmine pour qu'elles puissent être suivies!
N'hésitez pas à partager les échecs à l'extérieur de l'équipe puisqu'on peut apprendre beaucoup de ceux-ci, mais surtout évitez de les formuler comme un blâme sur la/les personne(s) ayant échoué.
Une rétrospective est surtout utile quand on la partage: ça permet aux autres d'apprendre de nos erreurs et aussi de nos idées d'améliorations. On peut par exemple envoyer une forme écrite par email, ou bien sauvegardée comme page wiki.
Information complémentaire
Si c'est désiré après la formation et/ou si on a le temps à la fin de la formation, voici un peu plus d'information ou noms de programmes à investiguer pour approfondir votre connaissance (à noter: on a utilisé certains des outils dans les exercices, mais chacun a beaucoup plus de fonctionnalités qui rendent les commandes utiles à bien plus de choses)
configuration "permanente" des interfaces réseau dans debian
La configuration permanente pour le réseau dans debian se trouve dans: /etc/network/interfaces.
NB: on peut également créer des fichiers sous /etc/network/interfaces.d.
voir man interfaces
outils de tests de réseau
iperf -- faire des transferts entre deux machines pour un test de bandwidth
nmap -- outil complexe de sondage réseau
gnutls-cli -- tester spécifiquement des connexions TLS
nc -- tester qu'une connexion tcp peut bien être établie (permet des tests pour udp aussi)
noping (package debian nommé oping) - outil qui envoie des pings à plusieurs destinations en même temps et montre un historique visuel des résultats.
arping -- trouver l'adresse ARP d'un autre ordi sur le même segment réseau (suggestion: chercher de l'info sur c'est quoi le protocole ARP. hint: c'est un protocole du niveau 2 du modèle OSI)
voir aussi ip neigh
- (avancé) outils de visualisation et manipulation de traces réseau
wireshark / termshark -- outils pour mieux visualiser ce que tcpdump enregistre. permet de décortiquer les différents morceaux d'un paquet pour analyser les échanges d'un protocole.
- comme exercice complémentaire: désactivez le réseau wifi, ensuite avec wireshark partez l'enregistrement de ce qui se passe sur votre interface réseau wifi et réactivez le réseau wifi (vous pouvez stopper l'enregistrement lorsque vous serez connecté.e au réseau sans-fil) -- constatez tous les noms de réseaux sans-fil (SSID) que vous envoyez sur les ondes radio: en effet lors de la recherche de connexion, votre ordi a tendance à essayer tous les réseaux qu'il connaît jusqu'à ce qu'il tombe sur qqch qui répond!
scapy -- programme et librairie python qui permet de forger des paquets réseau et de scripter l'envoi de paquets réseau puis d'enregistrer la réponse obtenue. Ça permet aussi de sortir de l'information des paquets réseau, soit pour afficher les détails à l'écran, soit pour la réutiliser dans un script.
On a tendance à utiliser mtr dans l'équipe comme remplacement de traceroute vu que ça donne des résultats mis à jour à chaque seconde. Cependant c'est important de se rappeler que mtr formule ses paquets un peut différemment et par conséquent donne des résultats un peu fautifs de temps en temps et peut nous induire en erreur par rapport à du supposé "packet loss".
Un exemple de cas où ça nous est arrivé avec l'output différent des deux commandes peut être consulté ici: https://rt.koumbit.net/rt/Ticket/Display.html?id=1312638#txn-10181099
Donc pour cette raison là, c'est toujours mieux de se fier à traceroute comme source finale d'information.
Protocoles réseau additionnels
VlanConfiguration - Protocole réseau qui permet de grouper plusieurs sous-réseaux sur un même lien physique tout en les gardant séparés d'un point de vue logique.
IPv6 - protocole "niveau 3" (network layer) de remplacement d'IPv4 finalisé en 1998 et qui commence finalement à devenir un peu plus populaire vu qu'on arrive à la toute fin de l'allocation d'IPv4 (voir https://en.wikipedia.org/wiki/IPv4_address_exhaustion)
ping6
ip -6 a
traceroute6
BGP: le routage peut devenir complexe à gérer lorsqu'on a affaire à un grand nombre de réseaux ou bien à un nombre de réseaux dynamiques. Lorsqu'on arrive à ces difficultés, certains protocoles de routage peuvent être utilisés pour faciliter la tâche. Un exemple de protocole de routage que Koumbit utilise, c'est BGP.
- BGP sert également à annoncer à tous les autres routeurs (qui utilisent BGP) sur Internet qu'on a un bloc d'adresses IP à nous, et que pour rejoindre ce bloc il faut passer par le(s) routeur(s) qui annonce(nt) l'existance du bloc d'adresse IP. C'est grâce à ce protocole qu'Internet permet de relayer l'information entre différents réseaux qui sont complètement indépendants mais connectés.
Représentations internes des informations de routage
- RIB (Routing Information Base) vs. FIB (Forwarding Information Base)
- En très résumé:
- la RIB contient de l'information par rapport au protocole IP, donc c'est quoi la destination IP qui doit recevoir le paquet pour un certain préfixe de sous-réseau
- la FIB contient de l'information par rapport à IP et aussi le niveau 2 (donc adresse MAC de la destination des paquets) et l'interface exacte d'où doit sortir un paquet
la FIB c'est ce qui est utilisé concrètement pour décider où envoyer les paquets réseau
- l'information dans la FIB est calculée entre autre chose à partir d'information dans la RIB
- Si le chemin pour rejoindre une adresse IP doit changer (p-e parce qu'on vient par exemple de brancher un fil réseau qui est préféré par le systèm à une interface wifi -- ou peut-être qu'un lien est tombé mais ça reste toujours possible de rejoindre la même IP de destination par une autre interface réseau), l'information dans la FIB peut être recalculée selon l'information dans la RIB
- dans linux, pour voir l'information selon:
la RIB: ip route get 10.0.0.42
la FIB: ip route get fibmatch 10.0.0.42
- voir aussi:
Comment ajouter une route blackhole avec iproute2
ajouter: ip route add blackhole 192.0.2.1/32
supprimer: ip route del 192.0.2.1/32
Références pour iproute2
https://www.baturin.org/docs/iproute2/ -- Documentation par tâche