Содержание статьи
Сегодня хранить важные данные в открытом виде стало как никогда опасно. И даже не столько из-за государственной слежки (захотят — найдут, к чему придраться, и так), сколько из-за желающих эти данные похитить. В принципе, для защиты информации имеется множество методов, но в статье будет описаны именно криптографические средства.
Введение
В отличие от некоторых других операционных систем, в Linux имеется множество средств для криптографической защиты информации — от шифрования почтовых переписок до шифрования файлов и блочных устройств. Нас интересует именно шифрование на уровне файловых систем, файлов и блочных устройств. Для начала стоит разобраться, в чем разница.
Шифрование на уровне файловых систем предполагает наличие прослойки между основной файловой системой (если, конечно, файловая система сама по себе не поддерживает шифрование) и пользователем. Преимущество у данного типа шифрования — то, что ключи для всех пользователей разные. Недостаток же — если включить шифрование имен файлов, длина допустимого имени уменьшится, кроме того, пользователь может сохранить файл в иное место на диске, что автоматически нивелирует пользу. И еще одно но — даже если включено шифрование имен, временные метки останутся прежними.
Шифрование блочных устройств происходит на более низком уровне, под файловой системой. При этом сама файловая система, разумеется, не знает, что она находится на шифрованном томе. Преимущества у данного способа противоположны недостаткам предыдущего. Недостаток же в том, что придется каждый раз при загрузке/монтировании вводить пароль. Второй же недостаток в том, что если в рантайме злоумышленник получит доступ к файлам на криптоконтейнере, все — пиши пропало. Это именно что защита от офлайновых атак. Кроме того, в абсолютном большинстве случаев сохранения криптоконтейнера в облако придется заливать его целиком заново.
В статье будет описана настройка следующих методов криптозащиты:
- dm-crypt/LUKS — создание криптоконтейнера с помощью device-mapper и CryptoAPI ядра;
- eCryptfs — шифрование на уровне файловых систем;
- EncFS — аналогично описанному выше, но не требует загрузки модулей ядра.
dm-crypt/LUKS
Существует два вида настройки dm-crypt — plain и LUKS. Отличие в том, что в случае использования LUKS в начале криптотома присутствуют метаданные, позволяющие использовать несколько ключей и изменять их. В то же время наличие подобного заголовка в некоторых случаях само по себе компрометирующе — впрочем, в большинстве подобных случаев будет компрометирующей и область с высокой степенью энтропии.
Настройка plain dm-crypt с файлом ключа и парольной фразой
Посмотрим, как настроить комбинацию из тома plain dm-crypt, зашифрованного с помощью ключевого файла, в свою очередь содержащегося в LUKS-контейнере. Для начала стоит определиться, как именно будут размещаться разделы. Существует три основных варианта:
- просто крипто-том;
- сперва крипто-том, затем поверх него LVM;
- сперва крипто-том, затем RAID, затем LVM.
И всяческие комбинации. Давай попробуем второй вариант. Первым делом создадим контейнер LUKS для хранения ключевого файла, чтобы использовать этот файл вместе с ключевой фразой. В этом случае вероятность криптоанализа тома, зашифрованного с помощью plain dm-crypt, снижается:
# dd if=/dev/zero of=/root/key.luks bs=512 count=2057
# cryptsetup --align-payload=1 luksFormat /root/key.luks
# cryptsetup luksOpen /root/key.luks cryptokey
# dd if=/dev/urandom of=/dev/mapper/cryptokey
Первая команда подготавливает файл контейнера, вторая этот контейнер создает, третья подключает, четвертая генерирует ключевую информацию. Стоит заметить, что опция --align-payload=1 нужна для того, чтобы размер метаданных LUKS составлял не 4096 512-байтовых блоков, а всего лишь 2056. Таким образом, на собственно ключевую информацию остается 512 байт.
Затем переходим к созданию криптотома. На этом этапе по желанию можно также заполнить диск псевдослучайными данными, чтобы затруднить криптоанализ, если он будет. Затем уже можно создавать криптотом. Команда для этого выглядит следующим образом (естественно, в иных случаях идентификаторы могут отличаться, так что нужно быть внимательным):
# cryptsetup --cipher=serpent-xts-plain64 --offset=0 --key-file=/dev/mapper/cryptokey --key-size=512 open --type=plain /dev/disk/by-id/ata-VBOX_HARDDISK_VB05eadebe-f25e8d59 crypto0
При необходимости надо повторить аналогичную команду и на других устройствах, для которых требуется шифрование. Затем создадим на криптотомах LVM и ФС на нем:
# pvcreate /dev/mapper/crypto0 /dev/mapper/crypto1
# vgcreate vgData /dev/mapper/crypto0 /dev/mapper/crypto1
# lvcreate -n lvData1 -L 10G vgData
# mkfs.ext4 /dev/vgData/lvData1
И далее потребуется настроить подключение этого тома при загрузке. Для этого мы будем использовать initramfs. Запишем имена нужных модулей в файл /etc/initramfs-tools/modules:
dm_crypt
cryptd
xts
serpent_generic
aes_x86_64
aesni_intel
Создадим файл /etc/initramfs-tools/hooks/cryptokeys
примерно следующего содержания (служебная часть скрипта опущена):
# <...>
. /usr/share/initramfs-tools/hook-functions
mkdir ${DESTDIR}/etc/crypto # Создаем каталог в образе initramfs
cp /root/key.luks ${DESTDIR}/etc/crypto # Копируем туда ключ
copy_exec /sbin/cryptsetup /sbin # Заодно копируем и cryptsetup
И файл /etc/initramfs-tools/scripts/local-top/cryptokeys
(служебная часть опять же опущена):
# <...>
modprobe -b dm_crypt
while ! ( /sbin/cryptsetup luksOpen /etc/crypto/key.luks cryptokey && /sbin/cryptsetup plainOpen --key-file=/dev/mapper/cryptokey /dev/disk/by-id/ata-VBOX_HARDDISK_VB05eadebe-f25e8d59 crypto0 && /sbin/cryptsetup plainOpen --key-file=/dev/mapper/cryptokey /dev/disk/by-id/ata-VBOX_HARDDISK_VBc2414841-cfeccde5 crypto1 && /sbin/cryptsetup luksClose cryptokey ) ; do
echo "Try again..."
done
Эти два файла должны быть исполняемыми. Затем создаем initrd:
# update-initramfs -u -k all -v
При следующей перезагрузке будет запрошен пароль для LUKS-контейнера.
В случае использования plain dm-crypt есть еще одна возможность — общий нижний слой, что позволяет сделать нечто наподобие скрытых томов TrueCrypt. Проще привести пример:
# cryptsetup --cipher=serpent-xts-plain64 --offset=0 --size=2097152 --shared open --type=plain /dev/disk/by-id/ata-VBOX_HARDDISK_VBcda8398f-f1f1deec crypto
# cryptsetup --cipher=serpent-xts-plain64 --offset=2097152 --size=2097152 --shared open --type=plain /dev/disk/by-id/ata-VBOX_HARDDISK_VBcda8398f-f1f1deec crypto_shared
Размер и смещение указываются в 512-байтовых блоках.
Xakep #200. Тайная жизнь Windows 10
Расширенные возможности LUKS
Давай посмотрим также и на расширенные возможности использования LUKS-контейнеров. К ним можно отнести смену ключей. Это необходимо при компрометации или создании политики смены ключей. Первым шагом для этого будет создание резервной копии заголовка контейнера. Если все нормально, после смены ключа ее можно уничтожить. Делаем мы ее, понятно, на нешифрованный раздел:
# mount /dev/sdf1 /mnt/flash
# cryptsetup luksHeaderBackup /dev/disk/by-id/ata-VBOX_HARDDISK_VBcda8398f-f1f1deec --header-backup-file /mnt/flash/luksHeader.bin
После этого сделаем копию файла ключа в случае использования данного метода и сгенерируем новый ключ. Затем смотрим текущие кейслоты (места в заголовке шифрованного тома, где хранятся ключи, — их может быть до восьми) и запоминаем номер активного (Enabled). Как правило, это нулевой.
# cryptsetup luksDump /dev/disk/by-id/ata-VBOX_HARDDISK_VBcda8398f-f1f1deec
Наконец, добавляем новый ключ в систему:
# cryptsetup luksAddKey /dev/disk/by-id/ata-VBOX_HARDDISK_VBcda8398f-f1f1deec
Отключаем-подключаем том, дабы убедиться, что мы ничего не сломали, и удаляем старый ключ:
# cryptsetup luksKillSlot /dev/disk/by-id/ata-VBOX_HARDDISK_VBcda8398f-f1f1deec 0
Рассмотрим и процедуру восстановления томов LUKS. Самый простой вариант, разумеется, когда есть копия заголовка. В этом случае для восстановления требуется всего одна команда:
# cryptsetup luksHeaderRestore /dev/disk/by-id/ata-VBOX_HARDDISK_VBcda8398f-f1f1deec --header-backup-file /mnt/flash/luksHeader.bin
После этого подключаем том, используя старые пароли/ключи.
В случае же, если вдруг по каким-то невероятным причинам был поврежден заголовок тома LUKS, при этом резервных копий не имеется, но том еще отключить не успели, его все же можно восстановить. Для этого прежде всего необходимо извлечь мастер-ключ, который хранится в памяти:
# dmsetup table --target crypt --showkey /dev/mapper/cryptoluks
Самая длинная непрерывная строчка и будет мастер-ключом. Ее нужно скопировать в файл на нешифрованный том и после этого преобразовать в бинарную форму (перед этим следует убедиться, что в данном файле нет никаких символов конца строки):
# cat master-key.txt | xxd -r -p >master-key.bin
Длина итогового файла варьируется от параметров, заданных при создании тома LUKS. Чаще всего — 32 байта. После извлечения мастер-ключа нужно отключить LUKS-том и проинициализировать его заново с использованием данного мастер-ключа и теми же самыми параметрами, что использовались при первой инициализации, например, так:
# cryptsetup -h=sha256 -c=aes-cbc-essiv:sha256 -s=256 luksFormat /dev/disk/by-id/ata-VBOX_HARDDISK_VBcda8398f-f1f1deec --master-key-file=/mnt/flash/master-key.bin
EncFS
Посмотрим, как настроить EncFS для автоматического монтирования при входе в систему. Для начала поставим нужные пакеты:
# apt-get install encfs libpam-encfs
Затем нужно выбрать, будет ли происходить автомонтирование при входе или же чуть позже, с помощью gkeyring. Здесь будет описан первый способ из-за его универсальности. Настроим сначала ФС.
$ mkdir -p ~/.private ~/private
$ encfs ~/.private ~/private
При настройке в режиме эксперта будет задан ряд вопросов: тип шифра (доступны только AES и Blowfish), размер ключа, размер блока, как шифровать имена файлов — блочное шифрование (которое полностью скрывает имя файла, в том числе длину), потоковое (которое шифрует с максимально близкой длиной, что иногда удобно, если имена чересчур длинные и при использовании блочного шифра есть достаточно большая вероятность превысить максимально допустимую длину) или вовсе будет отсутствовать... В конце будет запрошен пароль, он должен совпадать с используемым для входа, в противном случае автомонтирование работать не будет.
Следом нужно отредактировать файл /etc/security/pam_encfs.conf:
# Закомментируем следующую строчку для отключения авторазмонтирования по истечении какого-то времени
# encfs_default --idle=1
# Раскомментируем другую строчку
* .private private -v allow_other
И файл /etc/fuse.conf:
# Раскомментируем строчку для разрешения монтирования обычным пользователям:
user_allow_other
И добавим пользователя в группу fuse:
$ sudo usermod -a -G fuse $USER
После выхода-входа каталог private можно будет использовать как хранилище для личных данных. Стоит, однако, отметить, что аудит выявил некоторые (достаточно серьезные) проблемы с безопасностью, из-за чего данную систему крайне не рекомендуется использовать для хранения действительно важных данных.
eCryptFS
Известно, что eCryptFS применяется в Ubuntu как средство по умолчанию для защиты домашних каталогов. Посмотрим, как оно работает, — создадим шифрованный каталог вручную. Установим пакеты:
$ sudo apt-get install ecryptfs-utils
Как и в случае с encfs, создадим два каталога:
$ mkdir -p ~/.secret ~/secret
И смонтируем ФС (при первом монтировании создаются все необходимые метаданные):
$ sudo mount -t ecryptfs /home/rom/.secret /home/rom/secret
Будет запрошена парольная фраза (всего один раз, повторный ввод не реализован, что выглядит не очень хорошим решением, учитывая, что она должна быть длинной), затем будет запрошен тип шифра (AES, Blowfish, 3DES, Twofish, CAST6 и CAST5), размер ключа, задан вопрос, разрешить или запретить нешифрованные файлы в каталоге с зашифрованными, шифровать ли имена файлов... и в финале спросит, действительно ли желаем подмонтировать и сохранить ли сигнатуру в определенный файл. Вопрос не настолько глупый, как может показаться сначала: в данном ПО при отсутствии сигнатуры не существует возможности отличить правильный пароль от неправильного.
Посмотрим, как зашифровать весь домашний каталог в случае, если он не зашифрован. Для начала нужно создать резервную копию всех важных данных. Затем зайти под иным пользователем, не тем, чьи данные будут зашифрованы, убедиться, что нет процессов данного пользователя, и набрать команду (вместо rom подставить имя нужного пользователя):
$ sudo ecryptfs-migrate-home -u rom
Во время первого запуска может понадобиться завершить несколько процессов. После шифрования необходимо немедленно зайти под пользователем, при этом будет предложено записать или распечатать парольную фразу, сгенерированную для шифрования и защищенную, в свою очередь, пользовательским паролем. Это необходимо для восстановления в случае нештатной ситуации.
Посмотрим, как его восстанавливать. Предположим, что парольная фраза не записана и восстановление идет с Live CD. Подразумевается, что ФС подмонтирована. Переходим в каталог home/.ecryptfs/rom/.ecryptfs и набираем команду:
ecryptfs-unwrap-passphrase ./wrapped-passphrase
Затем передаем полученную парольную фразу в ecryptfs-add-passphrase:
# printf "%s" "e496ea18906ccbba4fb283fd3ea25307" | ecryptfs-add-passphrase --fnek -
И, запомнив токены и создав каталог, подмонтировать данную зашифрованную ФС к нему:
# mkdir /home/rom
# mount -t ecryptfs -o key=passphrase:passphrase_passwd=e496ea18906ccbba4fb283fd3ea25307 ../.Private /home/rom
Будут запрошены некоторые дополнительные данные об опциях монтирования. Почти все нужно оставить стандартным, за исключением вопроса о шифровании имен файлов и сигнатуры ключа для их шифрования — вместо значения по умолчанию нужно подставить второй токен из запомненных. И можно восстанавливать файлы.
dm-verify
Модуль dm-verify предназначен для проверки целостности блочных устройств. Верификация ведется с помощью hash tree, где «листья» — хеш-суммы блоков, а «ветви» — хеш-суммы наборов «листьев». Таким образом, для верификации блочного устройства (будь то раздел или диск) достаточно проверить всего одну контрольную сумму.
Этот механизм (вкупе с цифровой подписью) применяется в некоторых Android-устройствах для защиты от модификации системных разделов, а также в Google Chromium OS.
Заключение
Linux содержит действительно немало средств для криптографической защиты информации. Из трех описанных средств как минимум одно присутствует во всех современных дистрибутивах Linux. Но что же выбрать?
dm-crypt/LUKS стоит применять в тех случаях, когда есть возможность быстро отключить зашифрованный том и когда резервные копии либо не нужны, либо засекречиваются иным путем. В этом случае данное решение более чем эффективно, особенно с учетом того, что шифровать можно каскадом произвольной вложенности и типа (например, AES-Twofish-AES), — настоящий рай для параноиков.
eCryptFS подходит в тех случаях, когда нужно шифрованные данные куда-то сохранять — к примеру, в облако. Она обеспечивает довольно надежное шифрование (хотя в 128-битном варианте, используемом по умолчанию, есть возможность снижения криптостойкости на два бита) и для конечного пользователя прозрачна.
EncFS же — старичок примерно десятилетней давности, базирующийся на еще более древних работах. К настоящему времени не рекомендован к использованию из-за потенциальных дыр в безопасности, но может применяться в качестве кросс-платформенного средства для защиты несенситивных данных в облаках.
При необходимости использования подобных средств всегда нужно помнить, что защита должна быть комплексной.