Pack de contenus (8 labs, séquence 08 complète)
This commit is contained in:
parent
138235bd76
commit
5c396d5a94
13 changed files with 805 additions and 0 deletions
73
paillasse-contenus/01-shell-droits/lab.yaml
Normal file
73
paillasse-contenus/01-shell-droits/lab.yaml
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
id: 01-shell-droits
|
||||||
|
titre: Premiers pas dans le shell et droits
|
||||||
|
niveau: decouverte
|
||||||
|
duree_min: 40
|
||||||
|
formations: [snt, nsi-1re, bac-pro-ciel, bts-sio, but-rt, tssr]
|
||||||
|
competences: [arborescence, commandes-base, droits, utilisateurs]
|
||||||
|
|
||||||
|
reseaux:
|
||||||
|
- nom: isole
|
||||||
|
cidr: 10.0.0.0/24
|
||||||
|
|
||||||
|
machines:
|
||||||
|
- nom: poste
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [isole]
|
||||||
|
|
||||||
|
consignes:
|
||||||
|
- "Crée le dossier /home/eleve/projet."
|
||||||
|
- "Crée le fichier /home/eleve/projet/rapport.txt contenant le mot « paillasse »."
|
||||||
|
- "Crée le groupe `equipe` et l'utilisateur `alice`, membre de ce groupe."
|
||||||
|
- "Donne le fichier rapport.txt au groupe `equipe`."
|
||||||
|
- "Règle les droits de rapport.txt en 640 (propriétaire : lecture/écriture, groupe : lecture, autres : rien)."
|
||||||
|
- "Rends exécutable le script /home/eleve/projet/bonjour.sh que tu auras créé."
|
||||||
|
|
||||||
|
verifications:
|
||||||
|
- id: dossier
|
||||||
|
titre: Dossier projet
|
||||||
|
machine: poste
|
||||||
|
commande: "test -d /home/eleve/projet"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "Le dossier /home/eleve/projet n'existe pas."
|
||||||
|
- id: fichier
|
||||||
|
titre: Contenu du rapport
|
||||||
|
machine: poste
|
||||||
|
commande: "grep -q paillasse /home/eleve/projet/rapport.txt"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "rapport.txt n'existe pas ou ne contient pas « paillasse »."
|
||||||
|
- id: utilisateur
|
||||||
|
titre: Utilisatrice alice dans le groupe equipe
|
||||||
|
machine: poste
|
||||||
|
commande: "id -nG alice | grep -qw equipe"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "alice n'existe pas ou n'est pas dans le groupe equipe."
|
||||||
|
- id: groupe-fichier
|
||||||
|
titre: Groupe du fichier
|
||||||
|
machine: poste
|
||||||
|
commande: "test \"$(stat -c %G /home/eleve/projet/rapport.txt)\" = equipe"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "rapport.txt n'appartient pas au groupe equipe (regarde chgrp)."
|
||||||
|
- id: droits
|
||||||
|
titre: Droits 640
|
||||||
|
machine: poste
|
||||||
|
commande: "test \"$(stat -c %a /home/eleve/projet/rapport.txt)\" = 640"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "Les droits de rapport.txt ne sont pas 640."
|
||||||
|
- id: script
|
||||||
|
titre: Script exécutable
|
||||||
|
machine: poste
|
||||||
|
commande: "test -x /home/eleve/projet/bonjour.sh"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "bonjour.sh n'existe pas ou n'est pas exécutable."
|
||||||
|
|
||||||
|
indices:
|
||||||
|
- "mkdir crée un dossier, echo \"texte\" > fichier crée un fichier."
|
||||||
|
- "groupadd, puis useradd -G pour l'appartenance."
|
||||||
|
- "chmod 640 : 6 = rw-, 4 = r--, 0 = ---."
|
||||||
67
paillasse-contenus/02-reseau-paquets-ip/lab.yaml
Normal file
67
paillasse-contenus/02-reseau-paquets-ip/lab.yaml
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
id: 02-reseau-paquets-ip
|
||||||
|
titre: Configurer le réseau et installer un paquet
|
||||||
|
niveau: decouverte
|
||||||
|
duree_min: 40
|
||||||
|
formations: [nsi-1re, bac-pro-ciel, bts-sio, bts-ciel-ir, tssr]
|
||||||
|
competences: [adressage-ipv4, paquets-debian, diagnostic]
|
||||||
|
|
||||||
|
reseaux:
|
||||||
|
- nom: lan
|
||||||
|
cidr: 10.10.0.0/24
|
||||||
|
|
||||||
|
machines:
|
||||||
|
- nom: poste1
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lan]
|
||||||
|
- nom: poste2
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lan]
|
||||||
|
|
||||||
|
consignes:
|
||||||
|
- "Attribue 10.10.0.11/24 à poste1 et 10.10.0.12/24 à poste2."
|
||||||
|
- "Vérifie que les deux postes se joignent."
|
||||||
|
- "Sur poste1, installe le paquet `tree` fourni dans /opt/paquets/ (pas d'Internet dans les labs)."
|
||||||
|
- "Sur poste1, écris le nom d'hôte de poste2 dans /home/eleve/voisin.txt (utilise ssh ou nc pour le découvrir)."
|
||||||
|
|
||||||
|
verifications:
|
||||||
|
- id: ip-poste1
|
||||||
|
titre: Adresse de poste1
|
||||||
|
machine: poste1
|
||||||
|
commande: "ip -4 -o addr | grep -q ' 10.10.0.11/24 '"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "poste1 n'a pas 10.10.0.11/24."
|
||||||
|
- id: ip-poste2
|
||||||
|
titre: Adresse de poste2
|
||||||
|
machine: poste2
|
||||||
|
commande: "ip -4 -o addr | grep -q ' 10.10.0.12/24 '"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "poste2 n'a pas 10.10.0.12/24."
|
||||||
|
- id: ping
|
||||||
|
titre: Les postes se joignent
|
||||||
|
machine: poste1
|
||||||
|
commande: "ping -c 2 -W 1 10.10.0.12"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "poste1 ne joint pas poste2."
|
||||||
|
- id: paquet
|
||||||
|
titre: Paquet tree installé
|
||||||
|
machine: poste1
|
||||||
|
commande: "dpkg -s tree | grep -q 'Status: install ok installed'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "tree n'est pas installé (regarde dpkg -i)."
|
||||||
|
- id: voisin
|
||||||
|
titre: Nom du voisin
|
||||||
|
machine: poste1
|
||||||
|
commande: "grep -q poste2 /home/eleve/voisin.txt"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "voisin.txt ne contient pas le nom de poste2."
|
||||||
|
|
||||||
|
indices:
|
||||||
|
- "ip addr add 10.10.0.11/24 dev <interface>"
|
||||||
|
- "sudo dpkg -i /opt/paquets/tree_*.deb"
|
||||||
54
paillasse-contenus/03-web-client-serveur/lab.yaml
Normal file
54
paillasse-contenus/03-web-client-serveur/lab.yaml
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
id: 03-web-client-serveur
|
||||||
|
titre: Un serveur web et son client
|
||||||
|
niveau: decouverte
|
||||||
|
duree_min: 45
|
||||||
|
formations: [snt, nsi-1re, bts-sio, bts-ciel-ir, but-rt, but-mmi]
|
||||||
|
competences: [http, client-serveur, nginx, curl]
|
||||||
|
|
||||||
|
reseaux:
|
||||||
|
- nom: lan
|
||||||
|
cidr: 10.20.0.0/24
|
||||||
|
|
||||||
|
machines:
|
||||||
|
- nom: serveur
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lan]
|
||||||
|
- nom: client
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lan]
|
||||||
|
|
||||||
|
consignes:
|
||||||
|
- "Attribue 10.20.0.10/24 au serveur et 10.20.0.20/24 au client."
|
||||||
|
- "Démarre nginx sur le serveur et active-le au démarrage."
|
||||||
|
- "Remplace la page d'accueil par une page HTML contenant « Bienvenue sur Paillasse »."
|
||||||
|
- "Depuis le client, affiche la page avec curl et enregistre les en-têtes HTTP dans /home/eleve/entetes.txt."
|
||||||
|
|
||||||
|
verifications:
|
||||||
|
- id: nginx-actif
|
||||||
|
titre: nginx démarré et activé
|
||||||
|
machine: serveur
|
||||||
|
commande: "systemctl is-active --quiet nginx && systemctl is-enabled --quiet nginx"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "nginx n'est pas démarré ou pas activé au démarrage."
|
||||||
|
- id: page
|
||||||
|
titre: Page d'accueil servie au client
|
||||||
|
machine: client
|
||||||
|
commande: "curl -s --max-time 3 http://10.20.0.10/ | grep -q 'Bienvenue sur Paillasse'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 3
|
||||||
|
message_echec: "Le client ne reçoit pas la page attendue depuis 10.20.0.10."
|
||||||
|
- id: entetes
|
||||||
|
titre: En-têtes HTTP enregistrés
|
||||||
|
machine: client
|
||||||
|
commande: "grep -qi '^HTTP/1.1 200' /home/eleve/entetes.txt"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "entetes.txt ne contient pas la ligne de statut HTTP 200."
|
||||||
|
|
||||||
|
indices:
|
||||||
|
- "systemctl enable --now nginx"
|
||||||
|
- "La page par défaut est dans /var/www/html/"
|
||||||
|
- "curl -I affiche uniquement les en-têtes."
|
||||||
58
paillasse-contenus/04-processus/lab.yaml
Normal file
58
paillasse-contenus/04-processus/lab.yaml
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
id: 04-processus
|
||||||
|
titre: Processus et services
|
||||||
|
niveau: intermediaire
|
||||||
|
duree_min: 45
|
||||||
|
formations: [nsi-tle, bts-sio-sisr, bts-ciel-ir, but-rt, tssr]
|
||||||
|
competences: [processus, signaux, systemd]
|
||||||
|
|
||||||
|
reseaux:
|
||||||
|
- nom: isole
|
||||||
|
cidr: 10.0.0.0/24
|
||||||
|
|
||||||
|
machines:
|
||||||
|
- nom: poste
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [isole]
|
||||||
|
preparation: "systemd-run --unit=glouton --property=Restart=no sh -c 'while :; do :; done'"
|
||||||
|
|
||||||
|
consignes:
|
||||||
|
- "Un processus consomme tout le processeur : trouve-le avec top ou ps."
|
||||||
|
- "Arrête-le proprement."
|
||||||
|
- "Écris son ancien PID dans /home/eleve/pid.txt (relève-le avant de l'arrêter)."
|
||||||
|
- "Crée un service systemd `horloge` qui écrit la date dans /tmp/horloge.log toutes les 10 secondes, et active-le."
|
||||||
|
|
||||||
|
verifications:
|
||||||
|
- id: glouton-arrete
|
||||||
|
titre: Processus glouton arrêté
|
||||||
|
machine: poste
|
||||||
|
commande: "! systemctl is-active --quiet glouton"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "Le processus glouton tourne encore."
|
||||||
|
- id: pid
|
||||||
|
titre: PID relevé
|
||||||
|
machine: poste
|
||||||
|
commande: "grep -Eq '^[0-9]+$' /home/eleve/pid.txt"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "pid.txt doit contenir uniquement un numéro de processus."
|
||||||
|
- id: service
|
||||||
|
titre: Service horloge actif et activé
|
||||||
|
machine: poste
|
||||||
|
commande: "systemctl is-active --quiet horloge && systemctl is-enabled --quiet horloge"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "Le service horloge n'est pas actif ou pas activé."
|
||||||
|
- id: journal
|
||||||
|
titre: Le service écrit bien
|
||||||
|
machine: poste
|
||||||
|
commande: "test -s /tmp/horloge.log"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "/tmp/horloge.log est vide ou absent."
|
||||||
|
|
||||||
|
indices:
|
||||||
|
- "top trie par CPU ; ps aux --sort=-%cpu aussi."
|
||||||
|
- "kill envoie SIGTERM par défaut."
|
||||||
|
- "Un fichier .service va dans /etc/systemd/system/, puis systemctl daemon-reload."
|
||||||
63
paillasse-contenus/05-routage-ospf/lab.yaml
Normal file
63
paillasse-contenus/05-routage-ospf/lab.yaml
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
id: 05-routage-ospf
|
||||||
|
titre: Routage dynamique avec OSPF
|
||||||
|
niveau: intermediaire
|
||||||
|
duree_min: 60
|
||||||
|
formations: [nsi-tle, bts-sio-sisr, bts-ciel-ir, but-rt]
|
||||||
|
competences: [routage-dynamique, ospf, frr]
|
||||||
|
|
||||||
|
reseaux:
|
||||||
|
- nom: lan-a
|
||||||
|
cidr: 10.1.0.0/24
|
||||||
|
- nom: lien-12
|
||||||
|
cidr: 10.12.0.0/30
|
||||||
|
- nom: lien-23
|
||||||
|
cidr: 10.23.0.0/30
|
||||||
|
- nom: lan-c
|
||||||
|
cidr: 10.3.0.0/24
|
||||||
|
|
||||||
|
machines:
|
||||||
|
- nom: r1
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lan-a, lien-12]
|
||||||
|
- nom: r2
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lien-12, lien-23]
|
||||||
|
- nom: r3
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lien-23, lan-c]
|
||||||
|
|
||||||
|
consignes:
|
||||||
|
- "Les adresses sont déjà posées : relève-les avec ip -4 addr sur chaque routeur."
|
||||||
|
- "Active le démon ospfd de FRR sur les trois routeurs."
|
||||||
|
- "Avec vtysh, annonce tous les réseaux de chaque routeur dans l'aire 0."
|
||||||
|
- "Vérifie que r1 apprend le réseau 10.3.0.0/24 par OSPF."
|
||||||
|
|
||||||
|
verifications:
|
||||||
|
- id: ospf-r1
|
||||||
|
titre: r1 apprend le LAN C
|
||||||
|
machine: r1
|
||||||
|
commande: "vtysh -c 'show ip route ospf' | grep -q '10.3.0.0/24'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 3
|
||||||
|
message_echec: "r1 ne connaît pas 10.3.0.0/24 par OSPF."
|
||||||
|
- id: ospf-r3
|
||||||
|
titre: r3 apprend le LAN A
|
||||||
|
machine: r3
|
||||||
|
commande: "vtysh -c 'show ip route ospf' | grep -q '10.1.0.0/24'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 3
|
||||||
|
message_echec: "r3 ne connaît pas 10.1.0.0/24 par OSPF."
|
||||||
|
- id: voisins-r2
|
||||||
|
titre: r2 a deux voisins OSPF
|
||||||
|
machine: r2
|
||||||
|
commande: "test \"$(vtysh -c 'show ip ospf neighbor' | grep -c Full)\" -ge 2"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "r2 n'a pas deux voisins OSPF à l'état Full."
|
||||||
|
|
||||||
|
indices:
|
||||||
|
- "Dans /etc/frr/daemons, passe ospfd=yes puis redémarre frr."
|
||||||
|
- "router ospf, puis network 10.12.0.0/30 area 0, etc."
|
||||||
56
paillasse-contenus/06-chiffrement-https/lab.yaml
Normal file
56
paillasse-contenus/06-chiffrement-https/lab.yaml
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
id: 06-chiffrement-https
|
||||||
|
titre: Chiffrement et HTTPS
|
||||||
|
niveau: intermediaire
|
||||||
|
duree_min: 50
|
||||||
|
formations: [nsi-tle, bts-sio, bts-ciel-ir, but-rt, ais]
|
||||||
|
competences: [chiffrement-asymetrique, certificats, tls]
|
||||||
|
|
||||||
|
reseaux:
|
||||||
|
- nom: lan
|
||||||
|
cidr: 10.60.0.0/24
|
||||||
|
|
||||||
|
machines:
|
||||||
|
- nom: serveur
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lan]
|
||||||
|
|
||||||
|
consignes:
|
||||||
|
- "Génère une clé privée RSA 2048 bits et un certificat auto-signé pour le nom labo.paillasse.local, valable 30 jours, dans /etc/ssl/labo/."
|
||||||
|
- "Configure nginx pour servir sa page en HTTPS sur le port 443 avec ce certificat."
|
||||||
|
- "Redirige HTTP (port 80) vers HTTPS."
|
||||||
|
- "Protège la clé privée : seul root doit pouvoir la lire."
|
||||||
|
|
||||||
|
verifications:
|
||||||
|
- id: certificat
|
||||||
|
titre: Certificat au bon nom
|
||||||
|
machine: serveur
|
||||||
|
commande: "openssl x509 -in /etc/ssl/labo/labo.crt -noout -subject | grep -q 'labo.paillasse.local'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "Le certificat /etc/ssl/labo/labo.crt est absent ou n'a pas le bon nom."
|
||||||
|
- id: https
|
||||||
|
titre: HTTPS répond
|
||||||
|
machine: serveur
|
||||||
|
commande: "curl -sk --max-time 3 -o /dev/null -w '%{http_code}' https://localhost/ | grep -q 200"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 3
|
||||||
|
message_echec: "nginx ne répond pas en HTTPS sur le port 443."
|
||||||
|
- id: redirection
|
||||||
|
titre: HTTP redirige vers HTTPS
|
||||||
|
machine: serveur
|
||||||
|
commande: "curl -s --max-time 3 -o /dev/null -w '%{http_code}' http://localhost/ | grep -Eq '301|302|308'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "Le port 80 ne redirige pas vers HTTPS."
|
||||||
|
- id: cle
|
||||||
|
titre: Clé privée protégée
|
||||||
|
machine: serveur
|
||||||
|
commande: "test \"$(stat -c %a /etc/ssl/labo/labo.key)\" = 600"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "La clé privée doit avoir les droits 600."
|
||||||
|
|
||||||
|
indices:
|
||||||
|
- "openssl req -x509 -newkey rsa:2048 -nodes -days 30 -subj '/CN=labo.paillasse.local' …"
|
||||||
|
- "Dans nginx : listen 443 ssl; ssl_certificate …; ssl_certificate_key …;"
|
||||||
51
paillasse-contenus/07-sql/lab.yaml
Normal file
51
paillasse-contenus/07-sql/lab.yaml
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
id: 07-sql
|
||||||
|
titre: Interroger une base MariaDB
|
||||||
|
niveau: intermediaire
|
||||||
|
duree_min: 50
|
||||||
|
formations: [nsi-tle, stmg-sig, bts-sio-slam, bts-sio-sisr, but-info]
|
||||||
|
competences: [sql-select, jointures, ddl, droits-sgbd]
|
||||||
|
|
||||||
|
reseaux:
|
||||||
|
- nom: isole
|
||||||
|
cidr: 10.0.0.0/24
|
||||||
|
|
||||||
|
machines:
|
||||||
|
- nom: bdd
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [isole]
|
||||||
|
preparation: "systemctl enable --now mariadb && mysql < /opt/labs/07/lycee.sql"
|
||||||
|
|
||||||
|
consignes:
|
||||||
|
- "La base `lycee` contient les tables eleves, classes et notes. Explore-la."
|
||||||
|
- "Crée la vue `moyennes` qui donne, pour chaque élève, son pseudonyme et sa moyenne."
|
||||||
|
- "Crée la table `clubs` (id clé primaire auto-incrémentée, nom texte non nul) et insère au moins 3 clubs."
|
||||||
|
- "Crée l'utilisateur `prof` qui peut seulement lire (SELECT) la base lycee."
|
||||||
|
|
||||||
|
verifications:
|
||||||
|
- id: vue
|
||||||
|
titre: Vue moyennes
|
||||||
|
machine: bdd
|
||||||
|
commande: "mysql -N -e 'SELECT COUNT(*) FROM lycee.moyennes' | grep -Eq '^[1-9]'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 3
|
||||||
|
message_echec: "La vue lycee.moyennes n'existe pas ou est vide."
|
||||||
|
- id: table
|
||||||
|
titre: Table clubs remplie
|
||||||
|
machine: bdd
|
||||||
|
commande: "test \"$(mysql -N -e 'SELECT COUNT(*) FROM lycee.clubs')\" -ge 3"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "La table lycee.clubs n'existe pas ou contient moins de 3 lignes."
|
||||||
|
- id: droits
|
||||||
|
titre: Utilisateur prof en lecture seule
|
||||||
|
machine: bdd
|
||||||
|
commande: "mysql -N -e \"SHOW GRANTS FOR 'prof'@'localhost'\" | grep -q 'GRANT SELECT ON `lycee`'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "L'utilisateur prof n'a pas exactement le droit SELECT sur lycee."
|
||||||
|
|
||||||
|
indices:
|
||||||
|
- "SHOW TABLES; puis DESCRIBE eleves;"
|
||||||
|
- "CREATE VIEW moyennes AS SELECT … JOIN … GROUP BY …;"
|
||||||
|
- "GRANT SELECT ON lycee.* TO 'prof'@'localhost';"
|
||||||
76
paillasse-contenus/08-deux-lan-routeur/cours.md
Normal file
76
paillasse-contenus/08-deux-lan-routeur/cours.md
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Séquence 08 : deux LAN et un routeur
|
||||||
|
|
||||||
|
## Objectifs
|
||||||
|
|
||||||
|
À la fin de cette séquence, tu sais :
|
||||||
|
- configurer une adresse IPv4 et son masque sous Linux ;
|
||||||
|
- expliquer le rôle d'une passerelle par défaut ;
|
||||||
|
- transformer une machine Linux en routeur ;
|
||||||
|
- diagnostiquer un problème de communication pas à pas.
|
||||||
|
|
||||||
|
## 1. Deux réseaux séparés
|
||||||
|
|
||||||
|
Un réseau local (LAN) regroupe des machines qui partagent le même préfixe. Avec un masque `/24`, les trois premiers octets désignent le réseau : `192.168.1.10` et `192.168.1.25` sont sur le même LAN, `192.168.2.10` est sur un autre.
|
||||||
|
|
||||||
|
Deux machines du même LAN se parlent directement. Pour joindre un autre LAN, il faut passer par un **routeur**.
|
||||||
|
|
||||||
|
## 2. Configurer une adresse
|
||||||
|
|
||||||
|
```
|
||||||
|
ip link # liste des interfaces
|
||||||
|
sudo ip addr add 192.168.1.10/24 dev ens3
|
||||||
|
sudo ip link set ens3 up
|
||||||
|
ip -4 addr # vérifier
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. La passerelle par défaut
|
||||||
|
|
||||||
|
Quand une machine doit joindre une adresse hors de son LAN, elle envoie le paquet à sa **passerelle par défaut** : le routeur de son réseau.
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo ip route add default via 192.168.1.1
|
||||||
|
ip route # vérifier
|
||||||
|
```
|
||||||
|
|
||||||
|
Règle à retenir : la passerelle est **toujours sur le même LAN** que la machine.
|
||||||
|
|
||||||
|
## 4. Un Linux qui route
|
||||||
|
|
||||||
|
Par défaut, Linux jette les paquets qui ne lui sont pas destinés. Pour qu'il les transmette d'une interface à l'autre :
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Pour que ce soit permanent, on l'écrit dans `/etc/sysctl.d/routage.conf` :
|
||||||
|
```
|
||||||
|
net.ipv4.ip_forward = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. Diagnostiquer dans l'ordre
|
||||||
|
|
||||||
|
Quand « ça ne ping pas », on avance du plus proche au plus loin :
|
||||||
|
|
||||||
|
1. PC-A joint-il sa passerelle `192.168.1.1` ? Sinon : adresse ou masque de PC-A.
|
||||||
|
2. PC-A joint-il l'autre patte du routeur `192.168.2.1` ? Sinon : passerelle de PC-A.
|
||||||
|
3. PC-A joint-il PC-B ? Sinon : routage du routeur, ou passerelle de **PC-B** (le retour compte aussi !).
|
||||||
|
|
||||||
|
`tcpdump -i ens4 icmp` sur le routeur montre si les paquets passent.
|
||||||
|
|
||||||
|
## 6. Rendre la configuration permanente
|
||||||
|
|
||||||
|
Les commandes `ip` sont perdues au redémarrage. Sous Debian, on écrit la configuration dans `/etc/network/interfaces` :
|
||||||
|
|
||||||
|
```
|
||||||
|
auto ens3
|
||||||
|
iface ens3 inet static
|
||||||
|
address 192.168.1.10/24
|
||||||
|
gateway 192.168.1.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## À retenir
|
||||||
|
|
||||||
|
- Même préfixe = même LAN = communication directe.
|
||||||
|
- Autre LAN = passage par la passerelle par défaut.
|
||||||
|
- Un routeur Linux a besoin de `ip_forward = 1`.
|
||||||
|
- Le chemin retour compte autant que l'aller.
|
||||||
115
paillasse-contenus/08-deux-lan-routeur/lab.yaml
Normal file
115
paillasse-contenus/08-deux-lan-routeur/lab.yaml
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
id: 08-deux-lan-routeur
|
||||||
|
titre: Deux LAN et un routeur
|
||||||
|
niveau: decouverte
|
||||||
|
duree_min: 45
|
||||||
|
formations: [nsi-tle, bts-sio-sisr, bts-ciel-ir, but-rt, bac-pro-ciel, tssr]
|
||||||
|
competences: [adressage-ipv4, passerelle, routage-statique, ip-forwarding, diagnostic]
|
||||||
|
|
||||||
|
reseaux:
|
||||||
|
- nom: lan1
|
||||||
|
cidr: 192.168.1.0/24
|
||||||
|
- nom: lan2
|
||||||
|
cidr: 192.168.2.0/24
|
||||||
|
|
||||||
|
machines:
|
||||||
|
- nom: pc-a
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lan1]
|
||||||
|
- nom: routeur
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lan1, lan2]
|
||||||
|
- nom: pc-b
|
||||||
|
image: paillasse-debian
|
||||||
|
flavor: eleve.petit
|
||||||
|
reseaux: [lan2]
|
||||||
|
|
||||||
|
consignes:
|
||||||
|
- "Repère le nom des interfaces de chaque machine avec `ip link`."
|
||||||
|
- "Attribue 192.168.1.10/24 à PC-A."
|
||||||
|
- "Attribue 192.168.1.1/24 et 192.168.2.1/24 aux deux interfaces du routeur."
|
||||||
|
- "Attribue 192.168.2.10/24 à PC-B."
|
||||||
|
- "Donne à PC-A et PC-B leur passerelle par défaut : l'adresse du routeur sur leur LAN."
|
||||||
|
- "Active le routage IP sur le routeur."
|
||||||
|
- "Vérifie que PC-A joint PC-B avec `ping`."
|
||||||
|
- "Bonus : rends la configuration permanente (elle doit survivre à un redémarrage)."
|
||||||
|
|
||||||
|
verifications:
|
||||||
|
- id: ip-pc-a
|
||||||
|
titre: Adresse de PC-A
|
||||||
|
machine: pc-a
|
||||||
|
commande: "ip -4 -o addr | grep -q ' 192.168.1.10/24 '"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "PC-A n'a pas l'adresse 192.168.1.10/24."
|
||||||
|
|
||||||
|
- id: ip-routeur-lan1
|
||||||
|
titre: Adresse du routeur sur le LAN 1
|
||||||
|
machine: routeur
|
||||||
|
commande: "ip -4 -o addr | grep -q ' 192.168.1.1/24 '"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "Le routeur n'a pas 192.168.1.1/24 sur son interface du LAN 1."
|
||||||
|
|
||||||
|
- id: ip-routeur-lan2
|
||||||
|
titre: Adresse du routeur sur le LAN 2
|
||||||
|
machine: routeur
|
||||||
|
commande: "ip -4 -o addr | grep -q ' 192.168.2.1/24 '"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "Le routeur n'a pas 192.168.2.1/24 sur son interface du LAN 2."
|
||||||
|
|
||||||
|
- id: ip-pc-b
|
||||||
|
titre: Adresse de PC-B
|
||||||
|
machine: pc-b
|
||||||
|
commande: "ip -4 -o addr | grep -q ' 192.168.2.10/24 '"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "PC-B n'a pas l'adresse 192.168.2.10/24."
|
||||||
|
|
||||||
|
- id: passerelle-pc-a
|
||||||
|
titre: Passerelle de PC-A
|
||||||
|
machine: pc-a
|
||||||
|
commande: "ip route show default | grep -q 'via 192.168.1.1'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "PC-A n'a pas de route par défaut via 192.168.1.1."
|
||||||
|
|
||||||
|
- id: passerelle-pc-b
|
||||||
|
titre: Passerelle de PC-B
|
||||||
|
machine: pc-b
|
||||||
|
commande: "ip route show default | grep -q 'via 192.168.2.1'"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "PC-B n'a pas de route par défaut via 192.168.2.1."
|
||||||
|
|
||||||
|
- id: forwarding
|
||||||
|
titre: Routage activé sur le routeur
|
||||||
|
machine: routeur
|
||||||
|
commande: "test \"$(cat /proc/sys/net/ipv4/ip_forward)\" = 1"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "Le routeur ne transmet pas les paquets : regarde net.ipv4.ip_forward."
|
||||||
|
|
||||||
|
- id: ping-a-vers-b
|
||||||
|
titre: PC-A joint PC-B
|
||||||
|
machine: pc-a
|
||||||
|
commande: "ping -c 2 -W 1 192.168.2.10"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 2
|
||||||
|
message_echec: "PC-A ne joint pas PC-B. Vérifie les adresses, les passerelles et le routage, dans cet ordre."
|
||||||
|
|
||||||
|
- id: bonus-permanent
|
||||||
|
titre: "Bonus : configuration permanente"
|
||||||
|
machine: routeur
|
||||||
|
commande: "grep -rqs 'ip_forward *= *1' /etc/sysctl.conf /etc/sysctl.d/ && grep -rqs '192.168.2.1' /etc/network/interfaces /etc/network/interfaces.d/ /etc/systemd/network/"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "La configuration du routeur disparaîtra au redémarrage (sysctl et fichier d'interfaces)."
|
||||||
|
|
||||||
|
indices:
|
||||||
|
- "`ip addr add 192.168.1.10/24 dev <interface>` puis `ip link set <interface> up`."
|
||||||
|
- "La passerelle s'ajoute avec `ip route add default via <adresse>`."
|
||||||
|
- "Le routage se lit dans /proc/sys/net/ipv4/ip_forward et s'active avec `sysctl`."
|
||||||
|
- "Si le ping échoue, teste d'abord PC-A vers 192.168.1.1, puis 192.168.2.1, puis PC-B."
|
||||||
35
paillasse-contenus/08-deux-lan-routeur/quiz.gift
Normal file
35
paillasse-contenus/08-deux-lan-routeur/quiz.gift
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Quiz séquence 08 : deux LAN et un routeur (format GIFT)
|
||||||
|
|
||||||
|
::Q1 Même LAN::Avec un masque /24, 192.168.1.10 et 192.168.2.10 sont-elles sur le même LAN ?{F}
|
||||||
|
|
||||||
|
::Q2 Passerelle::À quoi sert la passerelle par défaut ?{
|
||||||
|
=À envoyer les paquets destinés à un autre réseau
|
||||||
|
~À attribuer les adresses IP automatiquement
|
||||||
|
~À traduire les noms en adresses IP
|
||||||
|
~À relier deux machines du même LAN}
|
||||||
|
|
||||||
|
::Q3 Passerelle sur le LAN::La passerelle par défaut d'une machine doit se trouver :{
|
||||||
|
=sur le même LAN que la machine
|
||||||
|
~sur le LAN de destination
|
||||||
|
~n'importe où, du moment qu'elle répond au ping}
|
||||||
|
|
||||||
|
::Q4 ip_forward::Quel paramètre permet à un Linux de transmettre des paquets d'une interface à l'autre ?{
|
||||||
|
=net.ipv4.ip_forward
|
||||||
|
~net.ipv4.icmp_echo
|
||||||
|
~net.ipv4.tcp_syncookies
|
||||||
|
~net.ipv4.conf.all.rp_filter}
|
||||||
|
|
||||||
|
::Q5 Commande adresse::Quelle commande ajoute l'adresse 192.168.1.10/24 à l'interface ens3 ?{
|
||||||
|
=ip addr add 192.168.1.10/24 dev ens3
|
||||||
|
~ip route add 192.168.1.10/24 dev ens3
|
||||||
|
~ip link set ens3 192.168.1.10/24
|
||||||
|
~ifconfig add ens3 192.168.1.10}
|
||||||
|
|
||||||
|
::Q6 Hôtes /24::Combien d'hôtes peut-on adresser dans un réseau /24 ?{#254}
|
||||||
|
|
||||||
|
::Q7 Diagnostic::PC-A joint les deux interfaces du routeur mais pas PC-B. Le routage est actif. Cause la plus probable ?{
|
||||||
|
=PC-B n'a pas de passerelle par défaut
|
||||||
|
~PC-A n'a pas de passerelle par défaut
|
||||||
|
~Le câble entre PC-A et le routeur est coupé}
|
||||||
|
|
||||||
|
::Q8 Permanent::Les adresses ajoutées avec la commande ip survivent à un redémarrage.{F}
|
||||||
55
paillasse-contenus/08-deux-lan-routeur/td.md
Normal file
55
paillasse-contenus/08-deux-lan-routeur/td.md
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
# TD 08 : adresses, masques et passerelles
|
||||||
|
|
||||||
|
## Exercice 1 : même LAN ou pas ?
|
||||||
|
|
||||||
|
Avec un masque /24, ces machines peuvent-elles communiquer directement ?
|
||||||
|
|
||||||
|
1. 192.168.1.10 et 192.168.1.200
|
||||||
|
2. 192.168.1.10 et 192.168.2.10
|
||||||
|
3. 10.0.0.5 et 10.0.0.250
|
||||||
|
4. 172.16.4.1 et 172.16.5.1
|
||||||
|
|
||||||
|
## Exercice 2 : adresse de réseau et diffusion
|
||||||
|
|
||||||
|
Donne l'adresse du réseau, l'adresse de diffusion et le nombre d'hôtes possibles :
|
||||||
|
|
||||||
|
1. 192.168.1.10/24
|
||||||
|
2. 10.20.30.40/16
|
||||||
|
3. 192.168.5.130/25
|
||||||
|
|
||||||
|
## Exercice 3 : plan d'adressage du lab
|
||||||
|
|
||||||
|
Complète le tableau pour la topologie PC-A – LAN 1 – Routeur – LAN 2 – PC-B :
|
||||||
|
|
||||||
|
| Machine | Interface | Adresse/masque | Passerelle |
|
||||||
|
|---|---|---|---|
|
||||||
|
| PC-A | ens3 | | |
|
||||||
|
| Routeur | ens3 (LAN 1) | | — |
|
||||||
|
| Routeur | ens4 (LAN 2) | | — |
|
||||||
|
| PC-B | ens3 | | |
|
||||||
|
|
||||||
|
## Exercice 4 : diagnostic
|
||||||
|
|
||||||
|
PC-A joint 192.168.1.1 et 192.168.2.1, mais pas PC-B. Le routage est activé sur le routeur. Quelle est la cause la plus probable ?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Corrigé
|
||||||
|
|
||||||
|
**Ex. 1** : 1. oui · 2. non · 3. oui · 4. non.
|
||||||
|
|
||||||
|
**Ex. 2** :
|
||||||
|
1. réseau 192.168.1.0, diffusion 192.168.1.255, 254 hôtes ;
|
||||||
|
2. réseau 10.20.0.0, diffusion 10.20.255.255, 65 534 hôtes ;
|
||||||
|
3. réseau 192.168.5.128, diffusion 192.168.5.255, 126 hôtes.
|
||||||
|
|
||||||
|
**Ex. 3** :
|
||||||
|
|
||||||
|
| Machine | Interface | Adresse/masque | Passerelle |
|
||||||
|
|---|---|---|---|
|
||||||
|
| PC-A | ens3 | 192.168.1.10/24 | 192.168.1.1 |
|
||||||
|
| Routeur | ens3 (LAN 1) | 192.168.1.1/24 | — |
|
||||||
|
| Routeur | ens4 (LAN 2) | 192.168.2.1/24 | — |
|
||||||
|
| PC-B | ens3 | 192.168.2.10/24 | 192.168.2.1 |
|
||||||
|
|
||||||
|
**Ex. 4** : PC-B n'a pas de passerelle par défaut (ou une mauvaise). Le ping arrive, mais la réponse ne sait pas revenir.
|
||||||
70
paillasse-contenus/README.md
Normal file
70
paillasse-contenus/README.md
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
# Pack de contenus Paillasse
|
||||||
|
|
||||||
|
> Recréé le 7 octobre 2026. À relire par un enseignant avant usage en classe.
|
||||||
|
|
||||||
|
## Organisation
|
||||||
|
|
||||||
|
```
|
||||||
|
paillasse-contenus/
|
||||||
|
├── README.md ce fichier : format des labs
|
||||||
|
├── sources-et-licences.md ce qu'on peut réutiliser, et sous quelle licence
|
||||||
|
└── NN-nom-sequence/
|
||||||
|
├── lab.yaml le lab : machines, réseaux, consignes, vérifications
|
||||||
|
├── cours.md (séquence 08 complète ; les autres cours sont dans design/js/contenus-*.js)
|
||||||
|
├── td.md exercices papier avec corrigé
|
||||||
|
└── quiz.gift quiz au format GIFT (importable dans Moodle)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Format d'un lab (`lab.yaml`)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: 08-deux-lan-routeur # identifiant unique, = nom du dossier
|
||||||
|
titre: Deux LAN et un routeur
|
||||||
|
niveau: decouverte # decouverte | intermediaire | avance
|
||||||
|
duree_min: 45
|
||||||
|
formations: [nsi-tle, bts-sio-sisr, bts-ciel-ir, but-rt]
|
||||||
|
competences: [adressage-ipv4, routage-statique]
|
||||||
|
|
||||||
|
reseaux: # deviennent des réseaux Neutron (modèle Heat)
|
||||||
|
- nom: lan1
|
||||||
|
cidr: 192.168.1.0/24 # informatif : pas de DHCP, port_security désactivé
|
||||||
|
|
||||||
|
machines: # deviennent des VM Nova
|
||||||
|
- nom: pc-a
|
||||||
|
image: paillasse-debian # image commune (voir plus bas)
|
||||||
|
flavor: eleve.petit # 1 vCPU, 768 Mo, 5 Go
|
||||||
|
reseaux: [lan1] # ordre = ordre des interfaces (ens3, ens4…)
|
||||||
|
|
||||||
|
consignes: # affichées à gauche du terminal
|
||||||
|
- Attribue l'adresse 192.168.1.10/24 à PC-A.
|
||||||
|
|
||||||
|
verifications: # exécutées par le service correcteur via l'agent QEMU
|
||||||
|
- id: ip-pc-a
|
||||||
|
titre: Adresse de PC-A
|
||||||
|
machine: pc-a
|
||||||
|
commande: "ip -4 -o addr | grep -q ' 192.168.1.10/24 '"
|
||||||
|
attendu: { code_retour: 0 }
|
||||||
|
points: 1
|
||||||
|
message_echec: "PC-A n'a pas l'adresse 192.168.1.10/24."
|
||||||
|
|
||||||
|
indices: # débloqués un par un par l'élève (comptés dans le suivi prof)
|
||||||
|
- "La commande `ip addr add` attend une adresse avec son masque."
|
||||||
|
```
|
||||||
|
|
||||||
|
## Règles pour le correcteur
|
||||||
|
|
||||||
|
1. Le correcteur n'exécute **que** les commandes déclarées dans `verifications`. Jamais de commande venant du portail ou de l'élève.
|
||||||
|
2. Chaque commande est exécutée en root dans la VM avec `guest-exec` de l'agent QEMU, avec un délai max de 10 s.
|
||||||
|
3. Une vérification réussit si le code retour vaut `attendu.code_retour`. Option : `attendu.sortie_contient: "texte"`.
|
||||||
|
4. Les commandes ne dépendent pas des noms d'interface (`ens3`…) quand c'est évitable.
|
||||||
|
5. Note = somme des points des vérifications réussies.
|
||||||
|
|
||||||
|
## Image commune `paillasse-debian`
|
||||||
|
|
||||||
|
Construite avec `virt-customize` depuis l'image cloud Debian 12 :
|
||||||
|
|
||||||
|
- `qemu-guest-agent`, getty sur `ttyS0`, utilisateur `eleve` (sudo, mot de passe `eleve`) ;
|
||||||
|
- réseau : iproute2, iputils-ping, traceroute, tcpdump, dnsutils, curl, netcat-openbsd ;
|
||||||
|
- services préinstallés **désactivés** : nginx, mariadb-server, frr ;
|
||||||
|
- outils : openssl, nano, vim, tree, htop ;
|
||||||
|
- `/opt/paquets/` : quelques `.deb` locaux pour le lab 02 (les VM n'ont pas Internet).
|
||||||
32
paillasse-contenus/sources-et-licences.md
Normal file
32
paillasse-contenus/sources-et-licences.md
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Sources et licences
|
||||||
|
|
||||||
|
> À vérifier avant toute publication. Ne jamais copier un contenu sous licence NC (non commerciale) dans une offre payante.
|
||||||
|
|
||||||
|
## Réutilisables (CC BY-SA), en citant l'auteur et en gardant la même licence
|
||||||
|
|
||||||
|
- Lyceum
|
||||||
|
- G. Lassus, NSI Terminale
|
||||||
|
- CodEx
|
||||||
|
|
||||||
|
## Lien seulement (licence NC) : on peut pointer vers eux, pas les copier
|
||||||
|
|
||||||
|
- Réseau Certa
|
||||||
|
- Banque nationale de sujets (BNS) NSI
|
||||||
|
- « Enseigner les SNT »
|
||||||
|
- cours-nsi (Forge)
|
||||||
|
|
||||||
|
## Licence inconnue : ne pas réutiliser sans accord écrit
|
||||||
|
|
||||||
|
- informatiquelycee
|
||||||
|
|
||||||
|
## Inspiration (sans copie)
|
||||||
|
|
||||||
|
- blog.stephane-robert.info/formations
|
||||||
|
|
||||||
|
## Programmes officiels
|
||||||
|
|
||||||
|
Voir `docs/referentiel-pedagogique-paillasse.md`. Lier le BO ou la fiche RNCP, ne jamais utiliser les logos de l'État.
|
||||||
|
|
||||||
|
## Licence des contenus Paillasse
|
||||||
|
|
||||||
|
À choisir plus tard (CC BY-SA ou propriétaire).
|
||||||
Loading…
Add table
Add a link
Reference in a new issue