Pull to refresh
Флант
DevOps-as-a-Service, Kubernetes, обслуживание 24×7

Как сделать безопасную загрузку с полностью зашифрованным диском на Linux без загрузчика на UEFI

Level of difficultyHard
Reading time14 min
Views11K

Всем привет! На связи Алексей Гаврилов, DevOps-инженер компании «Флант». Эта статья предназначена для довольно искушённых пользователей Linux. Я покажу, как устанавливать Debian или его аналоги стандартным установщиком в Secure boot. Эту установку я проверил на AWS ARM64 и в Selectel Cloud. Также конечные скрипты работают на служебном Lenovo ThinkPad T14 и личном L380 Yoga.

Чего в итоге мы добьёмся:

  1. Включённый Secure boot с личными ключами для него. Так мы получим возможность загружать только EFI-файлы, подписанные нашим ключом. Это исключит возможность запуска сторонних EFI-файлов, подписанных другими ключами, например, Microsoft или производителем железа.

  2. Файл ядра и initramfs, которые подписаны нашим ключом. Это возможно благодаря использованию UKI. Так мы получаем EFI-файл, содержимое которого подписано. Это позволяет нам исключить из последовательности загрузки grub или systemd-boot. Исключение загрузчиков нужно для уменьшения возможного вектора взлома ноутбука.

  3. Зашифрованные разделы, кроме EFI boot. Так мы получим возможность исключить утечку данных в случае кражи ноутбука, а также усложним жизнь потенциальному взломщику тем, что в его распоряжении будут только подписанные EFI-файлы.

Ручной вариант установки

Прежде чем перейти к установке, убедимся, что Secure Boot находится в режиме настройки. При этом настройки UEFI BIOS должны быть защищены паролем, чтобы Secure boot нельзя было отключить.

Дальше работаем по следующему алгоритму:

1. Нужно загрузиться с установщика и выбрать экспертный режим. Это даёт дополнительные вопросы при установке, но также и возможности в более тонкой настройке новой системы.  

2. С помощью программы установки разобьём диск на:

  • системный раздел EFI (он должен быть как минимум 512 МБ, иначе все EFI-файлы могут не поместиться);

  • зашифрованный корневой раздел. Здесь вы вправе сделать разбивку настолько сложной, насколько хотите. Главное — не забыть, чтобы разделы оказались в LUKS-разделе либо его аналоге.

[12:18:23][ssh][root@aws2] ~ $ cat /etc/crypttab 
nvme0n1p2_crypt UUID=2de785af-2b9e-432a-bb31-a8f1fe36fa31 none luks,discard
[12:18:29][ssh][root@aws2] ~ $ cat /etc/fstab 
/dev/mapper/aws-root /               ext4    errors=remount-ro 0       1
# /boot/efi was on /dev/nvme0n1p1 during installation
UUID=F751-88E0  /boot/efi       vfat    umask=0077      0       1
/swapfile swap swap defaults 0 0
[12:18:35][ssh][root@aws2] ~ $ lsblk 
NAME                MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
zram0               253:0    0  466M  0 disk  [SWAP]
nvme0n1             259:0    0   25G  0 disk  
├─nvme0n1p1         259:1    0  487M  0 part  /boot/efi
└─nvme0n1p2         259:2    0 24.5G  0 part  
  └─nvme0n1p2_crypt 254:0    0 24.5G  0 crypt 
    └─aws-root      254:1    0 24.5G  0 lvm   /

3. На этапе установки системы выберем backports в качестве пакета для bookworm (stable), так как в bookworm нет systemd-ukify.

4. На этапе выбора загрузчика выберем вариант без загрузчика. При этом нам нужно пропустить пункт с установкой grub.

5. Завершим установку. При этом нужно остановиться перед перезагрузкой, так как в этот момент система не сможет запуститься корректно.

6. Переключимся в Shell-режим для модификации новой системы, которая монтируется в /target в процессе установки.

7. Поменяем приоритет bookworm-backports на приоритет как для bookworm. Это нужно для установки systemd-ukify.

TARGET=/target

# ukify install
cat > $TARGET/etc/apt/preferences.d/bookworm-backports <<EOF
Package: *
Pin: release bookworm-backports
Pin-Priority: 500
EOF

8. Обновим пакеты в новой системе, чтобы поставить версии из bookworm-backports:

in-target sh -c "export DEBIAN_FRONTEND=noninteractive && apt update && apt full-upgrade -y"

9. Установим необходимые пакеты:

apt-install systemd-boot-efi efibootmgr sbsigntool python3-pefile

10. Настроим dropbear для возможности удалённо ввести пароль от зашифрованного диска по SSH. В данном случае мы перенастраиваем dropbear на 1022-й порт при запуске и делаем жёсткую ссылку на /root/.ssh/authorized_keys. Это позволит с тем же ключом зайти и при запуске сервера, а также при изменении содержимого получить новый список ключей после применения update-initramfs:

apt-install dropbear-initramfs
echo 'DROPBEAR_OPTIONS="-I 600 -j -k -p 1022 -s -c cryptroot-unlock"' >> $TARGET/etc/dropbear/initramfs/dropbear.conf
ln $TARGET/root/.ssh/authorized_keys $TARGET/etc/dropbear/initramfs/authorized_keys

11. Запомним параметры запуска ядра:

root_fs=$(cat $TARGET/etc/fstab | grep errors=remount-ro | grep " / " | awk '{print "root=" $1}')
echo "$root_fs ro" > $TARGET/etc/kernel/cmdline

12. Сделаем дополнительную настройку для kernel-install из состава systemd. Данные скрипты добавляют собранные EFI-файлы ядер в загрузочное меню. Также добавляется настройка для сборки ядер в EFI-файлы:

cat > $TARGET/etc/kernel/install.d/99-efiboot.install <<EOF
#!/bin/sh
set -e
[ "\$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
COMMAND="\${1:?}"
KERNEL_VERSION="\${2:?}"
boot=\$(mount | grep "\$KERNEL_INSTALL_BOOT_ROOT" | awk '{print \$1}')

case "\$COMMAND" in
  remove)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
      efibootmgr -B -b "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
    fi
    ;;
  add)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "0" ] ; then
      prefix='\EFI\Linux\'
      efibootmgr -d \$boot -C -L "\${KERNEL_VERSION}" -l "\$prefix\${KERNEL_INSTALL_ENTRY_TOKEN}-\${KERNEL_VERSION}.efi"
    fi
    if [ -f "/boot/initrd.img" ] ; then
      if [ "\$(ls -la /boot/initrd.img | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
      fi
    else
      if [ "\$(efibootmgr | grep BootOrder: | grep \$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8) | wc -l)" -eq "0" ] ; then
        list=""
        if [ "\$(efibootmgr | grep BootOrder: | awk '{print \$2}' | wc -l)" -eq "1" ] ; then
          list=",\$(efibootmgr | grep BootOrder: | awk '{print \$2}')"
        fi
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)\$list"
      fi
    fi
    ;;
  *)
    exit 0
    ;;
esac
EOF
chmod +x $TARGET/etc/kernel/install.d/99-efiboot.install

cat > $TARGET/etc/kernel/install.conf <<EOF
layout=uki
uki_generator=ukify
EOF

cat > $TARGET/etc/kernel/postrm.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install remove "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF
chmod +x $TARGET/etc/kernel/postrm.d/zz-kernel-install

cat > $TARGET/etc/kernel/postinst.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install add "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF
mkdir -p $TARGET/etc/initramfs/post-update.d/
ln $TARGET/etc/kernel/postinst.d/zz-kernel-install $TARGET/etc/initramfs/post-update.d/zz-kernel-install
chmod +x $TARGET/etc/kernel/postinst.d/zz-kernel-install

13. Используем sbctl, чтобы упростить создание сертификатов для Secure boot и их применение к UEFI. 

sbctl на данный момент нет в Debian, поэтому приходится ставить с GitHub. Ключ --yes-this-might-brick-my-machine нужен только для AWS, так как в VM используется довольно старая версия EFI BIOS. После исполнения данной части Secure boot перейдёт в режим пользователя, так как sbctl загрузит в него созданные ключи:

ARCH=$(chroot /target/ dpkg --print-architecture)
wget --quiet https://github.com/Foxboron/sbctl/releases/download/0.14/sbctl-0.14-linux-$ARCH.tar.gz -O - | tar -xz sbctl/sbctl -O > $TARGET/usr/local/bin/sbctl
chmod +x $TARGET/usr/local/bin/sbctl
  1. Также настроим /etc/kernel/uki.conf, чтобы при создании EFI-файлы подписывались указанными ключами:

cat > $TARGET/etc/kernel/uki.conf <<EOF
[UKI]
SecureBootSigningTool=sbsign
SecureBootPrivateKey=/usr/share/secureboot/keys/db/db.key
SecureBootCertificate=/usr/share/secureboot/keys/db/db.pem
EOF

15. Создадим ключи для EFI, загрузим их в UEFI и обновим initramfs и EFI-файлы:

in-target sh -c "mount -o rw -t efivarfs efivarfs /sys/firmware/efi/efivars; \
    sbctl create-keys; \
    sbctl enroll-keys --yes-this-might-brick-my-machine; \
    update-initramfs -u -k all; \
    umount /sys/firmware/efi/efivars;"

Автоматизированный вариант установки

Это практически автоматизированная версия установки. На момент написания статьи требуется разметка диска. Для такого варианта нужен работающий nginx с файлами, доступный с сервера в процессе установки. Ссылки в файлах нужно менять на свои.

1. Соберём EFI-файл установщика с параметрами для загрузки файла ответов для автоматической установки auto=true url=https://le9i0nx.gitlab.io/autoinstall/aws-crypt.cfg interface=auto netcfg/dhcp_timeout=60 keyboard-configuration/xkb-keymap=en priority=critical, а также настройки взаимодействия через ttyS0 (это нужно для работы в AWS) console=tty0 console=ttyS0. После выполнения мы получаем /boot/efi/EFI/BOOT/BOOTAA64.EFI, с которого запустим установщик:

#!/bin/sh
set -x
wget "https://ftp.debian.org/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz"
wget "https://ftp.debian.org/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux"
apt update
apt install systemd-boot-efi binutils python3-pefile -y
wget https://raw.githubusercontent.com/systemd/systemd/v255/src/ukify/ukify.py -v -O /usr/local/bin/ukify
chmod +x /usr/local/bin/ukify

mkdir -p /boot/efi/EFI/BOOT/
ukify build \
	--linux=./linux \
	--initrd=./initrd.gz \
	--cmdline="auto=true url=https://le9i0nx.gitlab.io/autoinstall/aws-crypt.cfg interface=auto netcfg/dhcp_timeout=60 keyboard-configuration/xkb-keymap=en priority=critical theme=dark gfxpayload=800x600x16,800x600 console=tty0 console=ttyS0" \
	--uname="Debian install" \
	--output "/boot/efi/EFI/BOOT/BOOTAA64.EFI"

Скрипт для установки Debian

2. Файл ответов для почти автоматической установки. Здесь важная часть находится в команде d-i preseed/late_command string. В ней исполняются произвольные команды после установки Debian. В нашем случае — добавление SSH-ключей пользователю root и настройка Secure boot:

d-i preseed/late_command string \
  wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/ssh.sh > /ssh.sh; \
  sh /ssh.sh /target; \
  wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/secure-boot/kernel-install.sh > /install.sh; \
  sh /install.sh /target

Так как установка предполагается по сети, используется d-i network-console/authorized_keys_url string. Он указывает на файл с ключами, которыми можно зайти для продолжения установки:

d-i keyboard-configuration/xkb-keymap select us
d-i netcfg/get_hostname string unassigned-hostname
d-i netcfg/get_domain string unassigned-domain
d-i hw-detect/load_firmware boolean true
d-i anna/choose_modules string network-console
d-i preseed/early_command string anna-install network-console
d-i network-console/password password root42
d-i network-console/password-again password root42
d-i network-console/authorized_keys_url string https://le9i0nx.gitlab.io/autoinstall/authorized_keys

d-i debian-installer/language string en
d-i debian-installer/country string US
d-i debian-installer/locale string en_US.UTF-8
d-i localechooser/supported-locales multiselect en_US.UTF8, ru_RU.UTF8
d-i console-keymaps-at/keymap select us
d-i keyboard-configuration/variant select American English
d-i netcfg/choose_interface select auto
d-i mirror/http/proxy string
tzsetup-udeb time/zone select UTC
d-i clock-setup/utc boolean true
d-i clock-setup/ntp boolean true
clock-setup clock-setup/ntp-server string pool.ntp.org
d-i apt-setup/contrib boolean true
d-i apt-setup/non-free boolean true
d-i apt-setup/non-free-firmware boolean true
apt-setup-udeb apt-setup/enable-source-repositories boolean false
popularity-contest popularity-contest/participate boolean true
tasksel tasksel/first multiselect ssh-server, standard
d-i pkgsel/include string openssh-server wget ca-certificates vim
pkgsel pkgsel/update-policy select unattended-upgrades
pkgsel pkgsel/upgrade select full-upgrade
openssh-server openssh-server/password-authentication boolean false
d-i base-installer/install-recommends boolean false
bootstrap-base base-installer/initramfs-tools/driver-policy select most

d-i passwd/root-login boolean true
d-i passwd/root-password-crypted password $6$0YbiHUntJTa$k7geJE7k0.GJqG8XZKpIHrM0frlVX5ZsxFFsZ6D7SGb2IZ08La6bV8KPYkkPNEK6NJzmOggU/T3JRE0lRwE6w1
d-i passwd/make-user boolean false
d-i preseed/late_command string \
  wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/ssh.sh > /ssh.sh; \
  sh /ssh.sh /target; \
  wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/secure-boot/kernel-install.sh > /install.sh; \
  sh /install.sh /target
d-i apt-setup/services-select multiselect security, updates, backports
#bootstrap-base base-installer/kernel/image select linux-image-cloud-arm64
#d-i debian-installer/add-kernel-opts string console=tty0 console=ttyS0

Сам файл ответов.

3. Загрузим список ключей для доступа по SSH:

#!/bin/sh
TARGET=$1
mkdir -p $TARGET/root/.ssh
chmod 0700 $TARGET/root/.ssh
wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/authorized_keys >> $TARGET/root/.ssh/authorized_keys
chmod 0600 $TARGET/root/.ssh/authorized_keys

Скрипт.

4. Модификация системы для загрузки в Secure boot:

#!/bin/sh
set -x

TARGET=$1

# ukify install
cat > $TARGET/etc/apt/preferences.d/bookworm-backports <<EOF
Package: *
Pin: release bookworm-backports
Pin-Priority: 500
EOF

# ukify install python3-pefile -> systemd-ukify
PACKAGE="systemd-boot-efi efibootmgr sbsigntool python3-pefile dropbear-initramfs"
if [ "$TARGET" = "" ]; then
  apt update
  apt full-upgrade -y
  apt install -y $PACKAGE
else
  in-target sh -c "export DEBIAN_FRONTEND=noninteractive && apt update && apt full-upgrade -y"
  apt-install $PACKAGE
fi

# dropbear
echo 'DROPBEAR_OPTIONS="-I 600 -j -k -p 1022 -s -c cryptroot-unlock"' >> $TARGET/etc/dropbear/initramfs/dropbear.conf
ln $TARGET/root/.ssh/authorized_keys $TARGET/etc/dropbear/initramfs/authorized_keys

#kernel-install fixed
root_fs=$(cat $TARGET/etc/fstab | grep errors=remount-ro | grep " / " | awk '{print "root=" $1}')
#echo "$root_fs ro console=tty0 console=ttyS0" > $TARGET/etc/kernel/cmdline
echo "$root_fs ro" > $TARGET/etc/kernel/cmdline

cat > $TARGET/etc/kernel/install.d/99-efiboot.install <<EOF
#!/bin/sh
set -e
[ "\$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
COMMAND="\${1:?}"
KERNEL_VERSION="\${2:?}"
boot=\$(mount | grep "\$KERNEL_INSTALL_BOOT_ROOT" | awk '{print \$1}')

case "\$COMMAND" in
  remove)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
      efibootmgr -B -b "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
    fi
    ;;
  add)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "0" ] ; then
      prefix='\EFI\Linux\'
      efibootmgr -d \$boot -C -L "\${KERNEL_VERSION}" -l "\$prefix\${KERNEL_INSTALL_ENTRY_TOKEN}-\${KERNEL_VERSION}.efi"
    fi
    if [ -f "/boot/initrd.img" ] ; then
      if [ "\$(ls -la /boot/initrd.img | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
      fi
    else
      if [ "\$(efibootmgr | grep BootOrder: | grep \$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8) | wc -l)" -eq "0" ] ; then
        list=""
        if [ "\$(efibootmgr | grep BootOrder: | awk '{print \$2}' | wc -l)" -eq "1" ] ; then
          list=",\$(efibootmgr | grep BootOrder: | awk '{print \$2}')"
        fi
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)\$list"
      fi
    fi
    ;;
  *)
    exit 0
    ;;
esac
EOF
chmod +x $TARGET/etc/kernel/install.d/99-efiboot.install

cat > $TARGET/etc/kernel/install.conf <<EOF
layout=uki
uki_generator=ukify
EOF

cat > $TARGET/etc/kernel/postrm.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install remove "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF
chmod +x $TARGET/etc/kernel/postrm.d/zz-kernel-install

cat > $TARGET/etc/kernel/postinst.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install add "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF

mkdir -p $TARGET/etc/initramfs/post-update.d/
ln $TARGET/etc/kernel/postinst.d/zz-kernel-install $TARGET/etc/initramfs/post-update.d/zz-kernel-install
chmod +x $TARGET/etc/kernel/postinst.d/zz-kernel-install

# sbctl
if [ "$TARGET" = "" ]; then
  ARCH=$(dpkg --print-architecture)
else
  ARCH=$(chroot /target/ dpkg --print-architecture)
fi
wget --quiet https://github.com/Foxboron/sbctl/releases/download/0.14/sbctl-0.14-linux-$ARCH.tar.gz -O - | tar -xz sbctl/sbctl -O > $TARGET/usr/local/bin/sbctl
chmod +x $TARGET/usr/local/bin/sbctl

cat > $TARGET/etc/kernel/uki.conf <<EOF
[UKI]
SecureBootSigningTool=sbsign
SecureBootPrivateKey=/usr/share/secureboot/keys/db/db.key
SecureBootCertificate=/usr/share/secureboot/keys/db/db.pem
EOF

if [ "$TARGET" = "" ]; then
  sbctl create-keys
  sbctl enroll-keys --yes-this-might-brick-my-machine
  update-initramfs -u -k all
else
  in-target sh -c "mount -o rw -t efivarfs efivarfs /sys/firmware/efi/efivars; \
    sbctl create-keys; \
    sbctl enroll-keys --yes-this-might-brick-my-machine; \
    update-initramfs -u -k all; \
    umount /sys/firmware/efi/efivars;"
fi

Скрипт

Как перейти на вариант загрузки с подписанным uki ядром на уже работающем grub для UEFI

Стоит учитывать, что при переходе можно сломать загрузку системы, так как можно не учесть особенности именно вашей инсталляции. Чтобы избежать этого, нужно сделать следующее:

  1. Переведём загрузку ПК в режим настройки Secure boot. После этого он может быть настроен из операционной сиситемы.

  2. Поменяем приоритет bookworm-backports на приоритет как для bookworm. Это нужно для установки systemd-ukify:

cat >/etc/apt/preferences.d/bookworm-backports <<EOF
Package: *
Pin: release bookworm-backports
Pin-Priority: 500
EOF
  1. Обновим пакеты в новой системе, чтобы поставить версии из bookworm-backports:

apt update && apt full-upgrade -y"
  1. Установим необходимые пакеты:

apt-install systemd-boot-efi efibootmgr sbsigntool python3-pefile
  1. Запомним параметры запуска ядра:

root_fs=$(cat/etc/fstab | grep errors=remount-ro | grep " / " | awk '{print "root=" $1}')
echo "$root_fs ro" > /etc/kernel/cmdline
  1. Сделаем дополнительную настройку для kernel-install из состава systemd. Данные скрипты добавляют собранные EFI-файлы ядер в загрузочное меню. Также добавляется настройка для сборки ядер в EFI-файлы:

cat > /etc/kernel/install.d/99-efiboot.install <<EOF
#!/bin/sh
set -e
[ "\$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
COMMAND="\${1:?}"
KERNEL_VERSION="\${2:?}"
boot=\$(mount | grep "\$KERNEL_INSTALL_BOOT_ROOT" | awk '{print \$1}')

case "\$COMMAND" in
  remove)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
      efibootmgr -B -b "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
    fi
    ;;
  add)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "0" ] ; then
      prefix='\EFI\Linux\'
      efibootmgr -d \$boot -C -L "\${KERNEL_VERSION}" -l "\$prefix\${KERNEL_INSTALL_ENTRY_TOKEN}-\${KERNEL_VERSION}.efi"
    fi
    if [ -f "/boot/initrd.img" ] ; then
      if [ "\$(ls -la /boot/initrd.img | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
      fi
    else
      if [ "\$(efibootmgr | grep BootOrder: | grep \$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8) | wc -l)" -eq "0" ] ; then
        list=""
        if [ "\$(efibootmgr | grep BootOrder: | awk '{print \$2}' | wc -l)" -eq "1" ] ; then
          list=",\$(efibootmgr | grep BootOrder: | awk '{print \$2}')"
        fi
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)\$list"
      fi
    fi
    ;;
  *)
    exit 0
    ;;
esac
EOF
chmod +x /etc/kernel/install.d/99-efiboot.install

cat > /etc/kernel/install.conf <<EOF
layout=uki
uki_generator=ukify
EOF

cat > /etc/kernel/postrm.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install remove "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF
chmod +x /etc/kernel/postrm.d/zz-kernel-install

cat > /etc/kernel/postinst.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install add "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF

mkdir -p /etc/initramfs/post-update.d/
ln /etc/kernel/postinst.d/zz-kernel-install /etc/initramfs/post-update.d/zz-kernel-install
chmod +x /etc/kernel/postinst.d/zz-kernel-install
  1. Используем sbctl, чтобы упростить создание сертификатов для Secure boot и их применение к UEFI. 

    sbctl на данный момент нет в Debian, поэтому приходится ставить с GitHub. После исполнения данной части Secure boot перейдёт в режим пользователя, так как sbctl загрузит в него созданные ключи:

ARCH=$(dpkg --print-architecture)
wget --quiet https://github.com/Foxboron/sbctl/releases/download/0.14/sbctl-0.14-linux-$ARCH.tar.gz -O - | tar -xz sbctl/sbctl -O > /usr/local/bin/sbctl
chmod +x /usr/local/bin/sbctl
  1. Также настроим /etc/kernel/uki.conf, чтобы при создании EFI-файлы подписывались указанными ключами:

cat > /etc/kernel/uki.conf <<EOF
[UKI]
SecureBootSigningTool=sbsign
SecureBootPrivateKey=/usr/share/secureboot/keys/db/db.key
SecureBootCertificate=/usr/share/secureboot/keys/db/db.pem
EOF
  1. Создадим ключи для EFI, загрузим их в UEFI и обновим initramfs и EFI-файлы:

sbctl create-keys
sbctl enroll-keys
update-initramfs -u -k all
  1. После перезапуска, если загрузка удачно завершилась, через новый вариант стоит закрыть доступ к изменению настроек BIOS.

Итоги

После завершения установки мы получим установленный Debian на зашифрованном диске с ограниченным списком того, что может быть загружено с ноутбука. В такой системе мы доверяем UEFI — что она не позволит загрузить неподписанные EFI-файлы.

Используемые ссылки:

Tags:
Hubs:
+57
Comments21

Articles

Information

Website
flant.ru
Registered
Founded
Employees
201–500 employees
Location
Россия
Representative
Александр