18d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft#!/bin/bash 28d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft# 38d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft# iptables-apply -- a safer way to update iptables remotely 48d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft# 58d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft# Copyright © Martin F. Krafft <madduck@madduck.net> 68d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft# Released under the terms of the Artistic Licence 2.0 78d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft# 88d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftset -eu 98d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 108d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftPROGNAME="${0##*/}"; 118d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftVERSION=1.0 128d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 138d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftTIMEOUT=10 148d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftDEFAULT_FILE=/etc/network/iptables 158d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 168d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfunction blurb() 178d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft{ 188d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft cat <<-_eof 198d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft $PROGNAME $VERSION -- a safer way to update iptables remotely 208d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft _eof 218d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft} 228d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 238d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfunction copyright() 248d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft{ 258d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft cat <<-_eof 268d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft $PROGNAME is C Martin F. Krafft <madduck@madduck.net>. 278d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 288d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft The program has been published under the terms of the Artistic Licence 2.0 298d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft _eof 308d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft} 318d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 328d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfunction about() 338d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft{ 348d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft blurb 358d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo 368d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft copyright 378d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft} 388d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 398d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfunction usage() 408d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft{ 418d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft cat <<-_eof 428d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft Usage: $PROGNAME [options] ruleset 438d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 448d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft The script will try to apply a new ruleset (as output by iptables-save/read 458d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft by iptables-restore) to iptables, then prompt the user whether the changes 468d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft are okay. If the new ruleset cut the existing connection, the user will not 478d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft be able to answer affirmatively. In this case, the script rolls back to the 488d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft previous ruleset. 498d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 508d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft The following options may be specified, using standard conventions: 518d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 528d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft -t | --timeout Specify the timeout in seconds (default: $TIMEOUT) 538d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft -V | --version Display version information 548d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft -h | --help Display this help text 558d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft _eof 568d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft} 578d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 588d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftSHORTOPTS="t:Vh"; 598d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftLONGOPTS="timeout:,version,help"; 608d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 618d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftOPTS=$(getopt -s bash -o "$SHORTOPTS" -l "$LONGOPTS" -n "$PROGNAME" -- "$@") || exit $? 628d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfor opt in $OPTS; do 638d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft case "$opt" in 648d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (-*) unset OPT_STATE;; 658d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (*) 668d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft case "${OPT_STATE:-}" in 678d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (SET_TIMEOUT) 688d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft eval TIMEOUT=$opt 698d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft case "$TIMEOUT" in 708d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft ([0-9]*) :;; 718d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (*) 728d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "E: non-numeric timeout value." >&2 738d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft exit 1 748d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft ;; 758d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft esac 768d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft ;; 778d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft esac 788d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft ;; 798d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft esac 808d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 818d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft case "$opt" in 828d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (-h|--help) usage >&2; exit 0;; 838d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (-V|--version) about >&2; exit 0;; 848d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (-t|--timeout) OPT_STATE=SET_TIMEOUT;; 858d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (--) break;; 868d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft esac 878d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft shift 888d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftdone 898d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 908d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftFILE="${1:-$DEFAULT_FILE}"; 918d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 928d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftif [[ -z "$FILE" ]]; then 938d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "E: missing file argument." >&2 948d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft exit 1 958d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfi 968d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 978d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftif [[ ! -r "$FILE" ]]; then 988d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "E: cannot read $FILE" >&2 998d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft exit 2 1008d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfi 1018d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1028d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftcase "${0##*/}" in 1038d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (*6*) 1048d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft SAVE=ip6tables-save 1058d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft RESTORE=ip6tables-restore 1068d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft ;; 1078d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (*) 1088d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft SAVE=iptables-save 1098d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft RESTORE=iptables-restore 1108d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft ;; 1118d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftesac 1128d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1138d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftCOMMANDS=(tempfile "$SAVE" "$RESTORE") 1148d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1158d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfor cmd in "${COMMANDS[@]}"; do 1168d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft if ! command -v $cmd >/dev/null; then 1178d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "E: command not found: $cmd" >&2 1188d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft exit 127 1198d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft fi 1208d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftdone 1218d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1228d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftumask 0700 1238d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1248d458beec463e0b16467ee4649d4575377854fd7Martin F. KrafftTMPFILE=$(tempfile -p iptap) 1258d458beec463e0b16467ee4649d4575377854fd7Martin F. Kraffttrap "rm -f $TMPFILE" EXIT 1 2 3 4 5 6 7 8 10 11 12 13 14 15 1268d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1278d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftif ! "$SAVE" >"$TMPFILE"; then 1288d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft if ! grep -q ipt /proc/modules 2>/dev/null; then 1298d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "E: iptables support lacking from the kernel." >&2 1308d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft exit 3 1318d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft else 1328d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "E: unknown error saving current iptables ruleset." >&2 1338d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft exit 4 1348d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft fi 1358d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfi 1368d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1378d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft[ -x /etc/init.d/fail2ban ] && /etc/init.d/fail2ban stop 1388d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1398d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftecho -n "Applying new ruleset... " 1408d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftif ! "$RESTORE" <"$FILE"; then 1418d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "failed." 1428d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "E: unknown error applying new iptables ruleset." >&2 1438d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft exit 5 1448d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftelse 1458d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo done. 1468d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftfi 1478d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1488d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftecho -n "Can you establish NEW connections to the machine? (y/N) " 1498d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1508d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftread -n1 -t "${TIMEOUT:-15}" ret 2>&1 || : 1518d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftcase "${ret:-}" in 1528d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (y*|Y*) 1538d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo 1548d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo ... then my job is done. See you next time. 1558d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft ;; 1568d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft (*) 1578d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft if [[ -z "${ret:-}" ]]; then 1588d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "apparently not..." 1598d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft else 1608d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo 1618d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft fi 1628d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo "Timeout. Something happened (or did not). Better play it safe..." 1638d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo -n "Reverting to old ruleset... " 1648d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft "$RESTORE" <"$TMPFILE"; 1658d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft echo done. 1668d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft exit 255 1678d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft ;; 1688d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftesac 1698d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1708d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft[ -x /etc/init.d/fail2ban ] && /etc/init.d/fail2ban start 1718d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1728d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafftexit 0 1738d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft 1748d458beec463e0b16467ee4649d4575377854fd7Martin F. Krafft# vim:noet:sw=8 175