Encrypting EVERYTHING With geli On FreeBSD

Monday, November 30th, 2009 at 12:09 am | 11,725 views | trackback url

New FreeBSD LogoI’ve been a long-time user and supporter of FreeBSD ever since I was exposed to it by Greg Lehey and Ceren Ercen back in the Linuxcare days. I’ve come to enjoy its security, speed and powerful simplicity. The FreeBSD documentation is also unrivaled in the community.

But I also realized that securing the system itself only means so much, if I don’t actually encrypt the data it stores locally on those platters, so I had to do better.

You can lock down externally-facing services, ports and daemons.. but someone who has physical access to your systems can bypass almost everything if they have the tools and the skills. This includes a clueless operations person working in a datacenter (which I’ve been fighting quite a bit lately, as my own hosting provider rooted one of my machines, because I refused to give them the root password. Grr!).

Enter “geli” encryption under FreeBSD!

But getting geli encryption working isn’t quite as straightforward as you’d think. It requires some prior planning and preparation to make sure you’re doing it correctly. We’ll do this in two steps:

  1. Set up encrypted swap
  2. Encrypt the secondary drive and mount /home to it, encrypted

In a nutshell, here are the steps to set that up to encrypt your data:

  1. Add a second drive in your system at least equal to the capacity of your primary drive. This drive will be the target of the encrypted filesystems you put on it. If you’re planning on encrypting the entire system including the root partition, you’ll need to make sure it’s the same size or larger. If you’re just encrypting home directories or /var or something smaller, you can use a lesser capacity drive.
  2. Boot your BSD system so it recognizes that new drive. If you’re using VMware, VirtualBox or similar virtualization product to run your FreeBSD instance, add a second virtual disk to the VM, of equal or larger size. On my system, this is called da1.
  3. Once booted, edit your kernel config (you have compiled a custom kernel, haven’t you?), and add the following lines to it:
    options GEOM_ELI
    device crypto
  4. Rebuild your kernel, install it and reboot back into that newly built kernel (which should now have geli support compiled in). If you’re using the GENERIC kernel, add the following line to /boot/loader.conf:
  5. Now you have to create your key for the partition or drive you wish to encrypt. Since we’re going to encrypt swap first, we have to find out which partition is the swap partition. We do that with swapinfo(8):
    # swapinfo -hg
    Device          1G-blocks     Used    Avail Capacity
    /dev/da0s1b             1       0B     2.0G     0%

    Here we can see that /dev/da0s1b is our swap partition. Let’s unmount that so we can begin:

    # swapoff /dev/da0s1b
  6. Now let’s randomize and scramble the data on that slice:
    # dd if=/dev/random of=/dev/da0s1b bs=1m
  7. Next, we encrypt that slice and mount it (choose the best algorithm for your needs. AES is fast and efficient, which is why I’m using it here. Blowfish, Camellia and 3DES are other ciphers you can choose from):
    # geli onetime -d -e aes /dev/da0s1b
    # swapon /dev/da0s1b.eli
  8. We can now verify that it is indeed mounted and encrypted:
    # swapinfo -hg
    Device          1G-blocks     Used    Avail Capacity
    /dev/da0s1b.eli         1       0B     2.0G     0%
  9. We’re not done yet, we still have to update /etc/fstab to reference the new encrypted slice (ending in .eli):
    # cat /etc/fstab
    # Device                Mountpoint      FStype  Options         Dump    Pass#
    /dev/da0s1b.eli         none            swap    sw              0       0
    /dev/da0s1a             /               ufs     rw              1       1
    /dev/da0s1e             /tmp            ufs     rw              2       2
    /dev/da0s1f             /usr            ufs     rw              2       2
    /dev/da0s1d             /var            ufs     rw              2       2
    /dev/da1.eli            /home           ufs     rw              2       2
    /dev/acd0               /cdrom          cd9660  ro,noauto       0       0

Now we need to start encrypting actual data itself. In this series of steps, we’re going to encrypt home directories on their own partition, secured by geli. Our secondary drive (the one we installed in our machine or attached to our VM in this case), is called “da1“.

Your drive lettering and designation may differ, so please make note of it when you boot your machine. Make sure you choose the blank drive when you follow these next steps; you don’t want to wipe out all of your data on your existing drive by accident. Been there, done that. Be careful!

  1. With da1 designated as the target drive in the system, let’s create an initial key to secure it. For better performance, a key size of 4k or larger is preferred (that’s the -s 4096 option below):
    # dd if=/dev/random of=/root/da1.key bs=64 count=1
    # geli init -s 4096 -K /root/da1.key /dev/da1
    Enter new passphrase:
    Reenter new passphrase:
  2. You’ll need to “attach” that new drive to the encryption provider, as follows:
    # geli attach -k /root/da1.key /dev/da1
    Enter passphrase:
  3. If that was successful, you’ll now want to completely ‘shred’ or randomize any data that may be on that drive, to ensure that there is nothing deterministic left on it.
    # dd if=/dev/random of=/dev/da1.eli bs=1m

    This may take awhile, so sit back and relax, but do not skip this step!

  4. Now let’s create the filesystem on top of that encrypted volume and mount it to a temporary mount point:
    # newfs /dev/da1.eli
    /dev/da1.eli: 30720.0MB (62914552 sectors) block size 16384, fragment size 4096
            using 92 cylinder groups of 336.88MB, 21560 blks, 21568 inodes.
    super-block backups (for fsck -b #) at:
    # mkdir -p /private
    # mount /dev/da1.eli /private
  5. You should now be able to see this and verify that it is mounted correctly:
    # df
    Filesystem   1K-blocks    Used    Avail Capacity  Mounted on
    /dev/da0s1a     507630  298322   168698    64%    /
    devfs                1       1        0   100%    /dev
    /dev/da0s1e     507630      16   467004     0%    /tmp
    /dev/da0s1f   25438226 2477294 20925874    11%    /usr
    /dev/da0s1d    2007598   39942  1807050     2%    /var
    /dev/da1.eli  30958184       8 28481524     0%    /private
  6. Now you can copy data to the partition and be assured that it is secured from prying eyes. My favorite tool to do this is rsync, and I’m a ninja with its hundreds of options. For example, to copy the user’s home directories over to the encrypted partition, simply use the following:
    # rsync -avSP /home/. /private
  7. From here, we now have to change where /home is mounted, by updating /etc/fstab to refer to that location:
    # cat /etc/fstab
    # Device                Mountpoint      FStype  Options         Dump    Pass#
    /dev/da0s1b             none            swap    sw              0       0
    /dev/da0s1a             /               ufs     rw              1       1
    /dev/da0s1e             /tmp            ufs     rw              2       2
    /dev/da0s1f             /usr            ufs     rw              2       2
    /dev/da0s1d             /var            ufs     rw              2       2
    /dev/da1.eli            /home           ufs     rw              2       2
    /dev/acd0               /cdrom          cd9660  ro,noauto       0       0
  8. We still need to make sure this partition is set up to mount at boot time, so let’s add that to /etc/rc.conf by adding these two additional lines at the end:
    geli_da1 _flags="-k /root/da1 .key"

    That should do it. Remember though, this will also mean you will be prompted to enter the passphrase at boot time; you can’t do this headless or remotely.

    When the machine boots up, it will prompt you for your passphrase, and then mount /home to /private/home (the encrypted provider). If all goes right, you should see this:

    GEOM_ELI: Device da1.eli created.
    GEOM_ELI: Encryption: AES-CBC 128
    GEOM_ELI:     Crypto: software
  9. If you want to unmount the partition, simply do the following:
    # umount /home
    # geli detach da1.eli
  10. You can also blow away /private, since we’re no longer using it. It was just a simple “trampoline” to allow us to get the data out of the unencrypted /home to the encrypted one:
    # rm -Rf /private

That’s it! Pretty simple, but pretty powerful. Once you incorporate that into your overall workflow, you won’t even know it’s there.

Encryption should be 100% transparent to valid users, but 100% opaque to unauthorized users or prying eyes.

Some more references:

Last Modified: Sunday, March 6th, 2016 @ 02:18

Leave a Reply

You must be logged in to post a comment.

Bad Behavior has blocked 1796 access attempts in the last 7 days.