Установка Линукса на зашифрованный DM-Crypt с LUKS корневой раздел

Discussion in 'Безопасность и Анонимность' started by teab0t, 13 Jul 2009.

  1. teab0t

    teab0t New Member

    Joined:
    12 Jul 2009
    Messages:
    3
    Likes Received:
    0
    Reputations:
    0
    Введение
    В этой статье будет описан способ установки Gentoo на зашифрованный корневой раздел.

    1 Разметка диска.

    Имя Тип Тип ФС Точка монтир. Размер (MB) Шифрование
    ------------------------------------------------------------------------------------------------------------
    sdb1 Основной ext2 /boot 100 нет
    sdb5 Логический swap swap 1000 да
    sdb6 Логический ext4 / 15000 да
    sdb7 Логический ReiserFS /home 1000 да
    sdb8 Логический ext4 /usr/local 5000 да
    sdb9 Логический ReiserFS /media/storage 10000 нет
    sdb10 Логический ext3 /media/backup 15000 да
    sdb11 Логический XFS /media/multimedia 160000 нет
    Осн/Лог Свободно 42900

    sdb9 - раздел для хранения различной текстовой информации, софта, музыки (не зашифрован);
    sdb10 - раздел для создания резервных копии важных данных (зашифрован)
    sdb11 - раздел для хранения мультимедийной информации и больших файлов DVD с видео, дистрибутивами Linux'а (не зашифрован)
    Свободное пространство оставляем для экспериментов с другими дистрибутивами GNU/Linux и операционными системами, например Hackintosh или Solaries.


    2 Заполнение диск случайными данными

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

    dd if=/dev/urandom of=/dev/sdb5
    dd if=/dev/urandom of=/dev/sdb6
    dd if=/dev/urandom of=/dev/sdb7
    dd if=/dev/urandom of=/dev/sdb8
    dd if=/dev/urandom of=/dev/sdb10

    При записи на диск программа dd не предоставляет индикатор прогресса, но узнать сколько данных записанно можно командой:
    killall -USR1 dd

    3 Генерация ключей

    dd if=/dev/urandom count=1 > swap_key
    dd if=/dev/urandom count=1 > home_key
    dd if=/dev/urandom count=1 > usr-local_key
    dd if=/dev/urandom count=1 > backup_key

    Ключь для корневого раздела зашифровываем:
    dd if=/dev/urandom count=1 | gpg --symmetric > ./root_key.gpg

    4 Шифрование swap раздела

    cryptsetup -c blowfish -h sha256 -d /dev/urandom create swap /dev/sdb5
    mkswap /dev/mapper/swap
    swapon /dev/mapper/swap

    5 Шифрование разделов диска

    cryptsetup --cipher serpent-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sdb7 home_key
    cryptsetup --cipher serpent-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sdb8 usr-local_key
    cryptsetup --cipher serpent-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sdb10 backup_key

    gpg --decrypt root_key.gpg | cryptsetup --cipher serpent-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sdb6

    6 Открытие зашифрованных LUKS разделов

    cryptsetup luksOpen /dev/sdb7 home --key-file home_key
    cryptsetup luksOpen /dev/sdb8 usr-local --key-file usr-local_key
    cryptsetup luksOpen /dev/sdb10 backup --key-file backup_key

    gpg --decrypt root_key.gpg | cryptsetup luksOpen /dev/sdb6 root

    7 Создание файловых систем на зашифрованных разделах

    mkfs.ext4 /dev/sdb6
    mkfs.reiserfs /dev/sdb7
    mkfs.ext4 /dev/sdb8
    mkfs.ext3 /dev/sdb10

    8 Монтирование файловой(ых) системы

    mount /dev/mapper/root /mnt/gentoo

    Теперь следуем Gentoo Installation Guide (http://www.gentoo.org/doc/en/handbook/handbook-x86.xml) с 5-го до 7-го пункта, либо копируем зараннее установленный дистрибутив линукс на смонтированный раздел.

    9 Скрипт загрузки initramfs - init

    #!/bin/sh

    uv_init=/sbin/init
    uv_root_mapping=root
    uv_swap_mapping=swap

    gv_root_mode=ro

    die()
    {
    local lv_msg="$1"
    umount -n /mnt 2>/dev/null
    echo -e "\033[01;31m${lv_msg}\033[00m"
    echo
    }

    bin_exist()
    {
    [ ! -e "/bin/${1}" ] && [ ! -e "/sbin/${1}" ] && die "Error: ${2} ${1} not found."
    }

    modprobe_group() {
    local lv_group="$1"
    local lv_mod

    if [ -f "/etc/modules/${lv_group}" ]; then
    for lv_mod in `cat "/etc/modules/${lv_group}"`; do
    modprobe "${lv_mod}" > /dev/null 2>&1
    done
    fi
    }

    get_key() {
    local lv_dev="${1}"
    gv_filepath="${2}"
    local lv_devname="`echo "${lv_dev}" | cut -d'/' -f3 | tr -d '0-9'`" # for use with /sys/block/
    local lv_filename="`echo "${gv_filepath}" | sed 's/\/.*\///g'`"

    local lv_first_time=1
    local lv_iter=0
    while ! mount -n -o ro,iocharset=cp437 "${lv_dev}" /mnt 2>/dev/null >/dev/null
    do
    if [ "${lv_first_time}" != 0 ]; then
    echo "Insert removable device and press Enter."
    read x
    echo "Please wait a few seconds...."
    lv_first_time=0
    else
    [ ! -e "/sys/block/${lv_devname}" ] && echo "Info: /sys/block/${lv_devname} does not exist."
    [ ! -e "${lv_dev}" ] && echo "Info: ${lv_dev} does not exist."
    fi
    sleep 5
    lv_iter = $(($lv_iter + 5))
    echo "Passed ${lv_iter} sec"
    done
    echo "Info: Removable device mounted."
    # check if keyfile exist
    if [ ! -e "/mnt/${gv_filepath}" ]; then
    die "Error: ${gv_filepath} does not exist on ${lv_dev}."
    fi
    # get the key
    [ "$uv_check_env" -eq 1 ] && bin_exist "gpg" "--"
    }

    exec_cryptsetup() { # 1 is device, 2 is mapping
    local lv_arg1="create"
    local lv_arg2="${2}"
    local lv_arg3="${1}"

    cryptsetup isLuks "${1}" 2>/dev/null && { lv_arg1="luksOpen"; lv_arg2="${1}"; lv_arg3="${2}"; }

    # Fixup gpg tty requirement
    mv /dev/tty /dev/tty.org
    cp -a /dev/console /dev/tty
    while [ ! -e "/dev/mapper/${2}" ]
    do
    sleep 2
    gpg --quiet --homedir / --logger-file /dev/null --decrypt /mnt/${gv_filepath} | \
    cryptsetup "${lv_arg1}" "${lv_arg2}" "${lv_arg3}" 2>/dev/null
    done
    rm /dev/tty
    mv /dev/tty.org /dev/tty
    umount -n /mnt
    }

    do_root_work() {
    [ -n "${gv_root_device}" ] || die "Error: root missing."

    # if 'init_key_root' arg was given
    [ -n "${gv_key_root_device}" ] || die "Error: init_key_root: device field empty."
    [ -n "${gv_key_root_filepath}" ] || die "Error: init_key_root: filepath field empty."

    get_key "${gv_key_root_device}" "${gv_key_root_filepath}"
    echo "Partition: root"
    exec_cryptsetup "${gv_root_device}" "${uv_root_mapping}"
    mount -o "${gv_root_mode}" "/dev/mapper/${uv_root_mapping}" /new-root
    if [ "$?" -ne 0 ]; then
    cryptsetup luksClose "${uv_root_mapping}" 2>/dev/null || cryptsetup remove "${uv_root_mapping}"
    die "Error: mount root failed, dm-crypt mapping closed."
    fi
    }

    do_work() {
    print_msg
    do_root_work
    do_switch
    }

    do_switch() {
    # Unmount everything and switch root filesystems for good:
    # exec the real init and begin the real boot process.
    echo > /proc/sys/kernel/hotplug
    [ "${gv_splash_silent}" -eq 1 ]
    echo "Switching / ..."
    sleep 1
    umount -l /proc
    umount -l /sys
    umount -l /dev
    exec switch_root /new-root "${uv_init}"
    }

    print_msg() {
    echo
    local msg=`cat /etc/msg`
    echo -e "\033[01;32m${msg}\033[00m"
    echo
    }

    set_gv() {
    gv_root_device="${gv_root}"
    gv_key_root_device="${gv_key_root}"
    gv_key_root_filepath="/.keys/gentoo-root-key.gpg"
    }

    main() {
    gv_root_uuid="8cg8ff58-859b-43ca-b7be-55a3ceb01ce9"
    gv_key_root_uuid="6A91-1360"

    export PATH=/sbin:/bin
    # dmesg -n 1
    umask 0077
    [ ! -d /proc ] && mkdir /proc
    mount -t proc proc /proc
    [ "$uv_check_env" -eq 1 ] && bin_exist "cryptsetup" "--"
    [ ! -d /tmp ] && mkdir /tmp
    [ ! -d /mnt ] && mkdir /mnt
    [ ! -d /new-root ] && mkdir /new-root
    mount -t sysfs sysfs /sys
    modprobe_group boot
    # populate /dev from /sys
    mount -t tmpfs tmpfs /dev
    /sbin/mdev -s
    # handle hotplug events
    echo /sbin/mdev > /proc/sys/kernel/hotplug
    # wait until root device won't be detected
    gv_root=
    gv_key_root=
    while [ -z "${gv_root}" ] || [ -z "${gv_key_root}" ]
    do
    sleep 3
    gv_root=`findfs UUID=${gv_root_uuid}`
    gv_key_root=`findfs UUID=${gv_key_root_uuid}`
    done
    # set global variables for root and key devices
    set_gv
    do_work
    }
    main

    Этот скрипт является упрощенной версией (http://www.gentoo-wiki.info/SECURITY_System_Encryption_DM-Crypt_with_LUKS)

    10 Создание initramfs образа

    Initramfs будет создан на основе BusyBox (www.busybox.net).

    ROOT="/tmp/bb" USE="static" emerge busybox

    cd /tmp
    mkdir initramfs
    cd initramfs
    mkdir bin dev etc lib mnt new-root proc sbin sys tmp
    cd bin
    cp /tmp/bb/bin/busybox .
    for i in echo md5sum mkdir mknod modprobe mount mv rm sed sh switch_root tr umount
    do
    ln busybox $i
    done
    cd ../sbin
    cp /sbin/cryptsetup .
    ln ../bin/busybox mdev
    cd ../dev
    mknode --mode=0660 null c 1 3
    mknode --mode=0660 console c 5 1

    Установка gnupg. Устанавливаем версию 1.4.9, в ней нет gpg-agent.
    USE="static" emerge -v =gnupg-1.4.9
    cd ../bin
    cp /usr/bin/gpg .

    Копирование init скрипта в корневой раздел:
    cp /path/to/init /tmp/initramfs

    Упаковка initramfs образа в сжатый cpio архив:
    find . | cpio -o -H newc | gzip -9 > /boot/initramfs-gentoo-crypt

    11 Конфигурация ядра

    Device Drivers --->
    Multi-device support (RAID and LVM) --->
    <*> Device mapper support
    <*> Crypt target support
    [*] DM uevents

    Device Drivers --->
    Block devices --->
    <*> RAM disk support
    [*] Initial RAM disk (initramfs/initrd) support

    File systems --->
    Pseudo filesystems --->
    [*] /proc file system support
    [*] Virtual memory file system support (former shm fs)
    # support for sysfs required (CONFIG_SYSFS)

    Cryptographic options --->
    <*> SHA256 digest algorithm
    <*> SHA384 and SHA512 digest algorithms
    <*> Blowfish cipher algorithm
    <*> Twofish cipher algorithm
    <*> Serpent cipher algorithm
    <*> AES cipher algorithms (x86_64)

    <*> The Extended 4 (ext4) filesystem
    [ ] Enable ext4dev compatibility
    [*] Ext4 extended attributes
    [*] Ext4 POSIX Access Control Lists
    [*] Ext4 Security Labels

    Если компилировать эти опции как модули, то их нужно скопировать вместе с зависимостями в дирректорию /tmp/initramfs/lib/modules/`uname -r`/ и добавить имена без суффикса .ko в файл /tmp/initramfs/etc/modules/boot.

    12 /etc/fstab
    Редактирования файла описания точек монтирования файловых систем. UUID дисков находятся в /dev/disk/by-uuid.

    UUID=b5bd3eaa-27ef-42g3-a2c4-ec8696564bdc /boot ext2 noauto,noatime 0 0
    UUID=1a9cs4fb-3esd-48b6-b9fb-13dda6928060 / ext4 noatime 0 1
    UUID=8d7d41ff-9geb-4e83-ad8b-4cc8cb89b408 none swap sw 0 0
    UUID=e0a39a9d-d57b-44e3-9114-63c30726827f /home reiserfs noatime,noexec 0 0
    UUID=f9601db4-d6e7-4952-b129-e501128c55e9 /usr/local ext4 relatime,user,exec 0 0
    UUID=9776e7bd-15b6-44cc-b1fc-6700401f6466 /media/storage reiserfs noexec,user 0 0
    UUID=3d3ea35b-b6eb-411f-9516-48741e038926 /media/backup ext4 defaults,noexec 0 0
    UUID=a12cfa02-60e8-4c5b-bdfd-34d3c7006a6c /media/multimedia xfs noexec,user 0 0

    13 Конфигурация загрузчика

    default 0
    timeout 5
    splashimage=(hd0,0)/boot/grub/splash.xpm.gz

    title Gentoo Linux 2.6.29-r5
    root (hd0,0)
    kernel /boot/kernel-genkernel-x86_64-2.6.29-gentoo-r5 vga=791 root=UUID=ba596e56-046a-4c87-8ab8-184b2bbd7e81
    initrd /boot/initramfs-gentoo-crypt

    14 Монтирование зашифрованных разделов во время запуска системы

    В файле /etc/conf.d/dmcrypt:

    swap=crypt-swap
    source='/dev/disk/by-uuid/c01f3387-5426-4a25-8051-220938f81a7c'
    key='/.keys/gentoo-crypt-swap'
    remdev='/dev/disk/by-uuid/6A91-1378'

    target=home
    source='/dev/disk/by-uuid/6d155170-a323-46ca-aa17-cdb462bc842b'
    key='/.keys/gentoo-crypt-home'
    remdev='/dev/disk/by-uuid/6A91-1378'

    target=usr-local
    source='/dev/disk/by-uuid/c04f3387-5426-4a25-8051-220938f81a7c'
    key='/.keys/gentoo-crypt-usr_local'
    remdev='/dev/disk/by-uuid/6A91-1378'

    target=backup
    source='/dev/disk/by-uuid/6d255170-a323-46ca-aa17-cdb462bc842b'
    key='/.keys/gentoo-crypt-backup'
    remdev='/dev/disk/by-uuid/6A91-1378'

    Во время загрузки я получал такую ошибку:
    "Failed to find mount point for ${target}, skipping"

    Что бы ее исправить в скрипте /lib/rcscripts/addons/dm-crypt-start.sh заменяем строку:
    mount_point=$(grep "/dev/mapper/${target}" /proc/mounts | cut -d' ' -f2)
    на
    mount_point=$(grep "/dev/${target}" /proc/mounts | cut -d' ' -f2)

    15 Проверка md5 суммы ядра во время загрузки системы

    Вычисляем md5 сумму ядра:
    md5sum /boot/vmlinux-2.6.29-gentoo-rc5

    В скрипте /etc/init.d/local добавляем функцию, в которой вместо значения переменной md5sum_boot="xxx." подставляем свое.
    check_md5sum_initramfs() {
    mnt=`mount | grep /boot`
    if [[ -z ${mnt} ]]; then
    mount /boot
    fi
    local md5sum_boot="xxxxxxx"
    local md5sum=`md5sum /boot/vmlinuz-2.6.29-gentoo-r5 | cut -d" " -f1`
    [ "${md5sum}" != "${md5sum_boot}" ] && echo -e "\033[01;31m * ALARM! Kernel partition was modified!\033[00m" && read x
    if [[ -z ${mnt} ]]; then
    umount /boot
    fi
    }
    check_md5sum_initramfs

    Список литературы
    http://www.gentoo-wiki.info/SECURITY_System_Encryption_DM-Crypt_with_LUKS
    http://forum.antichat.ru/showthread.php?t=51519
     
    #1 teab0t, 13 Jul 2009
    Last edited: 13 Jul 2009