coding, hacking, startups, computer security, technology and more

Encrypting File System Partitions in FreeBSD

I've lost a lot of data in the past and learning from these mistakes my current system is setup with a mirrored disk configuration. I have two 500GB disks (sata) and two 300GB disks (ide). On a weekly basis I use rsync to backup the primary drives to their secondary mirrors. This way I can ensure that I always have dual copies of all my important data. For multiple reasons I now wish to encrypt this data so that in the event of someone gaining physical access to this machine they would not be able to read the data if they didn't have the correct passphrase.

Firstly, let's take a look at the relevant bits from /etc/fstab

[root@orion] (~): grep 300 /etc/fstab
/dev/ad0s1 /mnt/300gb_primary ufs rw 0 0
/dev/ad1s1d /mnt/300gb_backup ufs rw,noauto 0 0

My plan was to experiment with the filesystem encryption on the secondary disk first. If that proved successful I could then copy all the contents from the primary to the newly encrypted secondary and then move on to making the primary encrypted aswell.  Since I'm running FreeBSD 6 I opted to use the newer GELI encryption system - for the sake of getting jumping into experimentation immediately I opted to just use the kernel modules rather than compile support for GELI into the kernel so let's begin:

[root@orion] (~): kldload geom_eli
[root@orion] (~): echo 'geom_eli_load="YES"' >> /boot/loader.conf

This loads the geli module into the kernel and the second line ensures that it's automatically loaded upon boot.  Next we create our master key, initialize geli on the ad1 disk and finally attach the geli provider:

[root@orion] (~): dd if=/dev/random of=/root/.geli_keys/ad1.key bs=64 count=1
1+0 records in
1+0 records out
64 bytes transferred in 0.000059 secs (1082401 bytes/sec)
[root@orion] (~): geli init -s 4096 -K /root/.geli_keys/ad1.key /dev/ad1
Enter new passphrase:
Reenter new passphrase:
[root@orion] (~): geli attach -k /root/.geli_keys/ad1.key /dev/ad1
Enter passphrase:

Success, as confirmed by /var/log/messages:

Oct 28 13:09:06 orion kernel: GEOM_ELI: Device ad1.eli created.
Oct 28 13:09:06 orion kernel: GEOM_ELI: Encryption: AES-CBC 128
Oct 28 13:09:06 orion kernel: GEOM_ELI:     Crypto: software

With the geli provider attached to the ad1 device we can now work with the disk as normal via the ad1.eli device and geli will transparently handle all the encryption so now we confirm the existance of the geli device and then newfs the encrypted disk:

 [root@orion] (~): ls /dev/ad1*
/dev/ad1      /dev/ad1.eli
[root@orion] (~): newfs /dev/ad1.eli
/dev/ad1.eli: 286168.1MB (586072360 sectors) block size 16384, fragment size 4096
        using 850 cylinder groups of 336.98MB, 21567 blks, 21568 inodes.
super-block backups (for fsck -b #) at:
 160, 690304, 1380448, 2070592, 2760736, 3450880, 4141024, 4831168, 5521312, 6211456,
6901600, 7591744, 8281888, 8972032, 9662176, 10352320, 11042464... etc. etc.

Next it's time to modify our fstab so it's looking at ad1.eli instead of ad1s1d :

[root@orion] (~): sed -i .bak -e 's/ad1s1d/ad1.eli/' /etc/fstab
[root@orion] (~): grep 300 /etc/fstab
/dev/ad0s1 /mnt/300gb_primary ufs rw 0 0
/dev/ad1.eli /mnt/300gb_backup ufs rw,noauto 0 0
[root@orion] (~): mount /mnt/300gb_backup/

There you have it - surprisingly easy.. and surprisingly powerful. Out of curiousity I decided to do a quick performance test:

[root@orion] (~): dd if=/dev/zero of=/mnt/300gb_backup/test.img count=10000 bs=1024
10000+0 records in
10000+0 records out
10240000 bytes transferred in 0.387872 secs (26400463 bytes/sec)
[root@orion] (~): dd if=/dev/zero of=/mnt/300gb_primary/test.img count=10000 bs=1024
10000+0 records in
10000+0 records out
10240000 bytes transferred in 0.158931 secs (64430469 bytes/sec)

So it's a little slower than I expected but still, I can live with that for the benefits it provides.

To ensure the drive is mounted upon boot I needed to add the following to my /etc/rc.conf:

geli_ad1_flags=" -k /root/.geli_keys/ad1.key"

Now it's time to copy the data from the primary disk to this encrypted disk and repeat this process for the primary disk and I'm all done!