Tutanum Lieve
Introduzione
Per le basi (didattica): Il percorso della didattica.
Per i motivi (discussione): Quali sono le versioni di Tutanum?, Modello di minaccia.
Tutanum Lieve nasce per riutilizzare un computer che si possiede già: un vecchio portatile, un fisso dismesso. È la stessa infrastruttura del Classico, costruita però su hardware che non ha i requisiti per certificare il nodo come sicuro (vedi Quali sono le versioni di Tutanum?).
Non significa che un Lieve sia insicuro. Significa che nella macchina restano parti nascoste, che non si possono ispezionare né togliere del tutto e che potrebbero comprometterne sicurezza e integrità. Il lavoro di questa guida è duplice: ridurre quelle parti quanto si può, e compensare con mitigazioni attorno alla macchina ciò che dentro non si può risolvere.
Il percorso è questo: si valuta il computer, lo si bonifica, si installa il sistema seguendo la guida del Classico con le differenze indicate qui, e si aggiungono le mitigazioni proprie del Lieve. Dove l'hardware non regge FreeBSD direttamente c'è la variante con Proxmox.
Che cosa cambia rispetto al Classico
| Aspetto | Classico | Lieve |
|---|---|---|
| Hardware | Scelto e acquistato apposta | Di recupero, con una storia che non si conosce |
| Firmware | Libero o verificabile | Quasi sempre proprietario (UEFI del produttore) |
| Sottosistemi di gestione | Assenti o neutralizzati | Intel ME o AMD PSP presenti e attivi |
| Radio, microfoni, webcam | Assenti | Presenti: vanno tolti a mano |
| Alimentazione | Gruppo di continuità esterno | La batteria del portatile fa da gruppo di continuità |
| Installazione | Sempre offline | Offline dove possibile; se serve la rete, il minimo indispensabile |
| Fiducia | Il nodo può custodire i segreti più importanti | Il nodo va trattato come potenzialmente osservato dal basso |
| Virtualizzazione | Jail, e bhyve dove serve | Jail; in alternativa Proxmox sotto il nodo, se l'hardware lo richiede |
| Dal sistema operativo in su | Identico: stessi livelli, stesse configurazioni | |
Scegliere il computer di recupero
Per le basi (didattica): Architettura di Neumann, Microarchitettura.
Per i motivi (discussione): CPU, Intel Management Engine e AMD PSP, Single Board Computer.
Non tutti i computer vecchi vanno bene. Prima di iniziare si controlla la macchina contro questa lista.
- Architettura supportata: il processore deve essere supportato da FreeBSD o OpenBSD. Un comune PC a 64 bit lo è.
- Risorse: il riferimento resta 4 core e 4 GB di RAM. Con meno si riduce il numero di jail: Tor, un servizio e l'esca sono il minimo sensato.
- Compatibilità con Libreboot o Coreboot: è la prima cosa da verificare. Se il modello è nell'elenco, il firmware si può sostituire e la macchina si avvicina molto a un Classico (vedi Intel Management Engine e AMD PSP).
- Portatile con batteria estraibile: è la soluzione più semplice per l'alimentazione, e i modelli precedenti al 2013 si aprono senza attrezzi speciali (vedi Alimentazione).
- Rete cablata: serve una porta ethernet. Il Wi-Fi non si usa.
- Disco: attacco SATA, per montare una SSD nuova.
- Lettore ottico: interno o USB, per installare da DVD-R.
Sono da scartare gli smartphone e i tablet: firmware chiuso, batteria fissa, radio sempre attive, nessun interruttore fisico (vedi Smartphone come server Tutanum). Un Raspberry Pi si avvia con firmware proprietario: può essere al massimo un Lieve, mai un Classico (vedi Single Board Computer).
Inventario delle parti nascoste
Per le basi (didattica): Memoria, bus e ingresso/uscita, Architettura di Neumann.
Per i motivi (discussione): Attacchi hardware delle intelligence, Impianti nel firmware, Impianti sulle interfacce.
Prima di toccare qualcosa si prende nota di che cosa c'è nella macchina. È la lista di ciò che andrà tolto, spento o compensato.
| Parte | Perché è un problema | Che cosa si può fare |
|---|---|---|
| Intel ME, AMD PSP | Un computer nel computer, sotto il sistema operativo, con accesso a memoria e rete | Neutralizzare dove possibile, altrimenti isolare dalla rete |
| UEFI proprietario | Non verificabile, bersaglio di rootkit che sopravvivono alla reinstallazione | Sostituire con Libreboot o Coreboot se supportato; altrimenti aggiornare, bloccare con password e installare in modalità BIOS |
| Wi-Fi, Bluetooth, modem cellulare | Canali radio fuori dal controllo del firewall | Rimuovere la scheda |
| Webcam, microfono, altoparlanti | Sensori, e canali di esfiltrazione | Scollegare i connettori |
| Disco esistente | Contiene i dati e forse il malware del passato della macchina | Sostituire con una SSD nuova |
| Porte con accesso diretto alla memoria | FireWire, ExpressCard, Thunderbolt leggono la RAM | Disattivare nel firmware, sigillare |
| CPU datata | Meltdown, Spectre e varianti, con microcodice non più aggiornato | Aggiornare il microcodice, attivare le mitigazioni |
| Tasto di accensione elettronico | La macchina "spenta" resta alimentata | Staccare alimentazione e batteria quando deve essere davvero spenta |
Da un sistema avviato da supporto esterno, o dopo l'installazione, si controlla che cosa la macchina dichiara:
# FreeBSD: c'è un sottosistema di gestione? quali schede di rete e radio?
pciconf -lv | grep -i -B3 -E "management engine|MEI|HECI|AMT"
pciconf -lv | grep -i -B3 -E "network|wireless|bluetooth"
# processore e stato delle mitigazioni
sysctl hw.model vm.pmap.pti hw.ibrs_disable hw.mds_disable hw.spec_store_bypass_disable
Bonifica dell'hardware
Per le basi (didattica): Radiotecnica, Diodi e alimentatori.
Per i motivi (discussione): BIOS e UEFI, Alimentazione, Esfiltrazione via radiofrequenza.
Aprire e togliere
- Staccare tutto: alimentatore e batteria, e tenere premuto il tasto di accensione per scaricare i condensatori.
- Fotografare l'interno prima di toccare, come riferimento per il rimontaggio e per il futuro.
- Rimuovere la scheda Wi-Fi e Bluetooth: di solito un modulo a innesto con due cavetti d'antenna. Rimuovere anche l'eventuale modem cellulare e la SIM.
- Scollegare webcam, microfono e altoparlanti: i connettori sono sulla scheda madre o nel bordo dello schermo.
- Sostituire il disco con una SSD SATA nuova. Il vecchio disco non si riusa nel nodo: va cancellato e distrutto come indicato in Anti-forensics ed emergenza.
- Pulire e controllare: polvere, pasta termica, ventola. Una macchina che scalda in modo irregolare è anche un canale laterale in più.
- Cercare ciò che non dovrebbe esserci: componenti aggiunti, saldature rifatte, moduli sulle porte (vedi Impianti sulle interfacce).
- Richiudere, sigillare e fotografare.
Firmware
Se la macchina è supportata da Libreboot o Coreboot, quella è la strada, e va percorsa seguendo la documentazione del progetto per il modello esatto. In tutti gli altri casi il firmware del produttore resta, e lo si mette nelle condizioni di fare meno danni possibile.
- Aggiornarlo all'ultima versione, scaricata dal sito del produttore sul computer fidato e verificata. È l'unica operazione che richiede di fidarsi ancora del produttore, e si fa una volta sola.
- Impostare una password per la configurazione e per l'avvio.
- Disattivare: avvio da rete (PXE) e da USB, Wake-on-LAN, Intel AMT e ogni funzione di gestione remota, Thunderbolt, FireWire, lettore di impronte, TPM se non lo si usa.
- Attivare la compatibilità BIOS (CSM o Legacy): l'installazione avverrà con tabella GPT in modalità BIOS, evitando UEFI (vedi BIOS e UEFI).
- Ordine di avvio: solo il disco interno, dopo l'installazione.
Per Intel ME esistono due interventi, entrambi per utenti esperti: lo strumento me_cleaner, che
riduce il firmware di ME al minimo necessario all'avvio, e il bit HAP, che gli chiede di spegnersi dopo
l'inizializzazione. Richiedono di leggere e riscrivere il chip del firmware con un programmatore esterno, e
un errore rende la macchina inutilizzabile. Non eliminano ME: ne riducono la superficie. Chi non può
applicarli passa direttamente alle mitigazioni.
Alimentazione e coperchio
Il portatile porta con sé il proprio gruppo di continuità. Perché funzioni da server vanno cambiate due abitudini della macchina: non deve mai sospendersi (in sospensione le chiavi del disco restano in memoria) e non deve reagire alla chiusura del coperchio.
# /etc/sysctl.conf
hw.acpi.lid_switch_state=NONE # chiudere il coperchio non fa nulla
hw.acpi.sleep_button_state=NONE
hw.acpi.power_button_state=S5 # il tasto di accensione spegne, non sospende
# /etc/rc.conf
powerd_enable="YES" # frequenza della CPU regolata sul carico: meno calore, meno consumo
La batteria va controllata: una batteria gonfia si sostituisce subito. Quando il nodo deve essere davvero spento, si staccano sia l'alimentatore sia la batteria.
Installazione
Per le basi (didattica): Sistemi operativi, File system.
Per i motivi (discussione): Distribuzioni, Crittografia.
Si segue la guida del Classico dal livello 2 in poi, con queste differenze.
| Passo del Classico | Nel Lieve |
|---|---|
| Scaricare e verificare l'immagine | Immagine amd64; per le macchine a 32 bit, che FreeBSD non supporta più nelle versioni recenti, si passa a OpenBSD |
| Installazione | Schema di partizionamento "GPT (BIOS)". Se la macchina richiede la rete per completare l'installazione, la si collega per il minimo indispensabile e si prosegue offline |
| Prima configurazione | Si aggiungono le righe per coperchio e alimentazione viste sopra |
| Hardening | Si aggiungono microcodice e mitigazioni della CPU, qui sotto |
| Firewall e DNS | Identico, più il filtro sul router descritto nelle mitigazioni |
| Jail | Identico. Con poca RAM si rinuncia per prime alle jail iop e i2p, mai all'esca |
| Livelli 5, 6 e 7 | Identici |
# microcodice del processore: è software non libero, ma corregge difetti che nessun altro strato può correggere
doas pkg install cpu-microcode
# /boot/loader.conf
cpu_microcode_load="YES"
cpu_microcode_name="/boot/firmware/intel-ucode.bin"
vm.pmap.pti=1 # Meltdown
machdep.hyperthreading_allowed=0 # niente hyper-threading: toglie una famiglia di canali laterali
# /etc/sysctl.conf: mitigazioni per i processori datati
hw.ibrs_disable=0 # Spectre v2
hw.mds_disable=3 # MDS, scelta automatica della mitigazione migliore
hw.spec_store_bypass_disable=2 # Spectre v4
machdep.syscall_ret_flush_l1d=1 # svuotamento della cache L1D: impostazione paranoica, qui giustificata
machdep.mitigations.rngds.enable=1
Le ragioni del microcodice sono in Hardening: le indicazioni di Kicksecure, quelle delle mitigazioni in CPU e in Canali laterali fisici.
Variante con Proxmox
Per le basi (didattica): Memoria virtuale, Processi e thread.
Per i motivi (discussione): Proxmox VE, Namespace, container e jail.
Se FreeBSD non riconosce l'hardware del computer di recupero, o se il nodo deve fare da banco di prova con istantanee e cloni, il Lieve si può costruire sopra Proxmox VE: sotto c'è Linux che parla con il ferro, sopra una macchina virtuale FreeBSD che ospita il nodo Tutanum. Vantaggi, limiti e valori non rispettati sono discussi in Proxmox VE, da leggere prima di scegliere questa strada. Per il Classico non è prevista.
| Conviene | Non conviene |
|---|---|
| FreeBSD non vede la scheda di rete o il disco | FreeBSD gira bene direttamente |
| Almeno 8 GB di RAM e un processore con VT-x o AMD-V | 4 GB di RAM, o nessuna estensione di virtualizzazione |
| Ruolo di banco di prova, esca o nodo ridondato | Il nodo custodisce chiavi importanti |
| Più sistemi diversi sulla stessa macchina | Un solo servizio |
Installare e ridurre
La bonifica dell'hardware resta quella descritta sopra. Poi si installa Debian in forma minima su un volume
cifrato, offline dove possibile, e vi si aggiunge Proxmox seguendo la
documentazione ufficiale della versione corrente: è la fase di
manutenzione, l'unica in cui l'host esce direttamente su Internet. Subito dopo lo si riduce e lo si chiude.
Tutto ciò che segue è stato provato su Proxmox VE 9.2, installato così su Debian 13, con il nodo FreeBSD 15.1
accanto: in questo caso lo storage dei dischi è local, una directory, e non
local-zfs, che esiste solo installando Proxmox su ZFS; per avere le istantanee i dischi si creano
in formato qcow2. Installando invece dall'immagine ISO di Proxmox, il disco è in LVM: local non
accetta dischi di macchine virtuali e si usa local-lvm, LVM-thin, che fa comunque le
istantanee. In quel caso si controllano prima di tutto il resto due cose: il repository di Ceph, che a un
nodo singolo non serve e va disattivato, e la partizione EFI in /etc/fstab. Se manca,
grub-install non trova dove scrivere e gli aggiornamenti del bootloader non arrivano.
findmnt /boot/efi || echo "manca: aggiungere UUID=<della partizione vfat> /boot/efi vfat defaults 0 1"
apt install grub-efi-amd64 && grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=proxmox
mv /etc/apt/sources.list.d/ceph.sources /etc/apt/sources.list.d/ceph.sources.disabled
# nodo singolo: niente cluster né alta disponibilità
systemctl disable --now pve-ha-lrm pve-ha-crm corosync
systemctl disable --now rpcbind.service rpcbind.socket
# niente deduplicazione della memoria tra ospiti (canale laterale): in Proxmox VE 9 ksmtuned non è
# installato di default (pacchetto ksm-control-daemon); se c'è, si spegne, e in ogni caso si controlla
systemctl disable --now ksmtuned 2>/dev/null
cat /sys/kernel/mm/ksm/run # 0: KSM spento
# niente uscite automatiche in chiaro. La procedura ufficiale installa chrony (NTP verso i pool di
# Debian), Debian aggiorna gli indici ogni giorno e pve-daily-update scarica l'elenco dei modelli
systemctl disable --now chrony apt-daily.timer apt-daily-upgrade.timer pve-daily-update.timer
# niente annunci di nomi sulla rete locale (dove Debian usa systemd-resolved: LLMNR sulla porta 5355)
mkdir -p /etc/systemd/resolved.conf.d
printf "[Resolve]\nLLMNR=no\nMulticastDNS=no\n" > /etc/systemd/resolved.conf.d/tutanum.conf
systemctl restart systemd-resolved
# il repository a pagamento: proxmox-ve lo aggiunge da solo, e senza abbonamento risponde 401
echo "Enabled: no" >> /etc/apt/sources.list.d/pve-enterprise.sources
# /etc/default/pveproxy: l'interfaccia web ascolta solo in locale
LISTEN_IP="127.0.0.1"
systemctl restart pveproxy spiceproxy
Poi le difese del kernel e della CPU. Il microcodice è software non libero e sta nel componente
non-free-firmware, che una Debian minimale non ha. Proxmox imposta da sé rp_filter in
modalità lasca, di cui ha bisogno il suo firewall, e lo applica dopo i file di /etc/sysctl.d: lo si
lascia così. I namespace utente restano attivi, perché servono ai container non privilegiati (provato: si
avviano normalmente con tutte le impostazioni qui sotto).
# microcodice e mitigazioni, sull'host
sed -i "s/^Components: main$/Components: main non-free-firmware/" /etc/apt/sources.list.d/debian.sources
apt update && apt install intel-microcode # oppure amd64-microcode
grep -H . /sys/devices/system/cpu/vulnerabilities/* # nessun "Vulnerable"
# /etc/default/grub: niente hyper-threading. Poi: update-grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet nosmt"
# /etc/sysctl.d/99-tutanum.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv4.tcp_timestamps = 0
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1
kernel.unprivileged_bpf_disabled = 1
net.core.bpf_jit_harden = 2
kernel.yama.ptrace_scope = 2
kernel.kexec_load_disabled = 1
kernel.sysrq = 0
fs.protected_symlinks = 1
fs.protected_hardlinks = 1
fs.protected_fifos = 2
fs.protected_regular = 2
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
# /tmp e /dev/shm non eseguono (apt, container e backup funzionano ugualmente)
mkdir -p /etc/systemd/system/tmp.mount.d
printf "[Mount]\nOptions=mode=1777,strictatime,nosuid,nodev,noexec,size=50%%%%,nr_inodes=1m\n" \
> /etc/systemd/system/tmp.mount.d/noexec.conf
echo "tmpfs /dev/shm tmpfs defaults,nosuid,nodev,noexec 0 0" >> /etc/fstab
apt install auditd
Su Debian con il disco cifrato restano in chiaro kernel e initramfs, non solo il piccolo codice di avvio come su
FreeBSD, e non c'è un securelevel che li protegga: chi ha accesso fisico ha un bersaglio più grande. Si mette
una password a GRUB, che lascia avviare il sistema ma non modificare le voci, e si conserva fuori dalla
macchina l'impronta di /boot, da confrontare a ogni controllo.
# GRUB: avvio libero, modifica delle voci solo con la password
grub-mkpasswd-pbkdf2 # copiare l'hash "grub.pbkdf2...."
printf 'set superusers="admin"\npassword_pbkdf2 admin grub.pbkdf2....\n' >> /etc/grub.d/40_custom
sed -i 's/^CLASS="--class gnu-linux --class gnu --class os"/CLASS="--class gnu-linux --class gnu --class os --unrestricted"/' /etc/grub.d/10_linux
update-grub
# l'impronta di /boot, da portare sul computer fidato e confrontare
find /boot -type f -exec sha256sum {} + | sort -k2 > boot.sha256
Il firewall dell'host è quello di Proxmox. Va scritto con attenzione, perché fa due cose che non si vedono:
accetta in automatico, dall'insieme management, le porte 22, 8006, 3128, 5900-5999 e
60000-60050, e in quell'insieme mette tutta la rete locale riconosciuta. Una regola come "SSH solo dal
computer di amministrazione" da sola quindi non basta (provato: pve-firewall compile mostrava
ancora l'intera 192.168.178.0/24). La rete locale si ridefinisce con l'alias local_network. In
uscita il criterio è quello del nodo: l'host non esce da solo, e per aggiornamenti e ora usa il SOCKS di Tor
del nodo (vedi qui sotto).
# /etc/pve/firewall/cluster.fw
[OPTIONS]
enable: 1
policy_in: DROP
policy_out: DROP
[ALIASES]
local_network 192.168.178.10 # "rete di gestione" = il solo computer di amministrazione
[IPSET management]
192.168.178.10
[RULES]
IN SSH(ACCEPT) -source 192.168.178.10
OUT ACCEPT -dest 192.168.178.3 -p tcp -dport 59353 # il SOCKS di Tor del nodo, e nient'altro
# con più computer di amministrazione: l'alias contiene un solo indirizzo, l'insieme tutti
# [ALIASES] local_network 192.168.178.10
# [IPSET management] 192.168.178.10 192.168.178.11
# [RULES] una riga IN SSH(ACCEPT) per ciascuno
pve-firewall compile | grep "add PVEFW-0-management" # soltanto 192.168.178.10
pve-firewall status # enabled/running
Il firewall richiede il kernel di Proxmox: con il kernel di Debian manca il modulo per i bridge e le regole non
vengono mai caricate (provato: pve-firewall status resta su "pending changes"). Dopo
l'installazione si riavvia, e uname -r deve finire con -pve.
Sull'host Debian valgono poi le stesse scelte del Classico tradotte per GNU/Linux: doas al posto di
sudo, sshguard (con il backend per nftables) contro la forza bruta, un messaggio di accesso che non
dice nulla del sistema (vedi Configurare doas.conf,
Difesa dalla forza bruta e Il messaggio di
accesso). sshd si configura come nel Classico, con le righe in cima al
file, ListenAddress 192.168.178.2 e la verifica con sshd -T. Con una differenza:
l'interfaccia web si raggiunge solo con un tunnel SSH, e il AllowTcpForwarding no del Classico lo
impedirebbe. Sull'host Proxmox si apre il solo inoltro locale, e soltanto verso la porta dell'interfaccia.
# /etc/ssh/sshd_config dell'host Proxmox, in cima: al posto di AllowTcpForwarding no
AllowTcpForwarding local
PermitOpen 127.0.0.1:8006
L'interfaccia web si raggiunge solo attraverso SSH, con un utente proprio e il secondo fattore. Il ruolo
PVEVMAdmin gestisce macchine e container ma non utenti e permessi; root@pam resta
per le operazioni sull'host, e riceve anch'esso un secondo fattore.
# un utente di amministrazione nel realm di Proxmox, con un ruolo limitato
pveum user add operatore@pve --password # chiede la password: serve un terminale
pveum acl modify / --users operatore@pve --roles PVEVMAdmin
# senza terminale (da uno script) pveum si ferma su --password: si usa l'API locale
# pvesh create /access/users --userid operatore@pve --password "$PASSWORD"
# secondo fattore TOTP: segreto in base32, lo stesso inserito nell'app sul telefono
pvesh create /access/tfa/operatore@pve --type totp --description telefono \
--totp "otpauth://totp/pve:operatore@pve?secret=<SEGRETO>&issuer=pve" --value <CODICE ATTUALE>
# dal proprio computer: poi si apre https://127.0.0.1:8006
ssh -L 8006:127.0.0.1:8006 operatore@192.168.178.2
Provato: con la sola password il ticket non concede alcun permesso, un codice sbagliato è respinto e solo il codice giusto apre la sessione.
Uscite: soltanto attraverso il nodo
Dopo la fase di manutenzione l'host Proxmox non ha più accesso diretto a Internet: aggiornamenti, ora e modelli passano dal SOCKS di Tor del nodo. Il SOCKS però sta in una jail dentro la macchina virtuale, quindi il nodo gli apre una sola porta sul proprio indirizzo, e soltanto per l'host.
# /etc/pf.conf del nodo
pve = "192.168.178.2" # l'host Proxmox (nella sezione delle macro)
# nella sezione di traduzione
rdr on $ext_if inet proto tcp from $pve to ($ext_if) port $tor_socks -> $j_tor port $tor_socks
# nella sezione di filtro, prima di "Verso Internet"
pass in quick on $ext_if inet proto tcp from $pve to $j_tor port $tor_socks keep state
# /usr/local/etc/tor/torrc (nella jail tor): anche Tor accetta l'host
SocksPolicy accept 10.0.0.2, accept 10.0.1.0/24, accept 192.168.178.2, reject *
# sull'host Proxmox: apt attraverso Tor (Debian e Proxmox)
printf 'Acquire::http::Proxy "socks5h://192.168.178.3:59353";\nAcquire::https::Proxy "socks5h://192.168.178.3:59353";\n' \
> /etc/apt/apt.conf.d/90tutanum-tor
apt update
Con chrony spento, l'ora arriva come sul nodo: la mediana dell'intestazione Date di tre onion
service, attraverso lo stesso SOCKS. Su Linux non c'è il limite del securelevel e l'orologio si corregge in un
passo (provato: spostato indietro di due minuti, torna in pari).
#!/bin/sh
# /usr/local/sbin/ora-da-tor (host Proxmox): mediana dell'ora di tre onion service, attraverso il nodo
P=socks5h://192.168.178.3:59353
ora=$(for o in primo.onion secondo.onion terzo.onion; do
d=$(curl -sI --max-time 60 -x $P "http://$o/" | sed -n 's/^[Dd]ate: //p' | tr -d '\r')
[ -n "$d" ] && date -u -d "$d" +%s
done | sort -n | sed -n 2p)
[ -n "$ora" ] || { echo "meno di due fonti: nessuna correzione" >&2; exit 1; }
scarto=$(( ora - $(date +%s) ))
echo "scarto: ${scarto} s"
if [ "${scarto#-}" -gt 5 ]; then
date -s "@$ora" > /dev/null
command -v hwclock > /dev/null && hwclock --systohc # util-linux-extra, se c'è
fi
pveam scarica soltanto direttamente, quindi i modelli dei container si prendono con curl attraverso
il nodo, verificando prima la firma dell'indice con la chiave di rilascio di Proxmox e poi l'impronta del
modello.
P=socks5h://192.168.178.3:59353; B=http://download.proxmox.com/images
curl -x $P -O $B/aplinfo-pve-9.dat -O $B/aplinfo-pve-9.dat.asc
gpgv --keyring /usr/share/doc/pve-manager/trustedkeys.gpg aplinfo-pve-9.dat.asc aplinfo-pve-9.dat
grep -A20 "^Package: alpine-3.24-default" aplinfo-pve-9.dat | grep -E "^(Location|sha512sum):"
curl -x $P -o /var/lib/vz/template/cache/alpine-3.24-default_20260714_amd64.tar.xz \
$B/system/alpine-3.24-default_20260714_amd64.tar.xz
sha512sum /var/lib/vz/template/cache/alpine-3.24-default_20260714_amd64.tar.xz # = sha512sum dell'indice
Provato con il firewall attivo: sulla porta verso Internet dell'host non esce alcun pacchetto, l'unica
destinazione è il SOCKS del nodo, e i tentativi di uscita diretta (HTTPS, DNS, NTP, pve-daily-update)
vengono scartati.
Due reti
Una rete collega alla porta fisica, l'altra esiste solo dentro la macchina. Sulla prima sta il nodo Tutanum, sulla seconda tutti gli altri ospiti, che così escono soltanto attraverso di lui.
Gli indirizzi sono quelli del Classico: nella zona del nodo, 192.168.178.0/24, il router è
.1, l'host Proxmox .2, il nodo Tutanum .3 e il computer di
amministrazione .10.
# /etc/network/interfaces
auto vmbr0 # verso il router: host Proxmox (.2) e nodo Tutanum (.3)
iface vmbr0 inet static
address 192.168.178.2/24
gateway 192.168.178.1
bridge-ports enp3s0
bridge-stp off
bridge-fd 0
auto vmbr1 # rete interna: nessuna porta fisica
iface vmbr1 inet manual
bridge-ports none
bridge-stp off
bridge-fd 0
La macchina virtuale del nodo
# immagine di FreeBSD, verificata come nel Classico, in /var/lib/vz/template/iso/
qm create 100 --name nodo --ostype other --machine q35 --bios seabios \
--memory 4096 --cores 2 --cpu host \
--scsihw virtio-scsi-single --scsi0 local:32,format=qcow2,discard=on,ssd=1 \
--net0 virtio,bridge=vmbr0,firewall=1 \
--net1 virtio,bridge=vmbr1,firewall=1 \
--ide2 local:iso/FreeBSD-RELEASE-amd64-dvd1.iso,media=cdrom \
--onboot 1
# meno dispositivi emulati, meno codice di QEMU esposto all'ospite
qm set 100 --balloon 0 --tablet 0 --agent 0 --vga serial0 --serial0 socket
qm start 100
Con il disco su local-lvm (installazione da ISO) la riga del disco diventa
--scsi0 local-lvm:32,discard=on,ssd=1. Senza scheda video, con --vga serial0, tutto
passa dalla console seriale, che si apre dall'interfaccia web o con qm terminal 100: anche il
BIOS della macchina virtuale scrive lì, e lì compare la richiesta della passphrase di GELI (provato). Il
programma di installazione di FreeBSD però usa lo schermo: al menu del loader si sceglie "Escape to loader
prompt" e si scrive set console=comconsole e poi boot; sul sistema installato
console="comconsole" va in /boot/loader.conf. Ogni volta che l'host si riavvia il
nodo si ferma sulla passphrase, e finché non la si inserisce l'host resta senza uscite: è il prezzo del disco
cifrato.
qm terminal 100 # dall'host: la console seriale del nodo (Ctrl+O per uscire)
# GELI Passphrase for disk0p3: <- la si digita qui, a ogni avvio
firewall=1 sulla scheda non basta: senza un file per la macchina virtuale con enable: 1
le regole per lei sono zero (provato). Il filtro in ingresso resta a pf, dentro il nodo; quello di Proxmox serve
a impedire che la macchina usi un indirizzo MAC o IP diverso dal suo, cioè che un ospite compromesso si finga
il nodo. Lo stesso vale per ogni container sulla rete interna.
# /etc/pve/firewall/100.fw
[OPTIONS]
enable: 1
ipfilter: 1
macfilter: 1
policy_in: ACCEPT # l'ingresso lo filtra pf, dentro il nodo
policy_out: ACCEPT
[IPSET ipfilter-net0] # gli unici indirizzi che il nodo può usare
192.168.178.3
[IPSET ipfilter-net1]
10.0.1.1
Dalla console della macchina virtuale si segue la guida del Classico dal passo dell'installazione, con queste differenze.
- Avvio in modalità BIOS (
seabios), coerente con la scelta "GPT (BIOS)". - Cifratura anche dentro l'ospite: il disco della macchina virtuale si cifra comunque con GELI, così che i suoi backup siano cifrati ovunque finiscano.
- Interfaccia di rete: si chiama
vtnet0anzichéem0: inpf.confbasta cambiare la macroext_if. La seconda,vtnet1, è la rete interna per gli altri ospiti: il nodo ne è il router e li fa uscire soltanto attraverso Tor. - Microcodice e mitigazioni della CPU: si applicano sull'host Proxmox, non nell'ospite.
- Niente MAC casuale:
ether randomdel Classico è incompatibile con ilmacfilterdi Proxmox, che lascia passare soltanto il MAC assegnato alla scheda: con un MAC nuovo a ogni avvio il nodo resterebbe isolato. L'indirizzo lo vede comunque solo il router di casa. - Il DNS passa da Tor: come indicato nelle mitigazioni, quindi in
pf.confle due righe che lasciano uscire dnscrypt-proxy (user 978) si commentano: l'host del nodo non ha più alcuna uscita propria.
# /etc/rc.conf del nodo: le due schede (niente "ether random")
ifconfig_vtnet0="inet 192.168.178.3/24"
ifconfig_vtnet1="inet 10.0.1.1/24"
# /etc/pf.conf del nodo, nella sezione delle jail: gli ospiti usano soltanto il SOCKS di Tor.
# Niente NAT e niente gateway_enable: tutto il resto cade nel default-deny.
pass in quick on vtnet1 proto tcp from 10.0.1.0/24 to $j_tor port $tor_socks keep state
- Jail, Tor, I2P, servizi e difesa: identici al Classico, dentro la macchina virtuale.
Istantanee, backup e altri ospiti
qm snapshot 100 prima-aggiornamento # prima di ogni aggiornamento del nodo
qm rollback 100 prima-aggiornamento # se qualcosa va storto
qm clone 100 101 --name prova --full # un clone su cui provare, da tenere sulla rete interna
# backup cifrato prima ancora di toccare il disco: la chiave privata non sta sull'host
vzdump 100 --mode snapshot --compress zstd --stdout | age -r <chiave-pubblica> > nodo-$(date +%F).vma.zst.age
# un container solo per servizi interni e sacrificabili: sempre non privilegiato, sempre sulla rete interna
# (il modello si scarica attraverso il nodo, vedi "Uscite: soltanto attraverso il nodo")
pct create 200 local:vztmpl/alpine-3.24-default_20260714_amd64.tar.xz --unprivileged 1 \
--memory 256 --net0 name=eth0,bridge=vmbr1,ip=10.0.1.20/24,gw=10.0.1.1,firewall=1
pct config 200 | grep -c nesting # 0: niente container annidati
# /etc/pve/firewall/200.fw: il container usa soltanto il suo indirizzo
[OPTIONS]
enable: 1
ipfilter: 1
macfilter: 1
[IPSET ipfilter-net0]
10.0.1.20
Tutto ciò che è esposto verso l'esterno sta in una macchina virtuale, mai in un container. Il clone di prova
va rigenerato nelle sue identità (chiavi SSH, chiavi degli onion service, destinazioni I2P) prima di essere
acceso in rete: due nodi con le stesse chiavi si tradiscono a vicenda. Provato: il backup passato in
age si decifra e restituisce l'archivio della macchina; il container gira con il profilo AppArmor
di Proxmox in modalità enforce.
Un'applicazione che non entra in una jail
Non tutto il software sta in una jail FreeBSD. Un'applicazione distribuita come insieme di container
Linux (più servizi che cooperano, un fornitore di identità, uno o più database, un
proxy davanti) non gira né in una jail né sotto il Linuxulator: le servono un kernel Linux e un
motore di container (Docker o podman). Il Lieve la ospita come ogni altro ospite interno: una
macchina virtuale propria sulla rete vmbr1, senza uscita se non il SOCKS di Tor del
nodo, raggiungibile da fuori solo come eepsite I2P (o come onion). Vale la regola già vista:
ciò che è esposto sta in una macchina virtuale, mai in un container, e nessun ospite parla con
il nodo — è il nodo a interrogarli.
La disciplina è quella dell'officina: l'ospite non ha un gateway predefinito, scarica immagini e
aggiornamenti soltanto attraverso il proxy Tor del nodo (il motore di container si configura con quel
proxy), e aggiorna tirando dal proprio repository, mai ricevendo una spinta. I segreti che
l'applicazione genera al primo avvio (file .env, chiavi, password dei database) restano sulla
macchina virtuale e si salvano anche fuori, come per il nodo. Un'applicazione del genere pesa: l'host deve
avere RAM a sufficienza (un fornitore di identità e due database non stanno in poche centinaia di
MiB), altrimenti conviene rimandarla o ridisegnarla in servizi nativi nelle jail.
# sull'host Proxmox: una VM Linux per l'applicazione, sulla rete interna, senza uscita propria
qm create 103 --name applicazione --memory 8192 --cores 2 \
--net0 virtio,bridge=vmbr1,firewall=1 --scsihw virtio-scsi-single --ostype l26
# nell'ospite (Debian): indirizzo interno, nessun gateway, rotta verso le jail attraverso il nodo, IPv6 spento
# 10.0.1.3/24 ; ip route add 10.0.0.0/24 via 10.0.1.1 ; il motore di container con proxy 10.0.0.2:59353
Sul nodo bastano due regole oltre a quella, già presente, che fa uscire gli ospiti da Tor: il nodo
deve poter interrogare l'ospite (per l'officina è lo scambio su SSH; vedi
la messa in opera dell'officina nel Classico), e la jail
i2p deve poter raggiungere il proxy dell'applicazione perché un tunnel di i2pd lo
pubblichi. Il nodo instrada tra la rete interna e quella delle jail, quindi serve
gateway_enable="YES" in rc.conf.
# /etc/pf.conf del nodo: scambio verso l'ospite ed esposizione dell'applicazione su I2P
app = "10.0.1.3"
# il nodo interroga l'ospite (officina: comando imposto; applicazione: lo si tira in aggiornamento)
pass out quick on vtnet1 proto tcp from (vtnet1) to $app port 22 keep state
# la jail i2p raggiunge il proxy dell'applicazione: un tunnel server di i2pd lo rende un eepsite
pass out quick on vtnet1 proto tcp from $j_i2p to $app port 8080 keep state
# /usr/local/etc/i2pd/tunnels.conf nella jail i2p: l'applicazione diventa un eepsite
[applicazione]
type = server
host = 10.0.1.3 # la VM sulla rete interna
port = 8080 # il proxy dell'applicazione
keys = applicazione.dat
inport = 80
La parte amministrativa dell'applicazione, se c'è, resta protetta dal suo stesso fornitore di
identità o da un auth_basic davanti al proxy: un eepsite non è pubblico solo
perché è raggiungibile. E poiché dietro un operatore domestico si finisce spesso sotto
CGNAT (nessun indirizzo pubblico proprio), l'ingresso diretto dall'esterno non è comunque possibile:
Tor e I2P non ne hanno bisogno — i primi raggiungono il nodo con un rendez-vous in uscita, i secondi
attraverso gli introducer — mentre un inoltro di porta sul router di casa non servirebbe a
nulla.
Pi-hole per la rete di casa
Per le basi (didattica): Applicazioni e web, La rete internet.
Per i motivi (discussione): Pi-hole, I limiti.
Un computer di recupero è il posto giusto per Pi-hole, il filtro DNS che protegge i dispositivi di casa da
pubblicità, tracciamento e telemetria. Che cosa fa, che cosa non fa e quali valori del progetto non rispetta è
discusso in Pi-hole. Richiede GNU/Linux: si installa su un Lieve dedicato con
una distribuzione minima, oppure in una macchina virtuale della variante con Proxmox,
collegata a vmbr0 perché deve servire la rete locale. Per il solo nodo basta la lista di blocco
di dnscrypt-proxy descritta nel Classico.
Installare
Pi-hole serve la rete di casa, che è separata dalla zona del nodo: negli esempi la rete di casa è
192.168.1.0/24 con Pi-hole in 192.168.1.4, il nodo resta in 192.168.178.3. Tra le due
zone il router lascia passare una sola cosa, il DNS da Pi-hole al nodo; se Pi-hole è una macchina virtuale
della variante con Proxmox, vale lo stesso al contrario, con il router che lascia arrivare a Pi-hole soltanto
il DNS della rete di casa. Non si usa lo script passato direttamente alla shell: si scarica un rilascio
preciso, lo si controlla e solo allora si esegue.
git clone --depth 1 --branch <rilascio> https://github.com/pi-hole/pi-hole.git && cd pi-hole
git rev-parse HEAD # l'hash, da confrontare con quello del rilascio su un altro canale
# la firma del commit, se c'è, è spesso quella di GitHub (chiave B5690EEEBB952194, i merge fatti dal sito):
# dice che il commit è passato da GitHub, non chi l'ha scritto
less "automated install/basic-install.sh" # leggere ciò che sta per girare come root
sudo bash "automated install/basic-install.sh"
pihole setpassword # password dell'interfaccia web
Configurare
# a monte c'è il dnscrypt-proxy del nodo, mai il resolver del provider
pihole-FTL --config dns.upstreams '["192.168.178.3#53"]'
# risponde solo alla rete locale
pihole-FTL --config dns.listeningMode LOCAL
# l'interfaccia web ascolta solo sulla macchina stessa: la si raggiunge con un tunnel SSH
pihole-FTL --config webserver.port '127.0.0.1:8080'
# il registro delle richieste: una delle due
pihole-FTL --config misc.privacylevel 3 # solo filtro: nessun dettaglio registrato
pihole-FTL --config database.maxDBdays 3 # sensore: dettaglio conservato per tre giorni
systemctl restart pihole-FTL # nella prova il nuovo livello di privacy valeva solo dal riavvio
# liste: quelle predefinite più i domini malevoli raccolti dal nodo
pihole-FTL sqlite3 /etc/pihole/gravity.db \
"INSERT INTO adlist (address, enabled, comment) VALUES ('file:///etc/pihole/ioc-domini.txt', 1, 'IOC del nodo');"
pihole -g # ricompila le liste
Sul nodo, dnscrypt-proxy ascolta anche sull'indirizzo della rete locale e pf lo apre soltanto a
Pi-hole: è l'unica eccezione alla regola "nessun servizio sull'host".
# dnscrypt-proxy.toml del nodo
listen_addresses = ['127.0.0.1:53', '10.0.0.1:53', '192.168.178.3:53']
# /etc/pf.conf del nodo, nella sezione dell'host
pass in quick on $ext_if proto { tcp, udp } from 192.168.1.4 to $nodo port domain keep state
I comandi sono stati provati su Pi-hole 6.4.3 (FTL 6.7.1) in Debian 13: le cinque chiavi vengono accettate,
l'interfaccia web ascolta soltanto su 127.0.0.1:8080, la lista locale file:// entra
nella compilazione e i suoi domini rispondono 0.0.0.0. Con versioni diverse vanno confrontati con
la documentazione. Il file
ioc-domini.txt arriva dal nodo con iop, come gli altri
indicatori (vedi Integrare iop).
Impedire di scavalcarlo
Il router distribuisce via DHCP l'indirizzo di Pi-hole come unico DNS. Ma un dispositivo può ignorarlo, quindi il router deve anche dirottare e bloccare.
# sul router (pf)
pihole = "192.168.1.4"
nodo = "192.168.178.3"
table <doh> persist file "/etc/pf.doh" # indirizzi dei server DoH noti: lista da aggiornare
table <dns_ammessi> const { $pihole } # le negazioni si scrivono con una tabella
# ogni richiesta DNS che non viene da Pi-hole finisce comunque a Pi-hole
rdr on $lan proto { tcp, udp } from ! <dns_ammessi> to any port 53 -> $pihole port 53
block in quick on $lan proto { tcp, udp } from ! <dns_ammessi> to any port 853 # DNS su TLS
block in quick on $lan proto tcp from any to <doh> port 443 # DNS su HTTPS
# tra la rete di casa e la zona del nodo passa soltanto il DNS di Pi-hole
pass in quick on $lan proto { tcp, udp } from $pihole to $nodo port 53 keep state
Verificare e usare
| Che cosa | Comando | Risultato atteso |
|---|---|---|
| Un dominio in lista | drill doubleclick.net @192.168.1.4 | 0.0.0.0 |
| Un dominio normale | drill freebsd.org @192.168.1.4 | Risposta, passata dal nodo |
| Il dirottamento | Da un dispositivo: drill doubleclick.net @8.8.8.8 | 0.0.0.0: ha risposto Pi-hole |
| Niente DNS in chiaro verso l'esterno | tcpdump -ni $wan port 53 sul router | Nessun pacchetto |
| Interfaccia web | nmap -p 80,443,8080 192.168.1.4 | Porte chiuse |
| Perché un nome è bloccato | pihole -q nome.example | La lista che lo contiene |
Se Pi-hole è usato come sensore, il suo registro entra nel collettore del nodo: un dispositivo che in un'ora chiede centinaia di nomi inesistenti merita un avviso.
# i dieci dispositivi con più risposte NXDOMAIN nell'ultima ora (reply_type 2 = NXDOMAIN: verificato su Pi-hole 6.4.3, FTL 6.7.1)
pihole-FTL sqlite3 /etc/pihole/pihole-FTL.db \
"SELECT client, COUNT(*) FROM queries WHERE timestamp > strftime('%s','now','-1 hour') AND reply_type = 2
GROUP BY client ORDER BY 2 DESC LIMIT 10;"
Se Pi-hole cade, in casa non si risolve più nulla. La soluzione non è rimettere il DNS del provider, e
nemmeno aprire a tutta la casa il dnscrypt-proxy del nodo, che bucherebbe la zona separata: è
distribuire come secondo DNS un secondo Pi-hole, configurato allo stesso modo.
Mitigazioni aggiuntive
Per le basi (didattica): Il collegamento dati, La sicurezza di rete.
Per i motivi (discussione): Firewall, Attacchi con accesso fisico, Honeypot.
Ciò che non si è potuto togliere dalla macchina si compensa attorno a essa. Il principio è semplice: dare per scontato che sotto il sistema operativo ci sia qualcosa che il sistema operativo non vede, e fare in modo che quel qualcosa non abbia dove andare né molto da prendere.
Rete: filtrare fuori dalla macchina
Il traffico generato da Intel ME non passa dal sistema operativo, quindi pf non lo vede e non lo può bloccare. Il filtro va messo dove ME non arriva.
- Una scheda di rete che ME non controlla: la gestione remota di Intel usa la scheda di rete integrata. Collegando il nodo attraverso una scheda diversa, USB o su slot, e lasciando la porta integrata vuota e disattivata nel firmware, si toglie a ME la sua via d'uscita abituale.
- Default-deny sul router: dal nodo si esce solo verso i propri bridge o guard di Tor. Perché il
corridoio resti così stretto, nel Lieve anche
dnscrypt-proxypassa da Tor (proxy = 'socks5://10.0.0.2:59353',force_tcp = truee, nella sezione[anonymized_dns],routes = []: provato, con i relay attivi ogni richiesta attraverso Tor va in timeout, e Tor nasconde già l'indirizzo; vedi Proxy), e I2P è la prima jail a cui si rinuncia: i suoi peer sono indirizzi qualunque, e ospitarlo allarga il corridoio a tutta Internet. Tutto il resto viene scartato e registrato dal router, non dal nodo. È il principio di corridor descritto in Buone pratiche da Whonix, applicato un passo più fuori. - Zona separata: il nodo sta in una rete propria (DMZ o VLAN) da cui non vede gli altri dispositivi di casa.
- Osservare da fuori: ogni tanto si registra sul router il traffico del nodo con Tor e I2P fermi (e quindi anche il DNS, che passa da Tor). Non deve uscire nulla. Qualunque pacchetto in quel momento viene da sotto il sistema operativo.
# sul router (qui pf), con il nodo in 192.168.178.3: esce solo verso i bridge, il resto è una fuga
nodo = "192.168.178.3"
table <ponti> persist file "/etc/pf.ponti" # i propri bridge, oppure i guard letti dal file state di Tor
pass in quick on $dmz proto tcp from $nodo to <ponti> modulate state
# solo se il nodo ospita I2P: il corridoio si allarga a qualunque indirizzo
#pass in quick on $dmz proto { tcp, udp } from $nodo to any keep state
block in log quick on $dmz from $nodo to any
# prova a servizi fermi: per un'ora non deve comparire alcun pacchetto
tcpdump -ni $dmz host 192.168.178.3 and not arp
Con UseBridges 0 l'elenco <ponti> contiene il guard scelto da Tor, che si
legge nel file state della jail tor e cambia di rado: quando cambia, il router lo
segnala come fuga, ed è il momento di aggiornare l'elenco a mano.
Ruolo: che cosa affidare a un Lieve
Un nodo Lieve non custodisce i segreti che non ci si può permettere di perdere. Si presta invece molto bene ad alcuni ruoli.
- Nodo ridondato: una copia dei servizi su un'altra rete, tenuta allineata con iop. Se cade, non ha nulla che il nodo principale non abbia.
- Esca: un honeypot su hardware di recupero è il suo uso ideale (vedi Honeypot).
- Destinazione di backup: riceve solo copie già cifrate altrove, di cui non possiede la chiave.
- Filtro DNS della rete di casa: Pi-hole, che richiede GNU/Linux e quindi non può stare sul nodo Classico.
- Banco di prova: per provare aggiornamenti e configurazioni prima di portarli sul Classico.
Le chiavi di lungo periodo (firma degli indicatori, identità degli onion service principali, chiavi dei backup) restano su un Classico o fuori linea.
Accesso fisico
- Cifratura del disco e spegnimento vero: con la batteria inserita la RAM resta alimentata più a lungo. In caso di emergenza si staccano alimentatore e batteria (vedi Attacchi con accesso fisico).
- Console: la sessione sulla console si chiude sempre, e la shell si disconnette da sola dopo qualche minuto di inattività.
- Sigilli e fotografie valgono come per il Classico, e contano di più: un portatile si apre in pochi minuti.
Verifica finale
Oltre alla verifica finale del Classico, un Lieve deve superare questi controlli.
| Che cosa | Come | Risultato atteso |
|---|---|---|
| Nessuna radio | pciconf -lv | grep -i -E "wireless|bluetooth" e usbconfig | Nessun dispositivo |
| Nessun sensore | usbconfig, cat /dev/sndstat | Nessuna webcam, nessun ingresso audio |
| Microcodice caricato | dmesg | grep -i microcode | Versione aggiornata all'avvio |
| Mitigazioni attive | sysctl vm.pmap.pti hw.ibrs_active hw.mds_disable_state | Attive |
| Nessuna sospensione | Chiudere il coperchio | Il nodo resta raggiungibile |
| Autonomia | Staccare l'alimentatore | Il nodo resta acceso, e parte un avviso |
| Silenzio a servizi fermi | tcpdump sul router per un'ora | Nessun pacchetto dal nodo |
| Solo con Proxmox: l'host non esce da solo | Sul router, per dieci minuti: tcpdump -ni <porta> host 192.168.178.2 | Soltanto connessioni verso 192.168.178.3, porta 59353 |
| Solo con Proxmox: rete di gestione | pve-firewall compile | grep "add PVEFW-0-management" | Soltanto il computer di amministrazione |
| Solo con Proxmox: secondo fattore | Accesso all'interfaccia web con la sola password | Richiesta del codice TOTP |
| Solo con Proxmox: anti-falsificazione | pve-firewall compile | grep -c tap100i0 | Più di zero regole, tra cui il filtro sul MAC |
| Solo con Proxmox: kernel e servizi | uname -r, systemctl is-enabled chrony pve-daily-update.timer | -pve, e disabled |
| Solo con Proxmox: interfaccia web | Da un altro computer: nmap -p 8006 192.168.178.2 | Porta chiusa |
| Solo con Proxmox: rete interna | Da un ospite su vmbr1, a nodo Tutanum spento | Nessuna uscita |
| Avvio bloccato | Provare ad avviare da USB | Rifiutato, o richiesta della password del firmware |
Quando un Lieve diventa un Classico
La distinzione non è per sempre. Un nodo Lieve si può considerare un Classico quando il firmware del produttore è stato sostituito con Libreboot o Coreboot, il sottosistema di gestione è stato neutralizzato e la catena di avvio si può verificare a ogni accensione. Finché una di queste condizioni manca, restano in vigore tutte le mitigazioni di questa pagina.