dm-crypt (Русский)/Swap encryption (Русский)

Шифрование подкачки при помощи dm-crypt. В зависимости от требований могут использоваться различные методы шифрования раздела подкачки (свопа), которые описаны ниже. Настройка, при которой шифрование подкачки пересоздаётся при каждой загрузке (с новым ключом), обеспечивает более высокую защиту данных, поскольку предотвращает утечку чувствительной информации, которая могла быть выгружена в подкачку и сколько угодно длительное время не была перезаписана случайным образом другими данными поверх данной информации. Однако такое перешифрование при каждом новом запуске системы также делает невозможным использование функции гибернации (suspend-to-disk). В данной статье рассмотрены способы шифрования свопа как с поддержкой гипернации так и без неё.

Без поддержки гибернации

В системах, где гибернация (suspend-to-disk) не требуется, можно настроить /etc/crypttab так, чтобы при загрузке раздел подкачки расшифровывался с использованием случайного пароля и обычного dm-crypt. Случайный пароль удаляется при выключении, оставляя в разделе подкачки только зашифрованные, недоступные данные.

Чтобы включить эту функцию, просто раскомментируйте строку, начинающуюся с swap в /etc/crypttab. Замените параметр устройства на имя вашего раздела подкачки. Например, это будет выглядеть примерно так:

/etc/crypttab
# <name>  <device>     <password>     <options>
swap      /dev/sdX#    /dev/urandom   swap,cipher=aes-xts-plain64,size=512,sector-size=4096

Это сопоставит /dev/sdX# (параметр, который требуется отредактировать) с /dev/mapper/swap как раздел подкачки, который можно добавить в /etc/fstab как обычный swap. Если у вас ранее был незашифрованный раздел подкачки, не забудьте его отключить — или переиспользуйте соответствующую запись в fstab, изменив устройство на /dev/mapper/swap. Значения по умолчанию подходят для большинства случаев. Другие параметры и объяснение колонок смотрите в crypttab(5), а также в FAQ cryptsetup, пункт 2.3.

Примечание: При использовании твёрдотельных накопителей типа NVMe, устройства вида /dev/nvme#n#p# аналогичны /dev/sdX#, а устройства вида /dev/nvme#n#/dev/sdX.


Важно: Все данные на указанном устройстве будут безвозвратно удалены. Использование простых имён устройств ядра небезопасно, поскольку порядок их назначения (например, /dev/sda, /dev/sdb) может изменяться при каждой загрузке. Возможные варианты:
  • Использовать пути by-id и by-path. Однако они тоже чувствительны к изменениям оборудования. См. Persistent block device naming (Русский)#by-id и by-path.
  • Использовать PARTLABEL.
  • Использовать имя логического тома LVM.
  • Использовать метод, описанный в #UUID и LABEL. Метки и UUID нельзя использовать напрямую, поскольку при каждом запуске устройство подкачки пересоздаётся и перешифровывается с помощью mkswap, см. FAQ cryptsetup.
Примечание: Иногда настройка раздела подкачки может завершиться сбоем, см. systemd issue 10179.

Чтобы использовать постоянное имя устройства by-id вместо простого имени ядра, сначала определите устройство подкачки:

# find -L /dev/disk -samefile /dev/sdaX
/dev/disk/by-id/ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-partX
/dev/disk/by-id/wwn-0x60015ee0000b237f-partX

Затем используйте один из найденных путей в качестве постоянной ссылки на раздел (вместо /dev/sdX#):

/etc/crypttab
# <name>  <device>                                                         <password>     <options>
swap      /dev/disk/by-id/ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-partX  /dev/urandom   swap,cipher=aes-xts-plain64,size=512,sector-size=4096

После перезагрузки, активировав зашифрованный swap, можно увидеть с помощью swapon -s, что для него создано устройство типа /dev/dm-1, а команда lsblk покажет тип crypt в колонке FSTYPE. Из-за нового шифрования при каждом запуске UUID для /dev/mapper/swap будет постоянно меняться.

Примечание: Если выбранный для подкачки раздел ранее использовался как LUKS-устройство, crypttab не перезапишет его, чтобы создать swap. Это сделано для предотвращения потери данных из-за ошибочной идентификации. Чтобы использовать такой раздел, необходимо стереть заголовок LUKS один раз.

UUID и LABEL

Опасно использовать crypttab swap с простыми именами устройств, такими как /dev/sdX# или даже /dev/disk/by-id/ata-SERIAL-partX. Небольшое изменение в разметке или порядке устройств может привести к тому, что /etc/crypttab при следующей загрузке отформатирует важные данные. То же самое касается PARTUUID, если вы решите использовать этот раздел для других целей, но забудете удалить запись из crypttab.

Надёжнее использовать UUID или LABEL. По умолчанию это не работает, потому что dm-crypt и mkswap перезапишут содержимое раздела, включая UUID и LABEL. Однако можно задать смещение, чтобы создать небольшую фиктивную файловую систему, которая будет служить только для хранения постоянной метки.

Создайте файловую систему с нужной меткой:

# mkfs.ext2 -L cryptswap /dev/sdX# 1M

Нетипичный параметр после имени устройства ограничивает размер файловой системы до 1 MiB, оставляя место для зашифрованной подкачки позади неё.

# blkid /dev/sdX#
/dev/sdX#: LABEL="cryptswap" UUID="b72c384e-bd3c-49aa-b7a7-a28ea81a2605" TYPE="ext2"

Теперь /dev/sdX# можно легко идентифицировать по UUID или LABEL, даже если имя устройства или номер раздела изменятся. Останется только указать записи в /etc/crypttab и /etc/fstab. Пример с другими параметрами шифрования:

/etc/crypttab
# <name> <device>         <password>    <options>
swap     LABEL=cryptswap  /dev/urandom  swap,offset=2048,cipher=aes-xts-plain64,size=512,sector-size=4096

Обратите внимание на смещение: оно составляет 2048 секторов по 512 байт (не зависит от сектора dm-crypt), то есть 1 MiB. Таким образом, шифрованный swap не повредит метку/UUID файловой системы, и соблюдается выравнивание данных.

/etc/fstab
# <filesystem>    <dir>  <type>  <options>  <dump>  <pass>
/dev/mapper/swap  none   swap    defaults   0       0

С такой настройкой cryptswap будет использовать только раздел с указанной LABEL, независимо от его имени в системе. Если вы решите использовать этот раздел для других целей, форматирование удалит метку, и /etc/crypttab больше не будет его использовать при загрузке.

Отключение гибернации в графических средах

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

В Xfce можно скрыть кнопки Гибернация и Гибридный сон следующими командами:

$ xfconf-query -c xfce4-session -np /shutdown/ShowHibernate -t bool -s false
$ xfconf-query -c xfce4-session -np /shutdown/ShowHybridSleep -t bool -s false

С поддержкой гибернации

Ниже описаны три альтернативных метода настройки зашифрованной подкачки с возможностью гибернации. При использовании любого из них нужно учитывать, что важные данные, выгруженные в подкачку, могут сохраняться там длительное время (до случайной перезаписи новыми данными поверх старых). Если данный риск критичный, рассмотрите возможность настройки системного задания, которое будет повторно шифровать swap, например, при каждом выключении системы, наряду с выбранным методом.

Использование swap-файла

Файл подкачки может располагаться в файловой системе внутри зашифрованного устройства. Следуйте инструкциям по созданию swap-файла из Swap (Русский)#Файл подкачки и настройте гибернацию согласно Power management (Русский)/Suspend and hibernate (Русский)#Настройка initramfs.

При использовании initrd на базе systemd и зашифрованной корневой файловой системы это может быть очень простым и гибким способом шифрования swap. После настройки зашифрованной корневой файловой системы можно создать swap-файл, активировать его и добавить в /etc/fstab — он будет работать с гибернацией без дополнительной настройки.

Примечание: При использовании параметра ядра resume= он должен указывать на уже расшифрованное/смонтированное устройство, содержащее файловую систему с файлом подкачки.

Использование swap-раздела

Примечание: Чтобы использовать раздел, который в данный момент используется системой, необходимо сначала его отключить с помощью swapoff /dev/device от имени root и убедиться, что в /etc/crypttab отсутствует строка, ссылающаяся на это устройство.

Используйте cryptsetup-luksFormat(8), чтобы создать зашифрованный контейнер для раздела подкачки:

# cryptsetup luksFormat --label swap /dev/device

Откройте контейнер под именем /dev/mapper/swap:

# cryptsetup open /dev/disk/by-label/swap swap

Создайте файловую систему swap внутри отображённого раздела:

# mkswap /dev/mapper/swap

Если вы не используете systemd#GPT partition automounting, добавьте отображённый раздел в /etc/fstab, добавив следующую строку:

/dev/mapper/swap none swap defaults 0 0

Чтобы настроить систему на восстановление из гибернации, используйте параметр ядра resume=/dev/mapper/swap. Подробности см. в Power management/Suspend and hibernate#Pass hibernate location to initramfs.

Использование TPM

Далее описывается способ автоматической расшифровки swap с помощью ключа, хранящегося в TPM.

Вы можете использовать systemd-cryptenroll, чтобы записать ключ в LUKS-контейнер и TPM, а затем удалить ранее созданный слот с паролем:

# systemd-cryptenroll --tpm2-device auto /dev/device
# systemd-cryptenroll --wipe-slot password /dev/device

Проверьте результат:

# systemd-cryptenroll /dev/device
SLOT TYPE
   0 tpm2

Использование дополнительной парольной фразы или ключевого файла

У основной настройки, приведённой выше, есть недостаток: требуется вручную вводить дополнительную парольную фразу для swap-раздела при каждой загрузке.

Важно: Не используйте эту настройку с ключевым файлом, если /boot не зашифрован. См. информацию об уязвимости здесь. В качестве альтернативы используйте ключевой файл, зашифрованный через gnupg, как описано здесь: https://bbs.archlinux.org/viewtopic.php?id=120181

Расшифровка раздела в initramfs

Для восстановления из гибернации с зашифрованного swap-раздела он должен быть расшифрован в initramfs.

mkinitcpio
initramfs на базе systemd

При использовании initramfs на базе systemd с хуком sd-encrypt из mkinitcpio, вы можете:

Пример для устройства swap, расшифровываемого через TPM:

/etc/crypttab.initramfs
swap UUID=56f8ee97-54b3-4a65-9282-688deb922527 none tpm2-device=auto
initramfs на базе busybox

При использовании стандартного initramfs на базе busybox с хуком encrypt следуйте приведённым ниже инструкциям.

Если swap-устройство находится на другом физическом диске, отличном от корневой файловой системы, хук encrypt не сможет его открыть. В этом случае восстановление из гибернации произойдёт до того, как будет доступен /etc/crypttab, поэтому необходимо создать собственный хук в /etc/mkinitcpio.conf, чтобы открыть LUKS-устройство подкачки до момента восстановления.

Примечание: Этот раздел применим только при использовании encrypt-хука, который может разблокировать только одно устройство (archlinux/mkinitcpio/mkinitcpio#231). При использовании sd-encrypt можно разблокировать несколько устройств, см. dm-crypt/System configuration#Using systemd-cryptsetup-generator.

Теперь нужно создать хук, который будет открывать swap при загрузке. Вы можете либо установить и настроить mkinitcpio-openswapAUR, либо выполнить следующие шаги вручную. Создайте файл хука со следующей функцией:

/etc/initcpio/hooks/openswap
run_hook ()
{
    cryptsetup open /dev/device swap
}
Важно: Монтирование файловой системы может быть опасным и разрушительным. Ключевой файл не должен считываться с файловой системы, которая была смонтирована во время перехода в гибернацию.

Для открытия swap-устройства вручную с вводом пароля:

/etc/initcpio/hooks/openswap
run_hook ()
{
    ## Необязательно: защита от гонок
    x=0;
    while [ ! -b /dev/mapper/root-device ] && [ $x -le 10 ]; do
       x=$((x+1))
       sleep .2
    done
    ## Конец необязательного блока

    mkdir crypto_key_device
    mount /dev/mapper/root-device crypto_key_device
    cryptsetup open --key-file crypto_key_device/path-to-the-key /dev/device swap
    umount crypto_key_device
}

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

На некоторых компьютерах возможны состояния гонки, при которых `mkinitcpio` пытается смонтировать устройство до завершения расшифровки или до появления устройства в `/dev`. Комментарии в блоке Optional добавляют задержку до 2 секунд, чтобы дождаться готовности корневого устройства.

Примечание: Если swap расположен на SSD и требуется поддержка discard/TRIM, необходимо добавить параметр --allow-discards в команду `cryptsetup` в хуке `openswap`. См. Dm-crypt/Specialties#Discard/TRIM support for solid state drives (SSD) или SSD для подробностей. Также необходимо указать параметр `discard` в `fstab` для соответствующего устройства.

Затем создайте и отредактируйте файл установки хука:

/etc/initcpio/install/openswap
build ()
{
   add_runscript
}
help ()
{
cat<<HELPEOF
  Этот хук открывает зашифрованный раздел подкачки /dev/device в /dev/mapper/swap
HELPEOF
}

Добавьте хук openswap в массив HOOKS в файле /etc/mkinitcpio.conf, перед filesystem, но после encrypt. Не забудьте также добавить хук resume после openswap:

HOOKS=(... encrypt openswap resume filesystems ...)

Пересоберите initramfs.

При следующей загрузке хук openswap откроет раздел подкачки, и ядро сможет использовать его для восстановления. Если вы используете специальные хуки для гибернации, убедитесь, что они идут после openswap в массиве HOOKS. Обратите внимание, что если swap открывается в initrd, то запись о нём в /etc/crypttab больше не требуется.

dracut

Создайте файл ключа:

# dd bs=512 count=4 if=/dev/random iflag=fullblock | install -m 0600 /dev/stdin /etc/cryptsetup-keys.d/swap.key

Добавьте ключ в LUKS:

# cryptsetup luksAddKey /dev/device /etc/cryptsetup-keys.d/swap.key

Настройте `dracut` так, чтобы он включал модуль resume и добавлял ключ в initramfs (см. также dracut#Hibernation):

/etc/dracut.conf.d/resume-from-hibernate.conf
add_dracutmodules+=" resume "
install_items+=" /etc/cryptsetup-keys.d/swap.key "

Пересоберите initramfs.

Добавьте параметры rd.luks.name и rd.luks.key (подставив UUID раздела swap) в командную строку ядра. Пример строки загрузки:

kernel /vmlinuz-linux cryptdevice=/dev/sda2:root root=/dev/mapper/root resume=/dev/mapper/swap rd.luks.name=fd839505-3213-4603-9a70-c5a96a24768f=swap rd.luks.key=/etc/cryptsetup-keys.d/swap.key ro

LVM внутри LUKS

Если том подкачки находится в группе томов, которая активируется в initramfs, просто следуйте инструкциям из Power management (Русский)/Suspend and hibernate (Русский)#Гибернация.

Известные проблемы