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ón | 0.1.0-ga, commit 4c6ce93, 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, SBOM CycloneDX, firma cosign, atestación del SBOM, SHA256SUMS firmado |
| Forma | Herramienta de línea de comandos de un solo disparo. Sin demonio, sin telemetría, sin latido |
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:
| Artefacto | Validador |
|---|---|
sshd_config | sshd -t -f <candidate> |
| sudoers | visudo -c |
| conjunto de reglas de nftables | nft -c -f <candidate> |
| conjunto de reglas de iptables | iptables-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:
NOT EXAMINEDes 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.NOT VALIDATEDnombra el porqué, por fichero.sshd -tnecesita 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í.- 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=blockinghace 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 -tynft -cse 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 EXAMINEDle 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.
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:
| Plataforma | Publicada | Por qué |
|---|---|---|
Linux amd64 | Sí | |
Linux arm64 | Sí | |
macOS amd64/arm64 | No | Retenida — ver abajo |
Windows amd64 | No | Retenida — 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
- Las protecciones, y por qué la v1 no aplica cambios — las dieciocho protecciones contra bloqueo de acceso, el control de CI, y por qué la ruta de aplicación efectiva queda deliberadamente fuera de esta versión.
- Verificación de sus descargas — hágalo antes de la primera ejecución.
- bitcollector — la mitad de la pareja que reporta, y de donde viene la evidencia continua de postura.
- Marcos de cumplimiento — cómo se mapean los controles.
¿Te resultó útil esta página?