Установка Archlinux c полным шифрованием системы и LVM на LUKS

В данном посте вы прочитаете немного о моих странных изыскания во время вынужденного отпуска по болезни. Речь пойдёт сразу о нескольких вещах, которые не являются «best practice», но так же тоже можно! Итак, здесь будет туториал о том, как установить Archlinux(мой любимый дистр) так, чтобы:

  • без отдельного /boot (просто в /root)
  • / на lvm
  • lvm внутри luks-контейнера
  • с UEFI
  • в виртуальной машине.
  • с secure boot(«сложна», в виртуалке вряд ли получится)

Примечательно, что зашифровано будет всё, кроме EFI system partition с единственным файлом grubx64.efi — EFI-приложением для запуска grub.

Если заинтересовались, — добро пожаловать под кат!

Сначала я настроил это всё на моём ноутбуке Lenovo X240, потом для написания статьи пользовался уже виртуальной машиной с OVMF в Proxmox.

Настройка тестового стенда:

Создаётся всё достаточно стандартно. Образом используется мой любимый арч, который можно всегда загрузить с яндекса.

Далее несколько моментов по виртуалке в Proxmox относительно UEFI. Чтобы протестировать работу стенда с UEFI(иначе не будет так интересно), нужно в свойствах виртуальной машины выставить OVMF вместо SeaBIOS:

Далее соответственно добавить UEFI-диск, чтобы получилось примерно так:

Теперь можем стартовать виртуальную машину и начинать процесс установки. В консоли виртуальной машины сразу стартуем сервис sshd, задаём пароль root и узнаём dhcp-адрес виртуальной машины:

Далее мы можем продолжить работу по ssh чтобы было удобнее.

Разметка дисков

Итак, уже подключившись по ssh мы для начала устанавливаем время, чтобы потом не оказалось, что файловые системы созданы в будущем:

timedatectl set-ntp true && timedatectl set-timezone Europe/Moscow

Проверяем, что всё верно:

 root@archiso ~ # timedatectl                Local time: Tue 2018-08-14 13:42:03 MSK            Universal time: Tue 2018-08-14 10:42:03 UTC                  RTC time: Tue 2018-08-14 10:42:04                 Time zone: Europe/Moscow (MSK, +0300) System clock synchronized: yes               NTP service: active           RTC in local TZ: no 

Теперь можем приступать к разметке диска. На данном этапе у меня есть диск /dev/vda, т.к. контроллер Virtio и это просто пустой диск без таблицы разделов:

 root@archiso ~ # fdisk -l /dev/vda                                                                                                                                                     Disk /dev/vda: 15 GiB, 16106127360 bytes, 31457280 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes 

Разбивать его будем на 2 партиции:

  • fat32 диск для UEFI приложений(EFI_system_partition)
  • LUKS контейнер со всем остальным

Используем gdisk для создания GPT:

 root@archiso ~ # gdisk /dev/vda GPT fdisk (gdisk) version 1.0.4 Command (? for help): o This option deletes all partitions and creates a new protective MBR. Proceed? (Y/N): y 

Далее создаём первую партицию для EFI с типом EF00 (EFI System Partition):

 Command (? for help): n Partition number (1-128, default 1): First sector (34-31457246, default = 2048) or {+-}size{KMGTP}: Last sector (2048-31457246, default = 31457246) or {+-}size{KMGTP}: +512M Current type is 'Linux filesystem' Hex code or GUID (L to show codes, Enter = 8300): <b>EF00</b> Changed type of partition to 'EFI System' 

Теперь создаём партицию для LUKS, где даже не будем заморачиваться с типом и оставим как есть:

 Command (? for help): n Partition number (2-128, default 2): First sector (34-31457246, default = 1050624) or {+-}size{KMGTP}: Last sector (1050624-31457246, default = 31457246) or {+-}size{KMGTP}: <b>Current type is 'Linux filesystem' Hex code or GUID (L to show codes, Enter = 8300): Changed type of partition to 'Linux filesystem'</b> 

Запишем изменения и закончим с разметкой партиций:

 Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): y OK; writing new GUID partition table (GPT) to /dev/vda. The operation has completed successfully. 

Создание LUKS-контейнера и файловых систем

C первым разделом(vda1) всё достаточно просто. Нам нужно его просто отформатировать и пока на этом всё:

root@archiso ~ # mkfs.vfat /dev/vda1 mkfs.fat 4.1 (2017-01-24) 

Вторая партиция это контейнер, который нужно сначала подготовить. Форматируем партицию через cryptsetup и задаём парольную фразу:

root@archiso ~ # cryptsetup -v luksFormat /dev/vda2  WARNING! ======== This will overwrite data on /dev/vda2 irrevocably.  Are you sure? (Type uppercase yes): YES Enter passphrase for /dev/vda2: Verify passphrase: Command successful. 

*** я не стал заморачиваться с выбором шифров, с затиранием рандомом урандомом и прочим, а просто создал контейнер по умолчанию.

Далее открываем контейнер указывая ту же парольную фразу:

root@archiso ~ # cryptsetup luksOpen /dev/vda2 container Enter passphrase for /dev/vda2: 

Теперь у нас есть открытый контейнер, доступной через device mapper:

root@archiso ~ # ls -l /dev/mapper | grep container lrwxrwxrwx 1 root root       7 Aug 14 14:01 container -> ../dm-0

Теперь мы можем продолжить с lvm(напишу по-быстрому, так как это не сабж):

 root@archiso ~ # pvcreate /dev/mapper/container   Physical volume "/dev/mapper/container" successfully created. root@archiso ~ # vgcreate rootvg /dev/mapper/container   Volume group "rootvg" successfully created root@archiso ~ # lvcreate -L1G -n swap rootvg   Logical volume "swap" created. root@archiso ~ # lvcreate -L5G -n root rootvg   Logical volume "root" created. root@archiso ~ # lvcreate -L2G -n home rootvg   Logical volume "home" created.  root@archiso ~ # lvs   LV   VG     Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert   home rootvg -wi-a----- 2.00g   root rootvg -wi-a----- 5.00g   swap rootvg -wi-a----- 1.00g 

Далее создадим файловые системы на наших lv:

 root@archiso ~ # mkfs.ext4 -L root /dev/mapper/rootvg-root mke2fs 1.44.3 (10-July-2018) ... Writing superblocks and filesystem accounting information: done  [root@archiso ~]# mkfs.ext4 -L home /dev/mapper/rootvg-home mke2fs 1.44.3 (10-July-2018) Creating filesystem with 524288 4k blocks and 131072 inodes ... Writing superblocks and filesystem accounting information: done  [root@archiso ~]# mkswap -L swap /dev/mapper/rootvg-swap ... LABEL=swap, UUID=98b0bc31-1c62-4fec-bb97-e1913d1e8cb4 

Теперь это всё можно примонтировать для установки базовой системы. Точкой установки будет /mnt, где будет начинаться корень нашей будущей системы:

 [root@archiso ~]# mount /dev/mapper/rootvg-root /mnt/ [root@archiso ~]# mkdir -p /mnt/{home,boot/efi} 

*** /boot/efi я создаю, чтобы сам /boot остался на /dev/mapper/rootvg-root, а папка efi уже для монтирования в неё /dev/vda1(fat32 efi partition):

 [root@archiso ~]# mount /dev/vda1 /mnt/boot/efi/ [root@archiso ~]# mount /dev/mapper/rootvg-home /mnt/home/ [root@archiso ~]# swapon /dev/mapper/rootvg-swap 

Проверим текуoие точки монтирования(всегда полезно):

[root@archiso ~]# lsblk NAME              MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT loop0               7:0    0 462.5M  1 loop  /run/archiso/sfs/airootfs sr0                11:0    1   573M  0 rom   /run/archiso/bootmnt vda               254:0    0    15G  0 disk ├─vda1            254:1    0   512M  0 part  /mnt/boot/efi └─vda2            254:2    0  14.5G  0 part   └─container     253:0    0  14.5G  0 crypt     ├─rootvg-swap 253:1    0     1G  0 lvm   [SWAP]     ├─rootvg-root 253:2    0     5G  0 lvm   /mnt     └─rootvg-home 253:3    0     2G  0 lvm   /mnt/home

Как мы видим, всё честно и теперь время ставить сам арч.

Установка базовой системы

Устанавливаем базовые пакеты из наборов base и base-devel используя пакет pacstrap( им можно поставить всё, что вы хотите и кроме этого):

pacstrap /mnt base base-devel

Всё прекрасно загрузилось, базовая система готова. Вывод я, естественно, убрал. Теперь мы можем настроить эту самую систему, чтобы она загрузилась и работала.

Из базовых вещей сразу сгенерируем fstab:

 genfstab -pU /mnt >> /mnt/etc/fstab 

Далее сделаем arch-chroot в эту новую систему:

 [root@archiso ~]# arch-chroot /mnt 

*** arch-chroot очень даже годная утилита, потому как она делает всё сама. Хотя вы всегда можете воспользоваться стандартным chroot, перед этим выполнив всё по инструкции gentoo-handbook wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Base раздел «Mounting the necessary filesystems»

Cразу настроим системное время и hostname:

ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime && \ hwclock --systohc && \ echo luks-test > /etc/hostname 

Зададим пароль root:

 [root@archiso /]# passwd root New password: Retype new password: passwd: password updated successfully 

Раскомментируем нужные локали в /etc/locale.gen:

[root@archiso /]# vi /etc/locale.gen [root@archiso /]# grep -v '^#' /etc/locale.gen en_US ISO-8859-1 en_US.UTF-8 UTF-8 ru_RU.UTF-8 UTF-8 ru_RU ISO-8859-5

Сгенерируем их:

[root@archiso /]# locale-gen Generating locales...   en_US.ISO-8859-1... done   en_US.UTF-8... done   ru_RU.UTF-8... done   ru_RU.ISO-8859-5... done Generation complete

Сразу их настроим для системы и консоли:

[root@archiso /]# echo LANG=en_US.UTF-8 > /etc/locale.conf [root@archiso /]# echo KEYMAP=ru > /etc/vconsole.conf [root@archiso /]# echo FOND=cyr-sun16 >> /etc/vconsole.conf

Теперь настроим файл /etc/mkinitcpio.conf, который у нас отвечает за опции, хуки и прочее при генерации initramfs:

vi /etc/mkinitcpio.conf

Самое главное здесь хуки и их порядок:

HOOKS=(base udev autodetect modconf block keymap encrypt lvm2 resume filesystems keyboard fsck)

*** хук resume для загрузки системы после гибернации из swap. На виртуалке он не нужен. Скопировал его с бука.

Теперь мы можем сгенерировать initramfs:

[root@archiso /]# mkinitcpio -p linux ==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'default'   -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img ==> Starting build: 4.17.14-arch1-1-ARCH   -> Running build hook: [base]   -> Running build hook: [udev]   -> Running build hook: [autodetect]   -> Running build hook: [modconf]   -> Running build hook: [block]   -> Running build hook: [keymap]   -> Running build hook: [encrypt]   -> Running build hook: [lvm2]   -> Running build hook: [resume]   -> Running build hook: [filesystems]   -> Running build hook: [keyboard]   -> Running build hook: [fsck] ==> Generating module dependencies ==> Creating gzip-compressed initcpio image: /boot/initramfs-linux.img ==> Image generation successful 

Теперь, когда у нас есть система, нам нужно установить сам загрузчик. Мой выбор пал на grub(2), потому как он как-то роднее и достаточно легко умеет загружать ядро с зашифрованного раздела(ну или я особо не искал другие).

Установим пакет grub:

 [root@archiso /]# pacman -S grub dosfstools efibootmgr mtools 

Перед генерацией конфига отредактируем дефолтные опции grub:

 vim /etc/default/grub 

здесь нужно раскомментить одну важную строчку(без коммента, естественно):

 # Uncomment to enable booting from LUKS encrypted devices GRUB_ENABLE_CRYPTODISK=y 

и добавить(там пусто по умолчанию) в GRUB_CMDLINE_LINUX:

 GRUB_CMDLINE_LINUX="cryptdevice=UUID=5ad7c9ad-fb17-4839-925e-479432516c07:container" 

UUID я взял из blkid:

[root@archiso /]# blkid | grep vda2 /dev/vda2: UUID="5ad7c9ad-fb17-4839-925e-479432516c07" TYPE="crypto_LUKS" PARTLABEL="Linux filesystem" PARTUUID="667a1243-17ff-4f03-952c-5afd5e3415cc" 


Генерируем конфиг для grub:

 [root@archiso /]# grub-mkconfig -o /boot/grub/grub.cfg Generating grub configuration file ...   WARNING: Failed to connect to lvmetad. Falling back to device scanning. Found linux image: /boot/vmlinuz-linux Found initrd image: /boot/initramfs-linux.img Found fallback initrd image(s) in /boot: initramfs-linux-fallback.img   WARNING: Failed to connect to lvmetad. Falling back to device scanning. done 

Далее устанавливаем сам grub на диск:

[root@archiso /]# grub-install /dev/vda Installing for x86_64-efi platform. ... Installation finished. No error reported. 

*** можно добавить —recheck —debug, указать архитектуру… но… оно ведь само и так работает)

Теперь отредактируем /etc/crypttab, чтобы сама система знала, что при загрузке надо расшифровывать LUKS раздел. Добавим строчку:

 echo "container /dev/vda2 none" >> /etc/crypttab 

Которая означает, что надо запрашивать пароль(none) для раздела /dev/vda2 и представлять его уже как container через device mapper.

Теперь мы готовы выйти из chroot и перезагрузить систему:

[root@archiso /]# exit exit [root@archiso ~]# reboot  Welcome back!

Теперь обратимся к консоли виртуальной машины чтобы увидеть результат:

На данном этапе у нас запустилось EFI-приложение /boot/efi/EFI/arch/grubx64.efi с /dev/vda1, которое запрашивает у нас пароль, чтобы расшифровать наш контейнер.

Далее, после ввода пароля:

Здесь уже привычное окно grub с нашими опциями загрузки из /boot/grub/grub.cfg.
На данном этапе grub расшифровал наш контейнер и получил доступ к этом самому файлу (/boot/grub/grub.cfg), ядру и initramfs. После выбора опции по умолчанию загрузится ядро, initramfs:

Активно, ядро и дело дошло до хука encrypt, который заново спрашивает нас пароль для расшифровки контейнера( вообще влом 2 раза вводить пароль, но может быть так, что вы от излишка паранойи сделаете 2 контейнера для boot и root 🙂

И далее уже после полной загрузки системы:

PS: для повышения уровня шизофрении здесь не хватает только secure boot, чтобы подписать наш загрузчик grubx64.efi.

Просто положить ядро и initramfs на /dev/vda1 я счёл безыинтересным, так как 100 раз так уже делал. Другие загрузчики типа SHIM, bootctl и прочее не умеют вытворять подобного(ну и ли я не в курсе — расскажите в комментах )

FavoriteLoadingДобавить в избранное
Posted in Без рубрики

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *