Automatické odomykanie LUKS diskov: Clevis, Tang a TPM2 na Linuxe v roku 2026

Nastavte automatické odomykanie LUKS diskov na Linuxe cez NBDE (Clevis + Tang) alebo TPM2 sealing pomocou systemd-cryptenroll. Praktický sprievodca s SSS threshold politikou, evil maid ochranou a rotáciou kľúčov v roku 2026.

LUKS Clevis Tang TPM2: Auto-unlock 2026

Aktualizované: 2. septembra 2026

Automatické odomykanie LUKS diskov na Linuxe v roku 2026 funguje najlepšie cez Network-Bound Disk Encryption (NBDE) pomocou Clevis klienta a Tang servera, prípadne cez TPM2 sealing so systemd-cryptenroll. Server sa po rebootovaní odomkne bez zásahu operátora, ale iba pokiaľ je fyzicky vo vašej sieti (Tang), alebo pokiaľ integrita boot reťazca sedí s uloženými PCR hodnotami (TPM2). Passphrase ostáva ako fallback pre recovery, no nikde na disku ani v initramfse ju v plaintexte nemáte.

  • Clevis a Tang riešia klasický boot-time passphrase problém pre unattended servery bez toho, aby ste tajomstvo písali na disk.
  • Tang je bezstavový server pod ~200 riadkov kódu, ktorý implementuje McCallum-Relyea handshake nad JOSE. Kompromis Tangu neodhalí kľúče iných klientov.
  • TPM2 sealing cez systemd-cryptenroll viaže odomknutie na PCR registre; akákoľvek zmena bootloadera alebo kernelu vyžaduje re-enroll.
  • SSS pin v Cleviso umožní threshold politiky typu „2 z 3" (napr. TPM2 plus dva Tang servery), takže výpadok jedného Tangu neblokuje boot.
  • Passphrase v LUKS keyslote 0 nechajte pre recovery, ale zablokujte ju v crypttab tak, aby sa nepokúšala pri každom boote.
  • Evil maid útok obchádza TPM2 iba pri fyzickom prístupe k neencryptovanému /boot. UKI (Unified Kernel Image) podpísaný Secure Bootom to zmierňuje.

Ako útočník získa dáta z odcudzeného servera

Väčšina serverových LUKS inštalácií, na ktoré som ako pentester narazil, mala celý „hardening" v tom, že root FS bol šifrovaný. Passphrase si operátor pri každom reboote posielal cez SSH konzolu poskytovateľa. Znie to bezpečne. Až kým hardware neskončí u niekoho iného: pri returne do DC, pri výmene disku pod RMA, pri fyzickom odcudzení rack unitu, alebo keď vám hosting predá VM s nesprávne wipe-nutým backing storom.

Prvá vec, ktorú v takom prípade vyskúšam, je forensic image cez dd a následne cryptsetup luksDump. Ak sú aktívne iba pôvodné passphrase keyslots a heslo bolo slabšie ako 12 znakov s bežným charset-om, hashcat mode 29541 (LUKS2 argon2id) ho zlomí na jednej H100 v čase merateľnom na hodiny. Pri LUKS1 (--pbkdf pbkdf2) je to ešte horšie; sha256 iterácie sa pri modernom GPU rozsypú za minúty.

Druhý bežný útok mieri na initramfs. Videl som v produkcii inštalácie, kde operátor zabudol, že si kľúč pre druhý dátový disk uložil ako plaintext súbor do /etc/luks/keys/data.key, ktorý dracut vtiahol do initramfsu. /boot nie je šifrovaný, initramfs sa dá extrahovať z odcudzeného disku bez akéhokoľvek kľúča, a máte kompletný key material. Cieľ NBDE je práve toto: nikdy nemať materiál kľúča na disku vo forme, ktorá dá prístup k datasetu bez ďalšej podmienky.

Prečo je LUKS passphrase pri každom boote problém

LUKS2 header podporuje 32 keyslots, pričom každý drží wrappovaný master key. Passphrase v slot 0 je bezpečná, kým ju nikto neuvidí. Pri hlasovom aj mailovom sprevádzaní inštalácie však uniká pravidelne. „Napíš mi to heslo do Slacku" počúvam bežne aj v teamoch, ktoré majú SSH hardening podľa CIS perfektne rozjaté. Keď máte 40 serverov s rôznymi rolami, ľudský operátor to skončí zjednodušením: rovnaká passphrase, wiki entry, zdieľané tajomstvo.

Druhá vrstva problému je operačná. Nadchádzajúci kernel update cez live patching linuxového jadra odloží reboot, ale skôr či neskôr fyzický reboot príde (napr. mikrokód CPU, memory error), a v ten moment potrebujete človeka pri klávesnici alebo remote console session. Pri kritickej infra to znamená pager v 3:00 ráno. Bol som pri troch takých hovoroch a všetky sa dali dopredu vyriešiť práve NBDE nasadením.

NBDE tento kompromis rozseká: odomknutie sa naviaže na podmienku, ktorú vie vyhodnotiť systém sám (Tang v sieti odpovie, TPM2 sedí s PCR bindingom), ale útočník, ktorý má iba disk, ju nesplní. Kľúč sám o sebe nie je na disku, je v hlave clevis pinu, ktorá potrebuje externý oracle na jeho zloženie.

Čo je NBDE a ako Clevis s Tangom spolupracujú

Network-Bound Disk Encryption stojí na dvoch komponentoch a jednom kryptografickom protokole (McCallum-Relyea handshake) nad JOSE. Podľa projektu Clevis a referenčnej Red Hat dokumentácie k Policy-Based Decryption ide o tieto tri stavebné kamene:

  • Tang server: bezstavový HTTP endpoint (default port 80), ktorý uchováva ECDH keypairs a odpovedá na klientov advertisement a recovery requesty. Nemá databázu, sessions, ani logy o tom, kto sa čo pýtal, pokiaľ to httpd alebo tangd-update nezaznamená explicitne.
  • Clevis: klientský framework s pluginmi („pins") pre tang, tpm2, sss a experimentálne yubikey. Šifruje ephemeral kľúč, ktorý bol vygenerovaný lokálne a zmiešaný cez ECDH s Tangovým verejným kľúčom. Rozšifrovaný kľúč sa na disk nikdy nezapíše, iba metadáta ako URL Tangu a jeho thumbprint.
  • McCallum-Relyea handshake: namiesto klasického key wrappingu klient pošle Tangu blinded verziu svojho ephemeral kľúča, Tang vráti derivat, klient si sám dopočíta symetrický kľúč a ephemeral pár zabudne. Tang teda nikdy nevidí plaintext ani zašifrovaný master key.

Praktický dopad? Kompromitovaný Tang server neodhalí žiadne dáta, ktoré sa už niekedy odomkli. Attacker musí mať súčasne Tang aj šifrovaný disk. Preto Tang bežne dávam do inej sieťovej zóny než sú storage nodes, s nftables pravidlami, ktoré povoľujú prístup iba z konkrétnej VLAN storage clientov.

Nasadenie Tang servera na Linuxe

Tang je jeden z najmenších bezpečnostných daemonov, aký som kedy nasadzoval. Celý zdrojový kód sa dá prečítať za obedovú prestávku a threat model má úprimne jednu vetu: „server, ktorý neublíži, ani keď ho ukradnete". Nasadenie na Fedore, RHEL alebo CentOS Streame:

# RHEL 10 / Fedora 40+
sudo dnf install -y tang
sudo systemctl enable --now tangd.socket

# Overte, že socket počúva
ss -lntp | grep :80

# Pozrite thumbprint (potrebujete ho pri clevis bind)
sudo tang-show-keys 80

Na Debiane alebo Ubuntu (od Debianu 12 a Ubuntu 24.04 je tang v universe):

sudo apt install -y tang
sudo systemctl enable --now tangd.socket

Default konfigurácia bindne na port 80 na všetkých interfaceoch. To takmer nikdy nechcem. Pre production preferujem inline override socketu:

sudo mkdir -p /etc/systemd/system/tangd.socket.d
sudo tee /etc/systemd/system/tangd.socket.d/override.conf <<'EOF'
[Socket]
ListenStream=
ListenStream=10.20.30.5:7500
EOF
sudo systemctl daemon-reload
sudo systemctl restart tangd.socket

A samozrejme firewall. Tang nemá autentifikáciu, jeho jediná ochrana je sieťová dostupnosť:

sudo nft add rule inet filter input ip saddr 10.20.30.0/24 tcp dport 7500 accept
sudo nft add rule inet filter input tcp dport 7500 drop

Rotácia Tang kľúčov

Tang generuje ECDH keypair pri prvom štarte do /var/db/tang. Rotácia je jednoduchá, ale je tu jeden footgun, na ktorý som narazil pri audite u zákazníka:

# Vygenerujte nové kľúče
sudo /usr/libexec/tangd-keygen /var/db/tang

# Presuňte staré do rotated (klienti ich stále vedia použiť pri recovery)
sudo /usr/libexec/tangd-update /var/db/tang

Nikdy staré .jwk súbory nemazajte, kým nemáte istotu, že všetci clienti prešli cez clevis luks report a re-bindovali sa. Tang ich servuje z rotated adresára ako fallback, ale nezobrazuje ich v advertisemente. Nová enrollment ide na aktuálne kľúče, existujúce recovery ešte funguje na staré.

Pripojenie LUKS zväzku k Tangu cez Clevis

Na klientovi (šifrovanom serveri) potrebujete clevis, clevis-luks a clevis-dracut, aby sa binding vtiahol do initramfsu:

sudo dnf install -y clevis clevis-luks clevis-dracut clevis-systemd

Pred bindingom si overte, ktorý zväzok chcete pripojiť, a existujúce keyslots:

lsblk -o NAME,TYPE,MOUNTPOINT,FSTYPE
sudo cryptsetup luksDump /dev/nvme0n1p3 | grep -E 'Keyslot|Token'

Samotný bind (interaktívne požiada o existujúcu passphrase, aby odomkol master key):

sudo clevis luks bind -d /dev/nvme0n1p3 tang \
  '{"url":"http://tang.internal:7500","thp":"tPHYQvJyKZAskJTHvLTdRhWGZ4Kn2G7L5m7z6EXAMPLE"}'

Thumbprint (thp) vyberte z výstupu tang-show-keys. Bez thp Clevis akceptuje advertisement od ľubovoľného Tang servera na URL, čo je bezpečnostný trapfál pre MITM. Nikdy to nevynechajte.

Ak chcete, aby sa zväzok skutočne odomkol pri boote, aktivujte generator:

sudo systemctl enable clevis-luks-askpass.path

# Pridajte _netdev do /etc/crypttab, aby crypttab-generator čakal na sieť
echo 'root UUID=<luks-uuid> none luks,discard,_netdev' | sudo tee -a /etc/crypttab

# Regenerujte initramfs
sudo dracut -f

Overenie po reboote:

sudo clevis luks list -d /dev/nvme0n1p3
# 1: tang '{"url":"http://tang.internal:7500"}'
sudo journalctl -u clevis-luks-askpass.service --since -1h

TPM2 sealing pomocou systemd-cryptenroll

Ak nemáte Tang alebo chcete druhú vrstvu, TPM2 sealing viaže master key na PCR registre základnej dosky. systemd-cryptenroll je preferovaná moderná cesta (od systemd 251+), nahrádza starší clevis-tpm2 workflow a je dobre integrovaná so systemd hardeningom. Oficiálny popis parametrov nájdete v systemd-cryptenroll manuálovej stránke.

Overte, že TPM2 zariadenie existuje a firmware ho exponuje:

ls -l /dev/tpm* /dev/tpmrm*
sudo systemd-cryptenroll --tpm2-device=list

Enroll do LUKS keyslotu s PCR 7 (Secure Boot state) a PCR 11 (UKI):

sudo systemd-cryptenroll /dev/nvme0n1p3 \
  --tpm2-device=auto \
  --tpm2-pcrs=7+11 \
  --wipe-slot=tpm2

Argument --wipe-slot=tpm2 najprv vyčistí staršie TPM2 sloty, aby ste nemali fragmentované enrollmenty pri každom update. Pre re-enroll po kernel update stačí ten istý príkaz, systemd-cryptenroll prepočíta PCR hodnoty a nahradí keyslot.

Odomknutie pri boote nastaví /etc/crypttab:

root UUID=<luks-uuid> none tpm2-device=auto,tpm2-pcrs=7+11,discard

Ktoré PCR registre skutočne vyberať

V produkcii používam iba tie PCRy, ktoré mám pod kontrolou:

  • PCR 0: CRTM/BIOS firmware. Mení sa pri BIOS update, po ktorom potrebujete re-enroll. Zapínam iba na strojoch s pravidelným firmware pipeline.
  • PCR 7: Secure Boot state a signing certifikáty. Rebooty s vypnutým Secure Bootom zlyhajú, čo je presne požadované správanie proti evil maid.
  • PCR 11: Unified Kernel Image measurement. Na Fedore a RHEL s UKI je toto najspoľahlivejšia väzba na konkrétny kernel plus initramfs.
  • PCR 14: MOK (Machine Owner Keys). Užitočné, ak podpisujete vlastné kernel moduly.

PCR 8, 9, 10 (grub, kernel command line, initrd merané cez grub tpm modul) neodporúčam pre bežné workloady. grub-mkconfig ich mení pri každom kernel update a operátor sa dostane do situácie, kedy re-enroll potrebuje passphrase, ktorú medzičasom stratil.

Kombinácia TPM2 a Tangu s SSS threshold pinom

SSS (Shamir's Secret Sharing) pin v Cleviso vám umožní zložiť odomykaciu politiku typu „potrebujem t z n sub-pinov". Táto flexibilita je najsilnejšia stránka NBDE. Na jednom stroji súčasne máte:

  • 2 z 3 kombinácie: TPM2 plus Tang-A plus Tang-B (výpadok jedného Tangu neblokuje boot),
  • 1 z 2 recovery cesty pre disaster scenar,
  • evil maid ochrana cez TPM2 sub-pin, ktorý zlyhá pri zmenenom bootloadere.

Príklad SSS bindingu s threshold 2 z 3:

sudo clevis luks bind -d /dev/nvme0n1p3 sss '{
  "t": 2,
  "pins": {
    "tpm2": {"pcr_ids": "7,11"},
    "tang": [
      {"url":"http://tang-a.internal:7500","thp":"tPHYQvJyKZAskJTHvLTdRh..."},
      {"url":"http://tang-b.internal:7500","thp":"H5EXAMPLEabc123def456..."}
    ]
  }
}'

SSS pin je pre auditníky elegantný, ale nastavovanie thumbprintov v JSON je náchylné na copy-paste chyby. Odporúčam ich mať v Ansible vaulte a šablónovať cez clevis luks bind -d ... -y (auto-accept advertisement) len v izolovanej provision fáze.

Sieť v initramfse pre Tang unlock

Aby Tang binding fungoval z initramfsu, dracut potrebuje sieťový modul aktivovaný pred pokusom o crypttab decrypt. Kernel command line musí obsahovať niečo v štýle:

rd.neednet=1 ip=dhcp
# alebo pre statickú konfiguráciu:
rd.neednet=1 ip=10.20.30.42::10.20.30.1:255.255.255.0::eth0:none

Pri statickom IP nezabudnite na rd.route, ak sa Tang nachádza za routerom mimo priamo pripojeného segmentu.

Rotácia kľúčov a obnova po strate Tangu

Reálny lifecycle NBDE deploymentu má tri opakujúce sa udalosti: Tang rotation (kvartálne alebo pri kompromise), PCR re-enroll (po každom firmware alebo kernel update s dopadom na zvolené PCRs) a disaster recovery (Tang je nedostupný, potrebujete núdzový unlock).

Pri Tang rotation postup zvyčajne vyzerá takto:

# Na Tang serveri: rotate
sudo /usr/libexec/tangd-keygen /var/db/tang
sudo /usr/libexec/tangd-update /var/db/tang

# Na každom klientovi: report a re-bind
sudo clevis luks report -d /dev/nvme0n1p3 -s 1
# Ak vypíše 'Advertisement contains updated keys!', re-bindnite:
sudo clevis luks regen -d /dev/nvme0n1p3 -s 1

Pri kernel alebo firmware update s dopadom na PCR:

sudo systemd-cryptenroll /dev/nvme0n1p3 \
  --tpm2-device=auto \
  --tpm2-pcrs=7+11 \
  --wipe-slot=tpm2

A pre disaster recovery scenár si vždy držte fyzicky offline kópiu recovery passphrase (papier v sejfe, printer bez sieťovej karty). LUKS2 header má max 32 keyslots, jeden nechajte pre --type luks2 --pbkdf argon2id --pbkdf-memory 1048576 vysoko-cost passphrase, ktorú operátor použije iba pri strate celej Tang infra.

Bežné chyby a ochrana pred evil maid útokmi

Toto sú chyby, ktoré vidím opakovane pri pentestingu NBDE inštalácií:

  1. Chýbajúci Tang thumbprint: bind bez thp parametra dôveruje čomukoľvek na URL. Attacker s prístupom do vašej management VLAN vie postaviť rogue Tang a naskriptovať decrypt oracle. Riešenie: thp vždy pevne, žiadny clevis luks bind -y v produkcii.
  2. PCR 8 alebo 9 na strojoch s klasickým GRUBom: po každom kernel update sa PCR zmení a operátor si to všimne v 3:00 ráno, keď server po security update neboot-ne. Riešenie: PCR 7+11 s UKI, alebo automatizovaný re-enroll v post-transaction skripte.
  3. Passphrase keyslot bez rate limitu: LUKS2 header má argon2id, ale ak passphrase je slabá, offline brute-force funguje. Riešenie: passphrase minimálne 4 slová (Diceware), cryptsetup luksAddKey --pbkdf argon2id --pbkdf-memory 1048576 --pbkdf-parallel 4.
  4. Nešifrovaný /boot bez Secure Bootu: evil maid pripojí live USB, upraví /boot/initramfs, pridá keylogger do dracut modulu. Pri ďalšom boote sa vaše heslo alebo PIN loguje na tajnú partíciu. Riešenie: Secure Boot plus shim signed by shim-sbat, PCR 7 v TPM2 enrollmente a najlepšie UKI s vendorovým sbat cert.
  5. Tang na tom istom stroji ako klient: porazí celý bod NBDE. Ak si niekto zoberie box, má disk aj Tang v jednom baleníčku. Riešenie: Tang na separátnom bare-metal boxe alebo aspoň na inom hypervizore.
  6. Reboot bez otestovanej recovery cesty: deploy s clevis luks bind a bez otestovania, či to skutočne odomkne bez zásahu, končí zvyčajne v dracut emergency shelli. Po každom bindingu robte cielený systemctl reboot v maintenance okne.

Ako defence-in-depth kombinujem NBDE s AIDE file integrity monitoringom na /boot, aby som dodatočne detegoval manipuláciu s initramfsom. AIDE beží post-boot z read-only mountu, hash databáza je uložená mimo stroja. Ak sa niekto pohral s /boot, AIDE run to nahlási v prvom cron behu, a ak máte SIEM ako Wazuh, alert dostanete okamžite.

Často kladené otázky

Aký je rozdiel medzi LUKS1 a LUKS2 pri NBDE?

LUKS2 podporuje tokens v headeri, ktoré Clevis využíva na uloženie metadát o bindingu, a defaultne používa argon2id namiesto PBKDF2. LUKS1 s Clevisom funguje, ale metadáta ostávajú iba v keyslote a nedajú sa jednoducho listovať cez clevis luks list. Pre nové inštalácie v roku 2026 vždy LUKS2.

Chráni TPM2 sealing proti evil maid útokom?

Čiastočne. TPM2 s PCR 7 detekuje zmenu Secure Boot stavu, PCR 11 detekuje zmenu UKI. Ak však /boot nie je šifrovaný a Secure Boot je vypnutý alebo v setup mode, útočník vie zmeniť bootloader a re-enroll svoj vlastný TPM2 slot pri nasledujúcom legitímnom prístupe operátora. Reálna ochrana vyžaduje Secure Boot plus signed UKI plus fyzickú kontrolu chassisu (intrusion detection).

Môžem používať Tang aj TPM2 súčasne?

Áno, práve na to slúži sss pin v Cleviso. Threshold t: 2 s TPM2 a Tangom znamená, že server sa odomkne iba ak sedí TPM2 a Tang je dostupný. Threshold t: 1 naopak umožní odomknúť ktorýmkoľvek z nich (užitočné pre high-availability).

Ako riešiť Tang server pre disaster recovery?

Minimálne dva Tang servery v rôznych fault doménach (iný rack, iný napájací okruh, ideálne iná lokalita) s SSS threshold politikou 1 z 2 pre availability alebo 2 z 3 s TPM2 pre bezpečnosť. Kľúče Tangu backupujte offline (encrypted USB v sejfe). Bez Tangu ani jedného clienta v produkcii nedostanete online bez recovery passphrase.

Prečo sa mi server po kernel update nevie odomknúť cez TPM2?

Ak enrollment obsahoval PCR 8, 9 alebo 10, kernel update zmení merania grubom, PCR sa nezhodujú a odomknutie zlyhá. Pre stabilnú prevádzku používajte PCR 7+11 s UKI. Ak už ste v tejto situácii, spustite recovery cez passphrase keyslot a re-enrollnite: systemd-cryptenroll /dev/... --tpm2-device=auto --tpm2-pcrs=7+11 --wipe-slot=tpm2.

Felix Lindqvist
O Autorovi Felix Lindqvist

Penetration tester and OSCP holder. Reverse engineers misconfigured servers for a living and writes about what he finds.