Удаленное разблокирование томов зашифрованных luks в CentOS6 через ssh

в 9:51, , рубрики: centos 6, linux, luks, ssh, unlock, системное администрирование, метки: , , ,

Приведенный ниже материал является адаптацией и дополнением метода удаленного разблокирования томов, предложенного «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

Источник

Поделиться

* - обязательные к заполнению поля