Saltar al contenido principal
Version: 1.0.0

bitenforcer

bitenforcer lee una política de endurecimiento declarativa y responde por completo a una sola pregunta:

"Si aplicara esto a esta máquina, ¿qué cambiaría exactamente — y qué podría pasarle a mi acceso?"

Versión0.1.0-ga, commit 4c6ce93, compilada con go1.25.12
PlataformasLinux amd64/arm64 únicamente — macOS y Windows no se publican, y por qué
Cadena de suministroCompilación reproducible, SBOM CycloneDX, firma cosign, atestación del SBOM, SHA256SUMS firmado
FormaHerramienta de línea de comandos de un solo disparo. Sin demonio, sin telemetría, sin latido
v1 no modifica hosts

bitenforcer v1 incluye validate y apply --dry-run. Planifica todos los cambios, valida el contenido que escribiría, ejecuta sus protecciones contra bloqueo de acceso — y entonces se detiene. No escribe en el host, y ninguna opción hace que lo haga.

Es una decisión de alcance deliberada; no es un fallo, ni una caída, ni un ajuste que a usted se le esté escapando. Por qué merece diez minutos de su tiempo antes de que planifique un despliegue.

Las protecciones en sí, y el relato completo de por qué la aplicación efectiva queda fuera del alcance, están en Las protecciones, y por qué la v1 no aplica cambios.

Qué hace​

Apúntela a una política YAML:

bitenforcer validate --config policy.yaml # is the policy well-formed?
bitenforcer apply --config policy.yaml --dry-run # what would it do to THIS host?

La comprobación previa nombra todos los ficheros que escribiría y los bytes que escribiría, todas las unidades de systemd que habilitaría, deshabilitaría, enmascararía o en las que dejaría un fragmento de endurecimiento, todas las reglas de firewall, todos los sysctls, todas las cuentas y permisos — en el orden en que se aplicarían.

Donde existe un validador real, el contenido candidato se pasa por él:

ArtefactoValidador
sshd_configsshd -t -f <candidate>
sudoersvisudo -c
conjunto de reglas de nftablesnft -c -f <candidate>
conjunto de reglas de iptablesiptables-restore --test

Así, "esta política genera un sshd_config que sshd rechazará" se detecta antes de que nadie tenga que responder por ello — no a las 03:00 cuando el demonio no consigue reiniciarse.

Junto a eso, las protecciones contra bloqueo de acceso reportan qué le haría su política a su propio acceso, medido contra la sesión en la que realmente se está ejecutando.

Lo que no hará es adivinar. Un módulo al que le faltan prerrequisitos da error en lugar de suponer. Una sesión que no puede medirse se reporta como no medida, nunca como "nadie está en riesgo". Un validador que no puede ejecutarse dice NOT VALIDATED por fichero, con el motivo, en lugar de dar a entender que el contenido se comprobó.

Salida real de la comprobación previa​

Esta es una ejecución real del binario distribuido 0.1.0-ga contra la plantilla standard, en un host Ubuntu corriente, como usuario no root. Solo se ha sustituido la dirección IP del operador por una dirección de documentación, y se ha recortado un bloque de error de nft muy largo.

$ bitenforcer generate --template standard --output-file policy.yaml
Example configuration written to policy.yaml

$ bitenforcer validate --config policy.yaml
Configuration 'standard-hardening' is valid.
Environment : staging
Compliance : [CIS-L1]
A valid policy is not a safe one: run `bitenforcer apply --dry-run` to see what it
would change and which guards fire.
(FR) Politique valide. Une politique valide n'est pas pour autant sûre : utilisez
`apply --dry-run`.

$ bitenforcer apply --config policy.yaml --dry-run

=== PRE-FLIGHT: every change this run would make ===
operator "ubuntu" is on an SSH session whose peer socket was NOT measured
(SSH_CONNECTION/SSH_CLIENT in this process's environment (an inherited, settable
environment variable -- a hint, NOT a measured socket)); any address in the
environment is a hint, not evidence

NOT EXAMINED on this host (the rest of the pre-flight below is unaffected):
selinux: SELinux prerequisites check failed: SELinux tools not found
(getenforce not in PATH)
These modules were SKIPPED, not found compliant — this run says nothing
about whether the host matches that part of the policy.
(FR) Modules NON EXAMINÉS sur cet hôte : ignorés, et non déclarés conformes.
1. [command] users /etc/passwd
chmod 0644 /etc/passwd
2. [command] users /etc/passwd
chown root:root /etc/passwd
3. [command] users /etc/shadow
chmod 0640 /etc/shadow
4. [command] users /etc/shadow
chown root:root /etc/shadow
5. [command] users /etc/group
chmod 0644 /etc/group
6. [command] users /etc/group
chown root:root /etc/group
7. [command] users /etc/gshadow
chmod 0640 /etc/gshadow
8. [command] users /etc/gshadow
chown root:root /etc/gshadow
9. [file-write] ssh /etc/ssh/sshd_config
1194 bytes, mode 0600, validated with sshd -t -f <candidate>; NOT VALIDATED in
this dry run (the validator could not be run in this context: sshd -t needs root
to read the host keys (sshd: no hostkeys available -- exiting.)) — re-run the
dry run as root to validate
10. [file-write] firewall /etc/nftables.conf
566 bytes, mode 0600, validated with nft -c -f <candidate>; NOT VALIDATED in
this dry run (nft -c needs root […]) — re-run the dry run as root to validate
11. [file-write] kernel /etc/sysctl.d/99-bitenforcer.conf
672 bytes, mode 0644, validated with sysctl key syntax check
12. [command] kernel /etc/sysctl.d/99-bitenforcer.conf
sysctl -p /etc/sysctl.d/99-bitenforcer.conf

=== PRE-FLIGHT ADVISORIES (the guards; they did NOT block this run) ===
These are the lockout guards. They are advisory: they report the shapes they
recognise, and seven independent reviewers each found one they did not — which is
why this release does not apply anything. Treat a finding as a reason to change the
policy, never as the full list of ways it could strand you. Re-run with
--guards=blocking to have findings exit non-zero, e.g. to gate a policy in CI.
1. [kernel-remote-access-loss] this run would set net.ipv4.conf.all.rp_filter=1,
which drops any packet whose reply route does not leave by the interface it
arrived on
evidence: bitenforcer measures the interface carrying your session (eth0)
but not this host's routing table, so it cannot show that the route back
to 198.51.100.24 leaves by that same interface. On a host with two
uplinks, a VPN, or asymmetric routing, strict reverse-path filtering
drops your session and every future connection from that address
remedy: run `ip route get 198.51.100.24` and confirm it leaves by eth0;
if it does, say so for this one parameter, and keep a second session
open while you apply
override: re-run with --acknowledge kernel-remote-access-loss (this guard only)
2. [kernel-remote-access-loss] this run would set net.ipv4.ip_forward=0, and
bitenforcer cannot establish whether this host routes the network your session
arrives through
…

DRY RUN: nothing above was applied and this host was not changed.
This is the only mode bitenforcer v1 runs in; enforcement is not part of this release.
(FR) SIMULATION : rien n'a été appliqué et cet hôte n'a pas été modifié.

Tres cosas de esa salida son el producto entero:

  1. NOT EXAMINED es una respuesta, no una omisión. El utillaje de SELinux no está en un Ubuntu de serie, así que el módulo selinux se reporta como omitido, explícitamente no declarado conforme, y el resto de la comprobación previa continúa. Una ejecución que no dice nada sobre un control es muy distinta de una ejecución que dice que el control está bien.
  2. NOT VALIDATED nombra el porqué, por fichero. sshd -t necesita root para leer las claves de host, así que como usuario normal la herramienta le dice que el contenido no se comprobó y qué hacer al respecto — en lugar de dar a entender calladamente que sí.
  3. El hallazgo de la protección lleva evidencia, un remedio y una anulación específica. No dice "arriesgado". Dice qué parámetro, qué midió, qué no pudo medir y el comando exacto que usted debería ejecutar para zanjar la cuestión.

Qué le aporta esto hoy​

Es fácil leer "no aplica cambios" como "no hace nada". Esto es lo que compra realmente una herramienta de solo comprobación previa:

  • Un artefacto para la ventana de cambio. Adjunte la salida de la comprobación previa a la solicitud de cambio. Cada fichero, unidad, regla y sysctl, en orden, con los bytes.
  • Un control en CI. --guards=blocking hace fallar la canalización cuando una línea base cortaría el acceso, antes de que llegue a un host.
  • Detectar pronto el contenido roto de una política. sshd -t y nft -c se ejecutan contra el contenido candidato, de modo que una política que genera una configuración no analizable se detecta en revisión.
  • Desviación sobre la que puede actuar, con seguridad. Ejecute la simulación en toda una flota y lea lo que cada host reporta que necesitaría — sin ninguna posibilidad de cambiar nada por accidente.
  • Un mapa de cobertura honesto. NOT EXAMINED le dice dónde la herramienta no tiene nada que decir, para que no confunda el silencio con el cumplimiento.

Política como código​

bitenforcer generate --template standard --output-file policy.yaml

Plantillas: minimal, standard, strict. Son puntos de partida fijos para editar — no leen el host ni derivan una postura de la máquina en la que se ejecutaron. Las políticas generadas hacen ida y vuelta: vuelva a alimentar la salida a validate y pasa.

validate va más allá de comprobar el esquema: una política que fija una clave que nada implementa se rechaza al cargarla, por su nombre, con una declaración de lo que no ocurre. Un ajuste que se analiza pero es inerte es el defecto que estos productos tardaron un mes en eliminar de sí mismos.

Una política válida no es una política segura

validate lee el fichero de política y nada más — no mira este host. Ejecute bitenforcer apply --config <file> --dry-run para averiguar qué cambiaría aquí.

Plataformas​

0.1.0-ga publica dos binarios firmados, y el hueco es deliberado:

PlataformaPublicadaPor qué
Linux amd64Sí
Linux arm64Sí
macOS amd64/arm64NoRetenida — ver abajo
Windows amd64NoRetenida — ver abajo

bitenforcer es solo para Linux porque todo su objeto es Linux. Cada módulo que planifica actúa sobre un mecanismo de Linux: conjuntos de reglas iptables/nftables, claves sysctl bajo /proc/sys, unidades systemd, SELinux y AppArmor, y /etc/passwd, /etc/shadow, /etc/gshadow y sudoers con sus modos y propietarios POSIX. Lo mismo ocurre con los validadores por los que pasa el contenido candidato — sshd -t, visudo -c, nft -c, iptables-restore --test.

Una compilación para macOS o Windows funcionaría. Ese es precisamente el problema: arrancaría, aceptaría una política y produciría una comprobación previa en la que cada módulo aparecería como NOT EXAMINED — un informe que parece una ejecución correcta y no dice nada sobre el host. Dado que esta herramienta existe para decirle qué haría un cambio antes de que lo haga, un binario cuya salida honesta es «no tengo nada que decir sobre esta máquina» es peor que no tener binario. No se publica, para que nadie lo confunda con cobertura.

Si necesita la postura de fortificación de un host macOS, eso es el colector posture de bitcollector, que se distribuye en macOS e informa, control por control, de si fue observado, no observado, o no soportado por el agente allí.

Próximos pasos​

¿Te resultó útil esta página?