Configure LUKS Network Bound Disk Encryption with clevis & tang server

In this article I will share the steps to configure CentOS/Red Hat Network Bound Disk Encryption (NBDE).
 
In our earlier articles we studied all about encrypting different types of disk devices and auto mount those LUKS devices to boot without password by using a key (/etc/crypttab) instead of passphrase.

Now with those steps you have an overhead to create a key on individual Linux server (luksAddkey) to boot without password. Assuming you have 100s of server then it will be very time consuming task.
 
Starting with RHEL 7.4 we can configure Network Bound Disk Encryption to use key from a specific LUKS Server to auto unmount LUKS device on client nodes within a network and boot without password.

 

We will cover below topics in this article

  • Installing and enabling tang server
  • Configuring the firewall for tang
  • Showing the tang keys under /var/db/tang
  • Installing the clevis, clevis-luks, and clevis-dracut packages on the client
  • Using "clevis luks bind" to bind to the tang server
  • Using "dracut -f" to generate a new initramfs
  • Simulating the client being removed from the environment, and no longer being able to connect to the tang server

 

Policy Based Decryption

The Policy-Based Decryption (PBD) is a collection of technologies that enable unlocking encrypted root and secondary volumes of hard drives on physical and virtual machines. The Network Bound Disk Encryption (NBDE) is a subcategory of PBD that allows binding encrypted volumes to a special network server to boot without password. The current implementation of the NBDE uses Clevis and Tang encryption which includes a Clevis pin for Tang server and the Tang server itself.

 

Let us understand some new terminologies we will use in this article

Tang:

Tang is a server for binding data to network presence. It makes a system containing your data available when the system is bound to a certain secure network. Tang is stateless and does not require TLS or authentication.

 

Clevis:

Clevis is a pluggable framework for automated decryption. In NBDE, Clevis provides automated unlocking of LUKS volumes. The clevis package provides the client side of the feature.

 

Clevis and Tang encryption are generic client and server components that provide network bound disk encryption. In Red Hat Enterprise Linux, they are used in conjunction with LUKS to encrypt and decrypt root and non-root storage volumes to accomplish Network Bound Disk Encryption (NBDE).

Both client- and server-side components use the José library to perform encryption and decryption operations.

 

How Network Bound Disk Encryption (NBDE) works?

  • The Clevis pin for Tang Server uses one of the public keys to generate a unique, cryptographically-strong encryption key.
  • Once the data is encrypted using this key, the key is discarded. This process of encrypting data is the provisioning step.
  • When the client is ready to access its data, it loads the metadata produced in the provisioning step and it responds to recover the encryption key. This process is the recovery step.
  • In NBDE, Clevis binds a LUKS volume using a pin so that it can be automatically unlocked.
  • After successful completion of the binding process, the disk can be unlocked using the provided Dracut unlocker.

 

Lab Environment

I have created two Virtual Machines to configure Clevis and Tang Encryption on Oracle VirtualBox wherein the server is installed with RHEL 8.1 while client is installed with CentOS 8.0

On my client node centos-8, I have already migrated my entire root file system to LUKS encrypted device which now requires a key every time I reboot the node. So on my client I will install and configure clevis while on my server, rhel-8 I will configure tang server to perform Network Bound Disk Encryption (boot without password) every time my client centos-8 reboots.

Server → rhel-8.example.com → 192.168.0.121 → RHEL 8.1
Client → centos-8.example.com → 192.168.0.119 → CentOS 8.0

Below are the OS installed on my client and server node.

[root@centos-8 ~]# cat /etc/redhat-release
CentOS Linux release 8.0.1905 (Core)

[root@rhel-8 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux release 8.1 (Ootpa)

 

Configure Server (RHEL 8)

We will configure tang server using it's default port and settings on rhel-8 which will act as our server. By default tang is configured to use port 80 but you can also configure tang server to use a different custom port for enhanced security.

 

Install and Configure Tang server

To enable Clevis and tang Encryption, we will first install tang rpm on our server node using yum

NOTE:

On RHEL system you must have an active subscription to RHN or you can configure a local offline repository using which "yum" package manager can install the provided rpm and it's dependencies.
[root@rhel-8 ~]# yum -y install tang

Next start and enable the tangd socket. Because tangd uses the systemd socket activation mechanism, the server starts as soon as the first connection comes in. A new set of cryptographic keys is automatically generated at the first start.

[root@rhel-8 ~]# systemctl enable tangd.socket --now
Created symlink /etc/systemd/system/multi-user.target.wants/tangd.socket → /usr/lib/systemd/system/tangd.socket.

For testing purpose I have disabled firewalld, nftables and selinux in my setup

[root@rhel-8 ~]# systemctl disable firewalld --now

But if you wish to use firewalld, then you can add below rule

# firewall-cmd --add-port=80/tcp
# firewall-cmd --runtime-to-permanent
NOTE:

If you wish to use different port to configure tang server, you can provide the respective port in firewalld rule assuming the port you select is 7500

# firewall-cmd --add-port=7500/tcp
# firewall-cmd --runtime-to-permanent

Similarly for selinux use semanage port -a -t tangd_port_t -p tcp 7500
Also, you must add below content in /etc/systemd/system/tangd.socket.d/override.conf

[Socket]
ListenStream=
ListenStream=7500

And reload the changed configuration:

# systemctl daemon-reload

Check that your configuration is working:

[root@rhel-8 ~]# systemctl show tangd.socket -p Listen
Listen=[::]:80 (Stream)

 

List tang server keys

The keys from tang server are available under /var/db/tang which will be used for Network Bound Disk Encryption (NBDE) by client.

[root@rhel-8 ~]# ls -l /var/db/tang/
total 8
-rw-r--r-- 1 root tang 349 Nov 21 11:36 7VXZSkDbTEqqIh7TqoXG6u82LK0.jwk
-rw-r--r-- 1 root tang 354 Nov 21 11:36 -NYm6-gTZ9dquHe6zy9ynGU8SAI.jwk

Now we will open a terminal of our tang server and execute journalctl -f to monitor the live incoming logs on our tang server i.e. rhel-8.example.com

[root@rhel-8 ~]# journalctl -f
-- Logs begin at Wed 2019-11-20 17:52:06 IST. --
Nov 21 11:46:12 rhel-8.example.com tangd[4454]: 192.168.0.119 POST /rec/7VXZSkDbTEqqIh7TqoXG6u82LK0 => 200 (src/tangd.c:168)
Nov 21 11:48:33 rhel-8.example.com systemd[1]: Started Tang Server (192.168.0.119:53408).
Nov 21 11:48:33 rhel-8.example.com tangd[4461]: 192.168.0.119 POST /rec/7VXZSkDbTEqqIh7TqoXG6u82LK0 => 200 (src/tangd.c:168)
Nov 21 11:49:49 rhel-8.example.com systemd[1]: Started Tang Server (192.168.0.119:60284).
Nov 21 11:49:49 rhel-8.example.com tangd[4465]: 192.168.0.119 POST /rec/7VXZSkDbTEqqIh7TqoXG6u82LK0 => 200 (src/tangd.c:168)

 

Configure Client

Next continue with the clevis and tang encryption configuration on client node centos-8 . Connect to client node centos-8 using a terminal or ssh client.

Now we have already migrated our entire file system to LUKS encrypted device which now prompts for password in every reboot. Here we wish to configure Network Based Disk Encryption to enable boot without password using the keys from tang server (rhel-8) to unlock the LUKS device.

 

Install and configure Clevis

To automatically unlock an existing LUKS-encrypted root volume and boot without password install these packages on client node which contains the LUKS encrypted partition:

[root@centos-8 ~]# yum -y install clevis clevis-luks clevis-dracut

Verify the available key slots using luksDump. As you see highlighted section we currently only have one key slot used i.e. 0:luks2

[root@centos-8 ~]# cryptsetup luksDump /dev/sdb1
<Output trimmed>
Keyslots:
  0: luks2
        Key:        256 bits
        Priority:   normal
        Cipher:     aes-xts-plain64
        PBKDF:      argon2i
        Time cost:  4
        Memory:     572835
        Threads:    1
        Salt:       2b f5 65 0e 50 36 d9 5a 2c 90 e9 e6 61 c8 db bc
                    ba 86 1b cd ea 79 cd b8 b1 cc 8d 20 84 29 fb 87
        AF stripes: 4000
        Area offset:32768 [bytes]
        Area length:131072 [bytes]
        Digest ID:  0
<Output trimmed>

 

Identity the LUKS device

Identify the LUKS-encrypted volume for Policy Based Decryption using NBDE. In the following example, the block device is referred as /dev/sdb1:

[root@centos-8 ~]# blkid -t TYPE=crypto_LUKS -o device
/dev/sdb1

So our LUKS encrypted device is /dev/sdb1

To enable Clevis and tang Encryption, bind the encrypted volume to a tang server using the clevis luks bind command:

[root@centos-8 ~]# clevis luks bind -d /dev/sdb1 tang '{"url":"192.168.0.121"}'
The advertisement contains the following signing keys:

-NYm6-gTZ9dquHe6zy9ynGU8SAI

Do you wish to trust these keys? [ynYN] Y
Enter existing LUKS password:

 

This command performs four steps:

  • Creates a new key with the same entropy as the LUKS master key.
  • Encrypts the new key with Clevis.
  • Stores the Clevis JWE object in the LUKS2 header token or uses LUKSMeta if the non-default LUKS1 header is used.
  • Enables the new key for use with LUKS.
NOTE:

The binding procedure assumes that there is at least one free LUKS password slot. The clevis luks bind command takes one of the slots.

The LUKS encrypted volume can now be unlocked with your existing password as well as with the Clevis policy.

 

Now if you verify we have two keys installed for our LUKS encrypted device as highlighted:

[root@centos-8 ~]# cryptsetup luksDump /dev/sdb1
<Output trimmed>
Keyslots:
  0: luks2
        Key:        256 bits
        Priority:   normal
        Cipher:     aes-xts-plain64
        PBKDF:      argon2i
        Time cost:  4
        Memory:     572835
        Threads:    1
        Salt:       2b f5 65 0e 50 36 d9 5a 2c 90 e9 e6 61 c8 db bc
                    ba 86 1b cd ea 79 cd b8 b1 cc 8d 20 84 29 fb 87
        AF stripes: 4000
        Area offset:32768 [bytes]
        Area length:131072 [bytes]
        Digest ID:  0
  1: luks2
        Key:        256 bits
        Priority:   normal
        Cipher:     aes-xts-plain64
        PBKDF:      argon2i
        Time cost:  4
        Memory:     560933
        Threads:    1
        Salt:       11 4b dd b5 f7 c9 72 74 90 a5 3e b2 7e 37 37 fa
                    e0 42 d5 7d 7e 18 19 56 ec c4 31 e3 cb 4b 25 d6
        AF stripes: 4000
        Area offset:163840 [bytes]
        Area length:131072 [bytes]
        Digest ID:  0
<Output trimmed>

To enable the early boot system to process the disk binding and boot without password, enter the following commands on an already installed system:

[root@centos-8 ~]# dracut -f

We are all set up here, now you can reboot the client node centos-8 and observe the node console.

 

Here as you see, during boot up stage the client prompts for LUKS encrypted passphrase for our root file system. But after waiting for few seconds it gets the key from the tang server (rhel-8) and continues to boot without password.

 

Lastly I hope the steps from the article to configure Network Bound Disk Encryption and enable boot without password using clevis and tang encryption on CentOS/RHEL 7/8 Linux was helpful. So, let me know your suggestions and feedback using the comment section.

 

References:
How to set up Network Bound Disk Encryption with multiple LUKS devices (Clevis and Tang encryption)
Configuring Automated Unlocking Of Encrypted Volumes Using Policy-Based Decryption (Boot without Password)

 

1 thought on “Configure LUKS Network Bound Disk Encryption with clevis & tang server”

  1. If you have a static IP for your client, you need to use the following:
    dracut -f --kernel-cmdline "ip=client_ip netmask= client_netmask gateway= client_gateway_ip nameserver= client_DNS_ip"
    instead of just
    dracut -f
    Otherwise you will continue to be prompted for the root disk password.

    Reply

Leave a Comment

Please use shortcodes <pre class=comments>your code</pre> for syntax highlighting when adding code.