My Universe Logo

FreeBSD verschlüsselt auf ZFS installieren

Dieses Tutorial beschreibt die Installation von FreeBSD 8.2 auf einem Notebook oder Desktop-Rechner (physischer Zugang zum Rechner erforderlich!). Aus Gründen des Diebstahlschutzes wird die Festplatte vollständig verschlüsselt.

Wie üblich gilt: Stumpfes abtippen oder kopieren führt unter Garantie zu einem unbenutzbaren System. Wie bei jeder Installation ist vor Beginn unbedingt das Hirn zu booten und während der Installation rege zu gebrauchen. Ich werde niemanden trösten, der durch Plan- und Ahnungslosigkeit seine Daten in die ewigen Jagdgründe geschickt hat. Backup ist Pflicht!

Setup

Auf der internen Festplatte des Rechners (hier als da0 bezeichnet) wird FreeBSD stand-alone installiert; eine Parallelinstallation von Windows ist bei dem beschriebenen Setup nicht möglich. Die Verschlüsselung erfolgt mit AES-256 im XTS-Modus; nach Möglichkeit wird auf Hardware-Verschlüsselung zurückgegriffen (neuere Intel-CPU mit Westmere-Kern o. ä. erforderlich).

Gebootet wird von einem USB-Stick; dieser soll auch den Schlüssel enthalten. Der Bootvorgang soll ohne Kennworteingabe auskommen (problematisch mit manchen USB-Tastaturen). Ergo muss das BIOS des eingesetzten Rechners in der Lage sein, von einem USB-Stick (hier als da1 bezeichnet) zu booten.

Als Dateisystem soll (fast) ausschließlich ZFS eingesetzt werden. Hierdurch entfällt die Notwendigkeit, sich den Kopf darüber zu zerbrechen, wie viel Platz denn nun für /usr, /var & Co. bereit gestellt werden muss – und natürlich der Ärger, der entsteht, sollte man sich hier geirrt haben. Hierzu sollte der Rechner aber über mindestens 4, besser 8 GB RAM verfügen.

Installation vorbereiten

Das System muss von der FreeBSD 8.2 DVD gebootet werden (volle FixIt-Unterstützung wird benötigt). Wird von CD anstelle der DVD gebootet, muss die Fixit-CD bereit gehalten werden. Nach erfolgreichem Start von sysinstall Fixit auswählen.

Fixit einrichten

rm /etc/pwd.db /etc/spwd.db /etc/group
ln -s /mnt2/etc/pwd.db /etc/pwd.db
ln -s /mnt2/etc/spwd.db /etc/spwd.db
ln -s /mnt2/etc/group /etc/group

ln -s /dist/boot/kernel /boot/kernel
ln -s /dist/lib /lib

AES-NI Unterstützung prüfen

Nun muss geprüft werden, ob die CPU AES-NI unterstützt:

dmesg | egrep "^[[:space:]]*Features2"

Taucht AESNI in der Liste auf, kann auf hardware-unterstützte Verschlüsselung zurückgegriffen werden.

Kernel-Module laden

# nur wenn AES-NI unterstützt wird
kldload aesni
# ab hier alles laden
kldload geom_eli
kldload zfs

Partitionen einrichten

Hier kommt das mit 8.2 endlich sauber und vollständig unterstützte GPT zum Einsatz. Zunächst müssen Festplatte und USB-Stick für GPT vorbereitet werden:

# Platte und Stick leeren
dd if=/dev/zero of=/dev/da0 bs=1m
dd if=/dev/zero of=/dev/da1 bs=1m

# GPT anlegen
gpart create -s GPT da0
gpart create -s GPT da1

# Überprüfung
gpart show

Nun können die Partitionen angelegt werden. Dazu muss aber zunächst überprüft werden, welche Sectorsize GPT auf den einzelnen Geräte verwendet:

gpart list da0 | grep -A3 Consumers
gpart list da1 | grep -A3 Consumers

Auf meinem System waren dort 512 Bytes angegeben; d. h. pro KiB Speicherplatz müssen zwei Sektoren eingerechnet werden. Auf dem USB-Stick werden zwei Partitionen benötigt; eine für den Bootcode, und eine für Kernel und Boot-Konfiguration. Die Partition für den Bootcode muss mindestens 16 KiB groß sein; bei einer Sectorsize von 512 bedeutet das also 32 Sektoren. gpart show verrät übrigens auch, mit welchem Sektor eine Partition frühestens beginnen darf (in meinem Fall 34).

gpart add -b 34 -s 32 -t freebsd-boot da1
gpart add -b 66 -t freebsd-ufs da1
gpart bootcode -b /dist/boot/pmbr -p /dist/boot/gptboot -i 1 da1
newfs -O2 /dev/da1p2
mkdir /usb
mount /dev/da1p2 /usb

Auf der Festplatte werden zwei Partitionen benötigt – eine für das System mit ZFS, und eine für Swap (Swap will man nicht auf ZFS haben, da Swapping auf ein ZFS Dataset den RAM-Verbrauch noch weiter hochschrauben würde, was weiteres Swapping nach sich zieht, usw. – bis das System dann abstürzt).

gpart add -b 34 -s 16777216 -t freebsd-swap da0
gpart add -b 16777250 -t freebsd-zfs da0

Verschlüsselung aktivieren

dd if=/dev/random of=/usb/key bs=256k count=1
mkdir /var/backups
geli init -l 256 -K /usb/key -s 4096 -b -P /dev/da0p2
geli attach -k /usb/key -p /dev/da0p2

# Kontrollieren
geli list

Die Ausgabe des letzten Befehls sollte in etwa so aussehen:

Geom name: da0p2.eli
State: ACTIVE
EncryptionAlgorithm: AES-XTS
KeyLength: 256
Crypto: hardware
UsedKey: 0
Flags: BOOT

ZFS einrichten

zpool create -m /tank tank da0p2.eli
zfs create tank/usr
zfs create tank/var
zfs create tank/home

zfs set atime=off tank

mkdir /boot/zfs
zpool export tank
zpool import tank

Der letzte Schritt erzeugt die Datei /boot/zfs/zpool.cache. Diese wird für den Bootvorgang später unbedingt benötigt. Wird am Consumer (da0p2.eli) später etwas geändert (etwa Wechsel von Soft- auf Hardware-Verschlüsselung o. ä.), muss dieser Schritt zwingend wiederholt werden – ohne gültige zpool.cache bootet das System nicht (bzw. findet beim booten das Root-FS nicht).

FreeBSD installieren

Zunächst wird das System auf die eben angelegten ZFS Datasets installiert:

export DESTDIR=/tank
cd /dist/8.2-RELEASE/base
./install.sh
cd /dist/8.2-RELEASE/kernels
./install.sh GENERIC

Zum Booten muss der Kernel aber auf den USB-Stick:

cd /tank
mv boot /usb/
mkdir stick
ln -s stick/boot boot

root benötigt ein Passwort, und ein bisschen aufräumen schadet ebenfalls nicht:

chroot /tank
passwd root
exit
chmod 0700 /tank/root

Boot-Konfiguration einrichten

Zunächst müssen die fehlenden Dateien auf den Stick übertragen werden:

cp -Rpv /var/backups /usb/
cp -Rpv /boot/zfs /usb/boot/

Außerdem wird eine /boot/loader.conf auf dem Stick benötigt, die das Booten überhaupt erst ermöglicht (in diesem Falle natürlich eine /usb/boot/loader.conf:

aesni_load="YES"
geom_eli_load="YES"
zfs_load="YES"

geli_da0p2_keyfile0_load="YES"
geli_da0p2_keyfile0_type="da0p2:geli_keyfile0"
geli_da0p2_keyfile0_name="/key"

vfs.root.mountfrom="zfs:tank"

Eine fstab muss auch noch angelegt werden, hier natürlich /tank/etc/fstab:

/dev/da0p1.eli   none              swap   sw               0 0
tank             /                 zfs    rw,noatime       0 0
tank/usr         /usr              zfs    rw,noatime       0 0
tank/var         /var              zfs    rw,noatime       0 0
tank/home        /home             zfs    rw,noatime       0 0
md               /tmp              mfs    rw,noatime,-s1G  2 0
/dev/da1p2       /stick            ufs    rw,noauto        0 0

Damit sollte das System nun booten, wobei der USB-Stick unbedingt benötigt wird. Allerdings wird der USB-Stick nicht automatisch gemounted, so dass er nach erfolgreichem Bootvorgang einfach abgezogen werden kann. Für ein System-Update (oder die Installation von Kernel-Modulen) muss der Stick jedoch gemounted werden; durch den fstab-Eintrag genügt dazu ein einfaches

mount /stick

Kernel im Eigenbau

Krypto-Unterstützung

Die Krypto-Unterstützung (aesni, geom_eli) kann auch fest im Kernel eingebaut werden, so dass die Einträge in /boot/loader.conf nicht mehr benötigt werden. Dazu gehört folgendes in die Kernel-Konfiguration:

options         GEOM_ELI
device          crypto
device          aesni

Konsolen-Farbe verändern

Die Farbe für Kernel-Meldungen auf der Konsole lassen sich mit folgenden Optionen anpassen:

options         SC_KERNEL_CONS_ATTR=(FG_LIGHTCYAN|BG_BLACK)
options         SC_KERNEL_CONS_REV_ATTR=(FG_BLACK|BG_CYAN)

pf-Unterstützung

Auch OpenBSDs pf lässt sich direkt im Kernel einbauen. Dazu werden folgende Einträge benötigt:

device          pf
device          pflog
options         ALTQ
options         ALTQ_CBQ
options         ALTQ_RED
options         ALTQ_RIO
options         ALTQ_HFSC
options         ALTQ_PRIQ