Search My Blog

Friday, January 30, 2015

DM-CRYPT (LUKS) Setup on New Volume / Mount Point or EBS Volume


I have recently had to do some work complying with "encryption at rest" of various data. There are many ways to handle this, but the target environment in my case was completely cloud-based and doesn't really allow for user-interaction during the boot process (to enter a password to decrypt the drive before boot time). Many solutions like TrueCrypt, Checkpoint, even full disk encryption using LUKS will require a password entry before boot, since the boot volume is encrypted. To avoid this issue during boot, but meet the requirement, I chose to use native LUKS (Linux Unified Key Setup) and only encrypt one volume/mount point.

I'm doing the setup for this tutorial on a Fedora 21 VM hosted on Oracle VirtualBox. I chose to add an empty new virtual hard drive off of my VM in VirtualBox. In Amazon AWS, you would add a new EBS volume to your EC2 instance. This setup will be the same on most Linux distros in either environment.

NOTE: All of this is performed as root.

Step #1: Make sure the required cryptsetup libraries are on your machine. If not install them.

[root@localhost juser]# cryptsetup --version
cryptsetup 1.6.6
In this case, it is present. This library is standard on most newer Linux distros. If you need to install it. You can install it with yum or apt-get.

[root@localhost juser]# yum install cryptsetup
 or (depending on Linux distro)
[root@localhost juser]# apt-get update
[root@localhost juser]# apt-get install cryptsetup
Step #2: Figure out where the mount point is (i.e. what device is is?)

  To determine this, we are going to run a few fdisk commands to determine the device and if it is empty and matches my known drive size. For this example, I'm using a 1GB drive. It will show up as /dev/sdb. In an Amazon AMI, this mount point will be /dev/xvdb.

[root@localhost juser]# fdisk -l

Disk /dev/sda: 40 GiB, 42949672960 bytes, 83886080 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5e44e428

Device     Boot   Start      End  Sectors  Size Id Type
/dev/sda1  *       2048  1026047  1024000  500M 83 Linux
/dev/sda2       1026048 83886079 82860032 39.5G 8e Linux LVM

Disk /dev/sdb: 1 GiB, 1073741824 bytes, 2097152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/mapper/fedora--server-swap: 3.9 GiB, 4160749568 bytes, 8126464 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/mapper/fedora--server-root: 35.6 GiB, 38214303744 bytes, 74637312 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


[root@localhost juser]# ls -lart /dev/sd*
brw-rw----. 1 root disk 8,  0 Jan 30 17:08 /dev/sda
brw-rw----. 1 root disk 8,  2 Jan 30 17:08 /dev/sda2
brw-rw----. 1 root disk 8,  1 Jan 30 17:08 /dev/sda1
brw-rw----. 1 root disk 8, 16 Jan 30 17:12 /dev/sdb
[root@localhost juser]#
[root@localhost juser]# fdisk -l /dev/sdb

Disk /dev/sdb: 1 GiB, 1073741824 bytes, 2097152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
[root@localhost juser]#
[root@localhost juser]# echo -e "p\nq\n" | fdisk /dev/sdb

Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xb558ecd7.

Command (m for help): Disk /dev/sdb: 1 GiB, 1073741824 bytes, 2097152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xb558ecd7

Command (m for help):
[root@ocalhost juser]#
Step #3: Partition the volume using fdisk

  I'm going to partition the volume and use the whole 1GB that I have available. You could make multiple volumes within the mount point, but I'm not going to cover that here. After it is partitioned, I check it and see that it is /var/sdb1.  In an Amazon AMI, this mount point will be /dev/xvdb1.

[root@localhost juser]# echo -e "n\np\n1\n\n\nw\n" | fdisk /dev/sdb

Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x60e686b4.

Command (m for help): Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): Partition number (1-4, default 1): First sector (2048-2097151, default 2048): Last sector, +sectors or +size{K,M,G,T,P} (2048-2097151, default 2097151):
Created a new partition 1 of type 'Linux' and of size 1023 MiB.

Command (m for help): The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

[root@localhost juser]# fdisk -l /dev/sdb

Disk /dev/sdb: 1 GiB, 1073741824 bytes, 2097152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x60e686b4

Device     Boot Start     End Sectors  Size Id Type
/dev/sdb1        2048 2097151 2095104 1023M 83 Linux

[root@localhost juser]#

Step #4: Fill it with random data (optional, but a best practice)

 [root@localhost juser]# dd if=/dev/urandom of=/dev/sdb1
dd: writing to ‘/dev/sdb1’: No space left on device
2095105+0 records in
2095104+0 records out
1072693248 bytes (1.1 GB) copied, 102.281 s, 10.5 MB/s
[root@localhost juser]#
 
Step #5: Format it with luksFormat

[root@localhost juser]# cryptsetup luksFormat /dev/sdb1

WARNING!
========
This will overwrite data on /dev/sdb1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase: 
(PasswordYouChooseTypedHere)
Verify passphrase: (PasswordYouChooseTypedHere)
[root@localhost juser]#


Step #6: Mount it with luksOpen to /dev/mapper

[root@localhost juser]# cryptsetup luksOpen /dev/sdb1 encrypted_drive
Enter passphrase for /dev/sdb1:
[root@localhost juser]# ls -lart /dev/mapper
total 0
crw-------.  1 root root 10, 236 Jan 30 17:08 control
lrwxrwxrwx.  1 root root       7 Jan 30 17:08 fedora--server-swap -> ../dm-0
lrwxrwxrwx.  1 root root       7 Jan 30 17:08 fedora--server-root -> ../dm-1
drwxr-xr-x. 20 root root    3260 Jan 30 17:58 ..
lrwxrwxrwx.  1 root root       7 Jan 30 17:58 encrypted_drive -> ../dm-2
drwxr-xr-x.  2 root root     120 Jan 30 17:58 .
[root@localhost juser]#
Step#7: Create an EXT4 filesystem on the encrypted drive

[root@localhost juser]# mkfs.ext4 /dev/mapper/encrypted_drive
mke2fs 1.42.11 (09-Jul-2014)
Creating filesystem with 261376 4k blocks and 65408 inodes
Filesystem UUID: dbd52a8d-2a7e-4bfc-83ff-cbade6e715d4
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376

Allocating group tables: done                          
Writing inode tables: done                          
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

[root@localhost juser]#

Step #8: Add it to /etc/fstab and mount it for use

[root@localhost juser]# mkdir /encrypted_drive
[root@localhost juser]# chmod 777 /encrypted_drive
(Should really be 755, but I'm just making it world writable for this example)
 
[root@localhost juser]# echo -e "/dev/mapper/encrypted_drive /encrypted_drive ext4 defaults 0 0" >> /etc/fstab
[root@localhost juser]# mount -a
[root@localhost juser]# df -h
Filesystem                       Size  Used Avail Use% Mounted on
/dev/mapper/fedora--server-root   35G  5.8G   28G  18% /
devtmpfs                         2.0G     0  2.0G   0% /dev
tmpfs                            2.0G  100K  2.0G   1% /dev/shm
tmpfs                            2.0G  752K  2.0G   1% /run
tmpfs                            2.0G     0  2.0G   0% /sys/fs/cgroup
tmpfs                            2.0G   60K  2.0G   1% /tmp
/dev/sda1                        477M  116M  332M  26% /boot
tmpfs                            396M   12K  396M   1% /run/user/1000
tmpfs                            396M     0  396M   0% /run/user/0
/dev/mapper/encrypted_drive      989M  1.3M  921M   1% /encrypted_drive
[root@localhost juser]#

 At this point, the drive is usable and will be encrypted. However, it will not remount at boot and you will have to manually cryptsetup luksOpen then mount -a at it every boot. This is disadvantageous. So, next we are going to create a keyfile and associate it with the drive. This will allow it to auto mount at boot.

Step #9: Add keyfile and add /etc/crypttab entry
[root@localhost juser]# echo -e "(Password from Step 5)" >> /root/encrypted_drive.key
[root@localhost juser]# echo -e "encrypted_drive  /dev/sdb1  /root/encrypted_drive.key  luks" >> /etc/crypttab
[root@localhost juser]# cryptsetup luksAddKey /dev/sdb1 /root/encrypted_drive.key
Enter any passphrase: (Password from Step 5)
[root@localhost juser]#

Step #10: Reboot your server and the drive should auto mount.

 After rebooting, open a console and see if the drive is present.....
[juser@localhost ~]$ df -h
Filesystem                       Size  Used Avail Use% Mounted on
/dev/mapper/fedora--server-root   35G  5.8G   28G  18% /
devtmpfs                         2.0G     0  2.0G   0% /dev
tmpfs                            2.0G  100K  2.0G   1% /dev/shm
tmpfs                            2.0G  732K  2.0G   1% /run
tmpfs                            2.0G     0  2.0G   0% /sys/fs/cgroup
tmpfs                            2.0G   64K  2.0G   1% /tmp
/dev/sda1                        477M  116M  332M  26% /boot
/dev/mapper/encrypted_drive      989M  1.3M  921M   1% /encrypted_drive
tmpfs                            396M  8.0K  396M   1% /run/user/1000
[juser@localhost ~]$
Hope this posting helps folks trying to setup an encrypted volume that auto mounts at boot time.

1 comment: