KVM QEMU und LUKS

reinhard@finalmedia.de Wed 06 Oct 2021 04:03:16 PM CEST # KVM Hypervisor mit Qemu und einem vollverschlüsselten LUKS Plattenimage betreiben # Das Plattenimage wird dabei von qemu unabhängig vom Gast-Betriebsystem vollverschlüsselt.

Beispiel: qemu host unter debian (host), alpine linux als gast

qemu unter debian installieren


apt-get update

# QEMU installieren
apt-get install qemu-system qemu-kvm

# kvm modul laden
modeprobe kvm

Variablendefinition. Hier sind Pfade ggf. anzupassen

keyfile="~/test_key_file.luks.secret.key"
imagefile="/mnt/pfad_zu_externem_host/container20G.luks.img"
imagesize="20G"

Eine Schlüsseldatei mit einem 32 stelligen Zufallskennwort erstellen. (Wir lassen Zeichen aus, die ggf. verwechselbar sind: O,0,1,I,i,l)

umask 077 && tr -dc "0-9a-zA-Z" < /dev/urandom | tr -d "01iloO" | head -c 32 > "$keyfile"

Ein leeres LUKS Disk Image erstellen.

Hinweis: Wird übrigens als Sparse-File erstellt, belegt also nicht von Anfang an fix 20 GB Speicherplatz auf der Platte, wird aber als 20GB alloziert.

qemu-img create -f luks \
--object secret,id=sec0,file="$keyfile" \
-o key-secret=sec0 "$imagefile" "$imagesize"

# Hier wird dir angezeigt werden, dass der volle speicherplatz alloziert ist
ls -lh "$imagefile"

# hiermit kannst du sehen, was die imagedatei wirklich auf der platte an Speicherplatz belegt
du -h "$imagefile"

Damit haben wir ein LUKS-Container erstellt, der mit dem in der keyfile hinterlegten schlüssel verschlüsselt ist.

Die keyfile verbleibt lokal und muss geschützt werden. Die container.luks.img kann man unproblematisch auf einem host ablegen, z.B. einem netshare.

Beispielhaft qemu starten, 2 GB RAM und in die beispiel.iso booten, um dann ein Betriebsystem im Image zu installieren



# beispiel iso herunterladen
wget https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-virt-3.14.2-x86_64.iso

# qemu mit verschluesselter hdd image starten und in iso booten
qemu-system-x86_64 -enable-kvm \
-cpu host -smp cores=2 -m 2048 \
-object secret,id=sec0,file="$keyfile" \
-device ahci,id=ahci \
-drive if=none,id=drive0,driver=luks,key-secret=sec0,file="$imagefile" \
-device ide-drive,bus=ahci.0,drive=drive0 \
-vga qxl -sandbox on -usb -k de -monitor /dev/null \
-cdrom alpine-virt-3.14.2-x86_64.iso

Dann in alpine linux einloggen mit benutzer root und leerem kennwort. Im Anschluss das setup ausführen und dem Dialog folgen:

apk update
apk add e2fsprogs
setup-alpine
setup-disk
poweroff

Damit ist die VM wieder beendet. Wir vergewissern uns, dass es sich um ein verschlüsseltes Container Image handelt:

# wir vergewissern uns...
file demo.luks.img

...: LUKS encrypted file, ver 1 [aes, xts-plain64, sha256] UUID: 072a3b80-26bd-11ec-9b49-f33511a6654c ...

# alternativ hexdump des images ansehen

hd demo.luks.img | head -n 20

Die VM ist nun so startbar:


qemu-system-x86_64 -enable-kvm \
-cpu host -smp cores=2 -m 2048 \
-object secret,id=sec0,file="$keyfile" \
-drive if=none,id=drive0,driver=luks,key-secret=sec0,file="$imagefile" \
-device ide-drive,drive=drive0 \
-vga qxl -sandbox on -usb -k de -monitor /dev/null

alternativ kann das secret auch von stdin gelesen werden, oder beim start abgefragt werden.

Einloggen in alpine linux und noch die Installation abschließen, sowie auf edge upgraden:

cat << +++EOF+++ > /etc/apk/repositories
http://dl-cdn.alpinelinux.org/alpine/edge/main
http://dl-cdn.alpinelinux.org/alpine/edge/community
#http://dl-cdn.alpinelinux.org/alpine/edge/testing
+++EOF+++
apk update
apk upgrade

# jetzt noch ein paar basics nachinstallieren
apk add nano htop wireguard-tools

# und noch einen user anlegen
adduser user
su user
cd
whoami