dracut + systemd + LUKS + usbflash = кушодани худкор

Ҳикоя хеле пеш, вақте ки Centos 7 (RHEL 7) бароварда шуд, оғоз ёфт. Агар шумо рамзгузорӣ дар дискҳо бо Centos 6 истифода шуда бошед, пас ҳангоми пайваст кардани флеши USB флешдор бо калидҳои зарурӣ дар кушодани худкори дискҳо ҳеҷ мушкиле вуҷуд надошт. Аммо, вақте ки 7 озод карда шуд, ногаҳон ҳама чиз тавре ки шумо одат карда будед, кор накард. Он гоҳ имкон пайдо шуд, ки роҳи баргардонидани dracut ба sysvinit бо истифода аз хати оддӣ дар конфигуратсия: echo 'omit_dracutmodules+=" systemd "' > /etc/dracut.conf.d/luks-workaround.conf
Ин дарҳол моро аз тамоми дилрабоии systemd маҳрум кард - зуд ва мувозии хидматҳои системавӣ, ки вақти оғозёбии системаро хеле кам кард.
Чизҳо ҳоло ҳам ҳастанд: 905683
Бе мунтазири ҳалли он, ман онро барои худ кардам ва ҳоло ман онро бо мардум мубодила мекунам, ки таваҷҷӯҳ доранд, хонед.
dracut + systemd + LUKS + usbflash = кушодани худкор

Муқаддима

Systemd, вақте ки ман бори аввал бо Centos 7 кор карданро оғоз кардам, ҳеҷ гуна эҳсосотро ба вуҷуд наовард, зеро ба ғайр аз тағироти ночиз дар синтаксиси идоракунии хидмат, ман дар аввал фарқияти зиёдро ҳис накардам. Баъдан, ба ман systemd маъқул шуд, аммо таассуроти аввал каме вайрон шуд, зеро таҳиягарони dracut барои дастгирии раванди пурборкунӣ бо истифода аз systemd дар якҷоягӣ бо рамзгузории диск вақти зиёд сарф накарданд. Умуман, он кор кард, аммо ворид кардани пароли диск ҳар дафъае, ки сервер ба кор шурӯъ мекунад, чизи ҷолибтарин нест.
Якчанд тавсияҳоро санҷида ва дастурро омӯхта, ман фаҳмидам, ки дар ҳолати системавӣ конфигуратсия бо USB имконпазир аст, аммо танҳо бо пайвастани дастӣ ҳар як диск бо калиди диски USB ва худи диски USB танҳо тавассути он алоқаманд аст. UUID, LABEL кор накард. Нигоҳ доштани ин дар хонаи шахсии худ чандон қулай набуд, бинобар ин ман дар ниҳоят ба интизорӣ афтодам ва пас аз тақрибан 7 сол интизорӣ фаҳмидам, ки ҳеҷ кас ин мушкилотро ҳал намекунад.

Масъалаҳо

Албатта, қариб ҳама метавонад плагини худро барои dracut нависад, аммо кор кардани он дигар он қадар осон нест. Маълум шуд, ки аз сабаби табиати параллели оғозёбии система, дохил кардани коди шумо ва тағир додани ҷараёни боркунӣ он қадар осон нест. Ҳуҷҷатҳои dracut на ҳама чизро шарҳ доданд. Аммо, пас аз таҷрибаҳои тӯлонӣ, ман тавонистам мушкилотро ҳал кунам.

Он чӣ гуна кор мекунад

Он ба се воҳид асос ёфтааст:

  1. luks-auto-key.service - ҷустуҷӯи дискҳо бо калидҳои LUKS
  2. luks-auto.target - ҳамчун вобастагӣ аз воҳидҳои дарунсохташудаи systemd-cryptsetup амал мекунад
  3. luks-auto-clean.service - файлҳои муваққатии аз ҷониби luks-auto-key.service сохташударо тоза мекунад

Ва luks-auto-generator.sh скриптест, ки аз ҷониби systemd оғоз карда мешавад ва воҳидҳоро дар асоси параметрҳои ядро ​​тавлид мекунад. Генераторҳои шабеҳро агрегатҳои fstab ва ғайра эҷод мекунанд.

luks-auto-generator.sh

Бо истифода аз drop-in.conf, рафтори стандартии systemd-cryptsetup бо илова кардани luks-auto.target ба вобастагии онҳо тағир дода мешавад.

luks-auto-key.service ва luks-auto-key.sh

Ин воҳид скрипти luks-auto-key.sh-ро иҷро мекунад, ки дар асоси калидҳои rd.luks.* медиаро бо калидҳо пайдо мекунад ва онҳоро барои истифодаи минбаъда ба директорияи муваққатӣ нусхабардорӣ мекунад. Пас аз анҷоми раванд, калидҳо аз феҳристи муваққатӣ аз ҷониби luks-auto-clean.service нест карда мешаванд.

Сарчашмаҳо:

/usr/lib/dracut/modules.d/99luks-auto/module-setup.sh

#!/bin/bash

check () {
        if ! dracut_module_included "systemd"; then
                "luks-auto needs systemd in the initramfs"
                return 1
        fi
        return 255
}

depends () {
        echo "systemd"
        return 0
}

install () {
        inst "$systemdutildir/systemd-cryptsetup"
		inst_script "$moddir/luks-auto-generator.sh" "$systemdutildir/system-generators/luks-auto-generator.sh"
		inst_script "$moddir/luks-auto-key.sh" "/etc/systemd/system/luks-auto-key.sh"
		inst_script "$moddir/luks-auto.sh" "/etc/systemd/system/luks-auto.sh"
		inst "$moddir/luks-auto.target" "${systemdsystemunitdir}/luks-auto.target"
		inst "$moddir/luks-auto-key.service" "${systemdsystemunitdir}/luks-auto-key.service"
		inst "$moddir/luks-auto-clean.service" "${systemdsystemunitdir}/luks-auto-clean.service"
		ln_r "${systemdsystemunitdir}/luks-auto.target" "${systemdsystemunitdir}/initrd.target.wants/luks-auto.target"
		ln_r "${systemdsystemunitdir}/luks-auto-key.service" "${systemdsystemunitdir}/initrd.target.wants/luks-auto-key.service"
		ln_r "${systemdsystemunitdir}/luks-auto-clean.service" "${systemdsystemunitdir}/initrd.target.wants/luks-auto-clean.service"
}

/usr/lib/dracut/modules.d/99luks-auto/luks-auto-generator.sh


#!/bin/sh
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh

. /lib/dracut-lib.sh

SYSTEMD_RUN='/run/systemd/system'
CRYPTSETUP='/usr/lib/systemd/systemd-cryptsetup'
TOUT=$(getargs rd.luks.key.tout)
if [ ! -z "$TOUT" ]; then
	mkdir -p "${SYSTEMD_RUN}/luks-auto-key.service.d"
	cat > "${SYSTEMD_RUN}/luks-auto-key.service.d/drop-in.conf"  <<EOF
[Service]
Type=oneshot
ExecStartPre=/usr/bin/sleep $TOUT

EOF
fi
mkdir -p "$SYSTEMD_RUN/luks-auto.target.wants"
for argv in $(getargs rd.luks.uuid -d rd_LUKS_UUID); do
	_UUID=${argv#luks-}
	_UUID_ESC=$(systemd-escape -p $_UUID)
	mkdir -p "${SYSTEMD_RUN}/systemd-cryptsetup@luksx2d${_UUID_ESC}.service.d"
	cat > "${SYSTEMD_RUN}/systemd-cryptsetup@luksx2d${_UUID_ESC}.service.d/drop-in.conf"  <<EOF
[Unit]
After=luks-auto.target
ConditionPathExists=!/dev/mapper/luks-${_UUID}

EOF
	cat > "${SYSTEMD_RUN}/luks-auto@${_UUID_ESC}.service"  <<EOF
[Unit]
Description=luks-auto Cryptography Setup for %I
DefaultDependencies=no
Conflicts=umount.target
IgnoreOnIsolate=true
Before=luks-auto.target
BindsTo=dev-disk-byx2duuid-${_UUID_ESC}.device
After=dev-disk-byx2duuid-${_UUID_ESC}.device luks-auto-key.service
Before=umount.target

[Service]
Type=oneshot
RemainAfterExit=yes
TimeoutSec=0
ExecStart=/etc/systemd/system/luks-auto.sh ${_UUID}
ExecStop=$CRYPTSETUP detach 'luks-${_UUID}'
Environment=DRACUT_SYSTEMD=1
StandardInput=null
StandardOutput=syslog
StandardError=syslog+console

EOF
ln -fs ${SYSTEMD_RUN}/luks-auto@${_UUID_ESC}.service $SYSTEMD_RUN/luks-auto.target.wants/luks-auto@${_UUID_ESC}.service
done

/usr/lib/dracut/modules.d/99luks-auto/luks-auto-key.service


[Unit]
Description=LUKS AUTO key searcher
After=cryptsetup-pre.target
Before=luks-auto.target
DefaultDependencies=no

[Service]
Environment=DRACUT_SYSTEMD=1
Type=oneshot
ExecStartPre=/usr/bin/sleep 1
ExecStart=/etc/systemd/system/luks-auto-key.sh
RemainAfterExit=true
StandardInput=null
StandardOutput=syslog
StandardError=syslog+console

/usr/lib/dracut/modules.d/99luks-auto/luks-auto-key.sh


#!/bin/sh
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
export DRACUT_SYSTEMD=1

. /lib/dracut-lib.sh
MNT_B="/tmp/luks-auto"
ARG=$(getargs rd.luks.key)
IFS=$':' _t=(${ARG})
KEY=${_t[0]}
F_FIELD=''
F_VALUE=''
if [ ! -z $KEY ] && [ ! -z ${_t[1]} ];then
	IFS=$'=' _t=(${_t[1]})
	F_FIELD=${_t[0]}
	F_VALUE=${_t[1]}
	F_VALUE="${F_VALUE%"}"
	F_VALUE="${F_VALUE#"}"
fi
mkdir -p $MNT_B

finding_luks_keys(){
	local _DEVNAME=''
	local _UUID=''
	local _TYPE=''
	local _LABEL=''
	local _MNT=''
	local _KEY="$1"
	local _F_FIELD="$2"
	local _F_VALUE="$3"
	local _RET=0	
	blkid -s TYPE -s UUID -s LABEL -u filesystem | grep -v -E -e "TYPE=".*_member"" -e "TYPE="crypto_.*"" -e "TYPE="swap"" | while IFS=$'' read -r _line; do
		IFS=$':' _t=($_line);
		_DEVNAME=${_t[0]}
		_UUID=''
		_TYPE=''
		_LABEL=''
		_MNT=''
		IFS=$' ' _t=(${_t[1]});
		for _a in "${_t[@]}"; do
			IFS=$'=' _v=(${_a});
			temp="${_v[1]%"}"
			temp="${temp#"}"
			case ${_v[0]} in
				'UUID')
					_UUID=$temp
				;;
				'TYPE')
					_TYPE=$temp
				;;
				'LABEL')
					_LABEL=$temp
				;;
			esac
		done
		if [ ! -z "$_F_FIELD" ];then
			case $_F_FIELD in
				'UUID')
					[ ! -z "$_F_VALUE" ] && [ "$_UUID" != "$_F_VALUE" ] && continue
				;;
				'LABEL')
					[ ! -z "$_F_VALUE" ] && [ "$_LABEL" != "$_F_VALUE" ] && continue
				;;
				*)
					[ "$_DEVNAME" != "$_F_FIELD" ] && continue
				;;
			esac
		fi
		_MNT=$(findmnt -n -o TARGET $_DEVNAME)
		if [ -z "$_MNT" ]; then
			_MNT=${MNT_B}/KEY-${_UUID}
			mkdir -p "$_MNT" && mount -o ro "$_DEVNAME" "$_MNT"
			_RET=$?
		else
			_RET=0
		fi
		if [ "${_RET}" -eq 0 ] && [ -f "${_MNT}/${_KEY}" ]; then
			cp "${_MNT}/${_KEY}" "$MNT_B/${_UUID}.key"
			info "Found ${_MNT}/${_KEY} on ${_UUID}"
		fi
		if [[ "${_MNT}" =~ "${MNT_B}" ]]; then
			umount "$_MNT" && rm -rfd --one-file-system "$_MNT"						
		fi
	done
	return 0
}
finding_luks_keys $KEY $F_FIELD $F_VALUE

/usr/lib/dracut/modules.d/99luks-auto/luks-auto.target


[Unit]
Description=LUKS AUTO target
After=systemd-readahead-collect.service systemd-readahead-replay.service
After=cryptsetup-pre.target luks-auto-key.service
Before=cryptsetup.target

/usr/lib/dracut/modules.d/99luks-auto/luks-auto.sh


#!/bin/sh
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
export DRACUT_SYSTEMD=1
. /lib/dracut-lib.sh

MNT_B="/tmp/luks-auto"
CRYPTSETUP='/usr/lib/systemd/systemd-cryptsetup'

for i in $(ls -p $MNT_B | grep -v /);do
	info "Trying $i on $1..."
	$CRYPTSETUP attach "luks-$1" "/dev/disk/by-uuid/$1" $MNT_B/$i 'tries=1'
	if [ "$?" -eq "0" ]; then
		info "Found $i for $1"
		exit 0
	fi
done
warn "No key found for $1.  Fallback to passphrase mode."

/usr/lib/dracut/modules.d/99luks-auto/luks-auto-clean.service

[Unit]
Description=LUKS AUTO key cleaner
After=cryptsetup.target
DefaultDependencies=no

[Service]
Type=oneshot
ExecStart=/usr/bin/rm -rfd --one-file-system /tmp/luks-auto

/etc/dracut.conf.d/luks-auto.conf

add_dracutmodules+=" luks-auto "

параметр


mkdir -p /usr/lib/dracut/modules.d/99luks-auto/
# размещаем тут почти все файлы
chmod +x /usr/lib/dracut/modules.d/99luks-auto/*.sh
# создаем файл /etc/dracut.conf.d/luks-auto.conf
# И генерируем новый initramfs
dracut -f

хулоса

Барои роҳат, ман мувофиқатро бо вариантҳои сатри фармони ядро ​​нигоҳ доштам, ба мисли ҳолати sysvinit, ки истифодаи онро дар насбҳои кӯҳна осонтар мекунад.

Манбаъ: will.com

Илова Эзоҳ