geli загрузка с шифрованого раздела с паролем

Ответить
admin
Администратор
Сообщения: 199
Зарегистрирован: 05 янв 2011, 04:19

geli загрузка с шифрованого раздела с паролем

Сообщение admin »

From: Mikhail E. Zakharov <zmey20000@yahoo.com.>
Newsgroups: email
Date: Mon, 5 Feb 2007 14:31:37 +0000 (UTC)
Subject: Шифрование корневого раздела диска во FreeBSD


Вместо введения

"Если у вас нет паранойи, это ещё не значит, что за вами не следят"


Народная мудрость

Когда разговор даже вскользь касается безопасности, люди моментально
делятся на два лагеря: первые очень серьезно относятся к проблеме,
вторые, напротив, легкомысленно и то и дело, в их речи проскакивает
насмешливое словечко "паранойя".

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

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

Ладно, попробуем определиться со всеми pro и contra в том, что хочется
получить в итоге. Шифрование файлов было отринуто сразу, ибо мыслить
надо широко. Во FreeBSD использовать какую-либо файловую систему кроме
UFS2 мы не будем, поскольку любим изящные решения, и хотим обойтись
именно тем, что входит в состав обычного инсталляционного CD.
Шифровать ключами отдельные партиции идея - заманчивая, но не
спортивная, ибо все очень детально объяснено в соответствующей главе
handbook, а какой же смысл настоящим скалолазам ходить проторенными
тропами? Кроме того, сгенерированные ключи придется хранить где-то
отдельно, например, на флэшке (или как говорят иностранцы USB-stick),
а если учитывать достаточно известную особенность этих устройств
неожиданно пропадать из поля зрения обладателя в самый неподходящий
момент, то придется еще и хранить дубликат носителя с ключами в
надежном месте. Ну, вы меня поняли.

Единственным выходом для настоящего мужчины придется признать
следующий вариант: прозрачное посекторное шифрование всего
FreeBSD-слайса только при помощи паролей. Хотя, отказавшись от ключей,
жизнь мы себе упростили, но конечно, несколько ослабили безопасность.
Далее, из двух механизмов шифрования партиций, предложенных в
учебнике, метод gbde (GEOM Based Disk Encryption) придется отбросить,
поскольку он не справится с корневым разделом диска. Остается
GEOM-класс geli, который появился во FreeBSD 6.0 и, что более важно,
умеет работать с зашифрованным корневым разделом. Однако не все так
безоблачно, ведь для того, чтобы смонтировать пресловутую
зашифрованную корневую партицию, необходимо чтобы ядро, к моменту
монтирования, было уже предварительно загружено. Но при этом само
ядро, по идее, находится на зашифрованном диске. Замкнутый круг, что
весьма обидно.

В случае с шифрованием по ключам или ключам и паролю, эту проблему
решали выносом ядра на внешний носитель. Т.е. попросту делали флэшку
загрузочной и клали с ключами рядом каталог /boot. Это нам не
подходит, ведь от использования внешнего носителя мы уже отказались и
чтобы выкрутиться из вышеозначенного замкнутого круга, мы для загрузки
ядра будем использовать отдельный некриптованный загрузочный слайс
FreeBSD. Делать большим этот слайс не имеет смысла, ведь там будет
лежать только /boot и 128Mб будет больше чем достаточно. Как я выяснил
потом, размер директории /boot включающей в себя не сжатое ядро и все
модули, не превысил 30Мб. Соответственно, если мы стремимся уменьшить
эту область, можно воспользоваться опытом построения загрузочных
дискет проекта PicoBSD. А мы меж тем


Поехали.

Итак, загружаем систему с установочного CD FreeBSD 6.х. В моем случае
это оказался свежий дистрибутив FreeBSD 6.2-RELEASE. Дождавшись,
появления sysinstall быстро двигаемся по меню:

Country Selection (я оставил default)->Fixit->CDROM/DVD


пока не появится приятное пожелание Good Luck! и долгожданное
приглашение командной строки:

Fixit#


Попав наконец в командную строчку, начнем наше благородное дело. Для
начала, как предлагает учебник, можно полностью уничтожить всю
информацию на диске:

Fixit# dd if=/dev/random of=/dev/ad0 bs=1m


Или, как это рекомендует Marc Schiesser в документе
Complete Hard Disk Encryption Using FreeBSD's GEOM Framework,
в идеальном варианте данные на диски должны быть перезаписаны несколько
раз. Поэтому, кому не жалко времени, могут повторить команду dd N-раз.

Далее, нарежем диск на два слайса и сделаем первый (ad0s1) активным.
Кое-кто может подумать, что работа с fdisk вместе со всеми этими
расчетами размеров слайсов в цилиндрах занятие уж слишком неприятное,
что ж они смело могут вернуться в sysinstall и выполнить аналогичную
операцию там. Но мы-то ведь, настоящие мужчины, и трудности нас делают
только сильнее. Кроме того, в дальнейшем, когда мы будем создавать
зашифрованную область, sysinstall нам поможет мало.

Итак, на стенде имеется скромного размера ATA-диск со следующей
геометрией:

22192cyls/15 heads/63 sectors = 20971440 sectors (10239Mb)


Тогда операция разбивки этого диска на партиции может выглядеть так:

Fixit# dd if=/dev/zero of=/dev/ad0 bs=512 count=32
Fixit# cat /tmp/fdisk.ad0
p 1 165 63 261702 # слайс ad0s1: ~128М для /boot и kernel
p 2 165 262269 20709171 # слайс ad0s2: ~10Gb будет зашифрован
a 1
Fixit# fdisk -f /tmp/fdisk.ad0 -iv /dev/ad0 # запишем таблицу разделов на диск


Строго говоря команда dd в первой строчке блока команд не является
обязательной, но man bsdlabel(8) рекомендует ее использовать,
утверждая, что иначе не все BIOS'ы смогут потом правильно распознать
диск. Далее, команда cat /tmp/fdisk.ad0 означает, что файл с таким
названием необходимо подготовить, например, при помощи редактора vi.

На этом трепетном моменте мы пока оставим без внимания наш скромный
слайс ad0s1 с его единственной значащей партицией ad0s1a и обратим
свой взор на слайс ad0s2, пространство которого, по нашим коварным
планам будет превращено в зашифрованное хранилище данных.

Поскольку любое чудо, как повторяет один мой друг, требует тщательной
подготовки, нам тоже придется сделать несколько предварительных
действий. Для начала стартуем модуль geli:

Fixit# ln -s /dist/boot/kernel /boot/kernel
Fixit# ln -s /dist/lib /lib
Fixit# kldload geom_eli.ko


Теперь можно инициализировать geli на слайсе ad0s2:

Fixit# geli init -b -s 4096 /dev/ad0s2


После нажатия Enter, вам предложат ввести и подтвердить парольную
фразу.

В этой команде ключ -b указывает на то, что парольную фразу необходимо
спросить перед тем, как корневая файловая система будет смонтирована.
Размер сектора указывается ключом -s, чем больше это значение, тем
быстрее работает механизм шифрования. Смотрите man geli(8) на предмет
ключа -e который задает алгоритм шифрования, по умолчанию,
используется AES.

Теперь, можно подключить нашу зашифрованную партицию:

Fixit# geli attach /dev/ad0s2


После чего вам будет предложено ввести пароль, который вы указали при
выполнении geli init, и если вы справились со своей задачей, в
каталоге /dev появится новое устройство /dev/ad0s2.eli, которое и
является нашим зашифрованным слайсом.

С этим устройством, можно не стесняясь обращаться как с обычным
слайсом, за исключением того, что при инициализации geli, мы
искусственно увеличили размер сектора, который теперь будет равняться
4096 байт, а не 512 как обычно. Поэтому, держа в голове
соответствующую поправку, рассчитываем размеры и размечаем на
ad0s2.eli партиции:

Fixit# bsdlabel -w ad0s2.eli
Fixit# cat /tmp/bsdlabel.ad0s2.eli
# /dev/ad0s2.eli:
8 partitions:
# size offset fstype [fsize bsize bps/cpg]
a: 131072 0 4.2BSD 0 0 0 # / ~512Mb
b: 131072 131072 swap # swap ~512Mb
c: 2588646 0 unused 0 0 # total size
d: 131072 262144 4.2BSD 0 0 0 # /tmp 512Mb
e: 262144 393216 4.2BSD 0 0 0 # /var 1G
f: 1933286 655360 4.2BSD 0 0 0 # /usr все остальное
Fixit# bsdlabel -R ad0s2.elic /tmp/bsdlabel.ad0s2.eli


Наконец, создаем файловые системы. Ключом -U активируем режим
soft-updates везде, кроме корневой файловой системы:

Fixit# newfs /dev/ad0s2.elia
Fixit# newfs -U /dev/ad0s2.elid
Fixit# newfs -U /dev/ad0s2.elie
Fixit# newfs -U /dev/ad0s2.elif


На /dev/ad2s2.elib файловую систему создавать не будем, поскольку на
этой партиции будет располагаться swap.

Теперь, созданные в зашифрованной области файловые системы можно
смонтировать и инсталлировать на них дистрибутив FreeBSD. Сначала
смонтируем корень:

Fixit# mkdir /crypted && mount /dev/ad0s2.elia /crypted


Затем воссоздадим дерево каталогов, для монтируемых партиций:

Fixit# mkdir /crypted/var /crypted/tmp /crypted/usr


И смонтируем в соответствующие точки оставшиеся партиции зашифрованной
области:

Fixit# mount /dev/ad0s2.elid /crypted/tmp
Fixit# mount /dev/ad0s2.elie /crypted/var
Fixit# mount /dev/ad0s2.elif /crypted/usr


Поскольук мы загрузились в режиме fixit дистрибутив FreeBSD уже
доступен в /dist/<VERSION>/base. В нашем случае <VERSION> принимает
значение 6.2-RELESE.

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

Fixit# export DESTDIR=/crypted
Fixit# cd /dist/6.2-RELEASE/base
Fixit# ./install.sh


Запустив скрипт, отвечаем, что бесспорно уверены в своих действиях и
ждем, пока операция успешно закончится, а файловые системы в
зашифрованной области диска окажутся заполненными данными из пакета,
который в sysinstall носит название BASE:

Теперь, когда FreeBSD в минимальной своей конфигурации
проинсталлирована, остается лишь создать etc/fstab:

Fixit# cat /crypted/etc/fstab
/dev/ad0s2.elia / ufs rw 1 1
/dev/ad0s2.elib none swap sw 0 0
/dev/ad0s2.elid /tmp ufs rw 2 2
/dev/ad0s2.elie /var ufs rw 2 2
/dev/ad0s2.elif /usr ufs rw 2 2


На этом упражнения с шифрованным разделом подходят к концу и можно
подготовить


Загрузочный раздел

Разобравшись с ad0s2, займемся незашифрованной областью - ad0s1,
которую мы предназначили исключительно для загрузки ядра FreeBSD и
ограничили размером ~128Mb. Поставим на этот слайс BSD-метку и запишем
boot-код:

Fixit# bsdlabel -w -B ad0s1


После этого растягиваем партицию ad0s1a на все доступное пространство
слайса:

Fixit# cat /tmp/bsdlabel.ad0s1
# /dev/ad0s1: 8 partitions:
# size offset fstype [fsize bsize bps/cpg]
a: 261702 0 unused 0 0
c: 261702 0 unused 0 0 # "raw" part, don't edit
Fixit# bsdlabel -R ad0s1c /tmp/bsdlabel.ad0s1


Теперь смело создаем единственную файловую систему на партиции ad0s1a:

Fixit# newfs /dev/ad0s1a


И сразу монтируем ее:

Fixit# mkdir /freeroot && mount /dev/ad0s1a /freeroot


Затем копируем /boot вместе с ядром, модулями и всем остальным:

Fixit# mkdir /freeroot/boot && cp -R /dist/boot/* /freeroot/boot


Кроме того, на загрузочном разделе нам понадобится fstab, перенесем
его из шифрованной области:

Fixit# mkdir /freeroot/etc && cp /crypted/etc/fstab /freeroot/etc/fstab


Поскольку выше по тексту мы стащили каталог boot и loader.conf с
установочного CD, то в loader.conf уже присутствуют ложные в нашем
случае параметры для загрузки корня с mfs, поэтому заключительным
аккордом все что там есть, недрогнувшей рукой следует вытереть:

Fixit# rm /freeroot/boot/loader.conf


Кроме того, по логике вещей, нам остается сделать только последний
штрих. А именно, указать системе на необходимость загрузки модуля ядра
geli при старте машины. Но как это выяснится чуть дальше, мы
скомпилируем ядро с необходимыми опциями, и загрузка этого модуля не
понадобится:

Fixit# echo geom_eli_load=\"YES\" > /newroot/boot/loader.conf


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


Разочарование

Дело в том, что если вы не являетесь счастливым обладателем
USB-клавиатуры то, из-за одного неприятного бага, то при загрузке
ядра с поддержкой geli, вы просто не сможете ввести пасс-фразу, когда
на этапе загрузки ядра вам это будет предложено сделать. На моем
стенде, данная проблема к счастью не проявилась, и я связываю это с
тем, что на стенде используется старенькая AT, а не PS/2-клавиатура.

Впрочем, на другой системе с клавиатурой PS/2, проблема
присутствовала, так что, можно констатировать что во FreeBSD
6.2-RELEASE, баг был все еще не устранен, и поэтому, создавая
работоспособный вариант придется прибегнуть к workaround который
заключается в удалении из ядра устройства kbdmux. Правда для этого
ядро придется пересобрать, что конечно не страшно, ведь даже учебник в
одной из своих глав, настоятельно рекомендует это сделать. И раз эту
процедуру каждый честный обладатель FreeBSD будет делать в любом
случае, то этапом раньше или этапом позже, не имеет большого значения.

Поэтому распаковываем исходники ядра хорошо знакомым скриптом
install.sh:

Fixit# cd /dist/6.2-RELEASE/src
Fixit# ./install.sh sys


После этого, исходные коды ядра благополучно распакуются в каталог
/crypted/usr/src. Затем, подготавливаем ядро почти так, как это
описывается в handbook:

Fixit# cd /crypted/usr/src/sys/i386/conf
Fixit# cp GENERIC CR


Далее согласно логике и здравому смыслу редактируем конфигурационный
файл ядра CR, удаляя и добавляя поддержку устройств и изменяя
необходимые опции и параметры ядра. Почти все эти параметры
индивидуальны для конкретной ситуации, но нас интересует как минимум
поддержка geli, поэтому добавляем в ядро следующие строки:

options GEOM_ELI
device crypto


Разумеется, не забываем изменить значение IDENT на CR:

ident CR


Кроме того, из-за того-самого неприятного бага, удалим устройство
kbdmux. Поэтому находим строчку:

device kbdmux


и комментируем или же удаляем ее.

Далее, прежде чем совершить таинство сборки ядра, нам потребуется
создать несколько линков, чтобы файлы оказывались в нужных местах,
когда это потребуется:

Fixit# ln -s /dist/usr/libexec /usr/libexec
Fixit# ln -s /dist/usr/lib /usr/lib
Fixit# ln -s /dist/usr/share/mk /usr/share/mk
Fixit# ln -s /dist/usr/include /usr/include


Кроме того, подключим swap, чтобы избежать нехватки виртуальной памяти
во время компиляции:

Fixit# swapon /dev/ad0s2.elib


И наконец, соберем ядро добрым старым способом:

Fixit# config CR
Fixit# cd ../compile/CR
Fixit# make depend
Fixit# make all


Ведь это самая первая компиляция ядра CR, поэтому без всякого зазрения
совести перед make depend пропускаем команду make cleandepend, которую
утилита config нам так любезно напомнила выполнить.

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

Fixit# export DESTDIR=/freeroot


И еще файл /etc/group на нашем LIVE-CD очень сильно укорочен, поэтому
добавим в него еще одну строчку:

echo "wheel:*:0:root" >> /etc/group


Теперь можно инсталлировать ядро:

Fixit# make install


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

Не буду рассказывать красочную историю о том, как я снова загружался с
инсталляционного CD-ROMа и монтировал файловые системы вручную.
Единственное, что я выяснил, так это то, что моя машина
реагировала-таки на ввод с клавиатуры. Просто делала она это крайне
медленно.

Итак, чтобы, наконец, ввести парольную фразу, я добавил в
/boot/loader.conf на незашифрованном разделе строчку, которая включает
эхо при вводе пасс-фразы:

echo "kern.geom.eli.visible_passphrase=1" > /freeroot/boot/loader.conf


Это, конечно, приведет к тому, что пароль будет явно виден как на
этапе загрузки, так и останется в /var/log/messages:



На этом действительно все, надеюсь только, что баг будет вскоре
устранен, или же с клавиатурой вам повезет гораздо больше чем мне. В
любом случае, желаю вам как можно быстрее насладиться работой FreeBSD
в полностью зашифрованном разделе, избежав при этом выполнение
небезопасной и унизительной процедуры с включением эха.
Ответить