Виртуальная машина (VM) — программная и/или аппаратная система, эмулирующая аппаратное обеспечение некоторой платформы.
Виртуальная машина (VM) исполняет некоторый машинно-независимый код (например, байт-код, шитый код, p-код) или машинный код реального процессора. Помимо процессора, ВМ может эмулировать работу как отдельных компонентов аппаратного обеспечения, так и целого реального компьютера (включая BIOS, оперативную память, жёсткий диск и другие периферийные устройства).
В последнем случае в ВМ, как и на реальный компьютер, можно устанавливать операционные системы (например, Windows можно запускать в виртуальной машине под Linux или наоборот). На одном компьютере может функционировать несколько виртуальных машин (это может использоваться для имитации нескольких серверов на одном реальном сервере с целью оптимизации использования ресурсов сервера).
Заметки по созданию полностью зашифрованного образа гостевой системы:
Извлекаем содержимое корневого раздела образа виртуальной машины, который требуется зашифровать, в tar-архив vm_root.tar. Проверяем, чтобы в образе были необходимые для шифрования и EFI-загрузки разделов утилиты, такие как cryptodisk и grub-efi.
Создаём файл с дисковым образом, содержащим два раздела - небольшой раздел для EFI (p1, 100МБ) и корневой раздел, содержимое которого будет зашифровано (p2).
truncate -s 4GB disk.img parted disk.img mklabel gpt parted disk.img mkpart primary 1Mib 100Mib parted disk.img mkpart primary 100Mib 100% parted disk.img set 1 esp on parted disk.img set 1 boot on |
Настраиваем EFI на первом разделе и дисковое шифрование LUKS на втором. Для повышения защищённости можно заполнить шифрованный раздел случайными числами, но это приведёт к увеличению размера итогового образа qcow2. Создаём на шифрованном разделе ФС Ext4.
Привязываем образ к loop-устройству.
losetup -P -f disk.img |
Определяем имя созданного устройства (/dev/loopN), в дальнейшем используем переменную $l вместо устройства.
l=($(losetup -l|grep disk.img)) |
Создаём раздел с EFI, используем VFAT.
mkfs.vfat ${l}p1 |
Определяем UUID раздела EFI.
blkid ${l}p1 |
Создаём шифрованный раздел, в процессе задаём временный пароль для расшифровки.
cryptsetup --type luks1 luksFormat ${l}p2 |
Определяем UUID шифрованного раздела.
blkid ${l}p2 |
Активируем шифрованный раздел и создаём на нём ФС ext4.
cryptsetup luksOpen ${l}p2 cr_root mkfs.ext4 /dev/mapper/cr_root |
Монтируем раздел, копируем в него содержимое tar-архива с начинкой корневого раздела и создаём каталоги для точек монтирования /run, /sys, /proc и /dev.
mount /dev/mapper/cr_root /mnt tar -C /mnt -xpf vm_root.tar for m in run sys proc dev; do mount --bind /$m /mnt/$m; done |
Входим в окружение созданного корневого раздела.
chroot /mnt |
В /etc/fstab определяем метку корневого раздела (/dev/disk/cr_root) и раздела EFI (/boot/efi).
Настраиваем и устанавливаем загрузчик GRUB (в некоторых дистрибутивах вместо /boot/grub используется /boot/grub2, а вместо префикса "grub" - "grub2-"):
echo "GRUB_ENABLE_CRYPTODISK=y" >> /etc/default/grub mount /boot/efi grub-install --removable --target=x86_64-efi grub-mkconfig -o /boot/grub/grub.cfg |
Для систем с mkinitramfs (Debian) дополнительно нужно добавить параметры шифрованного раздела в /etc/crypttab:
cr_root UUID=<uuid> luks none |
После чего пересоздаём образ ram-диска с компонентами для начальной загрузки.
Для систем с dracut требуется изменить настройки /etc/default/grub, указав в GRUB_CMDLINE_LINUX привязку rd.luks.uuid=<UUID>. Для дистрибутивов с SELinux также нужно обновить метки (relabel).
Отмонтируем созданные в процессе подготовки образа разделы из /mnt и пытаемся загрузить образ, используя режим EFI. В процессе загрузки вводим заданный ранее временный пароль и проверяем работоспособность окружения.
Заменяем временный пароль на ключ для быстрой загрузки и настраиваем ram-диск для его использования. Для образа, примонтированного через /dev/sda:
dd if=/dev/urandom bs=1 count=33|base64 -w 0 > /etc/cryptsetup-keys.d/luks-<UUID>.key chmod 600 /etc/cryptsetup-keys.d/luks-<UUID>.key cryptsetup --key-slot 1 luksAddKey /dev/sda2 # первичный ключ для восстановления cryptsetup --key-slot 0 luksRemoveKey /dev/sda2 # удаляем временный ключ cryptsetup --key-slot 0 --iter-time 1 luksAddKey /dev/sda2 /etc/cryptsetup-keys.d/luks-<UUID>.key |
Указание опции "-w 0" в dd необходимо для того, чтобы исключить появление в пароле символа перевода строки.
Для систем с mkinitramfs теперь нужно изменить настройки /etc/crypttab, указав путь к сгенерированному ключу:
cr_root UUID=<UUID> /etc/cryptsetup-keys.d/luks-<UUID>.key luks |
Для систем с dracut необходимо добавить hook ключа в /etc/dracut.conf.d, а для Debian также потребуется указать маску определения файла с ключом:
cryptodisk.conf install_items+=" /etc/cryptsetup-keys.d/* " echo "KEYFILE_PATTERN=\"/etc/cryptsetup-keys.d/*\"" >>/etc/cryptsetup-initramfs/conf-hook |
Теперь можно перегенерировать образ RAM-диска начальной загрузки. После попытки загрузки пароль будет спрошен один раз только на стадии запуска GRUB и на последующих стадиях загрузки запрашиваться не будет.
Дополнительные заметки доступны в блоге.