Kisah ini bermula lama dahulu, ketika Centos 7 (RHEL 7) dikeluarkan. Jika anda menggunakan penyulitan pada pemacu dengan Centos 6, maka tiada masalah dengan membuka kunci pemacu automatik apabila anda menyambungkan pemacu kilat USB dengan kekunci yang diperlukan. Namun, apabila 7 dikeluarkan, tiba-tiba semuanya tidak berfungsi seperti biasa. Kemudian adalah mungkin untuk mencari penyelesaian dalam mengembalikan dracut kepada sysvinit menggunakan baris mudah dalam konfigurasi: echo βomit_dracutmodules+=" systemd "' > /etc/dracut.conf.d/luks-workaround.conf
Yang segera melucutkan kami semua keindahan systemd - pelancaran perkhidmatan sistem yang pantas dan selari, yang mengurangkan masa permulaan sistem dengan ketara.
Perkara masih ada:
Tanpa menunggu penyelesaian, saya membuatnya untuk diri saya sendiri, dan sekarang saya berkongsi dengan orang ramai, yang berminat, baca terus.
Pengenalan
Systemd, apabila saya mula bekerja dengan Centos 7, tidak menyebabkan sebarang emosi, kerana selain daripada perubahan kecil dalam sintaks pengurusan perkhidmatan, saya tidak merasakan banyak perbezaan pada mulanya. Selepas itu, saya suka systemd, tetapi kesan pertama agak rosak, kerana pembangun dracut tidak menghabiskan banyak masa untuk menyokong proses but menggunakan systemd bersama-sama dengan penyulitan cakera. Secara umum, ia berfungsi, tetapi memasukkan kata laluan cakera setiap kali pelayan dimulakan bukanlah perkara yang paling menarik.
Setelah mencuba banyak cadangan dan mengkaji manual, saya menyedari bahawa dalam konfigurasi mod systemd dengan USB adalah mungkin, tetapi hanya dengan persatuan manual setiap cakera dengan kunci pada cakera USB, dan cakera USB itu sendiri hanya boleh dikaitkan dengannya. UUID, LABEL tidak berfungsi. Ia tidak begitu mudah untuk mengekalkan ini di rumah, jadi pada akhirnya saya terpaksa menunggu dan, selepas menunggu selama hampir 7 tahun, saya menyedari bahawa tiada siapa yang akan menyelesaikan masalah itu.
Masalah
Sudah tentu, hampir semua orang boleh menulis pemalam mereka sendiri untuk dracut, tetapi membuat ia berfungsi tidak lagi begitu mudah. Ternyata disebabkan sifat permulaan systemd yang selari, tidak begitu mudah untuk memasukkan kod anda dan mengubah kemajuan pemuatan. Dokumentasi untuk dracut tidak menjelaskan segala-galanya. Walau bagaimanapun, selepas percubaan yang panjang, saya dapat menyelesaikan masalah itu.
Bagaimanakah ia berfungsi
Ia berdasarkan tiga unit:
- luks-auto-key.service - mencari pemacu dengan kunci untuk LUKS
- luks-auto.target - bertindak sebagai kebergantungan untuk unit systemd-cryptsetup terbina dalam
- luks-auto-clean.service - membersihkan fail sementara yang dibuat oleh luks-auto-key.service
Dan luks-auto-generator.sh ialah skrip yang dilancarkan oleh systemd dan menjana unit berdasarkan parameter kernel. Penjana serupa dicipta oleh unit fstab, dsb.
luks-auto-generator.sh
Menggunakan drop-in.conf, gelagat systemd-cryptsetup standard diubah dengan menambahkan luks-auto.target pada kebergantungan mereka.
luks-auto-key.service dan luks-auto-key.sh
Unit ini menjalankan skrip luks-auto-key.sh, yang, berdasarkan kekunci rd.luks.*, mencari media dengan kunci dan menyalinnya ke direktori sementara untuk kegunaan selanjutnya. Selepas proses selesai, kunci dipadamkan daripada direktori sementara oleh luks-auto-clean.service.
Sumber:
/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 "
Pemasangan
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
Kesimpulan
Untuk kemudahan, saya telah mengekalkan keserasian dengan pilihan baris arahan kernel seperti untuk mod sysvinit, yang menjadikannya lebih mudah untuk digunakan dalam pemasangan yang lebih lama.
Sumber: www.habr.com