bitscanner
bitscanner trova i dispositivi che il tuo inventario non contiene.
bitcollector legge l'host su cui gira. bitscanner guarda verso l'esterno, da
quell'host verso il segmento che lo circonda — e la risposta che conta è quella che nulla nel
tuo elenco di asset spiega.
| Release | 0.1.3-ga, commit 7db3d4c, compilato con go1.25.12 |
| Piattaforme | Solo Linux amd64/arm64 — macOS e Windows non sono pubblicati, ed ecco perché |
| Supply chain | Build riproducibile (compilata due volte, rifiutata se non identica byte per byte), SBOM CycloneDX e attestazione cosign per singolo binario, gate sulle vulnerabilità, firma cosign per singolo binario e su SHA256SUMS |
| Superficie di rete in ingresso | Nessun servizio in ascolto. Nessuna porta di health, metriche o amministrazione, e nessuna chiave che ne apra una. Misurato con lo scanning disattivato: zero socket in ascolto. service_discovery, una volta armato, usa socket UDP effimeri e non vincolati; un datagramma che vi arriva diventa un record di inventario solo se risponde alla query appena inviata e proviene da allowed_cidrs — non verificato in 0.1.3-ga e versioni precedenti, vedi sotto |
| Traffico in uscita | Solo https, verso gli endpoint che configuri. Nessun redirect viene mai seguito |
| Scritture sull'host | La propria directory dati (agent.data_dir), che contiene la chiave di enrolment e il token dell'agente, 0600 dentro una directory forzata a 0700 |
| Pacchetti sulla rete per impostazione predefinita | Zero. Entrambi gli interruttori di armamento sono forniti disattivati |
Prima di eseguirlo, verifica il download — i passi specifici per bitscanner sono qui sotto.
Due cose qui sono abbastanza rilevanti da meritare una pagina a sé: la scansione e il modello di armamento a due interruttori — la scala delle sonde, cosa mette sulla rete ciascuna sonda e la guardia che autorizza ogni pacchetto — e cosa lascia l'host, compresi l'enrolment, il traffico in uscita e i limiti con cui questa release viene fornita.
La domanda a cui bitcollector non può rispondere
Un inventario costruito a partire dagli agenti può contenere soltanto le macchine su cui qualcuno ha installato un agente. La stampante, lo switch di laboratorio, il portatile del consulente esterno, la VM che un team ha creato per una migrazione senza dirlo a nessuno — nessuno di questi si annuncerà da solo, e nessuno di questi manca a causa di un guasto tecnico. Mancano perché nessuno sapeva di doverli cercare.
Quindi i due binari rispondono a due domande diverse, e il confine è la direzione in cui guardano:
bitcollector | bitscanner | |
|---|---|---|
| Guarda | Verso l'interno — l'host su cui gira | Verso l'esterno — il segmento su cui si trova quell'host |
| Risponde a | "Cos'è questa macchina, e in che stato si trova?" | "Cos'altro c'è su questa rete, e ce n'è qualcosa di non censito?" |
| Vede un dispositivo solo se | vi è installato un agente | è visibile da un host che ne ha uno |
| Invia pacchetti | Mai — legge l'host | Solo se lo armi, sonda per sonda |
Nessuno dei due sostituisce l'altro. Un dispositivo scoperto da bitscanner è una pista: un indirizzo, un MAC, un produttore, un istante di primo avvistamento. Trasformare quella pista in un asset con un proprietario è un lavoro che fai in Asset Management — il compito di bitscanner è assicurarsi che la pista esista.
Cosa riporta con tutto disattivato
La configurazione predefinita non arma alcuna sonda, e l'agente ha comunque qualcosa da dire, perché il kernel dell'host conosce già i propri vicini.
Misurato su un normale host Linux con la scansione attiva completamente disabilitata — l'impostazione predefinita fornita:
INFO scanguard active scanning is disabled; every probe will be denied
INFO network_collector network intelligence collector starting {"interval": "20s"}
INFO network_collector collection cycle complete
{"queued_for_delivery": ["network_state", "neighbor_table"]}
Entrambi provengono da file che l'host già possiede — /proc/net/arp e la tabella di routing
— quindi in questo stato non viene emesso alcun pacchetto.
| Record | Cosa trasporta | Richiede |
|---|---|---|
network_state | La tabella di routing: destinazione, gateway, interfaccia, metrica, flag | nulla |
neighbor_table | La cache ARP/NDP del kernel: indirizzo, MAC, interfaccia, stato | nulla |
neighbor_discovery | L'inventario arricchito dei vicini: indirizzo, MAC, produttore, tipo di dispositivo, raggiungibilità, primo/ultimo avvistamento — più le subnet su cui sono stati trovati | scanning.probes.neighbor_discovery |
gateway_discovery | I primi hop in uscita da questo host, con attribuzione del MAC | scanning.probes.gateway_discovery |
service_discovery | Responder mDNS/SSDP, attribuiti al vicino che ha risposto | scanning.probes.service_discovery |
Ogni record viaggia nello stesso envelope — schema_version, type, agent_id,
timestamp, sequence, payload, checksum — e il checksum è un controllo di integrità
SHA-256 sull'intestazione e sul payload dell'envelope, non una firma. bitscanner non
dispone della catena delle evidenze firmata e concatenata tramite
hash di bitcollector; se ti serve un artefatto che un auditor
possa verificare offline, quello è compito del collector, non di questo agente.
Come eseguirlo
bitscanner è un singolo binario statico. Verificalo prima, poi:
# What you have
bitscanner version
# BitScanner 0.1.3-ga (commit: 7db3d4c, built: 2026-08-09T09:54:40Z, go1.25.12, linux/amd64)
# Write a fully commented starting configuration
bitscanner config init --config /etc/bitscanner/config.yaml
# Check it BEFORE you start anything
bitscanner config validate --config /etc/bitscanner/config.yaml
# Configuration is valid.
# Run in the foreground
bitscanner run --config /etc/bitscanner/config.yaml
# Turn up the detail while you are setting it up
bitscanner run --config /etc/bitscanner/config.yaml --log-level debug --log-format console
config init scrive lo stesso file annotato che questa pagina sta descrivendo: ogni chiave di
scansione, cosa invia davvero ciascuna sonda e perché le impostazioni predefinite sono quelle
che sono. È fatto per essere letto.
--log-level e --log-format sono flag, e soltanto flagNon esiste alcun blocco logging:. C'era — level, format, output_path, max_size,
max_backups, max_age — e nessuna di quelle chiavi veniva letta da alcun codice, quindi il
logger era configurato interamente dalla riga di comando, qualunque cosa dicesse il file. Il
blocco è stato rimosso, e una configurazione che lo contiene ancora viene rifiutata per
nome:
Error: configuration validation failed: failed to load config: logging is set but no
longer exists: the whole `logging` block was parsed and read by nobody […] Use the
flags, which do work: `--log-level` (debug|info|warn|error) and `--log-format`
(json|console). There is no replacement for output_path or for the rotation keys — log
rotation was never implemented […]
Lo stesso trattamento vale per control_plane.retry_interval, control_plane.max_retries,
security.allow_root_only, security.secure_bootstrap, security.audit_log_path e
security.encrypt_local_data. Due di queste avevano true come valore predefinito, quindi il
file fornito si leggeva come un bootstrap protetto e una cifratura a riposo, mentre né l'uno
né l'altra esistevano. Una chiave che non fa nulla non viene fornita, e la sua rimozione viene
annunciata alla persona il cui file la contiene anziché essere ignorata in silenzio.
Quanto costa sull'host
- Nessuna superficie in ingresso. Verificato su un agente in esecuzione: il processo
possiede zero socket in ascolto. Non c'è una porta di salute, non c'è una porta per le
metriche e non esiste alcuna chiave di configurazione che ne apra una.
Una riserva onesta: con
service_discoveryarmato, l'agente apre socket UDP effimeri e non vincolati per inviare le query mDNS e SSDP e leggerne le risposte. Esistono solo per la durata di un sondaggio — ma «zero socket in ascolto» vale per la configurazione predefinita, non per ogni configurazione. - Costa poco quando è silenzioso. Su un host con 118 vicini ARP distribuiti su 27 subnet
collegate, un passaggio completo di scoperta dei vicini ha richiesto 71–189 ms per ciclo
su quattro cicli consecutivi. Il valore predefinito di
modules.network_intelligence.intervalè1m. - Un ciclo è un ciclo di scansione. Il budget di host per ciclo e la scadenza di scansione misurata sul tempo reale si azzerano all'inizio di una raccolta e in nessun altro punto, così un segmento lento o intrappolato in un tarpit non può far sconfinare il sondaggio di un ciclo in quello successivo.
- Niente store-and-forward e nessun tentativo ripetuto. Un batch che non può essere consegnato viene registrato come errore e scartato: non viene salvato su disco né ritentato. Se la destinazione è irraggiungibile per dieci minuti, sono dieci minuti di osservazioni che non avete. Una riga
queued_for_deliveryviene registrata a ogni ciclo, con o senza scanning attivo, così un errore di consegna non può essere scambiato per un collector fermo — ma «in coda» non significa «consegnato», e l'agente non può affermare più di quanto la destinazione gli abbia risposto.
0.1.3-ga e versioni precedentiQuesta pagina affermava che i socket di scoperta «non accettano nulla che non abbiate
sollecitato». Quel controllo non è mai stato implementato. I socket usano un binding
jolly, quindi il kernel consegna loro qualsiasi datagramma raggiunga la porta, e nulla
confrontava il mittente o il contenuto con la query appena inviata: un datagramma SSDP diventava
un dispositivo per il solo fatto di contenere il testo ST:. Qualsiasi cosa in grado di
raggiungere quella porta poteva aggiungere al vostro inventario host che non esistono, agli
indirizzi che preferiva, registrati come osservazioni compiute da questo agente.
Il controllo ora esiste nel codice sorgente e pone due domande. Da chi: il mittente deve
trovarsi all'interno dei vostri scanning.allowed_cidrs e superare ogni altra regola che la
guardia applica a un bersaglio di sondaggio. Che cosa: il datagramma deve rispondere alla
query appena inviata — per mDNS, dalla porta 5353, con il bit di risposta impostato e
l'identificativo di transazione imprevedibile generato da questo agente; per SSDP, una risposta
M-SEARCH HTTP 200 che porti sia ST sia USN, mai un NOTIFY non sollecitato.
Non è ancora in un binario pubblicato. Se state eseguendo 0.1.3-ga o una versione
precedente, trattate i risultati di service_discovery come indizi non autenticati: sono
attribuibili a chi ha inviato il pacchetto, che non è necessariamente il dispositivo indicato.
Tutte le altre sonde non sono interessate — registrano ciò che ha restituito una connessione
aperta da questo agente.
A differenza di bitcollector, bitscanner non ha alcuna chiave
max_memory_mb / max_cpu_percent. Un controllo di salute periodico registra i conteggi di
allocazione e di goroutine e avvisa oltre i 50 MB e le 1.000 goroutine, e questo è tutto.
Limitalo con i controlli del tuo sistema di init (MemoryMax=, CPUQuota= in un'unità
systemd) se ti serve un limite rigido su un host che conta.
Verificare questa release
La directory della release di bitscanner contiene i binari, SHA256SUMS, una firma cosign su
quel manifest e — per ogni binario — un .sig, un'attestazione .att e un .sbom.json.
Verifica per prima la firma sul manifest, poi i checksum:
cosign verify-blob --key cosign.pub --bundle SHA256SUMS.sig \
--insecure-ignore-tlog=true SHA256SUMS
# WARNING: Skipping tlog verification is an insecure practice […]
# Verified OK
sha256sum -c SHA256SUMS
# bitscanner-linux-amd64: OK
# bitscanner-linux-arm64: OK
Entrambi i comandi qui sopra sono stati eseguiti sugli artefatti 0.1.3-ga forniti, e così
anche il controllo negativo: alterare un byte di SHA256SUMS fa uscire lo stesso comando
verify-blob con codice non zero e invalid signature when validating ASN.1 encoded signature. Un passo di verifica che non hai mai visto fallire non è un passo di verifica.
bitscanner è firmato con la chiave della famiglia bits — quella che usano bitcollector e bitenforcer, e quella pubblicata su cosign.pub. Se hai già verificato una release bits, hai già l'ancora di fiducia, e non dovrebbe essere cambiata. Vale la pena leggere una volta perché la verifica della chiave è il passo portante, compreso il confronto incrociato dell'impronta.
A partire da 0.1.3-ga, bitscanner include lo stesso insieme di artefatti del resto della
famiglia — un .sig, un'attestazione .att e un .sbom.json accanto a ogni binario, più un
SHA256SUMS.sig sul manifest — quindi ogni passo di quella pagina le si applica, compresi i
passi 4 e 5. Le release precedenti includevano solo il manifest firmato; se stai verificando
0.1.2-ga o una versione più vecchia, quei due passi non hanno nulla su cui fare il confronto.
La chiave pubblica completa è pubblicata come record TXT, il che è utile in uno script di installazione:
dig +short TXT _cosign-key.cert-ix.com | tr -d '"' | sed 's/.*key=//' \
| base64 -d | openssl pkey -pubin -inform DER -out cosign.pub
Il DNS è un sistema diverso dal server web, quindi una chiave ottenuta in questo modo e una
scaricata dal sito sono due fonti indipendenti che devono coincidere — che è esattamente il
confronto incrociato che verificare i tuoi download ti chiede di
fare. Il record complementare _cosign.cert-ix.com porta solo l'impronta, se vuoi confrontare
soltanto quella.
Piattaforme
0.1.3-ga pubblica due binari firmati, e il vuoto è deliberato:
| Piattaforma | Pubblicata | Perché |
|---|---|---|
Linux amd64 | Sì | |
Linux arm64 | Sì | |
macOS amd64/arm64 | No | Trattenuta — vedi sotto |
Windows amd64 | No | Trattenuta — vedi sotto |
bitscanner è solo per Linux perché i lettori che gli stanno sotto sono implementazioni
Linux. I due record che produce con tutte le sonde disattivate — neighbor_table e
network_state — provengono dalla cache ARP/NDP del kernel e dalla tabella di routing così come
Linux le espone. È questo che consente alla configurazione predefinita distribuita di riportare
qualcosa di reale mettendo zero pacchetti in rete, ed è la proprietà su cui si regge l'intero
modello di armamento a due interruttori.
macOS e Windows espongono le stesse informazioni, attraverso interfacce completamente diverse. Portare quei lettori è un lavoro vero, con il suo carico di test, e non è stato fatto. Una build per quelle piattaforme compilerebbe e poi riporterebbe una tabella dei vicini vuota su un host che ha vicini — indistinguibile, per chi legge l'output, da un segmento tranquillo. Un risultato vuoto che significa «non implementato qui» è l'output più pericoloso che questo agente possa produrre, perché tutta la sua ragion d'essere è dirti quando c'è qualcosa in rete che il tuo inventario non spiega.
Quindi non c'è alcuna build macOS o Windows da scaricare. Se devi osservare un segmento su cui ci sono solo host macOS o Windows, metti bitscanner su un qualsiasi host Linux collegato a esso: riporta sul segmento, non su se stesso, quindi un solo host Linux basta a coprire il dominio di broadcast.
Passi successivi
- La scansione, e i due interruttori che la armano — la scala delle sonde, esattamente cosa mette sulla rete ciascuna sonda, perché le dichiarazioni di accettazione possono essere scritte solo in un file, e la guardia che decide nel momento in cui il pacchetto parte.
- Cosa lascia l'host — il traffico in uscita, l'enrolment, i file dei segreti e i limiti dichiarati con onestà con cui questa release viene fornita.
- Verificare i tuoi download — l'ancora di fiducia, e perché conta più della firma.
- bitcollector — la metà della risposta che guarda verso l'interno.
- Cos'è bits? — come si incastrano i quattro compiti.
Questa pagina ti è stata utile?