Recherche de site Web

Protection de l’intégrité des données sur Ext4 et XFS avec dm-integrity et LUKS


Contrairement aux systèmes de fichiers COW comme BTRFS et ZFS, les systèmes de fichiers Linux traditionnels comme ext4 et XFS n’ont aucun moyen de détecter la dégradation lente des données (également connue sous le nom de bitrot), car ils n’effectuent pas de somme de contrôle des données. Cependant, lorsque nous utilisons ces systèmes de fichiers, nous pouvons stocker et vérifier les informations d’intégrité au niveau du bloc, en utilisant dm-integrity. Dans ce tutoriel, nous apprenons à créer des périphériques dm-integrity à l’aide de l’utilitaire integritysetup et, lors de la création de conteneurs LUKS, à l’aide de cryptsetup.

Dans ce tutoriel, vous allez apprendre :

  • Comment créer des périphériques dm-integrity avec la configuration de l’intégrité sur un seul disque
  • Comment créer des périphériques dm-integrity sur des configurations de redondance de données (une matrice RAID1)
  • Comment implémenter les fonctionnalités dm-integrity lors de la création d’un conteneur LUKS

Simulation de bitrot sur des systèmes de fichiers Linux traditionnels

Comme nous l’avons déjà dit, les systèmes de fichiers Linux traditionnels comme ext4 et XFS n’ont aucun moyen de vérifier l’intégrité des données et ne sont pas capables de repérer les corruptions de données. Montrons-le. Comme première chose, nous créons un fichier avec dd, en allouant 512 Mo d’espace :

dd if=/dev/zero of=blkdevice bs=1M count=512

Avec la commande ci-dessus, nous avons demandé à dd de lire 512 blocs de 1 Mo chacun à partir du pseudo-périphérique /dev/zero, et de les écrire sur le fichier « blkdevice », dans le répertoire de travail actuel. Une fois que nous avons créé le fichier, nous pouvons l’utiliser comme périphérique de bloc et construire un système de fichiers dessus. Pour les besoins de cet exemple, nous utiliserons ext4 :

mkfs.ext4 blkdevice

Nous pouvons monter le système de fichiers comme si nous avions affaire à n’importe quel autre « vrai » périphérique de bloc :

sudo mount blkdevice /mnt

À ce stade, nous écrivons des données aléatoires dans un fichier, lui permettant de remplir tout l’espace disponible :

sudo dd if=/dev/urandom of=/mnt/testfile

Nous devrions obtenir un résultat similaire à celui ci-dessous :

dd: writing to '/mnt/testfile': No space left on device 
976521+0 records in 
976520+0 records out 
499978240 bytes (500 MB, 477 MiB) copied, 3.95061 s, 127 MB/s

Récupérons maintenant la somme de contrôle du fichier que nous venons de créer :

sha256sum /mnt/testfile

Dans ce cas, on obtient le résultat suivant :

22eba8b04d389cd8f89ce055794823baa85c196e7ef81cc2465fb2a50e0f4f1e  /mnt/testfile

Nous en prenons note et montons le système de fichiers :

sudo umount /mnt

Maintenant, pour simuler la corruption de données, ou bitrot, nous pouvons écrire des données aléatoires directement sur le périphérique de bloc. Dans l’exemple ci-dessous, nous spécifions que nous voulons écrire un seul bloc de sortie (count=1) de 1MiB (bs=1M), et nous voulons commencer à écrire après un décalage de 15 blocs de sortie de la même taille, à partir du début de l’appareil cible (seek=15). Nous faisons cela pour nous assurer que nous couvrons la zone du système de fichiers qui héberge le « testfile ». Enfin, nous utilisons conv=notrunc pour nous assurer que notre « périphérique de blocage » n’est pas tronqué :

dd if=/dev/urandom of=blkdevice seek=15 count=1 bs=1M conv=notrunc

À ce stade, nous montons à nouveau le système de fichiers et vérifions si la somme de contrôle de « testfile » a changé :

sudo mount blkdevice /mnt
sha256sum /mnt/testfile

Voici le résultat que nous obtenons :

fb91581b5ed08eae9f3f8400d27bed0b4ad5a8fb4742f2fbabcc0ed409792160  /mnt/testfile

Comme prévu, la somme de contrôle du fichier est maintenant différente. Le changement s’est produit silencieusement : les systèmes de fichiers traditionnels ne gardent pas de trace des sommes de contrôle des données, ils n’ont donc aucun moyen de remarquer le « bitrot ». C’est là que dm-integrity peut vous aider.

Utilisation de dm-integrity sur un seul disque

L’utilisation de dm-integrity sur un seul disque n’est pas très utile : alors que sur une configuration avec plusieurs copies de données, comme un RAID1, les données corrompues peuvent être automatiquement remplacées par une copie intacte, sur une configuration à un seul disque, c’est, bien sûr, impossible. Cependant, être capable de remarquer une corruption, cependant, peut toujours être utile, peut-être comme signe d’un éventuel disque défaillant.

Installation de l’utilitaire integritysetup

Pour utiliser dm-integrity, nous devons formater notre appareil à l’aide de l’utilitaire integritysetup. Pour l’installer sur Fedora et d’autres distributions de la famille Red Hat, nous pouvons exécuter :

sudo dnf install integritysetup

Sur OpenSuse (Leap/Tumbleweed), nous pouvons utiliser le « zypper » pour installer le paquet du même nom :

sudo zypper in integritysetup

Sur Debian et les distributions basées sur Debian, l’utilitaire est fourni par le paquet « cryptsetup-bin ». Nous pouvons l’installer en exécutant :

sudo apt install cryptsetup-bin

Sur Archlinux, l’utilitaire integritysetup est inclus dans le paquet « cryptsetup », disponible dans le dépôt « core » :

sudo pacman -S cryptsetup

Création d’un volume dm-integrity

Pour créer un volume dm-integrity, nous utilisons l’utilitaire « integritysetup » pour formater un périphérique de partition/bloc. En suivant nos exemples précédents, nous opérons sur le fichier « blkdevice » existant, en le traitant comme un périphérique de bloc. Pour le formater, nous utilisons la commande suivante :

sudo integritysetup format blkdevice

Il nous sera demandé de confirmer que nous voulons effectuer l’opération, car elle va écrire toutes les données sur l’appareil :

WARNING!
========
This will overwrite data on blkdevice irrevocably.

Are you sure? (Type 'yes' in capital letters): YES

Une fois que nous avons créé le volume dm-integrity, nous devons l’ouvrir et lui fournir un nom de mappeur de périphérique. Pour les besoins de ce tutoriel, nous utilisons « testdevice » :

sudo integritysetup open blkdevice testdevice

À ce stade, nous pouvons créer un nouveau système de fichiers sur le périphérique mappé (/dev/mapper/testdevice) :

sudo mkfs.ext4 /dev/mapper/testdevice

Montons encore une fois le système de fichiers, et créons le fichier « testfile », en le remplissant avec des données aléatoires :

sudo mount /dev/mapper/testdevice /mnt
sudo dd if=/dev/urandom of=/mnt/testfile

Comme précédemment, nous gardons une trace de la somme de contrôle du fichier :

sha256sum /mnt/testdevice
3b0d6256f991d4a352ed9181621813ba6b909b5cab0547a9554cac400074c3a5  /mnt/testdevice

Il est temps de démonter le système de fichiers, de fermer le périphérique integritysetup et de simuler la corruption des données, à nouveau :

sudo umount /mnt
sudo integritysetup close testdevice
dd if=/dev/urandom of=blkdevice seek=15 count=1 bs=1M conv=notrunc

À ce stade, nous pouvons remonter le système de fichiers et essayer d’obtenir la somme de contrôle du fichier :

sudo integritysetup open blkdevice testdevice
sudo mount /dev/mapper/testdevice /mnt
sha256sum /mnt/testfile

Dès que nous essayons de lire le fichier, nous obtenons une erreur :

sha256sum: /mnt/testdevice: Input/output error

Que s’est-il passé? Comme nous utilisons maintenant dm-integrity, la corruption des données a été repérée et le système de fichiers a renvoyé une erreur d’entrée/sortie. Nous pouvons trouver plus de détails sur l’incident en jetant un coup d’œil aux journaux du noyau :

sudo dmesg | tail -5

Nous devrions être en mesure de lire quelque chose de similaire à :

[32942.115228] device-mapper: integrity: dm-8: Checksum failed at sector 0x5782 
[32942.117906] device-mapper: integrity: dm-8: Checksum failed at sector 0x5758 
[32942.119440] device-mapper: integrity: dm-8: Checksum failed at sector 0x5758 
[32942.119532] device-mapper: integrity: dm-8: Checksum failed at sector 0x5758 
[32942.119614] device-mapper: integrity: dm-8: Checksum failed at sector 0x5758

Utilisation de dm-integrity avec la redondance des données

Comme nous l’avons déjà dit, sur une configuration à disque unique, nous n’avons aucun moyen de corriger les corruptions, puisque nous n’avons qu’une seule copie des données. Les choses changent lors de l’utilisation d’une configuration de redondance de données telle que RAID1. Simulons-le. Tout d’abord, nous créons deux fichiers : blkdevice1 et blkdevice2. Nous les utiliserons comme dispositifs de blocage :

dd if=/dev/zero of=blkdevice1 bs=1M count=512
dd if=/dev/zero of=blkdevice2 bs=1M count=512

Sur chacun d’eux, nous créons un volume dm-integrity. Ci-dessous, nous utilisons l’option -q (abréviation de --batch-mode) pour sauter l’invite de confirmation :

sudo integritysetup -q format blkdevice1
sudo integritysetup -q format blkdevice2

Ouvrons-les :

sudo integritysetup open blkdevice1 testdevice1
sudo integritysetup open blkdevice2 testdevice2

Nous pouvons maintenant assembler les appareils dans un RAID1 avec l’utilitaire mdadm :

sudo mdadm --create /dev/md0 --level 1 --raid-devices=2 /dev/mapper/testdevice1 /dev/mapper/testdevice2

Nous créons un nouveau tableau à l’aide de l’option --create et fournissons le chemin du périphérique : /dev/md0. Nous spécifions le niveau RAID à l’aide de l’option --level, le nombre de périphériques actifs à l’aide de --raid-devices et, enfin, nous transmettons le chemin des périphériques en mode bloc que nous voulons inclure dans la matrice. Une fois le RAID assemblé, nous pouvons créer un système de fichiers sur le périphérique résultant :

sudo mkfs.ext4 /dev/md0

Maintenant, montons le système de fichiers que nous venons de créer, écrivons un fichier rempli de données aléatoires et créons la corruption de données sur le premier des deux disques qui font partie de la matrice :

sudo mount /dev/md0 /mnt
sudo dd if=/dev/urandom of=/mnt/testfile
dd if=/dev/urandom of=blkdevice1 seek=15 count=1 bs=1M conv=notrunc

On peut maintenant effectuer un data-scrub : en écrivant « test » dans le fichier /sys/block/md0/md/sync_action, on fait en sorte que le RAID lise tous les blocs de données sur tous les périphériques :

 echo "check" | sudo tee /sys/block/md0/md/sync_action

Comme nous l’avons vu précédemment, les erreurs d’intégrité sont signalées dans les journaux du noyau. Voici la partie pertinente :

[36735.559800] md: check of RAID array md0 
[36735.579268] device-mapper: integrity: dm-8: Checksum failed at sector 0x5b00 
[36735.579465] device-mapper: integrity: dm-8: Checksum failed at sector 0x5b80 
[36735.579508] device-mapper: integrity: dm-8: Checksum failed at sector 0x5980 
[36735.579522] device-mapper: integrity: dm-8: Checksum failed at sector 0x5a00 
[36735.579533] device-mapper: integrity: dm-8: Checksum failed at sector 0x5c80 
[36735.579544] device-mapper: integrity: dm-8: Checksum failed at sector 0x5900 
[36735.579606] device-mapper: integrity: dm-8: Checksum failed at sector 0x5a80 
[36735.579617] device-mapper: integrity: dm-8: Checksum failed at sector 0x5c00 
[36735.581460] device-mapper: integrity: dm-8: Checksum failed at sector 0x5780 
[36735.582377] device-mapper: integrity: dm-8: Checksum failed at sector 0x5e80 
[36737.803123] md: md0: check done.

À ce stade, si nous exécutons à nouveau le nettoyage des données et vérifions les journaux du noyau, nous ne devrions remarquer aucun message d’erreur :

[37245.887325] md: check of RAID array md0 
[37248.101670] md: md0: check done.

Grâce à dm-integrity, la corruption des données a été repérée et réparée automatiquement.

Utilisation de dm-integrity avec LUKS

LUKS (Linux Unified Key Setup) est la norme de chiffrement de disque sous Linux. Lors du formatage d’un périphérique de bloc brut ou d’une partition en tant que conteneur LUKS, nous pouvons spécifier que nous voulons utiliser dm-integrity sans utiliser integritysetup. Tout ce que nous avons à faire, c’est d’appeler cryptsetup avec l’option --integrity, et de passer l’algorithme d’intégrité que nous voulons utiliser, comme argument :

sudo cryptsetup luksFormat --type luks2 --integrity hmac-sha256 blkdevice1

Conclusions

Dans ce tutoriel, nous avons appris à utiliser dm-integrity pour activer la sommation de contrôle et la vérification des données au niveau du bloc, lors de l’utilisation de systèmes de fichiers Linux traditionnels. Être capable de vérifier les données corrompues sur un support de stockage (bitrot) est vraiment important, et est particulièrement utile sur les configurations multidisques, où les corruptions de données repérées peuvent être automatiquement réparées. L’activation de dm-integrity, cependant, n’est pas bon marché : entre autres choses, elle provoque des amplifications d’écriture, puisque, par défaut, elle écrit les données de secteur et les balises d’intégrité dans un journal. Dans cet article, pour des raisons évidentes, nous n’avons pas mentionné toutes les options possibles qui peuvent être utilisées pour affiner l’intégrité de dm. Pour en savoir plus, consultez la page de manuel integritysetup et la documentation pertinente.

Articles connexes: