dracut + systemd + LUKS + usbflash = avtomatik kiliddən çıxarmaq

Hekayə çoxdan, filmin yayımlandığı vaxtdan başlayıb. Centos 7 (RHEL 7). Əgər disklərdə şifrələmədən istifadə etmisinizsə Centos 6-cı versiyada, düzgün düymələrlə USB flash sürücüsünü qoşarkən disklərin avtomatik kilidini açmaqda heç bir problem yox idi. Lakin, 7-ci versiyanın buraxılması ilə hər şey gözlənildiyi kimi birdən işləməyi dayandırdı. Konfiqurasiyadakı sadə bir sətirdən istifadə edərək dracut-u sysvinit-ə qaytarmaqla həll yolu tapıldı: echo 'omit_dracutmodules+=" systemd "' > /etc/dracut.conf.d/luks-workaround.conf
Bu bizi dərhal systemd-in bütün gözəlliyindən məhrum etdi - sistemin işə salınma vaxtını əhəmiyyətli dərəcədə azaldan sistem xidmətlərinin sürətli və paralel işə salınması.
İşlər hələ də var: 905683
Həllini gözləmədən özüm üçün hazırladım və indi bunu ictimaiyyətlə bölüşürəm, maraqlananlar oxusunlar.
dracut + systemd + LUKS + usbflash = avtomatik kiliddən çıxarmaq

Giriş

İlk dəfə işləməyə başladığım zaman Systemd Centos 7 heç bir həyəcan doğurmadı, çünki xidmət idarəetmə sintaksisindəki kiçik bir dəyişiklikdən başqa, əvvəlcə çox fərq hiss etmədim. Nəticədə systemd-i bəyənməyə başladım, amma ilkin təəssüratım bir az dəyişdi, çünki dracut tərtibatçıları systemd açılış prosesini disk şifrələməsi ilə birlikdə dəstəkləmək üçün çox vaxt sərf etmədilər. Ümumiyyətlə işləyirdi, amma hər dəfə işə salanda disk parolumu daxil etməli oldum. server — ən maraqlı fəaliyyət deyil.
Bir sıra tövsiyələri sınadıqdan və təlimatı öyrəndikdən sonra başa düşdüm ki, sistem rejimində USB ilə konfiqurasiya mümkündür, ancaq hər bir diskin USB diskindəki açarla əl ilə əlaqələndirilməsi ilə və USB diskin özü yalnız onunla əlaqələndirilə bilər. UUID, LABEL işləmədi. Bunu evdə saxlamaq çox rahat deyildi, buna görə də sonda gözləməyə başladım və təxminən 7 il gözlədikdən sonra heç kimin problemi həll etməyəcəyini başa düşdüm.

Problemləri

Əlbəttə ki, demək olar ki, hər kəs dracut üçün öz plaginini yaza bilər, lakin onu işləmək artıq o qədər də asan deyil. Məlum oldu ki, sistem başlanğıcının paralel xarakterinə görə kodunuzu daxil etmək və yükləmə prosesini dəyişdirmək o qədər də asan deyil. Dracut üçün sənədlər hər şeyi izah etmədi. Ancaq uzun təcrübələrdən sonra problemi həll edə bildim.

Bu necə işləyir

Üç vahidə əsaslanır:

  1. luks-auto-key.service - LUKS üçün açarları olan sürücüləri axtarır
  2. luks-auto.target - daxili systemd-cryptsetup vahidləri üçün asılılıq kimi çıxış edir
  3. luks-auto-clean.service - luks-auto-key.service tərəfindən yaradılmış müvəqqəti faylları təmizləyir

Və luks-auto-generator.sh systemd tərəfindən işə salınan və nüvə parametrləri əsasında vahidlər yaradan bir skriptdir. Oxşar generatorlar fstab vahidləri tərəfindən yaradılır və s.

luks-auto-generator.sh

Drop-in.conf istifadə edərək, standart systemd-cryptsetup-un davranışı onların asılılığına luks-auto.target əlavə etməklə dəyişdirilir.

luks-auto-key.service və luks-auto-key.sh

Bu bölmə rd.luks.* düymələrinə əsaslanaraq, düymələri olan medianı tapıb sonrakı istifadə üçün onları müvəqqəti kataloqa köçürən luks-auto-key.sh skriptini idarə edir. Proses başa çatdıqdan sonra açarlar luks-auto-clean.service tərəfindən müvəqqəti kataloqdan silinir.

Mənbələr:

/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 "

Quraşdırma


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

Nəticə

Rahatlıq üçün sysvinit rejimində olduğu kimi kernel əmr satırı seçimləri ilə də uyğunluğu qorudum ki, bu da köhnə quraşdırmalarda istifadəni asanlaşdırır.

Mənbə: www.habr.com

DDoS mühafizəsi, VPS VDS serverləri olan saytlar üçün etibarlı hostinq alın 🔥 DDoS qorunması, VPS VDS serverləri ilə etibarlı veb sayt hostinqi alın | ProHoster