Tags: #FreeBSD #security #encryption #FDE #systemd #MBR #GPT #UFS #ZFS
FreeBSD: Full Disk Encryption
In order to get rid of systemd on a server, one way may seem to be within the realm of FreeBSD…
Note: The system installation process would be the same for either server or a desktop. Obviously, the 3rd party software will make the difference.
Introduction
FreeBSD’s man pages are notoriously known to be very comprehensive and full of useful information. The full disk encryption (FDE) is not an exception.
Important note: Naturally, installation of the FDE carries its obvious burden in relation to the fact that the encryption/decryption key needs to be provided each time the server is restarted. Reader discretion advised!
Installation
The FreeBSD’s installer’s “Welcome screen” (tested with version 11.1) enables administrator to jump to shell and return back later by pressing exit
. However, the disks can be manually configured later.
Choose <Install>
to continue with the installation and its further options selections: keymap, hostname, system components, and partitioning.
Choose <Shell>
to escape to shell.
The installer’s default shell is the Bourne shell. Sometimes, it may be useful to switch to the interactive C shell instead. It can be achieved by:
$ /bin/csh
Disk Availability
Available disks can be checked as follows (usually, ada0
represents the first disk):
$ sysctl kern.disks
Disk Check
Disks can be checked for current partition layout using gpart
. Note: An empty disk scheme (lacking MBR or GPT) results in: gpart: No such geom: ada0
.
$ gpart show ada0
More info about disks can be found using diskinfo
as follows:
$ diskinfo -v ada0
Disk Format and Partitioning
In order to retain compatibility with other operating systems that only understood MBR (MS Windows), it was a common practice in FreeBSD to encapsulate a bsdlabel inside an MBR slice resulting in e.g.:
ada0s1a
, i.e. the first label (a
) in the first slice (1
) on the first disk (ada0
).
Running FreeBSD exclusively on a system, the MBR slices are not needed anymore and the disk can utilise bsdlabel
s directly (sometimes called dangerously dedicated mode) e.g.:
ada0a
, i.e. the first label (a
) on the first disk (ada0
).
With the arrival of the UEFI standard (proposed to replace the PC BIOS), GPT replaced the MBR resulting in:
ada0p1a
, i.e. first label (a
) in the first slice (1
) on the first disk (ada0
).
More details can be found in the handbook or on forums.
Optionally, disk partitions can be deleted and partition tables destroyed as follows:
$ gpart delete -i PARTITIONNUMBER adaDISKID
$ gpart destroy -F adaDISKID
Disk format is also performed using gpart
and WILL DELETE DATA. An MBR table format (-s mbr
) of the first SATA disk (ada0
) can be achieved running the following command:
$ gpart create -s mbr /dev/ada0
Two freebsd
slices (aka partitions) the first of 768MB for /boot
(large enough to hold two kernels) and the rest for an encrypted /root
and swap
) can be created on the disk (ada0
) as follows:
$ gpart add -t freebsd -a 4k -s 768m ada0
$ gpart add -t freebsd -a 4k ada0
FreeBSD administrators have two main file system options available. The newest is called the Z File System (ZFS) and requires ECC RAMs, but such approach was not aligned with the goals of this project. Obviously, other members of the community do not agree with that statement. Either way, there is another (older) options called the Unix File System (UFS
).
A UFS BSD partition scheme can be created on the first slice as follows (this time, the partition type is freebsd-ufs
):
$ gpart create -s bsd ada0s1
$ gpart add -t freebsd-ufs -a 4k ada0s1
Partition labelling can be utilised for better reference (survives computer restarts, addition of new disk etc.) as follows:
$ glabel label -v bootfs /dev/ada0s1a
$ glabel label -v sysfs /dev/ada0s2
Now, a simple MBR boot loader needs to be installed into the first disk (ada0
) and a boot manager into the first active slice (ada0s1
) as follows:
$ gpart bootcode -b /boot/mbr ada0
$ gpart bootcode -b /boot/boot ada0s1
$ gpart set -a active -i 1 ada0
Disk Encryption
Full disk encryption is activated using geli
(AES-256, 4096bit key) as follows (if available, the aesni
driver can be loaded):
$ kldload aesni
$ geli init -b -s 4096 -l 256 /dev/label/sysfs
Metadata backup can be found in /var/backups/label_sysfs.eli
. This file can be copied on a backup medium in order to help restore a corrupted encrypted partition should it occur in the future. Reader discretion advised!
The encrypted partition now needs to be attached using:
$ geli attach /dev/label/sysfs
GEOM_ELI: Device label/sysfs.eli created.
Being attached as /dev/label/sysfs.eli
, the decrypted partition can now be modified in order to contain the swap
and root
partitions as follows (using the BSD partition scheme again):
$ gpart create -s bsd /dev/label/sysfs.eli
$ gpart add -t freebsd-swap -s 2048m /dev/label/sysfs.eli
$ gpart add -t freebsd-ufs /dev/label/sysfs.eli
And again, it is useful to label the partitions accordingly:
$ glabel label -v swapfs label/sysfs.elia
$ glabel label -v rootfs label/sysfs.elib
Now, it is time to format the partitions as follows (the -t
flag can be used with newfs
to enable TRIM support):
$ newfs -j /dev/label/bootfs
$ newfs -j /dev/label/rootfs
Having each partition formatted, the swap
and root
partitions be mounted as follows:
$ swapon /dev/label/swapfs
$ mount /dev/label/rootfs /mnt/
Since the FreeBSD boot loader expects its data to reside in the /boot
directory of the boot partition, it needs to be mounted under a different directory (e.g. /bootfs
) and the /boot
directory needs to be “symlinked” to its boot
sub-directory as follows:
$ mkdir /mnt/bootfs
$ cd /mnt
$ ln -s bootfs/boot boot
$ mount /dev/label/bootfs /mnt/bootfs
$ mkdir bootfs/boot
The exit
command returns back to the installer.
Optionally, the whole process can be performed for the GPT scheme as follows:
$ ### GTP scheme format
$ gpart create -s gpt /dev/ada0
$ ### protective MBR installation (backward compatibility) + 2nd stage boot loader
$ gpart add -t freebsd-boot -a 4k -s 64k ada0
$ gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada0
$ ### unencrypted /bootfs directory to hold kernel(s)
$ gpart add -t freebsd-ufs -a 4k -s 768m ada0
$ ### encrypted system directory (for root and swap slices)
$ gpart add -t freebsd-ufs -a 4k ada0
$ ### labelling for better reference
$ glabel label -v bootld /dev/ada0p1
$ glabel label -v bootfs /dev/ada0p2
$ glabel label -v sysfs /dev/ada0p3
$ ### encryption (loading AESNI if available)
$ kldload aesni
$ geli init -b -s 4096 -l 256 label/sysfs
$ geli attach label/sysfs
$ ### bsdlabels for swap & root partitions
$ gpart create -s bsd label/sysfs.eli
$ gpart add -t freebsd-swap -s 2048m label/sysfs.eli
$ gpart add -t freebsd-ufs label/sysfs.eli
$ ### labelling for better reference
$ glabel label -v swapfs label/sysfs.elia
$ glabel label -v rootfs label/sysfs.elib
$ ### formatting (-t flag to newfs to enable TRIM support)
$ newfs -j /dev/label/bootfs
$ newfs -j /dev/label/rootfs
$ ### mounting
$ swapon /dev/label/swapfs
$ mount /dev/label/rootfs /mnt/
$ mkdir /mnt/bootfs
$ cd /mnt
$ ln -s bootfs/boot boot
$ mount /dev/label/bootfs /mnt/bootfs
$ mkdir bootfs/boot
$ exit # back to the installer
Installation Finalisation
The trickiest part is luckily over. Since the installer expects the root of the filesystem to be mounted in /mnt
, which has been just done, it installs the necessary files (base, kernel, libs, ports etc.) there. Consequently, it prompts for further details necessary to finish the installation process (such as root password, network interface setup, DNS setup, services setup, user setup, time zones).
Unfortunately, the installer does not make sure the proper setup is in the /etc/fstab
and /boot/loader.conf
files. Therefore, before system restart, a manual configuration needs to be performed.
If the /dev
directory is suddenly empty (null
) and so is the /mnt
directory like the following examples:
$ ls -lA /dev
total 8
-rw-r--r-- 1 root wheel 8 Jan 1 00:00 null
$ ls -lA /mnt
total 0
the installer needs to be completed by the exit
command. And on the very last screen instead of “Reboot”, the “Live CD” option needs to be selected.
User root
can now log in (with empty password) in order to manually configure the mount points in /etc/fstab
as follows:
$ echo "# Device Mountpoint FStype Options Dump Pass#" > /mnt/etc/fstab
$ echo "/dev/label/bootfs /bootfs ufs rw,noatime 1 1" >> /mnt/etc/fstab
$ echo "/dev/label/swapfs none swap sw 0 0" >> /mnt/etc/fstab
$ echo "/dev/label/rootfs / ufs rw,noatime 1 1" >> /mnt/etc/fstab
and boot loader parameters as follows:
$ echo 'aesni_load="YES"' > /mnt/boot/loader.conf
$ echo 'geom_eli_load="YES"' >> /mnt/boot/loader.conf
$ echo 'geom_eli_passphrase_prompt="YES"' >> /mnt/boot/loader.conf
$ echo 'vfs.root.mountfrom="ufs:/dev/label/rootfs"' >> /mnt/boot/loader.conf
Finally, the system can be restarted now.
Useful Links
It may be useful to visit the FreeBSD: Post Installation Steps.
There is also a brief manual for FreeBSD: Full Disk Encryption with UEFI.