Disk encryption: LUKS ( Linux Unified Key Setup) with Tang
Key component
tang server
is responsible for helping dracut to decrypt the target disk. It won’t store any client key.encrypted server
is required to useclevis
,dracut
. It provide a easier way that integrate with tang server to decrypt LUKS disk.
Network topology
|-------------------------| |------------|
|LUKS encrypted server |-- disk decryption -->|tang server |
|(clevis, dracut) [env] |<----- response ------|[tang] |
|-------------------------| |____________|
Tang server
- software installation via apt on x86x64 Ubuntu 20.04
adm@tang:~$ sudo apt-get install tang -y
## check version
adm@tang:~$ apt list --installed | grep tang
tang/focal,now 7-1build1 amd64 [installed]
## Enable the tangd service
adm@tang:~$ sudo systemctl enable tangd.socket
- Create an override file with 7500 to prevent port conflict
adm@tang:~$ sudo systemctl edit tangd.socket
# tangd.socket
[Socket]
ListenStream=
ListenStream=7500
adm@tang:~$ sudo systemctl daemon-reload
## Check that your configuration is working:
adm@tang:~$ sudo systemctl show tangd.socket -p Listen
Listen=[::]:7500 (Stream)
## Start the tangd service
adm@tang:~$ sudo systemctl restart tangd.socket
adm@tang:~$ sudo systemctl status tangd.socket
● tangd.socket - Tang Server socket
Loaded: loaded (/lib/systemd/system/tangd.socket; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/tangd.socket.d
└─override.conf
Active: active (listening) since Mon 2022-03-14 00:54:03 UTC; 1h 25min ago
Triggers: ● tangd@0.service
Listen: [::]:7500 (Stream)
Accepted: 0; Connected: 0;
Tasks: 0 (limit: 984)
Memory: 44.0K
CGroup: /system.slice/tangd.socket
Mar 14 00:54:03 d systemd[1]: Listening on Tang Server socket.
encrypted server: try clevis, luks to bind with tang
Assume that tang server is now running on 192.168.100.10:7500
, we need to run clevis
to bind local encrypted disk (/dev/md0
in this case) with tang.
- software installation via apt on x86x64 Ubuntu 20.04
adm@enc:~$ sudo apt-get install clevis clevis-luks clevis-dracut -y
## check version
adm@enc:~$ apt list --installed | grep clevis
clevis-dracut/focal-updates,now 12-1ubuntu2.3 all [installed]
clevis-luks/focal-updates,now 12-1ubuntu2.3 all [installed]
clevis-systemd/focal-updates,now 12-1ubuntu2.3 amd64 [installed,automatic]
clevis/focal-updates,now 12-1ubuntu2.3 amd64 [installed]
adm@enc:~$ apt list --installed | grep dracut
dracut-core/focal,now 048+80-2 amd64 [installed,automatic]
dracut-network/focal,now 048+80-2 all [installed]
- check network configuration and check if tang server available
adm@enc:~$ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether c4:00:ad:94:d8:76 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.61/24 brd 192.168.100.255 scope global enp1s0
valid_lft forever preferred_lft forever
adm@enc:~$ curl -sfg http://192.168.100.10:7500/adv -o adv.jws
- check encrypted disk, partition
adm@enc:~$ sudo lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 55M 1 loop /snap/core18/1880
loop1 7:1 0 55.5M 1 loop /snap/core18/2344
loop2 7:2 0 67.9M 1 loop /snap/lxd/22526
loop3 7:3 0 67.8M 1 loop /snap/lxd/22753
loop4 7:4 0 61.9M 1 loop /snap/core20/1376
loop5 7:5 0 43.6M 1 loop /snap/snapd/15177
sda 8:0 0 953.9G 0 disk
├─sda1 8:1 0 512M 0 part /boot/efi
├─sda2 8:2 0 1G 0 part /boot
├─sda3 8:3 0 945.9G 0 part
│ └─md0 9:0 0 945.8G 0 raid1
│ └─dm_crypt-1 253:0 0 945.7G 0 crypt
│ └─vg0-lv--0 253:1 0 945.7G 0 lvm /
└─sda4 8:4 0 6.5G 0 part
sdb 8:16 0 953.9G 0 disk
├─sdb1 8:17 0 8G 0 part [SWAP]
└─sdb2 8:18 0 945.9G 0 part
└─md0 9:0 0 945.8G 0 raid1
└─dm_crypt-1 253:0 0 945.7G 0 crypt
└─vg0-lv--0 253:1 0 945.7G 0 lvm /
# check LUKS on encrpyt partition, total 8 keyslots
$ sudo cryptsetup luksDump /dev/md0
LUKS header information
Version: 2
Epoch: 5
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: b3abd9e0-b3be-4dab-9928-e3f29c749b93
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)
Data segments:
0: crypt
offset: 16777216 [bytes]
length: (whole device)
cipher: aes-xts-plain64
sector: 512 [bytes]
Keyslots:
0: luks2
Key: 512 bits
Priority: normal
Cipher: aes-xts-plain64
Cipher key: 512 bits
PBKDF: argon2i
Time cost: 5
Memory: 1048576
Threads: 4
Salt: 44 01 7e f7 be 90 fa d9 fe 24 8f b7 95 6e 28 91
53 7c 47 5d 6f 0a cf 34 18 c4 ee 13 d6 91 28 e5
AF stripes: 4000
AF hash: sha256
Area offset:32768 [bytes]
Area length:258048 [bytes]
Digest ID:
Tokens:
0: clevis
Keyslot: 1
Digests:
0: pbkdf2
Hash: sha256
Iterations: 100054
Salt: 8b 7d 45 cf 2b 25 07 bd 7d 48 47 04 1e 70 d0 41
46 7c fa 1f ec ed 12 2a c5 36 fc 24 56 b8 6c 7e
Digest: 06 89 5e 90 07 1c 83 eb 54 0a 14 d5 ad f2 f6 50
5f 13 00 58 62 ee 11 62 db 7c e0 1a 45 c5 fa 09
adm@enc:~$ sudo clevis luks bind -d /dev/md0 tang '{"url":"http://192.168.100.10:7500"}'
The advertisement contains the following signing keys:
ADIMDQW1mFAAoGFlQJIG9SioKDW
Do you wish to trust these keys? [ynYN] y
Enter existing LUKS password:
...
# check current state
adm@enc:~$ sudo clevis luks list -d /dev/md0
1: tang '{"url":"http://192.168.100.100:7500"}'
# try dracut
adm@enc:~$ dracut -fv --regenerate-all --kernel-cmdline " ip=192.168.100.61:192.168.100.0/24::255.255.255.0:enc:eth0:off " --kernel-cmdline " rd.net.timeout.carrier=3153600 "
generate a initramfs for bootloader
Make grub load our image that contains clevis luks disk encryption script. The image is built by dracut
. Our purpose is no matter when the grub.cfg
will be updated, the main menuentry should be our dracut environment (linux
, initrd
)
- check grub version
adm@enc:~$ sudo apt list --installed | grep grub
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
grub-common/now 2.04-1ubuntu26.2 amd64 [installed,upgradable to: 2.04-1ubuntu26.13]
grub-efi-amd64-bin/focal-updates,focal-security,now 2.04-1ubuntu44.2 amd64 [installed,automatic]
grub-efi-amd64-signed/focal-updates,focal-security,now 1.167.2+2.04-1ubuntu44.2 amd64 [installed]
grub-efi-amd64/focal-updates,focal-security,now 2.04-1ubuntu44.2 amd64 [installed]
grub2-common/now 2.04-1ubuntu26.2 amd64 [installed,upgradable to: 2.04-1ubuntu26.13]
- You can try to ping gateway IP and tang server’s IP, if gateway IP is not available, don’t fill in that field.
adm@enc:~$ ping 192.168.100.10
PING 192.168.100.10 (192.168.100.100) 56(84) bytes of data.
64 bytes from 192.168.100.10: icmp_seq=1 ttl=64 time=10.9 ms
64 bytes from 192.168.100.10: icmp_seq=2 ttl=64 time=1.00 ms
...
To enumerate all possible environment to generate new grub.cfg, please check our modified 10_linux file
Add new dracut script with customized argument for your environment to grub folder, please check detail in Misc dracut cmdline argument
part and edit files /etc/dracut.conf.d/
if needed.
adm@enc:~$ sudo vi dracut-config/etc-dracut.conf.d/12-kernel-cmdline.conf
kernel_cmdline+=" ip=192.168.100.61:192.168.100.0/24::255.255.255.0:enc:eth0:off "
kernel_cmdline+="rd.net.timeout.carrier=3153600 "
# copy to grub config path
adm@enc:~$ sudo cp dracut-config/etc-dracut.conf.d/12-kernel-cmdline.conf /etc/dracut.conf.d/12-kernel-cmdline.conf
# backup first
adm@enc:~$ sudo cp /etc/grub.d/10_linux /etc/grub.d/.10_linux.bk
# add our include running dracut script and set initramfs as default menuentry
adm@enc:~$ sudo cp etc-grub.d/10_linux /etc/grub.d/10_linux
# update grub.cfg manually
adm@enc:~$ sudo update-grub
# you might see lot of log including dracut, correct them if there's anything wrong.
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/init-select.cfg'
Generating grub configuration file ...
dracut: Executing: /usr/bin/dracut --kver=5.4.0-104-generic -fv --kernel-cmdline " ip=192.168.100.61:192.168.100.0/24::255.255.255.0:enc:eth0:off "
dracut: dracut module 'bootchart' will not be installed, because command '/sbin/bootchartd' could not be found!
dracut: dracut module 'clevis-pin-tpm2' will not be installed, because command 'clevis-decrypt-tpm2' could not be found!
dracut: dracut module 'clevis-pin-tpm2' will not be installed, because command 'tpm2_createprimary' could not be found!
dracut: dracut module 'clevis-pin-tpm2' will not be installed, because command 'tpm2_unseal' could not be found!
dracut: dracut module 'clevis-pin-tpm2' will not be installed, because command 'tpm2_load' could not be found!
dracut: dracut module 'cifs' will not be installed, because command 'mount.cifs' could not be found!
dracut: dracut module 'biosdevname' will not be installed, because command 'biosdevname' could not be found!
dracut: dracut module 'clevis-pin-tpm2' will not be installed, because command 'clevis-decrypt-tpm2' could not be found!
dracut: dracut module 'clevis-pin-tpm2' will not be installed, because command 'tpm2_createprimary' could not be found!
dracut: dracut module 'clevis-pin-tpm2' will not be installed, because command 'tpm2_unseal' could not be found!
dracut: dracut module 'clevis-pin-tpm2' will not be installed, because command 'tpm2_load' could not be found!
dracut: dracut module 'cifs' will not be installed, because command 'mount.cifs' could not be found!
dracut: *** Including module: bash ***
dracut: *** Including module: dash ***
...
dracut: *** Creating initramfs image file '/boot/initramfs-5.4.0-42-generic.img" done ***
Found linux image: /boot/vmlinuz-5.4.0-104-generic
Found initrd image: /boot/initramfs-5.4.0-104-generic.img
Found initrd image: /boot/initramfs-5.4.0-104-generic.img
Found initrd image: /boot/initrd.img-5.4.0-104-generic
Found initrd image: /boot/initrd.img-5.4.0-104-generic
Found linux image: /boot/vmlinuz-5.4.0-42-generic
Found initrd image: /boot/initramfs-5.4.0-42-generic.img
Found initrd image: /boot/initramfs-5.4.0-42-generic.img
Found initrd image: /boot/initrd.img-5.4.0-42-generic
Found initrd image: /boot/initrd.img-5.4.0-42-generic
Adding boot menu entry for UEFI Firmware Settings
done
- check if initramfs created by dracut
adm@enc:~$ ls -lh /boot
total 250M
-rw-r--r-- 1 root root 233K Feb 3 18:16 config-5.4.0-100-generic
-rw-r--r-- 1 root root 233K Mar 2 17:10 config-5.4.0-104-generic
drwxr-xr-x 3 root root 4.0K Jan 1 1970 efi
drwxr-xr-x 4 root root 4.0K Mar 12 06:33 grub
-rw------- 1 root root 24M Mar 11 06:29 initramfs-5.4.0-100-generic.img
-rw------- 1 root root 24M Mar 11 06:29 initramfs-5.4.0-42-generic.img
lrwxrwxrwx 1 root root 28 Mar 11 07:55 initrd.img -> initrd.img-5.4.0-104-generic
-rw-r--r-- 1 root root 84M Feb 26 06:34 initrd.img-5.4.0-100-generic
-rw-r--r-- 1 root root 84M Mar 11 07:56 initrd.img-5.4.0-104-generic
lrwxrwxrwx 1 root root 28 Mar 11 07:55 initrd.img.old -> initrd.img-5.4.0-100-generic
drwx------ 2 root root 16K Feb 25 06:13 lost+found
-rw------- 1 root root 4.6M Feb 3 18:16 System.map-5.4.0-100-generic
-rw------- 1 root root 4.6M Mar 2 17:10 System.map-5.4.0-104-generic
lrwxrwxrwx 1 root root 25 Mar 11 07:55 vmlinuz -> vmlinuz-5.4.0-104-generic
-rw------- 1 root root 14M Feb 4 17:04 vmlinuz-5.4.0-100-generic
-rw------- 1 root root 14M Mar 2 18:37 vmlinuz-5.4.0-104-generic
lrwxrwxrwx 1 root root 25 Mar 11 07:55 vmlinuz.old -> vmlinuz-5.4.0-100-generic
- check if grub config (
/boot/grub/grub.cfg
) changed and the first one should be direct to our image
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-eec358a5-d009-4f70-9210-424330e9adb4' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 a5963b85-5235-4b31-9776-5f6251c206f3
else
search --no-floppy --fs-uuid --set=root a5963b85-5235-4b31-9776-5f6251c206f3
fi
linux /vmlinuz-5.4.0-104-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro
initrd /initramfs-5.4.0-104-generic.img
}
...
- you may try clevis-luks boot with disk decryption flow!
adm@enc:~$ sudo reboot
Enhancement in the future
- Shamir’s Secret Sharing (SSS) algorithm with clevis multiple constriant: tpm, tangd, … etc.
- add tpm to protect tangd key on site controller
- make dracut image name to be fixed
Misc
Tangd
tech, McCallum-Relyea Exchange: client(clevis) need server(tang) to decrypt data, there’s no client data stored in server.dracut cmdline argument
ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|ibft}[:[<mtu>][:<macaddr>]]
explicit network configuration. If you want do define a IPv6
address, put it in brackets (e.g. [2001:DB8::1]). This
parameter can be specified multiple times. <peer> is
optional and is the address of the remote endpoint for
pointopoint interfaces and it may be followed by a slash and
a decimal number, encoding the network prefix length.
<macaddr>
optionally set <macaddr> on the <interface>. This cannot
be used in conjunction with the ifname argument for the
same <interface>.
Ref: https://man7.org/linux/man-pages/man7/dracut.cmdline.7.html
bootloader alternative
you can still use grub shell, if the
/boot/grub/grub.cfg
is broken.bootable Ubuntu USB stick
Ref
- luks, clevis, tang
https://mdtsai.medium.com/%E8%A7%A3%E9%99%A4-linux-%E5%8A%A0%E5%AF%86%E7%A3%81%E5%8D%80-5b8e597e4c37
https://www.osslab.com.tw/research-luks/
https://www.itread01.com/content/1542818777.html
https://kknews.cc/zh-tw/code/n22kq38.html
https://www.tecmint.com/file-and-disk-encryption-tools-for-linux/
https://www.tecmint.com/disk-encryption-in-linux/
https://help.ubuntu.com/community/Full_Disk_Encryption_Howto_2019
https://wiki.archlinux.org/title/Data-at-rest_encryption
https://docs.microsoft.com/zh-tw/azure/virtual-machines/linux/how-to-configure-lvm-raid-on-crypt
https://linuxsecurity.com/features/top-8-file-and-disk-encryption-tools-for-linux
https://nakedsecurity.sophos.com/2022/01/14/serious-security-linux-full-disk-encryption-bug-fixed-patch-now/
https://www.cyberciti.biz/security/howto-linux-hard-disk-encryption-with-luks-cryptsetup-command/
https://docs.nvidia.com/drive/drive_os_5.1.6.1L/nvvib_docs/index.html#page/DRIVE_OS_Linux_SDK_Development_Guide/Windows%20Systems/security_disk_encryption_lnx.html
https://www.wibu.com/
https://wiki.centos.org/zh-tw/HowTos/EncryptedFilesystem
https://gitlab.com/cryptsetup/cryptsetup/-/wikis/DMCrypt
https://www.digitalocean.com/community/tutorials/how-to-use-dm-crypt-to-create-an-encrypted-volume-on-an-ubuntu-vps
https://www.howtoforge.com/ubuntu_dm_crypt_luks
https://ubuntuqa.com/zh-tw/article/8257.html
https://www.gushiciku.cn/pl/g4f9/zh-tw
https://askubuntu.com/questions/996155/how-do-i-automatically-decrypt-an-encrypted-filesystem-on-the-next-reboot
https://dywang.csie.cyut.edu.tw/dywang/linuxsecurity/node59.html
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/configuring-automated-unlocking-of-encrypted-volumes-using-policy-based-decryption_security-hardening
https://www.youtube.com/watch?v=Dk6ZuydQt9I
https://www.youtube.com/watch?v=h5H6_oxpFA0
https://www.admin-magazine.com/Archive/2018/43/Automatic-data-encryption-and-decryption-with-Clevis-and-Tang
https://www.snia.org/sites/default/files/SDC15_presentations/security/NathanielMcCallum_Network_Bound_Encryption.pdf
https://www.youtube.com/watch?v=p_M0YEE-esA
https://www.cs.purdue.edu/homes/hmaji/teaching/Fall%202018/lectures/19.pdf
https://docs.okd.io/latest/security/network_bound_disk_encryption/nbde-managing-encryption-keys.html
# systemd, init
https://hugh712.gitbooks.io/buildroot/content/system-initialization.html
http://felix-lin.com/linux/init%e6%bc%94%e5%8c%96%e6%ad%b7%e7%a8%8b-%e8%bd%89%e8%b2%bc-%e6%b7%ba%e6%9e%90-linux-%e5%88%9d%e5%a7%8b%e5%8c%96-init-%e7%b3%bb%e7%b5%b1%ef%bc%8c%e7%ac%ac-1-%e9%83%a8%e5%88%86-sysvinit/
https://linux.die.net/man/5/init
http://felix-lin.com/linux/init%E6%BC%94%E5%8C%96%E6%AD%B7%E7%A8%8B-%E8%BD%89%E8%B2%BC-%E6%B7%BA%E6%9E%90-linux-%E5%88%9D%E5%A7%8B%E5%8C%96-init-%E7%B3%BB%E7%B5%B1%EF%BC%8C%E7%AC%AC-2-%E9%83%A8%E5%88%86-upstart/
# grub
https://hugh712.gitbooks.io/grub/content/configuration-files.html
https://wiki.ubuntu-tw.org/index.php?title=Grub2