Subsections of Linux

Subsections of How To

ASDF Nutzung und Beispiele

Vorbereitung

Die hier installierten Versionen können bereits morgen veraltet sein. Am besten die möglichen Versionen auflisten lassen und entsprechend des Bedarfs installieren…

Befehle

Versionen eines Plugins anzeigen
asdf list all <NAME>
asdf list all golang
asdf list all python

Plugins

Python
Vorbereitung

Es werden ggf. weitere Anwendungen wie z.B. make benötigt, beim Einrichten werden aussagekräftige Fehlermeldungen ausgegeben…

asdf plugin add python https://github.com/asdf-community/asdf-python.git
asdf install python 3.12.2
asdf global golang 3.12.2
Golang
asdf plugin add golang https://github.com/asdf-community/asdf-golang.git
asdf install golang 1.22.0
asdf global golang 1.22.0

Hardware und Details via CLI-Tools ermitteln

Mit leichtgewichtigen Tools erhält man viel Informationen zur genutzten Hardware. Es braucht nicht immer große Software-Pakete oder gar GUIs ;)

Root Rechte nötig

Die Befehle werden mit root-Rechten ausgeführt. Nutze “sudo” oder su (switch user), wenn du nicht als root eingeloggt bist.

CPU / Prozessor

lscpu

Architektur:                     x86_64
CPU Operationsmodus:             32-bit, 64-bit
Byte-Reihenfolge:                Little Endian
Adressgrößen:                    39 bits physical, 48 bits virtual
CPU(s):                          8
Liste der Online-CPU(s):         0-7
Thread(s) pro Kern:              2
Kern(e) pro Sockel:              4
Sockel:                          1
NUMA-Knoten:                     1
Anbieterkennung:                 GenuineIntel
Prozessorfamilie:                6
Modell:                          94
Modellname:                      Intel(R) Xeon(R) CPU E3-1260L v5 @ 2.90GHz
Stepping:                        3
CPU MHz:                         900.140
Maximale Taktfrequenz der CPU:   3900,0000
Minimale Taktfrequenz der CPU:   800,0000
BogoMIPS:                        5802.42
Virtualisierung:                 VT-x
L1d Cache:                       128 KiB
L1i Cache:                       128 KiB
L2 Cache:                        1 MiB
L3 Cache:                        8 MiB
NUMA-Knoten0 CPU(s):             0-7
Vulnerability Itlb multihit:     KVM: Mitigation: VMX disabled
Vulnerability L1tf:              Mitigation; PTE Inversion; VMX conditional cache flushes, SMT vulnerable
Vulnerability Mds:               Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Meltdown:          Mitigation; PTI
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:        Mitigation; Full generic retpoline, IBPB conditional, IBRS_FW, STIBP conditional, RSB filling
Vulnerability Srbds:             Mitigation; Microcode
Vulnerability Tsx async abort:   Mitigation; Clear CPU buffers; SMT vulnerable
Markierungen:                    fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx
                                  est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2
                                 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d

Block-Devices (Festplatten, SSDs, NVMEs)

Mit lsblk können eine Vielzahl von Informationen abgerufen werden (–output). Eine Liste erhält man mit (-h|–help). Der Parameter –nodeps (-d) sorgt dafür, dass man nur “Hauptgeräte” wie Festplatten, aber keine Partitionen, RAIDs, LVMs angezeigt bekommt. ROTA zeigt an, ob das Gerät rotierende Teile hat (Festplatten).

lsblk --output name,model,serial,rota --nodeps

NAME MODEL                      SERIAL               ROTA
sda  SAMSUNG_MZ7KM1T9HAJM-00005 S2XXXXXXXXXXXX          0
sdb  SAMSUNG_MZ7KM1T9HAJM-00005 S2XXXXXXXXXXXX          0
sdc  WDC_WD80EFZX-68UW8N0       xxxxxxxx                1
sdd  WDC_WD30EFRX-68EUZN0       WD-WMCxxxxxxxxx         1
sde  WDC_WD30EFRX-68EUZN0       WD-WMCxxxxxxxxx         1
sdf  WDC_WD30EFRX-68EUZN0       WD-WMCxxxxxxxxx         1
sdg  WDC_WD30EFRX-68EUZN0       WD-WMCxxxxxxxxx         1

S.M.A.R.T. Werte von Block Devices

Ist der Health-Status, die Menge der Lesefehler oder Laufzeit relevant, ist das Auslesen der SMART-Werte von nöten. Alle gängigen Distributionen halten hierfür Pakete bereit. Unter Archlinux und Ubuntu nennt dieses sich smartmontools.

# Ubuntu
apt update && apt install smartmontools

# Archlinux
pacman -Syu smartmontools

smartctl -a /dev/sda

smartctl 7.4 2023-08-01 r5530 [x86_64-linux-5.15.81-1-lts] (local build)
Copyright (C) 2002-23, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Model Family:     Samsung based SSDs
Device Model:     SAMSUNG xxxxxx-xxxxxxx
Serial Number:    xxxxxxxxxxxxxxxxxxxx
LU WWN Device Id: 5 xxxxx xxxxxxxxx
Firmware Version: xxxxxxx
User Capacity:    1.920.383.410.176 bytes [1,92 TB]
Sector Size:      512 bytes logical/physical
Rotation Rate:    Solid State Device
TRIM Command:     Available, deterministic, zeroed
Device is:        In smartctl database 7.3/5528
ATA Version is:   ACS-2, ATA8-ACS T13/1699-D revision 4c
SATA Version is:  SATA 3.1, 6.0 Gb/s (current: 6.0 Gb/s)
Local Time is:    Sat Feb  3 20:36:53 2024 CET
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

..........

SMART Attributes Data Structure revision number: 1
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  5 Reallocated_Sector_Ct   0x0033   100   100   010    Pre-fail  Always       -       0
  9 Power_On_Hours          0x0032   089   089   000    Old_age   Always       -       51508
 12 Power_Cycle_Count       0x0032   099   099   000    Old_age   Always       -       36
177 Wear_Leveling_Count     0x0013   099   099   005    Pre-fail  Always       -       82
179 Used_Rsvd_Blk_Cnt_Tot   0x0013   100   100   010    Pre-fail  Always       -       0
180 Unused_Rsvd_Blk_Cnt_Tot 0x0013   100   100   010    Pre-fail  Always       -       15335
181 Program_Fail_Cnt_Total  0x0032   100   100   010    Old_age   Always       -       0
182 Erase_Fail_Count_Total  0x0032   100   100   010    Old_age   Always       -       0
183 Runtime_Bad_Block       0x0013   100   100   010    Pre-fail  Always       -       0
184 End-to-End_Error        0x0033   100   100   097    Pre-fail  Always       -       0
187 Uncorrectable_Error_Cnt 0x0032   100   100   000    Old_age   Always       -       0
190 Airflow_Temperature_Cel 0x0032   060   052   000    Old_age   Always       -       40
195 ECC_Error_Rate          0x001a   200   200   000    Old_age   Always       -       0
197 Current_Pending_Sector  0x0032   100   100   000    Old_age   Always       -       0
199 CRC_Error_Count         0x003e   099   099   000    Old_age   Always       -       1
202 Exception_Mode_Status   0x0033   100   100   010    Pre-fail  Always       -       0
235 POR_Recovery_Count      0x0012   099   099   000    Old_age   Always       -       24
241 Total_LBAs_Written      0x0032   099   099   000    Old_age   Always       -       180868725074
242 Total_LBAs_Read         0x0032   099   099   000    Old_age   Always       -       135827340303
243 SATA_Downshift_Ct       0x0032   100   100   000    Old_age   Always       -       0
244 Thermal_Throttle_St     0x0032   100   100   000    Old_age   Always       -       0
245 Timed_Workld_Media_Wear 0x0032   100   100   000    Old_age   Always       -       65535
246 Timed_Workld_RdWr_Ratio 0x0032   100   100   000    Old_age   Always       -       65535
247 Timed_Workld_Timer      0x0032   100   100   000    Old_age   Always       -       65535
251 NAND_Writes             0x0032   100   100   000    Old_age   Always       -       232084360256

..........

PCI Devices

Je genauer die Ausgabe sein soll, desto mehr “-v”.
Nach Menge der Ausgabe lohnt sich die Umleitung in eine Datei, oder nach less, um den Inhalt in Ruhe lesen zu können…

lspci
lspci -v
lspci -vvvvv | less
lspci -vvvvv > pci.out; less pci.out

USB Devices

Das gleich Prozedere wie bei PCI-Devices…

lsusb

Mainboard, RAM, Prozessor, BIOS

dmidecode
biosdecode

https://wiki.ubuntuusers.de/dmidecode/


Linux Betriebssystem migrieren (remote & lokal)

Binär-Dump war gestern. Linux migrieren mit Rsync (remote und lokal).

Vorwort

Um ein Betriebssystem (Linux basiert) mit Daten auf einen anderen Host, oder eine andere Festplatte zu synchronisieren und wieder lauffähig zu machen, gibt es viele Herangehensweisen.
In dieser Anleitung soll dies Anhand eines Ubuntus und rsync veranschaulicht werden. Die folgenden Szenarien werden beleuchtet:

  • Ubuntu soll auf eine andere Festplatte kopiert und im Anschluss von dieser gebootet werden
  • eine lokal laufende Maschine soll auf einen Remote Host kopiert werden

In beiden Fällen wird die Migration mithilfe von GRML durchgeführt. Hierbei handelt es sich um eine Live-CD (auf Basis von Debian) die kostenfrei heruntergeladen und genutzt werden kann: https://grml.org/download/ Grundsätzlich funktioniert diese Anleitung aber auch mit Ubuntu, Arch Linux, oder anderen ISO.

Datenverlust

Alle hier gezeigten Schritte müssen mit Sinn und Verstand durchgeführt werden.
Beim verdrehen von Parametern oder falscher Anwendung droht Datenverlust! Ich schließe jegliche Haftung aus und rate dazu die offiziellen Dokumentationen der Software zu lesen um ein tieferes Verständnis für die Anwendung zu erlangen.

Kopieren einer lokalen Installation auf weitere Festplatte

Prinzipiell kann die Kopie auch im gebooteten Zustand des originalen Betriebssystems erfolgen. Ich rate hierbei allerdings davon ab, weil sich während des Betriebs Daten ändern können.
Eine saubere Übertragung erreicht man, wenn ein Live-System gebootet wurde und das Quellsystem nicht in Nutzung ist!

Die Festplatten werden wie folgt gemappt:

  • sda (alt)
  • sdb (neu)
neue Festplatte Partitionieren

Die Partitionstabelle kann kopiert und wieder eingespielt werden. Falls GPT verwendet wird, müssen die UUIDs ersetzt werden!

sfdisk -d /dev/sda > part_table
grep -v ^label-id part_table | sed -e 's/, *uuid=[0-9A-F-]*//' -i part_table | sfdisk /dev/sdb

In manchen Fällen kann die neue Platte auch größer, oder kleiner ausfallen.
In diesem Fall kann die Partitionierung auch manuell durchgeführt werden. Ob GPT oder MSDOS hängt vom persönlichen Geschmack ab.
Im Hinblick auf stetig größer werdende Speichermedien bietet sich die Verwendung von GPT aber an.

parted -s /dev/sdb mklabel gpt
parted -s /dev/sdb mkpart "EFI system partition" fat32 1MiB 261MiB
parted -s /dev/sdb set 1 esp on
parted -s /dev/sdb mkpart primary 261MiB 100%free
Dateisystem erzeugen und mounten

Hier wird davon ausgegangen, dass die zweite Partition der alten Festplatte das / (rootfs) bereitstellt.
Falls noch andere Mountpoints auf der Platte existieren, müssen diese im Nachgang eingegangen werden!

mkfs.ext4 /dev/sdb2

mkdir -p /mnt/{old,new}
mount /dev/sda2 /mnt/old
# optional (falls weitere Mountpoints!)
# mount /dev/sda3 /mnt/old/home
# mount /dev/sda5 /mnt/old/var
mount /dev/sdb2 /mnt/new
Dateien synchronisieren

Bitte unbedingt auf die abschließenden Slashes ("/") bei den Ordnern achten!

rsync -aHv --numeric-ids /mnt/old/ /mnt/new/
FStab korrigieren

Aufgrund der neuen UUIDs der Dateisysteme auf der neuen Platte, müssen diese in der FSTab hinterlegt werden. Die UUIDs ermittelt man wie folgt:

blkid

/dev/sda2: UUID="823779fc-3231-4189-8a64-eee8e2d616e0" BLOCK_SIZE="4096" TYPE="ext4"
/dev/sdb2: UUID="aa6c1ffb-c522-4620-b4a5-dc45da6f2613" BLOCK_SIZE="4096" TYPE="ext4"

Je nach Menge der Mountpoints kann die Liste deutlich länger sein.
Alle Einträge der FSTab müssen dann berücksichtigt werden.

# File-Name: /mnt/new/etc/fstab

# vor Änderung UUID=823779fc-3231-4189-8a64-eee8e2d616e0 (sda2) 
UUID=aa6c1ffb-c522-4620-b4a5-dc45da6f2613 /      ext4 rw,relatime 0 0
# hier ggf. die weiteren Mountpoints hinterlegen
UUID=00000000-0000-0000-0000-000000000000 /home  ext4 rw,relatime 0 0
Chroot, Installation von Grub

Für die Installation von Grub auf die neue Festplatte sind verschiedene Laufzeit-Ordner notwendig, die System-Dateien der Live-Umgebung, aber auch Block-Devices (z.B. /dev/sd*) bereitstellen.
Abschließend betritt man mit seiner Shell die Kopie des System auf der neuen Festplatte und installiert Grub auf selbiger.

# mounten der notwendigen Ordner
for i in proc sys dev run;do
  mount --bind /$i /mnt/new/$i
done

# Wechsel der Shell
chroot /mnt/new /bin/bash

# Grub Konfiguration generieren
update-grub

# Grub auf neuer Festplatte installieren
grub-install /dev/sdb

# Chroot verlassen
exit

# herunterfahren
shutdown -h now

Nach dem Herunterfahren kann die alte Festplatte abgeschlossen und von der neuen gebootet werden.

Kopieren einer lokalen Installation auf Remote Host

Grundsätzlich verhält sich das Kopieren auf einen Remote Host, wie die lokale Variante.
Aufgrund der Tatsache dass die UUIDs der Dateisysteme sich doppeln dürfen und diese nur lokal eindeutig sein müssen, kann die Einrichtung etwas vereinfacht werden.

Zunächst liest man die UUIDs der Quell-Partitionen aus, denn diese werden wiederverwendet, damit man die FStab auf dem Remote-Host nicht korrigieren muss (bei gleicher Partitionsstruktur):

blkid

/dev/sda1: UUID="fcfca092-1654-1094-affd-a0293affcdee" BLOCK_SIZE="4096" TYPE="ext4"
/dev/sda2: UUID="01938725-dfea-cddc-ffff-0582aefc3a1a" BLOCK_SIZE="4096" TYPE="ext4"
Partitionierung übertragen
sfdisk -d /dev/sda > part_table

# Die Ausgabe wird durch den StdOut-Kanal und mittels SSH auf den Remote-Host gesendet. Die Ausgabe wird mittels Pipe an sfdisk geleitet
grep -v ^label-id part_table | sed -e 's/, *uuid=[0-9A-F-]*//' -i part_table | ssh root@my.remote.host 'cat - | sfdisk /dev/sdb'
Dateisystem(e) anlegen
# Dateisystem mit der alten UUID auf Remote-Host anlegen
mkfs.ext4 -U fcfca092-1654-1094-affd-a0293affcdee /dev/sda1
mkfs.ext4 -U 01938725-dfea-cddc-ffff-0582aefc3a1a /dev/sda2
Dateisystem(e) mounten
mount /dev/sda2 /mnt/
mkdir /mnt/boot
mount /dev/sda1 /mnt/boot
# optional (falls weitere Mountpoints!)
# mount /dev/sda3 /mnt/home
# mount /dev/sda5 /mnt/var
Dateien synchronisieren
rsync -aHv --numeric-ids / root@my.remote.host:/mnt/
Chroot, Installation von Grub
# mounten der notwendigen Ordner
for i in proc sys dev run;do
  mount --bind /$i /mnt/$i
done

# Wechsel der Shell
chroot /mnt/ /bin/bash

# Grub Konfiguration generieren
update-grub

# Grub auf Festplatte installieren
grub-install /dev/sda

# Chroot verlassen
exit

# neu starten
reboot

https://wiki.archlinux.org/index.php/Parted#Partitioning


Subsections of Security

LUKS Volume mit USB Keystick verknüpfen

Hinweis

Diese Anleitung setzt eine bestehende Installation mit LUKS voraus.
Die Installation wird hier nicht vorgenommen.

Idee

Es wird ein neuer Schlüssel zum LUKS Container hinzugefügt und dieser auf einer beliebigen Position eines USB Stick gespeichert. Beim Booten wird dieser dann ausgelesen und zum Öffnen der verschlüsselten Festplatte genutzt.

Hinweise

Wichtig zu wissen ist, sofern die /boot Partition nicht verschlüsselt ist, die Position des Schlüssels ausgelesen werden kann, da diese in der grub.cfg und ggf. im Init-RamFS liegt, sofern man in der Crypttab weitere Dateisysteme mit dem USB-Stick öffnen möchte.

Möchte man dies umgehen, ist die Verschlüsselung der /boot Partition nötig und eine Eingabe des Kennworts im Bootloader (z.B. Grub) nötig.
Dieses Szenario wird hier nicht thematisiert, kann aber genau so konfiguriert werden.
Durch die Passwort-Eingabe im Bootload wird /boot geöffnet, “/” und ggf. weitere Volumes werden dann über den Schlüssel des USB-Sticks geöffnet.

unterstützte Distributionen
  • Archlinux
  • Debian / Ubuntu
  • in der Regel auch andere Distributionen (mit Anpassungen)

Konfiguration

Software installieren
pacman -Syu ntfs-3g parted
apt-get update && apt-get install ntfs-3g parted
Partitionierung

Es wird eine Partitionstabelle und eine Partition angelegt und mit NTFS formatiert. Dies kann hilfreich sein, damit Dritte, wenn Sie den USB-Stick irgendwo anschließen, ggf. ein Dateisystem angezeigt bekommen und keinen Verdacht schöpfen.
Hierbei muss persönlich abgewogen werden, ob man das Dateisystem vorher noch mit Daten vollschreibt, oder den -f Parameter deaktiviert um das gesamte Dateisystem zu initalisieren.
Je nach Tiefe einer USB-Stick Analyse könnte der Key so ermittelt werden.

# Partitionstabelle anlegen um eine Partition mit Fake Dateisystem zu erzeugen
parted -s /dev/sdc mklabel msdos

# Partition anlegen
parted -s /dev/sdc mkpart primary 1m 100%free

# NTFS Dateisystem erzeugen (kann aber auch jedes andere FS sein!)
# -f aktiviert den Schnellmodus
mkfs.ntfs -f /dev/sdc1

# UUID der Partition (PARTUUID) auslesen (wird später benötigt!)
# blkid  | grep sdc
/dev/sdc1: BLOCK_SIZE="512" UUID="xxxxxxxxxxxxxxxx" TYPE="ntfs" PARTUUID="xxxxxxxx-01"
Schlüssel erzeugen und auf USB Stick schreiben

Der Schlüssel wird in diesem Beispiel 4096 Bit groß und in die Datei /root/keyfile geschrieben.
dd liest einen Block von 4096 Bytes aus der Datei /dev/random und schreibt diesen in das Keyfile.
Danach wird mit dd das Keyfile gelesen und an eine beliebige Stelle der Partition geschrieben.
Hierbei ist die Blocksize wieder 4096, aber mittels seek wird bestimmt, wie viele Blocksizes übersprungen werden sollen.
In diesem Beispiel sind es 1234 * 4096 Bytes, bedeutet es wird ab der Position (4194304. Byte geschrieben. - 4194304 / 1024 (Byte/KiByte)/ 1024 (KiByte / MiByte) / 1024 (MiByte / GiByte) - wodurch der Stick mindestens 4 GiByte groß sein muss …).
Bei einem kleineren USB Stick kann auch ein Wert wie zum Beispiel 7 verwendet werden. Die Verschiebung (Offset) ist aber im späteren Verlauf wichtig und sollte sich notiert werden!

# neuen Schlüssel erzeugen erzeugen
dd if=/dev/random of=/root/keyfile bs=4096 count=1

# Keyfile auf Partition schreiben
dd of=/dev/sdc1 if=/root/keyfile   bs=4096 seek=1234 
Key zu LUKS hinzufügen

Es wird angenommen, dass /dev/sda2 die verschlüsselte Systempartition ist.
Diese kann je nach lokaler Konfiguration (HDD,SSD, NVME, RAID, LVM, …) abweichen! Unbedingt auf die korrekten Werte beim skip achten, der dem seek Wert beim Schreiben auf den USB-Stick entspricht.

# aktuelle Slotbelegung ausgeben
cryptsetup luksDump /dev/sda2

# Keyfile als Schlüssel hinzufügen
cryptsetup luksAddKey /dev/sda2 /root/keyfile

# erneut Slotbelegung ausgeben und ermitteln, welcher dazu gekommen ist
cryptsetup luksDump /dev/sda2


# testen des Keys (ermittelter Slot, z.B. 5)
cryptsetup luksOpen --test-passphrase --key-slot 5 /dev/sda2 -d <(dd if=/dev/sdc1 bs=4096 count=1 skip=1234)
Host Konfiguration anpassen
optionale Nutzung von Crypttab
NAME      UUID=DISK_UUID   /dev/disk/by-partuuid/xxxxxxxx-01   luks,tries=3,keyfile-size=4096,keyfile-offset=4194304
Grub Konfiguration
# UUID der Partition prüfen, diese wurde bereits am Anfang der Anleitung ermittelt. Nun wird noch mal geprüft ob diese stimmt:

ls -hla /dev/disk/by-partuuid/xxxxxxxx-01
lrwxrwxrwx 1 root root 10 16. Nov 22:57 /dev/disk/by-partuuid/xxxxxxxx-01 -> ../../sdc1

# Grub konfigurieren, der Syntax ist wie folgt:
# cryptkey=$PFAD_ZUR_PARTITION$:$SEEK_BYTES:$KEYSIZE
# Die SEEK_BYTES = seek * key_size (z.B. 1234 * 4096 = 
/etc/default/grub
cryptkey=/dev/disk/by-partuuid/xxxxxxxx-01:4194304:4096
Grub Konfiguration generieren
grub-mkconfig -o /boot/grub/grub.cfg
update-grub
Initramfs generieren
# -p linux oder -p linux-lts, je nachdem welches Paket installiert ist
mkinitcpio -p linux
update-initramfs -k all -u

salted SHA512 Passwort Hashes generieren

Hier ein paar Möglichkeiten wie man einfach Passwort-Hashes generieren lassen kann, viele nativ ohne Installation von Paketen.
Oft wird mkpasswd vorgeschlagen, was sich aber nicht auf jeder Distribution gleich verhält, daher ein paar praktische Alternativen.

Python

python -c 'import crypt,getpass; print(crypt.crypt(getpass.getpass(), crypt.mksalt(crypt.METHOD_SHA512)))'

# oder in der Shell als Alias
alias gen_sha512="python -c 'import crypt,getpass; print(crypt.crypt(getpass.getpass(), crypt.mksalt(crypt.METHOD_SHA512)))'"

OpenSSL

Sollte im Regelfall bereits installiert sein, weil es für SSL/TLS Verbindungen benötigt wird.

openssl passwd -6

# oder mit festgelegtem Salt
openssl passwd -6 --salt ABCDEF

mkpasswd

Hinweis

Funktioniert mit Debian / Ubuntu

apt update
apt install whois

mkpasswd -m sha-512

# oder wenn der salt selbst bestimmt werden soll
mkpasswd -m sha-512 --salt=abcdefgh

HTPasswd

Manche Distributionen ziehen verhältnismäßig viele Abhängigkeiten nach, weswegen diese Option nicht immer attraktiv ist.
Einfach selber entscheiden ob die anderen Wege nicht sinnvoller sind.
Außerdem existiert die Option erst in Apache >= 2.5 (https://httpd.apache.org/docs/trunk/programs/htpasswd.html).

htpasswd -n -d -5 $USERNAME

transparent verschlüsselte VMs mit Libvirt

Vorwort

Diese Anleitung soll einen kurzen Überblick ermöglichen, wie mittels Libvirt und LUKS Images virtueller Maschinen verschlüsseln kann.
Hierbei findet die Verschlüsselung nicht in der virtuellen Maschine selbst statt, sondern wird außerhalb angewendet, sodass das Gastsystem nichts von der Verschlüsselung mitbekommt (transparent).
Somit ist keine VNC- / Spike- / serielle Verbindung beim booten, oder gar ein Dropbear Server von nötigen um das Gastsystem zu booten.

Libvirt vorbereiten

Secret anlegen

Zuerst muss ein Kennwort (bzw. ein Keyfile) generiert werden, was zum Öffnen des LUKS-Containers genutzt wird. Jedes Image hat zwar in seiner Struktur einen individuellen Schlüssel mit dem die symmetrische Verschlüsselung realisiert wird, allerdings muss eben jener mittels Keyfile geöffnet werden.

# UUID generieren und in Variable UUID speichern
UUID=$(uuidgen)

# Anlegen der Datei mysecret.xml mit Nutzung der UUID Variablen
cat <<EOF > mysecret.xml
<secret ephemeral='no' private='yes'>
   <description>my luks secret</description>
   <uuid>${UUID}</uuid>
</secret>


virsh secret-define --file mysecret.xml

# 128 Zeichen langes Kennwort generieren und in Base64 speichern
# die Nutzung von -base64 statt -hex sorgt dafür, dass der Key binäre Daten enthält. Hier kann man selbst entscheiden ob der Schlüsel lesbar sein soll ;). Ich empfehle die Konstellation mit -hex | base64 zu nutzen.

PASSWORD=$(openssl rand -hex 128 | base64)

# Passphrase / Key setzen
virsh secret-set-value "${UUID}" "${PASSWORD}"

# Secrets auflisten, hier sollte das Secret angezeigt werden!
virsh secret-list
Volume anlegen
UUID=<UUID des Libvirt Secrets>

V_NAME=my_volume
# in GB, ohne Einheit (siehe <capacity>)
V_SIZE=100
V_PATH="/srv/images/${V_NAME}"


cat <<EOF > myvolume.xml
<volume>
  <name>${V_NAME}</name>
  <capacity unit='G'>${V_SIZE}</capacity>
  <target>
    <path>${V_PATH}</path>
    <format type='raw'/>
    <encryption format='luks'>
       <secret type='passphrase' uuid='${UUID}'/>
       <cipher name='aes' size='256' mode='xts' hash='sha512'/>
       <ivgen name='plain64' hash='sha512'/>
    </encryption>
  </target>
</volume>

# Volume anlegen, bitte falls ein anderer Pool gewünscht ist, entsprechend anpassen
virsh vol-create --pool default --file myvolume.xml

Libvirt erzeugt danach mittels QEMU-IMG ein Image, welches außen mittels LUKS gesichert ist und im inneren mit RAW-Format verwendet wird, nicht dass man plötzlich wunderbare QCOW2 Funktionen erwartet ;)

Image in VM einbinden

In der XML Defintion der virtuellen Maschine müssen Parameter gesetzt sein, damit das Image angezogen werden kann. Deshalb hier ein Beispiel aus dem Kontext heraus gezogen, mit aufgelösten Variablen:

<domain type='kvm'>
<!-- INHALT AUF DISK CONFIG REDUZIERT! -->
    <disk type='file' device='disk'>
      <!-- cache deaktivieren und io=native bringen Geschwindigkeit -->
      <driver name='qemu' type='raw' cache='none' io='native'/>
      <!-- PFAD wie in der my_volume.xml! -->
      <source file='/srv/images/my_volume'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <encryption format='luks'>
        <!-- unbedingt die UUID mit der Secret-UUID beibehalten, darüber wird der Schlüssel zum öffnen des LUKS Containers gefunden -->
        <secret type='passphrase' uuid='16cd518f-35ee-4a55-acc3-376bb0c9152e'/>
      </encryption>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </disk>
</domain>