#!/usr/bin/env bash working_dir="$(dirname "$(realpath "$0")")" tmp_err_msg=$(mktemp) log_file="$tmp_err_msg" backup_date="$(date +%Y-%m-%d-%H%M)" # ------------- # --- Some functions # ------------- clean_up() { # Perform program exit housekeeping rm -f $tmp_err_msg exit $1 } echononl(){ echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n "$*\\c" 1>&2 else echo -e -n "$*" 1>&2 fi rm /tmp/shprompt$$ } fatal(){ echo "" echo -e "fatal error: $*" echo "" echo -e "\t\033[31m\033[1mInstalllation will be interrupted\033[m\033[m" echo "" exit 1 } error(){ echo "" echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*" echo "" } warn (){ echo "" echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" echo "" } info (){ echo "" echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*" echo "" } echo_done() { echo -e "\033[80G[ \033[32mdone\033[m ]" } echo_ok() { echo -e "\033[80G[ \033[32mok\033[m ]" } echo_warning() { echo -e "\033[80G[ \033[33m\033[1mwarn\033[m ]" } echo_failed(){ echo -e "\033[80G[ \033[1;31mfailed\033[m ]" } echo_skipped() { echo -e "\033[80G[ \033[33m\033[1mskipped\033[m ]" } systemd_exists=false systemd=$(which systemd) systemctl=$(which systemctl) if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_exists=true fi ## - Install Postfix Firewall Daemon from debian packages system ## - echononl " Install Postfix Firewall Daemon from debian packages system" _pkg="postfwd" if aptitude search $_pkg | grep " $_pkg " | grep -e "^i" > /dev/null 2>&1 ; then echo_skipped else DEBIAN_FRONTEND=noninteractive apt-get -y install $_pkg > /dev/null 2> $tmp_err_msg if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $tmp_err_msg)" fi fi ## - Adjust /etc/default/postfwd ## - ## - set_postfwd_default ## - ## - - VAR is set (uncommented) and has the wanted value -> nothing to do ## - - VAR is set with a different value -> comment out the current ## - setting and add the new setting directly below it ## - - VAR is not set at all -> append the new setting ## - ## - Quotes around the value are ignored when comparing ("1" == 1). ## - postfwd_default_file="/etc/default/postfwd" set_postfwd_default() { local _var="$1" local _val="$2" local _tmp_file echononl " ${_var}=${_val}" if [[ ! -f "$postfwd_default_file" ]] ; then touch "$postfwd_default_file" > "$log_file" 2>&1 || { echo_failed ; error "$(cat $log_file)" ; return 1 ; } fi _tmp_file="$(mktemp)" awk -v var="$_var" -v val="$_val" ' function unq(s) { gsub(/^[ \t\r]+|[ \t\r]+$/, "", s) if (s ~ /^".*"$/ || s ~ /^\047.*\047$/) s = substr(s, 2, length(s) - 2) return s } function is_set(s) { return s ~ ("^[ \t]*" var "=") } function is_wanted(s) { sub("^[ \t]*" var "=", "", s) return unq(s) == unq(val) } # - Read the whole file first: a line with the wanted value must stay # - untouched, no matter which other settings of VAR precede it. { line[NR] = $0 if (is_set($0) && is_wanted($0)) found = 1 } END { for (i = 1; i <= NR; i++) { if (! is_set(line[i])) { print line[i] ; continue } if (is_wanted(line[i])) { print line[i] ; continue } print "#" line[i] if (! found) { print var "=" val ; found = 1 } } if (! found) print var "=" val } ' "$postfwd_default_file" > "$_tmp_file" 2> "$log_file" if [[ $? -ne 0 ]] ; then echo_failed error "$(cat $log_file)" elif cmp -s "$_tmp_file" "$postfwd_default_file" ; then echo_skipped else # - cat instead of mv/cp keeps owner and permissions of the original file cat "$_tmp_file" > "$postfwd_default_file" 2> "$log_file" if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi rm -f "$_tmp_file" } echo "" echo " Adjust ${postfwd_default_file}" set_postfwd_default STARTUP "1" set_postfwd_default CONF "/etc/postfix/postfwd.cf" set_postfwd_default INET "127.0.0.1" set_postfwd_default PORT "10040" set_postfwd_default ARGS '"--summary=600 --cache=0"' echo "" ## - Install postfwd configuration and list files shipped with this ## - repository (directory 'files/postfwd'). ## - ## - - postfwd.cf: installed; an existing, differing file is saved ## - as postfwd.cf. first. ## - - list files (whitelists, blacklists, high-rate exceptions): ## - only installed if not yet present - existing lists contain ## - local data and are never overwritten. ## - postfwd_src_dir="${working_dir}/files/postfwd" postfwd_conf_dir="/etc/postfix" postfwd_list_files=" postfwd.wl-nets postfwd.wl-hosts postfwd.wl-user postfwd.wl-sender postfwd.bl-nets postfwd.bl-hosts postfwd.bl-user postfwd.bl-sender postfwd.bl-recipient-exeeds-msg-size-20mb postfwd.high_rate_ip postfwd.high_rate_hostname postfwd.high-rate-number-messages postfwd.high-rate-number-recipients " if [[ ! -d "$postfwd_src_dir" ]] || [[ ! -f "${postfwd_src_dir}/postfwd.cf" ]] ; then error "Directory '${postfwd_src_dir}' (or postfwd.cf in it) not found - postfwd configuration NOT installed!" else for _file in $postfwd_list_files ; do echononl " Install list file '${postfwd_conf_dir}/${_file}'" if [[ ! -f "${postfwd_src_dir}/${_file}" ]] ; then echo_failed error "Source file '${postfwd_src_dir}/${_file}' not found." elif [[ -f "${postfwd_conf_dir}/${_file}" ]] ; then echo_skipped else install -m 0644 -o root -g root "${postfwd_src_dir}/${_file}" \ "${postfwd_conf_dir}/${_file}" > "$log_file" 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi done _file="${postfwd_conf_dir}/postfwd.cf" if [[ -f "$_file" ]] && ! cmp -s "${postfwd_src_dir}/postfwd.cf" "$_file" ; then echononl " Backup existing '${_file}'" cp -a "$_file" "${_file}.${backup_date}" > "$log_file" 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi echononl " Install configuration file '${_file}'" if [[ -f "$_file" ]] && cmp -s "${postfwd_src_dir}/postfwd.cf" "$_file" ; then echo_skipped else install -m 0644 -o root -g root "${postfwd_src_dir}/postfwd.cf" "$_file" > "$log_file" 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi # - Check configuration: postfwd reports missing list files, undefined # - macros or invalid lines only as warnings and keeps running. echononl " Check postfwd configuration" _postfwd_check="$(postfwd --showconfig --file "$_file" 2>&1 \ | grep -E '^\[LOG (warning|err|crit)')" if [[ -z "$_postfwd_check" ]] ; then echo_ok else echo_warning warn "postfwd reports problems with '${_file}':\n\n${_postfwd_check}" fi fi echononl " Restart Postfix firewall daemon 'postfwd'.." if $systemd_exists ; then systemctl restart postfwd > /dev/null 2> $tmp_err_msg if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $tmp_err_msg)" fi else /etc/init.d/postfwd restart > /dev/null 2> $tmp_err_msg if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $tmp_err_msg)" fi fi warn "Postfix firewall daemin is installed, but not integrated in postfix mailsystem (/etc/postfix/main.cf)" clean_up 0