Passa al contenuto principale
Versione: 1.0.0

bitcollector

bitcollector legge un host e pubblica ciò che trova. Non scrive mai sull'host.

Risponde alla domanda "cosa c'è su questa macchina e in che stato si trova" — in modo continuo, su tutta la flotta, in una forma che puoi consegnare a un auditor e difendere.

Release0.1.0-ga, commit 8819759, compilato con go1.25.12
PiattaformeLinux amd64/arm64, macOS amd64/arm64, Windows amd64 — vedi piattaforme
Supply chainBuild riproducibile, SBOM CycloneDX, firma cosign, attestazione dell'SBOM, SHA256SUMS firmato
Superficie di rete in ingressoNessuna. L'unico listener è solo su loopback
Scritture sull'hostLa propria directory dati e il proprio file di log — più qualunque file tu chieda esplicitamente a export-pubkey di scrivere

Prima di eseguirlo, verifica il download.

Cosa raccoglie e quanto costa eseguirlo li trovi qui sotto. Due cose che fa sono abbastanza rilevanti da meritare una pagina a sé: la catena delle evidenze — la firma, la concatenazione e la verifica offline che rendono il dato difendibile — e privacy e account locali, che è ciò che lo rende distribuibile in Francia senza discussioni.

Cosa raccoglie​

Nove collector, ciascuno abilitabile in modo indipendente e ciascuno con il proprio intervallo:

CollectorCosa riporta
processProcessi in esecuzione. Le righe di comando sono disattivate per impostazione predefinita — vedi Privacy
portPorte in ascolto
softwarePacchetti installati
systemHardware e sistema operativo
metricsMetriche delle risorse dell'host
networkInterfacce e peer stabiliti
posturePostura di sicurezza attiva — vedi Postura
accountsAccount locali privilegiati e dormienti — vedi Account
fileInput da log e file (ad attivazione esplicita; disabilitato nella configurazione fornita)

Due regole valgono per tutti:

  • Ogni record porta con sé il timestamp di raccolta e il collector che lo ha prodotto.
  • "Assente" e "non autorizzato a guardare" non sono mai la stessa risposta. Un collector che non può essere eseguito riporta il motivo, come valore di prima classe. Un agente senza privilegi che non può leggere /etc/shadow riporta unknown con la ragione — non riporta mai un certificato di buona salute che non ha osservato.

Quella seconda regola non è un vezzo. Un inventario che riporta in silenzio "nessun rilievo" quando in realtà gli è stato negato il permesso è peggio di nessun inventario, perché su quello agirai.

Postura: osservata, non presunta​

Il collector posture è l'input che trasforma migliaia di rilievi in quella manciata che conta davvero: "CVE presente, ma il controllo Y risulta verificato come applicato."

Tutto ciò che riporta è stato dell'host osservato, mai un file di configurazione:

ControlloLetto da
SELinux/sys/fs/selinux/enforce — il kernel in esecuzione
AppArmor/sys/module/apparmor/…, /sys/kernel/security/apparmor/…
FirewallIl ruleset nftables/iptables/ip6tables attivo, entrambe le famiglie di indirizzi
sshdsshd -T (con fallback su sshd -G) — il parsing del demone stesso, che segue le direttive Include
Sysctl/proc/sys/… — non /etc/sysctl.conf

La distinzione è il prodotto. Un file di configurazione dice cosa qualcuno intendeva fare. sshd -T dice cosa sshd farà davvero. Le due cose differiscono più spesso di quanto chiunque gradisca, ed è proprio quello scarto a far fallire gli audit.

È in sola lettura: sei comandi di elencazione con argv fisso attraverso un'allowlist, nessuna shell, ogni file aperto in O_RDONLY. Gira senza privilegi e riporta, per ciascun controllo, se il controllo era assente o se l'agente non era autorizzato a guardare. L'esecuzione come root (o con CAP_NET_ADMIN) fornisce in più il ruleset del firewall e l'inventario dei profili AppArmor.

Il change feed​

La telemetria a stato completo a ogni ciclo è ciò che spinge un DBA a mettere il veto sul tuo rollout. Il change feed (A4) invia solo ciò che è cambiato.

Misurato su un host di riferimento reale, pubblicato insieme alla forma dell'host che lo ha prodotto:

Baseline a stato completo284.57 KB/ciclo (media di 4 cicli consecutivi da 60s, scarto dello 0.53 %)
Delta effettivo6.55 KB medi, 7.84 KB p95, 10.57 KB nel caso peggiore — entro il budget su tutti i 21 cicli
Forma dell'host558 processi, 714 pacchetti, 45 porte in ascolto, 71 connessioni stabilite, 32 interfacce, 6 collector, command_line: off, non root

L'86.36 % dei byte nei collector di tipo elenco si ripete alla lettera a ogni ciclo, e circa il 13 % dei record di processo "cambia" a ogni ciclo per i soli valori campionati di CPU e memoria — ed è per questo che si tratta di una separazione di schema (fatti del parco macchine rispetto ai campionamenti) e non di un algoritmo di diff. Un diff ingenuo a livello di record ha misurato solo 7.4×, ancora ben oltre il budget.

Un flusso di delta si ricostruisce esattamente nello stesso stato di uno snapshot completo, e uno snapshot completo riancora il flusso a intervalli regolari (snapshot_interval: 6h per impostazione predefinita), così un delta perso non può desincronizzare in silenzio la visione che la piattaforma ha di un host.

Il change feed è fornito DISATTIVATO, ed è deliberato

delta.enabled: false nella configurazione fornita, e attivarlo è necessario ma non sufficiente: l'agente richiede in più che il control plane dichiari di comprendere il protocollo, e continua a inviare lo stato completo finché non lo fa.

Quel secondo cancello è nel codice anziché in un runbook perché la modalità di guasto è silenziosa. Un delta inviato a un ricevitore che non lo comprende viene inoltrato a valle come se fosse un payload completo — cosa che non produce errori, ma corrompe in silenzio l'immagine che la piattaforma ha del tuo parco macchine. Attivalo quando il tuo tenant Cert-IX lo supporta, non come effetto collaterale di un'altra modifica.

Due domini non viaggiano affatto sul percorso delta: posture e accounts sono pubblicati solo sul percorso completo, quindi un agente con il change feed attivo non li invierebbe. Quel limite è dichiarato nel file di configurazione fornito, non lasciato da scoprire.

Sicuro da eseguire in produzione​

Lo scopo di questa sezione è darti il permesso di installarlo su una macchina che conta.

I limiti di risorse sono applicati, non documentati.

agent:
max_memory_mb: 50
max_cpu_percent: 80
  • max_memory_mb viene applicato come limite di memoria del runtime Go, così il garbage collector lavora progressivamente di più per restare al di sotto. Copre l'heap Go, gli stack delle goroutine e le strutture del runtime. Non è un OOM killer: superarlo rende l'agente più lento, mai morto — un agente che si suicida sotto pressione di memoria smette di essere evidenza esattamente quando sta accadendo qualcosa di interessante.
  • max_cpu_percent è un tetto sul ciclo di lavoro dell'agente stesso, come percentuale di un core (80 = 0.8 core). L'applicazione avviene per differimento: quando la media a finestra scorrevole supera il tetto, il tick di raccolta successivo viene saltato e conteggiato. La consegna, gli heartbeat, la coda di replay e l'endpoint di salute locale non vengono mai differiti — un host sotto carico deve comunque poter inviare ciò che ha già.

Il differimento è visibile quando accade:

Collection tick DEFERRED: this agent is above agent.max_cpu_percent. Delivery and
heartbeats are unaffected; the deferral is counted on the local health endpoint so a
permanently throttled agent cannot pass for a quiet host

Zero superficie di rete in ingresso. L'unico listener è un endpoint locale di salute/metriche, e si lega solo al loopback — 127.0.0.1 e [::1], come due listener espliciti, con gli indirizzi di bind come costanti di compilazione. Non esiste una chiave di configurazione per allargarlo, perché un listener che un operatore può allargare prima o poi viene allargato.

curl -s 127.0.0.1:9713/status

Un watchdog riavvia un collector bloccato senza riavviare l'agente. Lento e bloccato sono distinti per misurazione, non per congettura: lento significa che il collector risponde in ritardo (già riportato come timeout); bloccato significa che il suo contesto è stato annullato e non è ancora rientrato. La rotazione dei log elimina per dimensione e per età, così l'agente non può riempirti /var e regalarti un'interruzione di servizio.

Store-and-forward. La telemetria che non è stato possibile consegnare viene ritentata con backoff e consegnata quando il gateway torna disponibile. Un 401 sul percorso della telemetria aggiorna il token e riprova. Ciò che non è stato possibile consegnare è attribuibile — un buco non è mai indistinguibile da "non esistevano dati".

Come eseguirlo​

bitcollector è un singolo binario statico. Verificalo prima (come), poi:

# Check what you have
bitcollector --version
# bitcollector 0.1.0-ga (commit: 8819759, built: 2026-08-09T12:08:13Z)

# Run with a configuration file
bitcollector -config /etc/bitcollector/bitcollector.yaml

# Turn up the detail while you are setting it up
bitcollector -config /etc/bitcollector/bitcollector.yaml -log-level debug

Le variabili d'ambiente hanno la precedenza sui valori del file di configurazione:

VariabileScopo
CERTIX_TENANT_IDIl tuo tenant, da Settings → Organization
CERTIX_ENROLLMENT_TOKENToken di enrolment monouso, generato nella dashboard. Obbligatorio a meno che non siano configurati certificati client mTLS
CERTIX_GATEWAY_URLAgent Gateway (registrazione, refresh del token, policy)
CERTIX_INGEST_URLAgent Ingestion Gateway (heartbeat, telemetria)
CERTIX_TLS_CA_CERT / CERTIX_TLS_CLIENT_CERT / CERTIX_TLS_CLIENT_KEYMateriale mTLS

L'agente si rifiuta di avviarsi anziché funzionare senza un'identità che possa dimostrare:

ERROR: Failed to load configuration: missing required configuration:
control_plane.enrollment_token (CERTIX_ENROLLMENT_TOKEN) required when mTLS client
certificates are not configured

Regolare quanto costa​

I valori interval: e timeout: per collector vengono rispettati. Ogni collector abilitato gira sul proprio intervallo e riempie una cache; un tick di pubblicazione separato, a agent.collection_interval, invia un unico batch che trasporta i domini che hanno prodotto dati nuovi.

Quota misurata di ciascun collector all'interno di un batch, così puoi regolare su numeri reali anziché a intuito (5 cicli a 60s, non root, command_line: off):

CollectorQuota del batch
process89.79 %
software6.85 %
port1.86 %
system1.20 %
network0.27 %
metrics0.01 %

Il collector di cui allungare l'intervallo se vuoi meno byte è process, non software.

Non esiste un valore che significhi "illimitato"

timeout: 0s significa "non configurato": viene usato il valore predefinito interno e l'agente registra un avviso nominando la chiave. Non è un modo per dire "prenditi tutto il tempo che ti serve" — tutti i collector condividono un'unica goroutine dello scheduler, quindi un'esecuzione che nulla può annullare blocca anche la pubblicazione, l'heartbeat e ogni altro collector. Imposta il tempo massimo che un'esecuzione sana richiede su questo host, con un margine.

Piattaforme​

0.1.0-ga pubblica cinque binari firmati, e non viene trattenuto nulla — bitcollector è l'unico bit distribuito su tutte le piattaforme a cui punta la famiglia:

PiattaformaPubblicataNote
Linux amd64Sì
Linux arm64Sì
macOS amd64Sì
macOS arm64Sì
Windows amd64SìDistribuito come bitcollector-windows-amd64.exe

Può farlo perché legge, e ogni collector ha un'implementazione per sistema operativo, con una risposta esplicita «non disponibile qui» dove una piattaforma non ha un equivalente. Gli altri tre bits trattengono ciascuno almeno una piattaforma, e ognuna delle loro pagine dice quale e perché — bitscanner, bitenforcer, bitmapper.

Essere distribuito su una piattaforma non equivale a osservarvi tutto. I controlli che l'agente non legge su un dato sistema operativo sono riportati con uno stato distinto — non supportato dall'agente su questa piattaforma — che porta la piattaforma come origine e un'istruzione esplicita a non valutare il controllo come assente. È un'affermazione sull'agente, mai un riscontro sull'host.

È la stessa regola valida ovunque in questa pagina: assente, non autorizzato a guardare e non osservato su questa piattaforma sono tre risposte diverse, e nessuna di esse è un certificato di buona salute.

Passi successivi​

Questa pagina ti è stata utile?