Шифрование диска - это одна из тех тем, где разрыв между "поставил галочку при установке" и "понимаю что происходит" особенно опасен. Ноутбук с включённым LUKS, пароль к которому записан на стикере, приклеенном к крышке - не анекдот, а реальная история из корпоративной практики. Понять механизм значит не только настроить правильно, но и не совершить ошибок, которые превращают шифрование в ложное чувство защищённости.

dm-crypt - это подсистема ядра Linux, реализующая прозрачное шифрование блочных устройств. Слово "прозрачное" здесь техническое: операционная система и приложения работают с виртуальным блочным устройством через device mapper, совершенно не зная о том, что каждый сектор на реальном диске зашифрован. Шифрование происходит в ядре, в пространстве kernel space, с минимальным участием пользовательских процессов. LUKS - это стандарт хранения метаданных шифрования поверх dm-crypt. Именно LUKS отвечает за управление ключами, хранение параметров шифра и обеспечение возможности сменить пароль без перешифрования всего диска.

Как dm-crypt и LUKS работают вместе на уровне ядра

Архитектура dm-crypt строится на подсистеме Device Mapper - универсальном механизме ядра для создания виртуальных блочных устройств. Device Mapper принимает запросы на чтение и запись, перенаправляет их через цепочку "таргетов" и возвращает результат. dm-crypt - это один из таргетов, который перехватывает операции и применяет к данным криптографическое преобразование через Crypto API ядра.

Когда приложение записывает данные на /dev/mapper/encrypted, dm-crypt шифрует каждый сектор отдельно с уникальным вектором инициализации (IV), после чего передаёт зашифрованные данные на реальное блочное устройство. При чтении процесс обратный. С точки зрения файловой системы поверх dm-crypt ничего особенного не происходит - она видит обычное блочное устройство.

LUKS добавляет к этому заголовок в начале зашифрованного устройства. Заголовок хранит не сам ключ шифрования, а мастер-ключ, зашифрованный через один или несколько "слотов". Каждый слот может содержать отдельный пароль или ключевой файл. Именно поэтому LUKS поддерживает до 8 независимых паролей для одного устройства в LUKS1 и до 32 слотов в LUKS2 - менять пароль можно без перешифрования данных, поскольку меняется только зашифрованная копия мастер-ключа в слоте.

# Установка cryptsetup
apt install cryptsetup       # Debian/Ubuntu
dnf install cryptsetup       # Fedora/RHEL

# Посмотреть доступные шифры в ядре
cat /proc/crypto | grep -A2 "name"
cryptsetup benchmark

Создание LUKS-контейнера и выбор параметров шифрования

Выбор параметров при создании контейнера - это решение, которое невозможно изменить после без полного перешифрования. Здесь стоит потратить время на осознанный выбор, а не принять дефолты вслепую.

LUKS2 - текущий стандарт, рекомендованный для всех новых развёртываний. Он использует argon2id в качестве функции получения ключа из пароля (KDF) по умолчанию. argon2id намеренно требователен к памяти и времени, что делает перебор паролей значительно дороже для атакующего. LUKS1 использует PBKDF2 и остаётся актуальным только для совместимости с GRUB, который пока имеет ограниченную поддержку LUKS2.

Наиболее распространённая комбинация - AES-XTS с ключом 512 бит (256 бит для AES плюс 256 бит для XTS). Режим XTS спроектирован специально для шифрования дисков и устраняет слабости более старых режимов (CBC, ECB) в контексте блочного хранилища:

# Создать LUKS2-контейнер с явными параметрами
cryptsetup luksFormat --type luks2 \
  --cipher aes-xts-plain64 \
  --key-size 512 \
  --hash sha256 \
  --pbkdf argon2id \
  --iter-time 3000 \
  /dev/sdb

# Открыть контейнер и создать маппер
cryptsetup luksOpen /dev/sdb encrypted_disk

# Создать файловую систему на виртуальном устройстве
mkfs.ext4 /dev/mapper/encrypted_disk

# Смонтировать
mount /dev/mapper/encrypted_disk /mnt/secure

Параметр --iter-time задаёт время в миллисекундах, которое cryptsetup тратит на настройку KDF при создании слота. Больше времени - больше итераций argon2id - медленнее перебор паролей. На сервере с мощным CPU и редкими перезагрузками можно поставить 5000-10000 мс. На слабом одноплатном компьютере придётся снизить до 500-1000 мс.

Управление ключевыми слотами и смена паролей

Возможность иметь несколько независимых паролей для одного устройства - одна из важнейших практических возможностей LUKS. Системный диск сервера может иметь административный пароль и пароль для процедуры восстановления в отдельных слотах. Ноутбук разработчика - личный пароль и пароль для системного администратора компании.

# Просмотреть состояние заголовка и слотов
cryptsetup luksDump /dev/sdb

# Добавить второй пароль в новый слот
cryptsetup luksAddKey /dev/sdb

# Добавить ключевой файл как альтернативу паролю
cryptsetup luksAddKey /dev/sdb /path/to/keyfile.bin

# Изменить пароль в конкретном слоте
cryptsetup luksChangeKey /dev/sdb

# Удалить пароль из слота (нужен любой действующий пароль)
cryptsetup luksRemoveKey /dev/sdb

# Принудительно уничтожить конкретный слот по номеру
cryptsetup luksKillSlot /dev/sdb 1

Критически важная операция, о которой нередко забывают при первоначальной настройке - резервная копия заголовка LUKS. Заголовок хранится в начале зашифрованного устройства. Если несколько секторов в начале диска окажутся повреждены (плохие блоки, случайная запись, fsck применённый к зашифрованному устройству напрямую), данные станут навсегда недоступны даже при наличии верного пароля. Резервная копия заголовка - это страховка от таких сценариев:

# Создать резервную копию заголовка
cryptsetup luksHeaderBackup /dev/sdb \
  --header-backup-file /secure/location/sdb-luks-header.img

# Восстановить заголовок из резервной копии
cryptsetup luksHeaderRestore /dev/sdb \
  --header-backup-file /secure/location/sdb-luks-header.img

Резервную копию заголовка нужно хранить отдельно от самого зашифрованного диска. Если оба окажутся у атакующего, он получит полный доступ при знании пароля - никакой дополнительной защиты заголовок сам по себе не даёт.

Автомонтирование и интеграция с systemd через crypttab

Для системных дисков и томов, которые должны монтироваться автоматически, существует файл /etc/crypttab. Он играет для зашифрованных устройств ту же роль, что /etc/fstab для файловых систем - описывает, что и как нужно открыть при загрузке.

# Формат записи в /etc/crypttab:
# имя  устройство  ключ  опции

# Открывать с запросом пароля при каждой загрузке
encrypted_disk  /dev/sdb  none  luks

# Открывать автоматически с ключевым файлом
data_disk  /dev/sdc  /root/keys/data.key  luks

# Открывать с UUID устройства (надёжнее имени)
secure_home  UUID=a1b2c3d4-...  none  luks,timeout=30

После добавления записи в crypttab соответствующая запись в /etc/fstab монтирует устройство через /dev/mapper/имя:

# /etc/fstab
/dev/mapper/encrypted_disk  /mnt/secure  ext4  defaults  0 2

systemd генерирует юниты Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. для каждой записи в crypttab автоматически. Управлять ими можно как обычными службами, что особенно удобно при диагностике проблем с монтированием на серверах без физического доступа.

Шифрование корневой файловой системы и роль initramfs

Полнодисковое шифрование с зашифрованным корневым разделом требует особой архитектуры загрузки. Ядро и initramfs должны оставаться незашифрованными на отдельном разделе /boot, потому что именно initramfs содержит инструменты для ввода пароля и открытия зашифрованного корня до передачи управления системе.

При установке с LUKS на корневой раздел дистрибутив автоматически настраивает initramfs с поддержкой cryptsetup. На Debian-based системах это делается через update-initramfs, на RHEL-based через dracut. После любых изменений в /etc/crypttab или параметрах шифрования нужно пересобрать initramfs:

# Debian/Ubuntu
update-initramfs -u -k all

# RHEL/Fedora
dracut --force

# Проверить что dm_crypt модуль включён в initramfs
lsinitramfs /boot/initrd.img-$(uname -r) | grep dm-crypt

Отдельного внимания заслуживает поддержка LUKS в GRUB. Загрузчик должен открыть зашифрованный раздел ещё до запуска ядра, если /boot находится внутри LUKS-контейнера. GRUB поддерживает LUKS1 без ограничений, поддержка LUKS2 появилась позже и требует использования PBKDF2 вместо argon2id - именно поэтому при шифровании раздела /boot рекомендуется создавать его в формате LUKS1.

Аппаратное ускорение AES и влияние на производительность

Производительность шифрования на уровне блочного устройства - вопрос, который волнует больше всего тех, кто ещё не пробовал. На практике современные процессоры с поддержкой AES-NI (Intel с 2010 года, AMD с 2011 года) выполняют шифрование AES со скоростью, практически равной скорости самого диска. На NVMe-накопителе с пропускной способностью 3 ГБ/с зашифрованное устройство покажет 2.8-3 ГБ/с - потери измеряются единицами процентов.

Убедиться в наличии AES-NI и проверить производительность шифрования:

# Проверить поддержку AES-NI процессором
grep -m1 aes /proc/cpuinfo

# Замерить производительность шифрования разными шифрами
cryptsetup benchmark

# Проверить что dm-crypt использует аппаратное ускорение
dmsetup table /dev/mapper/encrypted_disk

На системах без AES-NI (старые ARM-платы, некоторые встраиваемые системы) ситуация иная. Там накладные расходы шифрования могут достигать 30-50% от пропускной способности диска. В таких сценариях стоит рассмотреть ChaCha20-Poly1305 через capi:rfc7539(chacha20,poly1305) - он эффективнее на устройствах без аппаратного ускорения AES.

dm-crypt и LUKS - это зрелый, хорошо задокументированный стек шифрования, который прошёл проверку временем в производственных системах любого масштаба. Понимание архитектуры мастер-ключей и слотов, осознанный выбор параметров KDF, обязательное резервирование заголовка и правильная интеграция с initramfs превращают его из "галочки при установке" в реальный рубеж защиты данных.