Verschlüsselung: LUKS und LVM

LVM und LUKS

(Update 10.06.2013: Verschlüsseltes Filesystem als Datei | 13.11.2012: Reparatur beschädigter LVM-Devices)

LVM (Logical Volume Manager) bietet unter Linux eine sehr komfortable Methode an, Festplatten und Partitionen zu verwalten.

LUKS (Linux Unified Key Setup) erlaubt die transparente (Anwendungen bemerken nichts davon) Verschlüsselung ganzer Festplatten oder Teilen davon. LUKS ist Nachfolger von dm_crypt und bietet unter anderem den Vorteil, mehrere Passwörter vergeben zu können und beim Ändern (d.h. ein neues erstellen und ein altes löschen) eines Passwortes muss nicht der gesamte Inhalt neu verschlüsselt werden.

LUKS kann auf LVM aufsetzen (bspw. das Verschlüsseln einer Partition oder volume group (Gruppe) oder LVM kann auf LUKS aufsetzen. Über die Vor- und Nachteile sei hier im Moment nichts weiter geschrieben. Das Thema ist recht weitläufig.

Dokumentation: Archilinux: dm-crypt with LUKS (en)

Verschlüsseln einer Partition

Prinzipielles Vorgehen

  • Erstellen einer Partition (mit LVM oder als "normale" Partition oder als Datei).
  • Erstellen eines Behälters (Container) zur Aufnahme des verschlüsselten Bereiches mit neuem Passwort
  • Öffnen des Bereiches mit dem gewählten Passwort
  • Initialisieren des Dateisystems auf dem Bereich
  • Einbinden (mount) des verschlüsselten Bereiches

LUKS auf LVM

Komfortabel ist die Benützung des LVM Tools (Redhat, Centos, Fedora: system-config-lvm oder Menü System->Admininstration->Logical Volume Management). Doch per Hand geht es auch:

Auf einer Harddisk (/dev/sdb) wird eine Partition (dev/sdb1) eingerichtet, die dann LVM "beherbergt". Zuerst die (neue) Harddisk oder den (neuen) USB-Stick partitionieren. Einfach in der Shell geht das mit cfdisk (oder fdisk). Grafisch kann das mit gparted oder palimpsest (Fedora).

In (auf) dieser neuen Partition wird ausgeführt:

LVM

Initialisieren der Partition für LVM:

pvcreate /dev/sdb1

Erstellen einer "volume group" mit Namen LV03 (frei wählbar) in dieser LVM-Partition:

vgcreate LV03 /dev/sdb1

Erstellen eines Volumens (herkömmlich: einer Partition) auf LV03 mit Namen LV03_crypted (frei wählbar):

lvcreate -L 10G -n LV03_crypted LV03

Sicherheit, Verschlüsseln und Erstellen des Dateisystems

Füllen des Volumens (Partition) mit Zufallszeichen. Dies verhindert, dass ein Angreifer anhand der sonst erkennbaren Strukturierung der Daten einen Angriff starten kann. Achtung dieser Vorgang kann (wird) mehrere Stunden dauern, je nach Grösse des Bereiches und Geschwindigkeit des Rechners:

dd if=/dev/urandom of=/dev/LV03/LV03_crypted bs=1M

Verschlüsseln (Hinterlegen des Schlüssels) und erstellen des Block Devices. Auf CentOS5.4 (RHEL5.4) wird dabei AES mit CBC-Essiv und SHA256 verwendet (auf den neueren Fedoras (ab 12) AES-XTS-PLAIN).

cryptsetup -y luksFormat /dev/mapper/LV03_crypted

(ergibt auf CentOS: cryptsetup -c aes-cbc-essiv:sha256 -y -s 256 luksFormat ...)

"Unlocking" des Block Devices und Eingabe des Passwortes (Pass phrase):

cryptsetup luksOpen /dev/mapper/LV03_crypted crypt

Erstellen des Dateisystems. Es kann prinzipiell jedes verfügbare Dateisystem benutzt werden:

mkfs.ext3 -j -m 1 -O dir_index,filetype,sparse_super /dev/mapper/crypt

oder

mkfs.ext4 -j -m 1 -O dir_index,filetype,sparse_super /dev/mapper/crypt

Einbinden der verschlüsselten Partition

mkdir /mnt/crypt
mount /dev/mapper/crypt /mnt/crypt

Abhängen und Abmelden

umount /mnt/crypt
cryptsetup luksClose /dev/mapper/crypt

Automatischen Mounten beim Booten

Dafür wird die eindeutige UUID der zu mountenden Partition benötigt:

cryptsetup luksUUID /dev/mapper/LV03_crypted

Das ergibt eine Zeile der Art:
5f110d4c-e746-2114-9f08-efc7b5cd1206

Diese wird auf einer Zeile in eine (neue, wenn nicht vorhandene) Datei /etc/crypttab geschrieben:

echo "luks-5f110d4c-e746-2114-9f08-efc7b5cd1206 UUID=5f110d4c-e746-2114-9f08-efc7b5cd1206 none" >>/etc/crypttab

Der Ort zum Einbinden wird erstellt (frei wählbar):

mkdir /mnt/crypt

Dann wird die Datei /etc/fstab erweitert um die Zeile:

echo "/dev/mapper/luks-5f110d4c-e746-2114-9f08-efc7b5cd1206 /mnt/crypt  ext3  defaults  1 2" >>/etc/fstab

Beim nächsten Booten wird nach dem Passwort der neuen Partition gefragt und das System hängt sie in den vorher definierten "mountpoint".

Hinzufügen eines Schlüssels

Man weitere Schlüssel hinzufügen oder entfernen. Bei beiden Befehlen kann man entweder den Schlüssel angeben oder eine Schlüsseldatei.

cryptsetup luksAddKey /dev/mapper/LV03_crypted [<Schlüsseldate>]
cryptsetup luksRemoveKey /dev/mapper/LV03_crypted [<Schlüsseldatei>]

Wenn man einen Schlüssel entfernen möchte, den man nicht mehr kennt, aber man ist noch in Besitz eines weiteren, dann geht das unter Angabe eines bekannten Schlüssels direkt mit:

cryptsetup luksDelKey /dev/mapper/LV03_crypted <Schlüsselnummer>

Reparatur

Annahme: USB-Stick mit 3 Partitionen. Die dritte Partition (/dev/sdb3) ist LVM. Die beiden anderen nicht.

Wenn die Informationen von LVM auf dem Device zerstört sind, kann nicht mehr auf die Partition zugegriffen werden. Man kontrolliert das mit:

vgck VOLGROUPNAME

(wobei VOLGROUPNAME für den eigenen Namen steht. Im Folgenden 'livelvm'). Direkt lässt sich das Label so auslesen:

pvck /dev/sdb3

  Found label on /dev/sdb3, sector 1, type=LVM2 001
  Found text metadata area: offset=4096, size=1044480

Sollte das aber kein Resultat liefern, ist die Metainformation der volume group zerstört. Doch es gibt ein Backup davon. In /etc/lvm/backup (auf dem Rechner, auf dem die Harddisk, der Stick, usw. eingerichtet wurde).

more /etc/lvm/backup/livelvm 

# Generated by LVM2 version 2.02.86(2) (2011-07-08): Wed Sep  5 15:02:30 2012
contents = "Text Format Volume Group"
version = 1
description = "Created *after* executing '/sbin/vgcreate -M2 -l 256 -p 256 -s 4m -c n livelvm /dev/sdb3'"
creation_host = "ceres.inetcom.local"    # Linux ceres.inetcom.local 3.3.8-1.fc16.i686.PAE #1 SMP Mon Jun 4 21:10:09 UTC 2012 i686
creation_time = 1346850150    # Wed Sep  5 15:02:30 2012
livelvm {
    id = "jO6HWE-DvYd-qVBl-Zvxg-0g7s-xPz3-FnT5zC"
    seqno = 1
    status = ["RESIZEABLE", "READ", "WRITE"]
    flags = []
    extent_size = 8192        # 4 Megabytes
    max_lv = 256
    max_pv = 256
    metadata_copies = 0
    physical_volumes {
        pv0 {
            id = "oWnpZI-0IPN-1flW-FFA1-ZqvT-h267-hGFLdu"
            device = "/dev/sdb3"    # Hint only
            status = ["ALLOCATABLE"]
            flags = []
            dev_size = 104118272    # 49.6475 Gigabytes
            pe_start = 2048
            pe_count = 12709    # 49.6445 Gigabytes
        }
    }
}

Noch einmal kontrollieren, ob es wirklich einen Defekt hat. Ist das Device überhaupt vorhanden?

ls /dev/sdb*

/dev/sdb  /dev/sdb1  /dev/sdb2  /dev/sdb3

Es ist vorhanden. Findet sich das LVM-Label auf /dev/sdb3?

pvck /dev/sdb3

Could not find LVM label on /dev/sdb3

Es ist nicht vorhanden. Dann kann repariert werden. Wer sich nicht sicher ist, der macht vorher ein Backup:

dd if=/dev/sdb3 of=backup.sdb bs=1024 count=5

Dann die eigentliche Reparatur, das Neubeschreiben der LVM-Metadaten:

pvcreate --restorefile /etc/lvm/backup/livelvm -u jO6HWE-DvYd-qVBl-Zvxg-0g7s-xPz3-FnT5zC /dev/sdb3

Nun muss noch die Logical Volume Information wieder hergestellt werden:

vgcfgrestore -f /etc/lvm/backup/livelvm livelvm

Weitere Optionen

http://linux.die.net/man/8/cryptsetup
http://www.bitbull.ch/wiki/index.php/LVM_Troubleshooting_for_REL5

Auch machbar: Verschlüsseltest Filesystem als Datei

Statt einer (LVM-)Partition auf einer Harddisk lässt sich das Verfahren auch auf ein Partitionsabbild oder einer "Container"-Datei anwenden. Zuerst müssen ein paar Kernel-Module geladen sein (weitere Verschlüsselungsmethoden wie z.B. cbc nach Bedarf):

modprobe loop cryptoloop aes

Dann erstellt man einen Container von bspw. 1GB und bindet ihn via loop-device ein:

dd if=/dev/urandom of=~/filesystemdatei.dd bs=1M count=1024
/sbin/losetup -e aes-cbc-256 /dev/loop0 ~/filesystemdatei.img

Der zweite Befehl fragt nach einem Passwort. Anschliessend formatiert man mit:

mkfs.ext4 -j -m 1 -O dir_index,filetype,sparse_super ~/filesystemdatei.img

und hängt die Datei wieder aus:

/sbin/losetup -d /dev/loop0

Nun kann man entweder manuell oder via fstab das Dateisystem im Container einhängen. Losetup fragt nach dem zuvor eingegeben Passwort. Erst die manuelle Methode

/sbin/losetup -e aes-cbc-256 /dev/loop0 ~/filesystemdatei.img
mkdir /mnt/test; mount /dev/loop0 /mnt/test

Und nun via fstab. Dazu muss /etc/fstab um folgende Zeilen erweitert werden:

/root/filesystemdatei.img     /mnt/test     ext4     defaults,noauto,loop=/dev/loop0,encryption=aes-cbc-256 0 0

Dann kann man das Dateisystem mit:

mount /mnt/test

einbinden.