#!/usr/bin/perl # vim: set ts=4 sw=4 tw=78 et si: # use strict; use warnings; my $timeout = 15; my $it_save = '/sbin/iptables-save'; my $it_restore = '/sbin/iptables-restore'; my $new_rules = shift || '/tmp/iptables.rules'; my $old_rules = shift || $new_rules . '.bak'; backup($old_rules); eval { local $SIG{ALRM} = sub { die "alarm\n" }; # see 'perldoc -f alarm'! restore($new_rules); print "Please type 'yes' to commit\n"; alarm $timeout; while (<>) { last if /yes/i; } alarm 0; }; if ($@) { die unless $@ eq "alarm\n"; # timed out restore($old_rules); print "Timed out. Old rules restored from '$old_rules'\n"; } else { # didn't time out print "New iptables rules from '$new_rules' commited\n"; } sub backup { my $path = shift; my $lines = 0; if (open my $out, '>', $path) { if (open my $in, '-|', $it_save) { while (<$in>) { print $out $_; $lines++; } close $in; } else { die "backup: can't run '$it_save' to read iptables: $!"; } close $out; } else { die "backup: can't open '$path' for writing: $!"; } die "backup: iptables-save delivered no output" unless $lines; } # backup() sub restore { my $path = shift; if (open my $in, '<', $path) { if (open my $out, '|-', $it_restore) { while (<$in>) { print $out $_; } close $out; } else { die "restore: can't run '$it_restore' to write iptables: $!"; } close $in; } else { die "restore: can't open '$path' for reading: $!"; } } # restore()