Wersja: 0.0.1
Ostatni update: 29.10.2007 05:29
Trochę z nudów, trochę z chęci podzielenia się doświadczeniem [ale głównie z nudów], postanowiłem spłodzić swoje drugie howto. Tym razem o mojej, póki co, największej zabawie z przeróbkami systemu – szyfrowaniu całości. Na gentoo-wiki można znaleźć howto jak to zrobić za pomocą DM-Crypt'a, moje po części będzie podobne. Co do różnic - po pierwsze ja stwierdziłem, że skorzystam z TrueCrypt'a, do którego już przez dłuższy okres używania [odległe lata M$okien] nabrałem zaufania. Po drugie chciałem mieć podwójny system dostępu, za pomocą pendrive'a, który w całości tego howto pełni rolę punktu wyjścia – zawiera niezaszyfrowane dane, klucze, a jego strata kładzie wszystko, oraz za pomocą haseł. I po trzecie, powód już nie dla mnie - osoby, które mają M$Win na dysku, mogą zaszyfrować partycję fat|ntfs z jakimiś danymi, będą one dalej dostępne spod okien.
2. Wymagania
Potrzebne są:
- wiedza, nie będę tutaj opisywał wszystkiego od podstaw, pewna znajomość systemu, skryptów bash'owych, kompilacji, busybox'a, etc. jest wymagana,
- pendrive, karta pamięci, lub cokolwiek "zewnętrznego" co wędruje zawsze z nami i nigdy nie jest zostawione razem z komputerem [w moim przypadku notebookiem] bez naszej uwagi,
- czysta partycja [lub kilka], która zostanie zakodowana TrueCrypt'em i gdzie zostanie przeniesiony cały system
- niezaszyfrowany /boot, gdzie wyląduje jajko, grub i własny initramfs - niestety na to łatwego obejścia chyba nie ma, sam bootloader nie odszyfruje partycji, musi to zrobić jajko, które skądś trzeba odczytać, na dobrą sprawę można je trzymać również na pendrive, ale nie ma też co kombinować, tego nie ma chyba potrzeby ukrywania
- truecrypt [ # emerge truecrypt ],
- device mapper i niektóre algorytmy szyfrujące w jajku [ale o to powinien zakrzyczeć sam truecrypt przy emerge], dobrze jest to wszystko mieć wkompilowane statycznie, będzie mniej problemów przy tworzeniu initramfs.
3. Tworzenie partycji i kluczy
Obsługa truecrypt'a jest prosta jak konstrukcja cepa. Tworzenie zaszyfrowane partycji sprowadza się do odpalenia:
Code: Select all
# truecrypt -c /dev/sda2Code: Select all
# truecrypt --keyfile-create ~/true_keyTeraz trochę wytłumaczenia "o co biega". W pierwszym kilobajcie danego urządzenia TC za pomocą naszego hasła|klucza szyfruje klucz właściwy, którym kodowane są wszystkie dane na dysku. Taka kombinacja pozwala nam dowolnie modyfikować nasze hasła|klucze, wystarczy, że TC odkoduje klucz główny i zapisze go zakodowanego na nowo w początkowych obszarach.
A po co to wszystko? Musimy mieć dwa takie nagłówki - pierwszy, który będzie na dysku przez większość czasu, z kluczem zakodowanym za pomocą podanego wcześniej hasła, i drugi za pomocą true_key. Mam nadzieję, że nie namieszałem, jakby co to krzyczeć
Do rzeczy. Najpierw robimy zrzut do pliku pierwszego nagłówka, gdzie klucz główny jest zaszyfrowany za pomocą hasła:
Code: Select all
# truecrypt --type normal --backup-headers ~/header_pass /dev/sda2Code: Select all
# truecrypt -C /dev/sda2Code: Select all
# truecrypt --type normal --backup-headers ~/header_key /dev/sda2Code: Select all
# truecrypt --type normal --restore-header ~/header_pass /dev/sda24. Przenoszenie danych
Ten akapit pominę, ta umiejętność jest wymagana, wraz ze zdrowym rozsądkiem, od użytkownika
5. fstab
Niewielka zmiana tutaj, zamiast /dev/sdaX wpisujemy /dev/mapper/truecryptX [licząc od zera, w kolejności odkodowywania partycji, czyli root będzie to truecrypt0].
6. uvesafb + splash
Żeby całość wyglądała ładnie, używam uvesafb [x86_64, nie mogłem poprzednika - vesafb_tng] oraz fbcondecor, który pozwala już pod koniec ładowania jajka ustawić tło. Działający uvesafb, lub inny sterownik fb, oraz skompilowanie splashutils i znalezienie wymarzonego theme wyrzucam poza ramy tego tekstu.
7. initramfs
Najwięcej zabawy i przekleństw czeka w tym punkcie. Nie będę tłumaczył tutaj co to jest initramfs, praktyczną wiedzę o nim dorwałem na gentoo-wiki, więć tam również odsyłam. Chciałem osiągnąć pełne zintegrowanie szyfrowania z init'em. Opiszę od końca, jak całość wygląda: komputer się włącza, pokazuje grub, uruchamia jajko [tryb quiet, nic nie widać], które b. szybko [~2 sek.] zmienia rozdzielczość z użyciem uvesafb oraz ustawia tło [fbcondecor]. Po chwili pokazuje się zmodyfikowane przeze mnie przywitanie
Code: Select all
Gentoo/Linux; Preloader by manwe; http://www.gentoo.org/
Copyright 1999-2007 Gentoo Foundation; Distributed under the GPLv2Do rzeczy. Co potrzebujemy w initramfs:
- busybox - na czymś to musi działać
- truecrypt - chodzi o binarkę
- dmsetup, losetup - wymagane przez truecrypt'a
- setfont - o tym później
- kilka urządzeń w /dev
- moduł truecrypt.ko i modules.dep
- v86d [jeżeli używasz uvesafb] i fbcondecor_helper [ze splashutils]
- splash theme
- czcionkę, która jest w systemie [u mnie: lat2-14.psfu.gz]
Wszystkie binarki muszą być statyczne [gdyby zacząć dodawać wszystkie lib'y - archiwum rozrosło by się za bardzo], niektóre jak busybox, czy fbcondecor_helper już powinny być, o resztę musisz zadbać sam(a). Pełna struktura folderów i plików wygląda tak:
Code: Select all
./bin/
./bin/sh -> busybox - symlink
./bin/mount -> busybox - symlink
./bin/init-early.sh - skrypt, opisze później
./bin/dmsetup
./bin/setfont
./bin/losetup
./bin/truecrypt
./bin/pendrive - skrypt
./bin/busybox
./dev/
./dev/fb0 - to jak i pozostałe urządzenia blokowe, do zrobienia za pomocą mknod
./dev/mem
./dev/sr0
./dev/tty
./dev/null
./dev/ram0
./dev/tty1
./dev/zero
./dev/console
./dev/mapper/
./etc/
./etc/mtab
./etc/splash/
./etc/splash/default -> gentoo - symlink
./etc/splash/gentoo/
./etc/splash/gentoo/Vera.ttf
./etc/splash/gentoo/images/
./etc/splash/gentoo/images/verbose-1024x768.png
./etc/splash/gentoo/1024x768.cfg
./lib/
./lib/rcscripts/
./lib/rcscripts/console/
./lib/rcscripts/console/font
./lib/rcscripts/console/lat2-14.psfu.gz
./lib/modules/
./lib/modules/name/
./lib/modules/name/block/
./lib/modules/name/block/truecrypt.ko
./lib/modules/name/modules.dep
./lib/splash/
./lib/splash/sys/
./lib/splash/proc/
./proc/
./proc/self/
./proc/self/exe -> ../../bin/busybox - symlink
./sbin/
./sbin/v86d
./sbin/fbcondecor_helper
./init - skrypt
/etc/mtab:
Code: Select all
proc /proc proc 0 0Code: Select all
lat2-14.psfu.gz/bin/init-early.sh - jest to kopia z init'a serwowanego przez Gentoo, ustawia czcionkę konsoli. Odpalamy go zanim cokolwiek się pojawi na ekranie, dzięki temu unikniemy brzydkiego wyczyszczenia konsoli w trakcie ładowania stage boot:
Code: Select all
#!/bin/sh
# Try and set a font and as early as we can
termencoding="(K"
[ -e "${RC_LIBDIR}"/console/unicode ] && termencoding="%G"
printf "\033%s" "${termencoding}"
if [ -r "${RC_LIBDIR}"/console/font -a -x /bin/setfont ] ; then
font="$(cat "${RC_LIBDIR}"/console/font)"
CONSOLE="${CONSOLE:-/dev/console}"
[ -c "${CONSOLE}" ] && cons="-C ${CONSOLE}"
setfont ${cons} "${RC_LIBDIR}"/console/"${font}"
fi
/bin/pendrive:
Code: Select all
#!/bin/sh
X=`dmesg | grep -C 1 $1 | tail -n 1 | awk -F\[ '{ print $2 }' | awk -F\] '{ print $1 }'`
[ -z "$X" ] && exit 1
mount /dev/${X}${2} /pen 2> /dev/null
[ $? -ne 0 ] && exit 1
for A in /pen /pen/.keys /pen/.keys/true_key /pen/.keys/h_key /pen/.keys/h_pass; do
if [ ! -f $A -a ! -d $A ]; then
echo '^[[01;31m * ^[[0m'"Pen found, but missing ${A}!"
umount /pen
exit 1
fi
done
echo -n '^[[01;32m * ^[[0mPen found. Loading key header. '
X=`truecrypt --type normal --restore-header /pen/.keys/h_key /dev/sda2 2>&1`
[ $? -ne 0 ] && exit 1
echo "$X"
echo -n '^[[01;32m * ^[[0mMounting partition using key. '
X=`truecrypt -p '' -k /pen/.keys/true_key $3 2>&1`
[ $? -ne 0 ] && exit 1
echo "$X"
echo -n '^[[01;32m * ^[[0mRestoring password header. '
X=`truecrypt --type normal --restore-header /pen/.keys/h_pass /dev/sda2 2>&1`
[ $? -ne 0 ] && exit 1
echo "$X"
umount /pen
exit 0
No i ostatni, najdłuższy skrypt /init. On robi prawie wszystko, jest wywoływany przez jajko, musi pociągnąć całe przygotowanie i na koniec przekazać robotę do właściwego /sbin/init z Gentoo:
Code: Select all
#!/bin/sh
#basic
/bin/busybox mount -t proc proc /proc 2> /dev/null
mkdir /new
mkdir /pen
mkdir /root
#get params
CMD=`cat /proc/cmdline | sed 's/silent/verbose/g'`
ROOT=`cat /proc/cmdline | tr ' ' '\n' | grep -E '^root=' | awk -F= '{ print $2 }'`
PEN=`cat /proc/cmdline | tr ' ' '\n' | grep -E '^pen_name=' | awk -F= '{ print $2 }'`
PART=`cat /proc/cmdline | tr ' ' '\n' | grep -E '^pen_part=' | awk -F= '{ print $2 }'`
[ -z "$ROOT" ] && echo '^[[01;31m ROOT is empty. I have to commit suicide.' && exit
#mknod
cd /dev
for N in 0 16 32 48; do
case $N in
0) X='a' ;;
16) X='b' ;;
32) X='c' ;;
48) X='d' ;;
esac
mknod sd${X} b 8 ${N} &> /dev/null
for M in 1 2 3 4 5 6 7 8 ; do
let Y=${N}+${M}
mknod sd${X}${M} b 8 ${Y} &> /dev/null
done
done
cd /
#modules
cd /lib/modules
mv name `uname -r`
cd /
modprobe truecrypt
#setfont
export RC_LIBDIR="/lib/rcscripts/"
/bin/init-early.sh
#shell hack
if [ "$ROOT" = "shell" ]; then
exec /bin/sh
fi
#banner
clear
echo; echo '^[[01;32m Gentoo/Linux; ^[[01;33mPreloader by manwe; ^[[01;34mhttp://www.gentoo.org/';
echo '^[[0m Copyright 1999-2007 Gentoo Foundation; Distributed under the GPLv2'; echo;
#try mount
mount $ROOT /new 2> /dev/null
#wait for usb
if [ ! -f /new/sbin/init ]; then
echo -n '^[[01;32m * ^[[0mWaiting for usb devices'
for X in 1 2 3 4 5 6; do
echo -n '.'
sleep 1
done
echo
#main loop
/bin/pendrive $PEN $PART $ROOT
if [ $? -ne 0 ]; then
while [ -z "$END" ]; do
echo '^[[01;32m * ^[[0mInsert pendrive or enter the password...'
S=`stty -g`; stty -echo
read P
stty $S
if [ "${P}" ]; then
echo -n '^[[01;32m * ^[[0mMounting partition using given password. '
T=`truecrypt -p "$P" -k '' $ROOT 2>&1`
[ $? -eq 0 ] && END="end"
echo "$T"
else
/bin/pendrive $PEN $PART $ROOT
[ $? -eq 0 ] && END="end"
fi
done
fi
fi
#end
#umount /proc 2> /dev/null
if [ -b /dev/mapper/truecrypt0 ]; then
mount /dev/mapper/truecrypt0 /new
exec /bin/busybox switch_root /new /sbin/init $CMD
else
if [ -f /new/sbin/init ]; then
exec /bin/busybox switch_root /new /sbin/init $CMD
else
echo '^[[01;31m * ^[[0m'"No /dev/mapper/truecrypt0 or /sbin/init! What the fuck? Well... I'll die now ;-)"
fi
fi
#basic - brak komentarza
#ger params - tutaj zbierane są informacje przekazane jako parametry dla jajka, jak root=, pen_name=, czy pen_part
#mknod - tworzenie nodów które pokrywają większość zapotrzebowania na /dev/sdX [nie umieszczałem ich statycznie w /dev initramfs, zaśmiecały czytelność]
#modules - zmiana nazwy folder /lib/modules/name na nazwę jaką ma jajko, to również jak poprzedni punkt powstało z wygodny tworzenia initramfs, nie muszę zmieniać z nowym jajkiem nazwy folderu
#setfont - zmiana czcionki zanim cokolwiek wypiszemy na ekran [tak, jeszcze nic się nie pojawiło!]
#shell hack - taki mały myk który sobie zostawiłem, jeżeli w parametrach gruba jako root= zostanie wpisane shell, skrypt poprzestanie w tym miejscu i uruchomi sh, świetne miejsce na np. naprawę uszkodzonego systemu plików, żadna partycja dyskowa nie jest w tym momencie używana
#banner - wypisujemy zmodyfikowany banner
#try mount - całość starałem się napisać uniwersalnie, jeżeli jako root zostanie podana "zwykła" niezaszyfrowana partycja, mount tutaj się uda, warunek [ ! -f /new/sbin/init ] nawali i cała zabawa z TC zostanie pominięta
#wait for usb - skrypt czeka 6 sekund na pojawienie się pendrive [tyle zajmuje w moim jajku wykrycie] i jeżeli go znajdzie od razu przejdzie do /bin/pendrive, dzięki czemu jeżeli pen został wpakowany w port już wcześniej całość zotanie załatwiona bez interakcji z użyszkodnikiem, system wstanie zwyczajnie jak każdy inny [tylko kilka sekund dłużej mu to zajmie]
#main loop - nie wykryto pendrive, odczytanie hasła od użytkownika i próba odkodowania z jego użyciem [truecrypt -p "$P"] lub, przy klepnięciu enter, ponowne sprawdzenie /bin/pendrive - i tak w kółko, aż się uda
#end - jeżeli jest urządzenie /dev/mapper/truecrypt0 [odszyfrowane /dev/sda2], mount - switch_root, czyli przekazanie pałeczki do /sbin/init z Gentoo, w przeciwnym wypadku sprawdzenie czy jest już może /new/sbin/init [sytuacja montowania partycji bez TC] i znów switch_root, albo ... die - skrypt nie może znaleźć init'a
No to ufff
Code: Select all
cd ~/initramfs/ [czy tam inny folder gdzie pracowałeś]
find . -print | cpio -o -H newc | gzip -9 > ../initramfs
cp ../initramfs /boot/
8. Grub
Po ciężkim pkt. 7, chwila odpoczynku - niewielkie zmiany w grub.conf. Trzeba dodać parametry identyfikujące pendrive: pen_name=IntelligentStick pen_part=3 oraz polecenie initrd.
Code: Select all
title Gentoo Linux kernel-2.6.23-kamikaze4-ev18
kernel (hd0,0)/kernel-2.6.23-kamikaze4-ev18 splash=verbose,theme:gentoo quiet video=uvesafb:1024x768-24,mtrr:3,ypan pen_name=IntelligentStick pen_part=3 root=/dev/sda2
initrd (hd0,0)/initramfs-2.6.23-kamikaze4-ev18
9. Dopieszczanie
To by było w zasadzie wszystko. Partycje zaszyfrowane, initramfs działa, system wstaje, jest jeszcze tylko kilka drobnych poprawek:
1. Ponieważ initramfs+pendrive zaopiekowały się tylko /, trzeba podmontować pozostałe partycje [o ile są]. U mnie odstawiają to dwa takie bloki kodu [w /etc/conf.d/local.start]:
Code: Select all
if [ -f /mnt/flash/pqi3/.keys/h_key_home -a -f /mnt/flash/pqi3/.keys/true_key_home -a -f /mnt/flash/pqi3/.keys/h_pass_home ]; then
truecrypt --type normal --restore-header /mnt/flash/pqi3/.keys/h_key_home /dev/sda3 &> /dev/null
truecrypt -p '' -k /mnt/flash/pqi3/.keys/true_key_home /dev/sda3 /home
truecrypt --type normal --restore-header /mnt/flash/pqi3/.keys/h_pass_home /dev/sda3 &> /dev/null
fi
2. Jajko nie słucha parametru quiet. A dokładniej obsługa scsi. Pomimo próby wyciszenia go tak, aby pierwszą linijką, która pokazuje się już na kolorowym tle, był baner Gentoo - dostawałem 3 linijki informacji "Assuming drive cache: write through". Jedyny sposób to po prosty je wykomentować w drivers/scsi/sd.c i przekompilować jajco.
3. Banner gentoo i "INIT 2.xx" - oryginalny banner Gentoo i informacja o wersji init'a pojawią się w momencie przekazania sterownia do /sbin/init przez initramfs. Tutaj również trzeba komentować, ja robię to patch'ami dodawanymi do ebuild'ów:
Code: Select all
$ cat init_silent.patch
--- src/init.old.c 2004-07-30 14:16:20.000000000 +0200
+++ src/init.c 2007-08-11 16:21:10.000000000 +0200
@@ -762,12 +762,12 @@
/*
* And log to the console.
- */
+
if (loglevel & L_CO) {
print("\rINIT: ");
print(buf);
print("\r\n");
- }
+ }*/
}
$ cat baselayout_silent.patch
--- src/rc.old.c 2007-10-12 16:59:31.693372287 +0200
+++ src/rc.c 2007-10-12 16:59:55.698710122 +0200
@@ -932,12 +932,12 @@
uname (&uts);
- printf ("\n");
+ /*printf ("\n");
printf (" %sGentoo/%s; %shttp://www.gentoo.org/%s"
"\n Copyright 1999-2007 Gentoo Foundation; "
"Distributed under the GPLv2\n\n",
ecolor (ECOLOR_GOOD), uts.sysname, ecolor (ECOLOR_BRACKET),
- ecolor (ECOLOR_NORMAL));
+ ecolor (ECOLOR_NORMAL));*/
if (rc_env_bool ("RC_INTERACTIVE"))
printf ("Press %sI%s to enter interactive boot mode\n\n",
To w zasadzie wszystko. W ten sposób otrzymujemy ładny system, ze zintegrowaną procedurą ładowania, obsługą zarówno kluczy @pendrive, jak i haseł. TC + Blowfish zapewniają szybkie działanie [pojedyńcze % zużycia CPU u mnie, nie wpłynęły w żaden sposób na wygodę pracy], a w razie skradzenia laptopa, lub zwinięcia go przez CBA, możemy spać spokojnie
Pewnie nikt nie porwie się na odstawianie całości, którą ja z ciekawości popełniłem, ale może nauczy się czegoś nowego, jak np. obsługa initramfs i co można zrobić z systemem, jeszcze zanim ten rozpocznie procedurę ładowania. Podziękowania składam wolnemu czasowi, dzięki któremu miałem okazję to wszystko zrobić




