Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – IX – Verschlüsselter SWAP

Ich setze meinen Ausflug in das Setup eines Opensuse Laptops mit Voll-Verschlüsselung fort:

Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – I – Vorüberlegungen
Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – II – Vorüberlegungen zur Virtualisierung
Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – III – Zugriffs-Layer
Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – IV – Disk-Layout
Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – V – kryptierte Partitionen und Alignment
Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – VI – Key-Slots, PBKDF2- und MK-Iterationen
Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – VII – Grundinstallation für LUKS on LVM
Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – VIII – Systemd-Fehler nach Neustart

Die Leser der bisherigen Artikel erinnern sich sicher daran, dass ich während der Installation von Leap 15 auf einem verschlüsselten LUKS-Volume vermieden hatte, ein ebenfalls verschlüsseltes SWAP-Volume einzubinden. Der SWAP wird weder in der Grub2-Konfiguration, noch in der "/etc/fstab" oder der "/etc/crypttab" des Root-Filesystems der Installation referenziert. Wir werden dies nun nachträglich ändern.

Wir schließen unseren Laptop ans LAN an und booten die Leap 15-Installation von unserem verschlüsselten LUKS-Volume "/dev/vga/lva1" (LUKS on LVM) auf der externen SSD. Da wir während der Installation bereits den SSH-Service aktivieren ließen und die lokale Firewall deaktivierten, können wir uns nun bequemerweise von einem externen System einloggen. Wem das nicht möglich ist, muss halt an einem Konsolen-Terminal des Laptops arbeiten. Uns steht im Moment noch kein grafischer Desktop zur Verfügung; Arbeiten auf der Kommandozeile ist notwendig. FS steht nachfolgend wie immer für "Filesystem".

Check der Datei "/boot/grub2/grub.cfg"

Ich zeige nachfolgend die komplette Datei "/boot/grub2/grub.cfg", wie sie als Ergebnis unserer Installation angelegt wurde.
Hinweis: Ich erinnere dabei daran, dass wir keine separate Partition oder separates Volume für den Verzeichnis-Ast "/boot" angelegt hatten. "/boot" und seine Inhalte stellen vielmehr echte Inodes im "/"-FS dar.

#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub2-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
if [ -f ${config_directory}/grubenv ]; then
  load_env -f ${config_directory}/grubenv
elif [ -s $prefix/grubenv ]; then
  load_env
fi

if [ "${env_block}" ] ; then
  load_env -f "${env_block}"
fi

if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   if [ "${env_block}" ] ; then
     save_env -f "${env_block}" next_entry
   fi
   set boot_once=true
else
   set default="${saved_entry}"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi

function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
    if [ "${env_block}" ] ; then
      save_env -f "${env_block}" saved_entry
    fi

  fi
}

function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}

if [ x$feature_default_font_path = xy ] ; then
   font=unicode
else
insmod part_gpt
insmod lvm
insmod cryptodisk
insmod luks
insmod gcry_rijndael
insmod gcry_rijndael
insmod gcry_sha512
insmod ext2
cryptomount -u db43615a23e2512549c1ccbc2041e76c
set root='cryptouuid/db43615a23e2512549c1ccbc2041e76c'
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=root --hint='cryptouuid/db43615a23e2512549c1ccbc2041e76c'  a3202dac-a44e-4344-b551-dd123ce893b2
else
  search --no-floppy --fs-uuid --set=root a3202dac-a44e-4344-b551-dd123ce893b2
fi
    font="/usr/share/grub2/unicode.pf2"
fi

if loadfont $font ; then
  set gfxmode=auto
  load_video
  insmod gfxterm
fi

terminal_output gfxterm
insmod part_gpt
insmod lvm
insmod cryptodisk
insmod luks
insmod gcry_rijndael
insmod gcry_rijndael
insmod gcry_sha512
insmod ext2
cryptomount -u db43615a23e2512549c1ccbc2041e76c
set root='cryptouuid/d4f0ba2b904b4a73ba2927474433c740'
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=root --hint='cryptouuid/db43615a23e2512549c1ccbc2041e76c'  a3202dac-a44e-4344-b551-dd123ce893b2
else
  search --no-floppy --fs-uuid --set=root a3202dac-a44e-4344-b551-dd123ce893b2
fi
insmod gfxmenu
loadfont ($root)/boot/grub2/themes/openSUSE/DejaVuSans-Bold14.pf2
loadfont ($root)/boot/grub2/themes/openSUSE/DejaVuSans10.pf2
loadfont ($root)/boot/grub2/themes/openSUSE/DejaVuSans12.pf2
loadfont ($root)/boot/grub2/themes/openSUSE/ascii.pf2
insmod png
set theme=($root)/boot/grub2/themes/openSUSE/theme.txt
export theme

if [ x${boot_once} = xtrue ]; then
  set timeout=0
elif [ x$feature_timeout_style = xy ] ; then
  set timeout_style=menu
  set timeout=8
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
  set timeout=8
fi
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/00_tuned ###
set tuned_params=""
set tuned_initrd=""
### END /etc/grub.d/00_tuned ###

### BEGIN /etc/grub.d/10_linux ###
menuentry 'openSUSE Leap 15.0'  --class opensuse --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-a3202dac-a44e-4344-b551-dd123ce893b2' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod part_gpt
        insmod lvm
        insmod cryptodisk
        insmod luks
        insmod gcry_rijndael
        insmod gcry_rijndael
        insmod gcry_sha512
        insmod ext2
        cryptomount -u db43615a23e2512549c1ccbc2041e76c
        set root='cryptouuid/db43615a23e2512549c1ccbc2041e76c'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint='cryptouuid/db43615a23e2512549c1ccbc2041e76c'  a3202dac-a44e-4344-b551-dd123ce893b2
        else
          search --no-floppy --fs-uuid --set=root a3202dac-a44e-4344-b551-dd123ce893b2
        fi
        echo    'Loading Linux 4.12.14-lp150.11-default ...'
        linux   /boot/vmlinuz-4.12.14-lp150.11-default root=/dev/mapper/cr-root  nomodeset splash=silent quiet showopts
        echo    'Loading initial ramdisk ...'
        initrd  /boot/initrd-4.12.14-lp150.11-default
}
submenu 'Advanced options for openSUSE Leap 15.0' --hotkey=1 $menuentry_id_option 'gnulinux-advanced-a3202dac-a44e-4344-b551-dd123ce893b2' {
        menuentry 'openSUSE Leap 15.0, with Linux 4.12.14-lp150.11-default' --hotkey=2 --class opensuse --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.12.14-lp150.11-default-advanced-a3202dac-a44e-4344-b551-dd123ce893b2' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod part_gpt
                insmod lvm
                insmod cryptodisk
                insmod luks
                insmod gcry_rijndael
                insmod gcry_rijndael
                insmod gcry_sha512
                insmod ext2
                cryptomount -u db43615a23e2512549c1ccbc2041e76c
                set root='cryptouuid/db43615a23e2512549c1ccbc2041e76c'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root --hint='cryptouuid/db43615a23e2512549c1ccbc2041e76c'  a3202dac-a44e-4344-b551-dd123ce893b2
                else
                  search --no-floppy --fs-uuid --set=root a3202dac-a44e-4344-b551-dd123ce893b2
                fi
                echo    'Loading Linux 4.12.14-lp150.11-default ...'
                linux   /boot/vmlinuz-4.12.14-lp150.11-default root=/dev/mapper/cr-root  nomodeset splash=silent quiet showopts
                echo    'Loading initial ramdisk ...'
                initrd  /boot/initrd-4.12.14-lp150.11-default
        }
        menuentry 'openSUSE Leap 15.0, with Linux 4.12.14-lp150.11-default (recovery mode)' --hotkey=3 --class opensuse --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.12.14-lp150.11-default-recovery-a3202dac-a44e-4344-b551-dd123ce893b2' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod part_gpt
                insmod lvm
                insmod cryptodisk
                insmod luks
                insmod gcry_rijndael
                insmod gcry_rijndael
                insmod gcry_sha512
                insmod ext2
                cryptomount -u db43615a23e2512549c1ccbc2041e76c
                set root='cryptouuid/db43615a23e2512549c1ccbc2041e76c'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root --hint='cryptouuid/db43615a23e2512549c1ccbc2041e76c'  a3202dac-a44e-4344-b551-dd123ce893b2
                else
                  search --no-floppy --fs-uuid --set=root a3202dac-a44e-4344-b551-dd123ce893b2
                fi
                echo    'Loading Linux 4.12.14-lp150.11-default ...'
                linux   /boot/vmlinuz-4.12.14-lp150.11-default root=/dev/mapper/cr-root  
                echo    'Loading initial ramdisk ...'
                initrd  /boot/initrd-4.12.14-lp150.11-default
        }
}

### END /etc/grub.d/10_linux ###

### BEGIN /etc/grub.d/20_linux_xen ###

### END /etc/grub.d/20_linux_xen ###

### BEGIN /etc/grub.d/20_memtest86+ ###
### END /etc/grub.d/20_memtest86+ ###

### BEGIN /etc/grub.d/30_os-prober ###
### END /etc/grub.d/30_os-prober ###

### BEGIN /etc/grub.d/40_custom ###
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
### END /etc/grub.d/40_custom ###

### BEGIN /etc/grub.d/41_custom ###
if [ -f  ${config_directory}/custom.cfg ]; then
  source ${config_directory}/custom.cfg
elif [ -z "${config_directory}" -a -f  $prefix/custom.cfg ]; then
  source $prefix/custom.cfg;
fi
### END /etc/grub.d/41_custom ###

### BEGIN /etc/grub.d/80_suse_btrfs_snapshot ###
### END /etc/grub.d/80_suse_btrfs_snapshot ###
### BEGIN /etc/grub.d/90_persistent ###
### END /etc/grub.d/90_persistent ###

### BEGIN /etc/grub.d/95_textmode ###
### END /etc/grub.d/95_textmode ###

Wir sehen, wie die Konfigurationen der einzelnen Boot-Einträge zunächst dafür sorgen, dass notwendige Module geladen werden. Wir betrachten nachfolgend nurmehr den Haupteintrag des grafischen Boot-Menüs von Grub2 genauer; dafür durchgeführte Modifikationen sind analog auf andere Einträge zu übertragen:

menuentry 'openSUSE Leap 15.0'  --class opensuse --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-a3202dac-a44e-4344-b551-dd123ce893b2' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod part_gpt
        insmod lvm
        insmod cryptodisk
        insmod luks
        insmod gcry_rijndael
        insmod gcry_rijndael
        insmod gcry_sha512
        insmod ext2
        cryptomount -u db43615a23e2512549c1ccbc2041e76c
        set root='cryptouuid/db43615a23e2512549c1ccbc2041e76c'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint='cryptouuid/db43615a23e2512549c1ccbc2041e76c'  a3202dac-a44e-4344-b551-dd123ce893b2
        else
          search --no-floppy --fs-uuid --set=root a3202dac-a44e-4344-b551-dd123ce893b2
        fi
        echo    'Loading Linux 4.12.14-lp150.11-default ...'
        linux   /boot/vmlinuz-4.12.14-lp150.11-default root=/dev/mapper/cr-root  nomodeset splash=silent quiet showopts 
        echo    'Loading initial ramdisk ...'
        initrd  /boot/initrd-4.12.14-lp150.11-default
}

Für die Adressierung des Krypto-Volumes (= Raw-LVM-Volume) werden hier offenbar UUIDs verwendet. Die Krypto-UUID ist in unserem Fall "db43615a23e2512549c1ccbc2041e76c" (=db43615a-23e2-5125-49c1-ccbc2041e76c), die UUID des root-Filesystems dagegen "a3202dac-a44e-4344-b551-dd123ce893b2". Wir erkennen, dass das Krypto-Device von Grub2 angesprochen wird. Im Boot-Vorgang wird die entsprechende Passphrase abgefragt. Auf dem entschlüsselten Device wird dann das "/"-FS anhand seiner UUID identifiziert.

Später erkennen wir an der Zeile

linux   /boot/vmlinuz-4.12.14-lp150.11-default   root=/dev/mapper/cr-root   nomodeset   splash=silent   quiet   showopts

welcher Kernel aus dem Verzeichnis "boot" gestartet wird. (Die Option "nomodeset" resultierte übrigens aus der Grafik-Einstellung (Keine KMS), die wir zu Beginn der Installation getroffen hatten.)

Interessant ist hier, dass dem Kernel das "root"-Filesystem über seine Mapper-Kennung "dev/mapper/cr-root" übergeben wird. Das geht nur, wenn der Kernel über die Datei "etc/crypttab" herausfinden kann, welches Device da eigentlich gemappt wurde. Ich erinnere daran, dass diese Datei bislang den alleinigen Eintrag

cr-root    /dev/vga/lva1    none

beinhaltet. Das reicht jedoch, da ein (ggf. aus dem initramfs) geladenes LVM-Kernel-Modul auf dieser Basis das zugehörige Device eindeutig identifizieren kann.

Modifikation der Dateien "/boot/grub2/grub.cfg" und "/etc/default/grub"

Damit ist unsere Strategie klar, wie Grub2 dem Kernel das SWAP-Device (für Reboots aus einem Hibernation-Zustand) bekannt geben kann. Wir versehen die Zeilen für den Kernel in allen Menü-Optionen (bis auf den Recovery-Eintrag) mit einem "resume"-Parameter der folgenden Form:

linux    /boot/vmlinuz-4.12.14-lp150.11-default   root=/dev/mapper/cr-root   nomodeset splash=silent   quiet   showopts   resume=/dev/mapper/cr-swap

Die Editier-Arbeit führen wir direkt und vorsichtig mit dem vi-Editor durch. Nur Mut!

Hinweis: Wem das zu unsicher ist, führt statt dessen die nachfolgenden Schritte durch und führt am Ende

grub2-mkconfig -o /boot/grub2/grub.cfg

durch.

Wir passen in diesem Sinne nun auch die folgende Zeile in der Datei "/etc/default/grub" an:

GRUB_CMDLINE_LINUX_DEFAULT='nomodeset splash=silent quiet showopts resume=/dev/mapper/cr-swap'

Also:

linux-5l8q:~ # cat /etc/default/grub
# If you change this file, run 'grub2-mkconfig -o /boot/grub2/grub.cfg' afterwards to update
# /boot/grub2/grub.cfg.

# Uncomment to set your own custom distributor. If you leave it unset or empty, the default
# policy is to determine the value from /etc/os-release
GRUB_DISTRIBUTOR=
GRUB_DEFAULT=saved
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=8
GRUB_CMDLINE_LINUX_DEFAULT='nomodeset splash=silent quiet showopts resume=/dev/mapper/cr-swap'
GRUB_CMDLINE_LINUX=""

# Uncomment to automatically save last booted menu entry in GRUB2 environment

# variable `saved_entry'
# GRUB_SAVEDEFAULT="true"
#Uncomment to enable BadRAM filtering, modify to suit your needs

# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
# GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"
#Uncomment to disable graphical terminal (grub-pc only)

GRUB_TERMINAL="gfxterm"
# The resolution used on graphical terminal
#note that you can use only modes which your graphic card supports via VBE

# you can see them in real GRUB with the command `vbeinfo'
GRUB_GFXMODE="auto"
# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
# GRUB_DISABLE_LINUX_UUID=true
#Uncomment to disable generation of recovery mode menu entries

# GRUB_DISABLE_LINUX_RECOVERY="true"
#Uncomment to get a beep at grub start

# GRUB_INIT_TUNE="480 440 1"
GRUB_BACKGROUND=
GRUB_THEME=/boot/grub2/themes/openSUSE/theme.txt
SUSE_BTRFS_SNAPSHOT_BOOTING="true"
GRUB_DISABLE_OS_PROBER="false"
GRUB_ENABLE_CRYPTODISK="y"
GRUB_CMDLINE_XEN_DEFAULT="vga=gfx-1024x768x16"

Abänderung der Dateien "/etc/crypttab" und "/etc/fstab" // Mounten des SWAPs

Damit das alles funktioniert benötigen wir aber auch entsprechende konsistente Einträge in der "/etc/crypttab" und in der "/etc/fstab". Wir erweitern zunächst die "/etc/crypttab" mittels des vi-Editors:

cr-root    /dev/vga/lva1    none
cr-swap    /dev/vgs/lvs1   none

Wir hatten den SWAP ja auf einem separaten RAW-Volume "/dev/vgs/lvs1" angelegt. Nun müssen wir dafür sorgen, dass der SWAP nach dem Booten auch gemountet wird. Ein Blick in die "/etc/fstab" zeigt, dass SuSE dort UUIDs verwendet.

UUID=a3202dac-a44e-4344-b551-dd123ce893b2   /   ext4 acl,user_xattr   0 1

Achtung: das sind die UUIDs der Filesysteme. Wie finden wir die UUID für das Swap-Device heraus? Wir öffnen des kryptierte SWAP-Volume mittels

 
linux-5l8q:~ # cryptsetup open /dev/vgs/lvs1 cr_swap
Enter passphrase for /dev/vgs/lvs1:
linux-5l8q:~ # lsblk -o name,UUID | grep "swap\|lvs"
│ └─vgs-lvs1  d6bcf6fb-641c-4238-4f55-bc677d22d245
│   └─cr-swap 663e1134-ab5d-3aac-bb6f-d45b7b1f34dc
linux-5l8q:~ # vi /etc/fstab

Das sollten wir sowieso tun, weil wir später nochmal mkinitrd laufen lassen wollen.

Entsprechend erweitern wir die "/etc/fstab":

UUID=a3202dac-a44e-4344-b551-dd123ce893b2   /         ext4   acl,user_xattr   0 1
UUID=663e1134-ab5d-3aac-bb6f-d45b7b1f34dc    swap   swap   defaults           0 0

Danach können wir das Swap-Device auch mal mounten:

 
linux-5l8q:~ # swapon                                                                                                                                               
linux-5l8q:~ # swapon -av                                                                                                                                           
swapon: /dev/mapper/cr-swap: found signature [pagesize=4096, signature=swap]                                                                                        
swapon: /dev/mapper/cr-swap: pagesize=4096, swapsize=18247319552, devsize=18247319552                                                                               
swapon /dev/mapper/cr-swap                                                                                                                                          
linux-5l8q:~ # 

Ausführen von "mkinitrd"

Nach all diesen Vorbereitungen (Modifikation der Dateien /etc/default/grub, /boot/grub2/grub.cfg, /etc/crypttab, "/etc/fstab") können wir schließlich auch "mkinitrd" ausführen. Dieses Wrapper-Skript führt unter Opensuse einerseits "dracut" zur Konfiguration des "initramfs" und von "systemd" aus, startet aber andererseits am Schluss auch noch ein "Refresh" der Bootloader-Installation.

 
linux-5l8q:~ # mkinitrd 
....
DRACUT_MELDUNGEN
.....

(Im Gegensatz zum letzten Beitrag müssen wir hier natürlich kein chroot ausführen.)

Hinweis: Gerne würde ich hier sagen können, dass man YaST's Bootloader-Programm ausführen kann. In der ncurses-Version für die Kommandozeile kommt es dabei aber leider zu Fehlern beim Wechsel zwischen den verschiedenen Konfigurationsseiten.
(Opensuse wird in der letzten Zeit nicht gerade besser .... ; die grafische Version des "Bootloader"-Moduls unter "yast2" funktioniert, ist auf unserer Server-Installation aber natürlich nicht im Konsolen-Terminal verfügbar).

Checks und Reboot

Es lohnt sich, nochmal die Datei "/boot/grub2/grub.cfg" und die anderen manipulierten Dateien zu prüfen. Danach führen wir einen Reboot durch. An dieser Stelle sei daran erinnert, dass wir die Passphrase für SWAP und "/"-FS gleich gewählt haben. Wir müssen daher die Passphrase insgesamt nur zweimal eingeben. Der Boot-Vorgang sollte fehlerfrei funktionieren. je nachdem, welcher Eintrag (für cr-root oder cr-swap) zuerst in der "/etc/crypttab" steht, wird beim Laden des Kernels das Passwort für das erste Device abgefragt; die Abfrage für das 2-te Device unterbleibt.

Der SWAP sollte anschließend auch gemountet sein:

     
linux-5l8q:~ # swapon -s
Filename                                Type            Size    Used    Priority
/dev/dm-3                               partition       17819644        0       -1
linux-5l8q:~ # 

Fazit und Ausblick

Wenn die Einträge zwischen den verschiedenen Konfigurationsdateien (/etc/crypttab, /boot/grub2/grub.cfg, /etc/default/grub, /etc/fstab) konsistent gehalten werden, ist es einfach ein separat kryptiertes LVM-Volume für den SWAP einzubinden und im Boot-Vorgang mounten zu lassen.

Im nächsten Beitrag
Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – X – Hibernation
werfen wir einen Blick auf einen ersten Hibernation-Test.