Loading...
Linux cheat sheets

LUKS setup with cryptsetup

Introduction

LUKS encryption (and similar offerings such as Vormetric) protect data “at rest”. Fundamentally, this means that the filesystem is “unlocked” when it is mounted and the contents can be freely read or modified as if there was no encryption in use. When the protected filesystem is unmounted (or the server is powered down), the filesystem is “locked” such that its contents cannot be read until the appropriate key (typically a passphrase of some kind) is provided. As data can be freely accessed once the filesystem is mounted (with the key), LUKS cannot prevent data access on a running system with the encrypted filesystem(s) mounted. It only protects data “at rest” such as a case where a hard disk is lost or stolen.

At rest encryption can also protect data on SAN LUNs. While rare, it is possible to incorrectly present a SAN volume to another server. This server could then mount the filesystem and manipulate the data. With LUKS, this is only possible if the attacker has access to the key.

Many customers have compliance requirements that demand that measures be taken to prevent the inappropriate access to data if a server or hard drive is lost or stolen. These customers often ask for data at rest encryption to satisfy this requirement, but it may not be the most appropriate solution

What We Support

  • Setting up a LUKS encrypted partition that is not a root or boot partition.
  • Decryption of a partition on boot (that is not a root or boot partition).

What We Do Not Support

  • LUKS encryption for the whole root partition.
  • We do NOT offer manually decrypting the root filesystem on boot – this a burden that GTS Support or DCOps do not wish to take onboard.
  • Additionally, automatically decrypting the root partition on boot is self-defeating.
  • Setting up or management of any key management server or infrastructure. No Network Bound Disk Encryption (NBDE).
    • The customer might be better suited to the Vormetric offering.

Setup Steps

Required packages

Debian/Ubuntu:
apt-get install cryptsetup-luks
CentOS/Red Hat:
yum install cryptsetup-luks

Create the new partition

Create a single full disk GPT partition using your preferred method, and ensure its visible to the OS:
# ls /dev/xvdb*
/dev/xvdb  /dev/xvdb1

Scrub

At this point if you want to ensure the disk is clean before you configure LUKS you can write zeroes to the new partition using dd. This will prevent old data from being recoverable if any was present on the disk.
# dd if=/dev/zero of=/dev/xvdb1
dd: writing to ‘/dev/xvdb1’: No space left on device
2095072+0 records in
2095071+0 records out
1072676352 bytes (1.1 GB) copied, 7.05075 s, 152 MB/s

Format the New Partition with LUKS

NOTE1: You may wish to LVM the partition first before adding the LUKS volume into a logical volume, allowing potential expansions in the future (see the section below).

NOTE2: All data on the specified partition will be permanently deleted. Take care when entering the partition information.

You can change the cipher, key size and hash function if the customer explicitly requests something using options to cryptsetup. But otherwise we’ll devolve this decision to the OS vendor defaults. You can see what this is by running:
$ cryptsetup –help | grep LUKS1
LUKS1: aes-xts-plain64, Key: 256 bits, LUKS header hashing: sha256, RNG:
/dev/urandom
# pwgen -cny 16 1
(to generate a suitable password)
# cryptsetup –verbose –verify-passphrase luksFormat /dev/xvdb1

WARNING!

This will overwrite data on /dev/xvdb1 irrevocably.
Are you sure? (Type uppercase yes): YES
Enter passphrase:
Verify passphrase:
Command successful.

Open LUKS volume to create the mapped device

# cryptsetup luksOpen /dev/xvdb1 myvol
Enter passphrase for /dev/xvdb1:
# ls /dev/mapper/ | grep myvol

myvol

Create the filesystem on the newly mapped device

You will be using the mapped device instead of directly using the previously created partition:

# mkfs.xfs /dev/mapper/myvol

Mount the new filesystem at the desired location

# mkdir /myvol
# mount /dev/mapper/myvol /myvol/
# mount | grep myvol
/dev/mapper/myvol on /myvol type xfs
(rw,relatime,seclabel,attr2,inode64,noquota)

Mount a LUKS encrypted filesystem at boot

This NEEDS to be tested to confirm a reboot will be sucessful. Too many “Surprise! The server doesn’t boot” issues.

Find the UUID of the encrypted volume

# blkid | grep crypto_LUKS
/dev/xvdb1: UUID=”69b2adac-f640-492b-9e80-1cbcd9c88df4″ TYPE=”crypto_LUKS”
PARTLABEL=”Linux filesystem” PARTUUID=”bf8db559-f3ff-428e-a308-8feaa28c3ef4″

Add device to /etc/crypttab (without key file)

This will require the password be manually entered when the system is booted.
# cat /etc/crypttab
myvol UUID=”69b2adac-f640-492b-9e80-1cbcd9c88df4″

# Note: In this example, “myvol” needs to be used in /etc/fstab since that path will now end up being /dev/mapper/myvol

Add device to /etc/crypttab (with key file)

# cat /etc/crypttab

myvol UUID=”69b2adac-f640-492b-9e80-1cbcd9c88df4″ /root/keyfile luks

Creating lukskey

# dd if=/dev/random bs=32 count=1 of=/root/lukskey
1+0 records in
1+0 records out
32 bytes (32 B) copied, 0.00015331 s, 209 kB/s
# cryptsetup luksAddKey /dev/xvdb1 /root/lukskey

# Note: You should enter the password used in LUKS format

Update /etc/fstab

/dev/mapper/myvol    /myvol    xfs    defaults 0 0
# Note: “myvol” is taken from /etc/cryttab, first column

Ensure $VOLUMENAME in your /dev/mapper/$VOLUMENAME matches the first column in your /etc/cryttab

TEST

Testing LUKS mapping

Linux distros using SysV

This includes only Red Hat based distros < 6

Test crypttab:

crypttab
# source /etc/init.d/functions
# init_crypto
This takes care of reading /etc/crypttab and map (open) LUKS devices as defined in /etc/crypttab.

Then test fstab:
mount
# mount -a
This should mount the mapped LUKS device in the defined mount point.

To undo the tested changes:

  • umount the mounted fs.
  • close the LUKS device.

Linux distros using systemd

Red Hat based distros 7+, Debian 8+, Ubuntu 16+

The crypttab file is read through a systemd target cryptsetup.target. This target pulls in service units that are dynamically created based on the entries of crypttab.
Each entry in the crypttab file generates dynamically a cryptsetup service during boot time or in a configuration reload (daemon-reload) of systemd. Those dynamically generated services are created under /run/systemd/generator/. Generators are executed before unit files are loaded.

To test restart systemd daemon:

systemd reload
# systemctl daemon-reload
This will place the service under /run/systemd/generator/ and will load the service, then verify the service succeeded and the LUKS fs has been created:

Verification

# systemctl status systemd-cryptsetup@<NAME_OF_LUKS_DEVICE>.service
Successful test…
In this example:

  • The LUKS device is named encrypted0 (this is the first item in the /etc/crypttab file)
  • The UUID is set to 2c7fbe9f-1fc7-4742-b7a8-e036117f7189
  • The key is /dev/mykey

# systemctl status systemd-cryptsetup@encrypted0.service
● systemd-cryptsetup@encrypted0.service – Cryptography Setup for encrypted0

Loaded: loaded (/etc/crypttab; generated)
Active: active (exited) since Thu 2018-09-13 14:25:23 CDT; 8s ago
     Docs: man:crypttab(5)          
man:systemd-cryptsetup-generator(8)          
man:systemd-cryptsetup@.service(8)

Process: 13074 ExecStart=/usr/lib/systemd/systemd-cryptsetup attach  encrypted0
/dev/disk/by-uuid/2c7fbe9f-1fc7-4742-b7a8-e036117f7189 /etc/mykey
(code=exited, status=0/SUCCESS)
Main PID: 13074 (code=exited, status=0/SUCCESS)
CPU: 2.063s
Sep 13 14:25:21 example.com systemd[1]: Starting Cryptography Setup for encrypted0…
Sep 13 14:25:21 example.com systemd-cryptsetup[13074]: Set cipher aes, mode
xts-plain64, key size 256 bits for device /dev/disk/by-uuid/2c7fbe9f-1fc7-4742-b7a8-e036117f7189.
Sep 13 14:25:23 example.com systemd[1]: Started Cryptography Setup for encrypted0
Search for the device created under /dev/mapper:
data-syntaxhighlighter-params=”brush: plain; gutter: false; theme: Confluence” data-theme=”Confluence”># ls /dev/mapper/encrypted0
encrypted0
NOTE: If the entry is already in /etc/fstab then systemd will automatically mount it
Unsuccessful test…
In this example:

  • The LUKS device is named encrypted0 (this is the first item in the /etc/crypttab file)
  • The UUID is set to 2c7fbe9f-1fc7-4742-b7a8-e036117f7189
  • The key is /dev/mykey
    • NOTE 1: The key has too open permissions
    • NOTE 2: The key content is invalid

# systemctl status systemd-cryptsetup@encrypted0.service
● systemd-cryptsetup@encrypted0.service – Cryptography Setup for encrypted0
Loaded: loaded (/etc/crypttab; generated)
Active: activating (start) since Thu 2018-09-13 13:30:39 CDT; 43s ago
Docs: man:crypttab(5)
man:systemd-cryptsetup-generator(8)
man:systemd-cryptsetup@.service(8)
Main PID: 15628 (systemd-cryptse)
Tasks: 1 (limit: 4915)
Memory: 1.0M
CPU: 2.043s
CGroup: /system.slice/system-systemd\x2dcryptsetup.slice/systemd-cryptsetup@encrypted0.service

 └─15628 /usr/lib/systemd/systemd-cryptsetup attach encrypted0
/dev/disk/by-uuid/2c7fbe9f-1fc7-4742-b7a8-e036117f7189 /etc/mykey luks
Sep 13 13:30:39 example.com systemd[1]: Starting Cryptography Setup for encrypted0…
Sep 13 13:30:39 example.com systemd-cryptsetup[15628]: Key file /etc/mykey is
world-readable. This is not a good idea!
Sep 13 13:30:39 example.com systemd-cryptsetup[15628]: Set cipher aes, mode xts-plain64,
key size 256 bits for device /dev/disk/by-uuid/2c7fbe9f-1fc7-4742-b7a8-e036117f7189.
Sep 13 13:30:41 example.com systemd-cryptsetup[15628]: Failed to activate with key file
‘/etc/mykey’: Operation not permitted
Removing the entry of a LUKS fs from /etc/crypttab and reloading systemd daemon will not close (remove) the mapping from device mapper. It requires manual intervention, see the undo instructions below.

To undo the tested changes:

  • umount the mounted fs
  • comment out the tested entry in /etc/crypttab then reload systemd daemon (this step only takes care of removing the generated unit service)

close the LUKS device

Expand an existing LUKS encrypted filesystem

This work has been performed on CentOS 6.8 & tested on RHEL 6.6

Filesystem Layering

In this particular case, the Filesystem (EXT4) was layered on top of the Luks Encrypted Drive, which was layered on top of the LVM.

|————– EXT4 -|
|——– LUKS ———|
|- LVM ——————-|

The Expansion

Given the parameters and layering above, the general process is the following:
Once you have added the new disk/LUN proceed as any other LVM, part the new disk with the LVM flag.
gdisk /dev/xvdb
Create the new physical volume.
pvcreate /dev/xvdb2
Extend the LUKS volume group into the new disk/LUN.
vgextend myvol /dev/xvdb2

  • Expand the Logical Volume (Assuming space is available in the volume group to perform this, replace {ADDSIZE} with value)

lvextend -L +{ADDSIZE}G /dev/mapper/vgname-lvname

  • Extend the LUKS-Encryption (‘luksDevName’ is name of the created luks device, you should see this in /dev/mapper/, /etc/crypttab and likely this will be the filesystem mounted at your mount point). You can specify size(–size flag) in sectors, if not specified the underlying device size will be used.

cryptsetup –verbose resize luksDevName

  • Note that this will reply with a simple ‘Command Successful.’
  • Extend the Filesystem layer

resize2fs /dev/mapper/luksDevName

  • Confirm new sizes everywhere and verify you’re still seeing the overlying data.

lvs && df -h && ls -l /path/to/mount/

Key maintenance

Key files are optional at this step but need specified if that is the target of the change, otherwise it is assumed a passphrase will be used.

Add an additional passphrase/key to a volume

cryptsetup luksAddKey <device> [–key-file <key file>]

Note: on EL7 (at least), you don’t specify the “–key-file” part. Just put the key path after the device path. Docs state:

luksAddKey <device> [<new key file>] – add key to LUKS device

Remove passphrase/key from volume

cryptsetup luksRemoveKey <device> [–key-file <key file>]

Change a passphrase/key on a volume

The following will change the specified passphrase only. Any others, include keys, will not be affected.
cryptsetup luksChangeKey <device> [–key-file <key file>]

Create keyfile for LUKS volumes

# dd if=/dev/urandom of=/root/keyfile bs=1024K count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB) copied, 0.0981758 s, 10.7 MB/s
Add the key to the encrypted volume, you will need to provide any current and valid passphrase

Show LUKS header information

# cryptsetup luksDump /dev/xvdb1
LUKS header information for /dev/xvdb1
Version:                 1
cipher name:       aes
Cipher mode:       xts-plain64
Hash spec:            sha1
Payload offset:     4096
MK bits:                 256
MK digest:            ef 3b c1 4d 07 e2 0d b8 23 2f 8c 60 dd a1 e2 83 a3 9c 22 d8
MK salt:               c0 ce b3 5a 90 97 68 12 91 0e 59 30 06 6b e9 00
ab 02 ad 6b d2 a0 8d a5 41 c2 c4 27 4f fb 2b d3
MK iterations:     41125
UUID:              69b2adac-f640-492b-9e80-1cbcd9c88df4
Key Slot 0: ENABLED
Iterations:             159203
Salt:                         c6 62 44 c5 0d 0f 2a a5 41 ab 7b 98 80 8f 65 17       d1 28 e4 51 46 a4 a0 d4 23 94 04 08 a9 b8 0d ea Key material offset:    8

AF stripes:                4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

Leave a Reply

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