PC portable entièrement crypté avec boot sur clé USB

De plus en plus de distribution Linux proposent d'installer le système sur des partitions cryptées, c'est le cas de Debian et Fedora.

Dans ce genre d'installation, tout n'est pas crypté, il y a forcément une partition ”/boot” qui contient grub, le kernel et l'initrd, qui ne peuvent être cryptés. En effet le BIOS doit pouvoir lire grub pour le charger et grub doit pouvoir lire le kernel et l'initrd, à ce moment du boot, le système n'a pas les éléments nécessaires pour décrypter un espace disque et y lire ces programmes.

La solution pour avoir le disque dur totalement crypté est de mettre la partition /boot ailleurs, sur une clé USB par exemple. On va donc transférer une Debian sur un espace crypté en LVM et passer le kernel et grub sur une clé USB.

Les noms des devices sont à adapter selon le contexte.

Préparation

Il y a quelques prérequis pour cette opération :

  • Pour le backup: une autre machine, un disque dur USB,
  • Pour la configuration: un live CD ou SystemRescueCD sur un clé USB,
  • Pour le boot: une clé USB. Le BIOS du portable doit pouvoir booter sur une clé USB.

Ensuite, il faut installer tous les packages nécessaires:

# aptitude install lvm2 initramfs-tools cryptsetup hashalot mbr

Sauvegarde du système

Tout d'abord, il faut booter le portable sur SystemRescueCD ou un LiveCD qui possède de quoi faire un tar, scp, cryptsetup, du LVM.

Ensuite, on monte les partitions du système à sauvegarder. Cette techinque est à retenir, car on manipule les fichiers du système à froid, on est donc sûr que le système ne changera pas durant le backup:

Pour trouver quel est le disque dur du portable:

# fdisk -l
--> /dev/sda

On crée un répertoire pour monter la partition root du système à sauvegarder et on monte les partitions (à adapter à son /etc/fstab) :

# mkdir /a
# mount /dev/sda1 /a
# mount /dev/sda3 /a/home

Enfin, on sauvegarde ailleurs, sur une autre machine, par SSH, et on démonte les partitions :

# cd /a
# tar cpf - * | ssh orgrim@192.168.0.1 "cat | gzip > laptop.tar.gz"
# cd /
# umount /a/home
# umount /a

La commande crée le tar sur la sortie standard, renvoyée dans ssh, qui se connecte. On demande à SSH d'exécuter la commande entre guillemets au lieu de lancer un shell. Pour capter le flux du tar, on lance cat, qu'on redirige dans gzip puis dans un fichier.

On utilise tar pour ne pas altérer les fichiers, avec l'option “p” qui conserve les permissions et propriétaires des fichiers/répertoires.

Crypter le disque dur

Partionnement

On va partitionner le disque dur pour avoir une partition de SWAP (de 1Go, soit 2 fois la RAM, à adapter) et une partition pour un volume physique LVM2, voici pour référence les commandes à effectuer avec fdisk :

# fdisk /dev/sda
o, n, p, 1, <return>, +1024M, t, 1, 82
n, p, 2, <return>, <return>, t, 2, 8e

Destruction et initialisation des données du disques

Pour que ça serve à quelque chose, il ne faut pas laisser de trace des données qui sont actuellement sur le disque dur. Il existe des outils dit de “forensic” comme TCT, qui peuvent retrouver des données effacées.

Pour que l'encryption soit efficace sur le disque dur, il faut générer du bruit partout.on va donc prendre du bruit de /dev/urandom (parce /dev/random, c'est bien trop long) :

# dd if=/dev/urandom of=/dev/sda1
# dd if=/dev/urandom of=/dev/sda2

Cette opération est très longue, pour 80 Go ça m'a pris 12 heures environ.

Configuration du LVM crypté

La première chose à faire est de créer un partion LUKS (Linux Unified Key Setup). Ca permet de stocker les clés et la configuration du cryptage au début de la partition, comme ça n'importe quel système GNU/Linux est sensé pouvoir le lire. On fait ça avec cryptsetup, qui demande une passphrase à la création (luksFormat) et déverouille lors de l'ouverture de la partition (liksOpen).

# cryptsetup -y --cipher aes-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sda2
# cryptsetup luksOpen /dev/sda2 cryptpart

Le “luksOpen” a créé un mapping pour la partition cryptée, on n'utilise donc plus ”/dev/sda2” mais ”/dev/mapper/cryptpart”.

On crée ensuite notre configuration LVM2 :

  • Volume Physique :
# pvcreate /dev/mapper/cryptpart
  • Volume Group :
# vgcreate system /dev/mapper/cryptpart
  • Volumes Logiques :
# lvcreate -n root -L 10G system
# pvdisplay /dev/mapper/cryptpart | grep Free
  Free PE               16273
# lvcreate -n home -l 16273 system

Pour “lvcreate”, on utilise une taille fixe pour ”/” (”-L 10G”) et le reste pour ”/home”, en spécifiant le nombre exact de “Physical Extends” restants sur le volume physique.

Enfin, les systèmes de fichiers en ext3 :

# mke2fs -j /dev/mapper/system-root
# mke2fs -j -m 0 /dev/mapper/system-home

Restauration du système backupé

On procède maintenant à l'opération inverse :

# mount /dev/mapper/system-root /a
# mkdir /a/home
# mount /dev/mapper/system-home /a/home
# cd /a
# ssh orgrim@192.168.0.1 "zcat laptop.tar.gz" | tar xpf -

Tout est désormais en place sur un disque dur crypté.

Modification de la configuration du système

Il faut modifier quelques fichiers de configuration pour que le système puisse booter sur le LVM crypté:

  • /etc/crypttab, déclaration de la partition root crypté pour le device mapper :
# <target name> <source device>         <key file>      <options>
cryptpart       /dev/hda2       none    verify,cipher=aes,hash=sha256
  • /etc/fstab, passage vers LVM2 :
  # /etc/fstab: static file system information.
  #
  # <file system> <mount point>   <type>  <options>       <dump>  <pass>

  proc            /proc           proc    defaults        0       0
  /dev/mapper/system-root       /               ext3    defaults,errors=remount-ro 0       1
  /dev/sda1       /boot   ext2    defaults,noauto 0 2
  /dev/mapper/system-home       /home           ext3    defaults        0       2
  /dev/mapper/swap       none            swap    sw              0       0
  /dev/hdc        /media/cdrom0   udf,iso9660 user,noauto     0       0

/dev/sda1 sera le device de la clé USB sur le système définitif, l'option “noauto” permet de ne pas monter automatiquement cette partition, on évite ainsi une erreur si la clé utilise un autre device.

Créer la clé USB pour le boot

Prépartion de la clé

Il faut insérer la clé USB et trouver son device avec fdisk -l puis l'initialiser :

# fidsk /dev/sdd
o, n, p, 1, <return>, <return>, a, 1

On formatte en ext2 :

# mk2efs /dev/sdd1

Chroot sur le système restauré

Pour cette opération, on va se “chrooter” sur le système crypté :

# mount -o bind /dev /a/dev
# mount -t sysfs none /a/sys
# mount -t proc none /a/proc
# mkdir /a/usbkey
# mount /dev/sdd1 /a/usbkey
# chroot /a /bin/bash

On est maintenant sur notre Debian hébergée sur le disque dur du portable.

Mise à jour de l'initrd

Maintenant qu'on est chrooté, on a accès à “initramfs-tools”. On recrée donc un nouvel initrd, qui aura automagiquement tout ce qu'il faut pour gérer le disque crypté :

# update-initramfs -v -t -c -k 2.6.26-1-686
update-initramfs: Generating /boot/initrd.img-2.6.26-1-686
...
Calling hook cryptroot
...

On peut remplacer ”-k <version du noyau>” par ”-k all” qui recréera tout les initrd nécessaires. Il faut bien voir “update-initramfs” ajouter les outils nécessaires à la gestion du disque encrypté, sinon le système ne pourra pas booter.

Pour vérifier, on peut extraire le contenu de l'initrd, il doit y avoir un fichier conf/conf.d/cryptroot, qui reprend les informations de /etc/crypttab :

# cd /tmp
# mkdir test
# cd test
# zcat /boot/initrd.img-2.6.26-1-686 | cpio -i
# cat conf/conf.d/cryptroot
target=cryptpart,source=/dev/hda2,key=none,lvm=system-root,cipher=aes,hash=sha256
# cd /
# rm -rf /tmp/test

Grub sur la clé USB

Il faut mettre à jour le fichier de configuration de Grub (/boot/grub/menu.lst). On va mettre à jour la configuration utilisée par debconf pour la mise à jour de du fichier lors d'une installation de noyau, ça servira pour l'installation de futur noyau :

# kopt=root=/dev/mapper/system-root ro
# groot=(hd0,0)

Avec le “root” pour les 2 entrées de boot, on met le premier device car le BIOS oriente le nommage des devices selon l'ordre de boot (donc hd0 sera la clé) :

title           Debian GNU/Linux, kernel 2.6.26-1-686
root            (hd0,0)
kernel          /vmlinuz-2.6.26-1-686 root=/dev/mapper/system-root ro
initrd          /initrd.img-2.6.26-1-686

Ensuite, on doit copier le contenu du répertoire /boot sur la clé, c'est à dire l'installation existante de Grub, le kernel et l'initrd :

# cp -R /boot/* /usbkey

Puis on passe sur la clé :

# umount /usbkey
# mount /dev/sdd1 /boot

Et on mets à jour l'installation de Grub :

# grub-install --recheck --no-floppy /dev/sdd
...
(hd2) /dev/sdd
...

grub-install donne le mapping des disques entre le noyau et son nommage, dans notre exemple, il faudra utiliser (hd2) pour l'installation de Grub

Enfin, on peut installer Grub sur le MBR de la clé :

# grub
grub> root (hd2,0)
 Filesystem type is ext2fs, partition type 0x83
grub> setup (hd2)
Checking if "/boot/grub/stage1" exists... no
 Checking if "/grub/stage1" exists... yes
 Checking if "/grub/stage2" exists... yes
 Checking if "/grub/e2fs_stage1_5" exists... yes
 Running "embed /grub/e2fs_stage1_5 (hd2)"...  17 sectors are embedded.
succeeded
 Running "install /grub/stage1 (hd2) (hd2)1+17 p (hd2,0)/grub/stage2 /grub/menu.lst"... succeeded
Done.

grub> quit

Réinitialiser le MBR du disque

Pour faire les chose proprement, il est sympa de supprimer le Grub déjà installé dans le MBR du disque, ainsi la machine apparaitra vierge pour le profane si la clé USB de boot n'est pas en place :

# install-mbr /dev/sda

Sortie du chroot

Pour sortir du chroot :

# sync
# umount /boot
# exit
# umount /a/dev /a/sys /a/proc /a

Voilà, il reste maintenant à booter le système sur la clé…

Démarrage sur la clé USB

On reboote et on essaye de booter sur la clé. Le menu de Grub doit apparaitre, quand on choisit une entrée, le kernel doit être lancé. Les problèmes ici peuvent venir d'une mauvaise configuration utilisant les mauvais de devices, il faut donc bien connaitre son matériel pour bien interpréter la sortie de fdisk -l.

Lors du boot, l'initrd doit demander la passphrase pour décrypter le volume physique.

Une fois la machine booté, on peut débrancher sans risques la clé USB du portable.

Configurer la swap

Une fois qu'on are booté sur le système crypté avec la clé, il reste à faire la swap.

On crée une clé pour la swap qui sera stockée dans le fichier /etc/keys/swapkey, voici une commande pour créer une clé aléatoire :

# dd if=/dev/random bs=5k count=1 2> /dev/null | hashalot -s 'Une bonne phrase de sel bien compliquée' -x sha256 > /etc/keys/swapkey
# chmod 600 /etc/keys/swapkey

Puis on crypte la partition dédiée à la swap :

# cryptsetup create swap /dev/hda1 -d /etc/keys/swapkey -c aes-cbc-essiv:sha256 -h sha256

On ajoute une entrée dans /etc/crypttab :

# cat /etc/crypttab
swap /dev/hda1 /etc/keys/swapkey cipher=aes,hash=sha256

Puis on crée effectivement la swap :

# mkswap /dev/mapper/swap

Enfin, on l'active :

# swapon /dev/mapper/swap

Backup de la clé USB

Il est conseillé de faire un backup de la clé USB sur une autre machine, au cas où on la perd… Un petit tar c'est vite fait.

En cas de problème

  • Si on oublie la passphrase, c'est MORT. On peut donc recommencer à l'étape du “luksFormat”.
  • Si on veut reprendre sur SystemRescueCD, pour monter la racine :
# cryptsetup luksOpen /dev/sda2 cryptpart
# vgscan
# vgchange -ay
# mkdir /a
# mount /dev/mapper/system-root /a