Aller au contenu principal
Version: 1.0.0

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.

Version0.1.3-ga, commit 7db3d4c, compilée avec go1.25.12
PlateformesLinux amd64/arm64 uniquement — macOS et Windows ne sont pas publiés, et pourquoi
Chaîne d'approvisionnementCompilation 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 entranteAucun 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 sortanthttps uniquement, vers les endpoints que vous configurez. Aucune redirection n'est jamais suivie
Écritures sur l'hôteSon 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éfautZé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 :

bitcollectorbitscanner
RegardeVers l'intérieur — l'hôte sur lequel il s'exécuteVers 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 siun agent y est installéil est visible depuis un hôte qui en a un
Envoie des paquetsJamais — il lit l'hôteUniquement 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.

EnregistrementCe qu'il transporteNécessite
network_stateLa table de routage : destination, passerelle, interface, métrique, drapeauxrien
neighbor_tableLe cache ARP/NDP du noyau : adresse, MAC, interface, étatrien
neighbor_discoveryL'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ésscanning.probes.neighbor_discovery
gateway_discoveryLes premiers sauts en sortie de cet hôte, avec attribution de la MACscanning.probes.gateway_discovery
service_discoveryRépondeurs mDNS/SSDP, rattachés au voisin qui a réponduscanning.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 options

Il 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_discovery armé, 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.interval est 1m.
  • 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_delivery est 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.
Ces sockets acceptaient n'importe quoi, dans 0.1.3-ga et les versions antérieures

Cette 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.

Cette version ne comporte aucun plafond mémoire ou CPU configurable

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.

C'est la même clé que pour le reste de la famille

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.

Vous pouvez récupérer la clé via DNS plutôt que par HTTPS

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é :

PlateformePubliéePourquoi
Linux amd64Oui
Linux arm64Oui
macOS amd64/arm64NonRetenue — voir ci-dessous
Windows amd64NonRetenue — 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​

Cette page vous a-t-elle été utile ?