diff --git a/CHANGELOG.md b/CHANGELOG.md index 4995bee..a3583c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ and this project **does not adhere to [Semantic Versioning](http://semver.org/sp ### Added +* safe-start and safe-restart + ### Changed ### Deprecated diff --git a/minifirewall b/minifirewall index 2272a4b..286d4ab 100755 --- a/minifirewall +++ b/minifirewall @@ -111,6 +111,10 @@ STATE_FILE_DIFF='/var/run/minifirewall_state_diff' ACTIVE_CONFIG='/var/run/minifirewall_active_config' ACTIVE_CONFIG_DIFF="${ACTIVE_CONFIG}.diff" +SAFETY_LOCK='/var/run/minifirewall_safety.lock' +SAFETY_OUTPUT='/var/run/minifirewall_safety.out' +SAFETY_TIMER=30 + LOGGER_BIN=$(command -v logger) # No colors by default @@ -123,8 +127,12 @@ CYAN='' WHITE='' BOLD='' RESET='' + # check if stdout is a terminal... -if [ -t 1 ]; then +if [ -t 0 ]; then + INTERACTIVE=1 +elif [ -t 1 ]; then + INTERACTIVE=0 # see if it supports colors... ncolors=$(tput colors) @@ -142,6 +150,7 @@ if [ -t 1 ]; then RESET='\e[m' fi fi +readonly INTERACTIVE ## pseudo dry-run : ## Uncomment and call these functions instead of the real iptables and ip6tables commands @@ -155,6 +164,9 @@ fi # } ## Beware that commands executed from included files are not modified by this trick. +is_interactive() { + test "${INTERACTIVE}" = "1" +} remove_colors() { sed -r 's/\x1B\[(;?[0-9]{1,3})+[mGK]//g' } @@ -1143,6 +1155,57 @@ reset() { syslog_info "reset" printf "${GREEN}${BOLD}${PROGNAME} reset${RESET}\n" } + +stop_if_locked() { + count=0 + + while [ ${count} -lt ${SAFETY_TIMER} ] && [ -f "${SAFETY_LOCK}" ]; do + count=$(( count + 1 )) + sleep 1 + done + + if [ -f "${SAFETY_LOCK}" ]; then + syslog_error "safety lock is still here after ${SAFETY_TIMER} seconds, we need to stop" + + stop + + syslog_info "remove safety lock" + rm -f "${SAFETY_LOCK}" + else + syslog_info "safety lock is not there anymore, life goes on" + fi +} + +safe_start() { + # start the firewall + start + + # create the lock file + syslog_info "add safety lock" + touch "${SAFETY_LOCK}" + + # run the special background command + nohup "${0}" stop-if-locked > "${SAFETY_OUTPUT}" 2>&1 & + + if is_interactive; then + syslog_info "safe-restart in interactive mode ; if safety lock (${SAFETY_LOCK}) is not removed in the next ${SAFETY_TIMER} seconds, minifirewall will be stopped." + # Ask for input + confirm_default="I'm locked out, please stop the firewall" + printf "If the restart has locked you out you might see this\nbut you should not be able to type anything.\nPlease confirm you're still here: " + + read -r confirm + + if [ ! -f "${SAFETY_LOCK}" ]; then + printf "Safety lock is not there anymore.\nYou've probably been rescued by the safety checks.\n" + elif [ "${confirm}" != "${confirm_default}" ]; then + printf "OK, let's remove the safety lock.\n" + rm -f "${SAFETY_LOCK}" + fi + else + syslog_info "safe-restart in non-interactive mode ; if safety lock (${SAFETY_LOCK}) is not removed in the next ${SAFETY_TIMER} seconds, minifirewall will be stopped." + fi +} + show_version() { cat <