Ноутбук в рюкзаке на поезде, забытая сумка в такси, офисная кража за минуты - сценарии физической потери устройства случаются регулярно. Пароль учётной записи и экранная блокировка не создают препятствия для атакующего с физическим доступом к накопителю. Извлечённый диск подключается к другому компьютеру, и вся файловая система открывается без спроса. Полное шифрование блочного устройства через LUKS меняет эту картину: без знания парольной фразы данные остаются набором случайных байтов. Однако стандартные параметры установщиков дистрибутивов часто оставляют слабые места, которые упрощают подбор ключа. В статье разбираем, как настроить LUKS2 с современными алгоритмами, увеличенной длиной ключа и правильной структурой заголовка так, чтобы физическая потеря ноутбука не превратилась в утечку информации.
Выбор алгоритма хеширования и PBKDF для устойчивости к перебору
Сила шифрования определяется не только симметричным шифром, но и функцией деривации ключа из парольной фразы. В LUKS1 по умолчанию используется PBKDF2 с SHA-256 и фиксированным временем итераций 2000 мс. В LUKS2 дефолт сменился на argon2id - memory-hard функцию, требующую значительного объёма оперативной памяти для каждой попытки подбора. Это критично: видеокарты и специализированные ASIC отлично считают PBKDF2, но argon2id заставляет их ждать доступа к памяти, снижая скорость перебора на порядки.
При создании контейнера явно задайте argon2id с повышенными параметрами памяти и параллелизма:
cryptsetup luksFormat --type luks2 \
--pbkdf argon2id \
--pbkdf-memory 1048576 \
--pbkdf-parallel 4 \
--iter-time 5000 \
/dev/nvme0n1p3
Параметр --pbkdf-memory 1048576 выделяет 1 ГБ памяти на одну операцию деривации. Значение --pbkdf-parallel 4 использует четыре потока, что соответствует типичному количеству ядер современного мобильного процессора. --iter-time 5000 увеличивает целевое время вычисления до 5 секунд - заметно дольше дефолтных 2 секунд, но приемлемо при разблокировке. На слабом железе можно снизить память до 512 МБ (--pbkdf-memory 524288), сохраняя argon2id.
Для проверки применённых параметров используйте:
cryptsetup luksDump /dev/nvme0n1p3 | grep -A5 "PBKDF"
Вывод покажет argon2id, память в килобайтах, параллелизм и время итераций. Если видите pbkdf2 - контейнер создан в режиме LUKS1 или с устаревшими настройками.
Сравнение эффективности подбора: на RTX 4090 PBKDF2-SHA256 с 2000 мс даёт около 2.2 млн итераций в секунду, что позволяет перебирать миллионы паролей в день. Argon2id с 1 ГБ памяти и 4 потоками на том же железе ограничивается сотнями попыток в секунду. Разница в три-четыре порядка делает перебор словарных паролей нереалистичным.
Настройка полного шифрования блочного устройства с увеличенным ключом
Симметричный шифр по умолчанию в LUKS - aes-xts-plain64 с ключом 256 бит (что даёт 512 бит для XTS режима, так как XTS требует два независимых ключа). Переход на 512-битный ключ (1024 бита для XTS) удваивает пространство ключа и устойчивость к теоретическим атакам на связанные ключи, при этом производительность на современных процессорах с AES-NI падает незначительно.
Создайте контейнер с явно заданным размером ключа 512 бит:
cryptsetup luksFormat --type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha512 \
--pbkdf argon2id \
--pbkdf-memory 1048576 \
--pbkdf-parallel 4 \
--iter-time 5000 \
--label "nvme-root" \
/dev/nvme0n1p3
Опция --hash sha512 задаёт хеш-функцию для внутренних операций LUKS (не путать с PBKDF). --label присваивает понятное имя контейнеру, которое видно в lsblk -f и blkid.
После форматирования откройте контейнер и создайте файловую систему:
cryptsetup open /dev/nvme0n1p3 cryptroot
mkfs.ext4 -L root /dev/mapper/cryptroot
mount /dev/mapper/cryptroot /mnt
Для NVMe-накопителей добавьте --allow-discards при открытии, чтобы включить TRIM:
cryptsetup open --allow-discards /dev/nvme0n1p3 cryptroot
В /etc/crypttab запись для автоматической разблокировки при загрузке выглядит так:
cryptroot UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx none luks,discard,initramfs
UUID берется из blkid /dev/nvme0n1p3. Опция discard пробрасывает TRIM через dm-crypt, initramfs указывает на разблокировку на ранней стадии загрузки. Третье поле none означает интерактивный ввод пароля на консоли.
Альтернативные шифры при отсутствии AES-NI: serpent-xts-plain64 и twofish-xts-plain64. Их производительность на программной реализации ниже в 3-6 раз, но они не зависят от аппаратного ускорения. Выбор делайте на основе cryptsetup benchmark.
Работа с заголовком LUKS2 и резервным копированием ключей
Заголовок LUKS2 занимает первые 16-32 МБ устройства и содержит метаданные, слоты ключей (до 32) и область для внешних токенов. Повреждение заголовка делает данные невосстановимыми даже при известном пароле. Регулярное резервное копирование заголовка - обязательная практика.
Создайте резервную копию заголовка и всех слотов ключей:
cryptsetup luksHeaderBackup /dev/nvme0n1p3 \
--header-backup-file /root/luks-header-nvme0n1p3.bin
Храните копию на отдельном носителе (USB-флеш, зашифрованный архив в облаке). Восстановление:
cryptsetup luksHeaderRestore /dev/nvme0n1p3 \
--header-backup-file /root/luks-header-nvme0n1p3.bin
Команда требует подтверждения, так как перезаписывает текущий заголовок.
Добавление резервного ключа в свободный слот позволяет разблокировать диск, если основной пароль утерян или скомпрометирован:
cryptsetup luksAddKey /dev/nvme0n1p3 \
--key-slot 1 \
--pbkdf argon2id \
--pbkdf-memory 1048576 \
--pbkdf-parallel 4 \
--iter-time 5000
Система запросит существующий пароль, затем новый. Удаление ключа:
cryptsetup luksKillSlot /dev/nvme0n1p3 1
Проверка занятых слотов:
cryptsetup luksDump /dev/nvme0n1p3 | grep -E "Key slot|Keyslots"
Свободные слоты показывают DISABLED. Рекомендуется держать как минимум один резервный слот с высокоэнтропийным паролем, сгенерированным через openssl rand -base64 32.
Миграция с LUKS1 на LUKS2 без потери данных:
cryptsetup convert /dev/nvme0n1p3 --type luks2
Операция сохраняет все ключи и данные, расширяет заголовок до 32 МБ и включает поддержку argon2id. После конвертации обновите параметры PBKDF для каждого слота через luksConvertKey.
Автоматическая разблокировка через crypttab при загрузке системы
Для системного раздела корневая файловая система должна быть доступна до запуска пользовательского пространства. Это требует включения модулей dm-crypt и криптографических алгоритмов в initramfs, а также настройки загрузчика.
В /etc/mkinitcpio.conf (Arch Linux) или /etc/dracut.conf.d/luks.conf (Fedora, RHEL) добавьте хуки шифрования:
# mkinitcpio.conf
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)
Для dracut:
# /etc/dracut.conf.d/luks.conf
add_dracutmodules+=" crypt "
install_items+=" /etc/crypttab "
Обновите initramfs:
mkinitcpio -P
# или
dracut --force --regenerate-all
В загрузчике (systemd-boot, GRUB, rEFInd) добавьте параметр ядра rd.luks.uuid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx для systemd-boot или cryptdevice=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:cryptroot root=/dev/mapper/cryptroot для GRUB.
Пример для systemd-boot (/boot/loader/entries/arch.conf):
title Arch Linux
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options rd.luks.uuid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx rd.luks.name=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx=cryptroot root=/dev/mapper/cryptroot quiet
UUID указывается дважды: первый - для активации через systemd-cryptsetup, второй - для имени маппинга. После перезагрузки система запросит пароль до появления графического интерфейса.
Для GRUB (/etc/default/grub):
GRUB_CMDLINE_LINUX="cryptdevice=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:cryptroot root=/dev/mapper/cryptroot"
Затем grub-mkconfig -o /boot/grub/grub.cfg.
Проверка параметров шифрования и аудит безопасности
После настройки проведите полный аудит параметров контейнера. Команда luksDump выдаёт исчерпывающую информацию:
cryptsetup luksDump /dev/nvme0n1p3
Обратите внимание на следующие поля:
Version: LUKS2- подтверждает современный форматCipher name: aes/Cipher mode: xts/Hash spec: sha512- алгоритмы шифрования и хешированияKey size: 512- размер ключа в битахPBKDF: argon2id/Memory: 1048576/Parallel threads: 4/Iterations: 5000- параметры деривацииKey slots:- список слотов с их статусами (ENABLED/DISABLED) и параметрами PBKDF для каждого
Запустите бенчмарк для оценки производительности на конкретном железе:
cryptsetup benchmark --key-size 512 --cipher aes-xts-plain64
Результат покажет скорость шифрования и расшифрования в MiB/s. На процессорах с AES-NI ожидайте 1.5-2.5 GiB/s для aes-xts-512. Если скорость ниже 500 MiB/s - проверьте, загружен ли модуль aesni_intel (lsmod | grep aesni).
Проверьте, что TRIM работает на активном маппинге:
fstrim -v /mnt
Должен сообщить о количестве обрезанных байт. Для автоматического TRIM добавьте discard в опции монтирования в /etc/fstab или используйте системный таймер fstrim.timer.
Дополнительные меры защиты при физическом доступе к устройству
Шифрование диска защищает данные в состоянии покоя. При работающей системе ключ держится в памяти ядра, и атака через DMA (Thunderbolt, FireWire, PCIe) или cold boot может его извлечь. Настройте политики ядра для снижения рисков.
В /etc/default/grub добавьте параметры ядра:
GRUB_CMDLINE_LINUX_DEFAULT="... module_blacklist=thunderbolt intel_iommu=on iommu=pt"
module_blacklist=thunderbolt отключает драйвер Thunderbolt (если порт не используется), intel_iommu=on iommu=pt включает IOMMU в режиме pass-through, блокируя неавторизованный DMA.
Включите блокировку памяти для криптографических ключей:
echo 1 > /proc/sys/vm/mmap_min_addr
echo 1 > /proc/sys/kernel/kptr_restrict
echo 2 > /proc/sys/kernel/dmesg_restrict
Добавьте в /etc/sysctl.d/99-security.conf для постоянства:
vm.mmap_min_addr = 65536
kernel.kptr_restrict = 1
kernel.dmesg_restrict = 2
kernel.unprivileged_bpf_disabled = 1
Настройте автоматическую блокировку экрана и приостановку при закрытии крышки в /etc/systemd/logind.conf:
HandleLidSwitch=suspend
HandleLidSwitchExternalPower=suspend
IdleAction=suspend
IdleActionSec=30min
При приостановке ключи остаются в памяти. Для полной защиты используйте гибернацию с зашифрованным разделом подкачки или выключение питания. В systemd настройте HibernateMode=platform shutdown в /etc/systemd/sleep.conf.
Для ноутбуков с TPM 2.0 можно привязать разблокировку к состоянию платформы через systemd-cryptenroll:
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/nvme0n1p3
Это позволяет разблокировать диск без ввода пароля только при неизменном загрузчике и ядре (PCR 0 и 7). Любое изменение загрузчика потребует ввода пароля - защита от evil maid атак.
Шаги для полной подготовки ноутбука к потере:
- Создать LUKS2 контейнер с argon2id, 1 ГБ памяти, ключом 512 бит;
- Сохранить резервную копию заголовка на отдельном носителе;
- Добавить резервный ключ в слот 1 с высокой энтропией;
- Настроить crypttab и initramfs для загрузки;
- Включить IOMMU и отключить неиспользуемые DMA-интерфейсы;
- Настроить TPM2 привязку при наличии модуля;
- Проверить TRIM, бенчмарк и luksDump перед эксплуатацией.