Setting Up Auto Mounting Encrypted Raid Disks

Standard

This is a little guide (currently under construction) for how I handle encrypted disks on Linux. This won’t be the ultimate ‘tin foil hat’ guide, as the attack vector this is intended to protect from is physical theft of the hardware, so that the data can’t be accessed from elsewhere. It obviously will not handle a targeted hacking attempt or the $5 wrench method, but I believe it gives security and convenience to a level appropriate for me.

xkcd 538: describing the $5 wrench method of breaking security.

The reason this started is because my physical health is deteriorating and getting up to enter a password at the console on every reboot is tiresome. Therefore I came up with a new way of handling encrypted drives to not only increase security but also make things a bit more convenient.

Of course before following any of these instructions, you should be aware of my standard disclaimer.

Caution – You need to secure the location of where you store your key. If you fail to secure your key with an appropriate mechanism, this entire exercise is fruitless.

Examples include: IP restricting access to your key provisioning system, using a strong username and password, using an easy to revoke token based storage mechanism, verifying HTTPs transfer certificates and countless others.

Included below is a method similar to what I use to secure where I store my keys.

Create a keyfile

dd bs=256 count=1 if=/dev/random | base64 > data-keyfile

Upload the keyfile somewhere, for example a HTTPS server with a valid certificate, or S3 or Azure key storage, and then make a script to download the key from where you put it. If you’re storing your key on a HTTPS server, here is an example htaccess file to secure access to the directory to specific IPs and a user/password section to further increase security. This works with Apache 2.4 but the syntax may be different for later versions.

order deny,allow
deny from all
allow from 192.168.1.100

Options -Indexes
AuthType Basic
AuthName "Restricted Access"
AuthUserFile "/secure/path/to/htpasswd"
Require valid-user

Once you have uploaded it somewhere don’t forget to delete the original source file securely from your system (for example with shred).

#!/bin/sh
set -e
# Request the file from somewhere, maybe blob storage, asure, S3 or HTTPS Server, then pipe it through `base64 -d` to decode it from base64
curl -s --basic --user username:password "https://example.net/data-keyfile" | base64 -d

Then move the script somewhere and give it the right permissions

# Ensure the owner of this file is "root"
chown root:root /etc/luks/get-key.sh
# Allow only the owner (root) to read and execute the script
chmod 0500 /etc/luks/get-key.sh

Create the raid

# if all drives are already blank and ready to be added. Replace drives as appropriate.
mdadm --create /dev/md2 -l 1 -n 2 /dev/sdc1 /dev/sdd1
# if you need to create a 'degraded' array with a drive missing.
mdadm --create /dev/md2 -l 1 -n 2 /dev/sdc1 missing

Then encrypt the array

# Encrypt the disk
# Replace md2 with the correct array!
/etc/luks/get-key.sh | cryptsetup -d - -v luksFormat /dev/md2

# Open the encrypted volume, with the name "data"
# Replace md2 with the correct array!
/etc/luks/get-key.sh | cryptsetup -d - -v luksOpen /dev/md2 data

# Create a filesystem on the encrypted volume
mkfs.ext4 -F /dev/mapper/data

# Close the encrypted volume
cryptsetup -v luksClose data

Find the encrypted partitions UUID

$ lsblk --fs
NAME    FSTYPE      LABEL           UUID
[..]
sdc
└─sdc1         linux_raid_mem server:1 a38cbabe-0f12-3643-f3232-998822c5d42
  └─md2        crypto_LUKS             a17db19d-5037-4cbb-b50b-c85e3e074864 

Then create a script to run on boot to automount

#!/bin/bash
if [ -b "/dev/mapper/data" ]
	then
		if [[ $(findmnt -M "/disks/data") ]]; then
		:
		else
    		echo "Not mounted but unlocked... trying to mount..."
	mount -t ext4 -o errors=remount-ro /dev/mapper/data /disks/data
		fi
	else
		curl -s --basic --user username:password "https://example.net/data-keyfile" | base64 -d | /sbin/cryptsetup -d - -v luksOpen /dev/disk/by-uuid/a17db19d-5037-4cbb-b50b-c85e3e074864 data
		mount -t ext4 -o errors=remount-ro /dev/mapper/data /disks/data
fi

if [[ $(findmnt -M "/disks/data") ]]; then
# Anything you want to run after the disks are mounted
		echo "All disks mounted, starting services..."
		echo "Starting samba..."
		systemctl start smbd
fi

and add it to root’s crontab on reboot.

# m h  dom mon dow   command
@reboot sleep 30 && /etc/luks/start-crypto.sh

Don’t forget to disable any services you don’t want to run until the encrypted drives are mounted, for example samba

systemctl disable smbd

Create the mount point

mkdir /disks/data

And finally a script to stop encrypted drives (if required)

#!/bin/bash
echo "Stopping Samba..."
systemctl stop smbd

if [[ $(findmnt -M  "/disks/data") ]]; then
    echo "/disks/data is mounted, trying to unmount..."
	umount /dev/mapper/data
    echo "Attempting to close luks on /dev/mapper/data ..."
	if [ -b /dev/mapper/data ]
		then
		/sbin/cryptsetup -d - -v luksClose data
	fi
else
	if [ -b /dev/mapper/data ]
	then
    	echo "/disks/data is not mounted, but is unlocked, will attempt to close ...."
	/sbin/cryptsetup -d - -v luksClose data
	else
	echo "/disks/data is not unlocked or mounted, nothing to do."
	fi
fi

This work was inspired by an article on https://withblue.ink/2020/01/19/auto-mounting-encrypted-drives-with-a-remote-key-on-linux.html by Alessandro Segala and adapted/changed to meet my requirements.

Leave a Reply

Your email address will not be published. Required fields are marked *