10

I'm using Ubuntu in a corporate environment, and our security policy states that we have to use full disk encryption.

I've also got a laptop with a 32GB mSATA SSD and 750GB of spinning rust. My current installation uses bcache to leverage this, installed using this procedure. This provides a very welcome performance boost without me having to worry about filling up the SSD.

This will be a bountied question. The bounty will be awarded for :

  • A clear, reliable method of performing a fresh install of Ubuntu
    • Any release is acceptable but 15.04 (Vivid) will be fine
  • The entire filesystem will be encrypted
    • The preference here is to use the relevant checkbox in the default Ubiquity installer program (dm-crypt encryption)
  • The filesystem will be cached on an SSD
    • For preference, the kernel dm-cache / lvmcache method see here for method to do this with Debian Jessie
    • The cache must also be secured (ie encrypted)
    • There must be a clear explanation as to why the cache is also encrypted

Have already tried the method for Debian Jessie above, but it refuses to boot for me. Have not so far tried the method described in the comments here.

The posted solutions will be tested on a VirtualBox VM with two blank virtual disks and a release copy of 15.04 desktop (amd64 release). Bounty goes to the first solution that I adopt to reinstall my actual hardware.

Please write your solution as if it were going into the community wiki.


I've awarded the bounty - I think there is still potential for a "LUKS-on-LVM" solution that combines the ease of the approved answer in only having one password, with only using device-mapper components.

  • From what I understand, you don't want to use lvmcache in the default LVM on LUKS ubuntu install because the cache will be unencrypted. – solsTiCe May 7 '15 at 13:38
  • @solsTiCe - it was my understanding that lvmcrypt, being a nice easy layer on top of dm-cache, should be possible to reconcile with LUKS as well (LUKS being another device-mapper thing, dm-crypt), it just matters which way around you layer things – Adrian May 7 '15 at 14:34
  • You should understand, that the /boot partition most certainly will have to be unencrypted. bcache was incompatible with grub on Ubuntu 14.04 and I believe it still is. – Adam Ryczkowski May 7 '15 at 16:57
  • @AdamRyczkowski Yes, I have that configuration now. It's acceptable but I'd prefer a LUKS configuration. – Adrian May 7 '15 at 19:34
  • I don't see why LUKS would exclude bcache... They don't depend on each other and one can happily sit on top of the other. – Adam Ryczkowski May 8 '15 at 5:58
7
+150

LVM on LUKS on bcache

Here the russian doll game is a little deeper with 3 stacks/layers...

My initial idea about this question was to use a default Ubuntu install with LVM on LUKS and convert it into a bcache backing device with blocks but it did not work for me on my test with LVM.

Moreover, the ubuntu installer (ubiquity) is too limited to install inside a bcache device prepared in advance (at least with LUKS on LVM), so we fallback to a method of doing things manually.

Boot into the live CD/USB and choose "Try Ubuntu" and open up a terminal

Pre-install

sudo -i
# Define some variable to avoid confusion and error
luks_part=/dev/sda3
boot=/dev/sda2                    # boot partition
caching_bcache=/dev/sdb           # SSD or partition in SSD

# Do secure erase of encrypted backing and caching device (see Notes [1])
dd if=/dev/urandom of=$luks_part || dd if=/dev/urandom of=$caching_bcache
# Go and grab some coffe, this will take a while...

apt-get install bcache-tools
# Setup bcache caching and backing devices
make-bcache -C $caching_bcache -B $luks_part
# (Optional) Tweak bcache
echo writeback > /sys/block/bcache0/bcache/cache_mode

# Below we now create manually what ubiquity should have done for us
# Setup LUKS device on bcache device
cryptsetup --key-size 512 luksFormat /dev/bcache0
cryptsetup luksOpen /dev/bcache0 crypted

# Setup LVM on LUKS
# You can skip that part if you don't want to use a swap
# or don't want to use multiple partition. Use /dev/mapper/crypted
# as you root latter on
pvcreate  /dev/mapper/crypted
vgcreate vg /dev/mapper/crypted
lvcreate -L 1G vg -n swap
lvcreate -l 100%FREE vg -n root

Installation

Keep the terminal opened and now run the installation. Choose "Something else" when partitioning and specify

  • your boot partition (/dev/sda2)
  • your root partition (/dev/mapper/vg-root)
  • your swap (/dev/mapper/vg-swap)

and check the checkbox to format your partitions

At the end of the installation, don't reboot but just click "Continue trying ubuntu"

Post-install

In our opened terminal

# Install bcache-tools to add bcache module to initramfs
mount /dev/mapper/vg-root /mnt
mount $boot /mnt/boot
mount -o bind /sys /mnt/sys
mount -o bind /proc /mnt/proc
mount -o bind /dev /mnt/dev
chroot /mnt
# To get apt-get running in the chroot
echo 'nameserver 8.8.8.8' > /run/resolvconf/resolv.conf
apt-get install bcache-tools

# Create /etc/crypttab to add crypted bcached partition
echo "crypted UUID=`blkid -o value /dev/bcache0|head -1` none luks" > /etc/crypttab

exit
sync
umount /mnt/sys
umount /mnt/proc
umount /mnt/dev
umount /mnt/boot
umount /mnt
vgchange -an /dev/mapper/crypted
cryptsetup luksClose crypted
sync

# Reboot & enjoy

There is a known Ubuntu 15.04 reboot bug from Live CD/USB so you might have to force reboot/shutdown

Check

Once booted, you can check that /dev/bcache0 is in fact a LUKS partition with

if sudo cryptsetup isLuks /dev/bcache0; then \
    echo "crypted";\
    else echo "unencrypted";\
fi

This is because it is the cache of your LUKS partition, and you now access your data via the device /dev/bcache0 and never from the original backing device (/dev/sda3 here)

References

http://bcache.evilpiepirate.org/

https://wiki.archlinux.org/index.php/Bcache

https://wiki.archlinux.org/index.php/Dm-crypt

bcache-status is not officially merged into bcache-tools, yet. You can have it here: https://gist.github.com/djwong/6343451

[1] There might be better ways to do this wiping

  • Make sure to run update-initramfs -uk all after crypttab creation and following exit command. – dess May 27 '15 at 18:13
4

LVM on LUKS + LUKS/dm-cache

The Ubuntu installer uses the LVM on LUKS configuration for it's full disk encryption.

If you want to also use dm-cache / lvmcache to boost performance, you will need to place your cache pool into an encrypted volume to maintain the security of your data.

The steps are

  • Create a LUKS volume on the target block device
  • Extend the default volume group with the new encrypted LUKS volume
  • Create the cache metadata and data volumes in the new LUKS volume
  • Bind them together as a cache pool
  • Bind this cache pool to the root volume
  • Make sure the new encrypted volume can be mounted at boot by adding it to /etc/crypttab
  • Make sure that your boot environment supports dm-cache

The script below provides an example, and will add an encrypted cache pool to an existing root filesystem. It was designed for systems that have used the default disk encryption option in the Ubuntu installer - ie ; whole disk partitioned and encrypted, no custom partitions etc.

Please note that there is very little validation or defensive programming in this script. If it destroys your working system, that is your responsibility.

Call thus :

# 1   2          3           4     5    6
sudo bash lvmcryptocache /dev/sdb 32M 1968M
  1. Needs root to work
  2. run script in bash
  3. the script name
  4. the block device you want to use (only tested with whole disk)
  5. the metadata size
  6. the cache data size

The size parameters are by default in MB : you will need a ratio of 1:1000 metadata space to cache space (e.g. if your cache disk is 180GB, you need 180MB of metadata space and 179820MB of data space - you may want to round the metadata up a little to be cautious. There is a lower limit for the metadata of 8M.)

You will be prompted for a password for your cache volume - you will be prompted for the passwords for BOTH of your disks during boot.

References


#!/bin/bash
#
# lvmcryptocache
#
# Add an LVM cache pool on and attach it to the root volume
# Including LUKS encryption
# Assumes you are using an "all on root" setup
# If you are not, adapt it if you like
#
# Script licensed GPL3 or later
# © Adrian Wilkins May 2015
#
# Pass the name of the disk device you are using as a cache
# This should ideally be totally blank, so run
#
# dd if=/dev/zero of=/dev/${DISK}
#
# over it for a short while to nuke the partition table

CACHE_DISK=$1
META_SIZE=$2
DATA_SIZE=$3

DISK_NAME=$(basename $CACHE_DISK)

CRYPT_VOLUME=${DISK_NAME}_crypt
CACHE_PV=/dev/mapper/${CRYPT_VOLUME}

# Create LUKS volume in raw disk

cryptsetup luksFormat $CACHE_DISK
cryptsetup open --type luks $CACHE_DISK $CRYPT_VOLUME

# Started to try and work out disk size stuff but it's complex
# Have a go if you like, I kept running out of extents
#
# DISK_SIZE=$(fdisk -l | grep "Disk ${CACHE_DISK}" | awk ' { print $5 } ')
# 
# META_SIZE=$(( DISK_SIZE / 1000 ))
# META_SIZE=$(( META_SIZE + 512 ))
# MOD=$(( META_SIZE % 512 ))
# MOD_OFFSET=$((512 - MOD))
# META_SIZE=$((META_SIZE + 512)) 
# META_SIZE=$((META_SIZE + MOD_OFFSET))
# 
# DATA_SIZE=$(( DISK_SIZE - META_SIZE))
# 

# Create new PV inside encrypted volume

pvcreate $CACHE_PV
vgextend ubuntu-vg $CACHE_PV
lvcreate -L ${META_SIZE} -n cachemeta ubuntu-vg $CACHE_PV
lvcreate -L ${DATA_SIZE} -n cachedata ubuntu-vg $CACHE_PV
lvconvert --type cache-pool --poolmetadata ubuntu-vg/cachemeta --cachemode writethrough ubuntu-vg/cachedata --yes
lvconvert --type cache --cachepool ubuntu-vg/cachedata ubuntu-vg/root

# Now add the UUID of the cache pool PHYSICAL DRIVE (/dev/sdb) to /etc/crypttab
DISK_UUID=$(ls -al /dev/disk/by-uuid/ | grep $DISK_NAME | awk '{ print $9 }')
echo "${CRYPT_VOLUME} UUID=${DISK_UUID} none luks,discard" >> /etc/crypttab

apt-get install --yes thin-provisioning-tools

HOOK=$(tempfile)
# Add a hook script to initramfs to add the right tools and modules

echo "#!/bin/sh" > $HOOK
echo "PREREQ="lvm2"" >> $HOOK
echo "prereqs()" >> $HOOK
echo "{" >> $HOOK
echo "  echo \"$PREREQ\"" >> $HOOK
echo "}" >> $HOOK
echo "case $1 in" >> $HOOK
echo "prereqs)" >> $HOOK
echo "  prereqs" >> $HOOK
echo "  exit 0" >> $HOOK
echo "  ;;" >> $HOOK
echo "esac" >> $HOOK
echo "if [ ! -x /usr/sbin/cache_check ]; then" >> $HOOK
echo "  exit 0" >> $HOOK
echo "fi" >> $HOOK
echo ". /usr/share/initramfs-tools/hook-functions" >> $HOOK
echo "copy_exec /usr/sbin/cache_check" >> $HOOK
echo "manual_add_modules dm_cache dm_cache_mq dm_persistent_data dm_bufio" >> $HOOK

cp $HOOK /etc/initramfs-tools/hooks/lvmcache
chmod +x /etc/initramfs-tools/hooks/lvmcache

echo "dm_cache" >> /etc/initramfs-tools/modules
echo "dm_cache_mq" >> /etc/initramfs-tools/modules
echo "dm_persistent_data" >> /etc/initramfs-tools/modules
echo "dm_bufio" >> /etc/initramfs-tools/modules

# Update initramfs

update-initramfs -u

echo Now reboot!
  • 1. You suggest to blank your cache disk with zero but instead you should securely erase it with random data if you want to place an encrypted LUKS on it. 2. In your setup you have 2 LUKS partitions so even if you use the same passphrase you have to enter it twice, right ? – solsTiCe May 8 '15 at 16:00
  • 1. The random disk wipe is a bit outdated on modern hardware - zeroes are enough to put the disk beyond most non-academic level measures and certainly beyond commercial disk recovery labs. Unless the volume you're using previously held sensitive data, it's unnecessary as all the blocks written to it will be encrypted ; because of wear-levelling algorithms you shouldn't use an SSD that had plaintext sensitive data on it at all. 2. Yes, there are 2 LUKS partitions, as I say in the text, you'll be prompted for both passphrases during boot. – Adrian May 8 '15 at 16:51
  • the random wiping is NOT to securely delete data on SSD but to avoid scrutany and being able to distinguish encrypted data from blank like 00000000zerazer000000000000. Here you can see the encrypted data in the middle. this weaken your encryption instead of it being hidden in the middle of a random soup. – solsTiCe May 8 '15 at 17:02
  • I ended up going with this route after I got stuck setting up bcache. It looks like it's working pretty good: | cache_utilization_pct | 79.096846147 |. However in top I'm seeing iowait states 20-50% constantly. Could that be a side effect of the buffering? – Jean Jordaan Jul 14 '15 at 12:00
  • I can't really claim to know - but I'm guessing it might be a side-effect of the optimizations involved in minimizing writes to the SSD. Article about IOWait here : thattommyhall.com/2011/02/18/iops-linux-iostat – Adrian Jul 14 '15 at 15:20

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.