Portál AbcLinuxu, 15. května 2024 04:26

Šifrovaný Proxmox VE 6: ZFS, LUKS, systemd_boot a Dropbear

4. 9. 2019 | Mark Stopka
Články - Šifrovaný Proxmox VE 6: ZFS, LUKS, systemd_boot a Dropbear  

Tento článek, jenž byl přeložen z anglického originálu na blogu po svolení původního autora, popisuje, jak nastavit plně šifrovaného hostitele Proxmox VE 6 s rootem na ZFS a umožnit jeho odemčení skrze vzdálený přístup pomocí Dropbear SSH serveru. Navíc se jedná o metodu, jež zanechá systemd_boot netknutý, a proto zachová veškerou funkcionalitu nástrojů pve.

Obsah

  1. Instalace Proxmox VE 6 na server
  2. Základní konfigurace po instalaci
  3. Zašifrování provedené instalace
    1. Odstranění disku z ZFS poolu
    2. Zašifrování disku LUKSem
    3. Přidání disku zpět do ZFS poolu
    4. Opakování, dokud nejsou zašifrovány všechny disky
  4. Nastavení Dropbear SSH a systemd_boot pro zpřístupnění vzdáleného odemykání

Požadavky

Jediným zásadním požadavkem, kromě serveru, na který chcete nainstalovat Proxmox VE 6, je mít v tomto serveru alespoň 2 disky. To proto, abyste mohli vytvořit ZFS RAID 1. I pokud byste nechtěli mít root oddíl zrcadlený, stále budete potřebovat druhý disk alespoň dočasně, aby mohl být root oddíl zrcadlený. V opačném případě byste nejdříve museli nainstalovat šifrovaný Debian a až do něj nainstalovat Proxmox VE 6.

Mimo to předpokládám, že jste dostatečně obeznámeni s funkcionalitami plného šifrování disků na linuxových systémech, pokud nejste, měli byste se s touto problematikou nejprve seznámit předtím, než si začnete hrát se samotným hardware. Nezkoušejte tento postup na produkčních systémech, pokud nejste s problematikou plně seznámeni.

Instalace Proxmox VE 6

Jediná věc, na kterou si musíte při instalaci dát pozor, je, abyste instalaci provedli na ZFS RAID 1, zbytek postupu je shodný s jakoukoli jinou instalací Proxmox VE 6.

Základní konfigurace po instalaci

Z nějakého zvláštního důvodu se nastavení proměnné PATH v běžné příkazové řádce liší od nastavení PATH v javascriptové příkazové řádce přístupné z webového rozhraní, toto je vhodné napravit:

echo "export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" >> ~/.bashrc

Odstraňte oznámení o chybějící komerční podpoře (zdroj):

sed -i.bak "s/data.status !== 'Active'/false/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js && systemctl restart pveproxy.service

Nastavte komunitní repozitáře:

rm /etc/apt/sources.list.d/pve-enterprise.list
echo 'deb http://download.proxmox.com/debian/pve buster pve-no-subscription' > pve-community.list

Aktualizujte server:

apt update
apt upgrade

Zašifrování provedené instalace

Tento postup je částečně založen na postupu z tohoto komentáře.

Ihned po instalaci by rozdělení disků mělo být obdobné tomuto výstupu z lsblk:

NAME            MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda               8:0    0 465.8G  0 disk
├─sda1            8:1    0  1007K  0 part
├─sda2            8:2    0   512M  0 part
└─sda3            8:3    0 465.3G  0 part
sdb               8:16   0 931.5G  0 disk
sdc               8:32   0 931.5G  0 disk
sdd               8:48   0 465.8G  0 disk
├─sdd1            8:49   0  1007K  0 part
├─sdd2            8:50   0   512M  0 part
└─sdd3            8:51   0 465.3G  0 part

Třetí oddíl na každém disku obsahuje naši instalaci, první a druhý oddíl obsahují oddíly boot a efi.

zpool status by měl vypadat přibližně takto:

NAME             STATE     READ WRITE CKSUM
rpool            ONLINE       0     0     0
  mirror-0       ONLINE       0     0     0
    ata-Samsung_SSD_850_EVO_500GB_XXXXXXXXXXXXXXX-part3  ONLINE       0     0     0
    ata-WDC_WDS500G2B0A-XXXXXX_XXXXXXXXXXXX-part3        ONLINE       0     0     0

V tomto bodě je nutné nainstalovat cryptsetup:

apt install cryptsetup

Odstraňte první oddíl z rpoolu, poté jej zašifrujte, namapujte přes LUKS do /dev/mapper/cryptrpool1 a přidejte zpět do rpoolu.

zpool detach rpool ata-Samsung_SSD_850_EVO_500GB_XXXXXXXXXXXXXXX-part3
cryptsetup luksFormat /dev/disk/by-id/ata-Samsung_SSD_850_EVO_500GB_XXXXXXXXXXXXXXX-part3
cryptsetup luksOpen /dev/disk/by-id/ata-Samsung_SSD_850_EVO_500GB_XXXXXXXXXXXXXXX-part3 cryptrpool1
zpool attach rpool ata-Samsung_SSD_850_EVO_500GB_XXXXXXXXXXXXXXX-part3 cryptrpool1

Dále vyčkejte, než dojde k synchronizaci zrcadla, což si můžete ověřit na řádku scan příkazu zpool status. Výstup by měl být podobný tomuto:

scan: resilvered 1022M in 0 days 00:00:04 with 0 errors on Wed Aug 21 17:27:55 2019

Nyní stejný postup zopakujte pro druhý disk, který je součástí zpoolu:

zpool detach rpool ata-WDC_WDS500G2B0A-XXXXXX_XXXXXXXXXXXX-part3
cryptsetup luksFormat /dev/disk/by-id/ata-WDC_WDS500G2B0A-XXXXXX_XXXXXXXXXXXX-part3
cryptsetup luksOpen /dev/disk/by-id/ata-WDC_WDS500G2B0A-XXXXXX_XXXXXXXXXXXX-part3 cryptrpool2
zpool attach rpool cryptrpool1 cryptrpool2

Po provedení těchto změn by výstup příkazu lsblk měl vypadat následovně:

NAME            MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda               8:0    0 465.8G  0 disk
├─sda1            8:1    0  1007K  0 part
├─sda2            8:2    0   512M  0 part
└─sda3            8:3    0 465.3G  0 part
  └─cryptrpool1 253:0    0 465.3G  0 crypt
sdb               8:16   0 931.5G  0 disk
sdc               8:32   0 931.5G  0 disk
sdd               8:48   0 465.8G  0 disk
├─sdd1            8:49   0  1007K  0 part
├─sdd2            8:50   0   512M  0 part
└─sdd3            8:51   0 465.3G  0 part
  └─cryptrpool2 253:1    0 465.3G  0 crypt

Po provedení úplné synchronizace by výstup příkazu zpool status měl vypadat takto:

NAME             STATE     READ WRITE CKSUM
rpool            ONLINE       0     0     0
  mirror-0       ONLINE       0     0     0
    cryptrpool1  ONLINE       0     0     0
    cryptrpool2  ONLINE       0     0     0

Dalším krokem je nastavení souboru /etc/crypttab, k tomu použijeme nástroj blkid, abychom zjistili PARTUUID pro oba oddíly:

blkid -s PARTUUID -o value /dev/disk/by-id/ata-Samsung_SSD_850_EVO_500GB_XXXXXXXXXXXXXXX-part3
blkid -s PARTUUID -o value /dev/disk/by-id/ata-WDC_WDS500G2B0A-XXXXXX_XXXXXXXXXXXX-part3

Poté je přidáme do souboru /etc/crypttab tak, aby vypadal následovně:

root@caliban:~# cat /etc/crypttab
# <target name> <source device>                                <key file>      <options>
  cryptrpool1   PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX  none            luks,discard,initramfs
  cryptrpool2   PARTUUID=YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY  none            luks,discard,initramfs

Dalším krokem je úprava initramfs a jeho umístění na bootovací oddíl (zde se odlišujeme od odkazovaného postupu na fóru výše):

update-initramfs -u -k all
pve-efiboot-tool refresh

Pokud se vám to přihodí, v tomto bodě může cryptsetup skončit s chybovým hlášením při provádění update-initramfs, avšak řešení následně funguje:

cryptsetup: ERROR: Couldn't resolve device rpool/ROOT/pve-1
cryptsetup: WARNING: Couldn't determine root device

Nyní je čas server restartovat a při bootování odemknout pevné disky heslem tak, aby se správně sestavil ZFS oddíl.

Nastavení Dropbear SSH serveru pro umožnění vzdáleného odemčení

Nyní začíná ta složitější, avšak o to zábavnější část celého návodu! Vzhledem k tomu, že nepoužíváme grub, musíme udělat nějaké změny oproti běžnému postupu v těchto situacích.

Pár zajímavých odkazů, které se vyplatí prostudovat:

Nejdříve nainstalujeme Dropbear a busybox:

apt install dropbear busybox

Poté přidáme busybox do /etc/initramfs-tools/initramfs.conf:

root@caliban:~# cat /etc/initramfs-tools/initramfs.conf | grep ^BUSYBOX
BUSYBOX=y

Zkonvertujeme Dropbear SSH klíče:

cd /etc/dropbear-initramfs/
/usr/lib/dropbear/dropbearconvert dropbear openssh dropbear_rsa_host_key id_rsa
dropbearkey -y -f dropbear_rsa_host_key | grep "^ssh-rsa " > id_rsa.pub

Dalším krokem je přidání vlastního veřejného SSH klíče mezu autorizované klíče:

vi /etc/dropbear-initramfs/authorized_keys

Poté se ujistíme, že dropbear bude spuštěn tím, že ověříme, že hodnota klíče NO_START je rovna 0 v souboru /etc/default/dropbear.

root@caliban:~# cat /etc/default/dropbear | grep ^NO_START
NO_START=0

Nakonec nastavíme Dropbear SSH server na nestandardní port (odlišný od 22), abychom se vyvarovali varování o man-in-the-middle při připojování k serveru, když je v režimu bootování, případně již nabootován k produkčnímu užití změnou hodnoty DROPBEAR_OPTIONS v souboru /etc/dropbear-initramfs/config:

root@caliban:~# cat /etc/dropbear-initramfs/config | grep ^DROPBEAR_OPTIONS
DROPBEAR_OPTIONS="-p 12345"

Ve svém lokálním souboru ~/.ssh/config můžete přidat dvě nastavení pro snažší vzdálenou správu:

$ cat ~/.ssh/config
Host unlock_caliban
  Hostname 1.2.3.4
  User root
  Port 2222

Host caliban
  Hostname 1.2.3.4
  Port 22

V tuto chvíli jsem si všiml, že po restartu je připojen pouze třetí oddíl, který je součástí rpoolu. Po ručním připojení oddílu /boot jsem si všiml, že obsahuje konfigurační soubory systemd-boot, avšak vypadaly, že jsou automaticky generovány Proxmoxem po spuštění příkazu pve-efiboot-tool refresh. Podíval jsem se tedy na soubor /usr/sbin/pve-efiboot-tool a prohlížel zdrojový kód, dokud jsem nenarazil na část, jež odkazuje na /etc/kernel/postinst.d/zz-pve-efiboot, která obsahuje kód, který generuje konfigurační soubory pro systemd-boot:

# [...]
for kver in ${BOOT_KVERS}; do

    linux_image="/boot/vmlinuz-${kver}"
    initrd="/boot/initrd.img-${kver}"

    if [ ! -f "${linux_image}" ]; then
        warn "No linux-image ${linux_image} found - skipping"
        continue
    fi
    if [ ! -f "${initrd}" ]; then
        warn "No initrd-image ${initrd} found - skipping"
        continue
    fi

    warn "  Copying kernel and creating boot-entry for ${kver}"
    KERNEL_ESP_DIR="${PMX_ESP_DIR}/${kver}"
    KERNEL_LIVE_DIR="${esp}/${KERNEL_ESP_DIR}"
    mkdir -p "${KERNEL_LIVE_DIR}"
    cp -u --preserve=timestamps "${linux_image}" "${KERNEL_LIVE_DIR}/"
    cp -u --preserve=timestamps "${initrd}" "${KERNEL_LIVE_DIR}/"

    # create loader entry
    cat > "${esp}/loader/entries/proxmox-${kver}.conf" <<- EOF
            title    ${LOADER_TITLE}
            version  ${kver}
            options  ${CMDLINE}
            linux    /${KERNEL_ESP_DIR}/vmlinuz-${kver}
            initrd   /${KERNEL_ESP_DIR}/initrd.img-${kver}
    EOF
done
# [...]

Pro naše účely je podstatná část, která obsahuje příkaz cat: proměnná CMDLINE, která je obsažena na řádku začínajícím options a obsahuje bootovací parametry pro linuxové jádro. Tato proměnná je nastavena ve stejném souboru:

# [...]
if [ -f /etc/kernel/cmdline ]; then
  CMDLINE="$(cat /etc/kernel/cmdline)"
else
  warn "No /etc/kernel/cmdline found - falling back to /proc/cmdline"
  CMDLINE="$(cat /proc/cmdline)"
fi
# [...]

Soubor /etc/kernel/cmdline je místem, kde Proxmox ukládá své bootovací parametry na jediném řádku:

root=ZFS=rpool/ROOT/pve-1 boot=zfs

Po objevení souboru /etc/kernel/cmdline jsem procházel dokumentaci Proxmox a zjistil, že se jedná o to správné místo, kde by měly být upraveny bootovací parametry v tomto případě.

Nyní, když víme, kde provádět změny, jsou dvě změny, které chceme přidat:

  1. chceme se ujistit, že síťová rozhraní se nahodí, abychom se mohli připojit přes SSH do systému, který vytváří initramfs, k tomu použijeme příkaz ip v následujícím formátu (více v této dokumentaci):
        ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>:<ntp0-ip>:
        
    Vynechal jsem vše, co následovalo po autoconf, následující konfigurace mi funguje v pořádku:
        ip=1.2.3.4::1.2.3.1:255.255.255.0:caliban:enpXsY:none:
        
  2. také musíme říci jádru, které zařízení jsou ta, která chceme odemknout, k tomu použijeme proměnnou cryptodevice (ve které použijeme UUID patřičných diskových oddílů):
        cryptdevice=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX cryptdevice=UUID=YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY
        

Celý obsah souboru /etc/kernel/cmdline pak tedy vypadá následovně:

ip=1.2.3.4::1.2.3.1:255.255.255.0:caliban:enpXsY:none: cryptdevice=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX cryptdevice=UUID=YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY root=ZFS=rpool/ROOT/pve-1 boot=zfs

Naším posledním krokem pak bude:

update-initramfs -u -k all
pve-efiboot-tool refresh

Nyní byste se po restartu měli být schopni připojit na SSH port, který jste nastavili pro dropbear. Odtamtud již můžete odemknout pevné disky příkazem:

echo -n "password" > /lib/cryptsetup/passfifo

Tento příkaz musíte zopakovat dvakrát, protože v rpoolu máte dvě bloková zařízení. Případně můžete použít příkaz:

/lib/cryptsetup/askpass "password: " > /lib/cryptsetup/passfifo

Nebo můžete použít skript cryptroot-unlock, který se vás na heslo bude také ptát dvakrát.

Pokud se s dvojitým zadáváním hesla nechcete obtěžovat, můžete také umístit následující skript do /etc/initramfs-tools/hooks a přiřadit mu atribut "executable". V podstatě jsem spojil příkazy uvedené výše se skriptem, který se mi někde povaloval, zdá se, že se jednalo o skript z tohoto GISTu. Jednou se vás zeptá na heslo a pak použije echo, aby jej zapsal do /lib/cryptsetup/passfifo dvakrát (protože používáme dvě bloková zařízení) s jednosekundovým odstupem mezi oběma zápisy, a poté ukončí sezení, aby bootování mohlo pokračovat. Pravděpodobně není příliš bezpečné jej používat, ale mi funguje v pořádku:

#!/bin/sh

PREREQ="dropbear"

prereqs() {
    echo "$PREREQ"
}

case "$1" in
    prereqs)
        prereqs
        exit 0
        ;;
esac

. "${CONFDIR}/initramfs.conf"
. /usr/share/initramfs-tools/hook-functions

if [ "${DROPBEAR}" != "n" ] && [ -r "/etc/crypttab" ] ; then

    cat > "${DESTDIR}/bin/unlock" << EOF
#!/bin/sh
unlock_devices() {
  pw="\$(/lib/cryptsetup/askpass "password: ")"
  echo -n \$pw > /lib/cryptsetup/passfifo
  sleep 1
  echo -n \$pw > /lib/cryptsetup/passfifo
}
if unlock_devices; then
# kill \`ps | grep cryptroot | grep -v "grep" | awk '{print \$1}'\`
# following line kill the remote shell right after the passphrase has
# been entered.
kill -9 \`ps | grep "\-sh" | grep -v "grep" | awk '{print \$1}'\`
exit 0
fi
exit 1
EOF

    chmod 755 "${DESTDIR}/bin/unlock"

    mkdir -p "${DESTDIR}/lib/unlock"
    cat > "${DESTDIR}/lib/unlock/plymouth" << EOF
#!/bin/sh
[ "\$1" == "--ping" ] && exit 1
/bin/plymouth "\$@"
EOF

    chmod 755 "${DESTDIR}/lib/unlock/plymouth"

    echo To unlock root-partition run "unlock" >> ${DESTDIR}/etc/motd
fi

A toto je konec návodu, po jeho aplikaci si můžete užívat nový, šifrovaný Proxmox s možností vzdáleného odemykání šifrovaných disků.

Odkazy a zdroje

Encrypting Proxmox VE 6: ZFS, LUKS, systemd-boot and Dropbear

Další články z této rubriky

VDR a DVB-T2, část 2.
VDR a DVB-T2, část 1.
Šifrovaný Proxmox VE 6: ZFS, LUKS, systemd_boot a Dropbear
MapTiler – proměňte obrázek v zoomovatelnou mapu
Syncthing

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.