Automount von LUKS-verschlüsselten Festplatten

(2011-09-04)

In meinem Artikel über Festplattenverschlüsselung unter Linux habe ich unter anderem erklärt, wie man eine komplette Partition verschlüsselt. Nun möchte ich ergänzen, wie man eine externe Festplatte automatisch mountet, sobald man sie einsteckt.

Voraussetzung: Einzelne Partition ist verschlüsselt

Ich gehe davon aus, dass auf der Festplatte eine Partition Table existiert mit genau einer Partition, welche via dmcrypt+LUKS verschlüsselt wurde. Die Ausgabe von fdisk -l /dev/sdb sollte also folgendermaßen aussehen:

# fdisk -l /dev/sdb
Disk /dev/sdb: 1000.2 GB, 1000202043392 bytes
248 heads, 55 sectors/track, 143219 cylinders, total 1953519616 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00021631

Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048  1953519615   976758784   83  Linux

Voraussetzung: Keyfile kann zum Entschlüsseln benutzt werden

Weiterhin muss natürlich eine Schlüsseldatei vorhanden sein, welche die Partition entschlüsseln kann, sonst kann man die Festplatte natürlich nicht vollautomatisch mounten (sondern müsste eine Passphrase eingeben).

Eine solche Datei kann man folgendermaßen anlegen und zu einer bestehenden dmcrypt+LUKS-Partition hinzufügen:

$ mkdir keyfiles; cd keyfiles
$ dd if=/dev/random of=backup-hdd bs=256 count=1
# cryptsetup luksAddKey /dev/sdc1 ~/keyfiles/backup-hdd

Eintrag in /etc/fstab

Damit die udev-Regel aus dem nächsten Kapitel weiß, wohin sie die Festplatte mounten soll, legen wir einen entsprechenden Eintrag in der /etc/fstab an:

/dev/mapper/backup-crypt /mnt/backup        ext4    defaults,user,users 0   0

Seriennummer herausfinden

Um später die Festplatte eindeutig identifizieren zu können, brauchen wir die Seriennummer des Geräts. Wenn sie eingesteckt ist, kriegen wir sie mit dem folgenden Befehl heraus:

$ udevadm info -a -p $(udevadm info -q path -n /dev/sdb) | grep serial
    ATTRS{serial}=="66623425ABCDEF"
    ATTRS{serial}=="0000:00:1a.7"

Der erste Wert ist hierbei die Seriennummer (der zweite ein interner Pfad zum Gerät).

udev-Regel

Nun muss man dem System begreiflich machen, dass er zwei Sachen erledigen soll:

  1. Beim Einstecken der USB-Festplatte soll er via cryptsetup die Partition entschlüsseln
  2. Sobald cryptsetup fertig ist, soll die Partition gemountet werden

Das erledigt folgende udev-Regel, die man in /etc/udev/rules.d/85-usb-backup-hdd.rules ablegt:

$ cat /etc/udev/rules.d/85-usb-backup-hdd.rules 

##################################################################################
# rule 1: decrypt the disk once it gets plugged in
##################################################################################

# matches partitions (there is precisely one) of block devices with the serial
# number of my backup external hard disk

ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="partition", ATTRS{serial}=="66623425ABCDEF", \
RUN+="/sbin/cryptsetup --key-file /home/michael/keyfiles/backup-hdd luksOpen $env{DEVNAME} backup-crypt"

##################################################################################
# rule 2: as soon as the crypt container is opened, mount the filesystem inside it
##################################################################################

# we (also) match on change because the device name is known only after some time
ACTION=="add|change", SUBSYSTEM=="block", ENV{DM_NAME}=="backup-crypt", \
RUN+="/bin/mount /dev/mapper/$env{DM_NAME}"

Die fettgedruckten Stellen sind diejenigen, die ggf. ersetzt werden müssen. Die erste mit der Seriennummer der Festplatte, die wir zuvor herausgefunden haben. Die zweite mit dem Ort zum LUKS-keyfile und die letzten beiden mit dem Namen, unter dem die Partition entschlüsselt werden soll.

Einstecken testen

Das war’s schon (zumindest fürs automatische mounten). Ohne neuladen oder neustarten von irgendeinem Dienst sollte jetzt, sobald die Festplatte eingesteckt wird, automatisch die Partition gemountet werden. Mithilfe des Befehls udevadm monitor --property kann man sich die Events, die der Linux-Kernel bzw. udev gerade erzeugen, anzeigen lassen.

Umounten

Bevor man die Festplatte nun abziehen kann, muss man sie natürlich umounten. Anschließend müsste man dann noch via cryptsetup luksClose die Entschlüsselung wieder schließen, aber das kann man sich auch wegoptimieren :-).

Ich habe dazu ein kleines Script geschrieben, welches ein Wrapper für umount ist. Das Script prüft, ob das gemountete Gerät in /dev/mapper/ liegt und ruft nach dem eigentlich umount gleich ein passendes cryptsetup luksClose auf. Weiterhin zeigt es, während der umount läuft, an, wieviele Bytes noch auf die Platte(n) geschrieben werden müssen (man kann hier leider nur den Wert für alle Platten anzeigen).

Nachdem man sich das umount-wrapper-script heruntergeladen hat, legt man es einfach nach ~/.bin/umount und fügt ~/.bin ganz vorn in den PATH ein.