Datenträger unter Linux mit cryptsetup (LUKS) verschlüsseln

Ihr möchtet einen Datenträger wie z.B. eine Festplatte oder einen USB-Stick verschlüsseln, damit bei einem Verlust des Datenträgers nicht jeder ohne weiteres Zutun eure Daten lesen kann? Dann haben wir ein gemeinsames Ziel!

Im Folgenden beschreibe ich, wie unter Linux mit Hilfe des Programms cryptsetup eine Festplatte verschlüsselt werden kann. Dazu gehört die Beschreibung, wie das verschlüsselte Gerät anschließend zur Nutzung geöffnet wird und wie man es in die /etc/crypttab einträgt, um das Gerät automatisch beim Start des Rechners zu öffnen. Es handelt sich dabei um eine zusätzliche Festplatte. Wie die erste Festplatte eines Systems verschlüsselt werden kann ist hingegen nicht Gegenstand dieses Artikels. Hier hilft (hoffentlich) ein Blick in die Installationsanleitung der jeweiligen Linux-Distribution weiter.

Das Programm cryptsetup ist in allen gängigen Linux-Distributionen verfügbar. Falls nicht, kann es direkt von der Projekt-Homepage auf GitLab bezogen werden. Die hier gezeigten Kommandos funktionieren prinzipiell auf jedem Linux-System, auf dem cryptsetup verfügbar ist.

Bevor es losgeht noch ein Hinweis. Ich möchte ein verschlüsseltes Gerät erstellen, mit dem Ziel, dass nicht jeder die Daten einfach lesen kann, dem das Gerät in die Hände fällt. Dabei denke ich an Szenarien wie Verlust, Diebstahl, Verkauf etc. Die Daten vor dem Zugriff durch Sicherheitsbehörden, Geheimdiensten oder Schurkenstaaten zu schützen erfordert einen deutlichen höheren Aufwand und ist nicht Gegenstand dieses Artikels.

Ich verwende im Folgenden LUKS2. Wer stattdessen lieber dm-crypt verwendet, sei auf die Manpage cryptsetup(8) verwiesen.

Die zu verschlüsselnde Festplatte wird in diesem Tutorial als /dev/sdX bezeichnet. Dieser Bezeichner muss auf das tatsächlich zu nutzende Gerät angepasst werden. Wichtig: Wird versehentlich das falsche Gerät verschlüsselt gehen vorhandene Daten unwiederbringlich verloren!

LUKS-Container erstellen

Zur Erstellung eines LUKS-Containers wird der folgende Befehl ausgeführt und die Bildschirmanweisungen befolgt. Für die dabei abgefragte Passphrase gilt grundsätzlich: „Je länger und komplizierter, desto sicherer. Wobei es mehr auf die Länge als die Komplexität ankommt.“

Weitere Hinweise zur Passwort-Sicherheit bietet der Wikipedia-Artikel zu Passsatz.

$ sudo cryptsetup luksFormat --type luks2 /dev/sdX
WARNING: Device /dev/sdX already contains a 'dos' partition signature.

WARNING!
========
This will overwrite data on /dev/sdX irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase for /dev/sdX: 
Verify passphrase:

Hinzufügen einer Backup-Passphrase

LUKS-Passphrasen werden in sogenannten Key-Slots gespeichert. Bei LUKS2 stehen 32 Key-Slots zur Verfügung, welche von 0-31 nummeriert sind. Bei LUKS1 waren es 8 Key-Slots. Die Passphrase aus dem vorigen Abschnitt wurde in Slot 0 gespeichert.

Vergisst man die Passphrase, wird der Key-Slot oder der LUKS-Header beschädigt, ist ein Zugriff auf die Daten nicht mehr möglich. Um mich gegen die ersten beiden Fälle abzusichern, erstellte ich zwei Backup-Passphrasen, welche ich in den Key-Slots 3 und 8 speicherte. Wie man sich gegen den Verlust des LUKS-Headers schützt, beschreibe ich im folgenden Abschnitt.

$ # Hinzufügen der ersten Backup-Passphrase in Key-Slot 3
$ sudo cryptsetup luksAddKey /dev/sdX --key-slot 3
Enter any existing passphrase: 
Enter new passphrase for key slot: 
Verify passphrase:

$ # Hinzufügen der zweiten Backup-Passphrase in Key-Slot 8
$ sudo cryptsetup luksAddKey /dev/sdX --type luks2 --key-slot 8
Enter any existing passphrase: 
Enter new passphrase for key slot: 
Verify passphrase:

Für die Backup-Passphrasen gilt selbstverständlich das im vorangegangenen Abschnitt Beschriebene. Die einzelnen Passphrasen sollten von gleicher Güte sein.

Die Backup-Passphrasen sind an einem sicheren Ort aufzubewahren. Ich verwende dazu bspw. einen Passwort-Tresor (vgl. Sichere Passwörter und wie man sie verwaltet).

LUKS-Header sichern

Nun nützen alle Backup-Passphrasen nichts, wenn der LUKS-Header beschädigt wird. Daher empfehle ich diesen mit Hilfe des folgenden Kommandos in eine Datei zu sichern.

$ sudo cryptsetup luksHeaderBackup /dev/sdX --header-backup-file /var/tmp/luksHeaderBackup_2020-10-18

Die so erstellte Datei ist sicher — am besten offline und vom Datenträger getrennt — aufzubewahren. Mit Hilfe dieser Datei und einer Passphrase, welche bei Erstellung des Backups gültig war, kann ein defekter LUKS-Header und damit der Zugriff auf ein verschlüsseltes Gerät wiederhergestellt werden.

Ändert man im Laufe der Zeit in Key-Slots gespeicherte Passphrasen, löscht alte oder fügt neue hinzu, so ist eine erneute Sicherung des LUKS-Headers sinnvoll und angeraten.

LUKS-Container öffnen und nutzen

Bis jetzt haben wir auf dem Block-Gerät /dev/sdX einen verschlüsselten LUKS-Container erstellt, Backup-Passphrasen hinzugefügt und den LUKS-Header gesichert. Der folgende Code-Block zeigt, wie der LUKS-Container geöffnet und damit nutzbar gemacht wird. Dabei ist sdX_crypt ein Bezeichner, welcher für den Device Mapper verwendet wird. Dieser Bezeichner kann von euch frei gewählt werden.

$ sudo cryptsetup open /dev/sdX sdX_crypt
$ lsblk | grep sdX
sdX              8:16   0 111,8G  0 disk  
└─sdX_crypt    254:3    0 111,8G  0 crypt

Der so geöffnete LUKS-Container kann nun mit einem Dateisystem eurer Wahl formatiert werden. Folgender Code-Block zeigt ein Beispiel für ext4. Dies kann in Abhängigkeit zur Größe des LUKS-Containers einige Zeit dauern.

$ sudo mkfs.ext4 /dev/mapper/sdX_crypt
[...]
$ sudo blkid | grep sdX
/dev/sdX: UUID="Eine-furchbar-lange-UUID" TYPE="crypto_LUKS"
/dev/mapper/sdX_crypt: UUID="Eine-andere-furchbar-lange-UUID" TYPE="ext4"

Man beachte, dass der LUKS-Container direkt mit einem Dateisystem formatiert werden kann. Die Erstellung einer Partition ist nicht erforderlich.

Das erstellte Dateisystem kann anschließend wie gewohnt eingehängt werden.

$ sudo mount /dev/mapper/sdX_crypt /mnt

Mit den folgenden Kommandos wird das Dateisystem wieder ausgehängt und der LUKS-Container verschlossen. Damit liegen die Daten nur noch in verschlüsselter Form vor, bis sie das nächste Mal geöffnet werden.

$ sudo umount /dev/mapper/sdX_crypt
$ sudo cryptsetup close sdX_crypt
$ sudo cryptsetup status sdX_crypt
/dev/mapper/sdX_crypt is inactive.

Verschlüsseltes Dateisystem bei Startvorgang des Rechners öffnen und einhängen

Soll das erstellte Dateisystem /dev/mapper/sdX_crypt bereits beim Start des Rechners eingehängt werden, ist folgende Reihenfolge einzuhalten:

  1. LUKS-Container sdX_crypt mit Hilfe der /etc/crypttab öffnen
  2. Dateisysteme aus /etc/fstab einhängen

Die Einträge in den entsprechenden Dateien sehen in meinem Fall wie folgt aus. In /etc/crypttab wird dabei die UUID des Gerätes /dev/sdX verwendet.

$ sudo cat /etc/crypttab
sdX_crypt UUID="Eine-furchbar-lange-UUID" none luks,discard

$sudo cat /etc/fstab
/dev/mapper/sdX_crypt /mnt ext4 defaults 0 0

Man beachte, dass der Rechner nun den Startvorgang unterbricht und zur Eingabe der Passphrase zum Öffnen des LUKS-Containers auffordert. Anschließend wird der Startvorgang fortgesetzt.

Damit sind wir eigentlich am Ende des Tutorials angelangt. Wie fandet ihr es? War es verständlich genug, um folgen zu können und Eingangs erwähnte Ziele zu erreichen?

Wer noch Zeit und Lust hat, kann gerne weiterlesen. In den folgenden Abschnitten werde ich als Zugabe noch beschreiben, wie man Key-Slots löscht und einen LUKS-Header aus einem Backup wiederherstellt.

Key-Slots löschen

Mit dem folgenden Befehl werden sämtliche Key-Slots des LUKS-Containers gelöscht. Ein Zugriff auf den LUKS-Container ist anschließend nicht mehr möglich. Die Angabe eines Passworts ist nicht erforderlich.

Warnung: Dieser Vorgang kann nicht rückgängig gemacht werden.

$ sudo cryptsetup erase /dev/sdX

WARNING!
========
This operation will erase all keyslots on device /dev/sdb.
Device will become unusable after this operation.

Are you sure? (Type uppercase yes):

Das war’s.

LUKS-Header aus Sicherung wiederherstellen

Und nun halte ich noch fest, wie man einen LUKS-Header und die darin enthaltenen Key-Slots aus einer Datensicherung wiederherstellen kann.

$ sudo cryptsetup luksHeaderRestore /dev/sdX --header-backup-file /tmp/luksHeaderBackup_2020-10-18 

WARNING!
========
Device /dev/sdX already contains LUKS2 header. Replacing header will destroy existing keyslots.

Are you sure? (Type uppercase yes):

Uns schon kann man wieder auf seinen LUKS-Container zugreifen.

Reflexion

Um meine Festplatte zu verschlüsseln und diesen Beitrag zu schreiben, habe ich einige Zeit in der Manpage cryptsetup(8) und auf der Projekt-Seite gelesen. Nur mit der Manpage allein wäre mir eine Nutzung vermutlich erst nach deutlich längerer Zeit gelungen.

Dabei vermisse ich in der Manpage vor allem eine Inhaltsübersicht und Beispiele, mit denen man sich gängige Aufgaben schnell ins Gedächtnis rufen kann. Zwar existiert seit ca. zwei Jahren ein Ticket zur Überarbeitung der Manpage, doch fehlt es bei den am Projekt beteiligten Personen wie so oft an der Zeit. Diese wird primär zur Arbeit am Code genutzt. Für die Dokumentation bleibt keine Zeit übrig.

Aktuell erkundige ich mich auf der Mailling-Liste, wie man am besten dazu beitragen kann, die Manpage zumindest in Teilen zu verbessern. Mal sehen, was sich da machen lässt.

Da man vermutlich nicht täglich mit cryptsetup arbeitet, ist eine gute Dokumentation um so wichtiger, da vermutlich niemand alle notwendigen Befehle dauerhaft im Gedächtnis behält.

Mit diesem Tutorial habe ich mir meine eigene Dokumentation für meine häufigsten Anwendungsfälle geschaffen. Wenn ihr sie ebenfalls nützlich findet, freut mich dies umso mehr.

6 Gedanken zu „Datenträger unter Linux mit cryptsetup (LUKS) verschlüsseln

  1. almanya

    Danke für die gute Beschreibung.
    Fragen/Anmerkungen:
    Bei der Erstellung des Containers habe ich an anderer Stelle/Quelle gelesen:
    sudo cryptsetup –cipher aes-xts-plain –key-size 512 –verify-passphrase luksFormat /dev/sdX.
    Du lässt jedoch diese Detail-Optionen zur Verschlüsselung weg.

    Und weiter,
    In deinen o.g. Kommandozeilen schreibst du:
    $ # Hinzufügen der ersten Backup-Passphrase in Key-Slot 3
    $ sudo cryptsetup luksAddKey /dev/sdX –key-slot 3
    und in
    $ # Hinzufügen der zweiten Backup-Passphrase in Key-Slot 8
    $ sudo cryptsetup luksAddKey /dev/sdX –type luks2 –key-slot 8

    Kann es sein, dass dir bei Key-Slot 3 die Option „–type luks2“ fehlt?
    Du hattest ja schon beim Erstellen des Containers mit luks2 gearbeitet.

    Viele Grüße
    almanya

    Antworten
    1. Jörg Kastning Beitragsautor

      Bitte, gern geschehen.

      Zu deinen Fragen/Anmerkungen:
      Wenn man die Optionen `–cipher`, `–key-size` und `–verify-passphrase` nicht explizit mit angibt, werden die Standardwerte für diese Optionen genommen. Leider lässt sich mithilfe der Manpage nicht feststellen, welche dies sind. Im Zweifel gilt, dass explizit besser als implizit ist. Hat deine Quelle denn auch erklärt, warum diese Werte für die genannten Optionen gewählt wurden?

      Zu deiner zweiten Anmerkung:
      Es ist durchaus möglich, dass ich für den Key-Slot 3 schlicht vergessen habe, `–type luks2` mit anzugeben. Es ist jedoch auch möglich, dass dies gar nicht nötig war, weil luks2 auf meinem damaligen System der Standard war. Leider kann ich das heute nicht mehr nachvollziehen.

      Antworten
  2. almanya

    Bei mir sind die Einträge in der /etc/crypttab und der /etc/fstab
    leider nicht automatisch mit drin gewesen.
    Ich habe dann die /etc/crypttab mit einem Editor händisch um den o.g. Eintrag erweitert und dann noch
    {{{update-initramfs -u -k all}}}
    eingegben.
    Der Start mit einem gemeinsamen PW für das (von mir zuvor verschlüsselte) System auf SSD1 und nun mit dem Container auf SSD2 hat funktioniert.
    Auch wenn die /etc/fstab nichts von dem o.g. enthält.

    Antworten
    1. Jörg Kastning Beitragsautor

      Darf ich fragen, welche Distribution du nutzt?

      Es ist möglich, dass Dateisysteme nicht in der /etc/fstab stehen und trotzdem eingehängt werden, weil für sie evtl. eine systemd-Mount-Unit existiert.

      Auf jeden Fall freue ich mich, dass zu Erfolg hattest und dein Ziel erreichen konntest.

      Viele Grüße
      Jörg

      Antworten
  3. Rat

    Sehr schöne Anleitung um erst einmal in die Materie zu kommen. Danke dir.

    Kleine Logik-Frage allerdings.
    Es gibt acht Key-Slots, welche deiner Angabe nach von 0 bis 7 nummeriert sind.
    Ist die Angabe „–key-slot 8“ denn damit nicht außerhalb der möglichen Keys?

    Antworten
    1. Jörg Kastning Beitragsautor

      Hi Rat, danke für deinen Kommentar. Schön, dass dir das Tutorial gefällt.

      Zu deiner Frage:
      LUKS1 verwendet 8 Key-Slots. LUKS2 hingegen unterstützt bis zu 32 Key-Slots. Ich habe im Artikel von 8 Key-Slots (0-7) geschrieben, aber in den Beispielen LUKS2 verwendet. Da hier mehr Slots zur Verfügung stehen, konnte ich auch Slot Nr. 8 verwenden.

      Ich werde das im Artikel später noch präzisieren.

      Viele Grüße
      Jörg

      Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert