Се­год­ня пол­нодис­ковое шиф­рование — это нор­ма. В 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 поз­воля­ет исполь­зовать до вось­ми клю­чей шиф­рования для одно­го раз­дела.

 

Как устроен раздел LUKS

Раз­дел LUKS име­ет сле­дующий фор­мат.

Он начина­ется с заголов­ка phdr, далее за ним сле­дуют сло­ты с клю­чевы­ми дан­ными (KM1, KM2, ..., KM8). За клю­чевы­ми дан­ными рас­полага­ются дан­ные, шиф­рован­ные мас­тер‑клю­чом.

За­голо­вок phdr хра­нит информа­цию о про­токо­ле и режиме шиф­рования, дли­ну клю­чей, иден­тифика­тор UUID и кон­троль­ную сум­му мас­тер‑клю­ча.

В LUKS для одно­го зашиф­рован­ного раз­дела зарезер­вирова­но восемь сло­тов, в каж­дом из которых может хра­нить­ся отдель­ный ключ. Любой из вось­ми клю­чей может быть исполь­зован для рас­шифров­ки раз­дела.

За­голо­вок и сло­ты клю­чей мож­но хра­нить на дру­гом физичес­ком носите­ле, отдель­но от зашиф­рован­ных дан­ных, тем самым реали­зуя мно­гофак­торную защиту. Но при утра­те заголов­ка или сло­тов получить дос­туп к зашиф­рован­ным дан­ным ста­новит­ся невоз­можно.

Для управле­ния шиф­ровани­ем дис­ков исполь­зует­ся ути­лита cryptsetup.

С помощью этой ути­литы воз­можно:

  • соз­давать шиф­рован­ные раз­делы LUKS;
  • от­кры­вать и зак­рывать раз­делы LUKS;
  • уп­равлять сло­тами клю­чей;
  • дам­пить заголо­вок LUKS и мас­тер‑ключ.

Для работы cryptsetup тре­буют­ся пра­ва супер­поль­зовате­ля и пароль шиф­рования.

 

Шифруем

Пе­рехо­дим к прак­тике! Шиф­ровать мы будем толь­ко рутовый раз­дел. Есть, конеч­но, экзо­тичес­кие кей­сы, ког­да, помимо раз­дела 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%

Да­лее соз­дадим наш LUKS на sda2.

$ 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

Взгля­нем теперь на LUKS.

$ 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:

Пос­ле этих манипу­ляций у нас в сис­теме стал дос­тупен новый раз­дел cryptroot.

$ 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 для заг­рузки нашего ядра. Напоми­наю, что мы обой­дем­ся без GRUB и будем заг­ружать ядро нап­рямую, исполь­зуя фичу EFISTUB.

До­бав­ляем запись в 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

Осо­бое вни­мание обра­ти на парамет­ры ядра! Без них сис­тема прос­то не смо­жет най­ти шиф­рован­ный раз­дел.

Пе­резаг­ружа­емся и убеж­даем­ся, что все работа­ет, как мы хотели: на эта­пе заг­рузки тре­бует­ся ввод пароля для рас­шифро­вания раз­дела.

first_reboot
first_reboot
 

Настраиваем авторазблокировку

Хо­телось бы не вво­дить пароль при заг­рузке каж­дый раз. Для это­го нуж­но нас­тро­ить авто­раз­бло­киров­ку LUKS с помощью чипа TPM.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    8 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии