TP sysres IMA5sc 2018/2019 G3 : Différence entre versions

De Wiki d'activités IMA
(Partie TP commune)
(Partie TP commune)
Ligne 406 : Ligne 406 :
  
 
Pour attester du bon fonctionnement de DNSSEC, on pourra utiliser le site http://dnsviz.net/.
 
Pour attester du bon fonctionnement de DNSSEC, on pourra utiliser le site http://dnsviz.net/.
 +
 +
=Sécuriser apache2 : SSL/TLS=
 +
 +
Continuer ...
  
 
=Partie TP personnelle=
 
=Partie TP personnelle=

Version du 11 décembre 2018 à 21:56

Première séance

Nous allons au cours de cette première séance mettre en place un réseau de 3 conteneurs from scratch en exploitant le principe des espaces de noms pour assurer l'isolation. Un des conteneurs agira comme serveur mandataire inverse plus communément appelé reverse proxy et aura pour rôle de dispatcher les requêtes vers les deux autres conteneurs serveur web suivant le nom de domaine ciblé par l'utilisateur. Ces deux conteneurs ne seront pas accessibles directement depuis le réseau, c'est le reverse proxy qui assura la liaison entre ces deux différents réseaux.

Création des fichiers disque des conteneurs

On crée un fichier de 10 Gio = 10 240 * 1 Mio dont tous les octets sont égales à 0.

dd if=/dev/zero of=/home/pifou/containers/container1 bs=1024k count=10240

Création du système de fichiers

On associe un système de fichiers de type ext4 à notre fichier.

mkfs.ext4 /home/pifou/containers/container1

Montage du système de fichiers

On commence par créer les répertoires qui contiendront les rootfs montés. Dans un premier temps, on monte le système de fichiers précédemment créé dans /mnt/container1.

mkdir /mnt/container1
mkdir /mnt/container2
mkdir /mnt/container3
mount -t ext4 -o loop /home/pifou/containers/container1 /mnt/container1

Déploiement de l'arborescence Debian

Avant tout, on renseigne le proxy de l'école dans la variable d’environnement correspondante afin qu'on puisse télécharger les paquetages sur le miroir devuan extérieur à l'école.

export http_proxy=https://proxy.polytech-lille.fr:3128

Ensuite on utilise l'outil deboostrap dans /mnt/container1 pour créer un système Debian de base.

debootstrap --include=vim,nano,apache2 stable /mnt/container1

Puis on renseigne le fichier fstab de notre container1, il s'agit du fichier qui indique comment les systèmes de fichiers doivent être montés.

echo "proc /proc proc defaults 0 0" >> /mnt/container1/etc/fstab

Enfin, on peut démonter la partition

umount /mnt/container1

Une fois que nous avons déployé tout ce dont nous avons besoin au sein du container1 il ne reste plus qu'à dupliquer ce fichier deux fois, et on aura trois partitions utilisables pour nos conteneurs.

cp /home/pifou/containers/container1 /home/pifou/containers/container2
cp /home/pifou/containers/container1 /home/pifou/containers/container3

Ensuite on peut monter les trois systèmes de fichiers.

mount -t ext4 -o loop /home/pifou/containers/container1 /mnt/container1
mount -t ext4 -o loop /home/pifou/containers/container2 /mnt/container2
mount -t ext4 -o loop /home/pifou/containers/container3 /mnt/container3

Configuration des interfaces réseau

Pour l'instant, on a tout ce qu'il faut pour lancer les conteneurs, seulement ils seraient bien inutiles s'ils ne pouvaient aucunement communiquer entre eux ou avec le système hôte. C'est pourquoi on va créer dans le système hôte 4 interfaces virtuelles pour les 3 conteneurs (un conteneur aura deux interfaces virtuelles dont l'une sera dans le bridge donnant accès à internet, il s’agira de notre conteneur qui agira comme serveur mandataire inverse). On va donc créer un commutateur virtuel dans lequel on mettra les trois interfaces virtuelles vif1, vif2 et vif3 de nos trois conteneurs.

Création du bridge

ip link add monpetitpont type bridge

Création des 4 interfaces virtuelles

ip link add vif1 type veth peer name eth0@vif1
ip link add vif2 type veth peer name eth0@vif2
ip link add vif3 type veth peer name eth0@vif3
ip link add vif4 type veth peer name eth1@vif4

Connexion des interfaces virtuelles aux commutateurs virtuels

vif1 vif2 et vif3 sont mises dans monpetitpont, tandis que vif4 est mise dans bridge

ip link set vif1 master monpetitpont
ip link set vif2 master monpetitpont
ip link set vif3 master monpetitpont
ip link set vif4 master bridge

Il ne faut pas omettre d'activer les interfaces, sans quoi la communication serait impossible.

ip link set vif1 up
ip link set vif2 up
ip link set vif3 up
ip link set vif4 up

On pense à ajouter une adresse IP au commutateur virtuel, même si ce n'est pas obligatoire.

ip a add dev monpetitpont 192.168.1.1/24
ip link set monpetitpont down
ip link set monpetitpont up

Lancement et configuration réseau des 3 conteneurs

Lancement des conteneurs

Pour ce faire, on va utiliser l’utilitaire unshare permettant de lancer des programmes avec des espaces de noms différents de ceux du parent.

unshare -n -u -p -f -m chroot /mnt/container1 /bin/sh -c "mount /proc ; /bin/bash"

On avait créé dans la partie précédente des paires d'interfaces virtuelles connectées entre elles. Les vif ont été reliés à monpetitpont, il faut maintenant connecter les autres parties aux conteneurs pour qu'ils puissent communiquer entre eux bien qu'ils aient des des espaces de noms différents. Tout ceci aura pour effet de faire apparaître une interface nommée eth0 pour chaque conteneur et une interface eth1 pour le dernier conteneur.

ip link set eth0@vif1 netns /proc/<PID_unshare_c1>/ns/net name eth0
ip link set eth0@vif2 netns /proc/<PID_unshare_c2>/ns/net name eth0
ip link set eth0@vif3 netns /proc/<PID_unshare_c3>/ns/net name eth0
ip link set eth1@vif4 netns /proc/<PID_unshare_c3>/ns/net name eth1


Les différents PID sont récupérés simplement grâce à la commande suivante.

ps aux | grep unshare

On est maintenant en mesure d'attribuer des IPs pour nos conteneurs.

ip addr add 192.168.1.2/24 dev eth0
ip addr add 192.168.1.3/24 dev eth0
ip addr add 192.168.1.4/24 dev eth0

A nouveau, il est nécessaire d'activer les interfaces eth0 de nos 3 conteneurs.

ip link set eth0 up

Nous devons mettre une adresse ip à l'interface eth1 du container3 qui se trouve dans le bridge. Pour se faire, il faut trouver une adresse ip dans le réseau 172.26.145.0/24 (on ping pour voir si une adresse est libre)

ip addr add 172.26.145.150/24  dev eth1

Nous sommes maintenant en mesure de pinger les conteneurs entre-eux mais également les machines de la salle avec le conteneur 3 et son interface eth1 dont l'autre morceau est connecté au bridge de la machine.

Seconde séance

Suite de la première séance

Nous allons créer des sous-domaines du domaine plil.space mis à notre disposition chez Gandi.

Tout d'abord nous créons une entrée de type "A" avec comme nom "durotduq.plil.space" et qui pointe vers 172.26.145.150. Ensuite, nous ajoutons deux entrées CNAME "durotduq1" et "durotduq2" avec comme valeur "durotduq". Bien qu'au final tous ces sous-domaines dirigent vers 172.26.145.150, le reverse proxy sera quand même en mesure de distinguer les requêtes entrantes et de les dispatcher vers les services concernés selon le sous-domaine.

10h15 => Serveurs Web unshare OK

Sur le conteneur mandataire inverse, on applique la configuration suivante dans le fichier /etc/apache2/sites-enabled/000-default.conf.

<VirtualHost *:80>
ServerName durotduq1.plil.space ServerAdmin webmaster@localhost
ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined
ProxyPass / http://192.168.1.101/ ProxyPassReverse / http://192.168.1.101/ ProxyRequests Off
</VirtualHost>
<VirtualHost *:80>
ServerName durotduq2.plil.space ServerAdmin webmaster@localhost
ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined
ProxyPass / http://192.168.1.102/ ProxyPassReverse / http://192.168.1.102/ ProxyRequests Off
</VirtualHost>

192.168.1.102 et 192.168.1.101 étant les adresses IP des conteneurs 1 et 2 dans monpetitpont. S'agissant d'adresses privées, elles sont donc non accessibles depuis l'extérieur et par conséquent toute connexion se fera par le biais du serveur mandataire inverse.

Réalisation avec Docker

Notre architecture de conteneurs from scratch fonctionne mais elle a l'inconvénient d'être relativement longue à installer et peu pratique. De plus, sans un minimum de scripting, les configurations ne peuvent être pérennisées. Ainsi, nous devions tout refaire à la main à chaque fois.

Dans la pratique, on préférera utiliser Docker comme système de gestion de conteneurs, car il permet d’une manière simple de manipuler et gérer les conteneurs. Il permet également que les configurations soient durables et offre la possibilité de gérer différentes version pour une même image et même de les distribuer.

Nous allons donc réaliser exactement la même architecture mais cette fois-ci à l'aide de Docker. Nous partirons sur la base d'une image Debian.

Lancement d'un conteneur Docker à partir de l'image debian

docker run -i -t debian /bin/bash

Export du proxy

export http_proxy=http://proxy.polytech-lille.fr:3218

Mise à jour de la liste des paquetages en local puis installation des paquetages vim, nano et apache2

apt-get update && apt-get install vim nano apache2

Maintenant, nous pouvons faire un commit des fichiers de ce conteneur, de cette manière, nous aurons une nouvelle image sur laquelle on pourra instancier des conteneurs.

Pour pouvoir réaliser ce commit, il faut connaitre l'identifiant du conteneur :

docker ps
docker commit 7e456 myapache2

A cet instant, nous avons une image myapache2 basée sur Debian avec les paquetages listés précédemment. La présence de cette image se vérifier avec la commande suivante.

docker images

Maintenant que nous sommes en mesure de lancer 3 conteneurs identiques contenant un serveur web Apache 2, nous créons un réseau Docker pour interconnecter les conteneurs. Sans précision de l'option --driver, il s'agit par défaut d'un bridge, ce que nous voulons.

docker network create pontpont

Nous pouvons à présent lancer les 3 conteneurs en spécifiant leur réseau d'attache et sans oublier d'exposer le port 80 du conteneur reverse proxy en le rendant accessible depuis le port 80 de la machine. Il faudra donc veiller à changer l'entrée DNS de type A avec l'IP de la zabeth (172.26.145.37).

docker run --net pontpont -i -t myapache2 /bin/bash
docker run --net pontpont -i -t myapache2 /bin/bash
docker run --net pontpont -p 80:80 -i -t myapache2 /bin/bash

La suite est très similaire à ce qui a été fait en première partie.

On repère les IPs des conteneurs 1 et 2 pour pouvoir adapter la configuration d'Apache 2 et on change la valeur de l'entrée DNS de type A durotduq.plil.space avec l'IP de la zabeth.

Le résultat final est bien évidemment identique, la solution moins formatricice certes mais plus pratique et utilisée en production.

12h10 => Serveurs Web docker OK


Partie TP commune

Création des machines virtuelles

Pour réaliser cette partie du TP nous avons besoin d'une machine virtuelle, nous allons la créer sur cordouan à l'aide de l'hyperviseur xen.

Nous créons donc une image qui sera la base de notre machine :

xen-create-image --hostname=pegase --ip=193.48.57.179 --netmask=255.255.255.240 --gateway=193.48.57.160 -size=10Gb --swap=128Mb --lvm=virtual

Une fois que cette image est créée, on édite le fichier de configuration /etc/xen/pegase.cfg afin de lui attribuer une interface réseau virtuelle qui sera dans le bridge IMA5sc.

vif = [ 'mac=00:16:3E:6F:37:08, bridge=IMA5sc' ]

Une fois le fichier de configuration créé, nous pouvons lancer la machine virtuelle à l'aide de la commande suivante et de son option -c permettant d'afficher la console.

xl create -c /etc/xen/pegase.cfg

Le mot de passe root était affiché à l'écran à la fin de la création de la machine virtuelle, mais il est toujours possible d'aller le récupérer dans les logs dans le fichier /var/log/xen-tools/pegase.log

Ajout de partitions logiques

Notre machine virtuelle fonctionne et est connectée au réseau. Pour le moment un seul volume de 10Go accueil notre système. Pour les besoins du TP, nous allons sur l'hôte (cordouan) créer deux volumes virtuels, un pour le /home et un autre pour le /var. Nous allons créer ces volumes virtuels dans le groupe de volume "virtual". Nous ajoutons également trois volumes de 1Gb afin de faire un RAID 5 logiciel dans la machine virtuelle.

lvcreate -L10G -n pegase-home virtual
lvcreate -L10G -n pegase-var virtual
lvcreate -L1G -n pegase-part1 virtual
lvcreate -L1G -n pegase-part2 virtual
lvcreate -L1G -n pegase-part3 virtual

Nous ajoutons ensuite ces volumes à notre machine virtuelle en tant que disque physique xvdb1, xvdc1, etc...

root        = '/dev/xvda2 ro'
disk        = [
                 'phy:/dev/virtual/pegase-disk,xvda2,w',
                 'phy:/dev/virtual/pegase-swap,xvda1,w',
                 'phy:/dev/virtual/Pegase-home,xvdb1,w',
                 'phy:/dev/virtual/Pegase-var,xvdc1,w',
                 'phy:/dev/virtual/pegase-part1,xvdd1,w',
                 'phy:/dev/virtual/pegase-part2,xvde1,w',
                 'phy:/dev/virtual/pegase-part3,xvdf1,w'
             ]


Nous pouvons maintenant redémarrer la machine et monter un système de fichier sur nos disques. On peut vérifier qu'ils existent d'ailleurs à l'aide de la commande fdisk -l.

mkfs -t ext4 xvdb1
mkfs -t ext4 xvdc1
mkfs -t ext4 xvdd1
mkfs -t ext4 xvde1
mkfs -t ext4 xvdf1

Nous ajoutons le montage du disque xvdb1 en tant que /home dans /etc/fstab

/dev/xvdb1 /home ext4 defaults 0 2

Pour le /var, il faut faire attention de ne pas perdre les données déjà existante, au risque d'avoir une machine inutilisable. Ainsi, on va venir monter temporairement le disque xvdc1 dans /mnt avant d'y déplacer l'intégralité du /var.

mount /dev/xvdc1 /mnt
mv /var/* /mnt

Une fois ceci fait, nous pouvons le rajouter dans /etc/fstab

/dev/xvdc1 /var ext4 defaults 0 2

Maintenant, intéressons nous au RAID, nous avons utilisé l'utilitaire mdadm afin de réaliser le RAID5 en logiciel. Puis nous avons formaté la partition formée par le raid avant de la monter. Puis nous créons un fichier sur cette partition.

mdadm --create /dev/md0 --level=5 --assume-clean --raid-devices=3 /dev/xvdd1 /dev/xvde1 /dev/xvdef1
mkfs -t ext4 /dev/md0
mount /dev/md0 /mnt
touch coucou.txt

On ajoute le /dev/md0 au /etc/fstab afin qu'il soit monté au lancement de la machine :

proc            /proc           proc    defaults        0       0
devpts          /dev/pts        devpts  rw,noexec,nosuid,gid=5,mode=620 0  0
/dev/xvda1 none swap sw 0 0
/dev/xvda2 / ext4 noatime,nodiratime,errors=remount-ro 0 1
/dev/xvdb1 /home ext4 defaults 0 2
/dev/xvdc1 /var ext4 defaults 0 2
/dev/md0   /mnt/raid ext4 defaults 0 2

On vérifie que tous nos disques ont été correctement montés :

lsblk
NAME    MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
xvda1   202:1    0  128M  0 disk  [SWAP]
xvda2   202:2    0   10G  0 disk  /
xvdb1   202:17   0   10G  0 disk  /home
xvdc1   202:33   0   10G  0 disk  /var
xvdd1   202:49   0    1G  0 disk  
`-md0   9:127  0    2G  0 raid5 /mnt
xvde1   202:65   0    1G  0 disk  
`-md0   9:127  0    2G  0 raid5 /mnt
xvdf1   202:81   0    1G  0 disk  
`-md0   9:127  0    2G  0 raid5 /mnt

Par défaut, notre raid n'a pas de fichier de configuration, nous devons en créer un. Sans fichier de configuration, le device RAID ne sera pas forcément créé dans /dev/md0 mais dans un md aléatoire, ainsi, notre fstab plantera (car nous n'aurons pas forcément le RAID sur /dev/md0). Donc nous devons avoir un fichier de configuration qui sera persistant et chargé par le noyau durant le boot.

mdadm --detail --scan --verbose >> /etc/mdadm.conf

Cette configuration ressemble à

cat /etc/mdadm.conf
ARRAY /dev/md0 level=raid5 num-devices=3 metadata=1.2 name=pegase-ansible2:0 UUID=82f804f4:49086028:d00d6af6:97fffa09
devices=/dev/xvdd1,/dev/xvde1,/dev/xvdf1


A partir de là, nous avons une configuration persistante du raid. Le RAID 5 sera identifié au boot et monté automatiquement. Nous pouvons maintenant tester notre redondance, simulons une panne sur un des disques de notre RAID, ce qui pourrait arriver dans un cas réel.

mdadm --set-faulty /dev/md0 /dev/xvdf1
mdadm --remove /dev/xvdf1

Nous constatons que notre fichier coucou.txt est toujours présent, malgré la "perte" de l'un des disques. Cependant, il faut tout de même se dire que nous avons fait un raid logiciel sur des partitions logiques, en pratique, si on perd vraiment le disque, nous perdrons quoi qu'il arrive tous les volumes logiques. Ainsi nous faisons ça pour l'aspect éducatif.

Chiffrement des disques RAID

Il peut être utile pour diverses raison de chiffrer les disques afin qu'un accès non autorisé par le propriétaire soit proscrit. Pour cela nous allons utiliser l'utilitaire cryptsetup avec le format LUKS afin de chiffrer notre disque en AES-256 avec un mot de passe.

Installation de bind et apache2

L'objectif va être d'héberger notre propre serveur DNS grâce au logiciel bind et de vérifier son fonctionnement en hébergeant un site web avec apache2. On commence donc par installer ces deux paquets :

apt-get install apache2 bind9

Configuration de Bind

Pour continuer ce TP, nous avons acheté un nom de domaine (pegase.space) sur le registraire Gandi. La configuration de bind se trouve dans le répertoire /etc/bind dans lequel nous avons créé un fichier nommé db.pegase.space représentant notre zone et avec le contenu suivant :

$TTL    604800                                                                                                                                                                                                                                                                               
@       IN      SOA     ns.pegase.space. root.pegase.space (                                                                                    
                        42      ; Serial                                                                                                        
                        604800  ; Refresh                                                                                                       
                        86400   ; Retry                                                                                                         
                        2419200 ; Expire                                                                                                        
                        604800 )        ; Negative Cache TTL                                                            
;                                                                                                                               
IN      NS      ns.pegase.space.                                                                                        
IN      NS      ns6.gandi.net.                                                                                  
ns      IN      A       193.48.57.179                                                                                   
www     IN      A       193.48.57.179                                                                                   
@       IN      A       193.48.57.179

Nous avons également modifié le fichier de configuration named.conf.local en ajoutant la ligne allow-transfer et l'IP du serveur DNS esclave, ici l'IP de ns6.gandi.net.

zone "pegase.space" {
        type master;                                                                                                            
        file "/etc/bind/db.pegase.space";                                                                                
        allow-transfer {217.70.177.40;};                                                                                
}; 

On peut maintenant redémarrer le service bind qui est maintenant opérationnel

service bind9 restart

Nous nous sommes ensuite rendu sur le site de Gandi sur lequel avons ajouté un Glue Record ns.pegase.space pointant vers l'IP de notre VM. Cet enregistrement permet la résolution du nom de notre serveur DNS qui ne peut se résoudre lui même.

On peut ensuite ajouter les serveurs maître et esclave qui seront utilisés pour résoudre les adresses de notre zone pegase.space à savoir ns.pegase.space et ns6.gandi.net.

Après un certain temps, le temps que ces informations se propagent, nous étions en mesure d'obtenir l'IP de notre VM en effectuant par exemple un

host pegase.space

Sécuriser les échanges DNS : DNSSEC

Dans cette partie, nous allons faire en sorte de certifier à un utilisateur que l'IP qu'il reçoit dans la réponse DNS est bien celle du domaine voulu. Pour ce faire, nous allons configurer bind pour qu'il soit capable d'accepter les échanges suivant le protocole DNSSEC.

On commence naturellement par activer DNSSEC en ajoutant l'option dnssec-enable yes; dans le fichier /etc/bind/named.conf.local.

On génère deux couples de clefs (ZSK et KSK) qui permettront de chiffrer ou déchiffrer les enregistrements.

dnssec-keygen -f KSK -a RSASHA256 -b 2048 -n ZONE pegase.space
dnssec-keygen -a RSASHA256 -b 2048 -n ZONE pegase.space

Nous avons ensuite renommé ces clefs pour plus de lisibilité en pegase-zsk.key, pegase-zsk.private, pegase-ksk.key, pegase-ksk.private

On ajoute ensuite via la directive include nos clefs au fichier de zone db.pegase.space

$include /etc/bind/pegase-ksk.key
$include /etc/bind/pegase-zsk.key

Nous pouvons maintenant signer la zone :

dnssec-signzone -o pegase.space -k pegase-ksk db.pegase.space pegase-zsk

Enfin, il ne faut pas oublier d'incrémenter la valeur du sérial dans db.pegase.conf et de changer le fichier de zone dans named.conf.local.

zone "pegase.space" {
        type master;                                                                                                            
        file "/etc/bind/db.pegase.space.signed";                                                                                
        allow-transfer {217.70.177.40;};                                                                                
}; 

Du coté de chez Gandi, il faut fournir les deux clefs publiques générés dans la rubrique DNSSEC en veillant à sélectionner le bon algorithme de chiffrement.

Pour attester du bon fonctionnement de DNSSEC, on pourra utiliser le site http://dnsviz.net/.

Sécuriser apache2 : SSL/TLS

Continuer ...

Partie TP personnelle

Authentification LDAP sur point d'accès

L'objectif est de pouvoir s'authentifier auprès d'une borne point d'accès wifi Cisco à l'aide de ses identifiants Polytech. Pour se faire nous allons mettre en place un serveur RADIUS à l'aide de l'implémentation Open Source FreeRADIUS (https://github.com/FreeRADIUS). Le serveur RADIUS sert à interroger le serveur LDAP afin d'authentifier l'utilisateur et lui autoriser la connexion.

Topologie de notre réseau


Tout d'abord, nous allons créer une machine virtuelle sur Cordouan afin d'y mettre le serveur RADIUS. Pour se faire nous allons installer les paquets suivants :

apt-get install freeradius freeradius-ldap

On précise freeradius-ldap pour ajouter le module ldap, en effet freeradius est un serveur d'authentification qui ne gère pas que LDAP.

Configuration du serveur RADIUS

Pour configurer notre serveur RADIUS, on édite le fichier /etc/freeradius/3.0/client


Configuration du point d'accès

ap>en
ap(config)#interface dot11radio0
ap(config)#encryption mode ciphers tkip
ap(config)#ssid PLILL
ap(config-ssid)#authentication open eap eap_methods
ap(config-ssid)#authentication network-eap eap_methods
ap(config-ssid)#end
ap(config-ssid)#ip address 172.26.145.113 255.255.255.0
ap(config)#wirte memory