Indice

Discussione di Tutanum

Hardware

Hardware

Posizionamento

Per prima cosa bisogna capire se il server lo si vuole posizionare in modo che possa essere spostato facilmente oppure no. Nel caso è consigliato ancorare la struttura con cementi o supporti in acciaio inox resistenti al calore, affinché possa garantire una protezione in caso di furto. Nel caso invece lo si voglia mantenere portatile potrebbe essere conveniente metterlo in un supporto a valigetta, assicurandosi un corretto ricircolo di aria.
Il cammuffaggio è altrettanto importante e seppur sia rilevabile in una stanza grazie a rilevatori di emissioni elettromagnetiche, è importante dare la minor accessibilità possibile a terzi. I dispositivi impiegabili per scovare il server Tutanum in questione sono gli analizzatori di spettro, i dispositivi TEMPEST, i rilevatori RF e i rilevatori EMF.

È possibile inoltre rilevare tali informazioni per via acustica amplificando il segnale acustico emanato dalle CPU o da altri componenti in funzione, filtrando tutti gli altri rumori che fungono da disturbo al segnale, per poi ricostruire, solitamente tramite algoritmi di intelligenza artificiale e decifrare le informazioni raccolte, quasi solitamente criptate. Il nome di questo tipo di attacco è Acoustical Side-Channel Attack. Il metodo più semplice per trovare un server Tutanum rimane quello di verificare dove è agganciato il router risalendo il cavo ethernet, ma a questo si potrebbe trovare rimedio usando un ripetitore nascosto per casa, seppur sia soggetto agli attacchi di tipo elettromagnetico.

Pertanto il rimedio rimane quello di sorvegliare il possibile il server, di cammuffarlo, di non attirare troppa attenzione per quanto riguarda i prossimi livelli e soprattutto di mantenere l'anonimato, così da assicurare una buona continuità dei servizi.

Rete

Il server Tutanum in fase di installazione non deve essere collegato alla rete, in quanto potrebbero esserci delle intercettazioni o delle fughe di dati per mezzo di qualche software spia (spyware) presente sul dispositivo di installazione.
È consigliata infatti un'installazione completamente offline: basta visitare i siti che occorrono (usando un altro dispositivo) e salvarli se necessario, così che l'installazione possa essere condotta in tutta sicurezza.
È vero che Tutanum Lieve potrebbe presentare alcuni problemi per quanto riguarda la fase di installazione essendo il più delle volte, soprattutto per i dispositivi embedded basati su ARM, e pertanto potrebbe richiedere la connessione ad internet per proseguire, ma è importante una volta fatto il minimo indispensabile, procedere ad effettuare le modifiche offline, così che alla prossima riconnessione si possa garantire una migliore sicurezza in termini sia di privacy che di anonimato.

È fortemente sconsigliata la connessione wireless ed è consigliata la disabilitazione sia fisica che virtuale dei dispositivi che vi permettano una connessione, in quanto potrebbero esserci degli spyware che possono andare a sniffare il traffico reti, ricavando informazioni anche sensibili che potrebbero suggerire a terzi sia la vostra posizione, che la possibilità di potere sfruttare qualche vulnerabilità per compromettere il vostro router.
È importante utilizzare un router non fornito dai provider internet, come avviene nella maggior parte dei casi, poiché potrebbero essere presenti dei malware, spyware o configurazioni di dirottamento o di censura (come avviene su alcuni router), ma acquistato dal fornitore o da un distributore fidato.

Per scrupolo potrebbe essere anche utile effettuare il reset del router, solitamente premendo il tasto fisico per tot secondi, posto appositamente sul lato posteriore.

Ci sarebbe anche la possibilità di potere cambiare sistema operativo sul router al fine di garantire una migliore sicurezza, usando per esempio BSDRP o pfSense, verificando comunque a priori la compatibilità con il router stesso, oppure ancora meglio OPNsense che ha meno interessi commerciali e una community migliore. Una buona marca di router potrebbero essere quelli di Fritz!Box (prodotti dall'azienda tedesca AVM), in quanto presentano delle buone prestazioni e funzionalità hardware, anche se purtroppo integrando del firmware proprietario, sostituibile tuttavia con BSDRP, pfSense, OpenWrt, DD-WRT, LibreCMC, o qualsiasi altro firmware funzionante ma libero o aperto (verificarne sempre la compatibilità).

L'alternativa sarebbe osare e andare su prodotti più aperti e liberi come un router autocostruibile: LibreRouter, con LibreRouterOS, distro GNU Linux basata su OpenWRT.

Oppure ancora ci sarebbe l'alternativa di autocostruirsi un router in casa utilizzando un computer (meglio se ARM o RISC-V come vedremo poi, con uno dei sistemi operativi citati in precedenza) dotato di scheda di rete (le Intel sono migliori in quanto a compatibilità e prestazioni, per verificarne la compatibilità è possibile consultare la documentazione della propria scheda madre) con almeno due porte ethernet: una da collegare allo switch (per le connessioni ethernet) e l'altra da collegare al modem (per le connessioni wireless). Un router in fin dei conti è un computer, uno switch e un modem messi insieme, no?

Lasciamo tuttavia aperto questo punto, sulla scelta del router, in quanto potrebbe presentarsi in futuro come un ulteriore prodotto da aggiungere alla documentazione del progetto Tutanum.

Alimentazione

La soluzione più semplice ed efficace è quella di utilizzare, almeno per Tutanum Lieve, dei PC portatili con la batteria facilmente sostituibile: molti PC ormai presentano delle difficoltà non banali per quanto riguarda l'estrazione della batteria, con lo scopo di tenerli sempre accesi, questo è accaduto soprattutto dal 2013 in poi.
In alternativa potrebbe essere fornita una batteria collegata in parallelo ad un banco elettrico attaccato alla rete elettrica di casa, in modo che così la batteria abbia sempre della corrente e funga da UPS, tuttavia è anche vero che un sistema ideale sarebbe un sistema autoalimentato, ma sempre interrotto, di modo che la corrente elettrica non possa essere interrotta. L'interruzione della linea elettrica se condotta da qualche intelligence su aree locali, potrebbe portare per esclusione alla rivelazione della posizione geofisica del server.

Tornando sul server, il tasto di accensione e di spegnimento è ormai, nella maggior parte dei casi, digitale, come avviene per esempio negli smartphone, così che esso funzioni sempre e possa tenere accesi moduli hardware o comunque backdoor che possono compromettere la privacy e l'anonimato.

Tempo

Anche la batteria tampone in realtà fa la sua parte e potrebbe tenere attivi alcuni circuiti o presentare alcune emissioni elettromagnetiche rilevabili esternamente, come presentato nella sezione "Rete", pertanto consigliamo di toglierla e di usare moduli esterni come il DS1307 o il DS3231, alimentati esternamente o direttamente dalla scheda madre o dalla GPIO in caso di single board computer per una maggiore precisione sul timestamp. Le single board come il famoso Raspberry Pi scrivono il timestamp in un file prima di spegnersi e se è connesso ad internet provvede ad aggiornarlo, altrimenti rimane indietro, cosa che richiede pertanto, per progetti offline, un RTC esterno alimentato a batteria. Altre modalità più precise e scientifiche per quanto riguarda la misurazione del tempo, calcoli scientifici a parte da attuare su eventuali esperimenti o moduli da agganciare a Tutanum, riguardano l'implementazione di orologi atomici: un secondo equivale alla durata di 9.192.631.770 oscillazioni della radiazione elettromagnetica emessa dall'atomo dell'isotopo del cesio-133 in ambiente isolato. Il cesio rimane pericoloso da gestire e da maneggiare, pertanto vengono in alcuni casi preferite versioni meno precise ma più economiche, come quella che fa uso del rubidio gassoso: le oscillazioni vengono rilevate in base a dei rilevatori di fotoni, tenendo da conto anche delle latenze e al contempo viene misurato il feedback rispetto ad un oscillatore al quarzo. In altre parole questo sistema è quello di un orologio atomico e sul mercato si possono reperire a cifre intorno ai €2000.
Citiamo per correttezza anche gli orologi a frequenze ottiche (funziona con dei laser impiegati su celle di vapore di iodio) venduti dalla Vector Atomic, più performanti dei più comuni orologi a microonde ma meno precisi degli orologi atomici.

Il tempo come vettore d'attacco

L'orologio non è solo una questione di precisione. La documentazione di Whonix dedica una pagina agli attacchi basati sul tempo e una alla sincronizzazione: un orologio che si sincronizza male, o che lascia trapelare la propria ora, espone il nodo a una famiglia intera di attacchi di deanonimizzazione.

  • NTP è vecchio, in chiaro e non autenticato: un avversario sul percorso può falsificare le risposte, e i difetti dei client NTP sono stati sfruttati per eseguire codice da remoto. Usa UDP, quindi non può nemmeno passare da Tor.
  • Replay: chi riporta indietro l'orologio del nodo può fargli accettare un consenso di Tor scaduto, oppure aggiornamenti e certificati vecchi e vulnerabili.
  • Impronta dell'orologio: ogni quarzo deriva in modo proprio. Se l'ora del nodo trapela sia dal traffico anonimo sia da quello in chiaro, un osservatore passivo collega i due alla stessa macchina.
  • Localizzare un onion service: il carico della CPU scalda il quarzo e ne altera la frequenza. Chi può caricare a comando il servizio nascosto e insieme osservare l'orologio di una macchina candidata, vede le due curve coincidere.

L'ora trapela da quattro punti precisi, e tutti si possono chiudere.

Da dove trapelaChe cosa rivelaContromisura
Timestamp TCPOra al millisecondo e tempo di accensione, in ogni pacchetto Disattivarli, come in Attacchi di rivelazione, oppure farli modulare da pf con scrub reassemble tcp
Timestamp ICMPL'ora del nodo, a chiunque la chieda Non rispondere e scartare la richiesta nel firewall
Numeri di sequenza iniziali TCP (ISN)Il carico della CPU, attraverso il timer che li generaSu Linux il modulo tirdad; su *BSD modulate state di pf, che li riscrive con valori casuali
Client NTPL'ora, e la presenza stessa del nodo, a ogni interrogazione Nessun client NTP classico sul nodo
# FreeBSD, /etc/sysctl.conf net.inet.icmp.tstamprepl=0 # nessuna risposta alle richieste di timestamp ICMP net.inet.tcp.rfc1323=0 # nessun timestamp TCP # /etc/pf.conf block in quick inet proto icmp icmp-type timereq pass out on em0 proto tcp from (em0) to any modulate state # ISN casuali in uscita

Resta da decidere come regolare l'orologio senza NTP. Whonix usa sdwdate, che ricava l'ora interrogando attraverso Tor, su TCP cifrato, alcuni server onion scelti da gruppi indipendenti, e blocca la rete finché non ha finito. Su *BSD lo strumento non esiste, ma il principio si riproduce:

  • Ora attraverso Tor: si legge l'intestazione Date di più onion service indipendenti e si prende la mediana. La precisione è di qualche secondo, e basta: Tor smette di funzionare solo se l'orologio è più di un'ora indietro o di tre ore avanti, e Whonix raccomanda di restare entro mezz'ora.
  • Ora autenticata: dove serve maggiore precisione, ntpd di OpenBSD accetta un vincolo TLS (constraints from) che scarta le risposte NTP incompatibili con l'ora di un server HTTPS, e chrony supporta NTS. Restano traffico UDP in chiaro, visibile al fornitore di rete.
  • Orologio hardware: il modulo RTC esterno descritto sopra riduce quanto spesso serve chiedere l'ora a qualcuno.
# ora da tre onion service, attraverso Tor: si usa la mediana, mai una fonte sola for o in primo.onion secondo.onion terzo.onion; do curl -sI --max-time 60 --socks5-hostname 10.0.0.2:59353 "http://$o/" | sed -n 's/^[Dd]ate: //p' done

Lo script completo, che calcola la mediana e corregge l'orologio tenendo conto del securelevel, è in Tutanum Classico.

Sincronizzazione sicura: NTS, Roughtime e GPS

Il cenno fatto sopra a NTS merita di essere sviluppato, perché Network Time Security (RFC 8915) è oggi il modo più solido per prendere l'ora dalla rete in chiaro senza fidarsi del percorso: un primo scambio su TLS, il cosiddetto NTS-KE sulla porta 4460, autentica il server con un certificato e consegna al client alcune chiavi AEAD e dei cookie opachi, dopodiché lo scambio NTP vero e proprio prosegue su UDP, ma ogni risposta è firmata e verificabile, cosicché un avversario sul percorso riesce a ritardare o a bloccare il traffico senza però falsificare l'ora. Il contenuto resta visibile al fornitore di rete, quindi NTS si addice ai nodi che si affacciano sul web in chiaro, mentre per un nodo che esce solo da Tor, dove UDP non passa, resta valido l'approccio di sdwdate già descritto.

# /usr/local/etc/chrony.conf: ora autenticata da piu' fonti indipendenti server time.cloudflare.com iburst nts server nts.netnod.se iburst nts server nts.sth1.ntp.se iburst nts ntsdumpdir /var/db/chrony/nts # verifica che le fonti siano davvero autenticate: # chronyc -N authdata # Type 15 = AEAD-AES-SIV-CMAC-256; la colonna Cook mostra i cookie residui

Ancora più vicino alla filosofia di Tutanum, che già per l'ora onion prende la mediana di più fonti per non fidarsi di nessuna, è Roughtime (bozza IETF draft-ietf-ntp-roughtime): il client invia un nonce casuale e il server risponde con un timestamp e un raggio di incertezza firmati sulla radice di un albero di Merkle che include quel nonce, dimostrando così in modo crittografico di aver risposto dopo la richiesta, e interrogando una catena di server indipendenti, con la risposta di uno incatenata nel nonce del successivo, un server che mente viene scoperto e lascia per giunta una prova firmata della propria malafede, il che trasforma la fiducia cieca in una verifica distribuita.

Resta il caso dei nodi che ricavano ora e posizione da un ricevitore GPS, tipico delle single board e dei nodi radio con modulo GNSS: il segnale satellitare è debolissimo e privo di autenticazione, quindi un trasmettitore vicino lo sovrasta con un segnale falso e sposta a piacere sia l'orologio sia la posizione dichiarata, attacco che si lega direttamente alla localizzazione per differenza di arrivo vista nella sezione sulle reti radio, dove la marca temporale è tutto.

Mitigazione: non trattare mai il GPS come fonte unica. Un ricevitore che incroci più costellazioni e scarti i satelliti anomali con il T-RAIM, che verifichi l'autenticità del messaggio di navigazione dove è prevista (Galileo OSNMA, QZSS QZNMA) e che sorvegli il guadagno automatico e il rapporto portante/rumore riconosce gran parte degli inganni, mentre un oscillatore disciplinato dal GPS con tenuta autonoma, il GPSDO, continua a fornire l'ora attraverso un filtro di Kalman quando il segnale sparisce o diventa sospetto, e due oscillatori in tenuta che si controllano a vicenda smascherano quello corrotto. In pratica si combina il GPS con l'RTC esterno già descritto e con un'ora di rete autenticata via NTS, confrontando di continuo le fonti.

PoC di verifica: confrontare l'ora del GPS con quella disciplinata via NTS e allarmare quando divergono oltre il raggio atteso, nello stesso spirito del "mai una fonte sola".

#!/bin/sh # Allarme se l'ora del GPS e quella di sistema (disciplinata da chrony/NTS) divergono oltre 2 secondi. gps=$(gpspipe -w -n 5 | sed -n 's/.*"time":"\([^"]*\)".*/\1/p' | tail -1) gps_s=$(date -j -f "%Y-%m-%dT%H:%M:%S" "${gps%.*}" +%s 2>/dev/null) || exit 0 sys_s=$(date +%s) if [ "$(( gps_s > sys_s ? gps_s - sys_s : sys_s - gps_s ))" -gt 2 ]; then logger -t tempo "divergenza GPS/NTS sospetta: possibile spoofing del segnale" fi

Compromissione elettromagnetica

Al fine di proteggerlo da possibili attacchi elettromagnetici, è raccomandato ulteriormente instradare le connessioni esclusivamente via cavo ethernet (possibilmente schermato) proteggendolo così da possibili interferenze elettromagnetiche indesiderate.
La classificazione delle interferenze elettromagnetiche che possono compromettere l'elettronica si possono così classificare:

  • Un EMP (sia esso artificiale e dunque generato da una trasmittente, sia esso generato da un evento naturale come le tempeste solari o sia esso generato da un'esplosione nucleare, quindi un NEMP) è un impulso, quindi ha energia distribuita su un'ampia gamma di frequenze (nel campo delle microonde).
  • Il NEMP è formato dall'interazione di elettroni veloci (provenienti dalla fonte) che interagiscono con il campo magnetico terrestre. L'altitudine ottimale per lo scoppio è di circa 100km, quindi presso il suolo non vanno a formarsi solo campi elettrici o magnetici, ma piuttosto un'onda elettromagnetica che si propaga. Questa onda indurrà correnti e tensioni nei conduttori, e le cose collegate a tali conduttori potrebbero sperimentare tensioni elevate o correnti di iniezione, motivo per cui bisognerebbe implementare un filtro ad hoc.

Per risolvere queste problematiche catastrofiche, si può impiegare una gabbia di Faraday, la quale dovrebbe essere progettata assumendo come modello teorico lo scudo di Faraday. Questo schermo può avere una superficie omogenea e perfettamente conduttiva, oppure può presentare dei fori. Tali fori (la dimensione massima è più importante dell'area) agiscono come filtri passa-alto, quindi massimizzando la schermatura, riducendo al minimo le aperture e le discontinuità dello schermo.
Poiché il NEMP arriva alla superificie di Faraday come un'onda EM che si propaga con un'impedenza nello spazio libero di 377Ω, il componente principale della schermatura è la riflessione della prima superficie, causata dalla massiccia discontinuità dell'impedenza sulla superficie di Faraday. Quindi, una lastra di rame riflette meglio della gomma conduttiva e pertanto massimizza la conducibilità dello schermo. La profondità di penetrazione è altresì importante, ma quasi qualsiasi materiale conduttivo comune in grado di essere fabbricato e di sostenersi avrà così tante profondità di penetrazione che l'assorbimento all'interno dello schermo sarà un fattore di schermatura minore. È possibile costruire la superficie con una rete di bronzo o con un tessuto di rame, ma è importante prestare particolare attenzione all'ossidazione dove ogni filo incrocia un altro: spesso la rete in acciaio (con incroci conduttivi) è una soluzione a lungo termine migliore. La soluzione ulteriormente migliore sarebbe costruirla in acciaio saldato MIG continuo da 6,35mm.
Uno schermo di Faraday è un concetto ideale, mentre nel mondo reale si vanno a proteggere dispositivi fisici che presentano impurità, imperfezioni o rumori di diversa natura. Ogni penetrazione della superficie di Faraday ha il potenziale di potere compromettere completamente tutto lo schermo, quindi ogni penetrazione deve essere progettata con le appropriate tecniche di controllo.
Se ciò che si vuole è una schermatura minimale ma decente per potere conservare qualche apparecchiatura come il nostro server, si può ottenere dagli 80 ai 100 dB di schermatura, avvolgendolo in uno strato o due di alluminio e piegando saldamente le cuciture, tenendo da conto comunque che dovrà essere garantito il passaggio di calore per la refrigerazione del sistema. I modelli militari per NEMP hanno una forza di campo elettrico pari a 50.000 V/m, quindi permettendo anche di raggiungere anche 80 dB di schermatura, producendo solo 5 V/m all'interno dello schermo, e forse solo 0,5 V/m con 100 dB di schermatura elettromagnetica. La maggior parte delle apparecchiature minimali dovrebbero resistere abbastanza bene. Le apparecchiature con marchio CE hanno un po' più di possibilità rispetto alle apparecchiature senza marchio CE nel caso di un'acquisto di gabbie di Faraday, poiché l'Europa richiede test di esposizione di 3 V/m, mentre nazioni come gli Stati Uniti d'America non hanno tale requisito.

Calore e umidità

Al fine di proteggere il server da possibili incendi provenienti dall'esterno è necessario provvedere in primis ad un estintore e in seconda istanza ad un possibile armadio ignifugo IP68 in modo che sia resistente alla polvere, che possa essere immerso in acqua, garantendo oltretutto un sistema di aerazione consistente.

Per raffreddare il sistema è possibile diverse soluzioni, tra cui:

  • Ventola con filtro ai carboni attivi: prende aria dall'esterno ma non garantisce che essa sia fredda o calda e non garantisce che possa trattarsi per esempio di un gas infiammabile.
  • Sistema refrigerante: necessiterebbe di essere alimentato autonomamente e potrebbe subire guasti più frequentemente.
  • Isolamento all'azoto: il server potrebbe essere immerso in una scatola nella quale potrebbe essere ventilato dell'azoto prodotto al momento, così da evitare possibili problemi esplosivi e in modo da potere garantire una refrigerazione a circuito chiuso. L'unico problema è che l'azoto potrebbe portare all'asfissia saturando pertanto una stanza con tale gas a discapito dell'ossigeno, necessario per vivere.
  • Raffreddamento a liquido: necessità che il calore venga asportato con una ventola e per le leggi della termodinamica funzionerebbe fintanto che la stanza nella quale è ospitato il server fosse più fredda rispetto ad esso. Pertanto si renderebbe necessario un sistema refrigerante.

Monitoraggio e difesa

Un nodo Tutanum va osservato di continuo per accorgersi di saturazioni, scansioni e tentativi di DoS prima che diventino un problema. Il monitoraggio si articola su tre livelli:

  • Risorse e rete: uso di CPU, RAM, code e banda con strumenti di base (top, systat, vnstat) e, per i servizi di anonimato, nyx per Tor e la console web di i2pd.
  • Log ed eventi: lettura dei log di sistema e dei contatori del firewall (doas pfctl -s info), insieme ai ban di fail2ban, per distinguere il traffico legittimo dagli abusi.
  • Avvisi fuori banda: inoltrare le notifiche degli eventi critici (saturazione, crash di tor o i2pd, ban ripetuti) su un canale indipendente dal server. Una scelta comoda è XMPP (Jabber), federato e facilmente auto-ospitabile.

Monitoraggio e firewall lavorano insieme: il firewall blocca, il monitoraggio avvisa, e insieme costituiscono la base dell'EDR e del SIEM personalizzati previsti per Tutanum.

Una dashboard unificata

L'obiettivo è avere un unico punto da cui leggere lo stato del nodo. In linea con il software suckless e con la modularità che discende dal KISS, non si costruisce un monolite ma si compongono piccoli strumenti che fanno una cosa sola e la fanno bene, uniti in una sola vista.

Metriche e risorseLog di sistemaIntegrità e auditdHoneypotFeed IOC (MISP)Collettore(SIEM leggero)Dashboard unificata(hub dei servizi)Alerting(fuori banda)
Architettura modulare: strumenti piccoli e indipendenti (metriche, log, integrità, honeypot, feed di threat intelligence) confluiscono in un collettore leggero che alimenta un'unica dashboard e l'alerting fuori banda. Se un tassello cade, gli altri restano.
  • Metriche e risorse: oltre a top, systat e vnstat, per una vista web leggera vanno bene collectd con rrdtool, oppure monit, che in un solo processo controlla i servizi, mostra una paginetta e sa avvisare. Chi vuole più dettaglio può usare netdata disattivandone la telemetria.
  • Log centralizzati: syslogd raccoglie già tutto; per leggerli e correlarli senza uno stack pesante è ottimo lnav, che naviga ed evidenzia i log.
  • Servizi di anonimato: nyx per Tor e la console web di i2pd.
  • Composizione: invece di un cruscotto unico e chiuso, una pagina statica generata da uno script periodico che unisce i numeri chiave, oppure una dashboard da terminale con tmux che affianca gli strumenti.

Un esempio minimale con monit, che controlla un servizio e invia un avviso, e una dashboard da terminale:

# /usr/local/etc/monitrc: controlla tor e avvisa se cade check process tor matching "tor" if not exist then alert if cpu > 80% for 5 cycles then alert set alert tutanum@localhost # dashboard da terminale: tre strumenti affiancati in tmux tmux new-session -d -s cruscotto "nyx" tmux split-window -h "lnav /var/log/messages" tmux split-window -v "top" tmux attach -t cruscotto

Antivirus, EDR e XDR

Le tre sigle indicano tre generazioni della stessa idea: accorgersi che una macchina è stata compromessa e fare qualcosa prima che il danno si allarghi. Su un nodo Tutanum la prima difesa resta la prevenzione (pledge e unveil, securelevel, jail, partizioni noexec), perché riduce ciò che un processo compromesso può fare. Ma la prevenzione prima o poi fallisce, e in quel momento servono due cose: sapere subito che è successo e fermare subito ciò che sta succedendo. Questa sezione descrive come ottenerle con software libero, locale e piccolo.

Prima di tutto, la prevenzione: ciò che si scrive non si esegue

Il rilevamento per firma o per comportamento è una rete di sicurezza, non la prima difesa: un file scritto apposta per non dare nell'occhio, o semplicemente nuovo, la attraversa. La difesa che non dipende dal riconoscere la minaccia è strutturale, ed è il vecchio principio W^X esteso dal singolo processo all'intero filesystem: ciò che un servizio può scrivere non deve poterlo eseguire, e ciò che esegue non deve poterlo scrivere. Un servizio compromesso che non può materializzare ed eseguire un secondo programma è contenuto molto prima che l'antivirus o la sentinella se ne accorgano.

Sull'host del nodo le aree scrivibili da tutti (/tmp, /var/tmp) sono già noexec,nosuid. Nelle jail il principio va esteso a mano, e qui c'è un'insidia emersa provando su FreeBSD 15.1: impostare exec=off sul dataset ZFS non basta, perché le jail gestite da CBSD montano le proprie cartelle con nullfs in lettura-scrittura e senza noexec, e attraverso quel secondo montaggio il file resta eseguibile. La soluzione è dichiarare le opzioni giuste nel file dei montaggi aggiuntivi della jail (fstab.local), che CBSD applica al posto delle righe predefinite:

# /jails/jails-fstab/<jail>/fstab.local: ciò che si scrive non si esegue # eseguibili e configurazione: sola lettura (li cambia solo l'host, aggiornando i pacchetti) /jails/jails-data/<jail>-data/etc /etc nullfs ro 0 0 /jails/jails-data/<jail>-data/usr/local /usr/local nullfs ro 0 0 /jails/jails-data/<jail>-data/compat /compat nullfs ro 0 0 # aree scrivibili dal servizio: mai eseguibili /jails/jails-data/<jail>-data/tmp /tmp nullfs rw,noexec,nosuid 0 0 /jails/jails-data/<jail>-data/var /var nullfs rw,noexec,nosuid 0 0 /jails/jails-data/<jail>-data/home /home nullfs rw,noexec,nosuid 0 0 /jails/jails-data/<jail>-data/root /root nullfs rw,noexec,nosuid 0 0 # poi: cbsd jstop <jail> && cbsd jstart <jail>. Prova dall'interno della jail: # cp /bin/echo /tmp/x && /tmp/x -> Permission denied (exit 126) # touch /usr/local/x -> Read-only file system

Gli aggiornamenti dei pacchetti continuano a funzionare perché si fanno dall'host sulla cartella dei dati (pkg -r /jails/jails-data/<jail>-data), che resta scrivibile; dentro la jail, in esecuzione, quelle stesse cartelle sono in sola lettura. Un servizio che ha bisogno di eseguire file da una sua sottocartella scrivibile (per esempio un ambiente virtuale Python) fa eccezione mirata: quella cartella torna eseguibile ma diventa di sola lettura. I file che arrivano dall'esterno (scaricati dall'esca, ricevuti da altri nodi) atterrano solo nella quarantena, anch'essa noexec, e restano dati. Resta un limite onesto: un interprete già installato (sh, o Python nella jail dell'esca) può ancora leggere ed eseguire uno script che trova in un'area scrivibile; per questo l'eliminazione vera degli eseguibili non previsti richiederebbe veriexec, assente nel kernel GENERIC, e nel frattempo ci si appoggia ai flag schg e al securelevel per gli eseguibili legittimi.

Tre sigle, tre generazioni

  • Antivirus: confronta i file con un elenco di cose già viste (firme e hash). Guarda l'identità di un oggetto: è rapido e preciso, ma cieco davanti a tutto ciò che non è ancora in elenco.
  • EDR (Endpoint Detection and Response): osserva di continuo che cosa fanno i processi (esecuzioni, connessioni, modifiche ai file), riconosce i comportamenti anomali e soprattutto risponde: isola la macchina, ferma il processo, conserva le prove per l'indagine.
  • XDR (Extended Detection and Response): estende la correlazione oltre il singolo endpoint e mette insieme rete, autenticazioni, honeypot e più nodi, così che segnali deboli e separati diventino un unico allarme forte.

I prodotti commerciali fanno bene queste cose, ma a un prezzo che Tutanum non può pagare. Sono chiusi e quindi non verificabili. Inviano la telemetria (processi, nomi di file, connessioni) al cloud del fornitore, che equivale a consegnare a un terzo il diario completo del nodo. E girano nel kernel con i privilegi massimi: sono essi stessi superficie d'attacco e punto singolo di guasto, come ha mostrato l'aggiornamento difettoso di CrowdStrike che il 19 luglio 2024 ha bloccato circa 8,5 milioni di macchine Windows nel mondo. La difesa dell'endpoint, in Tutanum, si costruisce invece componendo strumenti che il sistema possiede già.

Che cosa insegna Whonix

Il progetto Whonix, con la sua base Kicksecure, discute da anni se un sistema votato all'anonimato debba dotarsi di antivirus e di rilevamento delle intrusioni. Le conclusioni, raccolte nella pagina Malware and Firmware Trojans e in alcune discussioni del forum, qui valgono come vincoli di progetto.

  • Uno scanner è superficie d'attacco, e non in teoria: gira con privilegi alti e per mestiere analizza input ostile. Nella discussione Installation of Antivirus Scanners by Default si ricordano exploit che ottenevano i privilegi massimi colpendo proprio l'antivirus. Il criterio che ne esce è netto: uno scanner è accettabile solo se non riferisce a un server remoto, non gira come root e non pesa in modo inaccettabile. Per questo in Tutanum clamd gira come utente non privilegiato in una jail propria, riceve i file per descrittore e scarica le firme attraverso Tor.
  • Meglio chiudere un meccanismo che inseguire le firme: un elenco di file malevoli è la prima cosa contro cui un attaccante prova i propri strumenti. Il controllo d'integrità (AIDE) e la protezione del kernel a runtime (LKRG) eliminano invece intere classi di attacco. Nella discussione su AIDE si riporta che la loro combinazione ha rilevato 14 rootkit su 15 provati. Da qui il peso che questa sezione dà all'allowlist e all'integrità rispetto alle firme.
  • L'integrità senza disciplina è solo rumore: la stessa discussione osserva che dopo un aggiornamento AIDE elenca centinaia di file cambiati, e nessuno sa più distinguere il legittimo dall'ostile. Il controllo va quindi eseguito subito prima di ogni aggiornamento e la base di riferimento rigenerata subito dopo, nella stessa operazione.
  • Su un server l'IDS ha senso, ma non sul traffico: nella discussione su IDS e IPS si nota che questi strumenti si addicono ai server più che ai client, ma che il traffico cifrato o instradato su Tor non si può ispezionare. Su un nodo Tutanum quasi tutto il traffico è Tor o I2P: il rilevamento va fatto sull'host, osservando i processi.
  • Chi osserva sta fuori da chi è osservato: uno scanner dentro la macchina sorvegliata è comodo ma può essere spento dal malware che dovrebbe trovare. In Tutanum la sentinella e le scansioni girano sull'host, fuori dalle jail, che non possono né vederle né fermarle.
  • Nessuno strumento certifica che un sistema è pulito: la pagina di Kicksecure cita Joanna Rutkowska: non esiste un metodo affidabile per stabilire che un sistema non è compromesso. Il malware mirato evita di lasciare tracce evidenti. Il silenzio dell'EDR non è una prova, e dopo una compromissione accertata si ricostruisce, non si ripulisce.

Rilevamento a hash

Il rilevamento a hash risponde alla domanda "questo oggetto è già noto?". Si calcola l'impronta crittografica del file (SHA-256) e la si cerca in un elenco. È il metodo con meno falsi positivi che esista: se l'impronta coincide, il file è quello, senza interpretazioni. Le fonti utili per un nodo Tutanum sono quattro.

  • Firme di ClamAV: il database ufficiale, aggiornato da freshclam. Non è uno scudo per il sistema operativo ma un controllo per ciò che transita: caricamenti, repository, allegati, pacchetti scaricati.
  • Indicatori di compromissione (IOC): gli hash pubblicati dai feed di threat intelligence (MISP, MalwareBazaar) e quelli raccolti dal proprio honeypot. ClamAV li accetta come firme personalizzate, in un file .hsb.
  • Regole YARA: non sono hash ma schemi sul contenuto, e reggono alle piccole variazioni che un hash non tollera. ClamAV le carica dalla stessa cartella delle firme.
  • Allowlist: l'uso inverso, e su un server il più potente. L'insieme degli eseguibili legittimi è piccolo e noto (il sistema di base descritto da mtree, i pacchetti verificabili con pkg check -s): tutto ciò che non vi compare è sospetto per definizione. Su FreeBSD mac_veriexec porta l'idea fino in fondo e rifiuta nel kernel l'esecuzione di ciò che non è in un manifesto firmato, ma richiede un sistema compilato con WITH_VERIEXEC.

Il limite è strutturale: basta cambiare un byte perché l'hash sia un altro. Il malware ricompilato, impacchettato o generato apposta per un bersaglio non è in nessun elenco, e un attacco che usa solo programmi già presenti (una shell, fetch, nc: la tecnica detta living off the land) non introduce alcun file da riconoscere. Contro un avversario mirato, che è quello del modello di minaccia di Tutanum, l'hash da solo ferma i passanti e non chi è venuto apposta.

Rilevamento comportamentale

Il rilevamento comportamentale risponde a un'altra domanda: "questa azione è normale per chi la compie?". Non importa che cosa sia il file, importa che cosa fa il processo. Un server è il terreno ideale, perché il comportamento legittimo è ripetitivo e stretto: un web server legge file e risponde sulla rete, non lancia shell e non scrive in /etc. Le sorgenti degli eventi cambiano con il sistema.

  • FreeBSD: auditd (OpenBSM) registra esecuzioni, connessioni e modifiche, e il dispositivo /dev/auditpipe le offre in tempo reale. DTrace copre ciò che l'audit non vede.
  • Linux: auditd oppure eBPF, con Falco (solo rilevamento) o Tetragon, che può anche uccidere il processo direttamente nel kernel. A questi si affianca LKRG, che verifica a runtime l'integrità del kernel e termina il processo le cui credenziali risultano alterate. È aggirabile per ammissione dei suoi stessi autori, ma costringe a exploit più complessi.
  • OpenBSD: non ha un sottosistema di audit, ma pledge e unveil sono già un blocco comportamentale: il processo che esce da quanto ha promesso viene terminato dal kernel e la violazione finisce nei log. Si aggiunge la contabilità dei processi (accton, lastcomm).

Le regole che valgono per quasi ogni nodo Tutanum sono poche, e ciascuna corrisponde a una tecnica del catalogo MITRE ATT&CK:

  • Shell da servizio (T1059): l'utente di un demone (www, _tor, i2pd, git, iop) esegue un interprete o uno strumento di rete.
  • Esecuzione da cartelle scrivibili: un programma parte da /tmp o /var/tmp.
  • Persistenza (T1543, T1053, T1098.004): modifiche a rc.d, a cron o ai file authorized_keys da parte di chi non è l'amministratore.
  • Moduli del kernel (T1547.006): un kldload fuori dall'avvio.
  • Uscita in chiaro (T1048): una jail di servizio tenta una connessione che non passa da Tor o I2P. La registra il firewall, non l'audit.
  • Cancellazione delle tracce (T1070): troncamento o rimozione dei log.

Il limite qui è opposto a quello dell'hash: il metodo vede anche ciò che è nuovo, ma sbaglia più spesso. Un amministratore che fa manutenzione somiglia a un intruso, e una regola troppo larga genera falsi positivi fino a essere ignorata. Per scrivere regole portabili conviene il formato libero Sigma.

Perché servono entrambi

I due metodi sbagliano in modi diversi, quindi si correggono a vicenda. L'hash dà certezza sull'identità, il comportamento dà copertura sull'ignoto, e la loro combinazione decide quanto energica deve essere la risposta.

Hash del fileComportamentoVerdettoRisposta automatica
Malevolo notoQualsiasiCritico: nessun dubbio sull'identità File in quarantena e jail congelata
SconosciutoSospettoAlto: probabile malware nuovo Jail congelata, file in quarantena
LegittimoSospettoAlto: abuso di strumenti di sistema Jail congelata, il file non si tocca
SconosciutoNormaleMedio: su un server non dovrebbe esistere Solo avviso
LegittimoNormaleNessunoNessuna

La soluzione proposta

L'EDR di Tutanum è fatto di quattro pezzi piccoli, ciascuno sostituibile: un motore a hash (ClamAV con gli IOC locali), un motore comportamentale (uno script che legge il flusso di audit), un punto in cui i due verdetti si incontrano e un unico comando, tutanum-edr, che contiene e rilascia.

File nuovi e modificatiFlusso di auditLog di pf e honeypotMotore a hash(firme, IOC, allowlist)Motore comportamentale(regole sugli eventi)Verdetto(correlazione)Contenimento immediatocongela, isola, quarantenaautomatico e reversibileAnalisi umanaRilascio: falso positivo(hash in allowlist)Eradicazione: minaccia vera(manuale e irreversibile)
L'EDR di Tutanum: due motori leggono le stesse sorgenti, il verdetto li combina e la risposta parte subito, ma solo con azioni reversibili. Cancellare, distruggere e ricostruire restano decisioni umane, così come il rilascio di ciò che si rivela un falso positivo.

Quattro principi tengono insieme il disegno.

  • La jail è l'unità di contenimento: ogni servizio vive in una jail con un proprio indirizzo. Così "bloccare la minaccia" ha un significato preciso (fermare quella jail e tagliarle la rete) e non costringe a spegnere il nodo.
  • In automatico solo ciò che è reversibile: congelare, isolare e mettere in quarantena si possono annullare senza perdite, quindi possono scattare da soli e subito. Cancellare, uccidere e ricostruire non si annullano, quindi li decide una persona.
  • I due motori condividono gli eventi: ogni esecuzione vista dall'audit passa anche dal controllo dell'hash, e ogni file segnalato dall'hash viene messo in relazione con la jail che lo ha scritto.
  • Tutto resta in casa: nessuna telemetria esterna. Gli eventi vanno al collettore, l'avviso parte sul canale fuori banda descritto in Alerting.

Contenimento immediato

Appena il verdetto è alto o critico, la risposta parte senza attendere nessuno. Le azioni sono quattro e ognuna ha una ragione precisa.

  1. Congelare, non uccidere: a tutti i processi della jail viene inviato SIGSTOP, che non può essere intercettato né ignorato. Un processo fermo non cifra, non cancella e non esfiltra, ma la sua memoria resta intatta: chiavi, impianti residenti solo in RAM e connessioni aperte sono ancora lì per l'analisi. Un kill distruggerebbe proprio le prove migliori.
  2. Isolare la rete: l'indirizzo della jail entra nella tabella quarantena di ipfw, che esamina ogni pacchetto e quindi taglia subito anche le connessioni già aperte. Anche se un processo sfuggisse al congelamento, non avrebbe dove andare. La tabella è di ipfw e non di pf perché dal securelevel 2 FreeBSD 15 non accetta più indirizzi nelle tabelle di pf né chiude le connessioni; e perché pf, a differenza di ipfw, lascerebbe proseguire le connessioni stabilite.
  3. Fotografare: un'istantanea ZFS del dataset della jail fissa lo stato del disco in quell'istante. È insieme una prova forense e un punto di ritorno.
  4. Mettere in quarantena i file: il file segnalato viene spostato in un dataset montato con exec=off, con permessi azzerati e accanto una scheda che ne ricorda percorso, proprietario, permessi, hash e motivo. Non può più essere eseguito, ma non è perduto.

Va detto con onestà che su FreeBSD questa risposta arriva dopo l'evento: l'audit registra una chiamata di sistema già avvenuta, e tra l'evento e il blocco passano alcuni millisecondi. Per questo la prevenzione non è sostituibile: /tmp montata noexec rende impossibile ciò che la regola dovrebbe altrimenti inseguire. Su Linux il blocco può invece precedere l'esecuzione, con clamonacc in modalità OnAccessPrevention o con fapolicyd, entrambi basati su fanotify.

Rilascio dei falsi positivi

Un sistema che blocca subito sbaglierà, ed è accettabile solo se l'errore costa poco. Il contenimento reversibile serve a questo: un falso positivo provoca una pausa, non una perdita. Il percorso è sempre lo stesso.

  1. L'avviso arriva con un identificativo: ogni contenimento apre un caso, con la sua scheda. tutanum-edr elenco mostra quelli in attesa.
  2. Si guarda prima di decidere: la scheda dice quale regola è scattata, l'istantanea permette di ispezionare i file senza toccare la jail, procstat mostra i processi fermi.
  3. Rilascio: se era un falso positivo, tutanum-edr rilascia rimette tutto come prima. Per una jail toglie l'indirizzo dalla tabella e invia SIGCONT: i processi riprendono dal punto esatto in cui erano. Per un file verifica che l'oggetto in quarantena non sia stato alterato, lo riporta al suo percorso con proprietario e permessi originali e ne aggiunge l'hash all'allowlist locale (tutanum.sfp), così che non venga segnalato di nuovo.
  4. Eradicazione: se la minaccia è reale, tutanum-edr elimina distrugge la jail, che va poi ricreata da un modello pulito. L'istantanea resta per l'analisi. I segreti che la jail custodiva si considerano bruciati: se era quella di Tor, la chiave dell'onion service va sostituita. L'analisi si svolge dall'host, sull'istantanea, senza mai riavviare la jail compromessa: è la regola che Kicksecure dà per le macchine intere (spegnere, e leggere il disco da un sistema fidato). Se il sospetto riguarda l'host stesso, vale alla lettera: si reinstalla, sapendo che un impianto nel firmware sopravvive anche a quello.

Ogni rilascio è anche una correzione: la regola che ha sbagliato va ristretta con un'eccezione precisa, mai allargata con un'esenzione generica. Per i verdetti di gravità media si può prevedere il rilascio a tempo: ogni voce porta come valore l'ora di inserimento, e un compito di cron toglie quelle più vecchie di un'ora (lo stesso schema delle esche, più sotto). I casi chiusi non si cancellano: restano come registro di chi ha rilasciato che cosa e quando.

Se è compromesso l'host

Il contenimento descritto sopra presume che l'host sia sano e che a cadere sia una jail. Se cade l'host non c'è più nessuno di cui fidarsi, e si applica la procedura di ripristino di Whonix, che parte da un principio: l'hardware è sacrificabile, i dati no.

  1. Tutto ciò che era collegato è compromesso: la macchina, i dischi, le periferiche. Si dà per scontato che ogni dato sia stato copiato e possa essere stato alterato.
  2. La macchina non torna più in rete: si usa soltanto per recuperare i dati, letti da un sistema pulito.
  3. Si riparte da hardware nuovo: acquistato in contanti, perché un impianto nel firmware sopravvive alla reinstallazione.
  4. Si cambia ciò che la macchina conosceva: chiavi degli onion service e delle destinazioni I2P, chiavi SSH, password, e la password della rete locale.
  5. I dati recuperati sono sospetti: riportarli senza precauzioni su un sistema pulito rischia di infettarlo di nuovo. Si recuperano solo i dati, mai gli eseguibili, e si controllano contro le copie di backup precedenti alla compromissione.

Whonix distingue poi il caso in cui a cadere è solo il gateway di Tor: chi lo controlla legge il traffico onion e toglie l'anonimato, ma per entrare negli altri compartimenti gli serve una seconda vulnerabilità. È lo stesso ragionamento che giustifica una jail separata per Tor.

In pratica su FreeBSD

Quanto segue è uno scheletro funzionante da adattare, non un prodotto: poche decine di righe di shell che si leggono in dieci minuti, ed è questo il loro pregio. I percorsi presumono le jail sotto /jails, con i dataset in zroot/jails.

1. Attivare l'audit
# /etc/security/audit_control: cosa registrare dir:/var/audit flags:lo,aa,ex,pc,nt,fm # login, autenticazione, exec, processi, rete, modifica attributi naflags:lo,aa policy:cnt,argv # argv: anche gli argomenti dei comandi eseguiti minfree:5 filesz:2M expire-after:10M # /etc/security/audit_user: più dettaglio sugli utenti dei servizi (creazione e cancellazione di file) www:ex,nt,fc,fd:no _tor:ex,nt,fc,fd:no sysrc auditd_enable=YES && service auditd start praudit -l /dev/auditpipe # il flusso in tempo reale, un evento per riga
2. Il motore a hash

FreeBSD non ha la scansione all'accesso, quindi il controllo avviene in due punti: ai confini, con una scansione frequente delle cartelle in cui entrano file dall'esterno, e all'esecuzione, dentro la sentinella del passo 5.

pkg install clamav jq torsocks sysrc clamav_clamd_enable=YES # niente clamav_freshclam_enable: il demone uscirebbe senza Tor, e pf lo ferma # /usr/local/etc/tor/torsocks.conf: il SOCKS della jail tor TorAddress 10.0.0.2 TorPort 59353 torsocks freshclam # firme ufficiali (firmate), senza rivelare quando ci si aggiorna # clamd gira come utente "clamav", mai come root: --fdpass gli passa i file già aperti # IOC locali: un hash SHA-256 per riga (feed MISP, MalwareBazaar, payload raccolti dall'honeypot) # convertiti in firme ClamAV. "*" = dimensione qualsiasi, 73 = livello minimo del motore. # Con l'elenco vuoto il file non si scrive: clamd rifiuta un .hsb vuoto ("Malformed database", # provato) e non parte. sort -u -o /var/db/ioc/sha256.txt /var/db/ioc/sha256.txt if [ -s /var/db/ioc/sha256.txt ]; then awk '{ print $1 ":*:Tutanum.IOC." NR ":73" }' /var/db/ioc/sha256.txt > /var/db/clamav/tutanum.hsb else rm -f /var/db/clamav/tutanum.hsb fi service clamav_clamd restart # dopo un "clamdscan --reload" le firme nuove valgono solo a ricarica finita # /usr/local/sbin/tutanum-scansione: i punti d'ingresso, da cron ogni pochi minuti clamdscan --fdpass --multiscan --infected --no-summary /jails/*/var/upload /jails/forge/var/db/repo | grep ' FOUND$' | while IFS= read -r riga; do # formato: "/percorso/file: Nome.Firma FOUND" tutanum-edr quarantena "${riga%%: *}" "hash: ${riga#*: }" done
3. Quarantena e regole del firewall
# dataset della quarantena: ciò che contiene non può essere eseguito zfs create -o exec=off -o setuid=off -o mountpoint=/var/quarantena zroot/quarantena chmod 700 /var/quarantena && mkdir -m 700 /var/quarantena/chiusi # /etc/ipfw.rules (già presente): prima di qualsiasi "allow" ipfw -q table quarantena create type addr ipfw -q add 50 deny log ip from 'table(quarantena)' to any not layer2 ipfw -q add 51 deny log ip from any to 'table(quarantena)' not layer2

Le regole valgono per ogni interfaccia, quella delle jail compresa. Provato su FreeBSD 15.1: una connessione già aperta tra due jail continua a passare dopo l'inserimento nella tabella di pf, e si ferma all'istante dopo quello nella tabella di ipfw.

4. Contenere e rilasciare: tutanum-edr
#!/bin/sh # /usr/local/sbin/tutanum-edr: contenimento reversibile, rilascio, eradicazione set -eu Q=/var/quarantena nota() { logger -p security.alert -t tutanum-edr "$*"; } val() { sed -n "s/^$1=//p" "$Q/$id/caso"; } nuovo() { id=$(date -u +%Y%m%dT%H%M%SZ)-$$; mkdir -m 700 "$Q/$id"; } case "${1:-}" in congela) # congela <jail> <motivo> jail=$2; motivo=$3 ip=$(jls -j "$jail" ip4.addr) ipfw table quarantena lookup "$ip" >/dev/null 2>&1 && exit 0 # già contenuta: nessun doppione nuovo pkill -STOP -j "$jail" || true # 1. processi fermi (SIGSTOP non si intercetta) ipfw -q table quarantena add "$ip" "$(date +%s)" # 2. niente rete, connessioni aperte comprese zfs snapshot -r "zroot/jails/$jail@caso-$id" # 3. istantanea: prova e punto di ritorno printf 'tipo=jail\njail=%s\nip=%s\nmotivo=%s\n' "$jail" "$ip" "$motivo" > "$Q/$id/caso" nota "CONTENUTO id=$id jail=$jail motivo=$motivo" ;; quarantena) # quarantena <file> <motivo> f=$2; motivo=$3; nuovo printf 'tipo=file\npercorso=%s\nproprietario=%s\nmodo=%s\nsha256=%s\nmotivo=%s\n' \ "$f" "$(stat -f %u:%g "$f")" "$(stat -f %Lp "$f")" "$(sha256 -q "$f")" "$motivo" > "$Q/$id/caso" mv "$f" "$Q/$id/oggetto"; chmod 000 "$Q/$id/oggetto" nota "QUARANTENA id=$id file=$f motivo=$motivo" ;; elenco) # i casi aperti, in attesa di una decisione for c in "$Q"/2*/caso; do [ -e "$c" ] && { echo "== ${c%/caso}"; cat "$c"; }; done ;; rilascia) # rilascia <id>: era un falso positivo, si torna allo stato di partenza id=$2 if [ "$(val tipo)" = file ]; then [ "$(sha256 -q "$Q/$id/oggetto")" = "$(val sha256)" ] || { echo "oggetto alterato" >&2; exit 1; } mv "$Q/$id/oggetto" "$(val percorso)" chown "$(val proprietario)" "$(val percorso)"; chmod "$(val modo)" "$(val percorso)" echo "$(val sha256):*:Tutanum.Rilasciato.$id:73" >> /var/db/clamav/tutanum.sfp # allowlist grep -v "^$(val sha256)\$" /var/db/ioc/sha256.txt > /var/db/ioc/sha256.tmp || true mv /var/db/ioc/sha256.tmp /var/db/ioc/sha256.txt clamdscan --reload else ipfw -q table quarantena delete "$(val ip)" pkill -CONT -j "$(val jail)" || true fi nota "RILASCIATO id=$id da=${SUDO_USER:-${DOAS_USER:-root}}" mv "$Q/$id" "$Q/chiusi/$id.rilasciato" ;; elimina) # elimina <id>: minaccia confermata. Irreversibile, quindi mai automatico. id=$2 if [ "$(val tipo)" = file ]; then rm -f "$Q/$id/oggetto" else jail -r "$(val jail)"; fi # l'istantanea resta per l'analisi nota "ELIMINATO id=$id da=${SUDO_USER:-${DOAS_USER:-root}}" mv "$Q/$id" "$Q/chiusi/$id.eliminato" ;; *) echo "uso: tutanum-edr congela|quarantena|elenco|rilascia|elimina" >&2; exit 64 ;; esac
5. La sentinella: comportamento e hash sullo stesso flusso
#!/bin/sh # /usr/local/sbin/tutanum-sentinella: regole di comportamento sul flusso di audit, # con il controllo dell'hash su ogni eseguibile lanciato dagli utenti dei servizi. MODO=${MODO:-avviso} # "avviso" finché le regole non sono rodate, poi "blocco" IOC=/var/db/ioc/sha256.txt # stdbuf: in una pipe praudit scrive a blocchi di 4 KB, e senza un flusso intenso di eventi # la sentinella li riceverebbe con minuti di ritardo (provato) stdbuf -o L praudit -l /dev/auditpipe | awk -F, ' { utente = ""; pid = ""; file = ""; regola = "" for (i = 1; i <= NF; i++) if ($i ~ /^subject/) { utente = $(i+2); pid = $(i+6); break } for (i = 1; i <= NF; i++) if ($i == "path") file = $(i+1) # ultimo "path": percorso risolto servizio = (utente ~ /^(www|_tor|_i2pd|git|iop|gestore|cowrie)$/) # i2pd gira come _i2pd if ($4 ~ /^execve/) { if (file ~ /^\/(tmp|var\/tmp)\//) regola = "exec-da-tmp" else if (servizio && file ~ /\/(sh|csh|tcsh|nc|fetch|ftp)$/) regola = "shell-da-servizio" else if (servizio) regola = "exec" } else if ($4 ~ /^kldload/) regola = "modulo-kernel" else if (servizio && $4 ~ /^(chmod|fchmod|chflags)/ && file ~ /\/(etc|rc\.d|\.ssh)\//) regola = "persistenza" if (regola != "" && pid != "") { print regola, pid, file; fflush() } }' | while read -r regola pid file; do jail=$(ps -o jid= -p "$pid" 2>/dev/null | tr -d ' ') [ -n "$jail" ] || continue # processo già terminato # nell'audit il percorso è già quello visto dall'host (/jails/jails/web/bin/sh, provato): # la radice della jail si antepone solo se il file così non esiste f=$file; [ "$jail" != 0 ] && [ ! -e "$f" ] && f=$(jls -j "$jail" path)$file noto=0 # motore a hash: l'eseguibile è un IOC? hash=$(sha256 -q "$f" 2>/dev/null) || hash="" [ -n "$hash" ] && grep -qxF "$hash" "$IOC" && noto=1 [ "$regola" = exec ] && [ "$noto" = 0 ] && continue # esecuzione ordinaria: nessun verdetto logger -p security.alert -t tutanum-edr \ "RILEVATO regola=$regola hash_noto=$noto pid=$pid jail=$jail file=$file" [ "$MODO" = blocco ] || continue if [ "$jail" = 0 ]; then kill -STOP "$pid" # sull'host si ferma il solo processo else tutanum-edr congela "$(jls -j "$jail" name)" "$regola"; fi # il nome, non il JID [ "$noto" = 1 ] && tutanum-edr quarantena "$f" "hash noto: $hash" done

La sentinella parte in modalità avviso. Si lascia girare qualche settimana, si restringono le regole che scattano a vuoto e solo allora si passa a MODO=blocco.

PoC di verifica: Si provano i due motori e il rilascio senza usare malware vero.

# 1. Motore a hash: un file innocuo il cui hash viene dichiarato malevolo echo "prova tutanum" > /jails/web/var/upload/prova.bin sha256 -q /jails/web/var/upload/prova.bin >> /var/db/ioc/sha256.txt # si rigenera tutanum.hsb come sopra, poi: tutanum-scansione ls /jails/web/var/upload/prova.bin # -> No such file: è in quarantena tutanum-edr elenco # -> tipo=file, percorso, sha256, motivo # 2. Motore comportamentale: l'utente del web server lancia una shell MODO=blocco tutanum-sentinella & jexec -U www web /bin/sh -c 'sleep 300' ipfw table quarantena list # -> l'indirizzo della jail web ps -J web -o pid,state,command # -> stato T: processi fermi, non terminati zfs list -t snapshot | grep caso- # -> l'istantanea del momento # 3. Rilascio: entrambi i casi erano prove, quindi falsi positivi tutanum-edr rilascia 20261004T101500Z-4242 ps -J web -o pid,state,command # -> di nuovo in esecuzione grep Rilasciato /var/db/clamav/tutanum.sfp

Da EDR a XDR

L'XDR non è un altro prodotto: è la stessa logica applicata a più sorgenti. In Tutanum le sorgenti esistono già e confluiscono nel collettore, quindi basta scrivere le regole che le incrociano. Ogni riga qui sotto unisce due segnali che da soli direbbero poco.

  • Rete ed endpoint: pf registra un tentativo di uscita in chiaro da una jail di servizio. La jail viene congelata anche se l'audit non ha visto nulla di strano.
  • Honeypot ed endpoint: l'esca viene toccata da un indirizzo interno. Nessun processo legittimo ha motivo di farlo, quindi la jail da cui parte il contatto è compromessa.
  • Honeypot e autenticazione: un indirizzo già visto dall'esca completa un accesso su un servizio reale. È l'allarme più grave: le credenziali sono in mano a chi stava scandagliando.
  • Integrità ed endpoint: AIDE o mtree segnalano un binario di sistema cambiato fuori da un aggiornamento. Il suo nuovo hash entra tra gli IOC e ogni jail che lo esegue viene contenuta.
  • Più nodi: in una federazione Tutanum gli IOC raccolti da un nodo (hash, indirizzi) si distribuiscono agli altri come commit firmati, senza alcun server centrale: è il compito di iop, descritto qui sotto.

La prima regola, per esempio, si realizza leggendo l'interfaccia di log di pf:

# /etc/pf.conf: le jail dei servizi parlano solo con la jail di Tor, mai con l'esterno block drop log quick on em0 from <jail_servizi> to any # /usr/local/sbin/tutanum-uscite: un tentativo di uscita in chiaro congela la jail che lo compie tcpdump -nli pflog0 'src net 10.0.0.0/24' 2>/dev/null | awk '{ sub(/\.[0-9]+$/, "", $3); print $3; fflush() }' | while read -r ip; do jail=$(jls | awk -v ip="$ip" '$2 == ip { print $1 }') [ -n "$jail" ] && tutanum-edr congela "$jail" "uscita-in-chiaro" done

Integrare iop

iop non è un forge: è lo strumento che permette di farne a meno. Condivide tra i nodi, attraverso I2P, qualunque insieme di file tracciato con git, senza alcun server di repository (è presentato in Forge proprio come alternativa ai server centrali). La divisione dei compiti è semplice. Il server di repository resta la scelta giusta per i dispositivi della propria rete, che da lì si aggiornano. iop serve dove quel server non arriva: tra server ridondati che stanno su reti diverse, per i dispositivi che si portano fuori casa e, più in generale, come alternativa a BitTorrent quando ciò che si distribuisce deve essere versionato e tracciato. Poiché trasporta file e non soltanto codice, in questo disegno entra in tre ruoli diversi.

  • Come servizio da sorvegliare: il demone gira in una jail propria con l'utente iop e ricade nelle stesse regole degli altri. La sua politica fail-closed semplifica il lavoro: con force_i2p attivo iop non parla mai in chiaro, quindi qualunque uscita in chiaro dalla sua jail è un'anomalia senza eccezioni. iop doctor esce con un codice di errore se un controllo critico fallisce, e va eseguito a intervalli.
  • Come sensore: il demone registra i propri eventi di rete in monitor.json e solleva avvisi a soglia: un picco di messaggi rifiutati (sondaggio o flood), connessioni da destinazioni non seguite (scansione), bridge SAM perso più volte, panic contenuti. Per scelta osserva e non blocca, quindi è una sorgente ideale per il collettore. Quel file elenca però le destinazioni dei pari: è materiale di correlazione e non deve lasciare il nodo.
  • Come canale: l'elenco degli IOC è un file tracciato con git, quindi diventa un progetto iop come qualunque altro, e lo stesso vale per le regole della sentinella e le configurazioni condivise. Ogni aggiornamento è un commit firmato con la chiave ed25519 del nodo che lo pubblica, viaggia nei tunnel I2P e ogni oggetto ricevuto viene verificato ricalcolandone l'identificativo. Nessun nodo vede l'indirizzo IP degli altri, e non esiste un server che possa essere sequestrato o spento. Un progetto con visibilità privata non viene annunciato e viene servito solo ai suoi delegati, cioè ai nodi il cui did il proprietario ha aggiunto a mano al documento del progetto.
# sensore: gli eventi del demone iop entrano nel collettore iop monitor --follow | logger -p security.notice -t iop-monitor & # crontab: controllo periodico della configurazione, esce con 1 se un controllo critico fallisce */30 * * * * iop doctor >/dev/null 2>&1 || logger -p security.alert -t iop-doctor "controllo critico fallito" # canale: nodo A, che pubblica gli IOC in un progetto privato iop project init ~/.iop/storage/ioc --name ioc --description "IOC della federazione" --private cp /var/db/ioc/sha256.txt ~/.iop/storage/ioc/ iop project commit ~/.iop/storage/ioc -m "IOC del 2026-10-04" # commit firmato iop daemon # privato: non viene annunciato # nodo B, che li riceve: comunica ad A il proprio did, fuori banda iop id # nodo A: aggiunge il did di B in coda a "delegates" in ~/.iop/storage/ioc/.iop/project.json # (il primo elemento resta il did di A, da cui deriva l'id del progetto; non serve un commit) # e passa a B, sempre fuori banda, la propria destinazione e il tip: iop i2p destination git -C ~/.iop/storage/ioc rev-parse HEAD # nodo B: "iop project clone" vale solo per i progetti pubblici, quindi la copia vuota si prepara a mano mkdir -p ~/.iop/storage/ioc/.iop git init -q ~/.iop/storage/ioc # ~/.iop/storage/ioc/.iop/project.json con "delegates": ["<DID_A>"] e "visibility": "private" iop project fetch aB3f...xyz.b32.i2p ioc --tip 4c1e9a... # poi, da cron, a ogni nuovo tip # allowlist locale: gli hash di tutto ciò che il nodo esegue legittimamente find /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin -type f -exec sha256 -q {} + \ | sort -u > /var/db/ioc/allowlist.txt # un IOC ricevuto da un altro nodo non può mai colpire ciò che è nell'allowlist grep -vxF -f /var/db/ioc/allowlist.txt ~/.iop/storage/ioc/sha256.txt >> /var/db/ioc/sha256.txt

La visibilità privata va presa per quello che è. Il nodo che serve il progetto riconosce un delegato dal did che questi dichiara aprendo la connessione, e quella dichiarazione non è firmata: chi conoscesse il did di un delegato, il nome del progetto e il tip potrebbe presentarsi al suo posto. Per gli IOC il danno è contenuto, perché non sono segreti e la loro autenticità non dipende da chi li scarica ma dalla firma dei commit e dalla verifica di ogni oggetto. Resta la regola: in un progetto privato non si mettono segreti.

L'ultima riga conta più delle altre. Un nodo della federazione può essere compromesso e pubblicare come "malevolo" l'hash di /bin/sh: senza il filtro, ogni nodo metterebbe in quarantena la propria shell. Gli indicatori ricevuti sono dati di terzi, e non possono mai prevalere sull'allowlist locale.

Limiti

  • Il silenzio non è una prova: come ricorda la documentazione di Kicksecure, nessuno strumento può dimostrare che un sistema è pulito. Un avversario mirato prova i propri strumenti contro queste stesse regole prima di usarli. L'EDR alza il costo dell'attacco e accorcia il tempo di scoperta, non di più.
  • Chi controlla il kernel acceca l'EDR: tutto questo gira in spazio utente. Contro un rootkit nel kernel valgono il securelevel, l'avvio verificato e l'invio dei log fuori dal nodo, non la sentinella.
  • I processi brevi sfuggono: la sentinella risale alla jail dal PID, e un processo che termina in pochi millisecondi non c'è già più. L'evento resta nel registro di audit, ma il blocco non scatta. Dove ogni utente di servizio vive in una sola jail, si può risalire alla jail dall'utente.
  • Il formato a righe di praudit è ambiguo: percorsi e argomenti contenenti virgole possono confondere l'analisi e un intruso può sfruttarlo. Per un uso serio si legge l'uscita XML (praudit -x) o il formato binario con libbsm.
  • Il blocco automatico è un'arma a doppio taglio: chi sa quali regole scattano può provocarle apposta per fermare un servizio. Perciò il contenimento agisce sulla singola jail, mai sull'host o sull'accesso di amministrazione, e i falsi positivi si rilasciano con un comando.
  • L'EDR è software, quindi superficie d'attacco: va tenuto piccolo, leggibile e sotto controllo d'integrità come tutto il resto.

Honeypot

Un honeypot è un'esca: una risorsa che non ha alcun motivo legittimo di essere toccata. Il suo valore sta tutto in questa proprietà. Un IDS deve distinguere il traffico ostile in mezzo a quello normale e quindi sbaglia; l'esca non ha traffico normale, perciò ogni contatto è già un segnale, quasi senza falsi positivi. È il sensore con il miglior rapporto tra informazione e rumore che un nodo possa avere, ed è anche quello che più facilmente si ritorce contro chi lo installa male.

Tipi di esca

Le esche si distinguono per quanto lasciano fare all'intruso: più interazione significa più informazione, ma anche più rischio e più manutenzione.

TipoChe cosa faStrumentiPer Tutanum
HoneytokenUn dato finto (chiave, file, account) che avvisa quando viene usatoNessuno: bastano SSH, audit e pfSempre: costo quasi nullo
TarpitNon emula nulla, fa solo perdere tempo ai bot endlesshSì: minuscolo e in stile suckless
Bassa interazioneApre porte finte e registra chi bussa OpenCanary, honeyd, dionaeaUtile sulla rete interna
Media interazioneEmula una shell e registra credenziali, comandi e file scaricaticowrieSì, in una jail isolata
Alta interazioneUn sistema vero lasciato compromettere Macchine virtuali dedicateNo: è un mestiere a tempo pieno
SuiteDecine di honeypot orchestrati in containerT-Pot No: pesante e non verificabile, contro il KISS

Dove collocarla

La stessa esca dà risposte diverse a seconda di dove la si mette, e la scelta dipende da che cosa si vuole sapere.

  • Verso l'interno (rete delle jail, LAN domestica): è la collocazione che vale di più. Qui il rumore di fondo è zero, quindi un contatto significa che qualcosa dentro il perimetro sta esplorando: un servizio compromesso o un dispositivo infetto in casa. È un allarme di compromissione, non una statistica.
  • Verso Internet in chiaro: raccoglie migliaia di contatti al giorno, quasi tutti di bot. Serve a costruire liste di blocco e a raccogliere IOC, non ad accorgersi di un attacco mirato. Ha un costo che per Tutanum pesa: un indirizzo domestico che risponde sulla porta 22 è più visibile di uno che scarta tutto in silenzio, e i motori di scansione catalogano gli honeypot riconoscibili. Un nodo che vuole restare invisibile può legittimamente rinunciarvi.
  • Dietro un onion service: qui le connessioni arrivano tutte dal demone Tor locale, quindi non esiste un indirizzo sorgente da bloccare. L'esca resta utile per ciò che registra (credenziali tentate, comandi, strumenti), ma la risposta non può essere una tabella di pf: è un avviso, e la difesa è quella anti-DoS del servizio.
  • Su I2P: il servizio vede la destinazione crittografica di chi si connette, che non si può falsificare ma si può rigenerare a costo zero. Bloccare le destinazioni ostili serve dunque a poco, mentre funziona il contrario: ammettere solo quelle note. È ciò che fa iop, il cui monitor segnala come possibile scansione ogni connessione da una destinazione non seguita. Su una rete di soli pari conosciuti, il nodo stesso è già un'esca per chiunque altro.

Architettura

Internetpf(rdr porta 22)Jail escacowrie, endlesshnessuna uscitaCollettorelogJail dei servizi realitraffico legittimocontatto internoSorgente esterna:blocco in tabella escheSorgente interna:jail congelata
L'esca vive in una jail senza uscita verso la rete. I suoi log, letti dall'host, alimentano il collettore: un contatto dall'esterno finisce nella tabella di blocco, un contatto dall'interno è la prova di una compromissione e congela la jail da cui parte.

Le regole sono poche e non negoziabili.

  • Una jail tutta sua: nessun file, chiave o volume in comune con i servizi reali, securelevel massimo, limiti di risorse imposti con rctl.
  • Nessuna uscita: l'esca risponde, non chiama mai. Chi riesce a evaderne l'emulazione non deve poterla usare come trampolino verso Internet o verso le altre jail.
  • I log si leggono da fuori: l'host legge i file della jail dal proprio filesystem. Non serve alcun canale di rete tra esca e collettore.
  • L'SSH vero sta altrove: raggiungibile solo dalla LAN di gestione o come onion service, come descritto in SSH. La porta 22 pubblica appartiene all'esca.

Rischi

  • È software esposto di proposito: cowrie è un programma Python che elabora input ostile. Un difetto nel suo codice è un ingresso nella jail, ed è per questo che la jail non deve contenere né poter raggiungere nulla.
  • Si riconosce: le configurazioni predefinite sono note (nome host, utenti, versione dichiarata, filesystem finto di cowrie). Un'esca riconosciuta non inganna nessuno e segnala che dietro c'è qualcuno attento. Vanno cambiati tutti i valori predefiniti.
  • Il blocco automatico si può rivolgere contro il nodo: un pacchetto SYN ha un mittente falsificabile. Se ogni tentativo su una porta esca finisse in una tabella di blocco, un avversario potrebbe far bloccare al nodo il proprio guard di Tor o il proprio resolver. Si blocca in automatico solo dopo una connessione TCP completata, che non si falsifica, e mai gli indirizzi della tabella <mai_bloccare>.
  • Registra dati di terzi: indirizzi e credenziali tentate sono dati raccolti su altre persone. Vedi Livello legale e giurisdizione.

In pratica su FreeBSD

1. La jail e il firewall
# /etc/jail.conf esca { path = /jails/esca; host.hostname = srv-backup; # un nome credibile, non "honeypot" ip4.addr = "lo1|10.0.0.66/32"; securelevel = 3; enforce_statfs = 2; mount.devfs; devfs_ruleset = 4; exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; } # limiti di risorse: l'esca non deve poter affamare il nodo (kern.racct.enable=1 in loader.conf) rctl -a jail:esca:memoryuse:deny=512m rctl -a jail:esca:maxproc:deny=100 rctl -a jail:esca:pcpu:deny=20 # /etc/pf.conf esca = "10.0.0.66" # solo da fuori della LAN: dalla LAN la porta 22 resta quella dell'sshd vero rdr on em0 inet proto tcp from ! $lan to (em0) port 22 -> $esca port 2222 # cowrie rdr on em0 inet proto tcp from ! $lan to (em0) port 2222 -> $esca port 2223 # endlessh block drop log quick from $esca to any # l'esca non apre mai connessioni pass in on em0 inet proto tcp to $esca port { 2222 2223 } keep state (max-src-conn 4) # le jail raggiungono l'esca: una jail compromessa che la tocca si tradisce pass quick on lo1 proto tcp from { $j_tor, $j_i2p, $j_web, $j_iop } to $esca port { 2222, 2223 } keep state # /etc/ipfw.rules (già presente): le tabelle che cambiano a sistema avviato stanno in ipfw ipfw -q table esche create type addr ipfw -q table mai_bloccare create type addr # riempita da /etc/ipfw.mai_bloccare: # guard di Tor, resolver, computer di amministrazione ipfw -q add 53 allow tcp from 'table(esche)' to any 22,2222,2223 in via em0 not layer2 # vede solo l'esca ipfw -q add 54 deny log ip from 'table(esche)' to any in via em0 not layer2
2. Il tarpit: endlessh

Prima che il server SSH invii la propria versione, il protocollo gli consente di mandare righe di testo arbitrarie. endlessh ne manda una ogni dieci secondi, per sempre: il bot resta appeso per ore e nel frattempo non scansiona altro. Non emula nulla, quindi non ha nulla da sbagliare.

# dall'host: la jail esca non esce su Internet (vedi Tutanum Classico, livello 4) doas pkg -C /usr/local/etc/pkg.conf -r /jails/jails/esca install endlessh doas jexec esca service ldconfig start # /usr/local/etc/endlessh.config (nella jail) Port 2223 Delay 10000 # una riga di banner ogni 10 secondi MaxLineLength 32 MaxClients 512 # oltre questo numero i nuovi client vengono rifiutati LogLevel 1 BindFamily 4 # lo script rc legge endlessh_config (predefinito: endlessh.conf), non i flag (provato) doas jexec esca sysrc endlessh_enable=YES endlessh_config=/usr/local/etc/endlessh.config doas jexec esca service endlessh start doas sockstat -4l -j esca # -> endlessh su 10.0.0.66:2223
3. La shell finta: cowrie

cowrie accetta le credenziali che decide di accettare, presenta una shell emulata e registra ogni comando e ogni file scaricato. Si installa nella jail come utente non privilegiato seguendo la documentazione ufficiale. Ciò che conta è togliere i valori predefiniti: nome host, versione dichiarata, elenco degli utenti (etc/userdb.txt) e filesystem finto. Il pacchetto di FreeBSD (cowrie 3.0.14, provato su FreeBSD 15.1 a ottobre 2026) non parte così com'è (TypeError: type 'ClientFactory' is not subscriptable): cowrie richiede Twisted 26.4, treq 26.7 e pyasn1-modules 0.4.2, mentre i port forniscono versioni più vecchie. La via provata usa il pacchetto per le dipendenze già compilate (cryptography, bcrypt) e aggiunge in un ambiente virtuale soltanto le librerie in Python puro che mancano, scaricate dall'host attraverso Tor: la jail non esce, e nell'ambiente si installa da una cartella locale. Il tarpit endlessh, dai pacchetti, non ne dipende.

# dall'host: le dipendenze compilate dai pacchetti, nella jail doas pkg -C /usr/local/etc/pkg.conf -r /jails/jails/esca install cowrie doas jexec esca service ldconfig start doas jexec esca pw useradd cowrie -m -s /usr/sbin/nologin doas jexec -U cowrie esca python3.12 -m venv --system-site-packages /home/cowrie/cowrie-env doas jexec -U cowrie esca mkdir /home/cowrie/wheels # dall'host, attraverso Tor: le sole librerie in Python puro che servono doas pkg install py312-pip py312-pysocks doas python3.12 -m pip download --proxy socks5h://10.0.0.2:59353 --no-deps \ -d /jails/jails-data/esca-data/home/cowrie/wheels \ "cowrie==3.0.14" "twisted[conch]>=26.4" "treq>=26.7" "pyasn1-modules>=0.4.2" multipart setuptools doas pkg delete -y py312-pip py312-pysocks # nella jail, senza rete doas jexec -U cowrie esca /home/cowrie/cowrie-env/bin/pip install --no-index --find-links /home/cowrie/wheels \ "twisted[conch]>=26.4" "treq>=26.7" "pyasn1-modules>=0.4.2" doas jexec -U cowrie esca /home/cowrie/cowrie-env/bin/pip install --no-index --find-links /home/cowrie/wheels \ --ignore-installed --no-deps "cowrie==3.0.14" # il plugin di twistd deve stare nell'ambiente # avvio, dalla cartella che contiene etc/cowrie.cfg e var/ doas jexec -U cowrie esca mkdir -p /home/cowrie/cowrie/etc /home/cowrie/cowrie/var/log/cowrie \ /home/cowrie/cowrie/var/run /home/cowrie/cowrie/var/lib/cowrie/downloads /home/cowrie/cowrie/var/lib/cowrie/tty doas jexec -U cowrie esca sh -c 'cd /home/cowrie/cowrie && /home/cowrie/cowrie-env/bin/twistd \ --umask=0022 --pidfile=var/run/cowrie.pid --logfile=var/log/cowrie/cowrie.log cowrie' # a ogni avvio della jail: /etc/rc.local (nella jail) su -m cowrie -c 'cd /home/cowrie/cowrie && /home/cowrie/cowrie-env/bin/twistd --umask=0022 \ --pidfile=var/run/cowrie.pid --logfile=var/log/cowrie/cowrie.log cowrie' # etc/cowrie.cfg (nella jail, utente non privilegiato "cowrie") [honeypot] hostname = srv-backup [ssh] listen_endpoints = tcp:2222:interface=10.0.0.66 version = SSH-2.0-OpenSSH_10.0 FreeBSD-20250801 # quello di un FreeBSD 15.1 vero: un banner datato tradisce l'esca [telnet] enabled = false [output_jsonlog] enabled = true logfile = ${honeypot:log_path}/cowrie.json
4. Dai log alle difese

È il passo che trasforma l'esca da curiosità in sensore. Lo script distingue i due casi del diagramma: la sorgente esterna viene tagliata fuori da tutti i servizi reali, la sorgente interna fa scattare il contenimento dell'EDR.

#!/bin/sh # /usr/local/sbin/tutanum-esca: dai log dell'esca alle difese. Gira sull'host, non nella jail. BASE=/jails/esca/home/cowrie/cowrie/var tail -F "$BASE/log/cowrie/cowrie.json" | jq --unbuffered -r 'select(.eventid == "cowrie.session.connect") | .src_ip' | while read -r ip; do [ "$ip" = 10.0.0.66 ] && continue # l'esca stessa (prove dall'host) ipfw table mai_bloccare lookup "$ip" >/dev/null 2>&1 && continue # mai tagliarsi fuori da soli jail=$(jls ip4.addr name | awk -v ip="$ip" '$1 == ip { print $2 }') # il nome, non il JID: if [ -n "$jail" ]; then # congela ne ricava il dataset tutanum-edr congela "$jail" "contatto-con-esca" # sorgente interna: compromissione certa else ipfw -q table esche add "$ip" "$(date +%s)" # sorgente esterna: fuori da tutto il resto fi logger -p security.alert -t tutanum-esca "CONTATTO ip=$ip jail=${jail:-esterna}" done # crontab di root # i blocchi scadono dopo una settimana: gli indirizzi cambiano proprietario # (il valore di ogni voce è l'ora di inserimento) 0 * * * * ipfw table esche list | awk -v l=$(( $(date +\%s) - 604800 )) '$2 < l { print $1 }' | xargs -n1 ipfw -q table esche delete # i payload scaricati dagli intrusi (cowrie li salva con il loro SHA-256 come nome) diventano IOC */10 * * * * ls /jails/esca/home/cowrie/cowrie/var/lib/cowrie/downloads >> /var/db/ioc/sha256.txt
5. Honeytoken: l'esca senza honeypot

Per un nodo singolo sono lo strumento con il miglior rendimento: nessun servizio in più, nessuna superficie d'attacco, e scattano solo quando qualcuno è già dentro.

# 1. Chiave esca. La parte privata si lascia dove un intruso la cercherebbe: ssh-keygen -t ed25519 -N "" -C "backup@srv-backup" -f /root/esca install -m 600 /root/esca /jails/web/root/.ssh/id_ed25519_backup && rm /root/esca # quella pubblica autorizza un account che non serve a nulla, con un comando forzato: pw useradd backup -m -s /bin/sh -c "Backup operator" # ~backup/.ssh/authorized_keys restrict,command="logger -p security.alert -t tutanum-esca CHIAVE-ESCA-USATA da=${SSH_CONNECTION%% *}" ssh-ed25519 AAAA... backup@srv-backup # 2. File esca: nessun processo legittimo lo apre mai. # Linux: auditctl -w /root/backup-chiavi.kdbx -p r -k esca # FreeBSD (DTrace, percorso assoluto): dtrace -qn 'syscall::open:entry /copyinstr(arg0) == "/root/backup-chiavi.kdbx"/, syscall::openat:entry /copyinstr(arg1) == "/root/backup-chiavi.kdbx"/ { printf("ESCA-APERTA pid=%d uid=%d exe=%s\n", pid, uid, execname); }' | logger -p security.alert -t tutanum-esca # 3. Destinazione esca su I2P: un indirizzo che non è pubblicato da nessuna parte, tranne che in # un file lasciato nella jail da sorvegliare (per esempio tra i pari "seguiti" di iop). # Chi vi si connette ha letto quel file. /usr/local/etc/i2pd/tunnels.conf: [esca] type = server host = 10.0.0.66 port = 2222 keys = esca.dat # 4. Porta esca senza alcun software: basta pf. Solo avviso, mai blocco automatico (vedi sotto). block drop in log quick on em0 proto tcp to port { 23 445 3389 5900 }

Se la chiave esca viene usata, chi la usa ha letto i file della jail in cui era nascosta: quella jail va trattata come compromessa anche se nessun'altra regola è scattata.

PoC di verifica: Si controlla che l'esca registri, che il blocco scatti, che dall'esca non si esca e che il contatto interno congeli la jail giusta.

# da una macchina esterna (o da un indirizzo di prova) ssh root@nodo.example # qualsiasi password: si entra nella shell finta # sul nodo tail -1 /jails/esca/home/cowrie/cowrie/var/log/cowrie/cowrie.json | jq '.eventid, .src_ip' ipfw table esche list # -> l'indirizzo di prova nc -zv nodo.example 443 # dall'esterno: ora il servizio reale non risponde più ipfw table esche delete 203.0.113.7 # rilascio manuale # l'esca non deve poter uscire jexec esca nc -zv -w 3 1.1.1.1 443 # -> timeout, e una riga in pflog0 # contatto interno: da una jail di servizio jexec web nc -z 10.0.0.66 2222 tutanum-edr elenco # -> jail=web motivo=contatto-con-esca

Che cosa fare dei dati

  • Liste di blocco: la tabella esche di ipfw protegge i servizi reali da chi ha già mostrato le proprie intenzioni. Le voci scadono, perché gli indirizzi cambiano proprietario.
  • IOC per il motore a hash: i file che gli intrusi scaricano nell'esca sono campioni autentici. I loro hash alimentano l'elenco usato dall'EDR, che così riconosce quegli stessi file se compaiono su un servizio vero.
  • Segnali di fuga: se tra le credenziali tentate compare un nome utente che esiste solo sul proprio nodo, o una password realmente in uso, quel dato è uscito da qualche parte. Il confronto va fatto sugli hash, senza mai scrivere le proprie password in un file di confronto.
  • Condivisione: gli indicatori raccolti si possono pubblicare verso una comunità MISP o tra i nodi di una federazione, come descritto in MISP e SIEM.

Tutto finisce nel collettore e nell'hub dei servizi, e il contatto interno è uno dei pochi eventi che merita un avviso di gravità massima, immediato e fuori banda.

MISP e SIEM

Un SIEM raccoglie e correla log ed eventi. Non è essenziale, ma è utile. Gli stack completi (Wazuh, lo stack Elastic, Graylog) sono potenti ma pesanti: in ottica KISS spesso basta un syslog centrale (rsyslog o syslog-ng) con regole di correlazione semplici e un instradatore leggero come fluent-bit o Vector, archiviando in un piccolo indice. Il SIEM pieno si adotta solo se serve davvero.

MISP è una piattaforma di threat intelligence per condividere indicatori di compromissione (IOC). Per un nodo domestico ospitare l'intero MISP, una grande applicazione, è sovradimensionato: conviene piuttosto consumarne i feed, convertendo gli IOC nelle forme che il nodo già usa, cioè tabelle di pf per gli IP malevoli, liste di blocco per DNSCrypt per i domini e regole per un IDS come Suricata o Zeek. Così i feed alimentano automaticamente le difese, gli eventi del firewall e degli honeypot alimentano il collettore, e la dashboard mostra mentre l'alerting avvisa.

Alerting

Gli avvisi vanno recapitati su un canale fuori banda e indipendente dal server, con due vincoli che discendono dai valori del progetto: niente servizi push di terzi (Google, Apple, un server ntfy pubblico), per non consegnare a un estraneo il fatto stesso che esista un nodo e che qualcosa sia successo; e nessuna porta in più aperta verso il mondo sul nodo, che resta dietro il firewall default-deny. Le soluzioni classiche (XMPP, Matrix, ntfy, posta via Tor o I2P) spingono invece il nodo a connettersi a un server esterno o a riceverne connessioni.

Il disegno adottato rovescia la direzione: il nodo pubblica, il telefono controlla. Un piccolo notificatore sull'host del nodo raccoglie a intervalli regolari i tre flussi che contano: gli allarmi di sicurezza dai log (EDR, sentinella, esca), gli esiti dei controlli di stato e le issue aperte dai servizi di analisi. Vi aggiunge le metriche correnti, e scrive un unico file di stato. Quel file viene servito come servizio nascosto I2P (o onion) in sola lettura, e un'app sul telefono lo scarica attraverso il router I2P del telefono stesso. Nessuno dei due apre connessioni verso l'altro al di fuori di questo: il nodo non conosce il telefono, il telefono raggiunge il nodo solo dentro la rete anonima.

Tre proprietà rendono il canale affidabile anche di fronte a un avversario:

  • Autenticità per firma, non per trasporto. Il file di stato è firmato con una chiave Ed25519 che vive sull'host del nodo, fuori dalle jail; la jail che lo serve lo vede in sola lettura e non può falsificarlo. L'app verifica la firma prima di leggere il contenuto, e un file alterato diventa esso stesso l'allarme «firma non valida». Così il servizio esposto può anche essere compromesso senza che si possano iniettare avvisi falsi o sopprimere quelli veri a monte della firma.
  • Segnale di vita (heartbeat). Il file porta un contatore che cresce a ogni pubblicazione. L'app misura da quanto tempo quel contatore non avanza con l'orologio del telefono, non con quello del nodo: così un nodo spento, isolato o sequestrato produce silenzio, e il silenzio oltre una soglia è un allarme critico. Misurare il tempo sul telefono impedisce che un file vecchio, rimesso in circolo da un intermediario, venga scambiato per un segno di vita.
  • Livelli e deduplica. Gli eventi hanno un livello (critico, informativo, issue); i problemi di stato si annunciano una volta sola per episodio, con un messaggio di ritorno alla normalità quando rientrano, così non si viene sommersi da avvisi ripetuti fino a ignorarli.

Il prezzo di questo disegno è la latenza: il sistema operativo del telefono esegue i controlli in secondo piano non più di una volta ogni quindici minuti circa, e meno spesso in risparmio energetico, quindi un allarme arriva con qualche minuto di ritardo e un silenzio dopo la soglia più un giro. In cambio non c'è nessun intermediario fidato, nessun account, e nessuna porta in ascolto sul nodo. Chi vuole il recapito immediato può aggiungere, in parallelo e non in sostituzione, un XMPP auto-ospitato per i soli eventi critici, accettandone il costo in esposizione.

L'app del telefono è un client minimo: su Android richiede soltanto l'app del router I2P (i2pd) in esecuzione e il permesso di mostrare notifiche; su iOS il disegno non è realizzabile, perché il sistema non lascia girare un router I2P in secondo piano. La configurazione (indirizzo del nodo, chiave pubblica di verifica, soglia del silenzio) si trasferisce una volta con un codice QR, e l'app chiede conferma mostrando la chiave, da confrontare con quella annotata dal nodo.

SYNwall

SYNwall è un firewall trasparente e senza configurazione che inserisce una one-time password (OTP) dentro i pacchetti TCP e UDP, calcolata da una chiave precondivisa (PSK), dall'orario corrente e, in modalità anti-spoofing, dagli indirizzi IP. Tutto il traffico privo dell'OTP corretta viene scartato in silenzio prima di raggiungere l'applicazione. Usa l'hashing leggero Quark, è pensato per dispositivi a basse risorse ed è un modulo del kernel Linux.

Casi d'uso su Tutanum:

  • Servizi di amministrazione invisibili: SSH, la dashboard e l'hub non rispondono, e non si fanno nemmeno rilevare dalle scansioni, a chi non presenta l'OTP. È più robusto del port knocking.
  • Collegamenti tra nodi fidati: in una federazione Tutanum (sincronizzazione del mirror dei repository, runner distribuiti) una PSK condivisa fa sì che solo i nodi che la possiedono si parlino.
  • Strato di invisibilità: davanti ai pochi servizi che devono restare in ascolto, sopra il firewall default-deny.

Integrazione nei valori del progetto: è software libero, decentralizzato (l'OTP è autosufficiente, non serve un server di autenticazione centrale) e leggerissimo. I limiti vanno detti con onestà: è un modulo del kernel Linux, quindi si applica ai dispositivi client Linux della rete domestica e ai nodi Linux; sul server *BSD, preferito per Tutanum, l'equivalente si ottiene con pf (knocking e overload) già visto nel firewall. Richiede inoltre orologi sincronizzati, il NAT può rompere l'anti-spoofing e l'OTP su UDP vuole il modulo a entrambi i capi.

Un hub dei servizi

Accanto alla dashboard serve un hub: una singola pagina minima che raccoglie e collega tutte le funzionalità auto-ospitate, cioè metriche, log, nyx per Tor, console di i2pd, forge, avvisi degli honeypot, stato del collettore e dell'alerting. In linea con suckless e con il KISS è una pagina statica, o generata da un piccolo script, dove ogni strumento mantiene la propria interfaccia minima e l'hub si limita ad aggregarne i collegamenti e qualche indicatore di stato, non una piattaforma monolitica. Si espone come eepsite I2P o onion service e, dove serve, dietro SYNwall. È modulare per costruzione: ogni tassello è indipendente e sostituibile, e se uno cade gli altri restano.

Estensioni

A livello di memoria di archiviazione sono consigliate le SSD in quanto essendo memorie flash sono anche più resistenti dei comuni Hard Disk funzionanti invece meccanicamente a dischi magnetici. Le marche consigliate sono Corsair, WD, Sandisk, Kingston e Samsung. Evitare l'uso di USB e di microSD per la memoria di archiviazione, in quanto potrebbero corrompersi velocemente a seguito della ripetuta scrittura di dati, soprattutto se si utilizza un filesystem ZFS, usato di default su sistemi operativi come FreeBSD. Le SSD NVMe sono buone ma meno affidabili di una SSD, in quanto sprovviste dell'attacco SATA, che ad oggi rimane il più sicuro, gestibile, scalabile e veloce.

In caso di installazioni da live è consigliato pertanto l'utilizzo di un CD-ROM o di un DVD-R, così che essendo esenti da sovrascrittura si possa mitigare la possibilità che venga applicato qualche malware. Per questo motivo potrebbe rendersi utile se non necessario un lettore CD/DVD.
Per una maggiore consistenza dei dati, nelle banche o in organizzazione dove i dati non si devono cancellare, vengono usati dei nastri magnetici conservati in cassaforti isolate da possibili interferenze che potrebbero comprometterne i dati; tali nastri in lettura sono lenti, ma offrono un supporto migliore per quanto riguarda la stesura dei dati. La carta ad ogni modo rimane il metodo più longevo, cui succedono metodi molto più grezzi, come l'incisione fisica in materiali come il metallo (negli ultimi tempi si parla di incisioni laser nel quarzo o di strutture utilizzanti il DNA, ma rimangono tutt'oggi soluzioni sperimentali).

CPU

La maggior parte delle CPU presenta attualmente ancora oggi le vulnerabilità Meltdown o Spectre; esse sono dovute principalmente ad una cattiva progettazione hardware e software, trascinando il problema anche a livello del sistema operativo.
Meltdown colpisce principalmente i processori Intel e ARM, mentre Spectre principalmente sia ARM, che Intel che AMD ma è più difficile da sfruttare rispetto a Meltdown. Ad oggi ci sono delle mitigazioni software ma potrebbero non essere sufficienti, per questo sarebbe meglio optare per processori con mitigazioni di sicurezza già implementate architetturalmente. Per sapere se il vostro processore è impattato consultate questa lista in formato json (fonte). Per verificare se sono presenti tali vulnerabilità è possibile utilizzare questo bash script. Per maggiori informazioni è possibile visitare questo sito, oppure consultare le documentazioni ufficiali: Meltdown e Spectre.

FPGA

Un'FPGA (Field-Programmable Gate Array) è un circuito integrato la cui logica si programma dopo la fabbricazione: invece di eseguire istruzioni come una CPU, se ne descrive direttamente l'hardware con un linguaggio di descrizione (HDL) e lo si configura come si vuole. Per Tutanum è interessante perché permette di costruire logica personalizzata e verificabile senza dipendere solo da CPU generaliste chiuse, con i loro motori di gestione nascosti.

Come è fatta

Un'FPGA è una matrice di blocchi logici configurabili (CLB) collegati da un'interconnessione programmabile (una rete di canali e matrici di commutazione), con blocchi di I/O sul bordo che la connettono ai piedini del chip.

I/OI/OI/OI/OI/OI/OI/OI/OI/OCLBCLBCLBCLBCLBCLBCLBCLBCLB
Un'FPGA è una matrice di blocchi logici configurabili (CLB) uniti da un'interconnessione programmabile, con blocchi di I/O sul bordo.

L'elemento base dentro un CLB è la cella logica: una look-up table (LUT), cioè una piccola memoria che realizza qualsiasi funzione booleana dei suoi ingressi, seguita da un flip-flop che ne registra il risultato a ogni colpo di clock. Combinando migliaia di queste celle e instradandole fra loro si ottiene qualunque circuito digitale. Le FPGA moderne aggiungono blocchi dedicati: memorie interne (block RAM), moltiplicatori per il calcolo (DSP) e gestione del clock (PLL).

ingressiLUT(look-up table)D flip-flopclockuscita
La cella logica di base: una LUT realizza qualsiasi funzione booleana dei suoi ingressi, un flip-flop ne registra il risultato al ritmo del clock.

Dal codice al circuito

Il flusso parte da una descrizione in HDL (Verilog o VHDL). La sintesi la traduce in una rete di celle logiche; il place and route decide quali celle usare e come collegarle sulla matrice; infine si genera il bitstream, il file che configura l'FPGA.

HDL(Verilog/VHDL)SintesiPlace& RouteBitstreamFPGA
Dal codice al circuito: la descrizione HDL viene sintetizzata, mappata sui blocchi (place & route) e trasformata nel bitstream che configura l'FPGA.

Nelle FPGA più comuni la configurazione vive in celle SRAM ed è volatile: va ricaricata a ogni accensione da una memoria flash esterna, che per questo è un componente da proteggere al pari del resto del sistema.

FPGA e sicurezza per Tutanum

Il vantaggio per un nodo Tutanum è la possibilità di eseguire logica aperta e verificabile: un processore soft core open come un RISC-V (ad esempio NEORV32), acceleratori crittografici dedicati (AES, SHA, generatori di numeri casuali) e isolamento realizzato nell'hardware, senza il motore di gestione nascosto di molte CPU commerciali. Progetti come OpenTitan mostrano la direzione di un hardware di fiducia aperto.

Restano però delle cautele. La fiducia nel silicio non è assoluta: l'FPGA è comunque un chip proprietario e un trojan hardware non è escluso a priori. Inoltre i toolchain e il formato del bitstream sono spesso chiusi (AMD/Xilinx Vivado, Intel/Altera Quartus), il che contrasta con i valori di software libero di Tutanum. Dove possibile conviene quindi scegliere FPGA supportate dai toolchain aperti (Yosys e nextpnr, con Project IceStorm per le Lattice iCE40 e Project Trellis per le ECP5), che rendono l'intera catena ispezionabile, usare soft core open, proteggere il flash di configurazione e, se supportate, attivare cifratura e autenticazione del bitstream.

Smartphone come server Tutanum

È sconsigliato l'utilizzo di dispositivi mobili/embedded come gli smartphone in quanto nella stragrande maggioranza dei casi si tratta di dispositivi proprietari, senza interruttori hardware, sempre accesi (anche da spenti), con la batteria irrimovibile (l'apertura viene fatta solitamente con strumenti specifici e da tecnici specializzati) e con la capacità di offrire una possibile triangolazione a causa dei segnali inviati ai ripetitori telefonici, anche senza SIM.

I telefoni smart sono stati costruiti per raccogliere quanti più dati biometrici possibile, evitare di usarli come server, il sistema operativo non sarebbe nemmeno ottimizzato: iOS seppur sia molto più prestante di Android a causa dell'adozione di un microkernel anziché di un kernel monolitico, rimane una scatola nera, nel senso che seppur possa essere svuotato dagli spyware più conosciuti (questo discorso vale più per Android che per iOS essendo che è molto più facile farlo per il primo sistema operativo che per il secondo) non si ha mai la sicurezza di averli rimossi totalmente. Il firmware inoltre è quasi sempre proprietario e difficilmente risulta modificabile. Librem e Pinephone potrebbero essere una buona scelta per Tutanum Lieve, seppur siano molto limitati a livello di risorse; ciò nonostante presentano interruttori hardware che permettono di disabilitare moduli come il microfono, il modem del telefono, la fotocamera, la SIM, etc., cosa che li rende i dispositivi mobile del futuro.

Single Board Computer

Il single board computer più famoso è Raspberry Pi, un piccolo computer che con la versione 5 ha presentato caratteristiche che lo rendono adatto come piccolo server.
Tuttavia, come riportato dalla FSF, la board è basata sulla famiglia Broadcom VideoCore 4 e fa utilizzo di driver proprietari per lo startup.
Nel repository ufficiale è possibile trovare nella cartella boot 8 firmware ARM in formato ELF senza alcun riferimento ad una documentazione o codice che possa permettere di poterne replicare i risultati: start.elf, start4.elf, start4cd.elf, start4db.elf, start4x.elf, start_cd.elf, start_db.elf e start_x.elf.
Di seguito un'analisi del contenuto di start.elf attuata con binwalk:

In base ai dati del 2015 (1, 2) la soluzione migliore rimarrebbe mangOH, ma non risulta ad oggi più reperibile in quanto deprecato.
Ci sarebbero delle schede con processori RISC-V, un'architettura open source che ad oggi sta trovando sempre più sviluppatori, ma per un utilizzo stabile è forse troppo presto per poterne parlare, seppur sviluppi futuri potranno vederla impiegata per un'implementazione ufficiale anche su Tutanum.
Ad oggi inoltre RISC-V manca di una community italiana, di una documentazione consistente e di una metodologia di sviluppo consolidata, andando pertanto contro i principi elencati all'inizio.
In termini di sviluppo dei processori, ci si potrebbe dedicare alle CPU FPGA come ZipCPU, ma in giro attualmente non è possibile trovare alcun prodotto finito.
Progetti come ZipCPU sono ancora in fase embrionale e di per sé il progetto attualmente si propone solo sulla carta e al massimo tramite emulazione virtuale.
Vi sono poi delle CPU costruire proprio da zero che integrando la documentazione su come poterle autoprodurre, ad esempio il processore di Sam Zeelof e il processore di Robert Elder.
Per chi volesse dedicarsi allo sviluppo delle CPU lascio qui di seguito del materiale di riferimento:

  • Per un'introduzione allo studio dei computer: "Architettura dei calcolatori", Andrew Tanenbaum.
  • Per iniziare a studiare l'architettura delle CPU consultare questa playlist.
  • Riguardo alle reti logiche.
  • Riguardo alla progettazione descrittiva delle CPU: Verilog
  • Per iniziare con RISC-V: documentazione ufficiale, Wikipedia.
  • Soft core RISC-V minimale

A livello pratico, la scelta dell'architettura della CPU risulta ad oggi ardua ed è pertanto necessario andare per compromessi, soprattutto per quanto riguarda la compatibilità con i sistemi operativi.
Per una scelta della CPU, delle loro possibili evoluzioni future e relativamente alle vulnerabilità note, consultare questo thread. Ad oggi non sono molte le soluzioni libere, supportate e con una decente capacità di calcolo. Tuttavia proponiamo qua una lista di dispositivi clusterizzabili, per potere aumentarne almeno la capacità computazionale:

Queste sono soluzioni che sono sì libere ma che purtroppo scemano in termini di risorse o potenza di calcolo. L'unica azienda ad oggi competitiva per la potenza di calcolo, le risorse e l'open source risulta ad oggi essere Banana Pi.
Qui di seguito vi è l'elenco delle soluzioni più compatibili con il progetto Tutanum:

  • Banana Pi BPI-M7 con Rockchip RK3588, con una selezione tra 8, 16 e 32GB RAM e 64 o 128GB eMMC. Rimane ad ora la soluzione più appropriata. In base ad AliExpress, in data 12 marzo 2024, il modello con 8GB di RAM (64GB interni di memoria, gli altri ne hanno 128GB) costa €208,10, quello con 16GB costa €252,76 e quello con 32GB di RAM costa €335,05.
  • StarFive VisionFive JH7100 RISC-V Single Board Computer. Come sappiamo l'architettura RISC-V è ancora in fase di sviluppo, pertanto utilizzarla in produzione è attualmente un rischio, seppur possa mitigare a molte vulnerabilità presenti e diffuse oggi nei più comuni processori. Ha dai 4 agli 8 GB di RAM.
  • Tutta la serie BPI-M*: BPI-M5, BPI-M6, BPI-M7, BPI-M2S.

Attacchi hardware delle intelligence

Le agenzie di intelligence non si fermano al software: attaccano l'hardware stesso. Le loro tecniche sono in parte pubbliche, grazie alle fughe di notizie del Vault 7 della CIA e del catalogo ANT della NSA, oltre che alla ricerca accademica. Tutanum assume questo avversario e si difende di conseguenza. Qui sotto le tecniche documentate e, per ciascuna, le difese concrete da applicare, con l'atteggiamento più paranoico possibile: dare per scontato che l'avversario abbia già provato, o possa provare, ad arrivare al ferro.

Intercettazione nella catena di fornitura

La tecnica dell'interdiction consiste nell'intercettare l'hardware durante la spedizione, aprirlo, impiantarvi una modifica e richiuderlo, in modo che arrivi al destinatario già compromesso. È una pratica documentata dell'unità TAO della NSA.

Difesa: acquistare di persona e localmente, da fornitori scelti a caso e non riconducibili, evitando consegne tracciabili al proprio indirizzo; preferire l'autoproduzione (single board computer, FPGA con toolchain aperti); usare imballi a prova di manomissione e ispezionare, pesare e fotografare ogni componente alla ricezione, confrontandolo con le specifiche ufficiali.

PoC di verifica: creare una "fotografia" dell'hardware come ricevuto (foto delle schede, peso, seriali e hash dei firmware) da conservare fuori banda per confronti futuri:

doas flashrom -p internal -r bios-iniziale.bin # dump del firmware sha256 bios-iniziale.bin > bios.sha256 # impronta di riferimento

Impianti nel firmware

Un impianto nel firmware vive sotto il sistema operativo e sopravvive alla reinstallazione. Il catalogo ANT elenca impianti BIOS per server (DEITYBOUNCE, IRONCHEF); il Vault 7 descrive impianti EFI per Mac (DerStarke, Sonic Screwdriver); l'Equation Group è arrivato a riprogrammare il firmware degli hard disk e degli SSD, rendendo l'impianto invisibile e non rimovibile dal sistema.

Difesa: usare firmware aperto e verificabile (coreboot e libreboot, vedi anche la sezione BIOS e UEFI); attivare la protezione in scrittura hardware della SPI flash; usare boot misurato con TPM e attestazione (per esempio Heads); cifrare l'intero disco, così che il firmware del drive non veda mai dati in chiaro; verificare periodicamente il firmware confrontandolo con l'impronta di riferimento.

PoC di verifica: ridumpare il firmware e confrontarlo con il riferimento, e leggere i registri del TPM del boot misurato:

doas flashrom -p internal -r bios-oggi.bin sha256 -c bios.sha256 # deve corrispondere al dump iniziale doas tpm2_pcrread sha256:0,1,2,3,4,7 # valori del boot misurato

Impianti sulle interfacce

Molti impianti si nascondono nei connettori e nei cavi. La famiglia COTTONMOUTH del catalogo ANT è fatta di connettori e cavi USB che integrano un ricetrasmettitore radio; la classe di attacchi BadUSB sfrutta periferiche USB che si fingono tastiere. Esistono anche impianti dedicati a tastiera e video, trattati nella sezione sulle radiofrequenze.

Difesa: disabilitare o riempire con resina le porte inutilizzate; non collegare mai dispositivi non fidati; adottare una allowlist dei dispositivi USB con usbguard; usare data blocker quando serve solo l'alimentazione; ispezionare fisicamente cavi e connettori, preferendo cavi schermati e corti.

PoC di verifica: elencare i dispositivi USB autorizzati e accorgersi di quelli nuovi:

doas usbguard list-devices # dispositivi noti e loro stato lsusb # confronto con l'inventario atteso

Esfiltrazione via radiofrequenza

Gli impianti più insidiosi sono i retroriflettori RF passivi: non emettono nulla da soli, quindi sono quasi invisibili a un controllo radio, ma illuminati da un radar esterno rimandano indietro un segnale modulato con i dati. Il catalogo ANT ne elenca diversi (RAGEMASTER sul cavo video, SURLYSPAWN sulla tastiera, TAWDRYYARD come beacon), illuminati da radar come CTX4000 o PHOTOANGLO. Così si può esfiltrare schermo e tasti anche da una macchina non collegata in rete.

Periferica(tastiera, video)Impianto RF passivo(retroriflettore)Radar illuminante(avversario)onda continua (illuminazione)riflessione modulata = dati
Un retroriflettore RF passivo non emette da solo: illuminato da un radar esterno rimanda indietro un segnale modulato con i dati, esfiltrando anche da sistemi non collegati in rete.

Difesa: schermatura elettromagnetica dell'apparato (una gabbia di Faraday o un armadio schermato), filtri sulle linee di alimentazione, e ispezione fisica alla ricerca di impianti. Vale tutto quanto già visto nella sezione Compromissione elettromagnetica: ridurre le emissioni e impedire che un radar esterno possa illuminare l'apparato.

Il WiFi come radar e le backdoor nei router

Le onde WiFi non servono solo a trasmettere dati: rimbalzano sui corpi e sugli oggetti, e analizzando come il segnale viene perturbato (il Channel State Information, CSI) si può rilevare la presenza di persone, contarle, seguirne i movimenti e perfino stimarne la posizione del corpo, anche attraverso i muri e senza telecamere. È un filone di ricerca consolidato (da RF-Pose del MIT fino a DensePose From WiFi) e sta persino diventando uno standard (IEEE 802.11bf, "WLAN Sensing").

Router WiFi(o avversario)Personamurosegnale WiFiriflessione (CSI)
Le onde WiFi rimbalzano sul corpo: analizzando il CSI il router (o un avversario) rileva presenza, posizione e movimento, anche attraverso i muri.

Il punto di osservazione naturale per questo sensing è il router: ha la radio WiFi e vede il CSI di tutto ciò che gli sta intorno. Un router con una backdoor, cosa tutt'altro che rara nei firmware proprietari dei router consumer e di quelli forniti dagli ISP, e prevista negli impianti di rete del catalogo ANT (NIGHTSTAND), diventa quindi uno strumento potente: può intercettare il traffico, dirottare il DNS e, con la stessa radio, trasformarsi in un sensore di presenza. Le intelligence potrebbero raccogliere questi dati su larga scala all'insaputa delle persone.

È esattamente il motivo per cui si rende necessario il software libero: l'unico modo per fidarsi di un router è poterne ispezionare e ricompilare il firmware. Un firmware chiuso può nascondere backdoor e funzioni di sensing senza che nessuno se ne accorga; un firmware aperto e verificabile (OpenWrt, libreCMC) permette di controllare cosa fa davvero la radio e di rimuovere telemetria e funzioni indesiderate. Vale lo stesso ragionamento fatto per i firmware delle CPU e dei BIOS: ciò che non si può ispezionare non si può dire sicuro.

Difesa: usare cavo Ethernet invece del WiFi per l'infrastruttura e spegnere la radio quando non serve; installare firmware aperto e verificabile (OpenWrt o libreCMC) su un router che lo supporti, evitando i router bloccati dell'ISP; schermare il locale (gabbia di Faraday, vedi Compromissione elettromagnetica) per ridurre le emissioni e ostacolare il sensing dall'esterno, tenendo presente che anche il WiFi di un vicino o di un avversario può "vedere" attraverso i muri; mantenere il controllo del DNS e monitorare il router.

Attacchi con accesso fisico

Con un accesso fisico anche breve, un avversario dispone di tutta una serie di tecniche documentate.

Evil maid

Manomissione del bootloader o del firmware durante una breve assenza (il nome è di Joanna Rutkowska). Difesa: sigilli a prova di manomissione, anche artigianali come lo smalto glitter sulle viti fotografato in anticipo; cifratura dell'intero disco con autenticazione pre-boot; boot misurato con attestazione (Heads con un codice TOTP mostrato all'avvio); non lasciare mai il server incustodito.

Cold boot

La RAM trattiene i dati per qualche secondo dopo lo spegnimento: raffreddandola e riavviando da un supporto esterno se ne possono estrarre le chiavi di cifratura (attacco descritto in Lest We Remember). Difesa: RAM saldata, azzeramento della memoria allo spegnimento, disabilitare il boot da supporti esterni nel firmware (protetto da password), e non lasciare la macchina accesa o sospesa in un luogo accessibile.

Attacchi DMA

Interfacce come Thunderbolt, FireWire e PCIe permettono l'accesso diretto alla memoria (DMA) e quindi la lettura della RAM senza passare dalla CPU (attacco Thunderclap). Difesa: abilitare l'IOMMU (VT-d o AMD-Vi) e la protezione DMA del kernel; disabilitare Thunderbolt e FireWire e l'hotplug PCIe non necessario.

Porte di debug (JTAG e UART)

Le interfacce di debug lasciate accessibili permettono di leggere e riscrivere memoria e firmware. Difesa: disabilitare o bruciare i fuse JTAG dove previsto, rimuovere o proteggere fisicamente gli header di debug sulla scheda.

PoC di verifica: controllare che l'IOMMU sia attivo (prima difesa contro il DMA):

doas dmesg | grep -i -E 'DMAR|IOMMU|AMD-Vi' # deve risultare abilitato doas sysctl hw.iommu # FreeBSD

Console, sospensione e memoria

La pagina di Kicksecure sulla protezione dagli attacchi fisici e quella sul cold boot aggiungono alcune misure pratiche a quelle già viste.

  • Le console restano aperte: una sessione lasciata su una console testuale non scade e non viene bloccata da nulla. Si chiude sempre con exit, e si imposta la disconnessione automatica della shell per inattività.
  • Mai la sospensione: in sospensione le chiavi del disco restano in RAM. Un nodo è acceso oppure spento.
  • Pulire la RAM allo spegnimento: Kicksecure azzera la memoria durante l'arresto. Funziona solo se lo spegnimento è regolare, quindi non ferma chi stacca la corrente ed estrae i moduli, ma toglie di mezzo il caso più comune.
  • Dopo lo spegnimento: staccare l'alimentazione (e la batteria, se c'è) e non lasciare la macchina incustodita nei primi minuti, quando la memoria conserva ancora il contenuto.
  • Moduli saldati e memoria cifrata: la RAM saldata sulla scheda non si può trasferire su un'altra macchina, e la cifratura della memoria rende inutile leggerla.
  • Password su firmware e boot loader: impediscono di avviare da un altro supporto o di cambiare i parametri del kernel senza lasciare traccia.

Canali laterali fisici

Un calcolatore non elabora soltanto dati: consuma corrente, scalda, emette onde elettromagnetiche, fa rumore e impiega tempi diversi a seconda di ciò che calcola. Tutte grandezze fisiche che dipendono dai segreti trattati e che un avversario può misurare senza toccare il software. Sono i canali laterali, tra gli strumenti preferiti delle intelligence proprio perché aggirano una crittografia altrimenti solida.

Analisi dei consumi (SPA e DPA)

Misurando l'assorbimento di corrente durante un'operazione crittografica si risale alla chiave: l'analisi semplice (SPA) legge il consumo di una singola esecuzione, quella differenziale (DPA) correla statisticamente migliaia di tracce. È la tecnica che svuota smart card e token hardware. Difesa: implementazioni a tempo e consumo costanti, mascheramento dei dati intermedi con valori casuali, filtraggio e disaccoppiamento dell'alimentazione, e preferenza per algoritmi e librerie progettati come resistenti ai canali laterali.

Analisi elettromagnetica e acustica

Le stesse informazioni dei consumi trapelano dalle emissioni elettromagnetiche del chip e persino dal rumore dei componenti: è dimostrata l'estrazione di chiavi RSA dal ronzio ad alta frequenza dei condensatori (ricerca di Genkin, Shamir e Tromer) o dal LED di un hard disk. Si lega al tema TEMPEST già visto nella compromissione elettromagnetica. Difesa: schermatura e distanza, generazione di rumore di copertura, componenti di qualità, ed evitare di eseguire operazioni sensibili con microfoni, fotocamere o sensori nelle vicinanze.

Rowhammer

Accedendo ripetutamente e molto rapidamente a una riga di celle DRAM si inducono per disturbo elettrico inversioni di bit nelle righe adiacenti, senza mai accedervi. Da qui si ottengono scalate di privilegi e manomissione di dati altrui, anche da codice non privilegiato o da JavaScript in un browser. Difesa: RAM con ECC e, meglio ancora, con Target Row Refresh; evitare la condivisione fisica della memoria con codice non fidato (niente tenant ostili sullo stesso ferro, coerente con l'air-gap per i nodi sensibili); kernel e microcodice aggiornati.

Esecuzione speculativa (Spectre e Meltdown)

Le CPU moderne eseguono istruzioni in anticipo e in modo speculativo, lasciando tracce nella cache che permettono di leggere memoria di altri processi o del kernel. Sono vulnerabilità della microarchitettura, non del codice. Difesa: microcodice e kernel aggiornati, isolamento dei processi sensibili su core o macchine dedicate, e per i nodi più critici la rinuncia alla condivisione della stessa CPU con carichi non fidati.

PoC di verifica: controllare quali canali laterali della CPU il sistema dichiara mitigati:

# Linux: stato delle mitigazioni note (Spectre, Meltdown, etc.) grep -r . /sys/devices/system/cpu/vulnerabilities/

La postura paranoica

Nessuna singola misura basta: conta la combinazione. In sintesi, Tutanum riduce al minimo la superficie fisica (meno radio, meno porte, meno interfacce), preferisce hardware aperto e autoprodotto, applica tamper-evidence in modo sistematico (foto, impronte dei firmware, sigilli), unisce boot misurato e cifratura del disco, schermatura RF e, per i nodi più sensibili, l'isolamento fisico dalla rete (air-gap). Il presupposto di fondo è sempre lo stesso: dare per scontato che l'avversario possa aver avuto accesso al ferro, e costruire in modo che anche in quel caso resti il più possibile cieco.