diff --git a/CHANGELOG.md b/CHANGELOG.md index 37bdd103..c529c00e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ The **patch** part changes is incremented if multiple releases happen the same m * all: change syntax "become: [yes,no]" → "become: [true,false]" * elasticsearch: improve networking configuration * evolinux-users: remove Stretch references in tasks that also apply to next Debian versions +* minifirewall: upstream release 23.07 * mysql: improve shell syntax for mysql_skip script * pbbouncer: minor fixes * varnish: Allow the systemd template to be overriden with a template outside of the role diff --git a/minifirewall/files/minifirewall b/minifirewall/files/minifirewall index 3922e889..2272a4b0 100755 --- a/minifirewall/files/minifirewall +++ b/minifirewall/files/minifirewall @@ -5,7 +5,7 @@ # It uses netfilter/iptables http://netfilter.org/ designed for recent Linux kernel # See https://gitea.evolix.org/evolix/minifirewall -# Copyright (c) 2007-2022 Evolix +# Copyright (c) 2007-2023 Evolix # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 @@ -29,14 +29,19 @@ # Description: Firewall designed for standalone server ### END INIT INFO -VERSION="23.02" +VERSION="23.07" -NAME="minifirewall" +PROGNAME="minifirewall" # shellcheck disable=SC2034 DESC="Firewall designed for standalone server" set -u +if [ "$(id -u)" -ne "0" ] ; then + echo "${PROGNAME} must be run as root." >&2 + exit 1 +fi + # Variables configuration ######################### @@ -103,6 +108,9 @@ STATE_FILE_CURRENT='/var/run/minifirewall_state_current' STATE_FILE_PREVIOUS='/var/run/minifirewall_state_previous' STATE_FILE_DIFF='/var/run/minifirewall_state_diff' +ACTIVE_CONFIG='/var/run/minifirewall_active_config' +ACTIVE_CONFIG_DIFF="${ACTIVE_CONFIG}.diff" + LOGGER_BIN=$(command -v logger) # No colors by default @@ -152,12 +160,12 @@ remove_colors() { } syslog_info() { if [ -x "${LOGGER_BIN}" ]; then - ${LOGGER_BIN} -t "${NAME}" -p daemon.info "$1" + ${LOGGER_BIN} -t "${PROGNAME}" -p daemon.info "$1" fi } syslog_error() { if [ -x "${LOGGER_BIN}" ]; then - ${LOGGER_BIN} -t "${NAME}" -p daemon.error "$1" + ${LOGGER_BIN} -t "${PROGNAME}" -p daemon.error "$1" fi } sort_values() { @@ -254,14 +262,91 @@ source_configuration() { source_file_or_error "${config_file}" fi } +include_files() { + if [ -d "${includes_dir}" ]; then + find ${includes_dir} -type f -readable -not -name '*.*' | sort -h + else + echo "" + fi +} source_includes() { if [ -d "${includes_dir}" ]; then - include_files=$(find ${includes_dir} -type f -readable -not -name '*.*' | sort -h) - for include_file in ${include_files}; do + for include_file in $(include_files); do source_file_or_error "${include_file}" done fi } +filter_config_file() { + # Remove lines with: + # * empty or only whitespaces + # * comments + grep --extended-regexp --invert-match -e "^(\s*#)" -e "^\s*$" "${1}" +} +save_active_configuration() { + dest_file=${1} + rm -f "${dest_file}" + + echo "# ${config_file}" >> "${dest_file}" + filter_config_file "${config_file}" >> "${dest_file}" + + found_include_files=$(include_files) + if [ -n "${found_include_files}" ]; then + for include_file in ${found_include_files}; do + echo "# ${include_file}" >> "${dest_file}" + filter_config_file "${include_file}" >> "${dest_file}" + done + fi +} +check_active_configuration() { + # NRPE-compatible return codes + # 0: OK + # 1: WARNING + # 2: CRITICAL + # 3: UNKNOWN + rc=0 + + if [ -f "${ACTIVE_CONFIG}" ]; then + cmp_bin=$(command -v cmp) + diff_bin=$(command -v diff) + + if [ -z "${cmp_bin}" ]; then + printf "${YELLOW}WARNING: Skipped active configuration check (Can't find cmp(1) command)${RESET}\n" + rc=1 + elif [ -z "${diff_bin}" ]; then + printf "${YELLOW}WARNING: Skipped active configuration check (Can't find diff(1) command)${RESET}\n" + rc=1 + else + rm -f "${ACTIVE_CONFIG_DIFF}" + + tmp_config_file=$(mktemp --tmpdir=/tmp minifirewall.XXX) + save_active_configuration "${tmp_config_file}" + + cmp_result=$(cmp "${ACTIVE_CONFIG}" "${tmp_config_file}" 2>&1) + cmp_rc=$? + + if [ ${cmp_rc} -eq 0 ]; then + # echo " config has not changed since latest start" + printf "${GREEN}OK: Active configuration is up-to-date.${RESET}\n" + rc=0 + elif [ ${cmp_rc} -eq 1 ]; then + diff -u "${ACTIVE_CONFIG}" "${tmp_config_file}" > "${ACTIVE_CONFIG_DIFF}" + + printf "${RED}CRITICAL: Active configuration is not up-to-date (minifirewall not restarted after config change?), check %s${RESET}\n" "${ACTIVE_CONFIG_DIFF}" + rc=2 + else + printf "${RED}CRITICAL: Error while comparing rules:${RESET}\n" + printf "${cmp_result}\n" + rc=2 + fi + + rm -f "${tmp_config_file}" + fi + else + printf "${YELLOW}WARNING: Skipped active configuration check (missing file ${ACTIVE_CONFIG})${RESET}\n" + rc=1 + fi + exit ${rc} +} check_unpersisted_state() { cmp_bin=$(command -v cmp) diff_bin=$(command -v diff) @@ -279,7 +364,7 @@ check_unpersisted_state() { rm -f "${STATE_FILE_DIFF}" if [ -f "${STATE_FILE_LATEST}" ]; then - cmp_result=$(cmp "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}") + cmp_result=$(cmp "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}" 2>&1) cmp_rc=$? if [ ${cmp_rc} -eq 0 ]; then @@ -320,7 +405,7 @@ report_state_changes() { # But if there is a previous known state # let's compare with the new known state if [ -f "${STATE_FILE_PREVIOUS}" ]; then - cmp_result=$(cmp "${STATE_FILE_PREVIOUS}" "${STATE_FILE_LATEST}") + cmp_result=$(cmp "${STATE_FILE_PREVIOUS}" "${STATE_FILE_LATEST}" 2>&1) cmp_rc=$? if [ ${cmp_rc} -eq 0 ]; then @@ -339,11 +424,11 @@ report_state_changes() { start() { syslog_info "starting" - printf "${BOLD}${NAME} starting${RESET}\n" + printf "${BOLD}${PROGNAME} starting${RESET}\n" # Stop and warn if error! set -e - trap 'printf "${RED}${NAME} failed : an error occured during startup.${RESET}\n"; syslog_error "failed" ' INT TERM EXIT + trap 'printf "${RED}${PROGNAME} failed : an error occured during startup.${RESET}\n"; syslog_error "failed" ' INT TERM EXIT # sysctl network security settings ################################## @@ -909,17 +994,20 @@ start() { trap - INT TERM EXIT syslog_info "started" - printf "${GREEN}${BOLD}${NAME} started${RESET}\n" + printf "${GREEN}${BOLD}${PROGNAME} started${RESET}\n" # No need to exit on error anymore set +e + # save active configuration + save_active_configuration "${ACTIVE_CONFIG}" + report_state_changes } stop() { syslog_info "stopping" - printf "${BOLD}${NAME} stopping${RESET}\n" + printf "${BOLD}${PROGNAME} stopping${RESET}\n" printf "${BLUE}flushing all rules and accepting everything${RESET}\n" @@ -1000,10 +1088,10 @@ stop() { ${IPT6} -X NEEDRESTRICT fi - rm -f "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}" + rm -f "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}" "${ACTIVE_CONFIG}" syslog_info "stopped" - printf "${GREEN}${BOLD}${NAME} stopped${RESET}\n" + printf "${GREEN}${BOLD}${PROGNAME} stopped${RESET}\n" } status() { @@ -1038,7 +1126,7 @@ status_without_numbers() { reset() { syslog_info "resetting" - printf "${BOLD}${NAME} resetting${RESET}\n" + printf "${BOLD}${PROGNAME} resetting${RESET}\n" ${IPT} -Z if is_ipv6_enabled; then @@ -1053,21 +1141,43 @@ reset() { fi syslog_info "reset" - printf "${GREEN}${BOLD}${NAME} reset${RESET}\n" + printf "${GREEN}${BOLD}${PROGNAME} reset${RESET}\n" } show_version() { cat <. +Copyright 2007-2023 Evolix . -${NAME} comes with ABSOLUTELY NO WARRANTY. +${PROGNAME} comes with ABSOLUTELY NO WARRANTY. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License. END } +show_help() { + cat <