ファイアウォール編集のためのデッドマンスイッチ

ホームラボの自動化で最も怖いのは、SSHで接続中のルーターのファイアウォールルールを編集する行だ。

それでも、Claude Codeと私がどのように編集するかを紹介する。


恐怖

UDM Proの “Block inter-VLAN traffic” というルールを accept から drop に変更する必要があった。このルールは長い間誤って設定されていた――accept に設定されており、その上にあるすべてのフロー別許可をショートサーキットしていた――そして、それを閉じ直すことが目的だった。変更を実行するオーケストレーターは、自宅ネットワーク上のNixOS VMだった。もし変更によってそのVM(または自分自身のSSH)が使用しているパスが切断されれば、コンソールのフォールバックもなく、自分のルーターから締め出されることになる。

解決策は「注意する」ことではない。解決策は、危険な編集を自動的に元に戻すようにすることだ――問題ないと確認しない限り。

このパターンはすでに見たことがあるはずだ。macOSやWindowsでモニターの解像度を変更すると、「この表示設定を維持しますか?」というカウントダウンダイアログとともに15秒間適用される。画面が真っ黒になった場合、何もクリックできない――それがポイントだ。デフォルトの結果はロールバック。確認はオプトインだ。

これがまさに、ルールを変更しようとしているルーターのファイアウォール変更に対して求めるものだ。


トリック

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

意味:「ルールを切り替えるが、300秒後に自動的に元に戻す――やめるよう指示しない限り。」

順番に何をするか:

  1. スナップショット。 現在のルールをGETして、完全なJSONペイロードをUDMの /root/.udm-flip-revert/payload-<id>.json に保存する。
  2. リバートの準備。 ペイロードの隣に小さなシェルスクリプトを書く。このスクリプトはスナップショットをUDM APIにPUTし直す。
  3. リバートのスケジュール。 systemd-run --on-active=300s --unit=udm-flip-revert-<id> でスクリプトを一時タイマーとしてキューに入れる。
  4. 切り替え。 新しいルール(action: drop)をPUTする。

これで5分間の確認ウィンドウが得られる:

✓ 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

3つの結果:

3番目のケースこそが、これが存在する理由だ。


なぜ at(1) ではなく systemd-run なのか

UDM Pro(Debian 11)には atd が付属していない。systemdはある。systemd-run --on-active=Ns は一度だけ発動して自己削除する一時タイマーを作成する。これはまさに「N秒後にこれをして、その後消える」という形だ。

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

--collect がキーフラグだ――これがないと、ユニットがfailed/inactive状態に留まり、systemctl が散らかる。


注意点

一時的なsystemdユニットは /run に存在し、これはtmpfsだ。リバートウィンドウ内にUDMが再起動した場合、タイマーは消えてしまう――そして切り替えはデッドマンの監視なしに適用されたままになる。

直感に反するが現実的だ:ウィンドウを短く保つ。小さな再起動リスクのある5分間のウィンドウは、12分目のUPSの不具合で永続的な締め出しをもたらす1時間のウィンドウよりも安全だ。確認するのに十分な長さで、「保留中のリバートを忘れたか?」が決して問いにならないほど短い。


まとめ

デッドマンパターンはUDMファイアウォールルールを超えて一般化できる。適用したパスを切断する可能性のある変更を適用しようとする場所――ルーティングテーブル、sshd_config、nftables、BGP――どこでも同じ形が機能する:

  1. 現在の状態を記録する
  2. それを復元するスクリプトを準備する
  3. N秒後に実行するようスクリプトをスケジュールする
  4. 変更を適用する

N+ε秒後もまだそこにいて、問題がなければ、タイマーをキャンセルする。そうでなければ、タイマーがあなたをキャンセルする。

このツールを持っているとよく眠れる。