Η ιστορία ξεκίνησε πολύ παλιά, όταν κυκλοφόρησε. Centos 7 (RHEL 7). Εάν χρησιμοποιήσατε κρυπτογράφηση σε δίσκους με Centos Στην έκδοση 6, δεν υπήρχαν προβλήματα με το αυτόματο ξεκλείδωμα δίσκων κατά τη σύνδεση μιας μονάδας flash USB με τα σωστά κλειδιά. Ωστόσο, με την κυκλοφορία της έκδοσης 7, όλα σταμάτησαν ξαφνικά να λειτουργούν όπως αναμενόταν. Βρέθηκε μια λύση επαναφέροντας το dracut σε sysvinit χρησιμοποιώντας μια απλή γραμμή στη διαμόρφωση: echo 'omit_dracutmodules+=" systemd "' > /etc/dracut.conf.d/luks-workaround.conf
Πράγμα που μας στέρησε αμέσως όλη την ομορφιά του systemd - γρήγορη και παράλληλη εκκίνηση υπηρεσιών συστήματος, που μείωσε σημαντικά τον χρόνο εκκίνησης του συστήματος.
Τα πράγματα είναι ακόμα εκεί:
Χωρίς να περιμένω λύση, το έφτιαξα για τον εαυτό μου και τώρα το μοιράζομαι με το κοινό, που ενδιαφέρεται, διαβάστε παρακάτω.

Εισαγωγή
Systemd όταν άρχισα να δουλεύω με αυτό Centos Το 7 δεν προκάλεσε κανέναν ενθουσιασμό, καθώς εκτός από μια μικρή αλλαγή στη σύνταξη διαχείρισης υπηρεσιών, δεν παρατήρησα μεγάλη διαφορά στην αρχή. Τελικά μου άρεσε το systemd, αλλά η αρχική μου εντύπωση αλλοιώθηκε ελαφρώς από το γεγονός ότι οι προγραμματιστές του dracut δεν αφιέρωσαν πολύ χρόνο στην υποστήριξη της διαδικασίας εκκίνησης του systemd σε συνδυασμό με την κρυπτογράφηση δίσκου. Γενικά λειτούργησε, αλλά έπρεπε να εισάγω τον κωδικό πρόσβασης του δίσκου μου κάθε φορά που το ξεκινούσα. υπηρέτης — όχι η πιο ενδιαφέρουσα δραστηριότητα.
Έχοντας δοκιμάσει πολλές συστάσεις και μελέτησα το εγχειρίδιο, συνειδητοποίησα ότι στη λειτουργία systemd η διαμόρφωση με USB είναι δυνατή, αλλά μόνο με τη μη αυτόματη σύνδεση κάθε δίσκου με ένα κλειδί σε έναν δίσκο USB και ο ίδιος ο δίσκος USB μπορεί να συσχετιστεί μόνο με Το UUID, LABEL δεν λειτούργησε. Δεν ήταν πολύ βολικό να το συντηρήσω στο σπίτι, οπότε στο τέλος βυθίστηκα στην αναμονή και, μετά από σχεδόν 7 χρόνια αναμονής, συνειδητοποίησα ότι κανείς δεν επρόκειτο να λύσει το πρόβλημα.
Προβλήματα
Φυσικά, σχεδόν ο καθένας μπορεί να γράψει το δικό του πρόσθετο για το dracut, αλλά η λειτουργία του δεν είναι πλέον τόσο εύκολη. Αποδείχθηκε ότι λόγω της παράλληλης φύσης της εκκίνησης του συστήματος, δεν είναι τόσο εύκολο να συμπεριλάβετε τον κωδικό σας και να αλλάξετε την πρόοδο φόρτωσης. Η τεκμηρίωση για το dracut δεν εξήγησε τα πάντα. Ωστόσο, μετά από μακροχρόνια πειράματα, κατάφερα να λύσω το πρόβλημα.
Πως δουλεύει
Βασίζεται σε τρεις ενότητες:
- luks-auto-key.service - αναζητά μονάδες δίσκου με κλειδιά για LUKS
- luks-auto.target - λειτουργεί ως εξάρτηση για ενσωματωμένες μονάδες systemd-cryptsetup
- 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, η οποία διευκολύνει τη χρήση σε παλαιότερες εγκαταστάσεις.
Πηγή: www.habr.com
