bitscanner
bitscanner trouve les équipements que votre inventaire ne contient pas.
bitcollector lit l'hôte sur lequel il s'exécute. bitscanner regarde vers l'extérieur
depuis cet hôte, vers le segment qui l'entoure — et la réponse qui compte est celle que rien de
votre liste d'actifs n'explique.
| Version | 0.1.3-ga, commit 7db3d4c, compilée avec go1.25.12 |
| Plateformes | Linux amd64/arm64 uniquement — macOS et Windows ne sont pas publiés, et pourquoi |
| Chaîne d'approvisionnement | Compilation reproductible (compilée deux fois, refusée si le résultat n'est pas identique au bit près), SBOM CycloneDX et attestation cosign par binaire, filtre de vulnérabilités, signature cosign par binaire et sur SHA256SUMS |
| Surface réseau entrante | Aucun service en écoute. Aucun port de santé, de métriques ou d'administration, et aucune clé qui en ouvre un. Mesuré, scanning désactivé : zéro socket en écoute. service_discovery, une fois armé, utilise des sockets UDP non liés et éphémères ; un datagramme qui y arrive ne devient un enregistrement d'inventaire que s'il répond à la requête qui vient d'être émise et provient de allowed_cidrs — non vérifié dans 0.1.3-ga et les versions antérieures, voir ci-dessous |
| Trafic sortant | https uniquement, vers les endpoints que vous configurez. Aucune redirection n'est jamais suivie |
| Écritures sur l'hôte | Son propre répertoire de données (agent.data_dir), qui contient la clé d'enrôlement et le jeton d'agent, en 0600 dans un répertoire forcé à 0700 |
| Paquets sur le réseau par défaut | Zéro. Les deux interrupteurs d'armement sont livrés désactivés |
Avant de l'exécuter, vérifiez le téléchargement — les étapes propres à bitscanner sont ci-dessous.
Deux aspects sont ici assez importants pour avoir leur propre page : le scan et son modèle d'armement à deux interrupteurs — l'échelle des sondes, ce que chaque sonde met sur le réseau, et le garde-fou qui autorise chaque paquet — et ce qui quitte l'hôte, y compris l'enrôlement, le trafic sortant et les limites livrées avec cette version.
La question à laquelle bitcollector ne peut pas répondre
Un inventaire constitué à partir d'agents ne peut jamais contenir que les machines sur lesquelles quelqu'un a installé un agent. L'imprimante, le commutateur du labo, le portable du prestataire, la VM qu'une équipe a créée pour une migration sans jamais en parler à personne — aucun d'eux ne se signalera de lui-même, et aucun d'eux ne manque à cause d'une défaillance technique. Ils manquent parce que personne ne savait qu'il fallait regarder.
Les deux binaires répondent donc à deux questions différentes, et la frontière est la direction dans laquelle ils regardent :
bitcollector | bitscanner | |
|---|---|---|
| Regarde | Vers l'intérieur — l'hôte sur lequel il s'exécute | Vers l'extérieur — le segment sur lequel se trouve cet hôte |
| Répond à | « Qu'est-ce que cette machine, et dans quel état est-elle ? » | « Qu'y a-t-il d'autre sur ce réseau, et y a-t-il là-dedans quelque chose de non répertorié ? » |
| Ne voit un équipement que si | un agent y est installé | il est visible depuis un hôte qui en a un |
| Envoie des paquets | Jamais — il lit l'hôte | Uniquement si vous l'armez, sonde par sonde |
Aucun ne remplace l'autre. Un équipement découvert par bitscanner est une piste : une adresse, une MAC, un fabricant, une date de première observation. Transformer cette piste en actif doté d'un propriétaire est un travail qui se fait dans la Gestion des actifs — le rôle de bitscanner est de faire en sorte que la piste existe.
Ce qu'il rapporte avec tout désactivé
La configuration par défaut n'arme aucune sonde, et l'agent a pourtant quelque chose à dire, parce que le noyau de l'hôte connaît déjà ses voisins.
Mesuré, sur un hôte Linux ordinaire avec le scan actif entièrement désactivé — la valeur par défaut livrée :
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"]}
Ces deux enregistrements proviennent de fichiers que l'hôte possède déjà — /proc/net/arp et
la table de routage — si bien que cet état n'émet aucun paquet.
| Enregistrement | Ce qu'il transporte | Nécessite |
|---|---|---|
network_state | La table de routage : destination, passerelle, interface, métrique, drapeaux | rien |
neighbor_table | Le cache ARP/NDP du noyau : adresse, MAC, interface, état | rien |
neighbor_discovery | L'inventaire enrichi des voisins : adresse, MAC, fabricant, type d'équipement, joignabilité, première et dernière observation — ainsi que les sous-réseaux sur lesquels ils ont été trouvés | scanning.probes.neighbor_discovery |
gateway_discovery | Les premiers sauts en sortie de cet hôte, avec attribution de la MAC | scanning.probes.gateway_discovery |
service_discovery | Répondeurs mDNS/SSDP, rattachés au voisin qui a répondu | scanning.probes.service_discovery |
Chaque enregistrement est encapsulé dans la même enveloppe — schema_version, type,
agent_id, timestamp, sequence, payload, checksum — et la somme de contrôle est un
contrôle d'intégrité SHA-256 portant sur l'en-tête et la charge utile de l'enveloppe, pas une
signature. bitscanner ne dispose pas de la chaîne de preuves signée et chaînée par
hachage de bitcollector ; s'il vous faut un artefact qu'un auditeur
puisse vérifier hors ligne, c'est le travail du collecteur, pas celui de bitscanner.
L'exécuter
bitscanner est un binaire statique unique. Vérifiez-le d'abord, puis :
# 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 écrit le fichier annoté que cette page décrit : chaque clé de scan, ce que chaque
sonde envoie réellement, et pourquoi les valeurs par défaut sont ce qu'elles sont. Il est fait
pour être lu.
--log-level et --log-format sont des options, et rien que des optionsIl n'y a pas de bloc logging:. Il y en avait un — level, format, output_path,
max_size, max_backups, max_age — et pas une seule de ces clés n'était lue par le moindre
code : le journaliseur était donc entièrement configuré depuis la ligne de commande, quoi que
dise le fichier. Le bloc a disparu, et une configuration qui le contient encore est refusée
nommément :
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 […]
Le même traitement s'applique à control_plane.retry_interval, control_plane.max_retries,
security.allow_root_only, security.secure_bootstrap, security.audit_log_path et
security.encrypt_local_data. Deux d'entre elles valaient true par défaut : le fichier livré
donnait donc à lire un amorçage sécurisé et un chiffrement au repos alors que ni l'un ni l'autre
n'existait. Une clé qui ne fait rien n'est pas livrée, et sa suppression est annoncée à la
personne dont le fichier la contient plutôt que silencieusement ignorée.
Ce qu'il coûte à l'hôte
- Aucune surface entrante. Vérifié sur un agent en cours d'exécution : le processus détient
zéro socket en écoute. Il n'y a pas de port de santé, pas de port de métriques, et aucune
clé de configuration qui en ouvre un.
Une réserve, énoncée honnêtement : avec
service_discoveryarmé, l'agent ouvre des sockets UDP éphémères et non liés pour émettre les requêtes mDNS et SSDP et en lire les réponses. Ils n'existent que le temps d'une sonde — mais « zéro socket en écoute » vaut pour la configuration par défaut, pas pour toutes les configurations. - Peu coûteux quand il est silencieux. Sur un hôte comptant 118 voisins ARP répartis sur 27
sous-réseaux attachés, une passe complète de découverte des voisins a pris 71 à 189 ms par
cycle sur quatre cycles consécutifs. La valeur par défaut de
modules.network_intelligence.intervalest1m. - Un cycle, c'est un cycle de scan. Le budget d'hôtes par cycle et l'échéance de scan en temps d'horloge sont réinitialisés au début d'une collecte et nulle part ailleurs : un segment lent ou englué (tarpit) ne peut donc pas laisser le sondage d'un cycle déborder sur le suivant.
- Ni store-and-forward, ni réessai. Un lot qui ne peut pas être livré est journalisé comme erreur puis abandonné : il n'est ni écrit sur disque ni réessayé. Si le point de collecte est injoignable pendant dix minutes, ce sont dix minutes d'observations que vous n'avez pas. Une ligne
queued_for_deliveryest journalisée à chaque cycle, que le scanning soit actif ou non, de sorte qu'un échec de livraison ne puisse pas être confondu avec un collecteur à l'arrêt — mais « mis en file » n'est pas « livré », et l'agent ne peut rien affirmer de plus que ce que la destination lui a répondu.
0.1.3-ga et les versions antérieuresCette page affirmait que les sockets de découverte « n'acceptent rien que vous n'ayez sollicité ».
Cette vérification n'a jamais été implémentée. Les sockets sont liés à l'adresse joker : le
noyau leur remet donc tout datagramme qui atteint le port, et rien ne comparait l'expéditeur ni
le contenu à la requête qui venait d'être émise — un datagramme SSDP devenait un équipement au
seul motif qu'il contenait le texte ST:. Tout ce qui pouvait atteindre ce port pouvait ajouter
à votre inventaire des hôtes qui n'existent pas, aux adresses de son choix, enregistrés comme
des observations faites par cet agent.
La vérification existe désormais dans le code source, et elle pose deux questions. De qui :
l'expéditeur doit se trouver dans vos scanning.allowed_cidrs et satisfaire toutes les autres
règles que le garde applique à une cible de sonde. Quoi : le datagramme doit répondre à la
requête qui vient d'être émise — pour mDNS, depuis le port 5353, avec le bit de réponse positionné
et l'identifiant de transaction imprévisible généré par cet agent ; pour SSDP, une réponse
M-SEARCH HTTP 200 portant à la fois ST et USN, jamais un NOTIFY non sollicité.
Ce n'est pas encore dans un binaire publié. Si vous utilisez 0.1.3-ga ou une version
antérieure, traitez les résultats de service_discovery comme des pistes non authentifiées :
ils sont attribuables à qui a envoyé le paquet, qui n'est pas nécessairement l'équipement nommé.
Toutes les autres sondes sont indemnes — elles enregistrent ce qu'a renvoyé une connexion que
cet agent a ouverte.
Contrairement à bitcollector, bitscanner n'a pas de clé
max_memory_mb / max_cpu_percent. Un contrôle de santé périodique journalise les allocations
et le nombre de goroutines et avertit au-delà de 50 Mo et de 1 000 goroutines, et c'est tout.
Bornez-le avec les contrôles de votre propre système d'init (MemoryMax=, CPUQuota= dans une
unité systemd) s'il vous faut une limite stricte sur un hôte qui compte.
Vérifier cette version publiée
Le répertoire de publication de bitscanner contient les binaires, SHA256SUMS, une signature
cosign portant sur ce manifeste et — pour chaque binaire — un .sig, une attestation .att et
un .sbom.json. Vérifiez d'abord la signature portant sur le manifeste, puis les sommes de
contrôle :
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
Les deux commandes ci-dessus ont été exécutées contre les artefacts 0.1.3-ga livrés, et le
contrôle négatif également : modifier un seul octet de SHA256SUMS fait sortir la même commande
verify-blob avec un code non nul et le message
invalid signature when validating ASN.1 encoded signature. Une étape de vérification que vous
n'avez jamais vue échouer n'est pas une étape de vérification.
bitscanner est signé avec la clé de la famille bits — celle qu'utilisent bitcollector et bitenforcer, et celle publiée à l'adresse cosign.pub. Si vous avez déjà vérifié une version bits, vous disposez déjà de l'ancre de confiance, et elle ne devrait pas avoir changé. Pourquoi la vérification de la clé est l'étape porteuse, recoupement d'empreinte compris, mérite d'être lu une fois.
Depuis 0.1.3-ga, bitscanner livre le même ensemble d'artefacts que le reste de la
famille — un .sig, une attestation .att et un .sbom.json à côté de chaque binaire, plus
un SHA256SUMS.sig portant sur le manifeste : toutes les étapes de cette page s'y appliquent
donc, y compris les étapes 4 et 5. Les versions antérieures ne livraient que le manifeste
signé ; si vous vérifiez 0.1.2-ga ou une version plus ancienne, ces deux étapes n'ont rien à
contrôler.
La clé publique complète est publiée sous forme d'enregistrement TXT, ce qui est utile dans un script d'installation :
dig +short TXT _cosign-key.cert-ix.com | tr -d '"' | sed 's/.*key=//' \
| base64 -d | openssl pkey -pubin -inform DER -out cosign.pub
Le DNS est un système distinct du serveur web : une clé obtenue de cette façon et une clé
téléchargée depuis le site sont donc deux sources indépendantes qui doivent concorder — c'est
exactement le recoupement que vérifier vos téléchargements vous
demande de faire. L'enregistrement associé _cosign.cert-ix.com ne porte que l'empreinte, si
vous voulez seulement comparer celle-ci.
Plateformes
0.1.3-ga publie deux binaires signés, et l'écart est délibéré :
| Plateforme | Publiée | Pourquoi |
|---|---|---|
Linux amd64 | Oui | |
Linux arm64 | Oui | |
macOS amd64/arm64 | Non | Retenue — voir ci-dessous |
Windows amd64 | Non | Retenue — voir ci-dessous |
bitscanner est réservé à Linux parce que les lecteurs qui le sous-tendent sont des
implémentations Linux. Les deux enregistrements qu'il produit avec toutes les sondes
désactivées — neighbor_table et network_state — proviennent du cache ARP/NDP et de la table
de routage du noyau tels que Linux les expose. C'est ce qui permet à la configuration livrée par
défaut de rapporter quelque chose de réel tout en mettant zéro paquet sur le réseau, et
c'est la propriété sur laquelle repose tout le modèle d'armement à deux interrupteurs.
macOS et Windows exposent les mêmes informations, par des interfaces entièrement différentes. Porter ces lecteurs est un vrai travail, avec sa propre charge de tests, et il n'a pas été fait. Une compilation pour ces plateformes fonctionnerait, puis rapporterait une table de voisins vide sur un hôte qui a des voisins — indiscernable, pour qui lit la sortie, d'un segment calme. Un résultat vide qui signifie « non implémenté ici » est la sortie la plus dangereuse que cet agent puisse produire, puisque toute sa raison d'être est de vous dire quand quelque chose se trouve sur le réseau sans que votre inventaire l'explique.
Il n'y a donc pas de compilation macOS ou Windows à télécharger. Si vous devez observer un segment qui ne porte que des hôtes macOS ou Windows, placez bitscanner sur n'importe quel hôte Linux qui y est raccordé : il rapporte sur le segment, pas sur lui-même, donc un seul hôte Linux suffit à couvrir le domaine de diffusion.
Étapes suivantes
- Le scan, et les deux interrupteurs qui l'arment — l'échelle des sondes, ce que chaque sonde met exactement sur le réseau, pourquoi les déclarations ne peuvent être écrites que dans un fichier, et le garde-fou qui décide au moment où le paquet part.
- Ce qui quitte l'hôte — trafic sortant, enrôlement, fichiers de secrets, et les limites honnêtes livrées avec cette version.
- Vérifier vos téléchargements — l'ancre de confiance, et pourquoi elle compte plus que la signature.
- bitcollector — la moitié de la réponse tournée vers l'intérieur.
- Qu'est-ce que bits ? — comment les quatre tâches s'articulent.
Cette page vous a-t-elle été utile ?