DM-Crypt/Root-Partition verschlüsseln

Aus Gentoo Linux Wiki

Wechseln zu: Navigation, Suche
Eine Einleitung und Hinweise zur Kernelkonfiguration sowie Installation vom DM-Crypt und cryptsetup-luks finden sie im Artikel DM-Crypt. Dort sind auch weitere Anwendungsbeispiele verlinkt.


Das Verschlüsseln des Root-Dateisystems ist natürlich die anspruchvollste Aufgabe. Schließlich liegt das gesamte Betriebssystem auf einer verschlüsselten Partition und der Mapper muss geöffnet werden, bevor das System läuft. Dafür haben wir dann am Ende nur noch eine einzige unverschlüsselte Partition: unsere Boot-Partition. Damit kann ein potentieller Angreifer nur noch unseren Kernel, unsere Bootloader-Konfiguration und die Tools zum Entschlüsseln und Starten des eigentlichen Systems (natürlich ohne den Schlüssel dazu) korrumpieren.

In diesem Abschnitt geht es vorranging um das Aufsetzen eines neuen Gentoo-Systems, weniger um die Verschlüsselung von Daten.

Inhaltsverzeichnis

[Bearbeiten] System installieren

Die Installation geht ganz normal nach dem Handbuch, nur dass die Zielpartition verschlüsselt ist. Um auf diese zugreifen zu können, muss das Host-System (Live-CD o.a.) natürlich die entsprechenden Algorithmen (AES, CBC, etc.) und LUKS unterstützen.

In meinem Beispiel installiere ich in eine luks-Partition auf /dev/hda3, die auf /dev/mapper/root gemapt ist.

[Bearbeiten] initrd

Um das verschlüsselte System zu booten, muss zunächst die root-Partition gemapt und gemountet werden. Danach wird das Root-Verzeichnis gewechselt (chroot) und init ausgeführt.

Dazu brauchen wir ein initrd-Image, das die entsprechenden Tools zur Verfügung stellt.

# cd /mnt
# mkdir ramdisk
# dd if=/dev/zero of=initrd bs=1024 count=4096
# mke2fs -F ./initrd
# mount -o loop initrd ramdisk
# mkdir ramdisk/{bin,etc,lib,sbin,dev,proc,mnt}
# cp -a /bin/{bash,cat,chroot,cryptsetup,echo,mkdir,mknod,mount,rm,sed,sleep,umount} ramdisk/bin/
# cp -a /sbin/{blockdev,pivot_root} ramdisk/sbin
# ln -s bash ramdisk/bin/sh
# mknod ramdisk/dev/console c 5 1
# mknod ramdisk/dev/hda3 b 3 3

Welche devices in /dev genau gebraucht werden, hängt davon ab, was die root-Partition werden soll (in diesem Fall /dev/hda3). Die Nummern, die man für andere Devices an mknod übergeben muss, bekommt man am schnellsten mit file raus, also z.B.

# file /dev/sda1
/dev/sda1: block special (8/1)

Für die Programme brauchen wir nun noch einige shared libs, einschließlich symbolischer Links. Die kann man für jedes der eben kopierten Programme mittels ldd ermitteln. Bei mir waren es

# cp -aL /lib/{ld-linux.so.2,libblkid.so.1,libc.so.6,libdevmapper.so.1.02,libdl.so.2,libncurses.so.5,libuuid.so.1} ramdisk/lib

[Bearbeiten] /sbin/init

Was unserem image jetzt noch fehlt, ist ein init-Programm, das der Kernel ausführt.

# vi ramdisk/sbin/init
#!/bin/sh

# == Konfiguration ==
# Root-Partition (die verschlüsselte):
ROOT_DEV=/dev/hda3
# Namen des Mappers:
ROOT_MAP=root

# == Script - ab hier sollte nichts mehr zu ändern sein ==
export PATH=/bin:/sbin

# Proc mounten, das für cmdline und LUKS benötigt wird
mount -t proc proc /proc

# cmdline von proc zum Weitergeben an "echtes" init holen
CMDLINE=`cat /proc/cmdline`

# Erstellen des /dev/mapper/control-Knotens für udev-Systeme
sh /sbin/devmap_mknod.sh
if [ $? -ne 0 ] ; then
        echo Creation of /dev/mapper/control failed. System halted.
        exit 0
fi

# == Hier kommt der Luks-Teil
count=0
pass=tralala
sesam=1
while [ ${sesam} -ne 0 ] ; do
        if [ "$count" = "3" ] ; then
                # Nach drei Fehlversuchen wird das System gestoppt:
                echo System halted
                exit 0
        fi

        # Versuch hochzählen
        count=$(( $count + 1 ))

        # Nutzereingabe:
        echo " --- Enter passphrase for root partition ---"
        read -s pass
        echo

        # Versuchen, Partition zu mounten:
        echo "${pass}" | cryptsetup luksOpen ${ROOT_DEV} ${ROOT_MAP}
        sesam=$?
done
# Wenn wir hier sind, hat das Öffnen funktioniert
echo "Mounting root"
mount /dev/mapper/${ROOT_MAP} /mnt
if [ $? -ne 0 ] ; then
        # Fehler beim Mounten
        echo "Mounting root failed, halting system"
        cryptsetup luksClose ${ROOT_MAP}
        exit 0
fi

# == Luks-Teil zuende
echo "Booting system now..."

# Ab hier brauchen wir Proc nicht mehr
umount /proc

# Zu unserer Partion wechseln
cd /mnt
mkdir initrd
pivot_root . initrd

# Alles soweit fertig, jetzt können wir unser System starten
echo Starting init and flushing ram device
exec chroot . /bin/sh <<- EOF >/dev/console 2>&1
umount initrd
rm -rf initrd
blockdev --flushbufs /dev/ram0
echo "Exec /sbin/init ${CMDLINE}"
exec /sbin/init ${CMDLINE}
EOF

Nun machen wir das Initskript noch ausführbar.

# chmod +x ramdisk/sbin/init

[Bearbeiten] /sbin/devmap_mknod.sh

Das Skript, das von init aus aufgerufen wird, sorgt dafür, dass /dev/mapper/control existiert. Hier ist es:

# vi ramdisk/sbin/devmap_mknod.sh
#!/bin/sh

# Startup script to create the device-mapper control device
# on non-devfs systems.
# Non-zero exit status indicates failure.
DM_DIR="mapper"
DM_NAME="device-mapper"

set -e

DIR="/dev/$DM_DIR"
CONTROL="$DIR/control"

# Check for devfs, procfs
if test -e /dev/.devfsd ; then
        echo "devfs detected: devmap_mknod.sh script not required."
        exit
fi
if test ! -e /proc/devices ; then
        echo "procfs not found; please create $CONTROL manually."
        exit 1
fi
# Get major, minor, and mknod
MAJOR=$(sed -n 's/^ *\([0-9]\+\) \+misc$/\1/p' /proc/devices)
MINOR=$(sed -n "s/^ *\([0-9]\+\) \+$DM_NAME\$/\1/p" /proc/misc)

if test -z "$MAJOR" -o -z "$MINOR" ; then
        echo "$DM_NAME kernel module not loaded: can't create $CONTROL."
        exit 1
fi

mkdir -p --mode=755 $DIR
test -e $CONTROL && rm -f $CONTROL

echo "Creating $CONTROL character device with major:$MAJOR minor:$MINOR."
mknod --mode=600 $CONTROL c $MAJOR $MINOR

Jetzt müssen wir das image noch packen und nach /boot verschieben

# umount ramdisk
# rmdir ramdisk
# gzip initrd
# mount /boot
# mv initrd.gz /boot

[Bearbeiten] grub.conf

Jetzt muss noch der bootloader angepasst werden. Ein neuer Eintrag root(..) entsprechend anpassen:

# vi /boot/grub/grub.conf
title=Verschlüsselte root-Partition
root (hd0,0)
kernel /deinkernel root=/dev/ram0 rw
initrd /initrd.gz
boot
# umount /boot

[Bearbeiten] Software-Suspend

Um Software-Suspend mit verschlüsselter root-Partition sinnvoll und sicher nutzen zu können, muss natürlich auch die swap-Partition, in der das Speicherabbild abgelegt wird, ebenfalls verschlüsselt sein, da sonst dort der Schlüssel im Klartext gesichert wird. Anders als weiter unten beschrieben muss die Partition aber mit einem Passwort, welches man kennt, verschlüsselt werden (sinnvollerweise mit dem selben Passwort, wie die root-Partition) - ansonsten ist das Laden des Speicherabbildes nicht mehr möglich.

Zusätzlich muss in die initrd in das Verzeichnis /sbin das Programm resume samt der benötigten Bibliotheken aus dem sys-power/suspend Paket. Die entsprechende Konfigurationsdatei (das mapper-Device als resume device eintragen) uswsusp.conf muss auch in die initrd und zwar in das Verzeichnis /etc. Nun ist noch das oben beschriebene Initscript so zu modifizieren, dass es

  1. zunächst die swap-Partition mit dem eingegebenen Passwort entschlüsselt
  2. resume aufruft
  3. wenn resume nicht funktioniert, weil vorher kein suspend gemacht wurde einfach normal fortfährt

Wenn man für swap- und root-Partition dasselbe Passwort verwendet, kann das Passwort ohne weitere Nachfrage auch für die root-Partition verwendet werden.

  • Nicht vergessen dass das reale Gerät (z.B. /dev/hda6) der swap-Partition auch in /dev vorhanden sein muss
  • resume kann bedenkenlos aufgerufen werden, auch wenn gar kein suspend vorausging (falls resume fehlschlägt, läuft das script normal weiter, ansonsten wird dort abgebrochen und nur resume ausgeführt)

[Bearbeiten] Ergebnis

Jetzt sollte das System nach dem Start nach dem Schlüssel fragen, damit die root-Partition mounten und von dort booten. Das Passwort sollte man sich natürlich sehr gut merken...

Bei der Passworteingabe beim Booten ist noch kein deutscher Tastaturtreiber geladen! Das bezieht sich nicht nur auf das bekannte Z/Y-Problem, sondern auch auf diverse Nichtwortzeichen. Um die zu finden, muss man seine US-Tastatur-Belegung schon ganz schön gut kennen, bei ner deutschen Tastatur!

'Persönliche Werkzeuge