nemunai.re/content/fr/post/gamification-of-a-advanced-linux-sysadmin-course/index.md
Pierre-Olivier Mercier 968e6a1389
All checks were successful
continuous-integration/drone/push Build is passing
Add video
2023-06-08 15:43:14 +02:00

25 KiB
Raw Blame History

title date tags aliases
Concevoir un cours ludique d'administration système Linux 2023-06-07 16:07:00
teaching
kernel
network
certificates
adlin

L'administration système n'est pas quelque chose d'évident pour tout le monde, c'est d'ailleurs un sujet qui, lorsqu'il a trait plus aux bases du réseau et de Linux, peut sembler beaucoup plus rébarbatif que l'apprentissage des dernières technologies à la mode (Docker, Terraform, Kubernetes…).

Aussi, avec le bombardement d'informations et la facilité d'accès à des contenus et tutoriaux informatiques souvent plus intéressants que les cours magistraux "classiques", les étudiants sont de moins en moins attentifs, présents ou participants.

Est-ce peine perdue de regagner leur attention? Non!

De nombreuses solutions existent. Dans cet article je vais décrire la manière dont j'ai appliqué les principes de la "ludification".

Définir les objectifs pédagogiques

Pour la direction des études, je devais mettre sur pied un cours d'administration système Linux, niveau avancé, à destination d'étudiants déjà familiers avec la ligne de commande, qui avaient des connaissances théoriques de réseaux et de bonnes bases en termes de programmation Unix.

Lorsque l'on prépare un cours, il est important de définir les objectifs pédagogiques que l'on cherche à atteindre. Pour moi ici, il s'agissait d'une part de faire pratiquer du réseau concrètement (sans DHCP) et de les amener à déboguer divers problèmes courants pour un administrateur système Linux (tant au niveau système que réseau). Bien évidemment, un certain nombre de sujets d'ouverture sont également survolés en même temps que l'on passe par les différentes étapes d'apprentissage.

Le sujet: Matrix Restarted

Une part importante de la ludification est le contexte dans lequel les étudiants vont évoluer. Il s'agit, au-delà des objectifs pédagogiques, de leur trouver une mission, qui s'apparente à un jeu.

Oui, on parle bien de faire cohabiter des besoins métiers concrets, avec un univers fictionnel qui leur donne envie de progresser dans les objectifs.

En école d'ingénieurs en informatique, le film Matrix est une bible sacrée. Tous les étudiants connaissent l'histoire et au moins vaguement l'univers.

Durant les quelques heures du cours, les étudiants incarneront donc un de leurs héros favoris, dans son univers, avec pour but ultime de: «se connecter à Internet pour rejoindre Zion». Dans Matrix Revolution, Neo doit rejoindre Zion pour la sauver.

Dès les premières minutes de l'exercice, on met donc en place l'environnement:

La Matrice, exclamations et frissons garantis

Et, encore plus primordial: leur objectif final leur est expliqué en quelques lignes, dès le début.

Quelqu´un communique avec nous comme au début du premier film pour nous donner les instructions !

Pour eux, se connecter à Internet représente une tâche facile, tout à fait raisonnable et accessible.

C'est la clef pour leur donner envie de s'investir: susciter leur curiosité, qu'y aura-t-il une fois arrivé à Zion?! Évidemment, à ce stade, les étudiants ignorent que de nombreuses péripéties les attendent…

Suivi individualisé

Pour le professeur, un aspect de première importance dans ce genre d'exercice est d'être capable d'aider les étudiants en difficulté. On sait très bien que beaucoup d'étudiants ne lèvent pas la main pour demander de l'aide. Au contraire, je constate que lors de cet exercice, ce sont principalement les étudiants qui se débrouillent le mieux qui ont tendance à demander de l'aide sur les parties bonus, évidemment plus ardues.

Lors de travaux pratiques, la principale source de décrochage que j'ai observée intervient lorsque l'enseignant est en avance sur l'étape de l'étudiant: non seulement il doit se dépêcher pour rattraper son retard, mais en plus il ne peut bénéficier des conseils donnés oralement par le professeur. On peut déplorer qu'il n'interrompe pas le cours pour demander de l'aide, mais voilà, de nombreux étudiants n'osent pas.

Dans le cadre de cet exercice, étant donné que tout est bien scénarisé, j'ai pu mettre en place un système qui supervise chaque étudiant. Cela a deux avantages principaux:

  • Cela me permet de suivre l'avancement global et individuel: je peux aller voir ceux qui sont en retard pour gérer individuellement leurs difficultés; et quand c'est toute la classe qui bloque sur une étape, je peux intervenir sans qu'aucun étudiant ne se sente en retard: on réfléchit collectivement sur le point bloquant, ce qui favorise la réflexion individuelle, y compris de ceux qui ne participent pas oralement.

  • Alors que la notation est habituellement une corvée, ici en monitorant l'avancement des étudiants, il est aisé de connaître les objectifs pédagogiques que chacun a acquis, afin de le noter en conséquence.

Le tableau de bord pour suivre chaque étudiant

Mais alors, quel est le contenu, les différentes étapes par lesquelles l'étudiant passe?

Contenu du «scénario» du cours

Étape 0: Rooter la machine

Dans une entreprise, il peut arriver que l'on se retrouve à devoir intervenir sur une machine installée il y a très longtemps ou par un stagiaire qui n'était pas au fait des procédures et des mots de passe à utiliser, et pourtant il faut en récupérer les accès.

La première étape du cours consiste donc pour les étudiants à "rooter" leur machine. C'est-à-dire passer outre l'écran de connexion, devenir administrateur sans connaître le mot de passe.

C'est une action "courante" qui ne fait appel à aucune vulnérabilité, il suffit d'avoir accès au programme de chargement du système d'exploitation.

Si pour beaucoup d'étudiants l'aspect théorique du "rootage" est bien présent, ils sont très peu à l'avoir expérimenté (et à avoir conscience que c'est si simple, qu'ils pourraient vouloir prendre des mesures pour contrer cette possibilité une fois dans le monde du travail).

Le bac à sable pour les apprenants

L'ensemble du cours se déroule dans une salle machine préparée spécialement pour l'occasion et chaque machine est un bac à sable pour l'étudiant qui l'utilise. Les étudiants sont sur un poste de travail piloté par un serveur (techniquement, les machines sont tout simplement configurées pour démarrer sur le réseau, en PXE).

Le système démarré est un véritable système GNU/Linux standard, basé sur la distribution Alpine afin d'être le plus léger possible. Aussi, afin de limiter les actions inopportunes (écrasement du disque de l'hôte par exemple), le noyau est spécialement compilé pour avoir un nombre limité de pilotes.

{{% card color="success" title="Quelques détails techniques sur le démarrage" %}} Les postes clients n'étant pas démarrés avec un disque physique ou distant attaché, il n'y a aucune donnée persistante: en cas de redémarrage, l'étudiant retrouve la situation initiale. L'exercice ne nécessitant pas de redémarrer volontairement, cela n'est donc généralement pas un problème, mais cela garantit de retrouver un état sain/connu de l'enseignant s'il doit aider un étudiant qui a détruit son système.

Il y a une exception, car dans la vraie vie, après avoir démarré notre machine en mode single pour écraser le mot de passe root, on redémarre pour retrouver le mode classique. Quel que soit le mode dans lequel la machine a été démarrée, un programme tourne en tâche de fond pour surveiller les modifications faites sur le fichier /etc/shadow, contenant les mots de passe des comptes de la machine. Aussitôt qu'un changement est effectué, le fichier est transmis au serveur démarrant les machines.

Afin de ne pas surcharger le serveur au moment où tous les étudiants changent leur mot de passe, au lieu de recréer l'image complète du système, je tire parti d'une astuce liée au format d'archive utilisé: il n'y a pas d'en-tête ni d'index global des fichiers, on peut donc ajouter un nouveau fichier à la fin de l'archive, dans le format attendu:

echo etc/shadow | cpio -oAF system.cpio

L'opération est peu coûteuse en ressources, il faudra simplement avoir suffisamment dimensionné l'espace disque du serveur puisque chaque étudiant aura sa propre archive complète du système (de l'ordre de 30Mo par étudiant). {{% /card%}}

Étape 1: Appréhender les modules noyau

Après avoir passé l'écran de connexion, l'étudiant fait donc face à un shell complet, avec lequel il peut lancer toutes les commandes installées qu'il souhaite. Il n'y a pas d'interface graphique, les étudiants savent utiliser un shell, on leur montre ici que le terminal brut est une option.

Ayant toujours en tête sa mission de joindre Zion en se connectant à Internet, l'étudiant va regarder s'il est bien connecté:

42sh# curl https://nemunai.re
curl: (6) Could not resolve host: nemunai.re

Peut-être que l'on peut joindre une IP?

42sh# ping 9.9.9.9
PING 9.9.9.9 (9.9.9.9): 56 data bytes
ping: sendto: Network unreachable

OK, est-ce que l'on a une IP?

42sh# ip address
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

Cette démarche est normalement acquise lors d'une pratique courante des systèmes Unix, mais il est important de rappeler ces commandes car certains, plus à l'aise avec les interfaces graphiques auraient cherché Firefox ou la boîte de dialogue de Network Manager.

La dernière commande doit interpeler car il s'agira sans doute d'une situation inédite! Seule l'interface lo, de boucle locale, est présente et elle n'est pas configurée. Où peut donc bien se trouver notre carte Ethernet utilisée pour démarrer la machine?

Cette situation peut être l'occasion de revenir sur les mécaniques de démarrage, expliquer le rôle du chargeur de système d'exploitation pour bien montrer la différence.

L'objectif de cette étape est de faire découvrir les modules noyau et la commande modprobe pour les charger.

Selon l'affinité de l'auditoire, on peut les laisser tâtonner avec lspci pour explorer le matériel, s'approprier le nom des constructeurs et rechercher dans l'arborescence /lib/modules les pilotes qui peuvent correspondre.

Pour les étudiants qui se demandent comment un système classique charge automatiquement les modules, il faut bien sûr leur parler de udev et mdev. Ces programmes vont eux-mêmes lire dans /sys les informations dont ils ont besoin.

Étape 2: configuration du réseau

Après avoir chargé le module noyau de la carte réseau, celle-ci apparaît enfin:

42sh# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:b4:bc:42 brd ff:ff:ff:ff:ff:ff
    inet 172.23.0.42/24 scope global eth0
       valid_lft forever preferred_lft forever

Mais elle n'est pas configurée.

Certains connaîtront le DHCP, néanmoins aucun utilitaire permettant de configurer le réseau automatiquement n'est installé sur le système.

Car pour démarrer en réseau une machine, il est nécessaire d'avoir sur le réseau un service de configuration automatique. Dans le cadre de cet exercice, il s'agit d'un sous-réseau dédié exclusivement au démarrage des machines, il ne donne pas accès à Internet, ce qui peut perturber les étudiants à ce stade: normalement on obtient une IP et donc Internet!

C'est donc pour éviter de se confronter à cette idée reçue à ce stade que j'ai préféré retirer tous les programmes de configuration automatique.

La seule voie est donc de configurer le réseau manuellement. Ils ont à leur disposition la véritable topologie du réseau, ainsi qu'une adresse IP à utiliser.

Topologie du réseau qui est fournie aux étudiants pour se repérer

Cette étape leur permet d'apprendre à lire une topologie et à s'exercer avec les masques de sous-réseau. Quelques étudiants oublieront notamment le masque en ajoutant l'IP à leur interface, ce qui les empêchera de contacter le serveur.

Le risque d'un tel exercice est que plusieurs étudiants prennent la même adresse et créent des conflits d'IP, ce qui rendrait l'exercice bien trop difficile. Pour annihiler tout risque de conflit, chaque étudiant se voit confier une adresse protégée: cette adresse est inscrite dans la table ARP du serveur pour qu'elle ne puisse communiquer qu'avec son poste exclusivement.

Lorsque leur interface réseau est configurée, il est utile de leur parler des protocoles d'attribution d'adresse tels que DHCP, Neighbor Discovery Protocol, Router Advertisement…

Étape 3: reconnaître un kernel panic

Comme il s'agit d'un challenge en plusieurs étapes, les étudiants doivent débloquer ces étapes en envoyant un jeton unique à un serveur de validation.

Ils disposent pour cela d'un programme pour générer ces jetons:

42sh# adlin
{
    "login": "nemunaire",
    "challenge": 1,
    "token": "db82f32ef6f2563663cb6ffa4826cfade0b822b56b4c0bc526873f3ba224bbae53b8fc6494b408720fb48f858eded6cd649e55edd8620d4ab587e1119c86072e"
}

À chaque étape, l'adresse du serveur est donnée, car c'est ce qui module la complexité, comme on le verra dans les étapes suivantes.

Pour le tout premier jeton, il est demandé de l'envoyer à une machine du sous-réseau local, donc sans configuration supplémentaire:

42sh# adlin | curl -d @- http://172.23.0.1/iamalive

Sauf qu'en faisant cela, l'étudiant va déclencher un kernel panic: un programme spécialement conçu pour exploiter un bug du noyau va faire planter la machine.

Alors que l'appel indépendant du programme adlin ou curl est inoffensif, lorsqu'ils sont appelés ensemble, un programme supplémentaire est lancé:

[ -t 1 ] || init-crypto

Il n'y a évidemment aucune cryptographie à initialiser, il s'agit de camoufler un binaire dont le seul but est de créer un kernel panic.

L´écran tant redouté du kernel panic

Rares sont les étudiants à avoir été confrontés à un kernel panic dans le passé. Et pour la plupart, leur réflexe sera de redémarrer la machine sans le regarder, ni chercher à le comprendre.

Le but de cette étape est donc de démystifier l'écran de kernel panic. Il s'agit surtout de lire la toute dernière ligne:

---[ end Kernel panic - not syncing: panic_on_oops set … ]---

Parfois avec un peu d'aide sur la terminologie anglaise du verbe to set, l'étudiant comprend qu'en fait il s'agit d'un paramètre particulier du noyau, que l'on pourrait sans doute inverser, faire qu'il ne soit plus définit et ne cause donc plus le plantage.

Étape 4: ancrage des connaissances

Outre l'intérêt d'appréhender un kernel panic, le redémarrage forcé du poste que cela induit, alors que l'environnement n'est pas persistent, oblige l'étudiant à refaire la configuration réseau.

Comme il s'agit de la compétence clef retenue pour ce cours, le fait d'obliger l'étudiant à refaire une deuxième fois cette étape permet de mieux fixer la méthode dans sa mémoire.

Étape 5: configuration du noyau

Avant de tester à nouveau de valider le premier jeton, et afin d'éviter un nouveau kernel panic, l'étudiant doit désactiver la fonctionnalité activée dans le noyau qui provoque ce comportement.

On commence ici à rentrer dans des aspects de Linux inconnus des étudiants. Pourtant de nombreuses fonctionnalités avancées (telles que les cgroups utilisés par Docker) sont conçus autour des mêmes principes de configuration: par une arborescence de fichiers virtuels.

Guidés par le sujet, les étudiants explorent donc le dossier /proc/sys, à la recherche du fameux fichier panic_on_oops dont il convient de changer le contenu afin de désactiver la fonctionnalité.

Enfin, ça y est, l'étudiant peut désormais valider son premier token, avec la satisfaction d'avoir appris et découvert de nombreuses choses importantes.

Étape 6: le routage réseau

De retour sur notre fil conducteur, afin d'accéder à Internet, une IP seule n'est pas suffisante, il faut indiquer à notre système l'adresse de notre routeur qui sera chargé d'acheminer nos paquets vers l'Internet.

Néanmoins la topologie ne nous donne que le nom de domaine du routeur par défaut. Mais impossible de résoudre un nom de domaine à ce stade. Pour ce faire, le sujet suggère de terminer la configuration de notre système en tirant parti des services locaux: un résolveur de noms ainsi qu'un serveur de temps sont accessibles dans une DMZ que l'on peut joindre avec une route réseau dédiée.

En réseaux, il est très souvent question de routage. Pour un étudiant, le routage consiste à laisser la box ou le routeur de l'entreprise gérer cette tâche. Pourtant ce sera bientôt à lui de gérer ces routeurs, d'où l'importance de montrer ici un exemple d'un routage "complexe", avec à la fois une route par défaut et une route statique vers notre DMZ.

Un second jeton est attendu pour valider le bon fonctionnement du routage. Certains étudiants auront à ce stade créé une route par défaut et cela fonctionnera, mais ils verront plus tard que cela leur posera des problèmes. Dans tous les cas c'est une étape d'apprentissage utile.

Étape 7: anomalie temporelle

Alors que jusqu'à maintenant tous les jetons devaient être envoyés vers un serveur web au travers d'une connexion non chiffrée (en HTTP en clair), il est maintenant demandé de valider un jeton sur une adresse utilisant le protocole HTTPS.

Si jusque-là tout semblait être cohérent, cette étape qui avait pourtant l'air simple: passer du protocole HTTP au HTTPS, va révéler un problème pour le moins inattendu:

42sh# curl https://172.23.200.1/challenge
curl: (60) SSL certificate problem: certificate is not yet valid
More details here: https://curl.haxx.se/docs/sslcerts.html

Il se trouve qu'au démarrage, une date aberrante est aléatoirement attribuée à la machine.

L'étudiant doit alors prendre conscience que le certificat est bien valide et que le problème vient de l'horloge de sa machine.

Il n'est pas rare, en tant qu'administrateur système, de rencontrer une machine dont l'horloge est repartie à 0 à cause d'une pile vide ou défectueuse.

Encore une fois, le point clef de l'étape consiste à prendre le temps de lire le message d'erreur. Beaucoup d'étudiants se précipitent pour ajouter l'option -k pour ignorer les erreurs de certificats, cependant le jeton de validation est basé sur l'horloge. Si l'horloge est trop éloignée, l'étudiant reçoit un message lui rappelant que l'usage réflexe de l'option -k n'est pas souhaitable.

Pour passer cette étape, il est attendu de découvrir les outils de synchronisation d'horloge, en utilisant le serveur NTP de la DMZ.

Une fois l'étape validée, il est important de faire un point avec les étudiants sur les magasins de certificats. En temps normal, sur une machine fraîchement installée, une telle requête n'aurait pas dû fonctionner car il est impossible d'obtenir un certificat TLS valide pour une IP privée. En l'occurrence, j'avais placé dans le magasin de leur système une autorité supplémentaire, que je contrôle. Je suis donc en mesure d'intercepter tout le trafic chiffré que leurs applications pourraient émettre. Il s'agit d'un point de sensibilisation particulièrement important.

Étape 8: résolution des noms de domaine

On a vu que l'on avait besoin de résoudre des noms de domaine pour obtenir l'adresse de notre routeur par défaut (mais aussi les noms de domaines de manière générale).

Une fois que le système de l'étudiant peut joindre la DMZ, il peut accéder aisément au serveur résolveur. Pour que le système et tous les programmes de sa machine soient en mesure d'utiliser des noms de domaine, l'étudiant apprend à manipuler le fichier /etc/resolv.conf.

À la marge de cette étape, afin d'éveiller l'intérêt du DNS, un jeton est à retrouver dans la zone utilisée pour le cours.

Étape 9: route par défaut

On approche du but, on a déjà ajouté une route statique, il faut maintenant ajouter la route par défaut.

Comme la plupart des actions importantes, c'est la deuxième fois que l'étudiant va ajouter une route, ce qui favorise l'apprentissage du mécanisme.

Le jeton à valider à cette étape nécessite d'avoir à la fois accès à la DMZ et à la route par défaut. Les étudiants qui n'avaient pas procédés ainsi à ce stade seront contraints de le faire, car ils ne peuvent pas encore accéder à Internet malgré la route par défaut…

Étape 9 bis: la folie des conflits d'IP

Jusque-là l'étudiant disposait d'une IP protégée, mais pour valider le palier il doit seul choisir une IP parmi une plage /16.

Il s'avère qu'à chaque fois que j'ai donné ce cours, de nombreux étudiants ont choisi l'IP du routeur plutôt que de choisir une IP aléatoire ou similaire à celle qui leur avait été attribuée sur le sous-réseau initial.

Pour que tous les étudiants sans exception soient confrontés à ce problème, le serveur réalise de l'ARP poisoning sur toutes les adresses qui cherchent à le contacter.

Les étudiants sont donc obligés de retrouver la véritable MAC du serveur parmi toutes les MAC qui répondent aux requêtes. Ils découvrent à cette occasion les entrées statiques dans la table ARP.

En complément, cette étape permet d'ouvrir sur l'ARP spoofing et les dangers notamment des points d'accès sans fils non protégés.

Étape 10: Traceroute

L'ultime étape nécessite de comprendre le cheminement des paquets sur le réseau. En découvrant l'outil traceroute, l'étudiant peut s'apercevoir que ses paquets sont systématiquement détruits au 4ème routeur!

L'exercice est quelque peu cavalier, mais il revient sur la configuration du noyau. La durée de vie des paquets IP a volontairement été fixée à 4, pour produire ce résultat. L'étudiant doit donc retrouver le bon paramètre pour remettre une valeur plus appropriée qui permettront aux paquets d'atteindre leur destination.

En ouverture, il est intéressant d'expliquer que ce nombre maximal de routeurs à traverser peut être utilisé pour reconnaître le système d'exploitation d'une cible.

Fin

Pour finir, les étudiants sont invités à se connecter à un serveur distant affichant le film Star Wars en ASCII Art.

Peut-être un clin d'œil au prochain cours…?

Les Bonus

1. Lecture du code

Certains étudiants curieux seront allés lire les scripts mis à leur disposition dans le système, notamment le fameux script adlin, causant le kernel panic. Un jeton bonus est caché dans le script, afin de récompenser la curiosité.

2. Prendre conscience du monitoring

Chaque étudiant est activement monitoré pour enregistrer sa progression. La présence en ligne/hors ligne de sa machine pouvant soulever un besoin d'aide.

Les paquets ICMP envoyés à chaque étudiant contenait une chaîne hexadécimale particulière qu'ils peuvent observer en analysant le trafic de leur carte Ethernet.

3. Fichier disparu sur le disque

Un disque virtuel est créé au démarrage du système, un fichier est créé avec un jeton unique, puis supprimé.

Ce bonus vise à montrer à l'étudiant averti l'usage d'outils de récupération de fichiers.

4. Envoyer un courriel avec la ligne de commande

Ce bonus vise à faire découvrir le format des courriels aux étudiants, pour notamment les sensibiliser au fait que l'expéditeur n'est qu'un en-tête et qu'il peut être falsifié très facilement.

Variantes

Je montre ici une trame standard de l'exercice que j'ai conçu. Selon les besoins attendus il est possible de dévier de ce scénario.

On peut notamment ajouter des VLAN (si le réseau sous-jacent ne les filtre pas), une technologie de tunnel, de l'IPv6, une connexion SSH finale nécessitant de générer des clefs sûres…

Conclusion

Une session de 3 à 4heures est nécessaire pour que 80% des étudiants valident tous les paliers prévus, avec 30 à 50élèves.

Les étudiants ressortent de ce cours systématiquement avec des étoiles dans les yeux. Ils sont reconnaissants d'une part pour tous les apprentissages qu'ils n'avaient pas eu l'occasion de pratiquer avant ou même qu'ils ignoraient. D'autre part ils sont reconnaissants de l'originalité du format, qui les stimule et les met face à des problèmes concrets qu'ils doivent dépasser, avec une frustration réduite du fait de l'accompagnement personnalisé qui peut être réalisé avec la remontée en direct de la progression.

Un tel format de cours prend tout de même un temps conséquent à préparer. Initialement j'y ai passé près de 165heures réparties entre:

  • 40heures de réflexions initiales sur les objectifs et le scénario,
  • 20heures pour réaliser quelques preuves de concepts sur les zones d'ombre à éclairer,
  • 100heures de conception du serveur et des différents mécanismes,
  • 5heures de tests sur place pour s'assurer de la compatibilité de l'ensemble du scénario.

Démonstration

Voici un aperçu de l'ensemble des étapes, brutes, sans explication:

{{< video src="https://storage.nemunai.re/adlin-clips/adlin-speed-run.mp4" >}}