Cahier 2016 groupe n°3 : Différence entre versions
(→Configuration du serveur DAS) |
(→Sauvegarde complète et automatisée des machines virtuelles) |
||
(191 révisions intermédiaires par 3 utilisateurs non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
− | = | + | = Tâche spécifique = |
− | + | Nous devons mettre en place un système de sauvegarde en réseau pour pouvoir sauvegarder l'état et les données de nos machines virtuelles. | |
− | + | Pour cela, nous allons utiliser un serveur de type DAS (Direct Attach Storage). | |
− | + | Cela consiste à une baie de stockage directement branchée sur le réseau via un câble et accessible comme n'importe quel périphérique. | |
+ | <center> | ||
+ | {| | ||
+ | | [[Fichier:schema_infra_das.png|thumb|upright=4|Schéma minimaliste de l'infrastructure]] | ||
+ | |} | ||
+ | </center> | ||
+ | |||
+ | == Gestion du serveur DAS == | ||
+ | |||
+ | === Installation des outils HP === | ||
+ | |||
+ | Ajout du dépôt dans /etc/apt/sources.net : | ||
+ | <pre> | ||
+ | deb http://downloads.linux.hpe.com/SDR/repo/mcp/ jessie/current non-free | ||
+ | </pre> | ||
+ | |||
+ | Copier / Coller le contenu des clés et les ajouter, liens des clés disponibles à ces adresses : | ||
+ | <pre> | ||
+ | http://downloads.linux.hpe.com/SDR/hpPublicKey1024.pub | ||
+ | http://downloads.linux.hpe.com/SDR/hpPublicKey2048.pub | ||
+ | http://downloads.linux.hpe.com/SDR/hpPublicKey2048_key1.pub | ||
+ | </pre> | ||
+ | |||
+ | Ajout des clefs : | ||
+ | <pre> | ||
+ | apt-key add ./hpPublicKey1024.pub | ||
+ | apt-key add ./hpPublicKey2048.pub | ||
+ | apt-key add ./hpPublicKey2048_key1.pub | ||
+ | </pre> | ||
+ | |||
+ | On met à jour les paquets et on installe l'utilitaire HP hpssacli : | ||
+ | <pre> | ||
+ | aptitude update | ||
+ | aptitude install hp-health hpssacli | ||
+ | </pre> | ||
+ | [https://oitibs.com/hp-acu-command-line-reference/ Liste des commandes disponibles pour hpssacli] | ||
+ | |||
+ | === Configuration des disques === | ||
+ | |||
+ | Après avoir installé l'utilitaire HP pour gérer nos disques, nous pouvons enfin savoir les caractéristiques des baies : | ||
+ | <pre> | ||
+ | hpssacli ctrl all show config | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On obtient alors : | ||
+ | <pre> | ||
+ | Smart Array P800 in Slot 4 (sn: P98690E9SV10C3) | ||
+ | |||
+ | |||
+ | Port Name: 1I | ||
+ | |||
+ | Port Name: 2I | ||
+ | |||
+ | Port Name: 1E | ||
+ | |||
+ | Port Name: 2E | ||
+ | |||
+ | Internal Drive Cage at Port 3I, Box 1, OK | ||
+ | |||
+ | Internal Drive Cage at Port 4I, Box 1, OK | ||
+ | |||
+ | StorageWorks MSA 60 at Port 1E, Box 1, OK | ||
+ | array A (SAS, Unused Space: 0 MB) | ||
+ | |||
+ | |||
+ | logicaldrive 1 (820.2 GB, RAID 5, OK) | ||
+ | |||
+ | physicaldrive 3I:1:1 (port 3I:box 1:bay 1, SAS, 146 GB, OK) | ||
+ | physicaldrive 3I:1:2 (port 3I:box 1:bay 2, SAS, 146 GB, OK) | ||
+ | physicaldrive 3I:1:3 (port 3I:box 1:bay 3, SAS, 146 GB, OK) | ||
+ | physicaldrive 3I:1:4 (port 3I:box 1:bay 4, SAS, 146 GB, OK) | ||
+ | physicaldrive 4I:1:5 (port 4I:box 1:bay 5, SAS, 146 GB, OK) | ||
+ | physicaldrive 4I:1:6 (port 4I:box 1:bay 6, SAS, 146 GB, OK) | ||
+ | physicaldrive 4I:1:8 (port 4I:box 1:bay 8, SAS, 146 GB, OK) | ||
+ | physicaldrive 4I:1:7 (port 4I:box 1:bay 7, SAS, 146 GB, OK, spare) | ||
+ | |||
+ | array B (SATA, Unused Space: 0 MB) | ||
+ | |||
+ | |||
+ | logicaldrive 2 (1.9 TB, RAID 5, Recovering, 0% complete) | ||
+ | logicaldrive 3 (1.9 TB, RAID 5, Ready for Rebuild) | ||
+ | logicaldrive 4 (751.2 GB, RAID 5, Ready for Rebuild) | ||
+ | |||
+ | physicaldrive 1E:1:1 (port 1E:box 1:bay 1, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:2 (port 1E:box 1:bay 2, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:4 (port 1E:box 1:bay 4, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:5 (port 1E:box 1:bay 5, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:6 (port 1E:box 1:bay 6, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:11 (port 1E:box 1:bay 11, SATA, 1 TB, Rebuilding) | ||
+ | physicaldrive 1E:1:3 (port 1E:box 1:bay 3, SATA, 1 TB, OK, spare) | ||
+ | |||
+ | array C (SATA, Unused Space: 0 MB) | ||
+ | |||
+ | |||
+ | logicaldrive 5 (1.9 TB, RAID 5, OK) | ||
+ | logicaldrive 6 (1.7 TB, RAID 5, OK) | ||
+ | |||
+ | physicaldrive 1E:1:7 (port 1E:box 1:bay 7, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:8 (port 1E:box 1:bay 8, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:9 (port 1E:box 1:bay 9, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:10 (port 1E:box 1:bay 10, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:12 (port 1E:box 1:bay 12, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:3 (port 1E:box 1:bay 3, SATA, 1 TB, OK, spare) | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Nous avons supprimé (et formaté) tous les disques logiques liés aux disques physiques du StorageWorks MSA 60 | ||
+ | <pre> | ||
+ | hpssacli ctrl slot=4 ld 6 delete | ||
+ | hpssacli ctrl slot=4 ld 5 delete | ||
+ | ... | ||
+ | hpssacli ctrl slot=4 ld 2 delete | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Puis créé un disque logique en RAID 10 avec tous les disques physiques du MSA60 qui sera notre disque réservé pour la sauvegarde des VM | ||
+ | <pre> | ||
+ | hpssacli ctrl slot=4 create type=ld drives=1E:1:1,1E:1:2,1E:1:3,1E:1:4,1E:1:5,1E:1:6,1E:1:7,1E:1:8,1E:1:9,1E:1:10,1E:1:11,1E:1:12 raid=1+0 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Enfin, on s'assure que le disque logique a correctement été généré | ||
+ | <pre> | ||
+ | array B (SATA, Unused Space: 0 MB) | ||
+ | |||
+ | |||
+ | logicaldrive 2 (5.5 TB, RAID 1+0, OK) | ||
+ | |||
+ | physicaldrive 1E:1:1 (port 1E:box 1:bay 1, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:2 (port 1E:box 1:bay 2, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:3 (port 1E:box 1:bay 3, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:4 (port 1E:box 1:bay 4, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:5 (port 1E:box 1:bay 5, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:6 (port 1E:box 1:bay 6, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:7 (port 1E:box 1:bay 7, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:8 (port 1E:box 1:bay 8, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:9 (port 1E:box 1:bay 9, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:10 (port 1E:box 1:bay 10, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:11 (port 1E:box 1:bay 11, SATA, 1 TB, OK) | ||
+ | physicaldrive 1E:1:12 (port 1E:box 1:bay 12, SATA, 1 TB, OK) | ||
+ | </pre> | ||
+ | |||
+ | === Montage du disque de sauvegarde sur le serveur Debian === | ||
+ | |||
+ | Les disques logiques et leurs partitions sont répertoriés à l'emplacement suivant : | ||
+ | <pre> | ||
+ | ls /dev/cciss/ | ||
+ | </pre> | ||
+ | <pre> | ||
+ | c0d0 c0d0p1 c0d0p2 c0d0p5 c0d0p6 c0d0p7 c0d0p8 c0d1 | ||
+ | </pre> | ||
+ | Ici, c0d0 représente le disque logique (p1,p2,...,p8 les partitions) où est installé Debian (disques physiques liés à la station DL380 G5). | ||
+ | |||
+ | |||
+ | On retrouve notre disque logique (disques physiques liés au MSA60) créé précédemment identifié c0d1 : | ||
+ | <pre> | ||
+ | fdisk -l /dev/cciss/c0d1 | ||
+ | </pre> | ||
+ | <pre> | ||
+ | Disque /dev/cciss/c0d1 : 5,5 TiB, 6001026883584 octets, 11720755632 secteurs | ||
+ | Unités : secteur de 1 × 512 = 512 octets | ||
+ | Taille de secteur (logique / physique) : 512 octets / 512 octets | ||
+ | taille d'E/S (minimale / optimale) : 512 octets / 512 octets | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On transforme notre disque logique en partition ext4 : | ||
+ | <pre> | ||
+ | mkfs.ext4 /dev/cciss/c0d1 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On créer le dossier qui servira de point de montage, puis on monte notre partition dans celui-ci : | ||
+ | <pre> | ||
+ | mkdir /backup | ||
+ | mount -t auto /dev/cciss/c0d1 /backup | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Afin de monter automatiquement notre partition à chaque démarrage, il suffit d'ajouter la ligne suivante dans fstab : | ||
+ | <pre> | ||
+ | vi /etc/fstab | ||
+ | </pre> | ||
+ | <pre> | ||
+ | /dev/cciss/c0d1 /backup ext4 defaults 0 2 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Après redémarrage du serveur, on vérifie si notre disque logique est monté automatiquement : | ||
+ | <pre> | ||
+ | df -h | ||
+ | </pre> | ||
+ | <pre> | ||
+ | Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur | ||
+ | /dev/cciss/c0d0p1 8,2G 881M 6,9G 12% / | ||
+ | udev 10M 0 10M 0% /dev | ||
+ | tmpfs 775M 456K 775M 1% /run | ||
+ | tmpfs 5,0M 0 5,0M 0% /run/lock | ||
+ | tmpfs 4,8G 0 4,8G 0% /run/shm | ||
+ | /dev/cciss/c0d0p8 781G 69M 741G 1% /home | ||
+ | /dev/cciss/c0d0p7 360M 2,1M 335M 1% /tmp | ||
+ | /dev/cciss/c0d0p5 2,7G 339M 2,3G 14% /var | ||
+ | /dev/cciss/c0d1 5,5T 58M 5,2T 1% /backup | ||
+ | </pre> | ||
+ | |||
+ | === Mise en réseau du disque === | ||
+ | Lors de la sauvegarde des machines virtuelles, nous aurons besoin d'accéder à notre disque de sauvegarde. | ||
+ | |||
+ | Pour cela, nous avons mis en place un partage de type NFS (Network File System) : | ||
+ | <pre> | ||
+ | apt-get install nfs-kernel-server | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Il suffit de paramétrer le partage de façon à autoriser un ordinateur distant à accéder à un dossier en particulier (/etc/exports/) : | ||
+ | <pre> | ||
+ | /backup/vm_backup cordouan.insecserv.deule.net(rw,sync,no_root_squash) | ||
+ | </pre> | ||
+ | Ici, on autorise le serveur Cordouan à accéder au sous-dossier /backup/vm_backup/ en lecture et écriture. | ||
+ | |||
+ | == Scripts de sauvegarde et de restauration de machine virtuelle == | ||
+ | === Commandes utiles === | ||
+ | Sauvegarder l'état d'une machine virtuelle : | ||
+ | <pre> | ||
+ | xl save -c Deadpool /usr/local/xen/domains/vm_backup/Deadpool.vmbackup | ||
+ | </pre> | ||
+ | |||
+ | Restaurer l'état d'une machine virtuelle : | ||
+ | <pre> | ||
+ | xl restore /usr/local/xen/domains/vm_backup/Deadpool.vmbackup | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Snapshot des LVM d'une machine virtuelle : | ||
+ | <pre> | ||
+ | lvcreate -l 10%ORIGIN -s -n ima5-Deadpool-home-snapshot /dev/virtual/ima5-Deadpool-home | ||
+ | lvcreate -l 10%ORIGIN -s -n ima5-Deadpool-var-snapshot /dev/virtual/ima5-Deadpool-var | ||
+ | </pre> | ||
+ | |||
+ | Suppression des snapshots LVM : | ||
+ | <pre> | ||
+ | lvremove /usr/local/xen/domains/vm_backup/ima5-Deadpool-home-snapshot | ||
+ | lvremove /usr/local/xen/domains/vm_backup/ima5-Deadpool-var-snapshot | ||
+ | </pre> | ||
+ | |||
+ | === Sauvegarde des états des machines virtuelles === | ||
+ | Nous avons créé un script capable de sauvegarder l'état de toutes les machines virtuelles en cours d’exécution. | ||
+ | |||
+ | Ces machines virtuelles sont mis en pause pendant une à deux secondes le temps de la sauvegarde, ce qui est très rapide. | ||
+ | |||
+ | Voici le script disponible sur notre serveur DAS (/backup/script_backup/save_running_vm.sh) : | ||
+ | <pre> | ||
+ | #!/bin/bash# | ||
+ | #Script de sauvegarde pour les VM en cours d?exécution | ||
+ | |||
+ | DATE=`date +%d%b%Y-%H%M%S` | ||
+ | MOUNTPOINT=/mnt/vm_backup | ||
+ | LIST_VM_FILE=/tmp/vm_list.txt | ||
+ | NFS_SERVER_IP="172.26.64.15" | ||
+ | |||
+ | ### Create mount point | ||
+ | echo "Creating mount point..."; | ||
+ | mkdir -p ${MOUNTPOINT} | ||
+ | |||
+ | ### Mounting remote nfs share backup drive | ||
+ | |||
+ | #[ ! -d ${MOUNTPOINT} ] && echo "No mount point found, kindly check"; exit 0 | ||
+ | echo "Mounting backup nfs..."; | ||
+ | mount -t nfs ${NFS_SERVER_IP}:/backup/vm_backup ${MOUNTPOINT} | ||
+ | |||
+ | BACKUPPATH=${MOUNTPOINT}/${DATE} | ||
+ | mkdir -p ${BACKUPPATH} | ||
+ | #[ ! -d ${BACKUPPATH} ] && echo "No backup directory found"; exit 0 | ||
+ | |||
+ | ### get all running vm | ||
+ | xl vm-list | tail -n +2 | cut -d" " -f7 > ${LIST_VM_FILE} | ||
+ | |||
+ | #[ ! -f ${LIST_VM_FILE} ] && echo "No UUID list file found"; exit 0 | ||
+ | |||
+ | while read VMUUID | ||
+ | do | ||
+ | echo "Saving ${VMUUID}..."; | ||
+ | mkdir -p ${BACKUPPATH}/${VMUUID}/ | ||
+ | xl save -c $VMUUID ${BACKUPPATH}/${VMUUID}/${VMUUID}.vmbackup | ||
+ | done < ${LIST_VM_FILE} | ||
+ | |||
+ | ### Umounting remote nfs share backup drive | ||
+ | echo "Umounting backup nfs..."; | ||
+ | umount ${MOUNTPOINT} | ||
+ | rm ${MOUNTPOINT} -r | ||
+ | echo "ALL DONE !"; | ||
+ | </pre> | ||
+ | Le script consiste à monter sur la machine le dossier mis en réseau précédemment, puis il récupère le nom de toutes les machines virtuelles en cours de fonctionnement, et enfin il sauvegarde l'état des machines virtuelles une par une dans des dossiers spécifiques. | ||
+ | |||
+ | Une fois terminé, il démonte le dossier monté précédemment. | ||
+ | |||
+ | |||
+ | Ce script doit être exécuté sur la machine hôte des machines virtuelles, à savoir Cordouan. | ||
+ | |||
+ | Pour cela, il suffit d'un petit script avec une commande pour exécuter le script ci-dessus sur une machine distante (/backup/script_backup/save_running_vm_remote.sh) : | ||
+ | <pre> | ||
+ | #!/bin/bash# | ||
+ | ssh root@cordouan.insecserv.deule.net 'bash -s' < save_running_vm.sh | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On exécute notre nouveau script : | ||
+ | <pre> | ||
+ | sh /backup/script_backup/save_running_vm_remote.sh | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Et on laisse le travail se faire : | ||
+ | <pre> | ||
+ | Creating mount point... | ||
+ | Mounting backup nfs... | ||
+ | Saving Wolverine... | ||
+ | Saving to /mnt/vm_backup/04janv.2017-210539/Wolverine/Wolverine.vmbackup new xl format (info 0x0/0x0/1094) | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 2048/32768 6% | ||
+ | ... | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 32768/32768 100% | ||
+ | Saving Ironman... | ||
+ | Saving to /mnt/vm_backup/04janv.2017-210539/Ironman/Ironman.vmbackup new xl format (info 0x0/0x0/919) | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 2048/32768 6% | ||
+ | ... | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 30720/32768 93% | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 32768/32768 100% | ||
+ | Saving Batman... | ||
+ | Saving to /mnt/vm_backup/04janv.2017-210539/Batman/Batman.vmbackup new xl format (info 0x0/0x0/1049) | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 2048/32768 6% | ||
+ | ... | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 32768/32768 100% | ||
+ | Saving Frotteman... | ||
+ | Saving to /mnt/vm_backup/04janv.2017-210539/Frotteman/Frotteman.vmbackup new xl format (info 0x0/0x0/1056) | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 7168/131072 5% | ||
+ | ... | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 131072/131072 100% | ||
+ | Saving Deadpool... | ||
+ | Saving to /mnt/vm_backup/04janv.2017-210539/Deadpool/Deadpool.vmbackup new xl format (info 0x0/0x0/1054) | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 7168/131072 5% | ||
+ | ... | ||
+ | xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 131072/131072 100% | ||
+ | Umounting backup nfs... | ||
+ | ALL DONE ! | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Nous pouvons accéder facilement à nos sauvegardes : | ||
+ | <pre> | ||
+ | root@baleine:/backup/vm_backup/04janv.2017-210539# ls | ||
+ | Batman Deadpool Frotteman Ironman Wolverine | ||
+ | root@baleine:/backup/vm_backup/04janv.2017-210539# cd Deadpool/ | ||
+ | root@baleine:/backup/vm_backup/04janv.2017-210539/Deadpool# ls | ||
+ | Deadpool.vmbackup | ||
+ | </pre> | ||
+ | |||
+ | === Sauvegarde des LVM liés aux machines virtuelles === | ||
+ | Nous avons créé un script qui permet d'enregistrer les LVM d'une machine virtuelle donnée en argument : | ||
+ | <pre> | ||
+ | #!/bin/bash | ||
+ | #Script de sauvegarde pour toutes les LVM souhaitées | ||
+ | #Run with "ssh remote_machine 'bash -s' < /backup/script_backup/save_lvm_data_vm.sh arg" | ||
+ | |||
+ | LIST_LVM_FILE=/tmp/lvm_list.txt | ||
+ | VM_NAME=$1 | ||
+ | LVM_PATH=/dev/virtual/ | ||
+ | LVM_MOUNT_PATH=/mnt/lvm_snap | ||
+ | MOUNTPOINT=/mnt/vm_backup | ||
+ | NFS_SERVER_IP="172.26.64.15" | ||
+ | |||
+ | echo "Creating mount point for NFS..."; | ||
+ | mkdir -p ${MOUNTPOINT} | ||
+ | |||
+ | echo "Mounting backup nfs..."; | ||
+ | mount -t nfs ${NFS_SERVER_IP}:/backup/vm_backup ${MOUNTPOINT} | ||
+ | |||
+ | echo "Creating directory for LVM mount point..."; | ||
+ | mkdir -p ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Cheking for $1 LVM..."; | ||
+ | ls ${LVM_PATH} | grep -i $1 | grep -i 'var\|home' > ${LIST_LVM_FILE} | ||
+ | |||
+ | while read LVM_NAME | ||
+ | do | ||
+ | echo "Snapshot of ${LVM_NAME} LVM..."; | ||
+ | lvcreate -l 10%ORIGIN -s -n ${LVM_NAME}-snapshot ${LVM_PATH}${LVM_NAME} | ||
+ | |||
+ | echo "Mounting ${LVM_NAME}-snapshot..."; | ||
+ | mount ${LVM_PATH}${LVM_NAME}-snapshot ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Doing the backup of ${LVM_NAME}-snapshot..."; | ||
+ | tar -cf ${MOUNTPOINT}/${LVM_NAME}-snapshot.tar ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Unmounting ${LVM_NAME} LVM..."; | ||
+ | umount ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Cleaning snapshot of ${LVM_NAME} LVM..."; | ||
+ | yes | lvremove ${LVM_PATH}${LVM_NAME}-snapshot | ||
+ | done < ${LIST_LVM_FILE} | ||
+ | |||
+ | rm ${LVM_MOUNT_PATH} -r | ||
+ | |||
+ | echo "Unmounting backup NFS..."; | ||
+ | umount ${MOUNTPOINT} | ||
+ | |||
+ | rm ${MOUNTPOINT} -r | ||
+ | |||
+ | echo "ALL DONE !"; | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On essaye le script pour notre machine virtuelle en mettant "Deadpool" comme argument : | ||
+ | <pre> | ||
+ | Creating mount point for NFS... | ||
+ | Mounting backup nfs... | ||
+ | Creating directory for LVM mount point... | ||
+ | Cheking for Deadpool LVM... | ||
+ | Snapshot of ima5-Deadpool-home LVM... | ||
+ | Logical volume "ima5-Deadpool-home-snapshot" created | ||
+ | Mounting ima5-Deadpool-home-snapshot... | ||
+ | Doing the backup of ima5-Deadpool-home-snapshot... | ||
+ | tar: Suppression de « / » au début des noms des membres | ||
+ | Unmounting ima5-Deadpool-home LVM... | ||
+ | Cleaning snapshot of ima5-Deadpool-home LVM... | ||
+ | Do you really want to remove active logical volume ima5-Deadpool-home-snapshot? [y/n]: Logical volume "ima5-Deadpool-home-snapshot" successfully removed | ||
+ | Snapshot of ima5-Deadpool-var LVM... | ||
+ | Logical volume "ima5-Deadpool-var-snapshot" created | ||
+ | Mounting ima5-Deadpool-var-snapshot... | ||
+ | Doing the backup of ima5-Deadpool-var-snapshot... | ||
+ | tar: Suppression de « / » au début des noms des membres | ||
+ | Unmounting ima5-Deadpool-var LVM... | ||
+ | Cleaning snapshot of ima5-Deadpool-var LVM... | ||
+ | Do you really want to remove active logical volume ima5-Deadpool-var-snapshot? [y/n]: Logical volume "ima5-Deadpool-var-snapshot" successfully removed | ||
+ | Unmounting backup NFS... | ||
+ | ALL DONE ! | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On récupère bien nos fichiers : | ||
+ | <pre> | ||
+ | root@baleine:/backup/vm_backup# ls | ||
+ | ima5-Deadpool-home-snapshot.tar ima5-Deadpool-var-snapshot.tar | ||
+ | </pre> | ||
+ | |||
+ | === Sauvegarde complète et automatisée des machines virtuelles === | ||
+ | Maintenant, il faut enregistrer à la fois les états des machines virtuelles allumées avec leurs LVM, ainsi que les LVM des machines virtuelles éteintes. | ||
+ | |||
+ | Pour celà, nous avons modifié le script et ajouter un fichier de configuration comportant le nom de toutes les machines virtuelles que l'on souhaite sauvegarder. | ||
+ | |||
+ | Le script reste largement simplifiable, car il s'agit ici des deux précédents scripts plus ou moins arrangés. | ||
+ | |||
+ | Lors de la soutenance, nous avons modifié le script pour qu'il sauvegarde aussi le disque image des machines virtuelles, ainsi, une sauvegarde totale de la machine virtuelle est effectuée, et non pas seulement l'état mémoire et les LVM. | ||
+ | |||
+ | De plus la machine virtuelle est mise en pause durant sa sauvegarde. | ||
+ | |||
+ | <pre> | ||
+ | #!/bin/bash# | ||
+ | #Script effectuant le backup de toutes les VM | ||
+ | |||
+ | DATE=`date +%d%b%Y-%H%M%S` | ||
+ | MOUNTPOINT=/mnt/vm_backup | ||
+ | LVM_MOUNT_PATH=/mnt/lvm_snap | ||
+ | LVM_PATH=/dev/virtual/ | ||
+ | LIST_VM_FILE=/tmp/vm_list.txt | ||
+ | LIST_VM_CLOSED=/tmp/vm_closed_list.txt | ||
+ | LIST_LVM_FILE=/tmp/lvm_list.txt | ||
+ | NFS_SERVER_IP="172.26.64.15" | ||
+ | BACKUPPATH=${MOUNTPOINT}/${DATE} | ||
+ | CONFIGPATH=${MOUNTPOINT}/vm_backup.cfg | ||
+ | |||
+ | ### Create mount point | ||
+ | echo "Creating mount point..."; | ||
+ | mkdir -p ${MOUNTPOINT} | ||
+ | |||
+ | echo "Creating directory for LVM mount point..."; | ||
+ | mkdir -p ${LVM_MOUNT_PATH} | ||
+ | |||
+ | ### Mounting remote nfs share backup drive | ||
+ | echo "Mounting backup nfs..."; | ||
+ | mount -t nfs ${NFS_SERVER_IP}:/backup/vm_backup ${MOUNTPOINT} | ||
+ | |||
+ | echo "Creating dated backup folder..."; | ||
+ | mkdir -p ${BACKUPPATH} | ||
+ | |||
+ | ### get all running vm | ||
+ | xl vm-list | tail -n +2 | cut -d" " -f7 > ${LIST_VM_FILE} | ||
+ | |||
+ | while read VMUUID | ||
+ | do | ||
+ | mkdir -p ${BACKUPPATH}/${VMUUID}/ | ||
+ | |||
+ | echo "Saving ${VMUUID} state..."; | ||
+ | xl save -p $VMUUID ${BACKUPPATH}/${VMUUID}/${VMUUID}.vmbackup | ||
+ | |||
+ | echo "Creating disk.img snapshot..."; | ||
+ | qemu-img create -f qcow2 -b /usr/local/xen/domains/${VMUUID}/disk.img /usr/local/xen/domains/${VMUUID}/disk-snapshot.img | ||
+ | modprobe nbd max_part=63 | ||
+ | qemu-nbd -c /dev/nbd0 /usr/local/xen/domains/${VMUUID}/disk-snapshot.img | ||
+ | |||
+ | echo "Mounting ${LVM_NAME} disk.img..."; | ||
+ | mount /dev/nbd0 ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Doing the backup of disk..."; | ||
+ | tar -cf ${BACKUPPATH}/${VMUUID}/disk.img-snapshot.tar ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Unmounting ..." | ||
+ | umount ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Cleaning snapshot..." | ||
+ | rm /usr/local/xen/domains/${VMUUID}/disk-snapshot.img | ||
+ | |||
+ | echo "Cheking for ${VMUUID} LVM..."; | ||
+ | ls ${LVM_PATH} | grep -i ${VMUUID} | grep -i 'var\|home' > ${LIST_LVM_FILE} | ||
+ | |||
+ | while read LVM_NAME | ||
+ | do | ||
+ | echo "Snapshot of ${LVM_NAME} LVM..."; | ||
+ | lvcreate -l 10%ORIGIN -s -n ${LVM_NAME}-snapshot ${LVM_PATH}${LVM_NAME} | ||
+ | |||
+ | echo "Mounting ${LVM_NAME}-snapshot..."; | ||
+ | mount ${LVM_PATH}${LVM_NAME}-snapshot ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Doing the backup of ${LVM_NAME}-snapshot..."; | ||
+ | tar -cf ${BACKUPPATH}/${VMUUID}/${LVM_NAME}-snapshot.tar ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Unmounting ${LVM_NAME} LVM..."; | ||
+ | umount ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Cleaning snapshot of ${LVM_NAME} LVM..."; | ||
+ | yes | lvremove ${LVM_PATH}${LVM_NAME}-snapshot | ||
+ | done < ${LIST_LVM_FILE} | ||
+ | xl unpause ${VMUUID} | ||
+ | done < ${LIST_VM_FILE} | ||
+ | |||
+ | ### get all closed vm | ||
+ | awk 'NR==FNR {t[$0]++; next} !t[$0]' ${LIST_VM_FILE} ${CONFIGPATH} > ${LIST_VM_CLOSED} | ||
+ | |||
+ | while read VMUUID | ||
+ | do | ||
+ | mkdir -p ${BACKUPPATH}/${VMUUID}/ | ||
+ | echo "Creating disk.img snapshot..."; | ||
+ | qemu-img create -f qcow2 -b /usr/local/xen/domains/${VMUUID}/disk.img /usr/local/xen/domains/${VMUUID}/disk-snapshot.img | ||
+ | modprobe nbd max_part=63 | ||
+ | qemu-nbd -c /dev/nbd0 /usr/local/xen/domains/${VMUUID}/disk-snapshot.img | ||
+ | |||
+ | echo "Mounting ${LVM_NAME} disk.img..."; | ||
+ | mount /dev/nbd0 ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Doing the backup of disk..."; | ||
+ | tar -cf ${BACKUPPATH}/${VMUUID}/disk.img-snapshot.tar ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Unmounting ..." | ||
+ | umount ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Cleaning snapshot..." | ||
+ | rm /usr/local/xen/domains/${VMUUID}/disk-snapshot.img | ||
+ | |||
+ | echo "Cheking for ${VMUUID} LVM..."; | ||
+ | ls ${LVM_PATH} | grep -i ${VMUUID} | grep -i 'var\|home' > ${LIST_LVM_FILE} | ||
+ | |||
+ | while read LVM_NAME | ||
+ | do | ||
+ | echo "Snapshot of ${LVM_NAME} LVM..."; | ||
+ | lvcreate -l 10%ORIGIN -s -n ${LVM_NAME}-snapshot ${LVM_PATH}${LVM_NAME} | ||
+ | |||
+ | echo "Mounting ${LVM_NAME}-snapshot..."; | ||
+ | mount ${LVM_PATH}${LVM_NAME}-snapshot ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Doing the backup of ${LVM_NAME}-snapshot..."; | ||
+ | tar -cf ${BACKUPPATH}/${VMUUID}/${LVM_NAME}-snapshot.tar ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Unmounting ${LVM_NAME} LVM..."; | ||
+ | umount ${LVM_MOUNT_PATH} | ||
+ | |||
+ | echo "Cleaning snapshot of ${LVM_NAME} LVM..."; | ||
+ | yes | lvremove ${LVM_PATH}${LVM_NAME}-snapshot | ||
+ | done < ${LIST_LVM_FILE} | ||
+ | |||
+ | done < ${LIST_VM_CLOSED} | ||
+ | |||
+ | ###Cleaning lvm mount path | ||
+ | rm ${LVM_MOUNT_PATH} -r | ||
+ | |||
+ | ### Umounting remote nfs share backup drive | ||
+ | echo "Umounting backup nfs..."; | ||
+ | umount ${MOUNTPOINT} | ||
+ | rm ${MOUNTPOINT} -r | ||
+ | echo "ALL DONE !"; | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Une fois avoir exécuté celui-ci sur Cordouan, on peut observer le résultat obtenu sur notre DAS : | ||
+ | <pre> | ||
+ | tree /backup/vm_backup/05janv.2017-205758/ | ||
+ | </pre> | ||
+ | <pre> | ||
+ | /backup/vm_backup/06janv.2017-175650/ | ||
+ | ├── Batman | ||
+ | │ ├── Batman.vmbackup | ||
+ | │ ├── disk.img-snapshot.tar | ||
+ | │ ├── ima5-Batman-home-snapshot.tar | ||
+ | │ └── ima5-Batman-var-snapshot.tar | ||
+ | ├── Deadpool | ||
+ | │ ├── Deadpool.vmbackup | ||
+ | │ ├── disk.img-snapshot.tar | ||
+ | │ ├── ima5-Deadpool-home-snapshot-snapshot.tar | ||
+ | │ ├── ima5-Deadpool-home-snapshot.tar | ||
+ | │ ├── ima5-Deadpool-var-snapshot-snapshot.tar | ||
+ | │ └── ima5-Deadpool-var-snapshot.tar | ||
+ | ├── Flash | ||
+ | │ ├── disk.img-snapshot.tar | ||
+ | │ └── Flash.vmbackup | ||
+ | ├── Frotteman | ||
+ | │ ├── disk.img-snapshot.tar | ||
+ | │ ├── Frotteman.vmbackup | ||
+ | │ ├── ima5-Frotteman-home-snapshot.tar | ||
+ | │ └── ima5-Frotteman-var-snapshot.tar | ||
+ | ├── GreenArrow | ||
+ | │ ├── disk.img-snapshot.tar | ||
+ | │ ├── GreenArrow.vmbackup | ||
+ | │ ├── ima5-GreenArrow-home-snapshot.tar | ||
+ | │ └── ima5-GreenArrow-var-snapshot.tar | ||
+ | ├── Ironman | ||
+ | │ ├── disk.img-snapshot.tar | ||
+ | │ └── Ironman.vmbackup | ||
+ | ├── Mulan | ||
+ | │ ├── disk.img-snapshot.tar | ||
+ | │ ├── ima5-Mulan-home-snapshot.tar | ||
+ | │ ├── ima5-Mulan-var-snapshot.tar | ||
+ | │ └── Mulan.vmbackup | ||
+ | ├── Spiderman | ||
+ | │ └── Spiderman.vmbackup | ||
+ | └── Wolverine | ||
+ | ├── disk.img-snapshot.tar | ||
+ | ├── wolverine-home-snapshot.tar | ||
+ | ├── wolverine-var-snapshot.tar | ||
+ | └── Wolverine.vmbackup | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Pour automatiser notre tâche, nous avons configuré Cron. | ||
+ | |||
+ | Cet utilitaire permet d’exécuter une commande automatiquement à n'importe quel moment : toutes les 2 heures, tous les jeudis à 15h48... | ||
+ | |||
+ | Nous avons donc configuré Cron pour exécuter une sauvegarde toutes les 6 heures : | ||
+ | <pre> | ||
+ | crontab -e | ||
+ | </pre> | ||
+ | <pre> | ||
+ | # m h dom mon dow command | ||
+ | 0 */6 * * * sh /backup/script_backup/vm_backup_script_remote.sh | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Le script de sauvegarde automatique pourrait être modifié de manière à ne garder que les 10 dernière sauvegardes sur notre DAS pour ne pas le surcharger ou ne pas supprimer manuellement toutes les semaines les sauvegardes trop vielles. | ||
+ | |||
+ | === Restauration d'une machine virtuelle === | ||
+ | Nous avons créé un script capable de restaurer une machine virtuelle depuis un dossier de sauvegarde voulu : | ||
+ | <pre> | ||
+ | #!/bin/bash# | ||
+ | |||
+ | #UTILISATION : ./restore_state_vm.sh Deadpool 05janv.2017-205758 | ||
+ | #UTILISATION : ./restore_state_vm.sh VM_NAME FOLDER_NAME | ||
+ | |||
+ | VM_NAME=$1 | ||
+ | DATE_FOLDER=$2 | ||
+ | MOUNTPOINT=/mnt/vm_backup | ||
+ | NFS_SERVER_IP="172.26.64.15" | ||
+ | |||
+ | ### Create mount point | ||
+ | echo "Creating mount point..."; | ||
+ | mkdir -p ${MOUNTPOINT} | ||
+ | |||
+ | ### Mounting remote nfs share backup drive | ||
+ | echo "Mounting backup nfs..."; | ||
+ | mount -t nfs ${NFS_SERVER_IP}:/backup/vm_backup ${MOUNTPOINT} | ||
+ | |||
+ | ### restoring vm | ||
+ | echo "Restoring ${VM_NAME} ..."; | ||
+ | xl destroy ${VM_NAME} | ||
+ | xl restore ${MOUNTPOINT}/${DATE_FOLDER}/${VM_NAME}/${VM_NAME}.vmbackup | ||
+ | echo "${VM_NAME} RESTORED !"; | ||
+ | |||
+ | ### Umounting remote nfs share backup drive | ||
+ | echo "Umounting backup nfs..."; | ||
+ | umount ${MOUNTPOINT} | ||
+ | |||
+ | #BUSY ERROR | ||
+ | #rm ${MOUNTPOINT} -r | ||
+ | echo "ALL DONE !"; | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Le script fonctionne, mais le disque en réseau devient occupé et il est impossible de le démonter de Cordouan. | ||
+ | |||
+ | Il est nécessaire d'éteindre la machine virtuelle, puis de la redémarrer pour pouvoir démonter le disque réseau correctement. | ||
+ | |||
+ | Ici, la restauration des LVM n'est pas effectuée. | ||
+ | |||
+ | === Amélioration du site === | ||
+ | |||
+ | On installe de quoi exécuter du PHP sur notre site web : | ||
+ | |||
+ | <pre> | ||
+ | apt-get install php5-common libapache2-mod-php5 php5-cli | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On a revu un peu l'index de notre page : | ||
+ | <pre> | ||
+ | <html> | ||
+ | |||
+ | <link rel="icon" type="image/png" href="images/Deadpool_ico.png" /> | ||
+ | <meta charset="utf-8"> | ||
+ | <!--[if IE]><link rel="shortcut icon" type="image/x-icon" href="images/Deadpool_ico.png" /><![endif]--> | ||
+ | |||
+ | <head> | ||
+ | <title>PISCINEMORTE.NET</title> | ||
+ | </head> | ||
+ | <body bgcolor=#CEECF5> | ||
+ | |||
+ | <center> | ||
+ | |||
+ | <img src="images/Deadpool.png" height="25%" width="25%"> | ||
+ | |||
+ | <h1><FONT color="#0B0B61">Bienvenue sur PISCINEMORTE.NET !</FONT></h1> | ||
+ | |||
+ | |||
+ | <p><FONT color="#0B0B61">Ce site internet est dédié à notre projet de système et réseaux à l'école Polytech Lille.</FONT></p> | ||
+ | <p><FONT color="#0B0B61">Par Geoffrey PIEKACZ et Nathan RICHEZ</FONT></p> | ||
+ | <p><FONT color="#0B0B61">Lien vers <a href="http://projets-ima.plil.net/mediawiki/index.php?title=Cahier_2016_groupe_n%C2%B03">notre Wiki</a></FONT></p> | ||
+ | </center> | ||
+ | </body> | ||
+ | </html> | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Nous devons maintenant trouver le moyen d'afficher les machines virtuelles démarrées sur notre site. | ||
+ | |||
+ | Pour cela, nous nous sommes inspirés de la commande ci-dessous : | ||
+ | |||
+ | <pre> | ||
+ | ssh [user]@[server] 'bash -s' < [local_script] | ||
+ | </pre> | ||
+ | Cette commande va nous permettre de lancer un script de Deadpool vers Cordouan. | ||
+ | |||
+ | |||
+ | Le script est le suivant (/var/www/www.piscinemorte.net/show_vm_list.sh): | ||
+ | <pre> | ||
+ | #!/bin/bash | ||
+ | |||
+ | ssh root@cordouan.insecserv.deule.net 'xl vm-list' | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Il affichera une liste des VM démarrées via un code PHP ajouté dans notre index : | ||
+ | <pre> | ||
+ | <?php | ||
+ | echo "Liste des machines virtuelles en cours de fonctionnement :"; | ||
+ | $output = shell_exec('sh /var/www/www.piscinemorte.net/show_vm_list.sh'); | ||
+ | echo "$output"; | ||
+ | ?> | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Ensuite, nous avons rencontré un problème. | ||
+ | |||
+ | En effet, cette commande fonctionne dans un bash mais le résultat n'est pas directement affiché sur notre site. | ||
+ | |||
+ | Cela s'explique par le fait que nous avons exécuté cette commande en root mais que apache via php execute cette commande dans un shell via l'utilisateur www-data. | ||
+ | |||
+ | Nous avions précédemment créé une clé pour pouvoir exécuter notre commande en root sans remettre à chaque fois le mot de passe. | ||
+ | |||
+ | Nous avons donc réitéré la démarche pour l'utilisateur www-data: | ||
+ | <pre> | ||
+ | root@Deadpool:/home/Deadpool-key# ssh-keygen -t rsa //on génère une clé sans mot de passe dans ~/.ssh sauvegardée dans /root/.ssh/id_rsa | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On copiera cette clé sur Cordouan et sur Baleine (notre DAS) pour permettre à nos machines de se connecter en ssh sans demande de mot de passe : | ||
+ | <pre> | ||
+ | root@Deadpool:~# cp /root/.ssh/id_rsa /var/www/.ssh/ //pour copier notre clé pour l'utilisateur www-data | ||
+ | root@Deadpool:~# chown www-data:www-data /var/www/.ssh/ -R // pour donner les droits de manière récursive à www-data | ||
+ | root@Deadpool:~# sudo -u www-data -s //Pour changer l'utilisateur à www-data | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Ainsi, notre commande est bien exécutée depuis notre site et affiche toutes les VM fonctionnant à l'instant t. | ||
+ | <center> | ||
+ | {| | ||
+ | | [[Fichier:piscinemorte_vm_list.png|thumb|upright=4|Affichage des machines virtuelles sur notre site]] | ||
+ | |} | ||
+ | </center> | ||
+ | |||
+ | = Tâches communes = | ||
+ | == Gestion de la machine virtuelle == | ||
+ | |||
+ | === Installation de la machine virtuelle avec Xen === | ||
+ | |||
+ | |||
+ | Pour créé la machine virtuelle, on utilise xen-create-image avec les paramètres souhaités : | ||
<pre> | <pre> | ||
xen-create-image --hostname=Deadpool --ip=193.48.57.163 --netmask=255.255.255.240 --gateway=193.48.57.171 --dir=/usr/local/xen | xen-create-image --hostname=Deadpool --ip=193.48.57.163 --netmask=255.255.255.240 --gateway=193.48.57.171 --dir=/usr/local/xen | ||
Ligne 12 : | Ligne 813 : | ||
</pre> | </pre> | ||
− | |||
+ | Puis, on récupère les informations suivantes afin de vérifier diverses paramètres : | ||
<pre> | <pre> | ||
General Information | General Information | ||
Ligne 58 : | Ligne 859 : | ||
RSA Fingerprint : d0:38:7b:89:c7:72:e7:52:d9:b7:5c:5b:ab:3e:fe:3f | RSA Fingerprint : d0:38:7b:89:c7:72:e7:52:d9:b7:5c:5b:ab:3e:fe:3f | ||
Root Password : hZsEGmZX | Root Password : hZsEGmZX | ||
+ | </pre> | ||
+ | |||
+ | === Configuration de la machine virtuelle === | ||
+ | On utilise lvcreate pour faire en sorte que les répertoires var et home de la machine virtuelle soient sur des partitions LVM de l'hôte : | ||
+ | <pre> | ||
+ | lvcreate -L 10G -n /dev/virtual/ima5-Deadpool-home -v | ||
+ | lvcreate -L 10G -n /dev/virtual/ima5-Deadpool-var -v | ||
+ | </pre> | ||
+ | Commande pour démarrer la machine virtuelle : | ||
+ | <pre> | ||
+ | xl create /etc/xen/Deadpool.cfg | ||
</pre> | </pre> | ||
+ | Commande pour se connecter à la machine virtuelle par console : | ||
+ | <pre> | ||
+ | xl console Deadpool | ||
+ | </pre> | ||
+ | Commande pour éteindre la machine virtuelle : | ||
+ | <pre> | ||
+ | xl shutdown Deadpool | ||
+ | </pre> | ||
+ | Commande pour détruire la machine virtuelle : | ||
+ | <pre> | ||
+ | xl destroy Deadpool | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On transforme nos disques logiques en partition ext4 : | ||
+ | <pre> | ||
+ | mkfs.ext4 /dev/xvdb | ||
+ | mkfs.ext4 /dev/xvdc | ||
+ | </pre> | ||
+ | |||
− | === | + | On sauvegarde les fichiers déjà existants dans home et var et on les met dans nos nouvelles partitions : |
+ | <pre> | ||
+ | mkdir /mnt/home/ | ||
+ | mkdir /mnt/var/ | ||
+ | mount /dev/xvdc/ /mnt/home/ | ||
+ | mount /dev/xvdb/ /mnt/var/ | ||
+ | cp -r /home/* /mnt/home/ | ||
+ | cp -r /var/* /mnt/var/ | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Afin de monter automatiquement notre partition à chaque démarrage, il suffit d'ajouter les lignes suivantes dans fstab : | ||
+ | <pre> | ||
+ | nano /etc/fstab | ||
+ | </pre> | ||
+ | <pre> | ||
+ | /dev/xvdc /home ext3 defaults 0 2 | ||
+ | /dev/xvdb /var ext3 defaults 0 2 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Après redémarrage de la machine virtuelle, on vérifie si nos disques sont montés automatiquement : | ||
+ | <pre> | ||
+ | df -h | ||
+ | </pre> | ||
+ | <pre> | ||
+ | Filesystem Size Used Avail Use% Mounted on | ||
+ | /dev/xvda2 3.9G 700M 3.0G 19% / | ||
+ | udev 10M 0 10M 0% /dev | ||
+ | tmpfs 99M 13M 87M 13% /run | ||
+ | tmpfs 247M 0 247M 0% /dev/shm | ||
+ | tmpfs 5.0M 0 5.0M 0% /run/lock | ||
+ | tmpfs 247M 0 247M 0% /sys/fs/cgroup | ||
+ | /dev/xvdb 9.8G 262M 9.0G 3% /var | ||
+ | /dev/xvdc 9.8G 23M 9.2G 1% /home | ||
+ | </pre> | ||
+ | |||
+ | == Tests d'intrusion == | ||
+ | |||
+ | === Cassage de clef WEP === | ||
+ | |||
+ | |||
+ | Via airodump-ng, on liste les réseaux wi-fi protégés par WEP : | ||
+ | <pre> | ||
+ | airodump-ng --encrypt wep wlx40a5ef01370a | ||
+ | </pre> | ||
+ | wlx40a5ef01370a représente ici notre interface réseau (équivalant à wlan0 par exemple) | ||
+ | |||
+ | |||
+ | On obtient la liste des réseaux wi-fi suivante : | ||
+ | <pre> | ||
+ | [ CH 5 ][ Elapsed: 2 mins ][ 2016-11-07 10:30 ][ WPA handshake: 04:DA:D2:CF:01:93 ] | ||
+ | |||
+ | BSSID PWR Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID | ||
+ | |||
+ | 44:AD:D9:5F:87:00 -50 73 0 0 11 54e. WEP WEP Wolverine | ||
+ | 04:DA:D2:9C:50:51 -64 90 0 0 13 54e. WEP WEP cracotte02 | ||
+ | 04:DA:D2:9C:50:53 -67 58 0 0 13 54e. WEP WEP cracotte04 | ||
+ | 04:DA:D2:9C:50:59 -68 85 0 0 13 54e. WEP WEP cracotte10 | ||
+ | 04:DA:D2:9C:50:56 -74 88 1329 17 13 54e. WEP WEP cracotte07 | ||
+ | 04:DA:D2:9C:50:52 -75 87 2279 14 13 54e. WEP WEP cracotte03 | ||
+ | 04:DA:D2:9C:50:58 -75 87 1751 14 13 54e. WEP WEP cracotte09 | ||
+ | 04:DA:D2:9C:50:57 -75 86 1293 7 13 54e. WEP WEP cracotte08 | ||
+ | 04:DA:D2:9C:50:54 -76 88 1460 15 13 54e. WEP WEP cracotte05 | ||
+ | 04:DA:D2:9C:50:50 -76 80 1345 11 13 54e. WEP WEP cracotte01 | ||
+ | 04:DA:D2:9C:50:55 -76 83 1501 10 13 54e. WEP WEP cracotte06 | ||
+ | 00:3A:7D:12:DC:F2 -1 0 0 0 6 -1 <length: 0> | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On lance le monitoring sur le réseau que l'on souhaite cracker : | ||
+ | <pre> | ||
+ | airodump-ng --essid cracotte07 --channel 13 -w testcrack wlx40a5ef01370a | ||
+ | </pre> | ||
+ | <pre> | ||
+ | [ CH 13 ][ Elapsed: 1 min ][ 2016-11-07 10:46 ] | ||
+ | |||
+ | BSSID PWR RXQ Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID | ||
+ | |||
+ | 04:DA:D2:9C:50:56 -72 12 608 8283 91 13 54e. WEP WEP cracotte07 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Nous pouvons ensuite lancer le crackage à l'aide de aircrack-ng : | ||
+ | <pre> | ||
+ | aircrack-ng testcarck-03.cap | ||
+ | </pre> | ||
+ | <pre> | ||
+ | Aircrack-ng 1.2 beta3 | ||
+ | |||
+ | |||
+ | [00:00:00] Tested 84483 keys (got 35490 IVs) | ||
+ | |||
+ | KB depth byte(vote) | ||
+ | 0 0/ 5 EE(46080) EF(44032) 53(43008) 7B(43008) FC(43008) | ||
+ | 1 3/ 15 EE(41984) 8D(41728) DD(41472) 16(41216) 28(41216) | ||
+ | 2 0/ 2 EE(47616) 29(45824) C9(43776) 27(43264) 42(43008) | ||
+ | 3 0/ 10 EE(44800) A9(44288) 15(43264) C5(42496) 2C(42496) | ||
+ | 4 0/ 1 EE(49920) 2A(45312) 9D(43520) DA(43008) FD(41216) | ||
+ | 5 0/ 4 EE(45312) A1(43520) C6(42240) E8(42240) 76(41472) | ||
+ | 6 0/ 1 EE(50944) 98(42496) BB(42496) 4C(41728) B3(41728) | ||
+ | 7 0/ 1 EE(54272) D3(42752) 19(42240) 08(41984) 58(41984) | ||
+ | 8 5/ 8 F4(41216) 39(40960) 5E(40960) D7(40960) 1E(40704) | ||
+ | 9 1/ 2 E4(45312) 51(43264) A7(42752) 5F(41984) CA(41728) | ||
+ | 10 0/ 1 44(51200) 12(43264) CD(41984) 9C(41216) E5(41216) | ||
+ | 11 0/ 1 44(50176) B0(42240) D2(41728) DC(41728) 62(41472) | ||
+ | 12 0/ 1 44(47872) 0B(44032) B4(42752) D9(42496) 43(41728) | ||
+ | |||
+ | KEY FOUND! [ EE:EE:EE:EE:EE:EE:EE:EE:EE:E4:44:44:44 ] | ||
+ | Decrypted correctly: 100% | ||
+ | </pre> | ||
+ | La clé est décryptée en quelques secondes ! | ||
+ | |||
+ | === Cassage de clef WPA-PSK par force brute === | ||
+ | |||
+ | |||
+ | De même que pour le cassage de clé WEP, nous allons utiliser les mêmes outils mais pour un craquage WPA. | ||
+ | |||
+ | <pre> | ||
+ | airmon-ng start wlx40a5ef01370a //On lance le mode monitoring sur notre carte wifi | ||
+ | airmon-ng mon0 //On liste ensuite toutes les interfaces wifi disponible | ||
+ | crunch 8 8 0123456789 > dico.txt //On sait que la clé possède 8 chiffres, on créé donc un dictionnaire contenant toutes les possibilités de clé avec l'outil crunch | ||
+ | airodump-ng --encrypt wpa wlx40a5ef01370a //Nous choisissons ensuite le réseau à attaquer en wpa | ||
+ | </pre> | ||
+ | <pre> | ||
+ | [ CH 3 ][ Elapsed: 8 s ][ 2016-11-07 11:30 ] | ||
+ | |||
+ | BSSID PWR Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID | ||
+ | |||
+ | 04:DA:D2:9D:82:A2 -75 2 0 0 4 54e. WPA2 CCMP PSK <length: 1> | ||
+ | 00:19:07:C5:0F:A6 -62 7 0 0 1 54e. WPA2 CCMP MGT <length: 1> | ||
+ | 00:19:07:C5:0F:A0 -63 6 4 0 1 54e. WPA2 CCMP MGT LILLE1 | ||
+ | 00:19:07:C5:0F:A5 -62 6 0 0 1 54e. WPA2 CCMP PSK <length: 1> | ||
+ | 00:19:07:C5:0F:A3 -64 7 0 0 1 54e. WPA2 CCMP PSK PolytechGuests | ||
+ | 00:19:07:C5:0F:A7 -62 6 0 0 1 54e. WPA2 CCMP MGT PolytechLilleStaff | ||
+ | 00:19:07:C5:0F:A2 -63 7 0 0 1 54e. WPA2 CCMP PSK <length: 1> | ||
+ | 00:19:07:C5:0F:A8 -62 6 4 0 1 54e. WPA2 CCMP MGT eduroam | ||
+ | 00:19:07:C5:0F:A4 -63 8 2 0 1 54e. WPA2 CCMP MGT PolytechLille | ||
+ | 00:19:07:C5:0F:A1 -64 8 6 1 1 54e. WPA2 CCMP MGT <length: 1> | ||
+ | 04:DA:D2:9C:50:58 -70 6 0 0 13 54e. WPA2 CCMP PSK cracotte09 | ||
+ | 04:DA:D2:9C:50:50 -71 6 0 0 13 54e. WPA2 CCMP PSK cracotte01 | ||
+ | 04:DA:D2:9C:50:55 -71 6 0 0 13 54e. WPA2 CCMP PSK cracotte06 | ||
+ | 04:DA:D2:9C:50:53 -71 7 0 0 13 54e. WPA2 CCMP PSK cracotte04 | ||
+ | 04:DA:D2:9C:50:57 -71 7 0 0 13 54e. WPA2 CCMP PSK cracotte08 | ||
+ | 04:DA:D2:9C:50:51 -72 9 0 0 13 54e. WPA2 CCMP PSK cracotte02 | ||
+ | 04:DA:D2:9C:50:56 -72 9 0 0 13 54e. WPA2 CCMP PSK cracotte07 | ||
+ | 04:DA:D2:9C:50:52 -72 8 0 0 13 54e. WPA2 CCMP PSK cracotte03 | ||
+ | 04:DA:D2:9C:50:59 -71 8 0 0 13 54e. WPA2 CCMP PSK cracotte10 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On observe ensuite (seulement) la cible choisie (cracotte03) | ||
+ | <pre> | ||
+ | airodump-ng --essid cracotte03 -c 13 --bssid 04:DA:D2:9C:50:52 -w dump mon0 | ||
+ | </pre> | ||
+ | <pre> | ||
+ | [ CH 13 ][ Elapsed: 4 mins ][ 2016-11-07 11:36 ][ WPA handshake: 04:DA:D2:9C:50:52 | ||
+ | |||
+ | BSSID PWR RXQ Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID | ||
+ | |||
+ | 04:DA:D2:9C:50:52 -74 9 2573 259 0 13 54e. WPA2 CCMP PSK cracotte03 | ||
+ | |||
+ | BSSID STATION PWR Rate Lost Frames Probe | ||
+ | |||
+ | 04:DA:D2:9C:50:52 00:0F:B5:92:23:6A -58 1e- 1e 0 185 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On lance l'attaque avec le handshake récupéré : | ||
+ | <pre> | ||
+ | #aireplay-ng --deauth=5 -a 04:DA:D2:9C:50:52 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Et enfin, on lance le décodage grâce au fichier généré et notre dictionnaire: | ||
+ | <pre> | ||
+ | aircrack-ng dump-03.cap -w dico.txt -l KEY | ||
+ | </pre> | ||
+ | |||
+ | Malheureusement, le décodage étant très long avec un eePC, nous avons recommencé et relancé le décodage sur notre Zabeth préférée. | ||
+ | |||
+ | |||
+ | Après une heure d'acharnement, nous avons enfin une clé ! | ||
+ | <center> | ||
+ | {| | ||
+ | |<pre> | ||
+ | Opening dump-01.cap | ||
+ | Read 5625 packets. | ||
+ | |||
+ | # BSSID ESSID Encryption | ||
+ | |||
+ | 1 04:DA:D2:9C:50:52 cracotte03 WPA (1 handshake) | ||
+ | |||
+ | Choosing first network as target. | ||
+ | |||
+ | Opening dump-01.cap | ||
+ | Reading packets, please wait... | ||
+ | |||
+ | Aircrack-ng 1.2 beta3 | ||
+ | |||
+ | |||
+ | [00:59:31] 12399952 keys tested (3160.12 k/s) | ||
+ | |||
+ | |||
+ | KEY FOUND! [ 12399903 ] | ||
+ | |||
+ | |||
+ | Master Key : 33 2B 69 DD 95 0A 5A E0 01 22 7E FF 98 DA 99 87 | ||
+ | 40 7A CB CC 8A E5 32 9F FE 4E 5C 44 91 38 13 93 | ||
+ | |||
+ | Transient Key : 27 04 CB E4 68 2F D2 F6 CE 7D DF 51 25 60 2E 34 | ||
+ | D0 D1 87 B9 A9 A5 3E 6E A6 6A EC 1E 05 29 12 D8 | ||
+ | 26 E5 DA 78 E4 87 AE 71 7A 5F AC BB 44 41 4E 2F | ||
+ | 9D 18 A4 2C BF 88 82 59 BB F8 50 15 82 45 77 35 | ||
+ | |||
+ | EAPOL HMAC : B6 83 11 A0 AC E3 AC 73 9D 7F 15 0A F1 A6 68 62 | ||
+ | </pre> | ||
+ | | [[Fichier:pra_ima5sc_crack_gr3.png|thumb|upright=3|Terminal affichant le résultat]] | ||
+ | |} | ||
+ | </center> | ||
+ | |||
+ | == Services Internet == | ||
+ | |||
+ | === Serveur SSH === | ||
+ | Il suffit d'installer ssh sur notre machine virtuelle si ce n'est pas déjà fait : | ||
+ | <pre> | ||
+ | apt-get install ssh | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Ensuite, pour autoriser la connexion en root en ssh, on remplace un paramètre dans le fichier /etc/ssh/sshd_config : | ||
+ | <pre> | ||
+ | #PermitRootLogin without-password | ||
+ | PermitRootLogin yes | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Et on redémarre le service : | ||
+ | <pre> | ||
+ | service ssh restart | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Une fois le DNS configuré ci-après, nous pouvons facilement accéder à notre machine virtuelle depuis n'importe où : | ||
+ | <pre> | ||
+ | ssh root@www.piscinemorte.net | ||
+ | </pre> | ||
+ | <pre> | ||
+ | root@www.piscinemorte.net's password: | ||
+ | |||
+ | The programs included with the Debian GNU/Linux system are free software; | ||
+ | the exact distribution terms for each program are described in the | ||
+ | individual files in /usr/share/doc/*/copyright. | ||
+ | |||
+ | Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent | ||
+ | permitted by applicable law. | ||
+ | Last login: Tue Dec 6 18:13:23 2016 | ||
+ | root@Deadpool:~# | ||
+ | </pre> | ||
+ | |||
+ | === Serveur DNS === | ||
+ | Nous avons d'abord réservé sur Gandi notre nom de domaine : piscinemorte.net | ||
+ | |||
+ | Ensuite, nous avons installé les paquets bind et apache sur notre machine virtuelle (le dossier /var/www/www.piscinemorte.net servira pour la page web) : | ||
+ | <pre> | ||
+ | apt-get update | ||
+ | apt-get install apache2 bind9 | ||
+ | mkdir /var/www/www.piscinemorte.net | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Une fois bind installé, on créer un fichier de zone db.piscinemorte.net (appellé également une "table de DNS") : | ||
+ | <pre> | ||
+ | ; | ||
+ | ; BIND data file for local loopback interface | ||
+ | ; | ||
+ | $TTL 604800 | ||
+ | @ IN SOA ns.piscinemorte.net. root.piscinemorte.net ( | ||
+ | 2 ; Serial | ||
+ | 604800 ; Refresh | ||
+ | 86400 ; Retry | ||
+ | 2419200 ; Expire | ||
+ | 604800 ) ; Negative Cache TTL | ||
+ | ; | ||
+ | IN NS ns.piscinemorte.net. | ||
+ | ns IN A 193.48.57.163 | ||
+ | www IN A 193.48.57.163 | ||
+ | </pre> | ||
+ | Notre DNS (ns) a pour adresse 193.48.57.163, c'est à dire l'IP de notre machine virtuelle. | ||
+ | |||
+ | |||
+ | Enfin, nous configurons le fichier named.conf.local pour autoriser le transfert de paquets vers le DNS Esclave (l'adresse de Gandi dans notre cas) : | ||
+ | <pre> | ||
+ | zone "piscinemorte.net" { | ||
+ | type master; | ||
+ | file "/etc/bind/db.piscinemorte.net"; | ||
+ | allow-transfer {217.70.177.40;}; | ||
+ | }; | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Pour finir, on redémarre notre service bind : | ||
+ | <pre> | ||
+ | service bind9 restart | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Sur le site Gandi, depuis la gestion des domaines, nous avons besoin de gérer les 'glue records' et signaler nos serveurs DNS : | ||
+ | <pre> | ||
+ | (Pour les 'glues records') | ||
+ | 'Nom du serveur' : ns.piscinemorte.net | ||
+ | 'IP' : 193.48.57.163 | ||
+ | </pre> | ||
+ | <pre> | ||
+ | (Pour les DNS) | ||
+ | 'DNS1' : ns.piscinemorte.net | ||
+ | 'DNS2' : ns6.gandi.net | ||
+ | </pre> | ||
+ | |||
+ | === Sécurisation de site web par certificat === | ||
+ | Pour avoir un certificat SSL généré Gandi, nous avons généré un CSR de la façon suivante : | ||
+ | <pre> | ||
+ | openssl req -nodes -newkey rsa:2048 -sha1 -keyout piscinemorte.net.key -out piscinemorte.net.csr | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Nous avons complété les différentes informations demandés (pas vraiment important ici) : | ||
+ | <pre> | ||
+ | Country Name (2 letter code) [AU]:FR | ||
+ | State or Province Name (full name) [Some-State]:Nord | ||
+ | Locality Name (eg, city) []:Lille | ||
+ | Organization Name (eg, company) [Internet Widgits Pty Ltd]:piscinemorte.net | ||
+ | Organizational Unit Name (eg, section) []:piscinemorte.net | ||
+ | Common Name (e.g. server FQDN or YOUR name) []:piscinemorte.net | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Une fois notre certificat généré et validé par Gandi, nous plaçons nos fichiers de certification dans les dossiers adéquates : | ||
+ | <pre> | ||
+ | cp piscinemorte.net.crt /etc/ssl/certs/piscinemorte.net.crt | ||
+ | cp piscinemorte.net.key /etc/ssl/private/piscinemorte.net.key | ||
+ | cp GandiStandardSSLCA2.pem /etc/ssl/certs/GandiStandardSSLCA2.pem | ||
+ | </pre> | ||
+ | On notera que GandiStandardSSLCA2.pem est un certificat intermédiaire qui permet de certifier notre certificat. | ||
+ | |||
+ | |||
+ | Nous refaisons un hashage de la structure pour prendre en compte notre certificat : | ||
+ | <pre> | ||
+ | c_rehash /etc/ssl/certs | ||
+ | </pre> | ||
+ | <pre> | ||
+ | Doing /etc/ssl/certs | ||
+ | piscinemorte.net.crt => 651ac028.0 | ||
+ | piscinemorte.net.crt => 179c2ae2.0 | ||
+ | GandiStandardSSLCA2.pem => 8544bf03.0 | ||
+ | GandiStandardSSLCA2.pem => e279a80b.0 | ||
+ | ssl-cert-snakeoil.pem => ac2485cc.0 | ||
+ | ssl-cert-snakeoil.pem => 1682ec15.0 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On créé le fichier 000-piscinemorte.net-ssl.conf dans /etc/apache2/sites-available/ pour associer apache2 avec notre nom de serveur : | ||
+ | <pre> | ||
+ | #NameVirtualHost *:443 | ||
+ | <VirtualHost 193.48.57.163:443> | ||
+ | ServerName www.piscinemorte.net | ||
+ | ServerAlias piscinemorte.net | ||
+ | DocumentRoot /var/www/www.piscinemorte.net/ | ||
+ | CustomLog /var/log/apache2/secure_acces.log combined | ||
+ | |||
+ | SSLEngine on | ||
+ | SSLCertificateFile /etc/ssl/certs/piscinemorte.net.crt | ||
+ | SSLCertificateKeyFile /etc/ssl/private/piscinemorte.net.key | ||
+ | SSLCertificateChainFile /etc/ssl/certs/GandiStandardSSLCA2.pem | ||
+ | SSLVerifyClient None | ||
+ | </VirtualHost> | ||
+ | <Directory /var/www/www.piscinemorte.net> | ||
+ | Require all granted | ||
+ | </Directory> | ||
+ | ServerName "piscinemorte.net" | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Nous avons modifié le fichier ports.conf du serveur Apache pour qu'il écoute le port 443 (SSL): | ||
+ | <pre> | ||
+ | Listen 80 443 | ||
+ | |||
+ | <IfModule ssl_module> | ||
+ | Listen 443 | ||
+ | </IfModule> | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Il ne suffit plus qu'à activer le module SSL de Apache : | ||
+ | <pre> | ||
+ | a2enmod ssl | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Puis activer notre site avec notre certificat : | ||
+ | <pre> | ||
+ | a2ensite 000-piscinemorte.net-ssl.conf | ||
+ | service apache2 reload | ||
+ | </pre> | ||
+ | |||
+ | <center> | ||
+ | {| | ||
+ | | [[Fichier:img_ima5sc_certificat_2.png|thumb|upright=4|Cadenas vert visible depuis la barre de lien]] | ||
+ | | [[Fichier:img_ima5sc_certificat_1.png|thumb|upright=2|Certificat délivré pour notre domaine]] | ||
+ | |} | ||
+ | </center> | ||
+ | |||
+ | === Sécurisation de serveur DNS par DNSSEC === | ||
+ | Tout d'abord, on ajoute une option dans /etc/bind/named.conf.options pour activer dnssec : | ||
+ | <pre> | ||
+ | dnssec-enable yes; | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On créé un répertoire spécial pour y générer les clés | ||
+ | <pre> | ||
+ | mkdir piscinemorte.net.dnssec | ||
+ | cd piscinemorte.net.dnssec | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Puis on génère la clé de signature de clefs de zone (KSK) et la clé de la zone pour signer les enregistrements (ZSK) | ||
+ | <pre> | ||
+ | dnssec-keygen -a RSASHA1 -b 2048 -f KSK -r /dev/urandom -n ZONE piscinemorte.net | ||
+ | dnssec-keygen -a RSASHA1 -b 1024 -r /dev/urandom -n ZONE piscinemorte.net | ||
+ | </pre> | ||
+ | L'option "-r /dev/urandom" sert à accélérer la génération des clés | ||
+ | |||
+ | |||
+ | Après avoir renommé les clés générées, on les inclue dans notre fichier de zone /etc/bind/db.piscinemorte.net | ||
+ | <pre> | ||
+ | $include /etc/bind/piscinemorte.net.dnssec/piscinemorte.net-ksk.key | ||
+ | $include /etc/bind/piscinemorte.net.dnssec/piscinemorte.net-zsk.key | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On signe les enregistrements de la zone : | ||
+ | <pre> | ||
+ | dnssec-signzone -o piscinemorte.net -k piscinemorte.net-ksk ../db.piscinemorte.net piscinemorte.net-zsk | ||
+ | </pre> | ||
+ | <pre> | ||
+ | Verifying the zone using the following algorithms: RSASHA1. | ||
+ | Zone fully signed: | ||
+ | Algorithm: RSASHA1: KSKs: 1 active, 0 stand-by, 0 revoked | ||
+ | ZSKs: 1 active, 0 stand-by, 0 revoked | ||
+ | ../db.piscinemorte.net.signed | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Pour finir, il ne reste plus qu'à communiquer la partie publique de la KSK (et ZSK) à notre registrar (sur gandi.net via "Gérer DNSSEC") et vérifier la sécurisation : | ||
+ | <center> | ||
+ | {| | ||
+ | | [[Fichier:img_ima5sc_gandiDNSSEC.png|thumb|upright=4|Partie publie de la KSK (et ZSK) sur Gandi]] | ||
+ | | [[Fichier:img_ima5sc_DNSSECtest.png|thumb|upright=1.75|Test du DNSSEC]] | ||
+ | |} | ||
+ | </center> | ||
+ | |||
+ | == Sécurisation et cryptage de données == | ||
+ | === Sécurisation de données via RAID5 === | ||
+ | On créer 3 disques virtuels avec lvcreate : | ||
+ | <pre> | ||
+ | lvcreate -L 1G -n /dev/virtual/Deadpool-raid1 | ||
+ | lvcreate -L 1G -n /dev/virtual/Deadpool-raid2 | ||
+ | lvcreate -L 1G -n /dev/virtual/Deadpool-raid3 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On les rajoute à notre configuration de machine virtuelle (/etc/xen/Deadpool.cfg) : | ||
+ | <pre> | ||
+ | 'phy:/dev/virtual/Deadpool-raid1,xvdd1, w', | ||
+ | 'phy:/dev/virtual/Deadpool-raid2,xvdd2, w', | ||
+ | 'phy:/dev/virtual/Deadpool-raid3,xvdd3, w', | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Ensuite, nous avons besoin d'installer mdadm et mettre à jour le kernel sinon nous aurons une erreur de mdadm lors de la création du RAID5 : | ||
+ | <pre> | ||
+ | apt-get install mdadm linux-image.3.16.0-4-amd64 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Il ne nous reste plus qu'à créer notre disque RAID5 md0 : | ||
+ | <pre> | ||
+ | mdadm --create /dev/md0 --level=5 --assume-clean --raid-devices=3 /dev/xvdd1 /dev/xvdd2 /dev/xvdd3 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On installe un système de fichier ext4 dessus: | ||
+ | <pre> | ||
+ | mkfs -t ext4 /dev/md0 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On sauvegarde notre configuration : | ||
+ | <pre> | ||
+ | mdadm --detail --scan >> /etc/mdadm/mdadm.conf | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On le monte : | ||
+ | <pre> | ||
+ | mount /dev/md0 /mnt | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Après avoir créer un fichier dans notre RAID5, nous supprimons une des répartitions pour voir si le RAID5 se reconstruit correctement : | ||
+ | <pre> | ||
+ | mdadm --set-faulty /dev/md0 /dev/xvdd2 | ||
+ | mdadm --remove /dev/md0 /dev/xvdd2 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | On voit que la partition a bien été supprimée et nos données toujours présents : | ||
+ | <pre> | ||
+ | cat /proc/mdstat | ||
+ | </pre> | ||
+ | <pre> | ||
+ | Personalities : [raid6] [raid5] [raid4] | ||
+ | md0 : active raid5 xvdd1[0] xvdd3[2] | ||
+ | 2095104 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [U_U] | ||
+ | </pre> | ||
+ | <pre> | ||
+ | mount /dev/md0 /mnt | ||
+ | </pre> | ||
+ | <pre> | ||
+ | [88763.077524] EXT4-fs (md0): recovery complete | ||
+ | [88763.077545] EXT4-fs (md0): mounted filesystem with ordered data mode. Opts: (null) | ||
+ | <pre> | ||
+ | root@Deadpool:/mnt# ls | ||
+ | lost+found test.txt | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Nous remettons la partition : | ||
+ | <pre> | ||
+ | mdadm --add /dev/md0 /dev/xvdd2 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Et on observe la reconstruction grâce à cat /proc/mdstat : | ||
+ | <pre> | ||
+ | Personalities : [raid6] [raid5] [raid4] | ||
+ | md0 : active raid5 xvdd2[3] xvdd1[0] xvdd3[2] | ||
+ | 2095104 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [U_U] | ||
+ | [==========>..........] recovery = 51.9% (544664/1047552) finish=0.2min speed=30259K/sec | ||
+ | </pre> | ||
+ | |||
+ | === Cryptage de données === | ||
+ | |||
+ | Dans cette partie, nous allons voir comment crypter des données sur une carte SD. | ||
+ | |||
+ | On cherche notre carte sd dans dev : | ||
+ | |||
+ | <pre> | ||
+ | ls /dev | ||
+ | </pre> | ||
+ | |||
+ | puis on va configurer notre carte : | ||
+ | |||
+ | <pre> | ||
+ | fdisk /dev/mmcblk1 | ||
+ | "d pour supprimer les partitions 1-2-3" | ||
+ | "n pour ajouter des partitions" | ||
+ | "w pour enregistrer" | ||
+ | </pre> | ||
+ | |||
+ | On créé donc une unique partition de taille 15G sur mmcblk1p1. | ||
+ | |||
+ | On va maintenant configurer la carte SD en type Luks avec un chiffrement aes et un algorithme de hachage SHA256: | ||
+ | |||
+ | <pre> | ||
+ | cryptsetup luksFormat -c eas -h sha256 /dev/mmcblk1 | ||
+ | </pre> | ||
+ | |||
+ | Avec la phrase secrète : pasglop | ||
+ | |||
+ | On peut vérifier les infos de la partitions avec : | ||
+ | |||
+ | <pre> | ||
+ | cryptsetup luksDump /dev/mmcblk1 | ||
+ | </pre> | ||
+ | |||
+ | On ouvre notre partition cryptée avec : | ||
+ | |||
+ | <pre> | ||
+ | cryptsetup luksOpen /dev/mmcblk1 | ||
+ | </pre> | ||
+ | en saisissant la phrase secrète. | ||
+ | |||
+ | et on ajoute des fichiers : | ||
+ | <pre> | ||
+ | mkfs.ext3 /dev/mapper/kadoc | ||
+ | </pre> | ||
+ | |||
+ | On décide de créer un dossier contenant un fichier txt contenant une phrase. | ||
+ | Pour écrire dedans il faut monter notre carte : | ||
+ | |||
+ | <pre> | ||
+ | |||
+ | mount -t ext3 /dev/mapper/kadoc /mnt/ pour monter la partition. | ||
+ | |||
+ | umount /mnt/ pour démonter la partition. | ||
+ | </pre> | ||
+ | |||
+ | Il faut re-encrypter notre partition avec | ||
+ | |||
+ | <pre> | ||
+ | cryptsetup luksClose kadoc | ||
+ | </pre> | ||
+ | |||
+ | On peut vérifier avec GParted que notre partition n'est plus accessible, à moins d'avoir le mot de passe pour la décrypter. | ||
+ | <pre> | ||
+ | gparted /dev/mmcblk1 | ||
+ | </pre> | ||
+ | |||
+ | == Création de deux points d'accès Wi-Fi avec serveur d'authentification FreeRADIUS == | ||
+ | === Création du serveur FreeRADIUS === | ||
+ | Tout d'abord, nous mettons en place un serveur d'identification FreeRADIUS en PEAP-MSCHAPv2 qui va tourner sur notre machine virtuelle. | ||
+ | |||
+ | Pour cela, il faut installer FreeRADIUS : | ||
+ | <pre> | ||
+ | apt-get install freeradius | ||
+ | </pre> | ||
− | |||
+ | Puis, on ajoute un utilisateur dans le fichier /etc/freeradius/users pour s'authentifier sur le réseau WiFi : | ||
<pre> | <pre> | ||
− | + | nom_de_l_utilisateur Cleartext-password := "mot_de_passe" | |
</pre> | </pre> | ||
− | + | ||
+ | On rajoute aussi les clients (correspondants aux deux points d'accès Wifi et à notre futur VLAN) dans le fichier /etc/freeradius/clients.conf : | ||
<pre> | <pre> | ||
− | + | client E304 { | |
− | + | ipaddr = 10.60.1.6 | |
+ | secret = mot_de_passe | ||
+ | } | ||
+ | |||
+ | client E306 { | ||
+ | ipaddr = 10.60.1.2 | ||
+ | secret = mot_de_passe | ||
+ | } | ||
+ | |||
+ | client VLAN3 { | ||
+ | ipaddr = 10.60.4.0 | ||
+ | secret = mot_de_passe | ||
+ | } | ||
</pre> | </pre> | ||
+ | Pour utiliser le PEAP-MSCHAPv2, on modifie dans le fichier /etc/freeradius/eap.conf les valeurs suivantes : | ||
+ | <pre> | ||
+ | eap | ||
+ | { | ||
+ | default_eap_type = peap | ||
+ | peap | ||
+ | { | ||
+ | default_eap_type = mschapv2 | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
− | |||
− | + | On fini par redémarrer FreeRADIUS pour bien prendre en compte les nouveaux paramètres : | |
+ | <pre> | ||
+ | service freeradius restart | ||
+ | </pre> | ||
− | + | === Configuration des bornes Wi-Fi === | |
+ | Une fois les points d'accès Wifi disponibles, nous pouvons les configurer afin de créer notre propre SSID protégé par la méthode WPA2-EAP avec notre serveur d'authentification FreeRadius. | ||
− | + | On commence par se connecter à l'une des deux bornes Wifi via Telnet : | |
+ | <pre> | ||
+ | telnet 10.60.1.2 | ||
+ | </pre> | ||
− | |||
− | + | Nous configurons le point d'accès (login : Cisco / password : Cisco) de la manière suivante pour créer notre VLAN et notre SSID : | |
+ | <pre> | ||
+ | enable | ||
+ | conf t | ||
− | + | aaa new-model | |
+ | aaa authentication login eap_deadpool group radius_deadpool | ||
+ | radius-server host 193.48.57.163 auth-port 1812 acct-port 1813 key mot_de_passe | ||
+ | aaa group server radius radius_deadpool | ||
+ | server 193.48.57.163 auth-port 1812 acct-port 1813 | ||
+ | exit | ||
− | + | dot11 ssid Deadpool | |
+ | vlan 4 | ||
+ | authentication open eap eap_deadpool | ||
+ | authentication network-eap eap_deadpool | ||
+ | authentication key-management wpa | ||
+ | mbssid guest-mode | ||
+ | exit | ||
− | + | interface Dot11Radio0 | |
+ | encryption vlan 4 mode ciphers aes-ccm tkip | ||
+ | ssid Deadpool | ||
+ | exit | ||
− | + | interface Dot11Radio0.4 | |
− | + | encapsulation dot1Q 4 | |
− | + | no ip route-cache | |
− | + | bridge-group 4 | |
− | + | bridge-group 4 subscriber-loop-control | |
+ | bridge-group 4 spanning-disabled | ||
+ | bridge-group 4 block-unknown-source | ||
+ | no bridge-group 4 source-learning | ||
+ | no bridge-group 4 unicast-flooding | ||
+ | exit | ||
− | + | interface GigabitEthernet0.4 | |
+ | encapsulation dot1Q 4 | ||
+ | bridge-group 4 | ||
+ | exit | ||
+ | |||
+ | exit | ||
+ | </pre> | ||
+ | Pour le deuxième point d'accès, il suffit de refaire la même chose. | ||
− | + | === Connexion à notre Wi-Fi === | |
− | + | On se connecte à notre point d'accès grâce à nos identifiants créés précédemment dans la configuration de FreeRadius. | |
− | |||
− | + | On configure l'accès sur un eeepc en modifiant le fichier /etc/network/interfaces : | |
<pre> | <pre> | ||
− | + | auto wlan0 | |
+ | iface wlan0 inet static | ||
+ | address 10.60.4.10 | ||
+ | netmask 255.255.255.0 | ||
+ | gateway 10.60.4.1 | ||
+ | wpa-ssid Deadpool | ||
+ | wpa-key-mgmt WPA-EAP | ||
+ | wpa-identity nom_de_l_utilisateur | ||
+ | wpa-password mot_de_passe | ||
</pre> | </pre> | ||
− | + | ||
+ | Enfin, on démarre l'interface pour se connecter sur notre point d'accès : | ||
+ | <pre> | ||
+ | ifup wlan0 | ||
+ | iwconfig | ||
+ | </pre> | ||
<pre> | <pre> | ||
− | + | wlan0 IEEE 802.11bgn ESSID:"Deadpool" | |
+ | Mode:Managed Frequency:2.447 GHz Access Point: 44:AD:D9:5F:87:00 | ||
+ | Bit Rate=1 Mb/s Tx-Power=20 dBm | ||
+ | Retry short limit:7 RTS thr:off Fragment thr:off | ||
+ | Encryption key:off | ||
+ | Power Management:off | ||
+ | Link Quality=59/70 Signal level=-51 dBm | ||
+ | Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 | ||
+ | Tx excessive retries:1 Invalid misc:53 Missed beacon:0 | ||
+ | </pre> | ||
− | + | On arrive à ping notre eePC depuis la machine virtuelle : | |
+ | <pre> | ||
+ | root@Deadpool:/# ping 10.60.4.10 | ||
+ | PING 10.60.4.10 (10.60.4.10) 56(84) bytes of data. | ||
+ | 64 bytes from 10.60.4.10: icmp_seq=1 ttl=62 time=1.22 ms | ||
+ | 64 bytes from 10.60.4.10: icmp_seq=2 ttl=62 time=1.57 ms | ||
+ | 64 bytes from 10.60.4.10: icmp_seq=3 ttl=62 time=8.32 ms | ||
+ | 64 bytes from 10.60.4.10: icmp_seq=4 ttl=62 time=9.30 ms | ||
+ | 64 bytes from 10.60.4.10: icmp_seq=5 ttl=62 time=1.55 ms | ||
+ | 64 bytes from 10.60.4.10: icmp_seq=6 ttl=62 time=1.29 ms | ||
+ | ^C | ||
+ | --- 10.60.4.10 ping statistics --- | ||
+ | 6 packets transmitted, 6 received, 0% packet loss, time 5007ms | ||
+ | rtt min/avg/max/mdev = 1.226/3.879/9.304/3.501 ms | ||
+ | </pre> | ||
− | |||
− | + | En ayant préalablement activé les logs des connexions dans la configuration de FreeRadius, on peut observer les authentifications dans /var/log/freeradius/radius.log : | |
+ | <pre> | ||
+ | Thu Dec 8 13:56:09 2016 : Info: Loaded virtual server <default> | ||
+ | Thu Dec 8 13:56:09 2016 : Info: Loaded virtual server inner-tunnel | ||
+ | Thu Dec 8 13:56:09 2016 : Info: Ready to process requests. | ||
+ | Thu Dec 8 13:59:58 2016 : Auth: Login OK: [pifou/<via Auth-Type = EAP>] (from client E306 port 0 via TLS tunnel) | ||
+ | Thu Dec 8 13:59:58 2016 : Auth: Login OK: [pifou/<via Auth-Type = EAP>] (from client E306 port 326 cli 40a5.ef05.a110) | ||
+ | </pre> | ||
− | + | == DHCP et PCBX == | |
+ | === Configuration du DHCP === | ||
+ | On installe de quoi faire un serveur DHCP sur notre eePC : | ||
+ | <pre> | ||
+ | apt-get install isc-dhcp-server | ||
+ | </pre> | ||
− | |||
− | + | On configure notre serveur DHCP via le fichier de configuration (/etc/dhcp/dhcpd.conf) | |
+ | <pre> | ||
+ | option domain-name "piscinemorte.net"; | ||
+ | option domain-name-servers ns.piscinemorte.net; | ||
+ | |||
+ | subnet 10.60.4.0 netmask 255.255.255.0 { | ||
+ | range 10.60.4.11 10.60.4.30 | ||
+ | option routers 10.60.4.254 | ||
+ | } | ||
+ | </pre> | ||
− | |||
− | |||
+ | Après avoir redémarré notre serveur DHCP, on se connecte facilement à notre point d'accès grâce au DHCP qui nous attribue une adresse IP dans la plage voulue : | ||
+ | <center> | ||
+ | {| | ||
+ | | [[Fichier:Screenshot_2016-12-12-11-08-16.png|thumb|upright=1|Informations de connexion sur un Sony Xperia S]] | ||
+ | | [[Fichier:Bvxfbdbd.jpg|thumb|upright=1|Informations de connexion sur un Iphone]] | ||
+ | |} | ||
+ | </center> | ||
− | + | === Configuration et utilisation du PCBX === | |
+ | On installe Asterisk pour créer un serveur permettant une communication SIP : | ||
+ | <pre> | ||
+ | apt-get install asterisk | ||
+ | </pre> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Configuration via /etc/asterisk/sip.conf : | |
+ | <pre> | ||
+ | [general] | ||
+ | allowguest=no | ||
+ | alwaysauthreject=yes | ||
+ | contactacl=local_ip_acl | ||
+ | hasvoicemail = yes | ||
+ | hassip = yes | ||
+ | hasiax = yes | ||
+ | callwaiting = yes | ||
+ | threewaycalling = yes | ||
+ | callwaitingcallerid = yes | ||
+ | tranfer = yes | ||
+ | canpark = yes | ||
+ | cancallforward = yes | ||
+ | callreturn = yes | ||
+ | callgroup = yes | ||
+ | pickupgroup = yes | ||
+ | nat = yes | ||
+ | [6001] | ||
+ | type=peer | ||
+ | host=dynamic | ||
+ | dtmfmode=rfc2833 | ||
+ | disallow=all | ||
+ | allow=ulaw | ||
+ | fullname=dpl1 | ||
+ | username=dpl1 | ||
+ | secret=secret | ||
+ | context=work | ||
+ | acl=acl1 | ||
− | + | [6002] | |
− | + | type=peer | |
− | + | host=dynamic | |
+ | dtmfmode=rfc2833 | ||
+ | disallow=all | ||
+ | allow=ulaw | ||
+ | fullname=dpl2 | ||
+ | username=dpl2 | ||
+ | secret=secret | ||
+ | context=work | ||
+ | acl=acl1 | ||
+ | </pre> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Configuration via /etc/asterisk/extensions.conf : | |
+ | <pre> | ||
+ | [work] | ||
+ | exten => _6XXX,1,Dial(SIP/${EXTEN},20) | ||
+ | exten => _6XXX,2,Hangup() | ||
+ | </pre> | ||
− | + | Configuration des autorisations via /etc/asterisk/acl.conf : | |
− | + | <pre> | |
+ | acl = acl1 | ||
− | + | [acl1] | |
− | + | permit=0.0.0.0/0.0.0.0 | |
− | |||
− | |||
− | |||
− | |||
</pre> | </pre> | ||
− | + | ||
+ | On se connecte à un compte SIP (dpl1 et dpl2) et on passe un appel grâce à l'identifiant configuré précédemment : | ||
+ | <center> | ||
+ | {| | ||
+ | | [[Fichier:20161212 123958.jpg|thumb|upright=2|Serveur asterisk avec les téléphones connectés]] | ||
+ | | [[Fichier:20161212 124022.jpg|thumb|upright=2|Communication entre les deux téléphones via SIP]] | ||
+ | |} | ||
+ | </center> | ||
+ | |||
+ | == Références == | ||
+ | Pour la gestion du serveur DAS : | ||
+ | *[http://www.hp.com/ctg/Manual/c00710359.pdf HP - Maintenance et service du G5] | ||
+ | *[https://www.hpe.com/h20195/v2/GetPDF.aspx/c04282492.pdf HP - Datasheet du G5] | ||
+ | *[http://h18000.www1.hp.com/products/quickspecs/archives_North_America/12627_na_v5/12627_na.PDF HP - Datasheet du MSA60] | ||
+ | *[http://h10032.www1.hp.com/ctg/Manual/c00816284 HP - Datasheet en Français (lien mort ?)] | ||
+ | *[http://wiki.csnu.org/index.php/Installation_des_outils_HP_pour_debian Wiki CSNU - Installation des outils HP pour debian] | ||
+ | *[https://oitibs.com/hp-acu-command-line-reference/ Oitibs - Commandes disponibles pour hpssacli] |
Version actuelle datée du 6 janvier 2017 à 15:59
Sommaire
- 1 Tâche spécifique
- 2 Tâches communes
Tâche spécifique
Nous devons mettre en place un système de sauvegarde en réseau pour pouvoir sauvegarder l'état et les données de nos machines virtuelles.
Pour cela, nous allons utiliser un serveur de type DAS (Direct Attach Storage).
Cela consiste à une baie de stockage directement branchée sur le réseau via un câble et accessible comme n'importe quel périphérique.
Gestion du serveur DAS
Installation des outils HP
Ajout du dépôt dans /etc/apt/sources.net :
deb http://downloads.linux.hpe.com/SDR/repo/mcp/ jessie/current non-free
Copier / Coller le contenu des clés et les ajouter, liens des clés disponibles à ces adresses :
http://downloads.linux.hpe.com/SDR/hpPublicKey1024.pub http://downloads.linux.hpe.com/SDR/hpPublicKey2048.pub http://downloads.linux.hpe.com/SDR/hpPublicKey2048_key1.pub
Ajout des clefs :
apt-key add ./hpPublicKey1024.pub apt-key add ./hpPublicKey2048.pub apt-key add ./hpPublicKey2048_key1.pub
On met à jour les paquets et on installe l'utilitaire HP hpssacli :
aptitude update aptitude install hp-health hpssacli
Liste des commandes disponibles pour hpssacli
Configuration des disques
Après avoir installé l'utilitaire HP pour gérer nos disques, nous pouvons enfin savoir les caractéristiques des baies :
hpssacli ctrl all show config
On obtient alors :
Smart Array P800 in Slot 4 (sn: P98690E9SV10C3) Port Name: 1I Port Name: 2I Port Name: 1E Port Name: 2E Internal Drive Cage at Port 3I, Box 1, OK Internal Drive Cage at Port 4I, Box 1, OK StorageWorks MSA 60 at Port 1E, Box 1, OK array A (SAS, Unused Space: 0 MB) logicaldrive 1 (820.2 GB, RAID 5, OK) physicaldrive 3I:1:1 (port 3I:box 1:bay 1, SAS, 146 GB, OK) physicaldrive 3I:1:2 (port 3I:box 1:bay 2, SAS, 146 GB, OK) physicaldrive 3I:1:3 (port 3I:box 1:bay 3, SAS, 146 GB, OK) physicaldrive 3I:1:4 (port 3I:box 1:bay 4, SAS, 146 GB, OK) physicaldrive 4I:1:5 (port 4I:box 1:bay 5, SAS, 146 GB, OK) physicaldrive 4I:1:6 (port 4I:box 1:bay 6, SAS, 146 GB, OK) physicaldrive 4I:1:8 (port 4I:box 1:bay 8, SAS, 146 GB, OK) physicaldrive 4I:1:7 (port 4I:box 1:bay 7, SAS, 146 GB, OK, spare) array B (SATA, Unused Space: 0 MB) logicaldrive 2 (1.9 TB, RAID 5, Recovering, 0% complete) logicaldrive 3 (1.9 TB, RAID 5, Ready for Rebuild) logicaldrive 4 (751.2 GB, RAID 5, Ready for Rebuild) physicaldrive 1E:1:1 (port 1E:box 1:bay 1, SATA, 1 TB, OK) physicaldrive 1E:1:2 (port 1E:box 1:bay 2, SATA, 1 TB, OK) physicaldrive 1E:1:4 (port 1E:box 1:bay 4, SATA, 1 TB, OK) physicaldrive 1E:1:5 (port 1E:box 1:bay 5, SATA, 1 TB, OK) physicaldrive 1E:1:6 (port 1E:box 1:bay 6, SATA, 1 TB, OK) physicaldrive 1E:1:11 (port 1E:box 1:bay 11, SATA, 1 TB, Rebuilding) physicaldrive 1E:1:3 (port 1E:box 1:bay 3, SATA, 1 TB, OK, spare) array C (SATA, Unused Space: 0 MB) logicaldrive 5 (1.9 TB, RAID 5, OK) logicaldrive 6 (1.7 TB, RAID 5, OK) physicaldrive 1E:1:7 (port 1E:box 1:bay 7, SATA, 1 TB, OK) physicaldrive 1E:1:8 (port 1E:box 1:bay 8, SATA, 1 TB, OK) physicaldrive 1E:1:9 (port 1E:box 1:bay 9, SATA, 1 TB, OK) physicaldrive 1E:1:10 (port 1E:box 1:bay 10, SATA, 1 TB, OK) physicaldrive 1E:1:12 (port 1E:box 1:bay 12, SATA, 1 TB, OK) physicaldrive 1E:1:3 (port 1E:box 1:bay 3, SATA, 1 TB, OK, spare)
Nous avons supprimé (et formaté) tous les disques logiques liés aux disques physiques du StorageWorks MSA 60
hpssacli ctrl slot=4 ld 6 delete hpssacli ctrl slot=4 ld 5 delete ... hpssacli ctrl slot=4 ld 2 delete
Puis créé un disque logique en RAID 10 avec tous les disques physiques du MSA60 qui sera notre disque réservé pour la sauvegarde des VM
hpssacli ctrl slot=4 create type=ld drives=1E:1:1,1E:1:2,1E:1:3,1E:1:4,1E:1:5,1E:1:6,1E:1:7,1E:1:8,1E:1:9,1E:1:10,1E:1:11,1E:1:12 raid=1+0
Enfin, on s'assure que le disque logique a correctement été généré
array B (SATA, Unused Space: 0 MB) logicaldrive 2 (5.5 TB, RAID 1+0, OK) physicaldrive 1E:1:1 (port 1E:box 1:bay 1, SATA, 1 TB, OK) physicaldrive 1E:1:2 (port 1E:box 1:bay 2, SATA, 1 TB, OK) physicaldrive 1E:1:3 (port 1E:box 1:bay 3, SATA, 1 TB, OK) physicaldrive 1E:1:4 (port 1E:box 1:bay 4, SATA, 1 TB, OK) physicaldrive 1E:1:5 (port 1E:box 1:bay 5, SATA, 1 TB, OK) physicaldrive 1E:1:6 (port 1E:box 1:bay 6, SATA, 1 TB, OK) physicaldrive 1E:1:7 (port 1E:box 1:bay 7, SATA, 1 TB, OK) physicaldrive 1E:1:8 (port 1E:box 1:bay 8, SATA, 1 TB, OK) physicaldrive 1E:1:9 (port 1E:box 1:bay 9, SATA, 1 TB, OK) physicaldrive 1E:1:10 (port 1E:box 1:bay 10, SATA, 1 TB, OK) physicaldrive 1E:1:11 (port 1E:box 1:bay 11, SATA, 1 TB, OK) physicaldrive 1E:1:12 (port 1E:box 1:bay 12, SATA, 1 TB, OK)
Montage du disque de sauvegarde sur le serveur Debian
Les disques logiques et leurs partitions sont répertoriés à l'emplacement suivant :
ls /dev/cciss/
c0d0 c0d0p1 c0d0p2 c0d0p5 c0d0p6 c0d0p7 c0d0p8 c0d1
Ici, c0d0 représente le disque logique (p1,p2,...,p8 les partitions) où est installé Debian (disques physiques liés à la station DL380 G5).
On retrouve notre disque logique (disques physiques liés au MSA60) créé précédemment identifié c0d1 :
fdisk -l /dev/cciss/c0d1
Disque /dev/cciss/c0d1 : 5,5 TiB, 6001026883584 octets, 11720755632 secteurs Unités : secteur de 1 × 512 = 512 octets Taille de secteur (logique / physique) : 512 octets / 512 octets taille d'E/S (minimale / optimale) : 512 octets / 512 octets
On transforme notre disque logique en partition ext4 :
mkfs.ext4 /dev/cciss/c0d1
On créer le dossier qui servira de point de montage, puis on monte notre partition dans celui-ci :
mkdir /backup mount -t auto /dev/cciss/c0d1 /backup
Afin de monter automatiquement notre partition à chaque démarrage, il suffit d'ajouter la ligne suivante dans fstab :
vi /etc/fstab
/dev/cciss/c0d1 /backup ext4 defaults 0 2
Après redémarrage du serveur, on vérifie si notre disque logique est monté automatiquement :
df -h
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur /dev/cciss/c0d0p1 8,2G 881M 6,9G 12% / udev 10M 0 10M 0% /dev tmpfs 775M 456K 775M 1% /run tmpfs 5,0M 0 5,0M 0% /run/lock tmpfs 4,8G 0 4,8G 0% /run/shm /dev/cciss/c0d0p8 781G 69M 741G 1% /home /dev/cciss/c0d0p7 360M 2,1M 335M 1% /tmp /dev/cciss/c0d0p5 2,7G 339M 2,3G 14% /var /dev/cciss/c0d1 5,5T 58M 5,2T 1% /backup
Mise en réseau du disque
Lors de la sauvegarde des machines virtuelles, nous aurons besoin d'accéder à notre disque de sauvegarde.
Pour cela, nous avons mis en place un partage de type NFS (Network File System) :
apt-get install nfs-kernel-server
Il suffit de paramétrer le partage de façon à autoriser un ordinateur distant à accéder à un dossier en particulier (/etc/exports/) :
/backup/vm_backup cordouan.insecserv.deule.net(rw,sync,no_root_squash)
Ici, on autorise le serveur Cordouan à accéder au sous-dossier /backup/vm_backup/ en lecture et écriture.
Scripts de sauvegarde et de restauration de machine virtuelle
Commandes utiles
Sauvegarder l'état d'une machine virtuelle :
xl save -c Deadpool /usr/local/xen/domains/vm_backup/Deadpool.vmbackup
Restaurer l'état d'une machine virtuelle :
xl restore /usr/local/xen/domains/vm_backup/Deadpool.vmbackup
Snapshot des LVM d'une machine virtuelle :
lvcreate -l 10%ORIGIN -s -n ima5-Deadpool-home-snapshot /dev/virtual/ima5-Deadpool-home lvcreate -l 10%ORIGIN -s -n ima5-Deadpool-var-snapshot /dev/virtual/ima5-Deadpool-var
Suppression des snapshots LVM :
lvremove /usr/local/xen/domains/vm_backup/ima5-Deadpool-home-snapshot lvremove /usr/local/xen/domains/vm_backup/ima5-Deadpool-var-snapshot
Sauvegarde des états des machines virtuelles
Nous avons créé un script capable de sauvegarder l'état de toutes les machines virtuelles en cours d’exécution.
Ces machines virtuelles sont mis en pause pendant une à deux secondes le temps de la sauvegarde, ce qui est très rapide.
Voici le script disponible sur notre serveur DAS (/backup/script_backup/save_running_vm.sh) :
#!/bin/bash# #Script de sauvegarde pour les VM en cours d?exécution DATE=`date +%d%b%Y-%H%M%S` MOUNTPOINT=/mnt/vm_backup LIST_VM_FILE=/tmp/vm_list.txt NFS_SERVER_IP="172.26.64.15" ### Create mount point echo "Creating mount point..."; mkdir -p ${MOUNTPOINT} ### Mounting remote nfs share backup drive #[ ! -d ${MOUNTPOINT} ] && echo "No mount point found, kindly check"; exit 0 echo "Mounting backup nfs..."; mount -t nfs ${NFS_SERVER_IP}:/backup/vm_backup ${MOUNTPOINT} BACKUPPATH=${MOUNTPOINT}/${DATE} mkdir -p ${BACKUPPATH} #[ ! -d ${BACKUPPATH} ] && echo "No backup directory found"; exit 0 ### get all running vm xl vm-list | tail -n +2 | cut -d" " -f7 > ${LIST_VM_FILE} #[ ! -f ${LIST_VM_FILE} ] && echo "No UUID list file found"; exit 0 while read VMUUID do echo "Saving ${VMUUID}..."; mkdir -p ${BACKUPPATH}/${VMUUID}/ xl save -c $VMUUID ${BACKUPPATH}/${VMUUID}/${VMUUID}.vmbackup done < ${LIST_VM_FILE} ### Umounting remote nfs share backup drive echo "Umounting backup nfs..."; umount ${MOUNTPOINT} rm ${MOUNTPOINT} -r echo "ALL DONE !";
Le script consiste à monter sur la machine le dossier mis en réseau précédemment, puis il récupère le nom de toutes les machines virtuelles en cours de fonctionnement, et enfin il sauvegarde l'état des machines virtuelles une par une dans des dossiers spécifiques.
Une fois terminé, il démonte le dossier monté précédemment.
Ce script doit être exécuté sur la machine hôte des machines virtuelles, à savoir Cordouan.
Pour cela, il suffit d'un petit script avec une commande pour exécuter le script ci-dessus sur une machine distante (/backup/script_backup/save_running_vm_remote.sh) :
#!/bin/bash# ssh root@cordouan.insecserv.deule.net 'bash -s' < save_running_vm.sh
On exécute notre nouveau script :
sh /backup/script_backup/save_running_vm_remote.sh
Et on laisse le travail se faire :
Creating mount point... Mounting backup nfs... Saving Wolverine... Saving to /mnt/vm_backup/04janv.2017-210539/Wolverine/Wolverine.vmbackup new xl format (info 0x0/0x0/1094) xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 2048/32768 6% ... xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 32768/32768 100% Saving Ironman... Saving to /mnt/vm_backup/04janv.2017-210539/Ironman/Ironman.vmbackup new xl format (info 0x0/0x0/919) xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 2048/32768 6% ... xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 30720/32768 93% xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 32768/32768 100% Saving Batman... Saving to /mnt/vm_backup/04janv.2017-210539/Batman/Batman.vmbackup new xl format (info 0x0/0x0/1049) xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 2048/32768 6% ... xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 32768/32768 100% Saving Frotteman... Saving to /mnt/vm_backup/04janv.2017-210539/Frotteman/Frotteman.vmbackup new xl format (info 0x0/0x0/1056) xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 7168/131072 5% ... xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 131072/131072 100% Saving Deadpool... Saving to /mnt/vm_backup/04janv.2017-210539/Deadpool/Deadpool.vmbackup new xl format (info 0x0/0x0/1054) xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 7168/131072 5% ... xc: progress: Saving memory: iter 0 (last sent 0 skipped 0): 131072/131072 100% Umounting backup nfs... ALL DONE !
Nous pouvons accéder facilement à nos sauvegardes :
root@baleine:/backup/vm_backup/04janv.2017-210539# ls Batman Deadpool Frotteman Ironman Wolverine root@baleine:/backup/vm_backup/04janv.2017-210539# cd Deadpool/ root@baleine:/backup/vm_backup/04janv.2017-210539/Deadpool# ls Deadpool.vmbackup
Sauvegarde des LVM liés aux machines virtuelles
Nous avons créé un script qui permet d'enregistrer les LVM d'une machine virtuelle donnée en argument :
#!/bin/bash #Script de sauvegarde pour toutes les LVM souhaitées #Run with "ssh remote_machine 'bash -s' < /backup/script_backup/save_lvm_data_vm.sh arg" LIST_LVM_FILE=/tmp/lvm_list.txt VM_NAME=$1 LVM_PATH=/dev/virtual/ LVM_MOUNT_PATH=/mnt/lvm_snap MOUNTPOINT=/mnt/vm_backup NFS_SERVER_IP="172.26.64.15" echo "Creating mount point for NFS..."; mkdir -p ${MOUNTPOINT} echo "Mounting backup nfs..."; mount -t nfs ${NFS_SERVER_IP}:/backup/vm_backup ${MOUNTPOINT} echo "Creating directory for LVM mount point..."; mkdir -p ${LVM_MOUNT_PATH} echo "Cheking for $1 LVM..."; ls ${LVM_PATH} | grep -i $1 | grep -i 'var\|home' > ${LIST_LVM_FILE} while read LVM_NAME do echo "Snapshot of ${LVM_NAME} LVM..."; lvcreate -l 10%ORIGIN -s -n ${LVM_NAME}-snapshot ${LVM_PATH}${LVM_NAME} echo "Mounting ${LVM_NAME}-snapshot..."; mount ${LVM_PATH}${LVM_NAME}-snapshot ${LVM_MOUNT_PATH} echo "Doing the backup of ${LVM_NAME}-snapshot..."; tar -cf ${MOUNTPOINT}/${LVM_NAME}-snapshot.tar ${LVM_MOUNT_PATH} echo "Unmounting ${LVM_NAME} LVM..."; umount ${LVM_MOUNT_PATH} echo "Cleaning snapshot of ${LVM_NAME} LVM..."; yes | lvremove ${LVM_PATH}${LVM_NAME}-snapshot done < ${LIST_LVM_FILE} rm ${LVM_MOUNT_PATH} -r echo "Unmounting backup NFS..."; umount ${MOUNTPOINT} rm ${MOUNTPOINT} -r echo "ALL DONE !";
On essaye le script pour notre machine virtuelle en mettant "Deadpool" comme argument :
Creating mount point for NFS... Mounting backup nfs... Creating directory for LVM mount point... Cheking for Deadpool LVM... Snapshot of ima5-Deadpool-home LVM... Logical volume "ima5-Deadpool-home-snapshot" created Mounting ima5-Deadpool-home-snapshot... Doing the backup of ima5-Deadpool-home-snapshot... tar: Suppression de « / » au début des noms des membres Unmounting ima5-Deadpool-home LVM... Cleaning snapshot of ima5-Deadpool-home LVM... Do you really want to remove active logical volume ima5-Deadpool-home-snapshot? [y/n]: Logical volume "ima5-Deadpool-home-snapshot" successfully removed Snapshot of ima5-Deadpool-var LVM... Logical volume "ima5-Deadpool-var-snapshot" created Mounting ima5-Deadpool-var-snapshot... Doing the backup of ima5-Deadpool-var-snapshot... tar: Suppression de « / » au début des noms des membres Unmounting ima5-Deadpool-var LVM... Cleaning snapshot of ima5-Deadpool-var LVM... Do you really want to remove active logical volume ima5-Deadpool-var-snapshot? [y/n]: Logical volume "ima5-Deadpool-var-snapshot" successfully removed Unmounting backup NFS... ALL DONE !
On récupère bien nos fichiers :
root@baleine:/backup/vm_backup# ls ima5-Deadpool-home-snapshot.tar ima5-Deadpool-var-snapshot.tar
Sauvegarde complète et automatisée des machines virtuelles
Maintenant, il faut enregistrer à la fois les états des machines virtuelles allumées avec leurs LVM, ainsi que les LVM des machines virtuelles éteintes.
Pour celà, nous avons modifié le script et ajouter un fichier de configuration comportant le nom de toutes les machines virtuelles que l'on souhaite sauvegarder.
Le script reste largement simplifiable, car il s'agit ici des deux précédents scripts plus ou moins arrangés.
Lors de la soutenance, nous avons modifié le script pour qu'il sauvegarde aussi le disque image des machines virtuelles, ainsi, une sauvegarde totale de la machine virtuelle est effectuée, et non pas seulement l'état mémoire et les LVM.
De plus la machine virtuelle est mise en pause durant sa sauvegarde.
#!/bin/bash# #Script effectuant le backup de toutes les VM DATE=`date +%d%b%Y-%H%M%S` MOUNTPOINT=/mnt/vm_backup LVM_MOUNT_PATH=/mnt/lvm_snap LVM_PATH=/dev/virtual/ LIST_VM_FILE=/tmp/vm_list.txt LIST_VM_CLOSED=/tmp/vm_closed_list.txt LIST_LVM_FILE=/tmp/lvm_list.txt NFS_SERVER_IP="172.26.64.15" BACKUPPATH=${MOUNTPOINT}/${DATE} CONFIGPATH=${MOUNTPOINT}/vm_backup.cfg ### Create mount point echo "Creating mount point..."; mkdir -p ${MOUNTPOINT} echo "Creating directory for LVM mount point..."; mkdir -p ${LVM_MOUNT_PATH} ### Mounting remote nfs share backup drive echo "Mounting backup nfs..."; mount -t nfs ${NFS_SERVER_IP}:/backup/vm_backup ${MOUNTPOINT} echo "Creating dated backup folder..."; mkdir -p ${BACKUPPATH} ### get all running vm xl vm-list | tail -n +2 | cut -d" " -f7 > ${LIST_VM_FILE} while read VMUUID do mkdir -p ${BACKUPPATH}/${VMUUID}/ echo "Saving ${VMUUID} state..."; xl save -p $VMUUID ${BACKUPPATH}/${VMUUID}/${VMUUID}.vmbackup echo "Creating disk.img snapshot..."; qemu-img create -f qcow2 -b /usr/local/xen/domains/${VMUUID}/disk.img /usr/local/xen/domains/${VMUUID}/disk-snapshot.img modprobe nbd max_part=63 qemu-nbd -c /dev/nbd0 /usr/local/xen/domains/${VMUUID}/disk-snapshot.img echo "Mounting ${LVM_NAME} disk.img..."; mount /dev/nbd0 ${LVM_MOUNT_PATH} echo "Doing the backup of disk..."; tar -cf ${BACKUPPATH}/${VMUUID}/disk.img-snapshot.tar ${LVM_MOUNT_PATH} echo "Unmounting ..." umount ${LVM_MOUNT_PATH} echo "Cleaning snapshot..." rm /usr/local/xen/domains/${VMUUID}/disk-snapshot.img echo "Cheking for ${VMUUID} LVM..."; ls ${LVM_PATH} | grep -i ${VMUUID} | grep -i 'var\|home' > ${LIST_LVM_FILE} while read LVM_NAME do echo "Snapshot of ${LVM_NAME} LVM..."; lvcreate -l 10%ORIGIN -s -n ${LVM_NAME}-snapshot ${LVM_PATH}${LVM_NAME} echo "Mounting ${LVM_NAME}-snapshot..."; mount ${LVM_PATH}${LVM_NAME}-snapshot ${LVM_MOUNT_PATH} echo "Doing the backup of ${LVM_NAME}-snapshot..."; tar -cf ${BACKUPPATH}/${VMUUID}/${LVM_NAME}-snapshot.tar ${LVM_MOUNT_PATH} echo "Unmounting ${LVM_NAME} LVM..."; umount ${LVM_MOUNT_PATH} echo "Cleaning snapshot of ${LVM_NAME} LVM..."; yes | lvremove ${LVM_PATH}${LVM_NAME}-snapshot done < ${LIST_LVM_FILE} xl unpause ${VMUUID} done < ${LIST_VM_FILE} ### get all closed vm awk 'NR==FNR {t[$0]++; next} !t[$0]' ${LIST_VM_FILE} ${CONFIGPATH} > ${LIST_VM_CLOSED} while read VMUUID do mkdir -p ${BACKUPPATH}/${VMUUID}/ echo "Creating disk.img snapshot..."; qemu-img create -f qcow2 -b /usr/local/xen/domains/${VMUUID}/disk.img /usr/local/xen/domains/${VMUUID}/disk-snapshot.img modprobe nbd max_part=63 qemu-nbd -c /dev/nbd0 /usr/local/xen/domains/${VMUUID}/disk-snapshot.img echo "Mounting ${LVM_NAME} disk.img..."; mount /dev/nbd0 ${LVM_MOUNT_PATH} echo "Doing the backup of disk..."; tar -cf ${BACKUPPATH}/${VMUUID}/disk.img-snapshot.tar ${LVM_MOUNT_PATH} echo "Unmounting ..." umount ${LVM_MOUNT_PATH} echo "Cleaning snapshot..." rm /usr/local/xen/domains/${VMUUID}/disk-snapshot.img echo "Cheking for ${VMUUID} LVM..."; ls ${LVM_PATH} | grep -i ${VMUUID} | grep -i 'var\|home' > ${LIST_LVM_FILE} while read LVM_NAME do echo "Snapshot of ${LVM_NAME} LVM..."; lvcreate -l 10%ORIGIN -s -n ${LVM_NAME}-snapshot ${LVM_PATH}${LVM_NAME} echo "Mounting ${LVM_NAME}-snapshot..."; mount ${LVM_PATH}${LVM_NAME}-snapshot ${LVM_MOUNT_PATH} echo "Doing the backup of ${LVM_NAME}-snapshot..."; tar -cf ${BACKUPPATH}/${VMUUID}/${LVM_NAME}-snapshot.tar ${LVM_MOUNT_PATH} echo "Unmounting ${LVM_NAME} LVM..."; umount ${LVM_MOUNT_PATH} echo "Cleaning snapshot of ${LVM_NAME} LVM..."; yes | lvremove ${LVM_PATH}${LVM_NAME}-snapshot done < ${LIST_LVM_FILE} done < ${LIST_VM_CLOSED} ###Cleaning lvm mount path rm ${LVM_MOUNT_PATH} -r ### Umounting remote nfs share backup drive echo "Umounting backup nfs..."; umount ${MOUNTPOINT} rm ${MOUNTPOINT} -r echo "ALL DONE !";
Une fois avoir exécuté celui-ci sur Cordouan, on peut observer le résultat obtenu sur notre DAS :
tree /backup/vm_backup/05janv.2017-205758/
/backup/vm_backup/06janv.2017-175650/ ├── Batman │ ├── Batman.vmbackup │ ├── disk.img-snapshot.tar │ ├── ima5-Batman-home-snapshot.tar │ └── ima5-Batman-var-snapshot.tar ├── Deadpool │ ├── Deadpool.vmbackup │ ├── disk.img-snapshot.tar │ ├── ima5-Deadpool-home-snapshot-snapshot.tar │ ├── ima5-Deadpool-home-snapshot.tar │ ├── ima5-Deadpool-var-snapshot-snapshot.tar │ └── ima5-Deadpool-var-snapshot.tar ├── Flash │ ├── disk.img-snapshot.tar │ └── Flash.vmbackup ├── Frotteman │ ├── disk.img-snapshot.tar │ ├── Frotteman.vmbackup │ ├── ima5-Frotteman-home-snapshot.tar │ └── ima5-Frotteman-var-snapshot.tar ├── GreenArrow │ ├── disk.img-snapshot.tar │ ├── GreenArrow.vmbackup │ ├── ima5-GreenArrow-home-snapshot.tar │ └── ima5-GreenArrow-var-snapshot.tar ├── Ironman │ ├── disk.img-snapshot.tar │ └── Ironman.vmbackup ├── Mulan │ ├── disk.img-snapshot.tar │ ├── ima5-Mulan-home-snapshot.tar │ ├── ima5-Mulan-var-snapshot.tar │ └── Mulan.vmbackup ├── Spiderman │ └── Spiderman.vmbackup └── Wolverine ├── disk.img-snapshot.tar ├── wolverine-home-snapshot.tar ├── wolverine-var-snapshot.tar └── Wolverine.vmbackup
Pour automatiser notre tâche, nous avons configuré Cron.
Cet utilitaire permet d’exécuter une commande automatiquement à n'importe quel moment : toutes les 2 heures, tous les jeudis à 15h48...
Nous avons donc configuré Cron pour exécuter une sauvegarde toutes les 6 heures :
crontab -e
# m h dom mon dow command 0 */6 * * * sh /backup/script_backup/vm_backup_script_remote.sh
Le script de sauvegarde automatique pourrait être modifié de manière à ne garder que les 10 dernière sauvegardes sur notre DAS pour ne pas le surcharger ou ne pas supprimer manuellement toutes les semaines les sauvegardes trop vielles.
Restauration d'une machine virtuelle
Nous avons créé un script capable de restaurer une machine virtuelle depuis un dossier de sauvegarde voulu :
#!/bin/bash# #UTILISATION : ./restore_state_vm.sh Deadpool 05janv.2017-205758 #UTILISATION : ./restore_state_vm.sh VM_NAME FOLDER_NAME VM_NAME=$1 DATE_FOLDER=$2 MOUNTPOINT=/mnt/vm_backup NFS_SERVER_IP="172.26.64.15" ### Create mount point echo "Creating mount point..."; mkdir -p ${MOUNTPOINT} ### Mounting remote nfs share backup drive echo "Mounting backup nfs..."; mount -t nfs ${NFS_SERVER_IP}:/backup/vm_backup ${MOUNTPOINT} ### restoring vm echo "Restoring ${VM_NAME} ..."; xl destroy ${VM_NAME} xl restore ${MOUNTPOINT}/${DATE_FOLDER}/${VM_NAME}/${VM_NAME}.vmbackup echo "${VM_NAME} RESTORED !"; ### Umounting remote nfs share backup drive echo "Umounting backup nfs..."; umount ${MOUNTPOINT} #BUSY ERROR #rm ${MOUNTPOINT} -r echo "ALL DONE !";
Le script fonctionne, mais le disque en réseau devient occupé et il est impossible de le démonter de Cordouan.
Il est nécessaire d'éteindre la machine virtuelle, puis de la redémarrer pour pouvoir démonter le disque réseau correctement.
Ici, la restauration des LVM n'est pas effectuée.
Amélioration du site
On installe de quoi exécuter du PHP sur notre site web :
apt-get install php5-common libapache2-mod-php5 php5-cli
On a revu un peu l'index de notre page :
<html> <link rel="icon" type="image/png" href="images/Deadpool_ico.png" /> <meta charset="utf-8"> <!--[if IE]><link rel="shortcut icon" type="image/x-icon" href="images/Deadpool_ico.png" /><![endif]--> <head> <title>PISCINEMORTE.NET</title> </head> <body bgcolor=#CEECF5> <center> <img src="images/Deadpool.png" height="25%" width="25%"> <h1><FONT color="#0B0B61">Bienvenue sur PISCINEMORTE.NET !</FONT></h1> <p><FONT color="#0B0B61">Ce site internet est dédié à notre projet de système et réseaux à l'école Polytech Lille.</FONT></p> <p><FONT color="#0B0B61">Par Geoffrey PIEKACZ et Nathan RICHEZ</FONT></p> <p><FONT color="#0B0B61">Lien vers <a href="http://projets-ima.plil.net/mediawiki/index.php?title=Cahier_2016_groupe_n%C2%B03">notre Wiki</a></FONT></p> </center> </body> </html>
Nous devons maintenant trouver le moyen d'afficher les machines virtuelles démarrées sur notre site.
Pour cela, nous nous sommes inspirés de la commande ci-dessous :
ssh [user]@[server] 'bash -s' < [local_script]
Cette commande va nous permettre de lancer un script de Deadpool vers Cordouan.
Le script est le suivant (/var/www/www.piscinemorte.net/show_vm_list.sh):
#!/bin/bash ssh root@cordouan.insecserv.deule.net 'xl vm-list'
Il affichera une liste des VM démarrées via un code PHP ajouté dans notre index :
<?php echo "Liste des machines virtuelles en cours de fonctionnement :"; $output = shell_exec('sh /var/www/www.piscinemorte.net/show_vm_list.sh'); echo "$output"; ?>
Ensuite, nous avons rencontré un problème.
En effet, cette commande fonctionne dans un bash mais le résultat n'est pas directement affiché sur notre site.
Cela s'explique par le fait que nous avons exécuté cette commande en root mais que apache via php execute cette commande dans un shell via l'utilisateur www-data.
Nous avions précédemment créé une clé pour pouvoir exécuter notre commande en root sans remettre à chaque fois le mot de passe.
Nous avons donc réitéré la démarche pour l'utilisateur www-data:
root@Deadpool:/home/Deadpool-key# ssh-keygen -t rsa //on génère une clé sans mot de passe dans ~/.ssh sauvegardée dans /root/.ssh/id_rsa
On copiera cette clé sur Cordouan et sur Baleine (notre DAS) pour permettre à nos machines de se connecter en ssh sans demande de mot de passe :
root@Deadpool:~# cp /root/.ssh/id_rsa /var/www/.ssh/ //pour copier notre clé pour l'utilisateur www-data root@Deadpool:~# chown www-data:www-data /var/www/.ssh/ -R // pour donner les droits de manière récursive à www-data root@Deadpool:~# sudo -u www-data -s //Pour changer l'utilisateur à www-data
Ainsi, notre commande est bien exécutée depuis notre site et affiche toutes les VM fonctionnant à l'instant t.
Tâches communes
Gestion de la machine virtuelle
Installation de la machine virtuelle avec Xen
Pour créé la machine virtuelle, on utilise xen-create-image avec les paramètres souhaités :
xen-create-image --hostname=Deadpool --ip=193.48.57.163 --netmask=255.255.255.240 --gateway=193.48.57.171 --dir=/usr/local/xen --mirror=http://debian.polytech-lille.fr/debian/ --dist=jessie --password=********
Puis, on récupère les informations suivantes afin de vérifier diverses paramètres :
General Information -------------------- Hostname : Deadpool Distribution : jessie Mirror : http://debian.polytech-lille.fr/debian/ Partitions : swap 128M (swap) / 4G (ext3) Image type : sparse Memory size : 128M Kernel path : /boot/vmlinuz-3.14-2-amd64 Initrd path : /boot/initrd.img-3.14-2-amd64 Networking Information ---------------------- IP Address 1 : 193.48.57.163 [MAC: 00:16:3E:FF:6F:DC] Netmask : 255.255.255.240 Gateway : 193.48.57.171 Creating partition image: /usr/local/xen/domains/Deadpool/swap.img Done Creating swap on /usr/local/xen/domains/Deadpool/swap.img Done Creating partition image: /usr/local/xen/domains/Deadpool/disk.img Done Creating ext3 filesystem on /usr/local/xen/domains/Deadpool/disk.img (...) Logfile produced at: /var/log/xen-tools/Deadpool.log Installation Summary --------------------- Hostname : Deadpool Distribution : jessie MAC Address : 00:16:3E:FF:6F:DC IP Address(es) : 193.48.57.163 RSA Fingerprint : d0:38:7b:89:c7:72:e7:52:d9:b7:5c:5b:ab:3e:fe:3f Root Password : hZsEGmZX
Configuration de la machine virtuelle
On utilise lvcreate pour faire en sorte que les répertoires var et home de la machine virtuelle soient sur des partitions LVM de l'hôte :
lvcreate -L 10G -n /dev/virtual/ima5-Deadpool-home -v lvcreate -L 10G -n /dev/virtual/ima5-Deadpool-var -v
Commande pour démarrer la machine virtuelle :
xl create /etc/xen/Deadpool.cfg
Commande pour se connecter à la machine virtuelle par console :
xl console Deadpool
Commande pour éteindre la machine virtuelle :
xl shutdown Deadpool
Commande pour détruire la machine virtuelle :
xl destroy Deadpool
On transforme nos disques logiques en partition ext4 :
mkfs.ext4 /dev/xvdb mkfs.ext4 /dev/xvdc
On sauvegarde les fichiers déjà existants dans home et var et on les met dans nos nouvelles partitions :
mkdir /mnt/home/ mkdir /mnt/var/ mount /dev/xvdc/ /mnt/home/ mount /dev/xvdb/ /mnt/var/ cp -r /home/* /mnt/home/ cp -r /var/* /mnt/var/
Afin de monter automatiquement notre partition à chaque démarrage, il suffit d'ajouter les lignes suivantes dans fstab :
nano /etc/fstab
/dev/xvdc /home ext3 defaults 0 2 /dev/xvdb /var ext3 defaults 0 2
Après redémarrage de la machine virtuelle, on vérifie si nos disques sont montés automatiquement :
df -h
Filesystem Size Used Avail Use% Mounted on /dev/xvda2 3.9G 700M 3.0G 19% / udev 10M 0 10M 0% /dev tmpfs 99M 13M 87M 13% /run tmpfs 247M 0 247M 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 247M 0 247M 0% /sys/fs/cgroup /dev/xvdb 9.8G 262M 9.0G 3% /var /dev/xvdc 9.8G 23M 9.2G 1% /home
Tests d'intrusion
Cassage de clef WEP
Via airodump-ng, on liste les réseaux wi-fi protégés par WEP :
airodump-ng --encrypt wep wlx40a5ef01370a
wlx40a5ef01370a représente ici notre interface réseau (équivalant à wlan0 par exemple)
On obtient la liste des réseaux wi-fi suivante :
[ CH 5 ][ Elapsed: 2 mins ][ 2016-11-07 10:30 ][ WPA handshake: 04:DA:D2:CF:01:93 ] BSSID PWR Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID 44:AD:D9:5F:87:00 -50 73 0 0 11 54e. WEP WEP Wolverine 04:DA:D2:9C:50:51 -64 90 0 0 13 54e. WEP WEP cracotte02 04:DA:D2:9C:50:53 -67 58 0 0 13 54e. WEP WEP cracotte04 04:DA:D2:9C:50:59 -68 85 0 0 13 54e. WEP WEP cracotte10 04:DA:D2:9C:50:56 -74 88 1329 17 13 54e. WEP WEP cracotte07 04:DA:D2:9C:50:52 -75 87 2279 14 13 54e. WEP WEP cracotte03 04:DA:D2:9C:50:58 -75 87 1751 14 13 54e. WEP WEP cracotte09 04:DA:D2:9C:50:57 -75 86 1293 7 13 54e. WEP WEP cracotte08 04:DA:D2:9C:50:54 -76 88 1460 15 13 54e. WEP WEP cracotte05 04:DA:D2:9C:50:50 -76 80 1345 11 13 54e. WEP WEP cracotte01 04:DA:D2:9C:50:55 -76 83 1501 10 13 54e. WEP WEP cracotte06 00:3A:7D:12:DC:F2 -1 0 0 0 6 -1 <length: 0>
On lance le monitoring sur le réseau que l'on souhaite cracker :
airodump-ng --essid cracotte07 --channel 13 -w testcrack wlx40a5ef01370a
[ CH 13 ][ Elapsed: 1 min ][ 2016-11-07 10:46 ] BSSID PWR RXQ Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID 04:DA:D2:9C:50:56 -72 12 608 8283 91 13 54e. WEP WEP cracotte07
Nous pouvons ensuite lancer le crackage à l'aide de aircrack-ng :
aircrack-ng testcarck-03.cap
Aircrack-ng 1.2 beta3 [00:00:00] Tested 84483 keys (got 35490 IVs) KB depth byte(vote) 0 0/ 5 EE(46080) EF(44032) 53(43008) 7B(43008) FC(43008) 1 3/ 15 EE(41984) 8D(41728) DD(41472) 16(41216) 28(41216) 2 0/ 2 EE(47616) 29(45824) C9(43776) 27(43264) 42(43008) 3 0/ 10 EE(44800) A9(44288) 15(43264) C5(42496) 2C(42496) 4 0/ 1 EE(49920) 2A(45312) 9D(43520) DA(43008) FD(41216) 5 0/ 4 EE(45312) A1(43520) C6(42240) E8(42240) 76(41472) 6 0/ 1 EE(50944) 98(42496) BB(42496) 4C(41728) B3(41728) 7 0/ 1 EE(54272) D3(42752) 19(42240) 08(41984) 58(41984) 8 5/ 8 F4(41216) 39(40960) 5E(40960) D7(40960) 1E(40704) 9 1/ 2 E4(45312) 51(43264) A7(42752) 5F(41984) CA(41728) 10 0/ 1 44(51200) 12(43264) CD(41984) 9C(41216) E5(41216) 11 0/ 1 44(50176) B0(42240) D2(41728) DC(41728) 62(41472) 12 0/ 1 44(47872) 0B(44032) B4(42752) D9(42496) 43(41728) KEY FOUND! [ EE:EE:EE:EE:EE:EE:EE:EE:EE:E4:44:44:44 ] Decrypted correctly: 100%
La clé est décryptée en quelques secondes !
Cassage de clef WPA-PSK par force brute
De même que pour le cassage de clé WEP, nous allons utiliser les mêmes outils mais pour un craquage WPA.
airmon-ng start wlx40a5ef01370a //On lance le mode monitoring sur notre carte wifi airmon-ng mon0 //On liste ensuite toutes les interfaces wifi disponible crunch 8 8 0123456789 > dico.txt //On sait que la clé possède 8 chiffres, on créé donc un dictionnaire contenant toutes les possibilités de clé avec l'outil crunch airodump-ng --encrypt wpa wlx40a5ef01370a //Nous choisissons ensuite le réseau à attaquer en wpa
[ CH 3 ][ Elapsed: 8 s ][ 2016-11-07 11:30 ] BSSID PWR Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID 04:DA:D2:9D:82:A2 -75 2 0 0 4 54e. WPA2 CCMP PSK <length: 1> 00:19:07:C5:0F:A6 -62 7 0 0 1 54e. WPA2 CCMP MGT <length: 1> 00:19:07:C5:0F:A0 -63 6 4 0 1 54e. WPA2 CCMP MGT LILLE1 00:19:07:C5:0F:A5 -62 6 0 0 1 54e. WPA2 CCMP PSK <length: 1> 00:19:07:C5:0F:A3 -64 7 0 0 1 54e. WPA2 CCMP PSK PolytechGuests 00:19:07:C5:0F:A7 -62 6 0 0 1 54e. WPA2 CCMP MGT PolytechLilleStaff 00:19:07:C5:0F:A2 -63 7 0 0 1 54e. WPA2 CCMP PSK <length: 1> 00:19:07:C5:0F:A8 -62 6 4 0 1 54e. WPA2 CCMP MGT eduroam 00:19:07:C5:0F:A4 -63 8 2 0 1 54e. WPA2 CCMP MGT PolytechLille 00:19:07:C5:0F:A1 -64 8 6 1 1 54e. WPA2 CCMP MGT <length: 1> 04:DA:D2:9C:50:58 -70 6 0 0 13 54e. WPA2 CCMP PSK cracotte09 04:DA:D2:9C:50:50 -71 6 0 0 13 54e. WPA2 CCMP PSK cracotte01 04:DA:D2:9C:50:55 -71 6 0 0 13 54e. WPA2 CCMP PSK cracotte06 04:DA:D2:9C:50:53 -71 7 0 0 13 54e. WPA2 CCMP PSK cracotte04 04:DA:D2:9C:50:57 -71 7 0 0 13 54e. WPA2 CCMP PSK cracotte08 04:DA:D2:9C:50:51 -72 9 0 0 13 54e. WPA2 CCMP PSK cracotte02 04:DA:D2:9C:50:56 -72 9 0 0 13 54e. WPA2 CCMP PSK cracotte07 04:DA:D2:9C:50:52 -72 8 0 0 13 54e. WPA2 CCMP PSK cracotte03 04:DA:D2:9C:50:59 -71 8 0 0 13 54e. WPA2 CCMP PSK cracotte10
On observe ensuite (seulement) la cible choisie (cracotte03)
airodump-ng --essid cracotte03 -c 13 --bssid 04:DA:D2:9C:50:52 -w dump mon0
[ CH 13 ][ Elapsed: 4 mins ][ 2016-11-07 11:36 ][ WPA handshake: 04:DA:D2:9C:50:52 BSSID PWR RXQ Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID 04:DA:D2:9C:50:52 -74 9 2573 259 0 13 54e. WPA2 CCMP PSK cracotte03 BSSID STATION PWR Rate Lost Frames Probe 04:DA:D2:9C:50:52 00:0F:B5:92:23:6A -58 1e- 1e 0 185
On lance l'attaque avec le handshake récupéré :
#aireplay-ng --deauth=5 -a 04:DA:D2:9C:50:52
Et enfin, on lance le décodage grâce au fichier généré et notre dictionnaire:
aircrack-ng dump-03.cap -w dico.txt -l KEY
Malheureusement, le décodage étant très long avec un eePC, nous avons recommencé et relancé le décodage sur notre Zabeth préférée.
Après une heure d'acharnement, nous avons enfin une clé !
Opening dump-01.cap Read 5625 packets. # BSSID ESSID Encryption 1 04:DA:D2:9C:50:52 cracotte03 WPA (1 handshake) Choosing first network as target. Opening dump-01.cap Reading packets, please wait... Aircrack-ng 1.2 beta3 [00:59:31] 12399952 keys tested (3160.12 k/s) KEY FOUND! [ 12399903 ] Master Key : 33 2B 69 DD 95 0A 5A E0 01 22 7E FF 98 DA 99 87 40 7A CB CC 8A E5 32 9F FE 4E 5C 44 91 38 13 93 Transient Key : 27 04 CB E4 68 2F D2 F6 CE 7D DF 51 25 60 2E 34 D0 D1 87 B9 A9 A5 3E 6E A6 6A EC 1E 05 29 12 D8 26 E5 DA 78 E4 87 AE 71 7A 5F AC BB 44 41 4E 2F 9D 18 A4 2C BF 88 82 59 BB F8 50 15 82 45 77 35 EAPOL HMAC : B6 83 11 A0 AC E3 AC 73 9D 7F 15 0A F1 A6 68 62 |
Services Internet
Serveur SSH
Il suffit d'installer ssh sur notre machine virtuelle si ce n'est pas déjà fait :
apt-get install ssh
Ensuite, pour autoriser la connexion en root en ssh, on remplace un paramètre dans le fichier /etc/ssh/sshd_config :
#PermitRootLogin without-password PermitRootLogin yes
Et on redémarre le service :
service ssh restart
Une fois le DNS configuré ci-après, nous pouvons facilement accéder à notre machine virtuelle depuis n'importe où :
ssh root@www.piscinemorte.net
root@www.piscinemorte.net's password: The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Tue Dec 6 18:13:23 2016 root@Deadpool:~#
Serveur DNS
Nous avons d'abord réservé sur Gandi notre nom de domaine : piscinemorte.net
Ensuite, nous avons installé les paquets bind et apache sur notre machine virtuelle (le dossier /var/www/www.piscinemorte.net servira pour la page web) :
apt-get update apt-get install apache2 bind9 mkdir /var/www/www.piscinemorte.net
Une fois bind installé, on créer un fichier de zone db.piscinemorte.net (appellé également une "table de DNS") :
; ; BIND data file for local loopback interface ; $TTL 604800 @ IN SOA ns.piscinemorte.net. root.piscinemorte.net ( 2 ; Serial 604800 ; Refresh 86400 ; Retry 2419200 ; Expire 604800 ) ; Negative Cache TTL ; IN NS ns.piscinemorte.net. ns IN A 193.48.57.163 www IN A 193.48.57.163
Notre DNS (ns) a pour adresse 193.48.57.163, c'est à dire l'IP de notre machine virtuelle.
Enfin, nous configurons le fichier named.conf.local pour autoriser le transfert de paquets vers le DNS Esclave (l'adresse de Gandi dans notre cas) :
zone "piscinemorte.net" { type master; file "/etc/bind/db.piscinemorte.net"; allow-transfer {217.70.177.40;}; };
Pour finir, on redémarre notre service bind :
service bind9 restart
Sur le site Gandi, depuis la gestion des domaines, nous avons besoin de gérer les 'glue records' et signaler nos serveurs DNS :
(Pour les 'glues records') 'Nom du serveur' : ns.piscinemorte.net 'IP' : 193.48.57.163
(Pour les DNS) 'DNS1' : ns.piscinemorte.net 'DNS2' : ns6.gandi.net
Sécurisation de site web par certificat
Pour avoir un certificat SSL généré Gandi, nous avons généré un CSR de la façon suivante :
openssl req -nodes -newkey rsa:2048 -sha1 -keyout piscinemorte.net.key -out piscinemorte.net.csr
Nous avons complété les différentes informations demandés (pas vraiment important ici) :
Country Name (2 letter code) [AU]:FR State or Province Name (full name) [Some-State]:Nord Locality Name (eg, city) []:Lille Organization Name (eg, company) [Internet Widgits Pty Ltd]:piscinemorte.net Organizational Unit Name (eg, section) []:piscinemorte.net Common Name (e.g. server FQDN or YOUR name) []:piscinemorte.net
Une fois notre certificat généré et validé par Gandi, nous plaçons nos fichiers de certification dans les dossiers adéquates :
cp piscinemorte.net.crt /etc/ssl/certs/piscinemorte.net.crt cp piscinemorte.net.key /etc/ssl/private/piscinemorte.net.key cp GandiStandardSSLCA2.pem /etc/ssl/certs/GandiStandardSSLCA2.pem
On notera que GandiStandardSSLCA2.pem est un certificat intermédiaire qui permet de certifier notre certificat.
Nous refaisons un hashage de la structure pour prendre en compte notre certificat :
c_rehash /etc/ssl/certs
Doing /etc/ssl/certs piscinemorte.net.crt => 651ac028.0 piscinemorte.net.crt => 179c2ae2.0 GandiStandardSSLCA2.pem => 8544bf03.0 GandiStandardSSLCA2.pem => e279a80b.0 ssl-cert-snakeoil.pem => ac2485cc.0 ssl-cert-snakeoil.pem => 1682ec15.0
On créé le fichier 000-piscinemorte.net-ssl.conf dans /etc/apache2/sites-available/ pour associer apache2 avec notre nom de serveur :
#NameVirtualHost *:443 <VirtualHost 193.48.57.163:443> ServerName www.piscinemorte.net ServerAlias piscinemorte.net DocumentRoot /var/www/www.piscinemorte.net/ CustomLog /var/log/apache2/secure_acces.log combined SSLEngine on SSLCertificateFile /etc/ssl/certs/piscinemorte.net.crt SSLCertificateKeyFile /etc/ssl/private/piscinemorte.net.key SSLCertificateChainFile /etc/ssl/certs/GandiStandardSSLCA2.pem SSLVerifyClient None </VirtualHost> <Directory /var/www/www.piscinemorte.net> Require all granted </Directory> ServerName "piscinemorte.net"
Nous avons modifié le fichier ports.conf du serveur Apache pour qu'il écoute le port 443 (SSL):
Listen 80 443 <IfModule ssl_module> Listen 443 </IfModule>
Il ne suffit plus qu'à activer le module SSL de Apache :
a2enmod ssl
Puis activer notre site avec notre certificat :
a2ensite 000-piscinemorte.net-ssl.conf service apache2 reload
Sécurisation de serveur DNS par DNSSEC
Tout d'abord, on ajoute une option dans /etc/bind/named.conf.options pour activer dnssec :
dnssec-enable yes;
On créé un répertoire spécial pour y générer les clés
mkdir piscinemorte.net.dnssec cd piscinemorte.net.dnssec
Puis on génère la clé de signature de clefs de zone (KSK) et la clé de la zone pour signer les enregistrements (ZSK)
dnssec-keygen -a RSASHA1 -b 2048 -f KSK -r /dev/urandom -n ZONE piscinemorte.net dnssec-keygen -a RSASHA1 -b 1024 -r /dev/urandom -n ZONE piscinemorte.net
L'option "-r /dev/urandom" sert à accélérer la génération des clés
Après avoir renommé les clés générées, on les inclue dans notre fichier de zone /etc/bind/db.piscinemorte.net
$include /etc/bind/piscinemorte.net.dnssec/piscinemorte.net-ksk.key $include /etc/bind/piscinemorte.net.dnssec/piscinemorte.net-zsk.key
On signe les enregistrements de la zone :
dnssec-signzone -o piscinemorte.net -k piscinemorte.net-ksk ../db.piscinemorte.net piscinemorte.net-zsk
Verifying the zone using the following algorithms: RSASHA1. Zone fully signed: Algorithm: RSASHA1: KSKs: 1 active, 0 stand-by, 0 revoked ZSKs: 1 active, 0 stand-by, 0 revoked ../db.piscinemorte.net.signed
Pour finir, il ne reste plus qu'à communiquer la partie publique de la KSK (et ZSK) à notre registrar (sur gandi.net via "Gérer DNSSEC") et vérifier la sécurisation :
Sécurisation et cryptage de données
Sécurisation de données via RAID5
On créer 3 disques virtuels avec lvcreate :
lvcreate -L 1G -n /dev/virtual/Deadpool-raid1 lvcreate -L 1G -n /dev/virtual/Deadpool-raid2 lvcreate -L 1G -n /dev/virtual/Deadpool-raid3
On les rajoute à notre configuration de machine virtuelle (/etc/xen/Deadpool.cfg) :
'phy:/dev/virtual/Deadpool-raid1,xvdd1, w', 'phy:/dev/virtual/Deadpool-raid2,xvdd2, w', 'phy:/dev/virtual/Deadpool-raid3,xvdd3, w',
Ensuite, nous avons besoin d'installer mdadm et mettre à jour le kernel sinon nous aurons une erreur de mdadm lors de la création du RAID5 :
apt-get install mdadm linux-image.3.16.0-4-amd64
Il ne nous reste plus qu'à créer notre disque RAID5 md0 :
mdadm --create /dev/md0 --level=5 --assume-clean --raid-devices=3 /dev/xvdd1 /dev/xvdd2 /dev/xvdd3
On installe un système de fichier ext4 dessus:
mkfs -t ext4 /dev/md0
On sauvegarde notre configuration :
mdadm --detail --scan >> /etc/mdadm/mdadm.conf
On le monte :
mount /dev/md0 /mnt
Après avoir créer un fichier dans notre RAID5, nous supprimons une des répartitions pour voir si le RAID5 se reconstruit correctement :
mdadm --set-faulty /dev/md0 /dev/xvdd2 mdadm --remove /dev/md0 /dev/xvdd2
On voit que la partition a bien été supprimée et nos données toujours présents :
cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4] md0 : active raid5 xvdd1[0] xvdd3[2] 2095104 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [U_U]
mount /dev/md0 /mnt
[88763.077524] EXT4-fs (md0): recovery complete [88763.077545] EXT4-fs (md0): mounted filesystem with ordered data mode. Opts: (null) <pre> root@Deadpool:/mnt# ls lost+found test.txt
Nous remettons la partition :
mdadm --add /dev/md0 /dev/xvdd2
Et on observe la reconstruction grâce à cat /proc/mdstat :
Personalities : [raid6] [raid5] [raid4] md0 : active raid5 xvdd2[3] xvdd1[0] xvdd3[2] 2095104 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [U_U] [==========>..........] recovery = 51.9% (544664/1047552) finish=0.2min speed=30259K/sec
Cryptage de données
Dans cette partie, nous allons voir comment crypter des données sur une carte SD.
On cherche notre carte sd dans dev :
ls /dev
puis on va configurer notre carte :
fdisk /dev/mmcblk1 "d pour supprimer les partitions 1-2-3" "n pour ajouter des partitions" "w pour enregistrer"
On créé donc une unique partition de taille 15G sur mmcblk1p1.
On va maintenant configurer la carte SD en type Luks avec un chiffrement aes et un algorithme de hachage SHA256:
cryptsetup luksFormat -c eas -h sha256 /dev/mmcblk1
Avec la phrase secrète : pasglop
On peut vérifier les infos de la partitions avec :
cryptsetup luksDump /dev/mmcblk1
On ouvre notre partition cryptée avec :
cryptsetup luksOpen /dev/mmcblk1
en saisissant la phrase secrète.
et on ajoute des fichiers :
mkfs.ext3 /dev/mapper/kadoc
On décide de créer un dossier contenant un fichier txt contenant une phrase. Pour écrire dedans il faut monter notre carte :
mount -t ext3 /dev/mapper/kadoc /mnt/ pour monter la partition. umount /mnt/ pour démonter la partition.
Il faut re-encrypter notre partition avec
cryptsetup luksClose kadoc
On peut vérifier avec GParted que notre partition n'est plus accessible, à moins d'avoir le mot de passe pour la décrypter.
gparted /dev/mmcblk1
Création de deux points d'accès Wi-Fi avec serveur d'authentification FreeRADIUS
Création du serveur FreeRADIUS
Tout d'abord, nous mettons en place un serveur d'identification FreeRADIUS en PEAP-MSCHAPv2 qui va tourner sur notre machine virtuelle.
Pour cela, il faut installer FreeRADIUS :
apt-get install freeradius
Puis, on ajoute un utilisateur dans le fichier /etc/freeradius/users pour s'authentifier sur le réseau WiFi :
nom_de_l_utilisateur Cleartext-password := "mot_de_passe"
On rajoute aussi les clients (correspondants aux deux points d'accès Wifi et à notre futur VLAN) dans le fichier /etc/freeradius/clients.conf :
client E304 { ipaddr = 10.60.1.6 secret = mot_de_passe } client E306 { ipaddr = 10.60.1.2 secret = mot_de_passe } client VLAN3 { ipaddr = 10.60.4.0 secret = mot_de_passe }
Pour utiliser le PEAP-MSCHAPv2, on modifie dans le fichier /etc/freeradius/eap.conf les valeurs suivantes :
eap { default_eap_type = peap peap { default_eap_type = mschapv2 } }
On fini par redémarrer FreeRADIUS pour bien prendre en compte les nouveaux paramètres :
service freeradius restart
Configuration des bornes Wi-Fi
Une fois les points d'accès Wifi disponibles, nous pouvons les configurer afin de créer notre propre SSID protégé par la méthode WPA2-EAP avec notre serveur d'authentification FreeRadius.
On commence par se connecter à l'une des deux bornes Wifi via Telnet :
telnet 10.60.1.2
Nous configurons le point d'accès (login : Cisco / password : Cisco) de la manière suivante pour créer notre VLAN et notre SSID :
enable conf t aaa new-model aaa authentication login eap_deadpool group radius_deadpool radius-server host 193.48.57.163 auth-port 1812 acct-port 1813 key mot_de_passe aaa group server radius radius_deadpool server 193.48.57.163 auth-port 1812 acct-port 1813 exit dot11 ssid Deadpool vlan 4 authentication open eap eap_deadpool authentication network-eap eap_deadpool authentication key-management wpa mbssid guest-mode exit interface Dot11Radio0 encryption vlan 4 mode ciphers aes-ccm tkip ssid Deadpool exit interface Dot11Radio0.4 encapsulation dot1Q 4 no ip route-cache bridge-group 4 bridge-group 4 subscriber-loop-control bridge-group 4 spanning-disabled bridge-group 4 block-unknown-source no bridge-group 4 source-learning no bridge-group 4 unicast-flooding exit interface GigabitEthernet0.4 encapsulation dot1Q 4 bridge-group 4 exit exit
Pour le deuxième point d'accès, il suffit de refaire la même chose.
Connexion à notre Wi-Fi
On se connecte à notre point d'accès grâce à nos identifiants créés précédemment dans la configuration de FreeRadius.
On configure l'accès sur un eeepc en modifiant le fichier /etc/network/interfaces :
auto wlan0 iface wlan0 inet static address 10.60.4.10 netmask 255.255.255.0 gateway 10.60.4.1 wpa-ssid Deadpool wpa-key-mgmt WPA-EAP wpa-identity nom_de_l_utilisateur wpa-password mot_de_passe
Enfin, on démarre l'interface pour se connecter sur notre point d'accès :
ifup wlan0 iwconfig
wlan0 IEEE 802.11bgn ESSID:"Deadpool" Mode:Managed Frequency:2.447 GHz Access Point: 44:AD:D9:5F:87:00 Bit Rate=1 Mb/s Tx-Power=20 dBm Retry short limit:7 RTS thr:off Fragment thr:off Encryption key:off Power Management:off Link Quality=59/70 Signal level=-51 dBm Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retries:1 Invalid misc:53 Missed beacon:0
On arrive à ping notre eePC depuis la machine virtuelle :
root@Deadpool:/# ping 10.60.4.10 PING 10.60.4.10 (10.60.4.10) 56(84) bytes of data. 64 bytes from 10.60.4.10: icmp_seq=1 ttl=62 time=1.22 ms 64 bytes from 10.60.4.10: icmp_seq=2 ttl=62 time=1.57 ms 64 bytes from 10.60.4.10: icmp_seq=3 ttl=62 time=8.32 ms 64 bytes from 10.60.4.10: icmp_seq=4 ttl=62 time=9.30 ms 64 bytes from 10.60.4.10: icmp_seq=5 ttl=62 time=1.55 ms 64 bytes from 10.60.4.10: icmp_seq=6 ttl=62 time=1.29 ms ^C --- 10.60.4.10 ping statistics --- 6 packets transmitted, 6 received, 0% packet loss, time 5007ms rtt min/avg/max/mdev = 1.226/3.879/9.304/3.501 ms
En ayant préalablement activé les logs des connexions dans la configuration de FreeRadius, on peut observer les authentifications dans /var/log/freeradius/radius.log :
Thu Dec 8 13:56:09 2016 : Info: Loaded virtual server <default> Thu Dec 8 13:56:09 2016 : Info: Loaded virtual server inner-tunnel Thu Dec 8 13:56:09 2016 : Info: Ready to process requests. Thu Dec 8 13:59:58 2016 : Auth: Login OK: [pifou/<via Auth-Type = EAP>] (from client E306 port 0 via TLS tunnel) Thu Dec 8 13:59:58 2016 : Auth: Login OK: [pifou/<via Auth-Type = EAP>] (from client E306 port 326 cli 40a5.ef05.a110)
DHCP et PCBX
Configuration du DHCP
On installe de quoi faire un serveur DHCP sur notre eePC :
apt-get install isc-dhcp-server
On configure notre serveur DHCP via le fichier de configuration (/etc/dhcp/dhcpd.conf)
option domain-name "piscinemorte.net"; option domain-name-servers ns.piscinemorte.net; subnet 10.60.4.0 netmask 255.255.255.0 { range 10.60.4.11 10.60.4.30 option routers 10.60.4.254 }
Après avoir redémarré notre serveur DHCP, on se connecte facilement à notre point d'accès grâce au DHCP qui nous attribue une adresse IP dans la plage voulue :
Configuration et utilisation du PCBX
On installe Asterisk pour créer un serveur permettant une communication SIP :
apt-get install asterisk
Configuration via /etc/asterisk/sip.conf :
[general] allowguest=no alwaysauthreject=yes contactacl=local_ip_acl hasvoicemail = yes hassip = yes hasiax = yes callwaiting = yes threewaycalling = yes callwaitingcallerid = yes tranfer = yes canpark = yes cancallforward = yes callreturn = yes callgroup = yes pickupgroup = yes nat = yes [6001] type=peer host=dynamic dtmfmode=rfc2833 disallow=all allow=ulaw fullname=dpl1 username=dpl1 secret=secret context=work acl=acl1 [6002] type=peer host=dynamic dtmfmode=rfc2833 disallow=all allow=ulaw fullname=dpl2 username=dpl2 secret=secret context=work acl=acl1
Configuration via /etc/asterisk/extensions.conf :
[work] exten => _6XXX,1,Dial(SIP/${EXTEN},20) exten => _6XXX,2,Hangup()
Configuration des autorisations via /etc/asterisk/acl.conf :
acl = acl1 [acl1] permit=0.0.0.0/0.0.0.0
On se connecte à un compte SIP (dpl1 et dpl2) et on passe un appel grâce à l'identifiant configuré précédemment :
Références
Pour la gestion du serveur DAS :