Se passer de clé de déchiffrement au démarrage

Page mise à jour le 30 avril 2024

Mise à jour : 14 décembre 2017

Cet article fait partie d’une série d’article sur l’installation d’un serveur Linux sous Debian

Les commandes sont à exécuter avec les droits root

Introduction : comment démarre le système Linux ?

  • A l’allumage du PC, le BIOS (Basic Input Output System) est chargé dans la RAM et s’exécute.
    Puis, en fonction de sa configuration (SETUP du BIOS), le BIOS pointe vers un périphérique (fréquemment un des disques durs) ;
  • Le périphérique (disque dur) contient un espace d’amorçage, le MBR (Master Boot Record), sur lequel un programme est installé : GRUB ;
  • GRUB (GRand Unified Bootloader) affiche le menu de démarrage à l’utilisateur, lui permettant notamment de choisir le noyau et l’initrd à charger s’il en existe plusieurs ;
  • Le noyau linux et l’initrd (INITial RamDisk) sont deux fichiers (images) qui sont stockés sur une partition nécessairement amorçable (/boot). Ils sont lancés par GRUB.
    (l’initrd est passé en argument au noyau).

Problématique

Dans l’article Installation de l’OS Debian, je détaille l’installation de l’OS Debian (9) sur une machine dont les disques durs sont chiffrés, notamment ceux qui accueillent l’OS (/, /var, …).

Dans ma configuration :

  • Une grappe RAID1 de 200 MB (md0) accueille une unique partition (non chiffrée, formatée en ext4) : /boot ;
  • Une grappe RAID1 de 16 GB (md1) accueille une unique partition chiffrée (avec changement de clé automatique à chaque démarrage) : la swap ;
  • Une grappe RAID1 de 483 GB (md2) accueille
    • une unique partition chiffrée (avec mot de passe) ;
    • cette partition sert de VG pour LVM ;
    • ce VG est découpé en différents LV ;
    • chaque LV est formaté en ext4 et est monté pour /, /tmp, /var, …

Au démarrage de la machine, GRUB peut accéder à /boot (car non chiffré, même si ce volume est hébergé sur une grappe RAID1) : le noyau linux et l’initrd sont exécutés.
Ainsi, au démarrage, après avoir vu s’afficher le menu de démarrage proposé par GRUB, puis le chargement de certains des modules du noyau et de l’initrd, la clé de déchiffrement est demandée pour md2 (qui contient les LV de /, /tmp, /var, …) pour pouvoir démarrer l’OS à proprement parler.

Niveau sécurité, cela correspond à ce qui est attendu. Toutefois, pour un serveur, cela pose comme problèmes :

  • en cas de redémarrage du serveur (suite à une coupure de courant, …), le redémarrage de l’OS n’est pas automatique (d’ou une indisponibilité problématique) ;
  • au démarrage, il faut un accès physique au serveur avec à minima un clavier pour taper la clé.

Solutions existantes

  • Placer la clé de déchiffrement sur une clé USB, sur /boot, ou un autre endroit judicieux non chiffré. Cette clé sera alors automatiquement chargée lors du démarrage.
    • Avantage :  aucune intervention de l’utilisateur ne sera requise au démarrage ;
    • Inconvénient : en cas d’accès physique à la machine (cambriolage, vol, effraction), une personne possédant les compétences requises pourra trouver la clé et s’en servir pour déchiffrer les disques.
  • Installer un « mini » serveur ssh dans l’initrd : dropbear.
    Ainsi, lors du boot, la machine (qui exécute donc un serveur SSH) attend une connexion entrante, par laquelle un client se connecte et envoie la clé de déchiffrement nécessaire.

    • Avantage :  sécurité maximale (la clé n’est pas stockée en clair dans le serveur ou sur une clé) et non nécessité d’être physiquement présent pour taper la clé au clavier ;
    • Inconvénient : une intervention d’un administrateur est encore nécessaire (à moins d’automatiser cette tache depuis une autre machine …) pour se connecter puis entrer la clé.

Configurer un démarrage de secours

Quelque soit la méthode non-native que l’on installe, sans solution de secours au cas ou la dite méthode ne fonctionne pas, le système est inutilisable et il est nécessaire de le réparer (avec une version Live sur clé USB bootable par exemple).

Je propose l’idée d’ajouter au menu de démarrage de GRUB une entrée qui correspond au démarrage classique initial, c’est à dire qui demande la clé au clavier lors du boot. Comme c’est le fichier initrd que nous modifierons suivant la solution choisie par la suite, c’est ce fichier qu’il faut sauvegarder et ajouter à la liste du menu de GRUB.

1) Copie du fichier initrd

$ cd /boot
$ ls
config-4.9.0-4-amd64
initrd.img-4.9.0-4-amd64
System.map-4.9.0-4-amd64
grub
vmlinuz-4.9.0-4-amd64
lost+found 

$ cp initrd.img-4.9.0-4-amd64 initrd.img-4.9.0-4-amd64.original

2) Ajout de cette version « originale » d’initrd au menu de boot de GRUB

Le fichier /etc/default/grub et la commande update-grub ne permettent pas (à ma connaissance) d’ajouter notre initrd de secours au menu de boot de grub.

Il faut éditer le fichier /boot/grub/grub.cfg (que l’on sauvegardera bien sûr auparavant)

 $ cd /boot/grub
$ cp grub.cfg grub.cfg.original 

Dans ce fichier on trouve le le bloc correspondant au menuentry original :

 menuentry 'Debian GNU/Linux' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-3ce42560-2705-47fc-baef-0db0524c1b3f' {
load_video
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_msdos
insmod part_msdos
insmod diskfilter
insmod mdraid1x
insmod ext2
set root='mduuid/9031e9bf00dd190c029b5a030001e2d5'
if [ x$feature_platform_search_hint = xy ]; then
   search --no-floppy --fs-uuid --set=root --hint='mduuid/9031e9bf00dd190c029b5a030001e2d5'  c8cb8309-38b5-4828-a90b-653d1110a286
else
   search --no-floppy --fs-uuid --set=root c8cb8309-38b5-4828-a90b-653d1110a286
fi
echo'Loading Linux 4.9.0-4-amd64 ...'
linux/vmlinuz-4.9.0-4-amd64 root=/dev/mapper/VGonCRYPTonMD2-LVslash ro
echo'Loading initial ramdisk ...'
initrd/initrd.img-4.9.0-4-amd64
}

On duplique ce bloc immédiatement en dessous (en respectant les accolades) et l’on modifie bien entendu la ligne correspondante à l’initrd :

menuentry 'Debian GNU/Linux original (manual entry of the LUKS key)' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-3ce42560-2705-47fc-baef-0db0524c1b3f' {
load_video
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_msdos
insmod part_msdos
insmod diskfilter
insmod mdraid1x
insmod ext2
set root='mduuid/9031e9bf00dd190c029b5a030001e2d5'
if [ x$feature_platform_search_hint = xy ]; then
   search --no-floppy --fs-uuid --set=root --hint='mduuid/9031e9bf00dd190c029b5a030001e2d5'  c8cb8309-38b5-4828-a90b-653d1110a286
else
   search --no-floppy --fs-uuid --set=root c8cb8309-38b5-4828-a90b-653d1110a286
fi
echo'Loading Linux 4.9.0-4-amd64 ...'
linux/vmlinuz-4.9.0-4-amd64 root=/dev/mapper/VGonCRYPTonMD2-LVslash ro
echo'Loading initial ramdisk (that ask for LUKS key)...'
initrd/initrd.img-4.9.0-4-amd64.original
} 

3) Test en redémarrant 

Lorsque l’on redémarre le système, le menu doit ressemble à cela :

Solution 1 : clé en clair dans /boot ou sur une clé USB

Attention, je répète qu’avec cette solution, les disques sont bien chiffrés mais la clé existe en clair sur le disque dur !

Les commandes ci-dessous correspondent à une clé enregistrée dans le /boot, mais il est trivial d’adapter ce guide pour le stockage de la clé sur une clé USB.

1) Création d’une nouvelle clé de 4096 Bytes

$ dd if=/dev/urandom of=/boot/keyfile bs=1024 count=4

2) Protection à minima de cette clé par chmod

Les droits 400 restreignent l’accès uniquement à root en lecture seule au fichier-clé. Il est judicieux de donner un nom moins évocateur au fichier …

 $ chmod 400 /boot/keyfile 

3) Ajout de cette nouvelle clé à la liste des clés acceptées

Remarque : la clé originale sera demandée, et fonctionnera encore par la suite car il s’agit d’un ajout de clé.

$ cryptsetup -v luksAddKey /dev/md2 /boot/keyfile
Enter any existing passphrase:
Key slot 0 unlocked.
Key slot 0 unlocked.
Command successful. 

4) Modification du fichier /etc/crypttab

Ce fichier est l’équivalent de /etc/fstab : il contient la liste des volumes chiffrés à monter (déchiffrer) au démarrage du système.

Initialement, dans ma configuration, il contient :

 

md1_crypt /dev/md1 /dev/urandom cipher=aes-xts-plain64,size=256,swap
md2_crypt UUID=d43db96b-2f83-4c1f-82a3-fe6c28871e7a none luks
  • La première ligne correspond au volume RAID MD1 qui contient la swap, avec une nouvelle clé aléatoire (/dev/urandom) à chaque redémarrage ;
  • La seconde ligne correspond au volume RAID MD2 qui contient le VG et les LV correspondants à /, /tmp, /var, … c’est à dire à l’OS. C’est ce volume que l’on veut déchiffrer automatiquement au démarrage.

Il faut à présent :

    • Remplacer le troisième paramètre none par l’emplacement absolu du fichier qui contient la clé, en désignant impérativement le disque via son UUID (obtenu avec la commande blkid par exemple).
      Si /boot correspond à un volume RAID, il faut utiliser l’uuid du RAID et non pas celui d’un des disques de la grappe RAID.
      Par exemple :

      /dev/disk/by-uuid/ec73be45-c8pe-45b0-bae9-5ae9e8e57hf6:/keyfile
    • Remplacer le quatrième paramètre luks par
      luks,keyscript=/lib/cryptsetup/scripts/passdev

5) Création du nouveau fichier initrd 

$ mkinitramfs -o /boot/initrd.img-4.9.0-4-amd64 4.9.0-4-amd6

Il faut bien entendu adapter ma version 4.9.0-4 à celle que vous utilisez …

6) Test

En cas de problème, démarrer avec l’initrd de secours créé précédemment.

Solution 2 : connexion en SSH au boot

De nombreux articles abordent cette solution sur le net. Un exemple.