Всем привет! На связи Алексей Гаврилов, DevOps-инженер компании «Флант». Эта статья предназначена для довольно искушённых пользователей Linux. Я покажу, как устанавливать Debian или его аналоги стандартным установщиком в Secure boot. Эту установку я проверил на AWS ARM64 и в Selectel Cloud. Также конечные скрипты работают на служебном Lenovo ThinkPad T14 и личном L380 Yoga.
![](https://habrastorage.org/getpro/habr/upload_files/439/eca/02d/439eca02dcdaea171098f7aff755dad8.png)
Чего в итоге мы добьёмся:
Включённый Secure boot с личными ключами для него. Так мы получим возможность загружать только EFI-файлы, подписанные нашим ключом. Это исключит возможность запуска сторонних EFI-файлов, подписанных другими ключами, например, Microsoft или производителем железа.
Файл ядра и initramfs, которые подписаны нашим ключом. Это возможно благодаря использованию UKI. Так мы получаем EFI-файл, содержимое которого подписано. Это позволяет нам исключить из последовательности загрузки grub или systemd-boot. Исключение загрузчиков нужно для уменьшения возможного вектора взлома ноутбука.
Зашифрованные разделы, кроме 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
Также настроим
/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"
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
Стоит учитывать, что при переходе можно сломать загрузку системы, так как можно не учесть особенности именно вашей инсталляции. Чтобы избежать этого, нужно сделать следующее:
Переведём загрузку ПК в режим настройки Secure boot. После этого он может быть настроен из операционной сиситемы.
Поменяем приоритет
bookworm-backports
на приоритет как дляbookworm
. Это нужно для установки systemd-ukify:
cat >/etc/apt/preferences.d/bookworm-backports <<EOF
Package: *
Pin: release bookworm-backports
Pin-Priority: 500
EOF
Обновим пакеты в новой системе, чтобы поставить версии из
bookworm-backports
:
apt update && apt full-upgrade -y"
Установим необходимые пакеты:
apt-install systemd-boot-efi efibootmgr sbsigntool python3-pefile
Запомним параметры запуска ядра:
root_fs=$(cat/etc/fstab | grep errors=remount-ro | grep " / " | awk '{print "root=" $1}')
echo "$root_fs ro" > /etc/kernel/cmdline
Сделаем дополнительную настройку для
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
-
Используем
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
Также настроим
/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
Создадим ключи для EFI, загрузим их в UEFI и обновим initramfs и EFI-файлы:
sbctl create-keys
sbctl enroll-keys
update-initramfs -u -k all
После перезапуска, если загрузка удачно завершилась, через новый вариант стоит закрыть доступ к изменению настроек BIOS.
Итоги
После завершения установки мы получим установленный Debian на зашифрованном диске с ограниченным списком того, что может быть загружено с ноутбука. В такой системе мы доверяем UEFI — что она не позволит загрузить неподписанные EFI-файлы.
Используемые ссылки:
Комментарии (17)
isumix
19.08.2024 07:57Эх, была бы возможность чекнуть галочку при установке, чтобы сделать всё хорошо.
Не помню в каком дистре видел зашифрованный boot автоматом, без uefi правда.
le9i0nx Автор
19.08.2024 07:57+1В принципе это возможно в grub2 с какой то версии он стал поддерживать шифрованный раздел /boot/ но в нём есть ограничение на поддерживаемый формат LUKS и самое противное это необходимость вводить пароль дважды. И нет возможности удалённо ввести пароль по ssh
alexkuzko
19.08.2024 07:57На самом деле там есть обход через... Раскрытие основного раздела через сохраненный ключ. Т.е. бут раскрывается через ввод пароля (на первой версии luks, да), а дальше используется сохраненный на зашифрованном разделе ключ.
Разумеется, минусы есть: лежащий в относительном доступе ключ (после загрузки), первая версия luks. Зато вектор атаки без основной дыры.
Johan_Palych
19.08.2024 07:57+3Ручной вариант установки
Нужно загрузиться с установщика и выбрать экспертный режим.debian-12.6.0-amd64-netinst.iso 2024-06-29 13:56 631M
Рекомедую почитать Unified kernel image, Unified kernel image specification
Рекомедую включить:network-console: Continue installation remotely using SSH
Пакет: systemd-ukify в Debian trixie и sid dep: systemd (>= 256.4-3)
В bookworm-backports systemd (254.16-1~bpo12+1)
Лучший вариант для меня:
Загрузка с live-cd. Для примера debian-live-12.6.0-amd64-lxde.iso
Разметка диска. debootstrap, arch-install-scripts или systemd-nspawn
AcidWave
19.08.2024 07:57А зачем этот весь геморрой, если в арче при установке все можно сделать не особо напрягаясь? А учитывая что в заключительном комментарии предлагают использовать арчевые скрипты, то смысл статьи теряется чуть больше чем полностью
le9i0nx Автор
19.08.2024 07:57выбор дистрибутива это совсем другой разговор.
А вот что вы подразумеваете под "арчевые скрипты" непонятно. Не могли бы вы раскрыть эту часть более подробно?
ivanrt
19.08.2024 07:57Недавно настаивал свои ключи и secure boot с подписанным systemd-boot и ядрами в Gentoo. Как вы храните ключ которым подписываете новые ядра?
Обидно что secure boot на AMD сломали, см. AMD sinkclose.
le9i0nx Автор
19.08.2024 07:57+2ключи хранятся локально на зашифрованном root. Это не 100% безопасно т.к. ключи не защищены паролем или шифрованием.
NZakh61
@le9i0nx, а будет инструкция, чтобы записать загрузочную флешку с windows 10/11 через любой дистр Линукса, например Debian, не прокидывая wine и не поднимая виндовую виртуалку?))))
Знаю, что в компании сталкивались с таким кейсом))
NZakh61
А, ну и чтобы система точно установилась))
le9i0nx Автор
Маловероятно это не профиль нашей компании.
agp88
Попробуйте ventoy. Судя по всему, не совсем то, о чем вы спрашиваете, но на выходе таки получается загрузочная флешка с любой виндой и не только.
dartraiden
Если в прошивке машины, на которую будете ставить Windows, есть драйвер NTFS (на FAT32 install.wim может не влезть, если его размер превышаает ограничения FAT32), то можно просто распаковать содержимое образа на флешку - EFI-загрузка работает с любой ФС, лишь бы прошивка могла прочитать файловую систему.
aapchy199
Есть хорошая утилита windows2usb (https://github.com/ValdikSS/windows2usb), есть в виде готового appimage.
Если нужна загрузка только с EFI систем, то можно просто распаковать в раздел с fat32.
Если wim файл больше 4 GiB, можно разбить на несколько файлов с помощью dism или open source утилиты wimlib-imagex. Работает быстро, без необходимости пережимать.