Приведенный ниже материал является адаптацией и дополнением метода удаленного разблокирования томов, предложенного «Michael Scherer» в bagzilla redhat, применительно к CentOS 6 x64. Суть метода заключается в модификации initramfs.
Установка дополнительных пакетов
В initramfs мы добавим ssh-сервер dropbear, его нет в стандартных репозиториях, по этому нужно подключить внешний — epel:
rpm -Uhv http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-7.noarch.rpm
yum -y install dropbear
Модификация initramfs
В CentOS 6 для генерации initramfs используется довольно удобная система- dracut, дополнительный модуль для которой мы и будем создавать. Он представляет из себя папку в /usr/share/dracut/modules.d со скриптами установки и необходимыми файлами.
cd /usr/share/dracut/modules.d
mkdir 40unlock
cd 40unlock
Основной скрипт установки модуля:
cat > install << 'EOF'
#!/bin/bash
cat /etc/shadow|grep root > ${moddir}/shadow
dracut_install /lib64/libnss_compat.so.2
dracut_install /lib64/libnss_files.so.2
dracut_install /lib64/libnss_dns.so.2
inst_dir "/etc/dropbear"
inst "${moddir}/dropbear_rsa_host_key" "/etc/dropbear/dropbear_rsa_host_key"
inst_dir "/home"
inst_dir "/home/root"
inst_dir "/home/root/.ssh"
inst "${moddir}/.profile" "/home/root"
[ -s "${moddir}/authorized_keys" ] && inst "${moddir}/authorized_keys" "/home/root/.ssh/authorized_keys"
inst "/etc/localtime"
inst "${moddir}/nsswitch.conf" "/etc/nsswitch.conf"
inst "/etc/resolv.conf"
inst "/etc/host.conf"
inst "/etc/hosts"
inst "${moddir}/shadow" "/etc/shadow"
inst "${moddir}/passwd" "/etc/passwd"
inst "${moddir}/shells" "/etc/shells"
inst "${moddir}/unlock" "/bin/unlock"
inst_hook pre-trigger 01 "$moddir/remote-ssh.sh"
inst_hook pre-pivot 01 "$moddir/clean.sh"
dracut_install sed awk dropbear ifconfig route blkid cut killall true mkdir
dracut_install -o ps find grep less cat tac head tail false rmdir rm touch vi ping ssh scp lsmod
EOF
Он берет из shadow зашифрованный пароль root, для возможности удаленного входа по паролю, если вам нужна авторизация по ключу, то положите в эту же папку файл authorized_keys c публичным ключём внутри и правами доступа 600. Также происходит установка всех необходимых конфигурационных файлов, команд и динамических библиотек. Файлы hosts, resolv.conf и host.conf берутся системные. Ставятся 2 хука: первый(remote-ssh.sh) запускает dropbear еще до запроса пароля и второй(clean.sh) убивает процесс dropbear перед сменой корневой фс. В «dracut_install -o» указаны опциональные команды, которые могут быть установлены в initramfs при наличии в основной системе.
Скрипт «проверки»:
cat > check << 'EOF'
#!/bin/sh
exit 0
EOF
Если не хотите чтобы этот модуль использовался dracut по умолчанию, то поменяйте код выхода на 255, а так при обновлении ядра новый initramfs будет включать в себя этот модуль.
Скрипт установки модулей ядра:
cat > installkernel << 'EOF'
#!/bin/bash
instmods e1000
EOF
Включение нужных модулей ядра в initramfs, в данном случае для поддержки сетевой карты intel e1000, замените на свой( посмотреть можно командой lspci -k
).
Теперь создадим все необходимые конфигурационные файлы и наши скрипты.
echo 'root:x:0:0:root:/home/root:/bin/sh' > passwd
echo '/bin/sh' > shells
echo 'export PATH=/sbin:/usr/sbin:$PATH' >.profile
dropbearkey -t rsa -f dropbear_rsa_host_key
«Создаем» root пользователя, указываем список системных «шелов», модифицируем переменную PATH и генерируем rsa ключ для dropbear.
cat >nsswitch.conf << 'EOF'
passwd: files
shadow: files
group: files
initgroups: files
hosts: files dns
bootparams: files
ethers: files
netmasks: files
networks: files
protocols: files
rpc: files
services: files
automount: files
aliases: files
EOF
Указываем откуда брать пользователей и как преобразовывать dns имена.
Скрипт подъема сетевых интерфейсов и запуска dropbear:
cat >remote-ssh.sh << 'EOF'
#!/bin/sh
/sbin/modprobe e1000
/sbin/ifconfig lo 127.0.0.1/8
/sbin/ifconfig lo up
/sbin/ifconfig eth0 192.168.100.203/24
/sbin/ifconfig eth0 up
/sbin/route add default gw 192.168.100.1
/bin/mkdir -p /var/log
/usr/sbin/dropbear -E -m -p 2222 -a -K 600 > /var/log/lastlog
EOF
После modprobe подставьте подгрузку модуля необходимого для вашей сетевой карты( тот что указывали в скрипте installkernel ), также замените сетевые настройки и имя интерфейса на свои, подразумевается, что ip статистический, если выдача происходит через dhcp — в сркрипт install надо будет добавить установку dhclient и всех необходимых для него библиотек.
Скрипт остановки dropbear:
cat > clean.sh << 'EOF'
#!/bin/sh
/usr/bin/killall dropbear
EOF
Скрипт разблокировки всех luks томов, требующих ввода пароля:
cat > unlock << 'EOF'
if [ -f /etc/crypttab ] ; then
sed '/^$/d;/^#/d' /etc/crypttab > /tmp/crypttab
n=1
line="`sed -n "$n"p /tmp/crypttab`"
while [ -n "$line" ]; do
name="`echo $line|awk '{ print $1 }'`"
dev="`echo $line|awk '{ print $2 }'`"
key="`echo $line|awk '{ print $3 }'`"
if [ "$key" = "none" ]; then
luksname="$name"
if [ "${dev%%=*}" = "UUID" ]; then
device="`blkid -t $dev|cut -d: -f1`"
else
device=$dev
fi
echo "Password [$device ($luksname)]:"
while :;
do
cryptsetup luksOpen $device $luksname && break
done
fi
n=$((n+1))
line="`sed -n "$n"p /tmp/crypttab`"
done
sed -i /cryptsetup/c true /pre-pivot/*
[ "$1" = "-noexit" ] && exit 0
killall plymouth
killall cryptroot-ask
fi
exit 0
EOF
Тут мы сначала создаем «чистый» crypttab без закоментированных и пустых строк, затем в цикле перебираем и расшифровываем все тома для которых нужен пароль. Так как модуль luks от dracut перед сменой корневой фс отключает все неиспользуемые luks тома, то модифицируем срикпты лежащие в /pre-pivot, чтобы этого не происходило. Если скрипту передать параметр -noexit
, то процессы препятствующие загрузке не будут убиты и можно будет из initramfs модифицировать основную систему, предварительно смонтировав нужные разделы. Для продолжения загрузки нужно отмонтировать ранее вручную смонтированные разделы и выполнить команду:
killall cryptroot-ask
Разблокировка делается именно так, а не методом предложенным в bugzilla потому, что все остальные luks тома( отличные от root ) будут подключаться только после смены корневой фс, тоисть dropbear у нас еще будет висеть(если убрать хук на его убиение), но ниодной команды в нем уже не выполнить.
В итоге в папке /usr/share/dracut/modules.d/40unlock у вас должны быть следующие файлы:
[root@crypt 40unlock]# ls -al
итого 56
drwxr-xr-x. 2 root root 4096 Окт 31 17:36 .
drwxr-xr-x. 32 root root 4096 Окт 31 17:35 ..
-rwxr-xr-x. 1 root root 17 Окт 31 17:35 check
-rwxr-xr-x. 1 root root 36 Окт 31 17:36 clean.sh
-rw-------. 1 root root 427 Окт 31 17:36 dropbear_rsa_host_key
-rwxr-xr-x. 1 root root 1066 Окт 31 17:35 install
-rwxr-xr-x. 1 root root 27 Окт 31 17:36 installkernel
-rw-r--r--. 1 root root 222 Окт 31 17:36 nsswitch.conf
-rw-r--r--. 1 root root 35 Окт 31 17:36 passwd
-rw-r--r--. 1 root root 34 Окт 31 17:36 .profile
-rwxr-xr-x. 1 root root 270 Окт 31 17:36 remote-ssh.sh
-rw-r--r--. 1 root root 8 Окт 31 17:36 shells
-rwxr-xr-x. 1 root root 740 Окт 31 17:36 unlock
Теперь даем права исполнения для всех скриптов и пересобираем initramfs.
chmod a+x check clean.sh install installkernel remote-ssh.sh unlock
dracut -f
При следующей загрузке можно будет зайти удаленно через ssh и разблокировать все luks тома требующие ручного ввода пароля командой:
unlock
Минусы:
Это не будет работать если система запущенна в виртуальной мащине и сетевая карта является virtio устройством. Вероятно до запуска udev она не успевает распознаться. Как вариант обхода можно попробовать на хук pre-trigger повесить скрипт- который будет добавлять правила udev, выполняющееся перед правилом luks( а разблокировка происходит именно за счет udev- при нахождении luks тома запускается соответствующая команда) и запускающее скрипт remote-ssh.sh.
Пример:
SUBSYSTEM!="block", GOTO="luks_end"
ACTION!="add|change", GOTO="luks_end"
ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/bin/remote-ssh.sh"
LABEL="luks_end"
Этот вариант я не тестировал.
Ссылки по теме:
Dracut + encrypted root + networking
Dracut manual
PS: Приведенный код скриптов достаточно просто скопировать в консоль и выполнить- все запишется в соответствующий файл.
Автор: saamich