Mit FreeBSD 13 lässt sich die native ZFS Verschlüsselung direkt nutzen. Dabei muss man zwischen einem komplett verschlüsselten zpool und verschlüsselten Datasets unterscheiden. Hat man einen komplett verschlüsselten zpool, bedeutet es nicht, dass damit auch alle Datasets verschlüsselt sein müssen, so wie es auch nicht bedeutet, dass man Datasets nur verschlüsseln kann, wenn auch der komplette ZFS Pool verschlüsselt ist.
Wer nun also sein FreeBSD auf Version 13 gehoben hat, möchte ggf. einzelne ZFS Datasets verschlüsseln. In der Praxis trifft dieses sicher oft auf Jails zu. Diese liegen in der Regel in eigenen ZFS Datasets und mit dem folgenden Beispiel lassen sich diese und andere Datasets nachträglich verschlüsseln.
Im Beispiel haben wir den Pool zroot und in diesem das Dataset varta. Weder der zpool noch das Dataset sind aktuell verschlüsselt:
root@testtest:/ # zfs list zroot/varta NAME USED AVAIL REFER MOUNTPOINT zroot/varta 100M 12.0G 100M /zroot/varta root@testtest:/ # zfs get encryption zroot/varta NAME PROPERTY VALUE SOURCE zroot/varta encryption off default root@testtest:/ #
Aktiviert man bei ZFS Dinge wie Komprimierung oder Deduplikation sind diese immer nur ab dem Moment der Aktivierung und bis genau zur Deaktivierung aktiv. Dieses hat viele Vorteile aber auch Nachteile. So greift dieses nur für Daten, welche neu geschrieben werden. Möchte man dieses nachträglich auf alle Daten anwenden, muss man die Daten komplett neu schreiben. Dieses lässt sich am einfachsten und schnellsten per zfs send und zfs receive erledigen. Wenn man also sein bestehendes Dataset verschlüsseln möchte, dann geht dieses faktisch nicht, sondern man erstellt im Grunde ein neues verschlüsseltes Dataset und schreibt seine Daten dort rein.
Bevor wir nun mit der Migration starten, müssen wir noch eine Kleinigkeit wissen…. Zum Verschlüsseln der Daten benötigen wir noch ein Geheimnis, einen Schlüssel/Key. Dieser kann bei ZFS in verschiedenster Form und an verschiedensten Orten liegen. So könnte man den Key zur Ver- und Entschlüsselung auf einen USB-Stick ablegen. Nur wenn dieser auch im System steckt usw. usw.. Der eingängigste Weg ist sicher ein Passphrase welches per prompt abgefragt wird. Will man sein verschlüsseltes Dataset öffnen, wird man nach einem Kennwort gefragt, welches sich das System bis zum nächsten Reboot oder dem manuellen „Schließen“ des Datasets merkt. Diesen Zustand wollen wir nach der Migration, in diesem Beispiel, erreichen.
Zur Verdeutlichung erstellen wir kurz ein neues verschlüsseltes Dataset:
root@testtest:/ # zfs create -o encryption=on -o keyformat=passphrase -o keylocation=prompt zroot/enc-beispiel Enter passphrase: Re-enter passphrase:
Damit haben wir ein neues Dataset welches sofort benutzt werden kann, alles was wir in dieses legen, ist verschlüsselt.
root@testtest:/ # zfs list zroot/enc-beispiel NAME USED AVAIL REFER MOUNTPOINT zroot/enc-beispiel 200K 12.0G 200K /zroot/enc-beispiel
Schauen wir in die Optionen des Datasets ist die Verschlüsselung aktiviert und der Schlüssel wird per Prompt vom Benutzer abgefragt:
root@testtest:/ # zfs get encryption,keylocation,keyformat zroot/enc-beispiel NAME PROPERTY VALUE SOURCE zroot/enc-beispiel encryption aes-256-gcm - zroot/enc-beispiel keylocation prompt local zroot/enc-beispiel keyformat passphrase -
Wie immer wird das Dataset sofort eingehangen:
root@testtest:/ # mount |grep enc-beispiel zroot/enc-beispiel on /zroot/enc-beispiel (zfs, local, noatime, nfsv4acls)
Nach einem reboot, wird das Dataset nicht automatisch eingehangen, da ZFS den Schlüssel nicht hat. Wenn wir es nun einhängen und ZFS anweisen, den Schlüssel zu laden (Option -l), dann werden wir zur Eingabe des Kennwortes aufgefordert und können das Dataset im Anschluss wieder nutzen:
root@testtest:~ # mount | grep enc-beispiel root@testtest:~ # zfs get encryption,keylocation,keyformat zroot/enc-beispiel NAME PROPERTY VALUE SOURCE zroot/enc-beispiel encryption aes-256-gcm - zroot/enc-beispiel keylocation prompt local zroot/enc-beispiel keyformat passphrase - root@testtest:~ # mount | grep enc-beispiel root@testtest:~ # zfs mount -l zroot/enc-beispiel Enter passphrase for 'zroot/enc-beispiel': root@testtest:~ # mount | grep enc-beispiel zroot/enc-beispiel on /zroot/enc-beispiel (zfs, local, noatime, nfsv4acls)
Gut gut… So viel zu den Basics. Damit ist nun auch klar, warum im nun folgenden zfs send / zfs reveive Beispiel, der Schlüssel einen Umweg nehmen wird. Denn durch das pipen kommen wir so schlecht an die stdin heran, um das Passphrase einzugeben 😉 Wir sind nun also wieder zurück bei unserem unverschlüsselten Dataset varta und dessen Migration in einen verschlüsselten Zustand. Als erstes legen wir nun das gewünschte Passphrase in einer Datei ab:
root@testtest:~ # echo 'Tolles-Kennwort' > /kennwort.txt root@testtest:~ # cat /kennwort.txt Tolles-Kennwort
Ebenfalls erstellen wir einen snapshot vom Dataset varta, welchen wir zur Migration nutzen:
root@testtest:~ # zfs snapshot zroot/varta@migration root@testtest:~ # zfs list -t snapshot NAME USED AVAIL REFER MOUNTPOINT zroot/varta@migration 0B - 100M -
Jetzt kann die eigentliche Migration starten:
root@testtest:~ # zfs send zroot/varta@migration | zfs receive -F -o encryption=on -o keyformat=passphrase -o keylocation=file:///kennwort.txt zroot/en-varta root@testtest:~ # zfs list zroot/varta zroot/en-varta NAME USED AVAIL REFER MOUNTPOINT zroot/en-varta 100M 11.8G 100M /zroot/en-varta zroot/varta 100M 11.8G 100M /zroot/varta root@testtest:~ # zfs list -t snapshot NAME USED AVAIL REFER MOUNTPOINT zroot/en-varta@migration 112K - 100M - zroot/varta@migration 0B - 100M -
Das ist schnell und einfach, oder? Natürlich liegt nun noch immer das Passphrase offen in einer Datei im root des Systems. Wir müssen nun also den Ort des Schlüssels auf prompt ändern:
root@testtest:~ # zfs get keylocation zroot/en-varta NAME PROPERTY VALUE SOURCE zroot/en-varta keylocation file:///kennwort.txt local root@testtest:~ # zfs set keylocation=prompt zroot/en-varta root@testtest:~ # zfs get keylocation zroot/en-varta NAME PROPERTY VALUE SOURCE zroot/en-varta keylocation prompt local
Damit kann die Datei mit dem Passphrase gelöscht werden:
root@testtest:~ # rm /kennwort.txt
Ebenfalls kann nun auch das unverschlüsselte Dataset weg:
root@testtest:~ # zfs destroy -r zroot/varta
Wenn man nun möchte, kann man das neue Dataset natürlich an die gleiche Stelle mounten oder direkt komplett gleich dem alten benennen:
root@testtest:~ # zfs rename zroot/en-varta zroot/varta
Damit ist die Migration fertig und das Dataset ist verschlüsselt:
root@testtest:~ # zfs list zroot/varta NAME USED AVAIL REFER MOUNTPOINT zroot/varta 100M 11.9G 100M /zroot/varta root@testtest:~ # zfs get encryption,keylocation,keyformat zroot/varta NAME PROPERTY VALUE SOURCE zroot/varta encryption aes-256-gcm - zroot/varta keylocation prompt local zroot/varta keyformat passphrase -
Es sieht nun nach sehr viel aus, ist es aber nicht und es lässt sich sogar automatisieren.
Fragen? Dann fragen!