Hello everyone! It’s been quite a while since I’ve last updated this website; I’ve been busy graduating from University and moving out to North Carolina to start my new job (I’ll do a more personal blog post at a later time detailing my thoughts on everything about this). I’ll try to stay more on top of this blog, I promise!
Lots has changed; I’m still running an ESXi server, but it’s no longer the Dell Optiplex that it was before (it’s actually an old Mac Pro!) and it’s not doing nearly as much as it used to; now that I have a ‘big people job’ and a little bit more dispensable income I’ve moved most of my services off to VPSes (including this blog you’re reading right now!). It just makes more sense to me. I’ll show all of my home network changes soon enough for those that are interested (for whatever reason).
So. On to the topic du jour. This is going to be long and kind of rambly.
The topic for today was inspired by one of my coworkers; he’s running Funtoo on a ThinkPad X1 Carbon, and in order to get to any of his stuff (home directory, in particular) he has to log in as the root user, unlock the home partition, mount it, then log in as himself.
“If a bad guy somehow manages to guess my user’s password, he won’t have any of my files; he’ll just have a ‘dummy user’ instead” was his reasoning for this.
I thought this was brilliant, so I set off to do this myself on a shiny might-as-well-be-new Lenovo ThinkPad T420 that I picked up for a great price on eBay.
I didn’t see any of the commands he ran when he did this, I just had a good idea of the methodology behind it; encrypt home directory and mount it manually. The details of implementation were up to me.
Let’s get started, shall we?
So first I had to decide what OS I wanted to throw onto this laptop. I originally considered Gentoo because I have been playing with it in a virtual machine and am liking all of the stuff that it can do, but ultimately I decided that I didn’t want to have to wait three hours to compile a software package and all of its dependencies, and all of their dependencies… yadda yadda. So I decided to go back to my old friend Arch; still has the minimalistic “install it from scratch, kind of” mentality, but with a quicker package installation time. Priorities.
(side note: I’m gonna at least try to install Linux from scratch at some point. Just because.)
So there were a couple of attempts at installing a GPT scheme on the hard drive, but a little bit of Googling told me that the motherboards of these older ThinkPads, despite having a “UEFI-flavored BIOS” on them, are unable to read/boot from GPTs. Curses.
Then I started reading up on this fancy “LUKS on LVM” methodology. Basically, you create two partitions on your hard drive (/dev/sda1 and /dev/sda2, in my case). You use the smaller partition (sda1) for your /boot partition, because it needs to remain unencrypted for the BIOS to be able to read from it. Then you split the larger partition (sda2) into pieces using LVM. Then what you can do is encrypt each of those LVM pieces (called Logical Volumes) separately using dm-crypt (LUKS). You can then choose to decrypt some or all of those partitions as the kernel boots up, or manually after boot-time.
Plus, because you only need two physical hard disk partitions, it will play nicely with the MBR partition table that I had to use to get the disk to boot, but I could have as many ‘partitions’ as I wanted through the use of LVM.
Perfect.
So I set off, using parted to create the MBR and the two partitions (I could’ve used fdisk, but I was still in a “install it like Gentoo!” mentality for some reason). Then comes the fun part; creating the LVM volumes and encrypting them.
Ideally you’d want to scramble the partition you were going to use for LVM before doing this (by dd’ing from /dev/random to /dev/sda2, for instance), but because this was a hard drive that I had no data on previously I will lose no sleep over not doing so.
Step 1 - create the LVM setup.
-Create the ‘physical volume’ (tell the LVM service that this drive is going to have some LVM bits on it),
-Create the ‘volume group’ (a ‘container’ for each of the LVM chunks. I think of this in terms of being a “virtual hard drive” because it’s kind of partitioned in the same way), and
-Create the ‘logical volumes’ (the actual ‘partitions’ or the ‘LVM chunks’ that we’re going to use to actually store the data).
lvm pvcreate /dev/sda2 lvm vgcreate lvm /dev/sda2 lvm lvcreate -L 50G -n lvroot lvm lvm lvcreate -L 16G -n swap lvm lvm lvcreate -l 100%FREE -n home lvm
My partitioning scheme for the LVM logical volumes: 50G for /, 16G for swap (8GB of RAM in the machine and I like the having-double-the-amount-of-RAM-for-swap-space methodology), and the rest of the open space for /home.
Next, we encrypt the device we’re going to use for the root directory.
cryptsetup luks /dev/lvm/lvroot
It will ask for a password. You’re going to have to enter this password every time the computer starts up, so make it secure but don’t make it unmanagable (a 50-character password, while awesomely secure, is also rather inconvenient to enter every time you have to reboot).
Now, open the freshly encrypted device, create a filesystem on it, and mount it to /mnt to continue installing Arch. The guide I was using suggested using reiserfs, and I’m not really sure why; I just used ext4.
cryptsetup open /dev/lvm/lvroot root #this mounts the unencrypted device at /dev/mapper/root mkfs.ext4 /dev/mapper/root mount /dev/mapper/root /mnt
Then you mount /dev/sda1 to /mnt/boot, pacstrap, arch-chroot, etc as usual.
Next change comes when it comes to the creation of the initial ramdisk and modifying mkinitcpio.conf. You’ll want to make sure that you have lvm2 and encrypt in your hooks section, and you’ll want to make sure that they’re placed before the filesystem hook. This way you make sure that LVM and dm-crypt are started before the kernel tries to load the filesystem.
(chrooted)/etc/mkinitcpio.conf
HOOKS="... lvm2 encrypt ... filesystems ..."
Next comes the configuration of a bootloader. I used GRUB2, so I can’t say for sure whether this procedure will work on Syslinux or Gummiboot or even LILO, so YMMV.
Install the grub package, install GRUB to /dev/sda, and edit the (chrooted)/etc/default/grub file as follows:
GRUB_CMDLINE_LINUX_DEFAULT="cryptdevice=/dev/lvm/lvroot:root root=/dev/mapper/root resume=/dev/lvm/swap"
Then generate the GRUB config file.
Finally, you’ll want to configure your filesystem table so the OS knows what to mount and where to find it:
/dev/mapper/root / ext4 defaults 0 1 /dev/sda1 /boot ext2 defaults 0 2 /dev/lvm/swap none swap sw 0 0
So why are we listing /dev/mapper/root instead of /dev/lvm/lvroot? Because of the mkinitcpio hook that we added earlier, the lvroot logical volume is decrypted and mounted to /dev/mapper before the kernel ever gets to fstab. And if you think about it, that’s the way it has to be; the kernel can’t read /etc/fstab if everything under / is still encrypted, can it? ;)
Some of you are currently shouting at the screen “WHAT?! Why do you have your swapspace unencrypted?! That’s basically asking for trouble!” Yep. I know. I don’t have a good excuse for it, either; this is just the process that I followed. We’ll get to fancyness with swap in a later post. Hold your horses.
At this point, you’ll want to reboot into your system. You’ll be prompted for your password for the root partition early on; enter it and you’ll be presented with a login prompt. Log in as the root user.
Now, some of you are probably thinking “Hey, wait a second! He hasn’t even touched the /home LVM logical volume! What a scam and a waste of my time, I’m gonna go read slashdot and actually learn something!”
Whoa, there, cowboy. We’re getting to that.
Next, create your “everyday” user; we don’t want to go masquerading around our system as the root user, do we? That’s a very bad idea. Add this user to group ‘wheel’, install ‘sudo’ using pacman, and turn on sudo rights for the ‘wheel’ group using ‘visudo’ (you can even make it passwordless sudo if you want, but keep in mind that anyone that gets to your account basically has root privileges without ever needing to know the password. Weigh the options). Make sure that you create the user’s /home directory as you do this.
Next, finally, go ahead and encrypt the logical volume which is going to be used for the /home directory and actually mount it to /home:
cryptsetup luksFormat /dev/lvm/home cryptsetup open /dev/lvm/home home mount /dev/mapper/home /home
Physically re-create the user’s home directory and chown it to username:username. Then, logout and log back in as the user. All should seem right with the world. As a test, touch a file in that directory. Why? you’ll see in a second.
Now, go ahead and reboot the machine you’re on. Decrypt the / directory, but don’t decrypt the /home directory. Log in as your user. ‘ls’ your home directory. What do you see?
Nothing. You see absolutely nothing, because your touch’d file is safely encrypted within the /dev/lvm/home logical volume. You’ve successfully set up a ‘dummy’ user; congratulations! :)
Now, you can ‘cd’ out of your home directory (important, otherwise the OS will assume the directory is ‘in use’ and won’t mount anything on top of it), sudo su - to the root user, unencrypt the /dev/lvm/home device, and mount the device to ‘/home’. Then, exit out of the root session and ‘cd’ back home. Voila! All of your file(s) are magically back.
Now, what about that swap issue we were talking about? What if we want hibernate to work with an encrypted swap partition? And that user that we created still has sudo permissions (possibly even paswordless sudo, like in my personal case), that’s still a security risk, how do we mitigate that?
That will have to come in a future blog post. Stay tuned, everyone. :)
/cliffhanger