iptables-apply 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #!/bin/bash
  2. #
  3. # iptables-apply -- a safer way to update iptables remotely
  4. #
  5. # Copyright © Martin F. Krafft <madduck@madduck.net>
  6. # Released under the terms of the Artistic Licence 2.0
  7. #
  8. set -eu
  9. PROGNAME="${0##*/}";
  10. VERSION=1.0
  11. TIMEOUT=10
  12. function blurb()
  13. {
  14. cat <<-_eof
  15. $PROGNAME $VERSION -- a safer way to update iptables remotely
  16. _eof
  17. }
  18. function copyright()
  19. {
  20. cat <<-_eof
  21. $PROGNAME is C Martin F. Krafft <madduck@madduck.net>.
  22. The program has been published under the terms of the Artistic Licence 2.0
  23. _eof
  24. }
  25. function about()
  26. {
  27. blurb
  28. echo
  29. copyright
  30. }
  31. function usage()
  32. {
  33. cat <<-_eof
  34. Usage: $PROGNAME [options] ruleset
  35. The script will try to apply a new ruleset (as output by iptables-save/read
  36. by iptables-restore) to iptables, then prompt the user whether the changes
  37. are okay. If the new ruleset cut the existing connection, the user will not
  38. be able to answer affirmatively. In this case, the script rolls back to the
  39. previous ruleset.
  40. The following options may be specified, using standard conventions:
  41. -t | --timeout Specify the timeout in seconds (default: $TIMEOUT)
  42. -V | --version Display version information
  43. -h | --help Display this help text
  44. _eof
  45. }
  46. SHORTOPTS="t:Vh";
  47. LONGOPTS="timeout:,version,help";
  48. OPTS=$(getopt -s bash -o "$SHORTOPTS" -l "$LONGOPTS" -n "$PROGNAME" -- "$@") || exit $?
  49. for opt in $OPTS; do
  50. case "$opt" in
  51. (-*) unset OPT_STATE;;
  52. (*)
  53. case "${OPT_STATE:-}" in
  54. (SET_TIMEOUT)
  55. eval TIMEOUT=$opt
  56. case "$TIMEOUT" in
  57. ([0-9]*) :;;
  58. (*)
  59. echo "E: non-numeric timeout value." >&2
  60. exit 1
  61. ;;
  62. esac
  63. ;;
  64. esac
  65. ;;
  66. esac
  67. case "$opt" in
  68. (-h|--help) usage >&2; exit 0;;
  69. (-V|--version) about >&2; exit 0;;
  70. (-t|--timeout) OPT_STATE=SET_TIMEOUT;;
  71. (--) break;;
  72. esac
  73. shift
  74. done
  75. case "$PROGNAME" in
  76. (*6*)
  77. SAVE=ip6tables-save
  78. RESTORE=ip6tables-restore
  79. DEFAULT_FILE=/etc/network/ip6tables
  80. ;;
  81. (*)
  82. SAVE=iptables-save
  83. RESTORE=iptables-restore
  84. DEFAULT_FILE=/etc/network/iptables
  85. ;;
  86. esac
  87. FILE="${1:-$DEFAULT_FILE}";
  88. if [[ -z "$FILE" ]]; then
  89. echo "E: missing file argument." >&2
  90. exit 1
  91. fi
  92. if [[ ! -r "$FILE" ]]; then
  93. echo "E: cannot read $FILE" >&2
  94. exit 2
  95. fi
  96. COMMANDS=(tempfile "$SAVE" "$RESTORE")
  97. for cmd in "${COMMANDS[@]}"; do
  98. if ! command -v $cmd >/dev/null; then
  99. echo "E: command not found: $cmd" >&2
  100. exit 127
  101. fi
  102. done
  103. umask 0700
  104. TMPFILE=$(tempfile -p iptap)
  105. trap "rm -f $TMPFILE" EXIT 1 2 3 4 5 6 7 8 10 11 12 13 14 15
  106. if ! "$SAVE" >"$TMPFILE"; then
  107. if ! grep -q ipt /proc/modules 2>/dev/null; then
  108. echo "E: iptables support lacking from the kernel." >&2
  109. exit 3
  110. else
  111. echo "E: unknown error saving current iptables ruleset." >&2
  112. exit 4
  113. fi
  114. fi
  115. [ -x /etc/init.d/fail2ban ] && /etc/init.d/fail2ban stop
  116. echo -n "Applying new ruleset... "
  117. if ! "$RESTORE" <"$FILE"; then
  118. echo "failed."
  119. echo "E: unknown error applying new iptables ruleset." >&2
  120. exit 5
  121. else
  122. echo done.
  123. fi
  124. echo -n "Can you establish NEW connections to the machine? (y/N) "
  125. read -n1 -t "${TIMEOUT:-15}" ret 2>&1 || :
  126. case "${ret:-}" in
  127. (y*|Y*)
  128. echo
  129. echo ... then my job is done. See you next time.
  130. ;;
  131. (*)
  132. if [[ -z "${ret:-}" ]]; then
  133. echo "apparently not..."
  134. else
  135. echo
  136. fi
  137. echo "Timeout. Something happened (or did not). Better play it safe..."
  138. echo -n "Reverting to old ruleset... "
  139. "$RESTORE" <"$TMPFILE";
  140. echo done.
  141. exit 255
  142. ;;
  143. esac
  144. [ -x /etc/init.d/fail2ban ] && /etc/init.d/fail2ban start
  145. exit 0
  146. # vim:noet:sw=8