Un Interruttore Uomo Morto per le Modifiche al Firewall
La riga più spaventosa nell’automazione del homelab è quella che modifica una regola firewall sul router a cui sei connesso via SSH.
Ecco come Claude Code e io le modifichiamo comunque.
La Paura
Dovevo cambiare una regola UDM Pro chiamata “Block inter-VLAN traffic” da accept a drop. La regola era stata configurata male per secoli — impostata su accept, cortocircuitando ogni permesso per-flusso sopra di essa — e chiuderla di nuovo era tutto il punto. L’orchestratore che eseguiva la modifica era una VM NixOS sulla mia rete domestica. Se il cambiamento eliminava il percorso che quella VM (o il mio SSH) stava usando, sarei rimasto bloccato fuori dal mio router senza accesso alla console.
La soluzione non è “fare attenzione.” La soluzione è far sì che la modifica pericolosa si ripristini automaticamente a meno che non la confermi come corretta.
Hai già visto questo schema. Cambia la risoluzione del monitor su macOS o Windows e il sistema la applica per quindici secondi con una finestra di dialogo “Mantenere queste impostazioni dello schermo?” che conta alla rovescia. Se lo schermo è diventato nero, non puoi fare clic su nulla — e questo è il punto. Il risultato predefinito è il rollback. La conferma è opt-in.
È esattamente quello che vogliamo per un cambio di firewall su un router di cui stiamo per cambiare le regole.
Il Trucco
udm_set_firewall_rules.py --flip-with-revert 300 --apply
Leggere come: “cambia la regola, ma ripristina automaticamente in 300 secondi a meno che non ti dica diversamente.”
Cosa fa, in ordine:
- Snapshot. GETs la regola corrente e salva il payload JSON completo sul UDM in
/root/.udm-flip-revert/payload-<id>.json. - Prepara il ripristino. Scrive un piccolo script shell accanto al payload che ri-PUT lo snapshot all’API UDM.
- Pianifica il ripristino.
systemd-run --on-active=300s --unit=udm-flip-revert-<id>mette in coda lo script come timer transitorio. - Cambia. PUT la nuova regola (
action: drop).
Ora hai una finestra di 5 minuti per verificare:
✓ 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
Tre risultati:
- Ha funzionato. Ferma il timer. Il cambio è permanente.
- Ha rotto qualcosa. Ferma il timer, esegui lo script di ripristino. O smetti semplicemente di digitare — il timer scatta dopo N secondi e la regola torna da sola.
- Mi ha bloccato fuori. Stesso. Il timer non ha bisogno di me per scattare.
Il terzo caso è la ragione per cui tutto questo esiste.
Perché systemd-run e non at(1)
UDM Pro (Debian 11) non include atd. Ha systemd. systemd-run --on-active=Ns crea un timer transitorio che scatta una volta e si auto-raccoglie, che è esattamente la forma di “fai questa cosa tra N secondi e poi sparisci.”
ssh_udm(
f"systemd-run --on-active={seconds} --unit={unit} --collect "
f"--quiet /bin/bash {script_file}"
)
--collect è il flag chiave — senza di esso l’unit rimane in stato failed/inactive e ingombra systemctl.
La Cautela
Le unit systemd transitorie vivono in /run, che è tmpfs. Se il UDM si riavvia durante la finestra di ripristino, il timer è sparito — e il cambio rimane applicato senza un uomo morto che lo sorveglia.
Controintuitivo ma reale: mantieni la finestra breve. Una finestra di 5 minuti con un piccolo rischio di riavvio è più sicura di una finestra di 1 ora dove un’interruzione dell’UPS al minuto 12 ti lascia con un blocco permanente. Abbastanza lunga per verificare, abbastanza breve perché “mi sono dimenticato di un ripristino pendente?” non sia mai una domanda.
Conclusione
Il pattern dell’uomo morto si generalizza oltre le regole firewall UDM. Ovunque stai per applicare una modifica che potrebbe interrompere il percorso attraverso cui l’hai applicata — tabelle di routing, sshd_config, nftables, BGP — la stessa forma funziona:
- Cattura lo stato corrente
- Prepara uno script che lo ripristini
- Pianifica lo script per essere eseguito tra N secondi
- Applica la modifica
Se sei ancora lì dopo N+ε secondi e le cose sembrano buone, annulla il timer. Se no, il timer annulla te.
Dormo meglio con questo nella cassetta degli attrezzi.