Kühlen Kopf behalten.
Systeme für optimalen Workflow.

-

systematrix entwickelt die webbasierten Anwendungen in einer LAMP-Umgebung: Linux, Apache, MySQL und PHP.

Unsere Entwickler sind Experten für diese Systeme.

Verschlüsselung am Linux-Arbeitsplatz

loop-AES verschlüsseltes root- und swap-Filesystem

Anleitung für Ubuntu 22 / Linux Mint 21

von Sven Palme

Wenn das bisherige Linux-System auf dem Desktop-PC in die Jahre gekommen ist und eine Aktualisierung bevorsteht, empfiehlt es sich, beim Umstieg auf das neue System gleich eine Verschlüsselung (swap und root) über loop-AES einzurichten. Wir haben uns erneut für Linux Mint - MATE entschieden (alter Beitrag hier):

32 GB sollten es mindestens sein

Die Installation von Linux Mint 21 benötigt ca. 16GB. Für eine erfolgreiche Kernelkompilierung benötigen wir jedoch mindestens 32GB, so dass wir uns für 32GB als minimale Anforderung entschieden haben. Da wir später auch die root-Partition verschlüsseln wollen und heutige Festplatten deutlich mehr Speicherplatz aufweisen, zeigt folgendes grobes Schema, wie eine Platte aufgeteilt werden kann.

Partition

Größe

Verwendung

Dateisystem

/dev/sda1

1GB

Linux Boot

Linux

/dev/sda2

4GB

Linux Swap

Linux Swap / Solaris

/dev/sda3

64GB-Rest

Linux Root

Linux

/dev/sda4

32-64GB

Linux Test

Linux

Nach erfolgter Partitionierung entscheiden wir uns bei der Installation für /dev/sda4 als / und /dev/sda1 als /boot Partition.

sda2 als Swap kann entfallen - da es fast immer unnötig ist und bei Speickerlecks im Firefox zu Problemen führt.

loop-AES

Für die Verschlüsselung benutzen wir loop-AES. Dieses Verfahren erzwingt ein modifiziertes mount, umount und losetup sowie ein eigenes loop-Modul für den Kernel. Die modifizierten Programme werden leider nicht mehr direkt zur  Verfügung gestellt. Aber wir zeigen wie es geht.

Der Kernel muß wie immer neu gebaut werden, aufgrund der festen Integration des loop-Moduls.

Wir holen uns die Sourcen von https://sourceforge.net/projects/loop-aes/

Aktuell: /loop-aes/v3.8e/loop-AES-v3.8e.tar.bz2

Kernel bauen

Es werden einige zusätzliche Pakete benötigt. Da wir ab hier die ganze Zeit als root arbeiten, setzen wir es mittels sudo su -.

sudo su -
apt-get install abiword-common abiword apache2
apt-get install mariadb-server
apt-get install virualbox
apt-get install vlc
apt-get install lbzip2
apt-get install ssh smartmontools
apt-get install traceroute
apt-get install php
apt-get install python*
apt-get install python-dev
apt-get build-dep linux-image-$(uname -r)
apt-get build-dep linux
apt-get install git-core
apt-get install libelf-dev asciidoc binutils-dev
apt-get install libudev-dev
apt-get install libpci-dev
apt-get install libpci*
apt-get install xmlto
apt-get install openssl
apt-get install openssl-dev
apt-get install libopenssl-dev
apt-get install python-pip python-dev libffi-dev libssl-dev libxml2-dev libxslt1-dev libjpeg8-dev zlib1g-dev
apt-get install libpython-dev
apt-get install fakeroot build-essential devscripts
apt-get install crash kexec-tools makedumpfile kernel-wedge
apt-get install dh-make
apt-get install dh-system*
apt build-dep -y linux
apt install -y libncurses5-dev
apt-get install -y devscripts libsqlite3-dev

Wir holen uns nun die Kernelsource von https://www.kernel.org/ und packen diese aus und konfigurieren es so, dass kein "loop" dabei ist.

cd /usr/src/
wget 'https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.11.10.tar.xz'
tar -xf linux-6.11.10.tar.xz
cd linux-6.11.10
make menuconfig

Der letzte Befehl bring ins Kernel-Setup wo wir uns durchhangeln über Device Driver -> Block devices

und hier zum Loopback device support

Es muss sowohl das Loopback device und die Cryptoloop deacktviert werden - und speichern nicht vergessen!

Und dann sollten wir um Platz zu sparen unbeding auch das Debugging abschalten:

 

Und speichern nicht vergessen!

Dann können wir den Kern kompilieren (-j8 nutzt 8 Kerne unserer CPU)

make -j8
make -j8 modules
make -j8 modules_install
make -j8 bzImage

 Das bzImage müssen wir nun noch boot bekommen:

cp /usr/src/linux-6.11.10/arch/x86_64/boot/bzImage /boot/vmlinuz-6.11.10
cp /usr/src/linux-6.11.10/System.map-6.11.10 /boot/
cp /usr/src/linux-6.11.10/config-6.11.10 /boot/

Wenn wir die Option für debug_infos nicht disabled haben - alle Module mit debug_symbolen versehen die wir nicht brauchen - und vor allem stören, wenn wir die initrd bauen - also kommen die so weg:

 find /lib/modules/6.11.10/ -iname "*.ko" -exec strip --strip-debug {} \;

Erstellung des Kernelmoduls Loop

Gute Hilfetellung finden wir in der README.

sudo su -
cd /usr/src
wget 'https://sourceforge.net/projects/loop-aes/files/loop-aes/v3.8e/loop-AES-v3.8e.tar.bz2/download'
tar -xvjf loop-AES-v3.8e.tar.bz2
cd loop-AES-v3.8e
make clean && make KEYSCRUB=y LINUX_SOURCE=/usr/src/linux-6.11.10/
cd ..

Wir brauchen Teile der util-linux

Damit die loop-devices gemountet werden können braucht es ein paar tools die wir neu komplieren müssen. Daher holen wir uns die util-linux von https://www.kernel.org/pub/linux/utils/util-linux/

sudo su -
cd /usr/src
wget 'https://www.kernel.org/pub/linux/utils/util-linux/v2.40/util-linux-2.40.2.tar.xz'
tar -xf util-linux-2.40.2.tar.xz
cd util-linux-2.40.2
patch -p1 < ../loop-AES-v3.8e/util-linux-2.40.2.diff
CFLAGS="-O2 -Wall" ./configure --disable-shared --enable-static --disable-pylibmountstatic-rnd=linux
make clean && make
cd ..

Da bei Paket-updates manchmal dieses Paket auch angefasst wird sollten wir ein kleines Script bereitstellen welches und alle Programme an die richtige Stelle kopiert

#!/bin/bash
cp /usr/src/util-linux-2.40.2/mount /bin/
cp /usr/src/util-linux-2.40.2/umount /bin/
cp /usr/src/util-linux-2.40.2/losetup /sbin/
cp /usr/src/util-linux-2.40.2/swapon /sbin/
cp /usr/src/util-linux-2.40.2/swapoff /sbin/

Vorher sollte man ggf. die originalen mounts/umounts sich sichern - aber das macht man ja nur einmal.

Wir brauchen ein statisches gpg

Für die Verschlüsselung der root-Partition und dem Entschlüsseln des Keyfiles brauchen wir ein im "initrd" sitzendes statisches gpg. Dies bauen wir uns auch schnell:

sudo su -
cd /usr/src
wget https://gnupg.org/ftp/gcrypt/gnupg/gnupg-1.4.23.tar.bz2
tar -xvjf gnupg-1.4.23.tar.bz2
cd gnupg-1.4.23
patch -p1 < ../loop-AES-v3.8e/gnupg-1.4.23.diff
CFLAGS="-O2 -fcommon" LDFLAGS="-static -s -lrt -fcommon" ./configure --prefix=/usr --enable-static-rnd=linux
make clean && make
cd ..

Ein Schlüssel muss her

Zuerst brauchen wir aber noch den eigentlichen Schlüssel, den wir als /boot/rootkey.gpg ablegen, wobei hier die gängigen Regeln für das Vergeben von Passwörtern/ Schlüsseln gelten. Etwas wie "geheim" ist denkbar schlecht. Besser wäre etwas wie "elake8ipus98", allerdings kaum zu merken. Längere Sätze wie "Luke, ich bin dein Vater" mögen zwar schwieriger wirken, sind es aber, aufgrund der Eingängigkeit der Zitate, nicht - so lange man sie für sich selbst nachvollziehbar verändert. Vielleicht wäre "Darth, ich bin dein Sohn" besser, aber nach meiner Veröffentlichung jetzt nicht mehr... Das Passwort sollte leicht zu merken sein, eine Länge von mindestens 16 Zeichen haben, wobei unbedingt der gesamte Zeichensatz benutzt werden sollte.

Der folgende Befehl braucht sehr lange. Schneller geht es mit /dev/urandom. Natürlich machen wir uns vorher wieder zu root.

sudo su -
head -c 3705 /dev/random | uuencode -m - | head -n 66 | tail -n 65 | gpg --symmetric -a > /boot/rootkey.gpg

Eintrag in /etc/fstab anlegen:

/dev/sda3 /mnt ext3 defaults,noauto,loop=/dev/loop3,encryption=AES256,gpgkey=/boot/rootkey.gpg 0 0

Jetzt können wir die Partition endlich verschlüsselt formatieren und unser aktuelles System darauf kopieren.

depmod -a
modprobe Loop
losetup -F /dev/loop3
mkfs.ext3 -j /dev/loop3
losetup -d /dev/loop3
mount /dev/sda3
rsync -vaH --exclude "/boot/*" --exclude "/mnt/*" --exclude "/sys/*" --exclude "/proc/*" --exclude "/dev/*" --exclude "/run/*" / /mnt

Wir ändern die /mnt/etc/fstab auf dem gerade kopierten Image (denn das wird ja unsere neue Root-Platte) und sorgen hierbei auch gleich dafür, dass die Swap-Partion (hier sda2) verschlüsselt wird.

# Ersetze den ROOT Eintrag durch diesen
/dev/loop3          /       ext3    errors=remount-ro                    0 1
# Ersetze den SWAP Eintrag durch diesen
/dev/sda2           swap    swap    sw,loop=/dev/loop2,encryption=AES256 0 0

Eine neue initrd

Wir legen uns ein Original der initrd zurecht:

rm -rf initrd 2>/dev/null
mkdir initrd
unmkinitramfs /boot/initrd.img-5.15.0-76-generic initrd

Nun kopieren wir die benötigten Dateien hinein.

cd initrd/main
cp -f /boot/rootkey.gpg .
mv sbin/losetup sbin/losetup.noaes
cp -f /sbin/losetup sbin
mv bin/mount bin/mount.noaes
cp -f /bin/mount bin
cp -f /usr/src/gnupg-1.4.23/g10/gpg bin
touch pubring.gpg
touch secring.gpg
rsync /usr/lib/modules/6.11.10 lib/modules

Nun müssen wir noch dafür sorgen das auch wirrklich loopaes benutzt wird. Dafür gehen wir nach initrd/main/scripts/local-top/
und erzeigen die Datei loopaes mit folgendem Inhalt:

#!/bin/sh
echo "load loop"
modprobe loop
while ! [ -b /dev/loop3 ]; do
  sleep 1
  echo "wait for device"
done
echo "wait for passwd"
while [ true ]; do
  if ! /sbin/losetup -e AES256 -I 0 -K /rootkey.gpg -G / /dev/loop3 /dev/sda3 ; then
    echo "try again"
    continue
  fi
  break
done
echo "ROOT=\"/dev/loop3\"" >> /conf/param.conf

Ich habe loop3 ausgewählt, weil sda3 auch unsere Root-Partion sein soll. Neben dieser Datei  die mittels chmod a+x loopaes auch ausführbar sein sollte, müssen wir noch in der Datei ORDER ergänzen. Dort fügen wir an:

/scripts/local-top/loopaes "$@"
[ -e /conf/param.conf ] && . /conf/param.conf

Wen bestimmte Hardware nicht erkannt wird (z.b. WLAN bei deuen e100 Boxen) fehlt in der Regel die Firmware für diese Hardware.
Mitteles dmesg kann man sich dann das bootlog ansehen und die fehlende Firmware dann entsprechend nach: /usr/src/initrd/main/lib/firmware schieben (nicht alles von /usr/lib/firmware !).

Mit dieser Abfolge von Befehlen erzeugen wir eine neue initrd mit dem Namen sda3initrd

cd initrd
# Add the first microcode firmware
# --------------------------------
cd early
find . -print0 | cpio --null --create --format=newc > /usr/src/sda3initrd
# Add the second microcode firmware
# ---------------------------------
cd ../early2
find kernel -print0 | cpio --null --create --format=newc >> /usr/src/sda3initrd
# Add the ram fs file system
# --------------------------
cd ../main
find . | cpio --create --format=newc | xz --format=lzma >> /usr/src/sda3initrd

Da wir das ggf. öfter machen wollen, können wir diese Zeilen auch in eine Datei schreiben (executabel). die sd2initrd sollten wir nun noch /boot / kopieren

Jetzt fehlt uns nur noch ein Eintrag in der /boot/grub/grub.cfg

menuentry 'Linux Mint 21.2 MATE, with Linux 6.11.10 SDA3' --class linuxmint --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-6.11.10-aes' {
        recordfail
        load_video
        gfxmode $linux_gfx_mode
        insmod gzio
        if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 f155d049-0c06-4bfc-81bb-a9587240e3fe
        else
          search --no-floppy --fs-uuid --set=root f155d049-0c06-4bfc-81bb-a9587240e3fe
        fi
        echo    'Loading Linux 6.11.10 ...'
        linux   /vmlinuz-6.11.10 root=UUID=f155d049-0c06-4bfc-81bb-a9587240e3fe ro nosgx
        echo    'Loading initial ramdisk ...'
        initrd  /sda3initrd
}

Die UUID: f155d049-0c06-4bfc-81bb-a9587240e3fe ist unsere /boot/ Partition - das root-Device haben wir mittels Script ja hart auf sda3 gesetzt - ist hier also egal.

Jetzt sind wir fertig und können neu booten.

Alle genannten Befehle dienen als Anregung - es selber zu versuchen. Bei Fehlermeldungen kann nur der eigene Verstand oder zur Not Mister "google" helfen.

Habt immer ein Backup und eine Install-CD, um im Notfall  zu reparieren!