La fila de la tabla se leía como «bloquear sitios». El cortafuegos NO sabe de sitios: su política de egress tiene UNA dimensión, qué cgroup sale, y ninguna de destino (leído en UnidadRed, no supuesto). El foco que estas piezas dan es «el navegador no sale», con todo lo local andando — promesa más honesta, además: una lista de dominios se esquiva con un espejo; un cgroup sin egress no. Medido con nuestro propio nft, en el LXC donde somos root: linea-base exit=0 · control exit=0 · foco exit=1 Tres medidas y no una: la línea base porque un harness roto se lee igual que un foco que funciona, y el control porque un reglaset que niega de más tampoco se distingue. `--broken-rules` abre egress al cgroup en foco y el guardián falla nombrándolo (sale 1). Verificado en los dos sentidos. Restricciones reales que salieron de medir: crear un cgroup pide root (EPERM incluso en un userns con CAP_ALL), y `nft -c` no es sintaxis — resuelve el path del cgroup contra la máquina viva. ⚠ Y lo que rompí en el camino, documentado: `/sys/fs/cgroup` está montado SHARED, así que desmontar la copia de un --rbind se propaga al montaje real. Dejé al worker sin cgroup2 dos veces, en silencio. Remontado y jerarquía intacta. Ahora todo va en un mount namespace propio (--propagation private), sin `umount -l` antes de un rm -rf, y con /proc/mounts consultado antes de borrar. Tres falsos positivos más que cazó el harness, todos con cara de éxito: un gmp viejo tomado por `ls store/*-gmp` (sin .so ⇒ nada conectaba, y el lab del hub lo tapaba), /sbin fuera del PATH del chroot (sin `ip`, loopback caído), y un COMENTARIO que se ejecutó — backticks dentro de un heredoc sin comillas corrieron `ip`/`ifconfig` en el host y pegaron su salida en el guión generado.
50 lines
2.3 KiB
Bash
Executable File
50 lines
2.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Corre `test-foco-egress.sh` donde SÍ hay root: empaqueta los artefactos VIGENTES, los manda al
|
|
# worker y trae el veredicto.
|
|
#
|
|
# scripts/foco-egress-remoto.sh [--broken-rules] [host] (host default: 1º de scripts/farm/.fleet)
|
|
#
|
|
# ⚠ Los artefactos se resuelven con `takana hash`, NO con `ls store/*-gmp`. La diferencia no es
|
|
# estética: el store guarda artefactos VIEJOS con el mismo nombre, y la primera corrida de esto
|
|
# empaquetó un `gmp` de otra época que sólo traía `libgmp.a` ⇒ `libnftables.so` no relocaba. En el
|
|
# hub no se veía porque el lab tiene su propia libgmp y la tapaba. Sellado ≠ vigente.
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
|
|
ROTO=""
|
|
if [ "${1:-}" = "--broken-rules" ]; then ROTO="--broken-rules"; shift; fi
|
|
HOST="${1:-}"
|
|
if [ -z "$HOST" ]; then
|
|
HOST="$(awk 'NR==1{print $1}' scripts/farm/.fleet 2>/dev/null || true)"
|
|
[ -n "$HOST" ] || { echo "✗ no hay host: pasalo por argumento o poné uno en scripts/farm/.fleet" >&2; exit 2; }
|
|
fi
|
|
LLAVE="${SSH_KEY:-$HOME/.ssh/github5}"
|
|
TAKANA=./target/release/takana
|
|
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
|
|
|
|
echo "== artefactos vigentes"
|
|
DIRS=()
|
|
for r in nftables libmnl libnftnl gmp; do
|
|
h="$($TAKANA --store ./store hash "recipes/$r.toml" | tail -1)"; h="${h#b3:}"
|
|
d="store/$h-$r"
|
|
[ -d "$d" ] || { echo "✗ $r vigente no está sellado ($d) — construilo antes" >&2; exit 1; }
|
|
[ -n "$(ls -A "$d")" ] || { echo "✗ $r vigente está VACÍO: eso no es un artefacto, es un nombre" >&2; exit 1; }
|
|
echo " $r → ${h:0:12}"
|
|
DIRS+=("$h-$r")
|
|
done
|
|
tar czf "$TMP/artefactos-nft.tar.gz" -C store "${DIRS[@]}"
|
|
|
|
echo "== enviando a $HOST"
|
|
scp -i "$LLAVE" -o StrictHostKeyChecking=no -q \
|
|
scripts/test-foco-egress.sh .dev-fs/alpine-minirootfs.tar.gz "$TMP/artefactos-nft.tar.gz" \
|
|
"root@$HOST:/root/"
|
|
# `set -e` mataría el script antes de leer $? de un ssh que falla, y entonces el veredicto ROJO del
|
|
# guardián llegaría como si nunca hubiera corrido. Se captura explícitamente.
|
|
SALIDA=0
|
|
ssh -i "$LLAVE" -o BatchMode=yes "root@$HOST" \
|
|
"bash /root/test-foco-egress.sh --rootfs /root/alpine-minirootfs.tar.gz --artifacts /root/artefactos-nft.tar.gz $ROTO" \
|
|
|| SALIDA=$?
|
|
ssh -i "$LLAVE" -o BatchMode=yes "root@$HOST" \
|
|
'rm -f /root/test-foco-egress.sh /root/alpine-minirootfs.tar.gz /root/artefactos-nft.tar.gz' || true
|
|
exit $SALIDA
|