Un Interrupteur Homme Mort pour les Modifications de Pare-feu

La ligne la plus effrayante dans l’automatisation homelab est celle qui modifie une règle de pare-feu sur le routeur auquel vous êtes connecté via SSH.

Voici comment Claude Code et moi les modifions quand même.


La Peur

Je devais changer une règle UDM Pro nommée “Block inter-VLAN traffic” de accept à drop. La règle avait été mal configurée depuis des lustres — réglée sur accept, court-circuitant chaque permission par flux au-dessus d’elle — et la refermer était tout l’enjeu. L’orchestrateur exécutant le changement était une VM NixOS sur mon réseau domestique. Si le changement coupait le chemin qu’utilisait cette VM (ou mon propre SSH), je serais exclu de mon propre routeur sans accès console de secours.

La solution n’est pas “faire attention.” La solution consiste à faire en sorte que la modification dangereuse se rétablisse automatiquement sauf si je confirme qu’elle est correcte.

Vous avez déjà vu ce schéma. Changez la résolution de votre moniteur sous macOS ou Windows et le système l’applique pendant quinze secondes avec une boîte de dialogue “Conserver ces paramètres d’affichage ?” qui décompte. Si votre écran est devenu noir, vous ne pouvez rien cliquer — et c’est bien là le but. Le résultat par défaut est le retour arrière. La confirmation est opt-in.

C’est exactement ce que nous voulons pour un changement de pare-feu sur un routeur dont nous allons modifier les règles.


L’Astuce

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

À lire comme : “basculer la règle, mais revenir automatiquement en arrière dans 300 secondes sauf si je te dis de ne pas le faire.”

Ce qu’il fait, dans l’ordre :

  1. Instantané. GETs la règle actuelle et stocke le payload JSON complet sur le UDM dans /root/.udm-flip-revert/payload-<id>.json.
  2. Préparer le retour arrière. Écrit un petit script shell à côté du payload qui re-PUT l’instantané vers l’API UDM.
  3. Planifier le retour arrière. systemd-run --on-active=300s --unit=udm-flip-revert-<id> met en file d’attente le script comme minuterie transitoire.
  4. Basculer. PUTs la nouvelle règle (action: drop).

Vous avez maintenant une fenêtre de 5 minutes pour vérifier :

✓ 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

Trois résultats :

Le troisième cas est toute la raison d’être de ce mécanisme.


Pourquoi systemd-run et pas at(1)

UDM Pro (Debian 11) ne fournit pas atd. Il a systemd. systemd-run --on-active=Ns crée une minuterie transitoire qui se déclenche une fois et s’auto-collecte, ce qui est exactement la forme de “faire cette chose dans N secondes puis disparaître.”

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

--collect est le drapeau clé — sans lui, l’unité reste dans un état failed/inactive et encombre systemctl.


La Mise en Garde

Les unités systemd transitoires vivent dans /run, qui est tmpfs. Si le UDM redémarre dans la fenêtre de retour arrière, la minuterie disparaît — et le basculement reste appliqué sans garde-fou pour le surveiller.

Contre-intuitif mais réel : gardez la fenêtre courte. Une fenêtre de 5 minutes avec un petit risque de redémarrage est plus sûre qu’une fenêtre d'1 heure où une coupure d’onduleur à la minute 12 vous laisse avec un verrouillage permanent. Assez longue pour vérifier, assez courte pour que “Ai-je oublié un retour arrière en attente ?” ne soit jamais une question.


Conclusion

Le schéma homme mort se généralise au-delà des règles de pare-feu UDM. Partout où vous êtes sur le point d’appliquer un changement qui pourrait couper le chemin par lequel vous l’avez appliqué — tables de routage, sshd_config, nftables, BGP — la même forme fonctionne :

  1. Capturer l’état actuel
  2. Préparer un script qui le restaure
  3. Planifier l’exécution du script dans N secondes
  4. Appliquer le changement

Si vous êtes encore là dans N+ε secondes et que tout va bien, annulez la minuterie. Sinon, la minuterie vous annule.

Je dors mieux avec ça dans la boîte à outils.