Alcune parti di questa pagina sono ancora in inglese: il testo originale in inglese è stato modificato dopo la traduzione.
Riferimento / Configurazione
Phala / Intel TDX · Implementazione ad alta sicurezza
Un server protetto attivo 24 ore su 24, 7 giorni su 7 su Hetzner o Phala Cloud, un DNS Gateway e controlli ripetibili da parte di terzi.
TgWitness / Documentazione · Implementazione e ripristino
L’implementazione ad alta affidabilità aggiunge controlli indipendenti dell’ambiente di raccolta alla verifica dell’archivio. Il revisore interroga i registri di implementazione e di accesso conservati dal fornitore di servizi cloud e da Cloudflare, mentre un’implementazione Intel TDX aggiunge l’attestazione hardware dell’ambiente del collettore.
L'utilizzo standard in locale e con Docker rimane invariato. Nulla qui funziona a meno che non si esegua la distribuzione con
python -m tgwitness.cloud, e il collector legge il proprio host solo quando la distribuzione imposta
TGWITNESS_ASSURANCE.
Diagramma sotto forma di testo
- Operatore → Server, firewall senza regole in entrata (API del provider)
- Operatore → Tunnel e DNS (API di Cloudflare)
- Server, firewall senza regole in entrata → Tunnel e DNS (solo in uscita)
- Server, firewall senza regole in entrata → Chiave di firma generata sul server
- Verifier, token di sola lettura → Log del provider e firewall
- Verifier, token di sola lettura → Indirizzo del connettore Tunnel e ingresso
- Verifier, token di sola lettura → Dichiarazione /api/assurance firmata
- Verifier, token di sola lettura → File ZIP contenente le prove
In questa pagina
- Cosa può verificare un verificatore
- Fornitori
- VM riservata su Phala Cloud (Intel TDX)
- Prima di iniziare
- Dal pannello
- Tunnel rapido senza dominio
- Distribuzione
- Debug della distribuzione e blocco
- Rimuovere una distribuzione
- Qualsiasi server (autocertificato)
- Verifica
- Rapporto per la consegna delle prove
- Cloudflare come testimone esterno
- Lettura del risultato della distribuzione
Cosa può verificare un verificatore#
| Affermazione | Come viene verificato | A cura di |
|---|---|---|
| Il server è stato creato tramite l’API del provider in un momento ben preciso | Oggetto Server e la sua creazione nel log del provider stesso | Fornitore |
| Nessuno ha utilizzato i percorsi di accesso del provider | Registro delle richieste della console, operazioni di ripristino, reimpostazione della password, ricostruzione, ISO, immagini, backup | Fornitore |
| Non è possibile connettersi ad esso | Il firewall del provider non ha regole di ingresso; l’accesso SSH viene nascosto sin dal primo avvio | Provider (firewall), host (SSH) |
| È possibile accedere al pannello solo tramite il tunnel | L'ingresso del tunnel inoltra esclusivamente al pannello; il connettore parte dall'indirizzo del server | Cloudflare |
| Questo stesso software funziona | L’hash firmato dell’albero dei sorgenti del collector corrisponde a un checkout del commit distribuito | Collector, sincronizzato con Git |
| La chiave di firma è stata creata su quel server | La chiave firma una dichiarazione in cui vengono indicati l’ID del server del provider e l’hash del file cloud-init ricevuto | Collector, verificato dal provider |
| Il diario appartiene a quella chiave e a quel server | Ogni avvio di processo nella prova ZIP riporta la misurazione dell’host per quel server | Prove ZIP |
Il collettore registra lo stato SSH, le sessioni, la cronologia degli accessi e le informazioni di avvio in record firmati
di avvio del processo e host.state. Su una macchina virtuale standard si tratta di record di inventario
locali, che il revisore confronta con i record indipendenti del provider. L’
implementazione Intel TDX riportata di seguito verifica inoltre le misurazioni supportate dall’hardware.
Fornitori#
--provider |
Credenziali | Accesso in sola lettura per il Verificatore | Log del provider per il verificatore | Conservato per |
|---|---|---|---|---|
hetzner |
HCLOUD_TOKEN |
Leggi il token dello stesso progetto | Azioni relative al server e al firewall | Finché le risorse sono disponibili |
digitalocean |
DIGITALOCEAN_TOKEN |
Token di accesso personale in sola lettura | Azioni di Droplet | Finché il Droplet esiste |
linode |
LINODE_TOKEN |
linodes, firewall, events ambiti di sola lettura |
Eventi relativi agli account, versioni delle regole del firewall | 90 giorni |
vultr |
VULTR_API_KEY |
Utente con accesso in lettura e il activity_logs autorizzazione |
Registro delle attività dell’account (metodo, percorso, autore) | 30 giorni, o più a lungo con un abbonamento al registro di audit |
aws |
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY |
ec2:DescribeInstances, ec2:DescribeSecurityGroups, cloudtrail:LookupEvents |
Cronologia degli eventi di CloudTrail | 90 giorni |
phala |
PHALA_CLOUD_API_KEY |
Una chiave API dello stesso spazio di lavoro | Revisioni dell’applicazione e operazioni CVM: modifiche alla configurazione e all’ambiente di Docker Compose, riavvii, aggiornamenti del sistema operativo | Sebbene l’applicazione esista |
generic |
nessuno | nessuno | nessuno: autocertificato | – |
Utilizzare un progetto, un team, un account o un sottoaccount dedicato per ogni caso: l’accesso
in sola lettura del verificatore mostrerà quindi solo questa distribuzione. Le credenziali vengono lette dal
--provider-token-file dalla variabile sopra indicata, mai dalla riga di comando. Per AWS il file
contiene ACCESS_KEY_ID SECRET_ACCESS_KEY [SESSION_TOKEN]; la regione è --location.
Ciò che i registri di ciascun provider non possono mostrare è riportato in ogni rapporto. In breve: Hetzner registra le richieste alla console; la Recovery Console di DigitalOcean, Lish/Glish di Linode e la console web di Vultr non vengono registrate in quanto tali, quindi l’account root è bloccato al primo avvio e un accesso alla console richiederebbe una reimpostazione della password o una modifica delle impostazioni di avvio, operazioni che vengono registrate. Vultr restituisce l’indirizzo della console a qualsiasi chiave in grado di leggere l’istanza; né la registrazione né il rapporto lo memorizzano.
VM riservata su Phala Cloud (Intel TDX)#
Con --provider phala il collector viene eseguito in una macchina virtuale riservata Intel TDX su
Phala Cloud, gestita da dstack. L’host e il personale di Phala non possono leggere la sua
memoria, e il processore firma un attestato relativo a ciò che la macchina ha avviato. Il verificatore non
si limita a fidarsi della parola di Phala: tgwitness.tdx verifica personalmente ogni attestato, fino alla Root CA Intel
SGX fissata, confrontandolo con gli elenchi di revoca di Intel e i dati della piattaforma firmati da Intel, e rifiuta
le macchine che possono essere sottoposte a debug o migrate.
| Inserimento di una segnalazione | Cosa mostra |
|---|---|
tdx_binding |
L’attestato comprende la dichiarazione firmata del raccoglitore e il valore casuale di questa richiesta |
tdx_quote |
Intel garantisce la validità dell’attestazione; questa viene rilasciata solo quando Intel valuta la piattaforma come aggiornata |
tdx_compose_hash |
RTMR3, riprodotto dal log degli eventi di dstack, misura i dati di composizione dell’app riportati dal collector |
tdx_compose |
Quel codice è, byte per byte, quello generato dal commit distribuito: file sorgente identificati tramite hash, entrambe le immagini tramite digest, nessun altro codice |
tdx_identity |
L’attestazione proviene dall’applicazione e dall’istanza distribuite, con chiavi provenienti dal KMS di Phala e da un disco crittografato |
tdx_os |
MRTD e RTMR0-2 corrispondono ai valori che il verificatore calcola dall’immagine del sistema operativo dstack pubblicata da Dstack-TEE, individuata tramite l’hash dell’immagine del sistema operativo segnalato dalla CVM, e dalle tabelle ACPI che QEMU genera per la configurazione della VM: firmware, kernel, initrd, riga di comando con l’hash del filesystem root, memoria, vCPU e dispositivi. Un’immagine di sviluppo non supera il controllo |
The OS image (about 180 MB, of which 21 MB are kept) is downloaded once from
Dstack-TEE/meta-dstack into
dstack-images beside the record; --tdx-image FOLDER uses another folder or an unpacked image,
--tdx-image none skips the comparison. The measurement follows dstack-mr and the qemu-acpi
crate of Dstack-TEE/dstack. Private measurement regressions compare QEMU's own ACPI
output and a retained Phala Cloud quote; live qualification also needs the published image.
--tdx-measurements still compares MRTD and RTMR0-2 given as JSON instead.
Ogni avvio del collettore registrato nel registro è accompagnato da tale attestato, pertanto
verify --evidence verifica ogni avvio e l’immagine del sistema operativo da cui è stato avviato. Le revisioni dell’applicazione di Phala
e le operazioni del CVM fungono da registro del provider: una configurazione di Docker Compose modificata dopo la distribuzione comporta il fallimento
del rapporto, e i riavvii vengono elencati per la revisione.
Nel pannello, selezionare «Macchina virtuale riservata · Phala Cloud» in «Extra → Server 24/7» e incollare una chiave API di Phala Cloud; il tunnel rapido funziona come su Hetzner. Dalla riga di comando:
python -m tgwitness.cloud deploy --provider phala --name case-1 --server-type tdx.small \
--ref v0.8.0 --repository https://github.com/phishdestroy/TgWitness --quick-tunnel \
--provider-token-file phala-key.txt
python -m tgwitness.cloud verify --record deployments/case-1/deployment.json \
--provider-token-file phala-key.txt --cloud-init deployments/case-1/docker-compose.yaml \
--source CHECKOUT_OF_COMMIT --fingerprint COLLECTOR_FINGERPRINT --report certificate.md
python -m tgwitness.cloud check-report --report certificate.pdf --verifier-fingerprint VERIFIER_KEY
--tdx-collateral Legge i certificati e gli elenchi di revoca di Intel da un file invece di
scaricarli dal sito di Intel. Il DNS gateway non è disponibile in questo caso: Phala non dispone di un firewall del provider
per il traffico in uscita.
Certificato di attestazione#
Per una distribuzione Phala, verify --report certificate.md scrive anche il certificato: un
certificate.html autonomo e un certificate.pdf in formato A4 contenente il verdetto, la catena di fiducia
dalla radice Intel alla chiave del collettore, un confronto tra server standard e ad alta sicurezza,
le misurazioni accanto ai valori calcolati dall’immagine pubblicata, chi garantisce per ciascuna
parte, la catena di certificati Intel, ogni controllo, il log del provider e le modalità per ripetere la
verifica. Il rapporto JSON rimane il documento ufficiale; le pagine ne riportano il contenuto.
Il rapporto è sigillato digitalmente con firme e timbri temporali, nel file certificate.seal.json e nei file .tsq/.tsr ad esso associati:
| Sigillo | Cosa offre in più |
|---|---|
Timbro temporale elettronico qualificato, http://tsa.belgium.be/connect |
Timestamp RFC 3161 sui byte esatti di certificate.json proveniente dal fornitore di servizi di fiducia qualificato del governo federale belga (FPS Policy and Support, BOSA). Tale entità è elencata come servizio di marcatura temporale qualificato, con stato «concesso», nell’elenco di fiducia dell’UE del Belgio; la radice (Belgium Root CA6) e le voci dell’elenco, secondo l’elenco pubblicato il 20 ottobre 2026, sono fissate in tgwitness/tsa_roots.py. Ai sensi dell’articolo 41 del Regolamento (UE) n. 910/2014, tale marcatura temporale è ritenuta accurata per quanto riguarda la data e l’ora, nonché l’integrità dei dati in ogni Stato membro dell’UE |
| Timestamp RFC 3161, FreeTSA | Un secondo timestamp indipendente |
| Firma del verificatore | Ed25519 su un’istruzione che indica lo SHA-256 del rapporto e ogni timestamp, utilizzando la chiave del verificatore stesso (--sign-with FOLDER, predefinita ~/.tgwitness/verifier); il PDF reca una firma generata con la stessa chiave |
--timestamp URL (ripetibile) sceglie altre autorità, --timestamp none nessuna, --sign-with
none lascia il sigillo non firmato. check-report verifica l’hash del rapporto, la firma del verificatore,
ogni timestamp rispetto a una radice attendibile e il suo stato qualificato, nonché la firma del PDF. Il valore
giuridico di un timbro temporale qualificato al di fuori dell’UE, nonché del rapporto nel suo complesso, spetta al tribunale
o all’autorità che lo riceve; il sigillo attesta quando il rapporto è stato creato e che non ha subito modifiche.
Un'attestazione non può escludere la presenza di una vulnerabilità nel modulo TDX o nel microcodice di Intel, né l’accesso fisico al bus di memoria. Chiunque controlli l’applicazione nell’account di Phala può distribuire un altro “compose”; questo appare come una nuova revisione con un nuovo hash del “compose”. L’host controlla la fonte dell’ora della macchina e la rete.
L’implementazione, la verifica con --evidence, i riavvii, il confronto delle immagini del sistema operativo, il certificato sigillato digitalmente con firme e timbri temporali e
la distruzione sono stati eseguiti su Phala Cloud stesso; si veda
, l’esecuzione del 4 novembre 2026, .
Prima di iniziare#
- Una zona Cloudflare, il relativo ID account e un token API con le autorizzazioni Cloudflare Tunnel Edit,
Zone Read e DNS Edit, fornito con
--cloudflare-token-fileoppureCLOUDFLARE_API_TOKEN. Per il verificatore: Cloudflare Tunnel Read, DNS Read e, per il registro di audit, Account Settings Read. Senza un dominio, un tunnel rapido non necessita di nulla di tutto ciò. - Credenziali del provider con accesso in scrittura a un progetto dedicato;
lockutilizza lo stesso:- Hetzner: token API con autorizzazioni di lettura e scrittura;
- DigitalOcean: token di accesso personale con diritti di scrittura;
- Linode: token di accesso personale con
linodes,firewalleeventsambiti di lettura/scrittura; - Vultr: chiave API di un account dedicato o di un sottoaccount;
- AWS: credenziali IAM consentite
ec2:DescribeVpcs,ec2:DescribeImages,ec2:CreateSecurityGroup,ec2:AuthorizeSecurityGroupIngress,ec2:RunInstances,ec2:CreateTags,ec2:DescribeInstances,ec2:DescribeSecurityGroupRuleseec2:RevokeSecurityGroupIngress.
- Il commit da eseguire. Un tag di rilascio viene risolto una sola volta nel suo commit con
git ls-remote; il server riceve sempre e solo il commit di 40 caratteri.
Dal pannello#
Sul proprio computer, la voce Extras → Server 24/7 esegue la stessa operazione deploy per Hetzner in tre
passaggi: scegli Europa o Stati Uniti, incolla un token Hetzner (Lettura e Scrittura), quindi verifica
il tipo di server, il prezzo mensile, l’indirizzo e la versione che il pannello ha individuato con quel token. Nulla
viene creato prima della tua conferma. Il pannello mostra ogni passaggio come deploy viene segnalato, quindi l’
indirizzo, il token del pannello e l’impronta digitale della chiave di firma. Senza un dominio, il server ottiene un
tunnel rapido
; “I tuoi server” → “Trova l’indirizzo attuale”
lo ricerca nuovamente dopo un riavvio. Per un indirizzo fisso sotto il proprio dominio, apri
“Opzionale” · “Il tuo dominio”
e aggiungi un token Cloudflare (il link preparato seleziona “Lettura zona”,
“Modifica DNS” e “Modifica tunnel Cloudflare”).
I token viaggiano con ogni richiesta dalla scheda del browser all’TgWitness sullo stesso computer
e non vengono scritti da nessuna parte; il registro di distribuzione, il file cloud-init redatto, il token del pannello e,
per un tunnel rapido, la chiave dell’indirizzo sono conservati deployments/NAME all’interno della directory dei dati.
Il pannello offre questo servizio solo all’amministratore principale tramite una connessione loopback diretta
(127.0.0.1, senza intestazioni proxy o tunnel); un pannello raggiungibile tramite rete mostra invece i comandi
. La versione predefinita è il tag di rilascio del pannello in esecuzione, risolto tramite l’
API di GitHub. Posizione, tipo di server e prezzo provengono dall’API di Hetzner: cpx22 laddove è
disponibile, altrimenti il tipo x86 più economico con almeno 2 GB di memoria.
Tunnel rapido senza dominio#
--quick-tunnel sostituisce --zone, --cloudflare-account e --panel-host; non è coinvolto alcun
account o token Cloudflare:
python -m tgwitness.cloud deploy --provider hetzner --name case-2026-11 --server-type cpx22 \
--ref 0123456789abcdef0123456789abcdef01234567 --quick-tunnel --provider-token-file hetzner.token
Sul server, cloudflared apre un
tunnel veloce
verso il pannello: un indirizzo casuale https://….trycloudflare.com che cambia ogni volta che cloudflared
o il server si riavvia. Un piccolo servizio sul server pubblica ogni indirizzo in un argomento casuale di ntfy.sh
, firmato (HMAC-SHA256) con una chiave presente solo nella directory di distribuzione
(address-key.txt), e lo ripete ogni tre ore poiché ntfy.sh conserva i post per 12.
deploy e "Trova l’indirizzo attuale" accettano solo post firmati, quindi un post contraffatto non può
inviare te e il tuo token del pannello all’indirizzo di qualcun altro. L’argomento è presente nel registro e nel
cloud-init pubblicato: chiunque ne disponga può leggere l’indirizzo corrente, che richiede comunque il
token del pannello. Il server non mantiene alcuna porta in entrata in entrambi i casi.
Un verificatore non possiede una chiave di indirizzo e chiunque legga l’argomento può pubblicarvi un post. Pertanto, il collettore
pubblica anche l’indirizzo stesso, firmato con la propria chiave Ed25519, e verify prende il post più recente
firmato dalla chiave del collettore nel record di distribuzione; i post sono ordinati in base all’ora in cui ntfy.sh
li ha ricevuti, non all’ora che essi dichiarano. Un collettore precedente a questa modifica non firma nulla, e
verify prende quindi il messaggio più recente e lo indica nel controllo statement; un messaggio contraffatto può
solo far fallire tale controllo, poiché l’indirizzo deve comunque rispondere con la chiave del collettore.
Costi: nessun account Cloudflare conserva registrazioni relative a un tunnel temporaneo, pertanto verify segnala il
tunnel, il connettore e il controllo DNS come non disponibili e il risultato è, nella migliore delle ipotesi, incomplete (su Phala
Cloud il controllo viene invece superato: il connettore viene eseguito all’interno della configurazione Docker Compose sottoposta a misurazione); i
registri del provider, il firewall, la dichiarazione firmata, le misurazioni dell’host e il confronto con il programma di installazione vengono
verificati come di consueto. Il confronto a livello di byte con il programma di installazione di riferimento richiede un commit distribuito
che riconosca già --quick-tunnel; un checkout della versione 0.7.0 compila il programma di installazione del dominio e segnala
la differenza. Cloudflare non garantisce l’uptime dei tunnel rapidi, consente 200 richieste in
corso e non supporta i Server-Sent Events; pertanto, gli aggiornamenti in tempo reale del pannello (versioni successive alla 0.7.0)
potrebbero non arrivare tramite un tunnel di questo tipo e potrebbe essere necessario ricaricare la pagina; tale aspetto non è stato ancora testato. Per un caso
in cui sia necessario garantire la disponibilità, si raccomanda di utilizzare il proprio dominio.
Distribuzione#
Controlla prima tutto ciò che verrà inviato. plan Non effettua alcuna richiesta al provider né a Cloudflare:
python -m tgwitness.cloud plan --provider hetzner --name case-2026-11 --server-type cpx22 \
--ref 0123456789abcdef0123456789abcdef01234567 --zone example.org \
--cloudflare-account CLOUDFLARE_ACCOUNT_ID --panel-host case.example.org
Quindi eseguire il deploy con le stesse opzioni e le credenziali:
python -m tgwitness.cloud deploy --provider hetzner --name case-2026-11 --server-type cpx22 \
--ref 0123456789abcdef0123456789abcdef01234567 --zone example.org \
--cloudflare-account CLOUDFLARE_ACCOUNT_ID --panel-host case.example.org \
--witness-host case-witness.example.org \
--provider-token-file hetzner.token --cloudflare-token-file cloudflare.token
Tipi di server con cui iniziare: cpx22 (Hetzner), s-1vcpu-2gb (DigitalOcean), g6-standard-1
(Linode), vc2-1c-2gb (Vultr), t3.small (AWS). --location e --image per impostazione predefinita, Ubuntu 24.04 di ciascun
provider in una regione europea.
--repository Prende il commit da un altro repository Git https, senza credenziali nell’
URL (per impostazione predefinita https://github.com/phishdestroy/TgWitness.git). deploy accetta anche --out
per un’altra directory di distribuzione (per impostazione predefinita deployments/NAME; una directory che contiene già una
distribuzione viene rifiutata) e --wait, i minuti di attesa per la dichiarazione firmata dal collector:
da 1 a 240, predefinito 20, oppure 60 per generic.
Il comando:
- crea un tunnel Cloudflare il cui ingresso inoltra il nome host del pannello al pannello stesso e,
se specificato, il nome host del testimone a
/api/witness/heade/api/assurancesolo; - crea record CNAME proxy per quei nomi host, rifiutando quelli già esistenti;
- crea un firewall provider senza regole in entrata e un server dietro di esso senza chiave SSH,
senza backup, senza agente console e con cloud-init che maschera SSH, blocca l’accesso come root, installa
cloudflared, recupera esattamente il commit, lo verifica e avvia TgWitness come servizio systemd rinforzato; - attende la dichiarazione firmata dal collettore e verifica che indichi questo server e l’ hash di questo cloud-init.
deployments/case-2026-11/ contiene poi:
| File | Indice | Condividi? |
|---|---|---|
deployment.json |
ID, hash, le chiamate API effettuate (metodo, percorso, stato) e la prima dichiarazione firmata | Sì, con il verificatore |
cloud-init.redacted.yaml |
Il comando esatto di cloud-init con i suoi due segreti sostituiti da REDACTED |
Sì |
panel-token.txt |
Il token del pannello | No |
La password root del provider, il token del tunnel e il token del pannello non vengono mai scritti su
deployment.json. Pubblicate l’impronta digitale del collettore riportata alla fine tramite un canale
che non controllate da soli, ad esempio un canale testimone o un messaggio al destinatario.
Accedi a Telegram all’indirizzo https://case.example.org con il token del pannello, come indicato nella
guida all’account. Le azioni del pannello vengono registrate nel registro firmato; non si tratta di
sessioni SSH. Un testimone può interrogare https://case-witness.example.org.
Non è presente SSH: se il bootstrap fallisce, il collector non risponde mai. Eliminare il server e effettuare nuovamente la distribuzione, oppure utilizzare una distribuzione di debug per individuare la causa.
Segreti nei dati degli utenti#
Il cloud-init contiene due segreti: il token del pannello e il token del tunnel Cloudflare. La
chiave di firma non è tra questi; viene creata sul server. Hetzner, DigitalOcean e Linode
non restituiscono i dati degli utenti tramite le loro API. Vultr li restituisce a qualsiasi chiave in grado di leggere l’
istanza, mentre EC2 tramite DescribeInstanceAttribute. Per AWS, fornire al verificatore solo le tre
azioni riportate nella tabella, mai ec2:Describe*. Per Vultr, si supponga che la chiave del verificatore possa leggere entrambi i
token. Un token del tunnel consente a qualcuno di eseguire un secondo connettore: verify segnala qualsiasi connettore
che non si trovi sul server, e le dichiarazioni del collettore non possono essere falsificate in questo modo poiché ciascuna di esse
firma una nuova sfida. Con --quick-tunnel il secondo segreto è invece la chiave dell’indirizzo:
chiunque la legga può pubblicare un indirizzo falso che il pannello accetterebbe.
La dichiarazione pubblica del responsabile della raccolta omette l’indirizzo del server e le fonti degli accessi; entrambi rimangono nel registro firmato.
Debug, distribuzione e blocco#
--debug-ssh-key KEY --debug-ssh-from 198.51.100.4 Conserva SSH per una chiave proveniente da un unico indirizzo
o da una rete di piccole dimensioni, al massimo un /24 per IPv4 o un /48 per IPv6. KEY è già registrato presso
il provider: il nome o l’ID di una chiave SSH nel progetto Hetzner, l’ID o l’impronta digitale di una
chiave SSH nel team DigitalOcean, un nome utente Linode le cui chiavi SSH del profilo sono aggiunte a root,
l’ID di una chiave SSH nell’account Vultr o il nome di una coppia di chiavi EC2 nella regione. Queste
opzioni non si applicano a generic. Tale distribuzione viene registrata come debug e viene segnalata mai come
ad alta sicurezza. Al termine, esegui sudo tgwitness-lock come ultimo comando dell’ultima
sessione SSH, quindi:
python -m tgwitness.cloud lock --record deployments/case-2026-11/deployment.json --provider-token-file hetzner.token
Il firewall perde tutte le regole in entrata. I report mostrano quindi quando l’accesso SSH era consentito e quando era bloccato; quella finestra rimane visibile.
Rimuovi una distribuzione#
destroy Elimina il server e il relativo firewall, individuati tramite l’etichetta della distribuzione, in modo che venga rimossa anche una
distribuzione che ha fallito a metà, quindi i record DNS che puntano al relativo
tunnel e il tunnel stesso. Il registro del server e la chiave di firma vengono eliminati insieme ad essi: esportare prima le
prove. Il registro rimane, contrassegnato removed, con le chiamate API relative alla rimozione.
python -m tgwitness.cloud destroy --record deployments/case-2026-11/deployment.json --confirm case-2026-11 \
--provider-token-file hetzner.token --cloudflare-token-file cloudflare.token
La rimozione tramite l’API è implementata per Hetzner. Per gli altri provider destroy si interrompe prima di
eliminare qualsiasi cosa e indica l’etichetta da eliminare nella console del provider. Un server installato manualmente
(generic) perde solo il proprio tunnel e i record DNS. Una distribuzione rapida del tunnel non richiede alcun
token Cloudflare: il tunnel termina con il server e i relativi post scadono da ntfy.sh entro
12 ore.
Qualsiasi server (autocertificato)#
--provider generic È destinato a un server acquistato o installato manualmente. deploy crea il tunnel
e il DNS, scrive install.sh (privato) e install.redacted.sh (per la pubblicazione), quindi rimane in attesa.
Copiare install.sh su un server Ubuntu 24.04 appena installato ed eseguilo lì:
sudo bash install.sh
Registra l’host così com’era (accessi, account, authorized_keys, socket in ascolto,
servizi, attività pianificate, pacchetti), installa il commit, abilita il firewall dell’host, si elimina
da solo, maschera SSH e termina la sessione. Il report relativo a un server di questo tipo è, nella migliore delle ipotesi,
AUTOCERTIFICATO: chiunque abbia eseguito il programma di installazione disponeva già dei privilegi di root, e non è disponibile alcuna registrazione del provider
per il verificatore. È comunque meglio di un server di cui non si conosce l’origine: l’inventario,
l’hash del programma di installazione e ogni accesso successivo sono firmati.
Verificare#
Il verificatore necessita deployment.jsonl'installer pubblicato, credenziali in sola lettura e,
idealmente, un checkout del commit e una prova ZIP:
git clone -c core.autocrlf=false https://github.com/phishdestroy/TgWitness.git checkout
git -C checkout checkout 0123456789abcdef0123456789abcdef01234567
python -m tgwitness.cloud verify --record deployment.json \
--provider-token-file read-only.token --cloudflare-token-file cloudflare-read.token \
--fingerprint COLLECTOR_FINGERPRINT --cloud-init cloud-init.redacted.yaml \
--source checkout --evidence tgwitness-evidence.zip --report report.md
Ogni valore relativo al provider e a Cloudflare viene richiesto dal verificatore in quel momento; il record
fornisce solo gli ID da richiedere. Il codice di uscita è 0 per PASS, 1 per FAIL e 2 per
REVIEW, INCOMPLETE o SELF-ATTESTED. --fingerprint dovrebbe provenire da un canale indipendente
; in sua assenza, la chiave viene confrontata solo con il record dell’operatore. python verify.py
verifica comunque la prova ZIP, come in Evidence.
Le azioni del provider vengono classificate: la creazione e l’avvio entro 30 minuti dalla creazione vengono approvate; console, ripristino, reimpostazione password, ricostruzione, ISO, immagini, snapshot, backup, Systems Manager, EC2 Instance Connect e aperture del firewall vengono rifiutate; le azioni relative all’alimentazione e qualsiasi evento imprevisto vengono contrassegnati per la revisione. Un’azione sconosciuta non viene mai ignorata.
Rapporto per il trasferimento delle prove#
--report report.md scrive il report in Markdown e report.json accanto ad esso:
- risultato, impronta digitale della chiave del collector, distribuzione, provider, commit, server, firewall, tunnel;
- ogni verifica con il relativo stato e la fonte (API del provider, API di Cloudflare, dichiarazione del collettore, registro delle prove);
- il registro del fornitore con la valutazione di ciascuna azione e, laddove il fornitore lo registri, l’autore dell’azione;
- gli endpoint Cloudflare che contengono le connessioni del tunnel, la configurazione e il registro di audit;
- la dichiarazione firmata del collezionista;
- ciò che il rapporto stabilisce e ciò che non stabilisce;
- i comandi per riprodurlo e l’SHA-256 di ogni file che gli è stato fornito.
Consegnare il rapporto, report.json, deployment.json, il programma di installazione pubblicato e le
prove ZIP. Preparate il rapporto tempestivamente: i log dei provider vengono conservati per periodi limitati.
Cloudflare come testimone esterno#
Tutto ciò che è riportato qui è facoltativo. Anche senza un account Cloudflare il server continua a funzionare, e due di questi sono attualmente operativi:
| Cosa | Cosa mostra | In TgWitness |
|---|---|---|
| Tunnel rapido o tunnel del proprio dominio | È possibile accedere al pannello solo tramite il tunnel | la procedura guidata per il server, vedi sopra |
drand relay drand.cloudflare.com |
i registri successivi a un round di drand sono più recenti di esso: il diario è stato scritto man mano che si svolgeva | modalità prove, Altri testimoni, nessun account (formato) |
| Notifiche sullo stato del tunnel | quando il tunnel era inattivo, tramite e-mail o webhook da Cloudflare | Configurali nella dashboard di Cloudflare |
Gateway DNS (--gateway-dns, o Cloudflare Gateway DNS nella procedura guidata) |
ogni nome cercato dal server, a cui Cloudflare ha risposto tramite TLS; il firewall di Hetzner impedisce al DNS di raggiungere qualsiasi altra risorsa; se una politica del Gateway potesse riscrivere le risposte | Hetzner, piano Zero Trust gratuito, senza dominio; verify controlla il firewall, la posizione, la registrazione dei log, le politiche, le query del server e il registro di audit; la modalità "evidence" copia il log nel registro |
| Gateway con il client Cloudflare One sul server, un firewall in uscita che consente l’accesso solo a Cloudflare | ogni connessione effettuata dal server, non solo quelle DNS | non ancora realizzato |
| Accesso davanti al pannello | chi ha effettuato l’accesso al pannello e quando | non implementato: richiede un dominio proprio |
| Registrazione dei comandi SSH | ogni comando in una sessione di debug | non ancora realizzato |
Logpush, che conserverebbe una copia di Cloudflare in R2, è una funzionalità Enterprise: nel piano gratuito
Cloudflare risponde logpush is not enabled for this account. Il log del Gateway rimane lì per 24
ore, quindi la modalità "evidence" lo copia nel registro firmato (il log di Cloudflare Gateway relativo alle
query DNS di questo server, un token di sola lettura con Account Analytics Read).
Senza un piano Zero Trust, un account ha un’unica posizione DNS. Quando Cloudflare ne rifiuta un’altra,
il server condivide quella esistente e le sue query vengono distinte in base all’indirizzo; tale filtro
richiede anche Zero Trust PII Read e destroy lascia un’ubicazione condivisa. Una query di log copre
al massimo tre ore, quindi la copia e la verify leggere la giornata in finestre di tre ore.
Il DNS gateway gestisce il resolver di sistema. Il DNS over HTTPS sulla porta 443 verso un altro resolver e le connessioni a un indirizzo non presente in nessun elenco (come, ad esempio, i data center di Telegram) non vengono registrate nel suo log.
Cloudflare non può vedere all’interno della crittografia di Telegram, né gli altri dispositivi collegati all’account Telegram (l’elenco dei dispositivi in modalità “evidence” li registra dal lato di Telegram) né l’hypervisor del provider.
Lettura del risultato della distribuzione#
Per una macchina virtuale standard, il provider controlla l’infrastruttura host e l’inventario locale viene verificato insieme ai registri del provider. Per Intel TDX, il verificatore controlla inoltre le specifiche hardware, il binding del collector, le misurazioni di composizione e del sistema operativo. Leggere i singoli risultati per vedere quali controlli sono stati superati o non erano disponibili.
I dettagli storici relativi al firewall dipendono dal provider; Linode conserva le versioni delle regole. Il record di convalida elenca le implementazioni testate e i controlli attivi rimanenti, mentre l’ambito di verifica collega questi controlli ambientali all’acquisizione e all’integrità dell’archivio.