bitscanner
bitscanner encuentra los dispositivos que su inventario no contiene.
bitcollector lee el host en el que se ejecuta. bitscanner mira hacia fuera desde ese
host, hacia el segmento que lo rodea — y la respuesta que importa es la que nada de su lista
de activos explica.
| Versión | 0.1.3-ga, commit 7db3d4c, compilada con go1.25.12 |
| Plataformas | Linux amd64/arm64 únicamente — macOS y Windows no se publican, y por qué |
| Cadena de suministro | Compilación reproducible (se compila dos veces y se rechaza salvo que sea idéntica byte a byte), SBOM CycloneDX y atestación cosign por binario, control de vulnerabilidades, firma cosign por binario y sobre SHA256SUMS |
| Superficie de red entrante | Ningún servicio a la escucha. Sin puerto de salud, de métricas ni de administración, y sin clave que abra uno. Medido con el escaneo desactivado: cero sockets a la escucha. service_discovery, una vez armado, usa sockets UDP efímeros y no ligados; un datagrama que llega a uno de ellos solo se convierte en registro de inventario si responde a la consulta recién enviada y procede de allowed_cidrs — no comprobado en 0.1.3-ga ni en versiones anteriores, véase más abajo |
| Saliente | Solo https, hacia los endpoints que usted configure. Nunca se sigue una redirección |
| Escrituras en el host | Su propio directorio de datos (agent.data_dir), que guarda la clave de enrolamiento y el token del agente, en 0600 dentro de un directorio forzado a 0700 |
| Paquetes en la red por defecto | Cero. Ambos interruptores de armado se distribuyen desactivados |
Antes de ejecutarlo, verifique la descarga — los pasos específicos de bitscanner están más abajo.
Dos temas son lo bastante grandes como para tener su propia página: el escaneo y el modelo de armado de dos interruptores — la escalera de sondas, qué pone cada una en el cable y el guardián que autoriza cada paquete — y qué sale del host, incluidos el enrolamiento, la salida de datos y los límites con los que se distribuye esta versión.
La pregunta que bitcollector no puede responder
Un inventario ensamblado a partir de agentes solo puede contener máquinas en las que alguien instaló un agente. La impresora, el switch del laboratorio, el portátil del contratista, la VM que un equipo levantó para una migración y de la que nunca informó a nadie — ninguno de ellos se reportará por sí mismo, y ninguno falta por un fallo técnico. Faltan porque nadie sabía que había que mirar.
Así que los dos binarios responden a dos preguntas distintas, y la frontera es la dirección hacia la que miran:
bitcollector | bitscanner | |
|---|---|---|
| Mira | Hacia dentro — el host en el que se ejecuta | Hacia fuera — el segmento en el que está ese host |
| Responde | «¿Qué es esta máquina y en qué estado está?» | «¿Qué más hay en este cable, y hay algo sin explicación?» |
| Ve un dispositivo solo si | tiene un agente instalado | es visible desde un host que sí lo tiene |
| Envía paquetes | Nunca — lee el host | Solo si usted lo arma, sonda a sonda |
Ninguno sustituye al otro. Un dispositivo que bitscanner descubre es una pista: una dirección, una MAC, un fabricante, una fecha de primera observación. Convertir esa pista en un activo con propietario es trabajo que usted hace en Gestión de activos — la tarea de bitscanner es asegurar que la pista exista siquiera.
Qué reporta con todo desactivado
La configuración por defecto no arma ninguna sonda, y el agente aun así tiene algo que decir, porque el propio kernel del host ya conoce a sus vecinos.
Medido, en un host Linux corriente con el escaneo activo completamente deshabilitado — el valor por defecto distribuido:
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"]}
Ambos proceden de ficheros que el host ya tiene — /proc/net/arp y la tabla de rutas — de
modo que este estado no emite ningún paquete en absoluto.
| Registro | Qué contiene | Necesita |
|---|---|---|
network_state | La tabla de rutas: destino, pasarela, interfaz, métrica, flags | nada |
neighbor_table | La caché ARP/NDP del kernel: dirección, MAC, interfaz, estado | nada |
neighbor_discovery | El inventario enriquecido de vecinos: dirección, MAC, fabricante, tipo de dispositivo, alcanzabilidad, primera/última observación — más las subredes en las que se encontraron | scanning.probes.neighbor_discovery |
gateway_discovery | Los primeros saltos de salida de este host, con atribución de MAC | scanning.probes.gateway_discovery |
service_discovery | Respondedores mDNS/SSDP, atribuidos al vecino que contestó | scanning.probes.service_discovery |
Cada registro va envuelto en el mismo sobre — schema_version, type, agent_id,
timestamp, sequence, payload, checksum — y la suma de comprobación es una
verificación de integridad SHA-256 sobre la cabecera y la carga útil del sobre, no una
firma. bitscanner no tiene la cadena de evidencia firmada y encadenada por
hash de bitcollector; si necesita un artefacto que un auditor pueda
verificar sin conexión, ese es el trabajo del recopilador, no de este.
Cómo ejecutarlo
bitscanner es un único binario estático. Verifíquelo primero y después:
# 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 escribe el mismo fichero comentado que describe esta página: cada clave de
escaneo, qué envía realmente cada sonda y por qué los valores por defecto son los que son.
Está pensado para leerse.
--log-level y --log-format son opciones, y solo opcionesNo hay bloque logging:. Lo hubo — level, format, output_path, max_size,
max_backups, max_age — y ni una sola de esas claves era leída por código alguno, así que
el registrador se configuraba enteramente desde la línea de comandos dijera lo que dijera el
fichero. El bloque ha desaparecido, y una configuración que todavía lo contenga se rechaza
por su nombre:
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 […]
El mismo trato se aplica a control_plane.retry_interval, control_plane.max_retries,
security.allow_root_only, security.secure_bootstrap, security.audit_log_path y
security.encrypt_local_data. Dos de ellas valían true por defecto, de modo que el fichero
distribuido se leía como un arranque seguro y un cifrado en reposo cuando no existía ninguno de
los dos. Una clave que no hace nada no se distribuye, y su eliminación se anuncia a la persona
cuyo fichero la contiene en lugar de ignorarse en silencio.
Qué cuesta en el host
- Ninguna superficie entrante. Verificado en un agente en ejecución: el proceso posee
cero sockets a la escucha. No hay puerto de salud, ni puerto de métricas, ni clave de
configuración que abra uno.
Una salvedad honesta: con
service_discoveryarmado, el agente abre sockets UDP efímeros y no ligados para enviar las consultas mDNS y SSDP y leer las respuestas. Existen solo mientras dura una sonda — pero «cero sockets a la escucha» es cierto de la configuración por defecto, no de todas las configuraciones. - Barato cuando está tranquilo. En un host con 118 vecinos ARP repartidos en 27 subredes
conectadas, una pasada completa de descubrimiento de vecinos tardó 71–189 ms por ciclo a
lo largo de cuatro ciclos consecutivos. El valor por defecto de
modules.network_intelligence.intervales1m. - Un ciclo es un ciclo de escaneo. El presupuesto de hosts por ciclo y el plazo de escaneo en tiempo real se reinician al comienzo de una recopilación y en ningún otro sitio, de modo que un segmento lento o con tarpit no puede dejar que el sondeo de un ciclo invada el siguiente.
- Ni store-and-forward ni reintento. Un lote que no se puede entregar se registra como error y se descarta: no se guarda en disco ni se reintenta. Si el destino no es alcanzable durante diez minutos, son diez minutos de observaciones que usted no tiene. Se registra una línea
queued_for_deliveryen cada ciclo, con o sin escaneo activo, de modo que un fallo de entrega no pueda confundirse con un recopilador detenido — pero «en cola» no es «entregado», y el agente no puede afirmar más de lo que el destino le respondió.
0.1.3-ga y versiones anterioresEsta página afirmaba que los sockets de descubrimiento «no aceptan nada que usted no haya
solicitado». Esa comprobación nunca se implementó. Los sockets usan un enlace comodín, de
modo que el núcleo les entrega cualquier datagrama que alcance el puerto, y nada comparaba el
remitente ni el contenido con la consulta recién enviada: un datagrama SSDP se convertía en un
dispositivo por el mero hecho de contener el texto ST:. Cualquier cosa capaz de alcanzar ese
puerto podía añadir a su inventario equipos que no existen, en las direcciones que eligiera,
registrados como observaciones hechas por este agente.
La comprobación ya existe en el código fuente y plantea dos preguntas. De quién: el
remitente debe estar dentro de sus scanning.allowed_cidrs y superar todas las demás reglas que
el guardián aplica a un objetivo de sonda. Qué: el datagrama debe responder a la consulta
recién enviada — para mDNS, desde el puerto 5353, con el bit de respuesta activo y el
identificador de transacción impredecible que generó este agente; para SSDP, una respuesta
M-SEARCH HTTP 200 que lleve tanto ST como USN, nunca un NOTIFY no solicitado.
Todavía no está en un binario publicado. Si ejecuta 0.1.3-ga o una versión anterior, trate
los resultados de service_discovery como pistas no autenticadas: son atribuibles a quien envió
el paquete, que no es necesariamente el dispositivo nombrado. Las demás sondas no se ven
afectadas — registran lo que devolvió una conexión abierta por este agente.
A diferencia de bitcollector, bitscanner no tiene una clave
max_memory_mb / max_cpu_percent. Una comprobación de salud periódica registra las
asignaciones y el número de goroutines, y avisa por encima de 50 MB y 1000 goroutines, y eso
es todo. Acótelo con los controles de su propio sistema de arranque (MemoryMax=, CPUQuota=
en una unidad de systemd) si necesita un límite duro en un host que importa.
Verificar esta versión
El directorio de la versión de bitscanner incluye los binarios, SHA256SUMS, una firma cosign
sobre ese manifiesto y — por cada binario — un .sig, una atestación .att y un .sbom.json.
Verifique primero la firma sobre el manifiesto y después las sumas de comprobación:
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
Ambos comandos se ejecutaron contra los artefactos 0.1.3-ga distribuidos, igual que el control
negativo: alterar un solo byte de SHA256SUMS hace que el mismo comando verify-blob salga
con código distinto de cero y el mensaje invalid signature when validating ASN.1 encoded signature. Un paso de verificación que nunca ha visto fallar no es un paso de verificación.
bitscanner está firmado con la clave de la familia bits — la que usan bitcollector y bitenforcer, y la publicada en cosign.pub. Si ya verificó una versión de bits, ya tiene el ancla de confianza, y no debería haber cambiado. Por qué la comprobación de la clave es el paso que sostiene todo, incluida la comprobación cruzada de la huella, merece una lectura.
Desde 0.1.3-ga, bitscanner incluye el mismo conjunto de artefactos que el resto de la
familia — un .sig, una atestación .att y un .sbom.json junto a cada binario, más un
SHA256SUMS.sig sobre el manifiesto — así que todos los pasos de esa página se le aplican,
incluidos los pasos 4 y 5. Las versiones anteriores solo incluían el manifiesto firmado; si
está verificando 0.1.2-ga o una versión más antigua, esos dos pasos no tienen nada contra lo
que comprobar.
La clave pública completa se publica como registro TXT, lo que resulta útil en un script de instalación:
dig +short TXT _cosign-key.cert-ix.com | tr -d '"' | sed 's/.*key=//' \
| base64 -d | openssl pkey -pubin -inform DER -out cosign.pub
El DNS es un sistema distinto del servidor web, así que una clave obtenida de este modo y otra
descargada del sitio son dos fuentes independientes que deben coincidir — que es exactamente la
comprobación cruzada que le pide verificar sus descargas. El registro
complementario _cosign.cert-ix.com lleva solo la huella, si únicamente quiere comparar eso.
Plataformas
0.1.3-ga publica dos binarios firmados, y el hueco es deliberado:
| Plataforma | Publicada | Por qué |
|---|---|---|
Linux amd64 | Sí | |
Linux arm64 | Sí | |
macOS amd64/arm64 | No | Retenida — ver abajo |
Windows amd64 | No | Retenida — ver abajo |
bitscanner es solo para Linux porque los lectores que hay debajo son implementaciones de
Linux. Los dos registros que produce con todas las sondas desactivadas — neighbor_table y
network_state — proceden de la caché ARP/NDP del kernel y de la tabla de rutas tal y como las
expone Linux. Eso es lo que permite que la configuración por defecto informe de algo real
poniendo cero paquetes en la red, y es la propiedad sobre la que se apoya todo el modelo de
armado de dos interruptores.
macOS y Windows exponen la misma información, a través de interfaces completamente distintas. Portar esos lectores es un trabajo real, con su propia carga de pruebas, y no se ha hecho. Una compilación para esas plataformas funcionaría y luego informaría de una tabla de vecinos vacía en un host que sí tiene vecinos — indistinguible, para quien lea la salida, de un segmento tranquilo. Un resultado vacío que significa «no implementado aquí» es la salida más peligrosa que este agente podría producir, porque su razón de ser es decirle cuándo hay algo en la red que su inventario no explica.
Así que no hay compilación de macOS ni de Windows que descargar. Si necesita observar un segmento en el que solo hay hosts macOS o Windows, ponga bitscanner en cualquier host Linux conectado a él: informa sobre el segmento, no sobre sí mismo, así que un solo host Linux basta para cubrir el dominio de difusión.
Próximos pasos
- El escaneo y los dos interruptores que lo arman — la escalera de sondas, qué pone exactamente cada una en el cable, por qué los reconocimientos solo pueden escribirse en un fichero, y el guardián que decide en el momento en que el paquete sale.
- Qué sale del host — salida de datos, enrolamiento, ficheros de secretos y los límites honestos con los que se distribuye esta versión.
- Verificación de sus descargas — el ancla de confianza, y por qué importa más que la firma.
- bitcollector — la mitad de la respuesta que mira hacia dentro.
- ¿Qué es bits? — cómo encajan los cuatro trabajos.
¿Te resultó útil esta página?