Сегодня полнодисковое шифрование — это норма. В Windows для этого есть BitLocker, в macOS — FileVault и APFS. В Linux для тех же целей служит dm-crypt и LUKS. В этой статье я покажу, как установить ОС на шифрованный корневой раздел, настроить авторазблокировку при загрузке с помощью модуля TPM и новой фичи systemd-cryptsetup, а также резервировать ключ восстановления в Active Directory. Все трюки будем делать в Arch Linux, хотя ты с легкостью сможешь повторить их в своем любимом дистрибутиве.
Шифрование дисков в Linux реализуется с помощью подсистемы dm-crypt Crypto API (встроено в ядро начиная с версии 2.6). Подсистема dm-crypt работает благодаря модулю ядра, который отображает шифрованный диск в виртуальное устройство. На вид оно ничем не отличается от обычного блочного устройства хранения данных. Для управления ключами шифрования используется раздел LUKS (Linux Unified Key Setup). Формат LUKS позволяет использовать до восьми ключей шифрования для одного раздела.
Он начинается с заголовка phdr, далее за ним следуют слоты с ключевыми данными (KM1, KM2, ..., KM8). За ключевыми данными располагаются данные, шифрованные мастер‑ключом.
Заголовок phdr хранит информацию о протоколе и режиме шифрования, длину ключей, идентификатор UUID и контрольную сумму мастер‑ключа.
В LUKS для одного зашифрованного раздела зарезервировано восемь слотов, в каждом из которых может храниться отдельный ключ. Любой из восьми ключей может быть использован для расшифровки раздела.
Заголовок и слоты ключей можно хранить на другом физическом носителе, отдельно от зашифрованных данных, тем самым реализуя многофакторную защиту. Но при утрате заголовка или слотов получить доступ к зашифрованным данным становится невозможно.
Для управления шифрованием дисков используется утилита cryptsetup.
С помощью этой утилиты возможно:
Начнем собирать нашу систему, загрузившись с установочного диска.
Для начала разметим диск следующим образом: sda1 для /boot, sda2 для /. Схему разделов выбираем GPT.
Далее создадим наш LUKS на sda2.
Взглянем теперь на LUKS.
Видно, что мы задействовали один из восьми доступных слотов с ключами — доступ к нему ограничен паролем.
Алгоритм шифрования по умолчанию (
Откроем раздел.
После этих манипуляций у нас в системе стал доступен новый раздел cryptroot.
Создадим на разделах файловые системы.
Для продолжения установки примонтируем наши разделы.
Заглядывая одним глазом в вики, устанавливаем систему обычным образом.
Не забудем включить хук encrypt при создании
Финальный этап — настройка UEFI для загрузки нашего ядра. Напоминаю, что мы обойдемся без GRUB и будем загружать ядро напрямую, используя фичу EFISTUB.
Добавляем запись в UEFI.
Особое внимание обрати на параметры ядра! Без них система просто не сможет найти шифрованный раздел.
Перезагружаемся и убеждаемся, что все работает, как мы хотели: на этапе загрузки требуется ввод пароля для расшифрования раздела.
Убедимся, что мы счастливые обладатели TPM. Необходимая версия TPM — 2.0.
Авторазблокировку сделаем с помощью относительно новой фичи
Для начала необходимо проверить нашу версию systemd.
Все отлично. Для работы с TPM нужно дополнительно установить пакет tpm2-tss.
Далее добавим ключ TPM в слот LUKS с помощью тулзы systemd-cryptenroll.
Не забываем проверить.
В команде выше мы указали параметр --tpm2-pcrs=0,4. Что такое PCR? Вот определение из Википедии:
Для включения systemd-cryptsetup необходимо добавить в /etc/mkinicpio.conf хуки systemd и sd-encrypt.
Наконец, изменим строку загрузки, добавив параметры rd.luks.name и rd.luks.name.
Перезагружаемся и проверяем, что все работает как надо.
Для тех, кому systemd-cryptsetup по каким‑то причинам не подходит (например, версия systemd старая или вообще нет systemd), могу порекомендовать фреймворк Clevis. С его помощью можно реализовать следующие сценарии авторазблокировки LUKS:
Проверяем.
Вариант с сервером tang настраивается не сложнее (разумеется, заранее разворачиваем tang и обеспечиваем сетевую доступность):
Проверяем.
В заключение темы авторазблокировки стоит упомянуть некоторые ограничения фреймворка Clevis:
Есть два варианта создания ключей восстановления:
При необходимости можно восстановить заголовок и установить новый пароль.
Для начала нужно включить нашу Arch Linux в домен. Делать это буду с помощью System Security Services Daemon (SSSD) и realmd.
Устанавливаем sssd обычным способом:
А realmd ставим из AUR.
Убедимся, что домен доступен.
Присоединяемся к домену, для этого понадобится учетная запись с правами ввода в домен (для простоты — administrator).
Проверяем, что все прошло успешно и мы получили билеты Kerberos:
Пароль восстановления будем хранить в учетной записи компьютера: это дочерний объект класса msFVE-RecoveryInformation. Так делает виндовый BitLocker, аналогично поступим и мы.
Записывать пароль в AD буду с помощью скрипта на Python.
Запускаем утилиту, указав необходимые параметры и текущий ключ (пароль):
Проверяем в AD, что пароль восстановления успешно записался.
Ну и напоследок проверяем сам пароль.
автор balabanov Андрей Балабанов
источник хакер.ру
Шифрование дисков в Linux реализуется с помощью подсистемы dm-crypt Crypto API (встроено в ядро начиная с версии 2.6). Подсистема dm-crypt работает благодаря модулю ядра, который отображает шифрованный диск в виртуальное устройство. На вид оно ничем не отличается от обычного блочного устройства хранения данных. Для управления ключами шифрования используется раздел LUKS (Linux Unified Key Setup). Формат LUKS позволяет использовать до восьми ключей шифрования для одного раздела.
КАК УСТРОЕН РАЗДЕЛ LUKS
Раздел LUKS имеет следующий формат.
Он начинается с заголовка phdr, далее за ним следуют слоты с ключевыми данными (KM1, KM2, ..., KM8). За ключевыми данными располагаются данные, шифрованные мастер‑ключом.
Заголовок phdr хранит информацию о протоколе и режиме шифрования, длину ключей, идентификатор UUID и контрольную сумму мастер‑ключа.
В LUKS для одного зашифрованного раздела зарезервировано восемь слотов, в каждом из которых может храниться отдельный ключ. Любой из восьми ключей может быть использован для расшифровки раздела.
Заголовок и слоты ключей можно хранить на другом физическом носителе, отдельно от зашифрованных данных, тем самым реализуя многофакторную защиту. Но при утрате заголовка или слотов получить доступ к зашифрованным данным становится невозможно.
Для управления шифрованием дисков используется утилита cryptsetup.
С помощью этой утилиты возможно:
- создавать шифрованные разделы LUKS;
- открывать и закрывать разделы LUKS;
- управлять слотами ключей;
- дампить заголовок LUKS и мастер‑ключ.
ШИФРУЕМ
Переходим к практике! Шифровать мы будем только рутовый раздел. Есть, конечно, экзотические кейсы, когда, помимо раздела root, шифруется еще и раздел boot, но такая конфигурация поддерживается не всеми загрузчиками и не считается стандартной и рекомендованной. Мы же вообще не будем использовать загрузчик, так что оставляем boot в покое и шифруем все остальное.Начнем собирать нашу систему, загрузившись с установочного диска.
Для начала разметим диск следующим образом: sda1 для /boot, sda2 для /. Схему разделов выбираем GPT.
Код:
$ parted /dev/sda mklabel gpt mkpart primary fat32 1MiB 501MiB
$ parted /dev/sda set 1 esp on
$ parted /dev/sda mkpart primary btrfs 501MiB 100%
Код:
$ cryptsetup luksFormat /dev/sda2
WARNING!
========
This will overwrite data on /dev/sda2 irrevocably.
Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sda2:
Verify passphrase:
cryptsetup luksFormat /dev/sda2 18.16s user 1.88s system 80% cpu 24.742 total
Код:
$ cryptsetup luksDump /dev/sda2
LUKS header information
Version: 2
Epoch: 3
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: e04b5b87-6bfc-4f73-83b0-36f91d52f141
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: 7
Memory: 483194
Threads: 2
Salt: a8 d7 82 ce 89 c8 0f d6 29 18 83 e5 5d 9d a7 f1
a2 6d 66 81 70 db c4 82 cc fb ae 81 4c 7f ed 0c
AF stripes: 4000
AF hash: sha256
Area offset:32768 [bytes]
Area length:258048 [bytes]
Digest ID: 0
Tokens:
Digests:
0: pbkdf2
Hash: sha256
Iterations: 149967
Salt: 87 ac 6f 61 75 fb 91 14 63 5d ca 5d 1c 25 ef 42
7b af 51 63 34 eb 26 d5 d7 be 7a 78 7b 2a 25 f1
Digest: da e7 fd 26 59 85 5d 5e 34 79 2a fa 20 95 f1 83
13 10 0d 0e a3 58 a6 0e 33 b0 f0 73 e8 0a a1 1e
Алгоритм шифрования по умолчанию (
aes-xts-plain64) нас устроит. Перечень всех поддерживаемых алгоритмов зависит от ядра (загляни в /proc/crypto). Можно протестировать работу с ними.
Код:
$ cryptsetup benchmark
# Tests are approximate using memory only (no storage IO)
PBKDF2-sha1 1817289 iterations per second for 256-bit key
PBKDF2-sha256 2302032 iterations per second for 256-bit key
PBKDF2-sha512 1646116 iterations per second for 256-bit key
PBKDF2-ripemd160 903944 iterations per second for 256-bit key
PBKDF2-whirlpool 681778 iterations per second for 256-bit key
argon2i N/A
argon2id N/A
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 1126.9 MiB/s 2966.7 MiB/s
serpent-cbc 128b 98.6 MiB/s 736.0 MiB/s
twofish-cbc 128b 226.0 MiB/s 404.9 MiB/s
aes-cbc 256b 868.5 MiB/s 2594.2 MiB/s
serpent-cbc 256b 107.9 MiB/s 779.9 MiB/s
twofish-cbc 256b 241.6 MiB/s 433.4 MiB/s
aes-xts 256b 3152.7 MiB/s 3146.5 MiB/s
serpent-xts 256b 676.5 MiB/s 665.9 MiB/s
twofish-xts 256b 400.6 MiB/s 410.4 MiB/s
aes-xts 512b 2614.9 MiB/s 2600.2 MiB/s
serpent-xts 512b 687.1 MiB/s 711.3 MiB/s
twofish-xts 512b 413.0 MiB/s 417.2 MiB/s
cryptsetup benchmark 9.54s user 23.98s system 107% cpu 31.226 total
Код:
$ cryptsetup open /dev/sda2 cryptroot
Enter passphrase for /dev/sda2:
Код:
$ lsblk /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 8G 0 disk
├─sda1 8:1 0 500M 0 part
└─sda2 8:2 0 7.5G 0 part
└─cryptroot 253:0 0 7.5G 0 crypt
Код:
$ mkfs.fat -F32 /dev/sda1
$ mkfs.btrfs -f -L "archroot" /dev/mapper/cryptroot
Код:
$ mount /dev/mapper/cryptroot /mnt
$ btrfs subvolume create /mnt/@root
$ btrfs subvolume create /mnt/@home
$ umount /mnt
$ mount /dev/mapper/cryptroot /mnt -o subvol=@root,ssd,noatime,space_cache,compress=zstd
$ mkdir /mnt/home
$ mount /dev/mapper/cryptroot /mnt/home -o subvol=@home,ssd,noatime,space_cache,compress=zstd
$ mkdir /mnt/boot
$ mount /dev/sda1 /mnt/boot
Не забудем включить хук encrypt при создании
initramfs.
Код:
$ vim /etc/mkinitcpio.conf
HOOKS=(base udev autodetect keyboard keymap modconf block encrypt filesystems)
$ mkinitcpio -p linux
Добавляем запись в UEFI.
Код:
$ efibootmgr \
--create \
--bootnum=0000 \
--label "Arch Linux" \
--disk /dev/sda \
--part 1 \
--loader /vmlinuz-linux \
--unicode 'cryptdevice=/dev/sda2:cryptroot root=/dev/mapper/cryptroot rootflags=subvol=@root rw initrd=\initramfs-linux.img' \
--verbose
Перезагружаемся и убеждаемся, что все работает, как мы хотели: на этапе загрузки требуется ввод пароля для расшифрования раздела.
НАСТРАИВАЕМ АВТОРАЗБЛОКИРОВКУ
Хотелось бы не вводить пароль при загрузке каждый раз. Для этого нужно настроить авторазблокировку LUKS с помощью чипа TPM.Убедимся, что мы счастливые обладатели TPM. Необходимая версия TPM — 2.0.
Код:
$ test -e /dev/tpm0 && echo PASS || echo FAIL
PASS
$ cat /sys/class/tpm/tpm0/device/description
TPM 2.0 Device
or
$ cat /sys/class/tpm/tpm0/tpm_version_major
2
systemd-cryptsetup. Systemd-cryptsetup добавлена в systemd начиная с версии 248.Для начала необходимо проверить нашу версию systemd.
Код:
$ systemctl --version
systemd 249 (249.2-1-arch)
+PAM +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified
Код:
$ pacman -Sy tpm2-tss
Код:
$ systemd-cryptenroll /dev/sda2 --tpm2-device=auto --tpm2-pcrs=0,4
Код:
$ systemd-cryptenroll /dev/sda2
SLOT TYPE
---------
0 password
1 tpm2
PCR — это внутренние регистры памяти TPM, в которых в зашифрованном виде содержится вся информация о целостности метрик системы, начиная с загрузки BIOS до завершения работы системы. Информация, содержащаяся в PCR, формирует корень доверия для измерений (RTM). Могут храниться как в энергонезависимой, так и в энергозависимой памяти. Эти регистры сбрасываются при старте и при перезагрузке системы. Спецификация предписывает минимальное количество регистров (16), каждый регистр содержит 160 бит информации. Регистры 0–7 зарезервированы для нужд TPM. Регистры 8–15 доступны для использования операционной системой и приложениями. Изменения значений PCR необратимы, и их значения нельзя записать напрямую, их можно только расширить новыми значениями, которые зависят от предыдущих. Все изменения значений PCR записываются в лог изменений, который хранится в энергозависимой памяти.
| PCR | USE |
|---|---|
| PCR0 | Core System Firmware executable code (aka Firmware) |
| PCR1 | Core System Firmware data (aka UEFI settings) |
| PCR2 | Extended or pluggable executable code |
| PCR3 | Extended or pluggable firmware data |
| PCR4 | Boot Manager |
| PCR5 | GPT / Partition Table |
| PCR6 | Resume from S4 and S5 Power State Events |
| PCR7 | Secure Boot State |
| PCR8 | Hash of the booted kernel |
| PCR 9 to 10 | Reserved for Future Use |
| PCR11 | BitLocker Access Control |
| PCR12 | Data events and highly volatile events |
| PCR13 | Boot Module Details |
| PCR14 | Boot Authorities |
| PCR 15 to 23 | Reserved for Future Use |
Код:
HOOKS=(base systemd modconf block keyboard sd-encrypt filesystems fsck)
$ mkinicpio -P
Код:
$ blkid /dev/sda2
/dev/sda2: UUID="e04b5b87-6bfc-4f73-83b0-36f91d52f141" TYPE="crypto_LUKS" PARTLABEL="primary" PARTUUID="136ffe26-5569-4c76-a871-9025ea52dbd8"
$ efibootmgr \
--create \
--bootnum=0001 \
--label "Arch Linux" \
--disk /dev/sda \
--part 1 \
--loader /vmlinuz-linux \
--unicode 'rd.luks.name=e04b5b87-6bfc-4f73-83b0-36f91d52f141=cryptroot rd.luks.options=tpm2-device=auto root=/dev/mapper/cryptroot rootflags=subvol=@root rw initrd=\initramfs-linux.img' \
--verbose
Для тех, кому systemd-cryptsetup по каким‑то причинам не подходит (например, версия systemd старая или вообще нет systemd), могу порекомендовать фреймворк Clevis. С его помощью можно реализовать следующие сценарии авторазблокировки LUKS:
- tpm2 — разблокировка с TPM;
- tang — разблокировка с сетевого сервера.
Код:
$ clevis luks bind -d /dev/sda2 tpm2 '{"pcr_bank":"sha1","pcr_ids":"0,4"}'
Enter existing LUKS password: ***************
Код:
$ sudo clevis luks list -d /dev/sda2
1: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha1","pcr_ids":"0,4"}
Код:
$ sudo clevis luks bind -d /dev/sda2 tang '{"url":"http://192.168.88.101:7500"}'
The advertisement contains the following signing keys:
QjvwIdUeor3gBqxLteIOKvWPRqM
Do you wish to trust these keys? [ynYN] y
Enter existing LUKS password:
Код:
$ sudo clevis luks list -d /dev/sda2
1: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha1","pcr_ids":"0,4"}'
2: tang '{"url":"http://192.168.88.101:7500"}'
- Clevis работает только с TPM 2.0; TPM 1.2 не поддерживается.
- В Tang не реализован механизм смены ключей.
- Для Tang необходима доступность сети на этапе загрузки, поэтому, например, для Wi-Fi-подключения требуется дополнительная настройка адаптера в initrd.
СОЗДАНИЕ КЛЮЧЕЙ ВОССТАНОВЛЕНИЯ
Бэкапы ключей в таком деле, как шифрование, должны быть, об этом знает каждый.Есть два варианта создания ключей восстановления:
- дамп заголовка и мастер‑ключа;
- запись пароля восстановления в Active Directory.
Делаем копию мастер-ключа
Сделать резервную копию заголовка и мастер‑ключа можно с помощью хорошо известной нам утилиты cryptsetup. С помощью созданной копии можно будет получить доступ к разделу, не зная пароль, поэтому нас заботливо предупреждают, что хранить ее нужно в секрете!
Код:
$ cryptsetup luksDump --dump-master-key /dev/sda2 --master-key-file mk.dump
WARNING!
========
The header dump with volume key is sensitive information
that allows access to encrypted partition without a passphrase.
This dump should be stored encrypted in a safe place.
Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sda2:
LUKS header information for /dev/sda2
Cipher name: aes
Cipher mode: xts-plain64
Payload offset: 32768
UUID: e04b5b87-6bfc-4f73-83b0-36f91d52f141
MK bits: 512
Key stored to file mk.dump
$ xxd mk.dump
00000000: 1501 eccc 84fd 82f7 f53b 56ae 4ab8 5775 .........;V.J.Wu
00000010: 4968 ea61 8d01 1f29 985e 33af 5537 ba40 Ih.a...).3.U7.@
00000020: af61 6aa2 b384 afe1 aff6 d4c9 ad95 1d67 .aj............g
00000030: 3a4f d64f 33ea 6f50 0a18 1139 9196 d694 :O.O3.oP...9....
Код:
$ cryptsetup luksAddKey /dev/sda2 --master-key-file mk.dump
Enter new passphrase for key slot: ********
Verify passphrase: ********
Добавляем пароль восстановления в Active Directory
Другой интересный способ — это хранение пароля в AD.Для начала нужно включить нашу Arch Linux в домен. Делать это буду с помощью System Security Services Daemon (SSSD) и realmd.
Устанавливаем sssd обычным способом:
Код:
$ pacman -Sy sssd
Убедимся, что домен доступен.
Код:
$ realm discover ad.localdomain
ad.localdomain
type: kerberos
realm-name: AD.LOCALDOMAIN
domain-name: ad.localdomain
configured: no
server-software: active-directory
client-software: sssd
Код:
$ realm join ad.localdomain
Password for Administrator: ********
Код:
$ realm list
ad.localdomain
type: kerberos
realm-name: AD.LOCALDOMAIN
domain-name: ad.localdomain
configured: kerberos-member
server-software: active-directory
client-software: sssd
login-formats: %U@ad.localdomain
login-policy: allow-realm-logins
$ klist -k
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
2 ARCH$@AD.LOCALDOMAIN
2 ARCH$@AD.LOCALDOMAIN
2 ARCH$@AD.LOCALDOMAIN
2 host/ARCH@AD.LOCALDOMAIN
2 host/ARCH@AD.LOCALDOMAIN
2 host/ARCH@AD.LOCALDOMAIN
2 RestrictedKrbHost/ARCH@AD.LOCALDOMAIN
2 RestrictedKrbHost/ARCH@AD.LOCALDOMAIN
2 RestrictedKrbHost/ARCH@AD.LOCALDOMAIN
Записывать пароль в AD буду с помощью скрипта на Python.
Код:
$ git clone https://github.com/ambalabanov/lukscrow
$ cd lukscrow/
$ pip install -r requirements.txt
Код:
$ ./lukscrow --luks-device /dev/sda2 --ldap-url "ldap://ad.localdomain" --computers-base-dn "CN=Computers,DC=ad,DC=localdomain" --unlock-key ********
Using Kerberos credential cache /tmp/tmpcsdyn49r
Connected to AD as 'u:AD\ARCH$'
Generating recovery key...
Adding recovery key to LUKS volume...
New key added.
Storing recovery key in Active Directory
Recovery key saved to AD.
Remove Kerberos credential cache /tmp/tmpcsdyn49r
Removed cache file.
Ну и напоследок проверяем сам пароль.
Код:
$ sudo cryptsetup --test-passphrase luksOpen /dev/sda2 && echo TRUE || echo FALSE
Enter passphrase for /dev/sda2: 287781-171655-523297-666928-307170-072073-039516-177220
TRUE
ЗАКЛЮЧЕНИЕ
Итак, мы установили Arch Linux на шифрованный корневой раздел, настроили авторазблокировку при старте и позаботились о резервировании ключей. Надеюсь, для тебя это тоже было увлекательным приключением!автор balabanov Андрей Балабанов
источник хакер.ру