summaryrefslogtreecommitdiff
path: root/iptables-apply
diff options
context:
space:
mode:
Diffstat (limited to 'iptables-apply')
-rwxr-xr-xiptables-apply174
1 files changed, 174 insertions, 0 deletions
diff --git a/iptables-apply b/iptables-apply
new file mode 100755
index 0000000..5fec76b
--- /dev/null
+++ b/iptables-apply
@@ -0,0 +1,174 @@
+#!/bin/bash
+#
+# iptables-apply -- a safer way to update iptables remotely
+#
+# Copyright © Martin F. Krafft <madduck@madduck.net>
+# Released under the terms of the Artistic Licence 2.0
+#
+set -eu
+
+PROGNAME="${0##*/}";
+VERSION=1.0
+
+TIMEOUT=10
+DEFAULT_FILE=/etc/network/iptables
+
+function blurb()
+{
+ cat <<-_eof
+ $PROGNAME $VERSION -- a safer way to update iptables remotely
+ _eof
+}
+
+function copyright()
+{
+ cat <<-_eof
+ $PROGNAME is C Martin F. Krafft <madduck@madduck.net>.
+
+ The program has been published under the terms of the Artistic Licence 2.0
+ _eof
+}
+
+function about()
+{
+ blurb
+ echo
+ copyright
+}
+
+function usage()
+{
+ cat <<-_eof
+ Usage: $PROGNAME [options] ruleset
+
+ The script will try to apply a new ruleset (as output by iptables-save/read
+ by iptables-restore) to iptables, then prompt the user whether the changes
+ are okay. If the new ruleset cut the existing connection, the user will not
+ be able to answer affirmatively. In this case, the script rolls back to the
+ previous ruleset.
+
+ The following options may be specified, using standard conventions:
+
+ -t | --timeout Specify the timeout in seconds (default: $TIMEOUT)
+ -V | --version Display version information
+ -h | --help Display this help text
+ _eof
+}
+
+SHORTOPTS="t:Vh";
+LONGOPTS="timeout:,version,help";
+
+OPTS=$(getopt -s bash -o "$SHORTOPTS" -l "$LONGOPTS" -n "$PROGNAME" -- "$@") || exit $?
+for opt in $OPTS; do
+ case "$opt" in
+ (-*) unset OPT_STATE;;
+ (*)
+ case "${OPT_STATE:-}" in
+ (SET_TIMEOUT)
+ eval TIMEOUT=$opt
+ case "$TIMEOUT" in
+ ([0-9]*) :;;
+ (*)
+ echo "E: non-numeric timeout value." >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+
+ case "$opt" in
+ (-h|--help) usage >&2; exit 0;;
+ (-V|--version) about >&2; exit 0;;
+ (-t|--timeout) OPT_STATE=SET_TIMEOUT;;
+ (--) break;;
+ esac
+ shift
+done
+
+FILE="${1:-$DEFAULT_FILE}";
+
+if [[ -z "$FILE" ]]; then
+ echo "E: missing file argument." >&2
+ exit 1
+fi
+
+if [[ ! -r "$FILE" ]]; then
+ echo "E: cannot read $FILE" >&2
+ exit 2
+fi
+
+case "${0##*/}" in
+ (*6*)
+ SAVE=ip6tables-save
+ RESTORE=ip6tables-restore
+ ;;
+ (*)
+ SAVE=iptables-save
+ RESTORE=iptables-restore
+ ;;
+esac
+
+COMMANDS=(tempfile "$SAVE" "$RESTORE")
+
+for cmd in "${COMMANDS[@]}"; do
+ if ! command -v $cmd >/dev/null; then
+ echo "E: command not found: $cmd" >&2
+ exit 127
+ fi
+done
+
+umask 0700
+
+TMPFILE=$(tempfile -p iptap)
+trap "rm -f $TMPFILE" EXIT 1 2 3 4 5 6 7 8 10 11 12 13 14 15
+
+if ! "$SAVE" >"$TMPFILE"; then
+ if ! grep -q ipt /proc/modules 2>/dev/null; then
+ echo "E: iptables support lacking from the kernel." >&2
+ exit 3
+ else
+ echo "E: unknown error saving current iptables ruleset." >&2
+ exit 4
+ fi
+fi
+
+[ -x /etc/init.d/fail2ban ] && /etc/init.d/fail2ban stop
+
+echo -n "Applying new ruleset... "
+if ! "$RESTORE" <"$FILE"; then
+ echo "failed."
+ echo "E: unknown error applying new iptables ruleset." >&2
+ exit 5
+else
+ echo done.
+fi
+
+echo -n "Can you establish NEW connections to the machine? (y/N) "
+
+read -n1 -t "${TIMEOUT:-15}" ret 2>&1 || :
+case "${ret:-}" in
+ (y*|Y*)
+ echo
+ echo ... then my job is done. See you next time.
+ ;;
+ (*)
+ if [[ -z "${ret:-}" ]]; then
+ echo "apparently not..."
+ else
+ echo
+ fi
+ echo "Timeout. Something happened (or did not). Better play it safe..."
+ echo -n "Reverting to old ruleset... "
+ "$RESTORE" <"$TMPFILE";
+ echo done.
+ exit 255
+ ;;
+esac
+
+[ -x /etc/init.d/fail2ban ] && /etc/init.d/fail2ban start
+
+exit 0
+
+# vim:noet:sw=8