Files
mailsystem/install_postfwd.sh
T
chrisandClaude Opus 5.5 39909a5b30 postfwd: install config from files/postfwd, idempotent /etc/default/postfwd handling
- Ship postfwd.cf and list files in files/postfwd; used by install_postfwd.sh
  and install_postfix_advanced.sh (lists only if missing, cf with backup).
- Add update_postfwd_defaults.sh.
- install_amavis.sh: disable smtpd_end_of_data_restrictions on localhost:10025.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 10:53:21 +01:00

282 lines
7.2 KiB
Bash
Executable File

#!/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> <VALUE>
## -
## - - 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]+|[ \t]+$/, "", s)
if (s ~ /^".*"$/ || s ~ /^\047.*\047$/) s = substr(s, 2, length(s) - 2)
return s
}
$0 ~ "^[ \t]*" var "=" {
cur = $0 ; sub("^[ \t]*" var "=", "", cur)
if (! done && unq(cur) == unq(val)) { print ; done = 1 ; next }
print "#" $0
if (! done) { print var "=" val ; done = 1 }
next
}
{ print }
END { if (! done) 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.<backup_date> 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