Un Interruptor de Hombre Muerto para Ediciones de Firewall

La línea más aterradora en la automatización del homelab es la que edita una regla de firewall en el router al que estás conectado por SSH.

Así es como Claude Code y yo las editamos de todas formas.


El Miedo

Necesitaba cambiar una regla de UDM Pro llamada “Block inter-VLAN traffic” de accept a drop. La regla había estado mal configurada durante mucho tiempo — establecida en accept, cortocircuitando cada permiso por flujo por encima de ella — y volver a cerrarla era el objetivo. El orquestador que ejecutaba el cambio era una VM NixOS en mi red doméstica. Si el cambio eliminaba la ruta que usaba esa VM (o mi propio SSH), quedaría bloqueado fuera de mi propio router sin acceso a la consola.

La solución no es “tener cuidado”. La solución es hacer que la edición peligrosa se revierta automáticamente a menos que confirme que está bien.

Ya has visto este patrón antes. Cambia la resolución de tu monitor en macOS o Windows y el sistema la aplica durante quince segundos con un diálogo “¿Mantener esta configuración de pantalla?” con cuenta regresiva. Si la pantalla se puso negra, no puedes hacer clic en nada — y ese es el punto. El resultado predeterminado es la reversión. La confirmación es opt-in.

Eso es exactamente lo que queremos para un cambio de firewall en un router cuyas reglas estamos a punto de cambiar.


El Truco

udm_set_firewall_rules.py --flip-with-revert 300 --apply

Leído como: “cambia la regla, pero revierte automáticamente en 300 segundos a menos que te diga que no.”

Lo que hace, en orden:

  1. Instantánea. Obtiene la regla actual con GET y guarda el payload JSON completo en el UDM en /root/.udm-flip-revert/payload-<id>.json.
  2. Preparar la reversión. Escribe un pequeño script de shell junto al payload que vuelve a enviar la instantánea a la API del UDM con PUT.
  3. Programar la reversión. systemd-run --on-active=300s --unit=udm-flip-revert-<id> pone en cola el script como un temporizador transitorio.
  4. Cambiar. Envía la nueva regla con PUT (action: drop).

Ahora tienes una ventana de 5 minutos para verificar:

✓ flipped 'Block inter-VLAN traffic' to action='drop'
⏱  auto-revert scheduled (~300s)

TO KEEP THE FLIP:    ssh udm 'systemctl stop udm-flip-revert-66c1d…timer'
TO ROLL BACK NOW:    ssh udm 'systemctl stop …timer; bash /root/.udm-flip-revert/revert-….sh'
WAIT IT OUT:         do nothing — timer will revert in ~300s

Tres resultados posibles:

El tercer caso es la razón de ser de todo esto.


Por qué systemd-run y no at(1)

UDM Pro (Debian 11) no incluye atd. Sí tiene systemd. systemd-run --on-active=Ns crea un temporizador transitorio que se dispara una vez y se autodestruye, que es exactamente la forma de “haz esto en N segundos y luego desaparece.”

ssh_udm(
    f"systemd-run --on-active={seconds} --unit={unit} --collect "
    f"--quiet /bin/bash {script_file}"
)

--collect es el flag clave — sin él la unidad permanece en estado failed/inactive y desordena systemctl.


La Advertencia

Las unidades transitorias de systemd viven en /run, que es tmpfs. Si el UDM reinicia durante la ventana de reversión, el temporizador desaparece — y el cambio permanece aplicado sin ningún interruptor de hombre muerto vigilándolo.

Contraintuitivo pero real: mantén la ventana corta. Una ventana de 5 minutos con un pequeño riesgo de reinicio es más segura que una ventana de 1 hora donde un fallo del SAI en el minuto 12 te deja con un bloqueo permanente. Suficientemente larga para verificar, suficientemente corta para que “¿olvidé una reversión pendiente?” nunca sea una pregunta.


Conclusión

El patrón del interruptor de hombre muerto se generaliza más allá de las reglas de firewall de UDM. En cualquier lugar donde estés a punto de aplicar un cambio que podría cortar la ruta por la que lo aplicaste — tablas de enrutamiento, sshd_config, nftables, BGP — la misma forma funciona:

  1. Captura el estado actual
  2. Prepara un script que lo restaure
  3. Programa el script para que se ejecute en N segundos
  4. Aplica el cambio

Si sigues ahí en N+ε segundos y todo se ve bien, cancela el temporizador. Si no, el temporizador te cancela a ti.

Duermo mejor con esto en la caja de herramientas.