#!/usr/bin/env bash working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/install_postfix_advanced.conf" _TLS_CERT_DIR=/etc/postfix/ssl _TLS_CERT_FILE="${_TLS_CERT_DIR}/mailserver.crt" _TLS_KEY_FILE="${_TLS_CERT_DIR}/mailserver.key" _TLS_CA_FILE=/etc/ssl/certs/ca-certificates.crt postfix_conf_dir="/etc/postfix" postfix_master_cf="${postfix_conf_dir}/master.cf" postfix_spool_dir="/var/spool/postfix" postgrey_socket_dir="${postfix_spool_dir}/postgrey" postgrey_socket_file="${postgrey_socket_dir}/postgrey.sock" log_file=$(mktemp) backup_date="$(date +%Y-%m-%d-%H%M)" # ------------- # --- Some functions # ------------- clean_up() { # Perform program exit housekeeping rm -f $log_file 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 "" clean_up 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 ]" } detect_os_1 () { if $(which lsb_release > /dev/null 2>&1) ; then os_dist="$(lsb_release -i | awk '{print tolower($3)}')" os_version="$(lsb_release -r | awk '{print tolower($2)}')" os_codename="$(lsb_release -c | awk '{print tolower($2)}')" if [[ "$os_dist" = "debian" ]]; then if $(echo "$os_version" | grep -q '\.') ; then os_version=$(echo "$os_version" | cut --delimiter='.' -f1) fi fi elif [[ -e "/etc/os-release" ]]; then . /etc/os-release os_dist=$ID os_version=${VERSION_ID} fi # remove whitespace from os_dist and os_version os_dist="${os_dist// /}" os_version="${os_version// /}" } trap clean_up SIGHUP SIGINT SIGTERM # ------------- # --- Some default settings # ------------- # - Default Values # - DEFAULT_ADMIN_EMAIL="argus@oopen.de" DEFAULT_IS_RELAY_HOST=false DEFAULT_ADDITIONAL_RELAY_PORT=2525 DEFAULT_IS_SYMPA_LIST_SERVER=no DEFAULT_SASL_AUTH_ENABLED=no DEFAULT_LISTEN_ON_ADDITIONAL_RELAY_PORT=false # - Is this a systemd system? # - if [[ "X`which systemd`" = "X" ]]; then systemd_exists=false else systemd_exists=true fi # - Detect OS - Set variable # - os_dist # - os_version # - os_codename # - detect_os_1 # - Read Configuration File if exists # - if [[ -f "$conf_file" ]]; then source $conf_file fi [[ -z "$_ADMIN_EMAIL" ]] && _ADMIN_EMAIL="$DEFAULT_ADMIN_EMAIL" [[ -z "$_SASL_AUTH_ENABLED" ]] && _SASL_AUTH_ENABLED="$DEFAULT_SASL_AUTH_ENABLED" if [[ -z "$_SYMPA_LIST_SERVER" ]] ; then _IS_SYMPA_LIST_SERVER=false else _IS_SYMPA_LIST_SERVER="$_SYMPA_LIST_SERVER" fi if [[ -z "$_RELAY_HOST" ]]; then _IS_RELAY_HOST=$DEFAULT_IS_RELAY_HOST else _IS_RELAY_HOST="$_RELAY_HOST" fi if [[ -z "$_LISTEN_ON_ADDITIONAL_RELAY_PORT" ]] ; then _LISTEN_ON_ADDITIONAL_RELAY_PORT=${DEFAULT_LISTEN_ON_ADDITIONAL_RELAY_PORT} fi echo "" echo "" echo "" echo "" echo "" # ------------- # --- Set default values for some non existent variables (i.e. no configuration file is present) # ------------- if [[ -z "$_HOSTNAME" ]] ; then _HOSTNAME="$(hostname -f)" _HOSTNAME_SHORT="$(hostname)" [[ "$_HOSTNAME" = "$_HOSTNAME_SHORT" ]] && _HOSTNAME="" fi clear echo -e "\033[21G\033[32mInstallation script for Postfix basic mailsystem \033[m" echo HOSTNAME= echo "" echo -e "\033[32m--\033[m" echo "" echo "Insert hostname" echo "" if [[ -n "$_HOSTNAME" ]]; then echononl "hostname [${_HOSTNAME}]: " read HOSTNAME if [[ "X${HOSTNAME}" = "X" ]]; then HOSTNAME=$_HOSTNAME fi else while [[ "X${HOSTNAME}" = "X" ]]; do echononl "hostname: " read HOSTNAME if [[ "X${HOSTNAME}" = "X" ]]; then echo -e "\n\t\033[33m\033[1mHostname is reqired\033[m\n" fi done fi # ------------- # --- Some further default values depending on Hostname # ------------- # - Set default values for ipv4- and ipv6-address # - if [[ -z $_IPV4 ]] && [[ -n "$_HOSTNAME" ]] && [[ -x "$(which dig)" ]]; then _IPV4="$(dig +short "$_HOSTNAME" A)" fi if [[ -z $_IPV6 ]] && [[ -n "$_HOSTNAME" ]] && [[ -x "$(which dig)" ]]; then _IPV6="$(dig +short "$_HOSTNAME" AAAA)" fi IPV4= echo "" echo -e "\033[32m--\033[m" echo "" echo "Insert IPv4 address" echo "" if [[ -n "$_IPV4" ]]; then echononl "IPv4 address [${_IPV4}]: " read IPV4 if [[ "X${IPV4}" = "X" ]]; then IPV4=$_IPV4 fi else while [[ "X${IPV4}" = "X" ]]; do echononl "IPv4 address: " read IPV4 if [[ "X${IPV4}" = "X" ]]; then echo -e "\n\t\033[33m\033[1mIPv4 address is reqired\033[m\n" fi done fi IPV6= echo "" echo -e "\033[32m--\033[m" echo "" echo "Insert IPv6 address" echo "Type:" echo -e "\t\033[33mNone\033[m if IPv6 is not suppoerted" echo "" if [[ -n "$_IPV6" ]]; then [[ "X$_IPV6" = "Xdisabled" ]] && _IPV6=None echononl "IPv6 address [${_IPV6}]: " read IPV6 if [[ "X${IPV6}" = "X" ]]; then IPV6=$_IPV6 fi else while [[ "X${IPV6}" = "X" ]]; do echononl "IPv6 address: " read IPV6 if [[ "X${IPV6}" = "X" ]]; then echo -e "\n\t\033[33m\033[1mIPv4 address is reqired\033[m\n" fi done fi if [ "X$IPV6" = "Xnone" -o "X$IPV6" = "XNone" ]; then IPV6=disabled fi IS_RELAY_HOST= echo "" echo -e "\033[32m--\033[m" echo "" echo "How will this Mailserver be used?" echo "" if [[ -n "$_IS_RELAY_HOST" ]]; then if $_IS_RELAY_HOST ; then echo "[1] Complete Mailserver (with mailboxes)" echo -e "\033[37m\033[1m[2] Mailrelay Host\033[m" else echo -e "\033[37m\033[1m[1] complete Mailserver (with mailboxes)\033[m" echo "[2] Mailrelay Host" fi echo "" echononl "Choose a number or press for highlighted value: " else echo "[1] Complete Mailserver (with mailboxes)" echo "[2] Mailrelay Host" echo "" echononl "Choose a Number: " fi while [[ "$IS_RELAY_HOST" != "true" && "$IS_RELAY_HOST" != "false" ]];do read OPTION case $OPTION in 1) IS_RELAY_HOST=false ;; 2) IS_RELAY_HOST=true ;; '') if [[ -n "$_IS_RELAY_HOST" ]] ; then IS_RELAY_HOST=$_IS_RELAY_HOST else echo "" echo -e "\tWrong entry! [ 1 = Complete Mailserver ; 2 = Mailrelay Host]" echo "" echononl "Reentry: " fi ;; *) IS_RELAY_HOST= echo "" if [[ -n "$_IS_RELAY_HOST" ]]; then echo -e "\tWrong entry! [ 1 = Complete Mailserver ; 2 = Mailrelay Host] or type " else echo -e "\tWrong entry! [ 1 = Complete Mailserver ; 2 = Mailrelay Host]" fi echo "" echononl "Reentry: " ;; esac done if $IS_RELAY_HOST ; then IS_SYMPA_LIST_SERVER="" echo "" echo -e "\033[32m--\033[m" echo "" echo "Are Sympa List Services provided? - [yes/no]" echo "" echononl "Sympa List Server? [$_IS_SYMPA_LIST_SERVER]: " read IS_SYMPA_LIST_SERVER if [[ -z "${IS_SYMPA_LIST_SERVER}" ]] ; then IS_SYMPA_LIST_SERVER="$_IS_SYMPA_LIST_SERVER" fi IS_SYMPA_LIST_SERVER=${IS_SYMPA_LIST_SERVER,,} while [[ "$IS_SYMPA_LIST_SERVER" != "yes" && "$IS_SYMPA_LIST_SERVER" != "true" \ && "$IS_SYMPA_LIST_SERVER" != "no" && "$IS_SYMPA_LIST_SERVER" != "false" ]]; do echo -e "\n\t\033[33m\033[1mWrong value was given!!\033[m\n" echononl "Sympa List Server? [$_IS_SYMPA_LIST_SERVER]: " read IS_SYMPA_LIST_SERVER if [[ -z "${IS_SYMPA_LIST_SERVER}" ]] ; then IS_SYMPA_LIST_SERVER=false fi IS_SYMPA_LIST_SERVER=${IS_SYMPA_LIST_SERVER,,} done if [[ "$IS_SYMPA_LIST_SERVER" = 'yes' || "$IS_SYMPA_LIST_SERVER" = 'true' ]] ; then IS_SYMPA_LIST_SERVER=true SASL_AUTH_ENABLED=no else IS_SYMPA_LIST_SERVER=false fi if [[ -z "$SASL_AUTH_ENABLED" ]]; then echo "" echo -e "\033[32m--\033[m" echo "" echo "Should this mail relay server support Cyrus SASL authentication?" echo "" while [[ "$SASL_AUTH_ENABLED" != "yes" && "$SASL_AUTH_ENABLED" != "no" ]];do if [[ -n "$_SASL_AUTH_ENABLED" ]]; then echononl "Support Cyrus SASL authentication [${_SASL_AUTH_ENABLED}]: " read SASL_AUTH_ENABLED SASL_AUTH_ENABLED=${SASL_AUTH_ENABLED,,} [[ -z "$SASL_AUTH_ENABLED" ]] && SASL_AUTH_ENABLED="$_SASL_AUTH_ENABLED" else echononl "Support Cyrus SASL authentication [yes/no]: " read SASL_AUTH_ENABLED SASL_AUTH_ENABLED=${SASL_AUTH_ENABLED,,} fi if [[ "$SASL_AUTH_ENABLED" != "yes" && "$SASL_AUTH_ENABLED" != "no" ]] ; then _SASL_AUTH_ENABLED="" echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n Type 'yes' or 'no'" fi done fi ADDITIONAL_RELAY_LISTEN_PORT= echo "" echo -e "\033[32m--\033[m" echo "" echo "Should this mail relay server listen on an additional port?" echo "" if [[ -n "$_ADDITIONAL_RELAY_LISTEN_PORT" ]]; then echo "Type:" echo -e "\t\033[33mNone\033[m for no additional listen port." else echo "Type:" echo -e "\t\033[33mNone\033[m or lrave empty for no additional listen port." fi echo "" if [[ -n "$_ADDITIONAL_RELAY_LISTEN_PORT" ]]; then echononl "additional listen port [${_ADDITIONAL_RELAY_LISTEN_PORT}]: " read ADDITIONAL_RELAY_LISTEN_PORT if [[ "X${ADDITIONAL_RELAY_LISTEN_PORT}" = "X" ]]; then ADDITIONAL_RELAY_LISTEN_PORT=$_ADDITIONAL_RELAY_LISTEN_PORT LISTEN_ON_ADDITIONAL_RELAY_PORT=true fi if [[ "${ADDITIONAL_RELAY_LISTEN_PORT,,}" = "none" ]] ; then ADDITIONAL_RELAY_LISTEN_PORT="" LISTEN_ON_ADDITIONAL_RELAY_PORT=false fi else echononl "additional listen port: " read ADDITIONAL_RELAY_LISTEN_PORT if [[ "X${ADDITIONAL_RELAY_LISTEN_PORT}" = "X" ]] || [[ "${ADDITIONAL_RELAY_LISTEN_PORT,,}" = "none" ]]; then ADDITIONAL_RELAY_LISTEN_PORT="" LISTEN_ON_ADDITIONAL_RELAY_PORT=false else LISTEN_ON_ADDITIONAL_RELAY_PORT=true fi fi else IS_SYMPA_LIST_SERVER=false fi ADMIN_EMAIL= echo "" echo "" echo -e "\033[32m--\033[m" echo "" echo "Insert e-mail address where messages to local root should be forwarded" echo "" echo "" if [[ -n "$_ADMIN_EMAIL" ]]; then echononl "Admin e-mail address [$_ADMIN_EMAIL]: " read ADMIN_EMAIL if [[ "X${ADMIN_EMAIL}" = "X" ]]; then ADMIN_EMAIL=$_ADMIN_EMAIL fi else while [[ "X${ADMIN_EMAIL}" = "X" ]]; do echononl "Admin e-mail address: " read ADMIN_EMAIL if [[ "X${ADMIN_EMAIL}" = "X" ]]; then echo -e "\n\t\033[33m\033[1mAdmin e-mail address is reqired\033[m\n" fi done fi echo "" echo "" echo -e "\033[21G\033[32mStart installation/configuration with the following parameters\033[m" echo "" echo -e "\tHostname..........................: $HOSTNAME" echo -e "\tIPv4 address......................: $IPV4" echo -e "\tIPv6 address......................: $IPV6" echo -e "\tAdmin e-mail......................: $ADMIN_EMAIL" echo "" if $IS_RELAY_HOST ; then echo -e "\tConfigure as relay host?..........: \033[33m\033[1m$IS_RELAY_HOST\033[m" echo -e "\tConfigure as complete mailserver..: false" echo "" echo -e "\tConfigure as sympa list server?...: \033[33m\033[1m$IS_SYMPA_LIST_SERVER\033[m" echo "" echo -e "\tSupport Cyrus SASL authentication.: $SASL_AUTH_ENABLED" echo "" echo -e "\tListen on an additional port?.......: \033[33m\033[1m${LISTEN_ON_ADDITIONAL_RELAY_PORT}\033[m" if ${LISTEN_ON_ADDITIONAL_RELAY_PORT}; then echo -e "\tAdditional Listen Port..............: ${ADDITIONAL_RELAY_LISTEN_PORT}" fi else echo -e "\tConfigure as relay host?..........: $IS_RELAY_HOST" echo -e "\tConfigure as complete mailserver..: \033[33m\033[1mtrue\033[m" fi echo "" echononl "einverstanden (yes/no): " read OK OK=${OK,,} while [ "X$OK" != "Xyes" -a "X$OK" != "Xno" ]; do echononl "Wrong entry! [yes/no]: " read OK OK=${OK,,} done [ $OK = "yes" ] || fatal Repeat with other settings.. echo "" echo "" _failed=false echononl " Save Configuration" cat << EOF > $conf_file # --- # - Parameter Settings Postfix Relay System # --- _HOSTNAME=$HOSTNAME _IPV4=$IPV4 _IPV6=$IPV6 _ADMIN_EMAIL=$ADMIN_EMAIL _RELAY_HOST=$IS_RELAY_HOST EOF if [[ $? -ne 0 ]]; then _failed=true fi if $IS_RELAY_HOST ; then cat << EOF >> $conf_file _SASL_AUTH_ENABLED=$SASL_AUTH_ENABLED _SYMPA_LIST_SERVER=$IS_SYMPA_LIST_SERVER _LISTEN_ON_ADDITIONAL_RELAY_PORT=${LISTEN_ON_ADDITIONAL_RELAY_PORT} EOF if ${LISTEN_ON_ADDITIONAL_RELAY_PORT} : then cat << EOF >> $conf_file _ADDITIONAL_RELAY_LISTEN_PORT=${ADDITIONAL_RELAY_LISTEN_PORT} EOF fi fi if [[ $? -ne 0 ]]; then _failed=true fi if $_failed ; then echo_failed else echo_ok fi [[ "$IPV6" = "disabled" ]] && IPV6="" # - Synchronise package index files with the repository # - echononl " Synchronise package index files with the repository.." apt-get update > "$log_file" 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi # - Deinstall debian exim4 packages # - echononl " Deinstall debian exim4 packages" _installed_exim_packages=`dpkg -l | grep exim4 | grep -e "^i" | awk '{print$2}'` for _pkg in $_installed_exim_packages ; do installed_exim_packages="$installed_exim_packages $_pkg" done if [[ -n "$installed_exim_packages" ]] ; then if `dpkg -l | grep bsd-mailx | grep -e "^i" > /dev/null 2>&1` ; then installed_exim_packages="$installed_exim_packages bsd-mailx" fi apt-get remove --purge -qq -y $installed_exim_packages > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi # - Install Postfix from debian packages system # - echononl " Install Postfix from debian packages system" _needed_packages="postfix postfix-pgsql postfix-mysql postfix-pcre libsasl2-modules bsd-mailx haveged" if [[ "$SASL_AUTH_ENABLED" = "yes" ]]; then _needed_packages="$_needed_packages sasl2-bin" fi for _pkg in $_needed_packages ; do if `dpkg -l | grep $_pkg | grep -e "^i" > /dev/null 2>&1` ; then continue else needed_packages="$needed_packages $_pkg" fi done if [[ -n "$needed_packages" ]]; then DEBIAN_FRONTEND=noninteractive apt-get -y install $needed_packages > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi if [[ "$os_dist" = "debian" ]] && [[ $os_version -ne 10 ]] ; then ## - Install Postgrey from debian packages system ## - echononl " Install Postgrey from debian packages system" _pkg="postgrey" 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> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi echononl " Adjust /etc/default/postgrey" # postgrey as tcp/ip socket # #perl -i -n -p -e "s#^(\s*)(POSTGREY_OPTS=.*)#\#\1\2\nPOSTGREY_OPTS=\"--inet=127.0.0.1:10023 --delay=149 --auto-whitelist-clients=3 --lookup-by-subnet\"#" \ # /etc/default/postgrey > $log_file 2>&1 # postgrey as unix socket # perl -i -n -p -e "s#^(\s*)(POSTGREY_OPTS=.*)#\#\1\2\nPOSTGREY_OPTS=\"--unix=/var/spool/postfix/postgrey/postgrey.sock --delay=149 --auto-whitelist-clients=3 --lookup-by-subnet\"#" \ /etc/default/postgrey > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi echononl " Create /etc/postgrey/whitelist_clients.local (additional whitelist entries)" cat << EOF > /etc/postgrey/whitelist_clients.local # For Office 365 - servers: ##/.*outbound.protection.outlook.com\$/ /^mail-.*\\.outbound\\.protection\\.outlook\\.com\$/ # facebookmail.com - big pool /.*\\.mail-mail\\.facebook\\.com\$/ # tor hidde service 127.0.0.25 EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create the Postgrey socket directory in Postfix's work aerea.." if [[ -d "${postgrey_socket_dir}" ]]; then echo_skipped else mkdir "${postgrey_socket_dir}" > /dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" echononl "\tcontinue anyway [yes/no]: " read OK OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do echononl "Wrong entry! - repeat [yes/nno]: " read OK done [[ $OK = "yes" ]] || fatal "Abbruch durch User" fi fi echononl " Set ownership on directory '${postgrey_socket_dir}'.." chown -R postgrey:postgrey ${postgrey_socket_dir} 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" echononl "\tcontinue anyway [yes/no]: " read OK OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do echononl "Wrong entry! - repeat [yes/nno]: " read OK done [[ $OK = "yes" ]] || fatal "Abbruch durch User" fi echononl " Enable Postgrey service at boot time.." if $systemd_exists ; then systemctl enable networking >/dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped warn "Skipped this step because systemd service was not found." fi echononl " Restart postrey daemon" if $systemd_exists ; then systemctl restart postgrey > /dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else /etc/init.d/postgrey restart > /dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi postgrey_socket="postgrey/postgrey.sock" #postgrey_additional_options="postgrey_time_limit = 3600" postgrey_additional_options="" else ## - Install tumgreyspf from debian packages system echononl " Install tumgreyspf from debian packages system" _pkg="tumgreyspf" 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> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi echononl " Add entry for 'tumgreyspf' at end of file '$postfix_master_cf" if ! $(grep -iq -E "^\s*tumgreyspf\s+" 2>/dev/null $postfix_master_cf) ; then cat <> $postfix_master_cf 2> $log_file # This is tumgreyspf, an external policy checker for the postfix mail server. # It can optionally greylist and/or use spfquery to check SPF records to # determine if email should be accepted by your server. # tumgreyspf unix - n n - - spawn user=tumgreyspf argv=/usr/bin/tumgreyspf EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi echononl " Create configuration file for whitelisting: /etc/tumgreyspf/disable.conf" if [[ ! -f /etc/tumgreyspf/disable.conf ]] ; then cat < "/etc/tumgreyspf/disable.conf" 2> $log_file SPFSEEDONLY=0 GREYLISTTIME=300 CHECKERS= OTHERCONFIGS= EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi _failed=false echononl " Whitelist tor hidde service '127.0.0.25'.." if [[ ! -d "/var/lib/tumgreyspf/config/client_address/127/0/0/" ]] ; then mkdir -p /var/lib/tumgreyspf/config/client_address/127/0/0/ 2> $log_file if [[ $? -ne 0 ]]; then _failed=true fi fi if [[ ! -L /var/lib/tumgreyspf/config/client_address/127/0/0/25 ]]; then ln -s /etc/tumgreyspf/disable.conf /var/lib/tumgreyspf/config/client_address/127/0/0/25 2>> $log_file fi if [[ $? -ne 0 ]]; then _failed=true fi if $_failed ; then echo_failed error "$(cat $log_file)" else echo_ok fi # --- # Configure parameters of tumgreyspf service # --- _setup_key="SPFSEEDONLY" _setup_val="0" _setup_file="/etc/tumgreyspf/default.conf" echononl " Setup defaults for tumgreyspf: $_setup_key .." if ! $(grep -iq -E "^\s*${_setup_key}\s*=" "$_setup_file") ; then cat <> "$_setup_file" 2> $log_file # Added by script $(basename $0) at $(date +%Y-%m-%d) $_setup_key = $_setup_val EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else if ! $(grep -iq -E "^\s*${_setup_key}\s*=\s*0$" "$_setup_file") ; then perl -i -n -p -e "s/(\s*${_setup_key}.*)/#\1\n${_setup_key} = $_setup_val/" "$_setup_file" 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi fi _setup_key="GREYLISTTIME" _setup_val="180" _setup_file="/etc/tumgreyspf/default.conf" echononl " Setup defaults for tumgreyspf: $_setup_key .." if ! $(grep -iq -E "^\s*${_setup_key}\s*=" "$_setup_file") ; then cat <> "$_setup_file" 2> $log_file # Added by script $(basename $0) at $(date +%Y-%m-%d) $_setup_key = $_setup_val EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else if ! $(grep -iq -E "^\s*${_setup_key}\s*=\s*${_setup_val/}$" "$_setup_file") ; then perl -i -n -p -e "s/(\s*${_setup_key}.*)/#\1\n${_setup_key} = $_setup_val/" "$_setup_file" 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi fi _setup_key="CHECKERS" _setup_val="spf,greylist" _setup_file="/etc/tumgreyspf/default.conf" echononl " Setup defaults for tumgreyspf: $_setup_key .." if ! $(grep -iq -E "^\s*${_setup_key}\s*=" "$_setup_file") ; then cat <> "$_setup_file" 2> $log_file # Added by script $(basename $0) at $(date +%Y-%m-%d) $_setup_key = $_setup_val EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else if ! $(grep -iq -E "^\s*${_setup_key}\s*=\s*${_setup_val/}$" "$_setup_file") ; then perl -i -n -p -e "s/(\s*${_setup_key}.*)/#\1\n${_setup_key} = $_setup_val/" "$_setup_file" 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi fi _setup_key="OTHERCONFIGS" _setup_val="client_address,envelope_sender,envelope_recipient" _setup_file="/etc/tumgreyspf/default.conf" echononl " Setup defaults for tumgreyspf: $_setup_key .." if ! $(grep -iq -E "^\s*${_setup_key}\s*=" "$_setup_file") ; then cat <> "$_setup_file" 2> $log_file # Added by script $(basename $0) at $(date +%Y-%m-%d) $_setup_key = $_setup_val EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else if ! $(grep -iq -E "^\s*${_setup_key}\s*=\s*${_setup_val/}$" "$_setup_file") ; then perl -i -n -p -e "s/(\s*${_setup_key}.*)/#\1\n${_setup_key} = $_setup_val/" "$_setup_file" 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi fi _setup_key="GREYLISTEXPIREDAYS" _setup_val="10.0" _setup_file="/etc/tumgreyspf/default.conf" echononl " Setup defaults for tumgreyspf: $_setup_key .." if ! $(grep -iq -E "^\s*${_setup_key}\s*=" "$_setup_file") ; then cat <> "$_setup_file" 2> $log_file # Added by script $(basename $0) at $(date +%Y-%m-%d) $_setup_key = $_setup_val EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else if ! $(grep -iq -E "^\s*${_setup_key}\s*=\s*${_setup_val/}$" "$_setup_file") ; then perl -i -n -p -e "s/(\s*${_setup_key}.*)/#\1\n${_setup_key} = $_setup_val/" "$_setup_file" 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi fi postgrey_socket="unix:private/tumgreyspf" postgrey_additional_options="tumgreyspf_time_limit = 3600" fi # - Install SPF-Policy-Tools # - echononl " Install Postfix SPF-Policy-Tools 'postfix-policyd-spf-python'" _pkg=postfix-policyd-spf-python 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> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi # - Backup existing configuration file for policyd-spf daemon # - _file="/etc/postfix-policyd-spf-python/policyd-spf.conf" echononl " Backup configuration file '${_file}'." if [[ -f "${_file}" ]]; then cp -a "${_file}" "${_file}.${backup_date}" > /dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi echononl " Creeate new configuration '${_file}'.." cat < "${_file}" # For a fully commented sample config file see policyd-spf.conf.commented # Reject and deferred reason Reason_Message = Message {rejectdefer} due to: {spf}. # Amount of debugging information logged. 0 logs no debugging messages # 5 includes all debug messages. debugLevel = 1 # HELO check rejection policy. Options are: # HELO_reject = SPF_Not_Pass (default) - Reject if result not Pass/None/Tempfail. # HELO_reject = Softfail - Reject if result Softfail and Fail # HELO_reject = Fail - Reject on HELO Fail # HELO_reject = Null - Only reject HELO Fail for Null sender (SPF Classic) # HELO_reject = False - Never reject/defer on HELO, append header only. # HELO_reject = No_Check - Never check HELO. HELO_reject = SPF_Not_Pass # Mail From rejection policy. Options are: # Mail_From_reject = SPF_Not_Pass - Reject if result not Pass/None/Tempfail. # Mail_From_reject = Softfail - Reject if result Softfail and Fail # Mail_From_reject = Fail - Reject on Mail From Fail (default) # Mail_From_reject = False - Never reject/defer on Mail From, append header only # Mail_From_reject = No_Check - Never check Mail From/Return Path. # # Dieser Parameter steuert, wie der SPF-Check auf Fehler bei der Überprüfung der # MAIL FROM-Adresse reagiert. Ein Fehler tritt auf, wenn die IP-Adresse des sendenden # Servers nicht den SPF-Einträgen der Domain in der MAIL FROM-Adresse entspricht. # Mail_From_reject = Fail # Policy for rejecting due to SPF PermError. Options are: # PermError_reject = True # PermError_reject = False # # Wirkung: Dieser Parameter bestimmt, wie der SPF-Check auf permanente Fehler (PermError) # reagiert. Ein permanenter Fehler tritt auf, wenn die SPF-DNS-Einträge ungültig oder # fehlerhaft sind (z. B. syntaktische Fehler oder ungültige Mechanismen). # # Wenn PermError_reject auf True gesetzt ist, wird die E-Mail abgewiesen (rejected), # PermError_reject = True # Policy for deferring messages due to SPF TempError. Options are: # TempError_Defer = True # TempError_Defer = False # # Wirkung: Dieser Parameter bestimmt das Verhalten bei temporären SPF-Fehlern (TempError). # Ein temporärer Fehler tritt auf, wenn der SPF-Check aufgrund von vorübergehenden # Problemen (z. B. DNS-Auflösungsfehler oder Netzwerkprobleme) nicht durchgeführt werden kann. # # Wenn TempError_Defer auf True gesetzt ist, wird die E-Mail vorübergehend zurückgewiesen # (deferred), und der empfangende Server versucht später erneut, die E-Mail zuzustelle # TempError_Defer = Defer # Type of header to insert to document SPF result. Can be Received-SPF (SPF) # or Authentication Results (AR). It cannot be both. # Examples: (default is Received-SPF): # Header_Type = AR # Header_Type = SPF Header_Type = SPF # Do not check SPF for localhost addresses - add to skip addresses to # skip SPF for internal networks if desired. Defaults are standard IPv4 and # IPv6 localhost addresses. skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1 EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed 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> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi echononl " Adjust /etc/default/postfwd" perl -i -n -p -e "s#^(\s*)(STARTUP=.*)#\#\1\2\nSTARTUP=1#" \ /etc/default/postfwd > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi _file="/etc/postfix/postfwd.wl-nets" echononl " Create whitelist file '$_file' for postfwd" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # Trusted networks whitelisted by postfwd # # Example: # # # web0.warenform.de # #83.223.86.76 # #2a01:30:0:505:286:96ff:fe4a:6ee # #2a01:30:0:13:286:96ff:fe4a:6eee # # --- # give truested networrk adresses here EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/postfwd.wl-hosts" echononl " Create whitelist file '$_file' for postfwd" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # Trusted hosts whitelisted by postfwd # # This file is called with '=~'. This means perl regexp is possible # # Example: # # # all hosts of domain 'oopen.de' # \.oopen\.de$ # # # host a.mx.oopen.de # a.mx.oopen.de # # --- # give truested hostnames here EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/postfwd.wl-user" echononl " Create whitelist file '$_file' for postfwd" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # SASL Users whitelisted by postfwd # --- EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/postfwd.wl-sender" echononl " Create whitelist file '$_file' for postfwd" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # Trusted senders whitelisted by postfwd # # This file is called with '=~'. This means perl regexp is possible # # Example: # # # all senders of maildomaindomain 'oopen.de' # @oopen\.de$ # # # sender address ckubu@oopen.de # ckubu@oopen.de # # --- # give trusted sender addresses here EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/postfwd.bl-nets" echononl " Create whitelist file '$_file' for postfwd" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # Networks blocked by postfwd # # Example: # # # web0.warenform.de # #83.223.86.76 # #2a01:30:0:505:286:96ff:fe4a:6ee # #2a01:30:0:13:286:96ff:fe4a:6eee # # --- # give networks to block here EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/postfwd.bl-hosts" echononl " Create whitelist file '$_file' for postfwd" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # hosts blocked by postfwd # # This file is called with '=~'. This means perl regexp is possible # # Example: # # # block all hosts of domain 'oopen.de' # \.oopen\.de$ # # # block host a.mx.oopen.de # a.mx.oopen.de # # --- # give hostnames to blocke here EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/postfwd.bl-user" echononl " Create whitelist file '$_file' for postfwd" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # SASL Users blocked by postfwd # --- EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/postfwd.bl-sender" echononl " Create whitelist file '$_file' for postfwd" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # Sender addresses blocked by postfwd # --- # annoying spammer domains @acieu.co.uk # annoying spammer addresses error@mailfrom.com EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/postfwd.bl-sender" echononl " Create whitelist file '$_file' for postfwd" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # Sender addresses blocked by postfwd # # This file is called with '=~'. This means perl regexp is possible # # Example: # # # all senders of maildomaindomain 'oopen.de' # @oopen\.de$ # # # sender address ckubu@oopen.de # ckubu@oopen.de # # --- # annoying spammer domains @acieu.co.uk # annoying spammer addresses error@mailfrom.com EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi echononl " Create configuration file '/etc/postfix/postfwd.cf'.." if [[ ! -f "/etc/postfix/postfwd.cf" ]]; then cat << EOF > /etc/postfix/postfwd.cf #======= Definitions ============ # Match messages with an associated SASL username &&SASL_AUTH { sasl_username!~^\$ } # Trusted networks &&TRUSTED_NETS { client_address==file:/etc/postfix/postfwd.wl-nets } # Trusted hostnames # client_name~=.warenform.de$ &&TRUSTED_HOSTS { client_name=~file:/etc/postfix/postfwd.wl-hosts } # Trusted users &&TRUSTED_USERS { sasl_username==file:/etc/postfix/postfwd.wl-user } # Trusted senders &&TRUSTED_SENDERS { sender=~file:/etc/postfix/postfwd.wl-sender } # Blacklist networks &&BLOCK_NETS { client_address==file:/etc/postfix/postfwd.bl-nets } # Blacklist hostnames &&BLOCK_HOSTS { client_name=~file:/etc/postfix/postfwd.bl-hosts } # Blacklist users &&BLOCK_USERS { sasl_username==file:/etc/postfix/postfwd.bl-user } # Blacklist sender adresses &&BLOCK_SENDER { # =~ # using '=~' allows also matching entries for domains (i.e. @acieu.co.uk) sender=~file:/etc/postfix/postfwd.bl-sender } # Inbound emails only &&INCOMING { client_address!=127.0.0.1 } #======= Rule Sets ============ # --- # # Processing of the Rule Sets # # The parser checks the elements of a policy delegation request against the postfwd set # of rules and, if necessary, triggers the configured action (action=). Similar to a # classic firewall, a rule is considered true if every element of the set of rules (or # one from every element list) applies to the comparison. I.e. the following rule: # # client_address=1.1.1.1, 1.1.1.2; client_name==unknown; action=REJECT # # triggers a REJECT if the # # Client address is equal (1.1.1.1 OR 1.1.1.2) AND the client name 'unknown' # # # Note: # If an element occurs more than once, an element list is formed: # # The following rule set is equivalent to the above: # # client_address=1.1.1.1; client_address=1.1.1.2; client_name==unknown; action=REJECT # # # triggers a REJECT if (as above) the # # Client address (1.1.1.1 OR 1.1.1.2) AND the client name 'unknown' # # --- # Whitelists # Whitelist trusted networks id=WHL_NETS &&TRUSTED_NETS action=DUNNO # Whitelist trusted hostnames id=WHL_HOSTS &&TRUSTED_HOSTS action=DUNNO # Whitelist sasl users id=WHL_USERS &&TRUSTED_USERS action=DUNNO # Whitelist senders id=WHL_SENDERS &&INCOMING &&TRUSTED_SENDERS action=DUNNO # Blacklists # Block networks id=BL_NETS &&BLOCK_NETS action=REJECT Network Address \$\$client_address blocked by Mailserver admins. Error: BL_NETS # Block hostname id=BL_HOSTS &&BLOCK_HOSTS action=REJECT \$\$client_name blocked by Mailserver admins. Error: BL_HOSTS # Block users id=BL_USERS &&BLOCK_USERS action=REJECT User is blocked by Mailserver admins. Error: BL_USERS # Blacklist sender # # Claim successful delivery and silently discard the message. # id=BL_SENDER &&BLOCK_SENDER #action=DISCARD action=REJECT Sender address is blocked by Mailserver admins. Error: BL_SENDER # Rate Limits # Throttle unknown clients to 5 recipients per 5 minutes: id=RATE_UNKNOWN_CLIENT_ADDR sasl_username =~ /^$/ client_name==unknown action=rate(client_address/5/300/450 4.7.1 only 5 recipients per 5 minutes allowed) # Block clients (ip-addresses) sending more than 50 messages per minute exceeded. Error:RATE_CLIENT) id=RATE_CLIENT_ADDR &&INCOMING action=rate(\$\$client_address/50/60/421 421 4.7.0 Too many connections from \$\$client_address) # Block messages with more than 50 recipients id=BLOCK_MSG_RCPT &&INCOMING &&SASL_AUTH recipient_count=50 action=REJECT Too many recipients, please reduce to less than 50 or consider using a mailing list. Error: BLOCK_MSG_RCPT # Block users sending more than 50 messages/hour id=RATE_MSG &&INCOMING &&SASL_AUTH action=rate(\$\$sasl_username/50/3600/450 4.7.1 Number messages per hour exceeded. Error:RATE_MSG) # Block users sending more than 250 recipients total/hour id=RATE_RCPT &&INCOMING &&SASL_AUTH action=rcpt(\$\$sasl_username/250/3600/450 4.7.1 Number recipients per hour exceeded. Error:RATE_RCPT) EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi echononl " Enable Postfix firewall daemon at boot time .." if $systemd_exists ; then systemctl enable postfwd > /dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else update-rc.d postfwd defaults > /dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi echononl " Restart Postfix firewall daemon 'postfwd'.." if $systemd_exists ; then systemctl restart postfwd > /dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else /etc/init.d/postfwd restart > /dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi # - Backup existing postfix configuration file # - echononl " Backup existing postfix configuration file" if [[ -f "/etc/postfix/main.cf" ]]; then cp -a /etc/postfix/main.cf /etc/postfix/main.cf.$backup_date if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi # - Creeate new postfix configuration file # - echononl " Creeate new postfix configuration file" cat < /etc/postfix/main.cf # ============ Basic settings ============ # Disable backwards compatibility compatibility_level = 2 # With "smtputf8_enable = yes", Postfix requires that non-ASCII address information # is encoded in UTF-8 and will reject other encodings such as ISO-8859. It is not # practical for Postfix to support multiple encodings at the same time. There is no # problem with RFC 2047 encodings such as "=?ISO-8859-1?Q?text?=", because those use # only characters from the ASCII characterset. #smtputf8_enable = no EOF if $IS_SYMPA_LIST_SERVER ; then cat <> /etc/postfix/main.cf smtputf8_enable = no EOF fi cat <> /etc/postfix/main.cf # Debian specific: Specifying a file name will cause the first # line of that file to be used as the name. The Debian default # is /etc/mailname. #myorigin = /etc/mailname myorigin = /etc/mailname smtpd_banner = \$myhostname ESMTP \$mail_name (Debian/GNU) biff = no # appending .domain is the MUA's job. append_dot_mydomain = no # Uncomment the next line to generate "delayed mail" warnings #delay_warning_time = 4h readme_directory = /usr/share/doc/postfix html_directory = /usr/share/doc/postfix/html ## - The Internet protocols Postfix will attempt to use when making ## - or accepting connections. ## - DEFAULT: ipv4 EOF if [ -n "$IPV6" ]; then cat <> /etc/postfix/main.cf inet_protocols = ipv4, ipv6 inet_interfaces = all #inet_interfaces = # 127.0.0.1 # $IPV4 # $IPV6 myhostname = $HOSTNAME mydestination = $HOSTNAME localhost ## - The list of "trusted" SMTP clients that have more ## - privileges than "strangers" ## - mynetworks = # +++++++++++++++++++++++++++++++++++++ # replace 127.0.0.1/8 with 127.0.0.1/32 # +++++++++++++++++++++++++++++++++++++ # So we can use i.e 127.0.0.25 (or any other 127.x.x.x address) # to bind to hidden tor service on port 25 without having an # open relay # # see also: https://github.com/ehloonion/onionmx/blob/master/open-relay.md # #127.0.0.0/8 127.0.0.1/32 [::ffff:127.0.0.0]/104 [::1]/128 ${IPV4}/32 [${IPV6}]/128 # a.mx.oopen.de #95.217.204.247/32 #[2a01:4f9:4a:47e5::247]/128 # b.mx.oopen.de #162.55.82.73/32 #[2a01:4f8:271:1266::73]/128 # d.mx.oopen.de #95.217.204.227/32 #[2a01:4f9:4a:47e5::227]/128 # e.mx.oopen.de #95.217.204.205/32 #[2a01:4f9:4a:47e5::205]/128 smtp_bind_address = $IPV4 smtp_bind_address6 = $IPV6 # The address type ("ipv6", "ipv4" or "any") that the Postfix SMTP client will try first, # when a destination has IPv6 and IPv4 addresses with equal MX preference. This feature # has no effect unless the inet_protocols setting enables both IPv4 and IPv6. # #smtp_address_preference = ipv4 EOF else cat <> /etc/postfix/main.cf inet_protocols = ipv4 #inet_interfaces = all inet_interfaces = 127.0.0.1 $IPV4 myhostname = $HOSTNAME mydestination = $HOSTNAME localhost ## - The list of "trusted" SMTP clients that have more ## - privileges than "strangers" ## - mynetworks = # +++++++++++++++++++++++++++++++++++++ # replace 127.0.0.1/8 with 127.0.0.1/32 # +++++++++++++++++++++++++++++++++++++ # So we can use i.e 127.0.0.25 (or any other 127.x.x.x address) # to bind to hidden tor service on port 25 without having an # open relay # # see also: https://github.com/ehloonion/onionmx/blob/master/open-relay.md # #127.0.0.0/8 127.0.0.1/32 ${IPV4}/32 # a.mx.oopen.de #95.217.204.247 # b.mx.oopen.de #162.55.82.73 # d.mx.oopen.de #95.217.204.227/32 # e.mx.oopen.de #95.217.204.205/32 smtp_bind_address = $IPV4 #smtp_bind_address6 = $IPV6 EOF fi cat <> /etc/postfix/main.cf ## - The method to generate the default value for the mynetworks parameter. ## - ## - mynetworks_style = host" when Postfix should "trust" only the local machine ## - mynetworks_style = subnet (default value) "when Postfix should "trust" SMTP ## - clients in the same IP subnetworks as the local machine. ## - mynetworks_style = class" when Postfix should "trust" SMTP clients in the same ## - IP class A/B/C networks as the local machine. ## - #mynetworks_style = host ## - The maximal size of any local(8) individual mailbox or maildir file, ## - or zero (no limit). In fact, this limits the size of any file that is ## - written to upon local delivery, including files written by external ## - commands that are executed by the local(8) delivery agent. ## - mailbox_size_limit = 0 ## - The maximal size in bytes of an individual virtual(8) mailbox or ## - maildir file, or zero (no limit). ## - virtual_mailbox_limit = 0 ## - The maximal size in bytes of a message, including envelope information. ## - ## - we user 50MB ## - message_size_limit = 52480000 ## - The system-wide recipient address extension delimiter ## - recipient_delimiter = + ## - The alias databases that are used for local(8) delivery. ## - alias_maps = hash:/etc/aliases ## - The alias databases for local(8) delivery that are updated ## - with "newaliases" or with "sendmail -bi". ## - alias_database = hash:/etc/aliases ## - Optional address mapping lookup tables for envelope and header sender ## - addresses. The table format and lookups are documented in canonical(5). ## - ## - Example: you want to rewrite the SENDER address "user@ugly.domain" ## - to "user@pretty.domain", while still being able to send mail to the ## - RECIPIENT address "user@ugly.domain". ## - ## - Note: \$sender_canonical_maps is processed before \$canonical_maps. ## - sender_canonical_maps = btree:/etc/postfix/sender_canonical ## - smtp_generic_maps (default: empty) ## - ## - Optional lookup tables that perform address rewriting in the Postfix ## - SMTP client, typically to transform a locally valid address into a ## - globally valid address when sending mail across the Internet. This is ## - needed when the local machine does not have its own Internet domain name, ## -but uses something like localdomain.local instead. ## - smtp_generic_maps = btree:/etc/postfix/generic ## - Optional lookup tables with mappings from recipient address ## - to (message delivery transport, next-hop destination). ## - See transport(5) for details. ## - transport_maps = btree:/etc/postfix/transport btree:/etc/postfix/relay_domains EOF if $IS_SYMPA_LIST_SERVER ; then cat <> /etc/postfix/main.cf regexp:/etc/postfix/sympa_transport EOF fi cat <> /etc/postfix/main.cf ## - The maximal time a message is queued before it is sent back as ## - undeliverable. Defaults to 5d (5 days) ## - Specify 0 when mail delivery should be tried only once. ## - maximal_queue_lifetime = 12h bounce_queue_lifetime = \$maximal_queue_lifetime ## - delay_warning_time (default: 0h) ## - ## - The time after which the sender receives a copy of the message ## - headers of mail that is still queued. To enable this feature, ## - specify a non-zero time value (an integral value plus an optional ## - one-letter suffix that specifies the time unit). ## - Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). ## - The default time unit is h (hours). delay_warning_time = 4h # ============ header/mime-header/body checks ============ header_checks = pcre:/etc/postfix/header_checks.pcre mime_header_checks = pcre:/etc/postfix/mime_header_check.pcre body_checks = pcre:/etc/postfix/body_check.pcre prepend_delivered_header = forward file ## - proxy_read_maps ## - ## - The lookup tables that the proxymap(8) server is allowed to access for the read-only service. ## - ## - Specify zero or more "type:name" lookup tables, separated by whitespace or comma. Table ## - references that don't begin with proxy: are ignored. ## - #proxy_read_maps = \$local_recipient_maps \$mydestination \$virtual_alias_maps \$virtual_alias_domains \$virtual_mailbox_maps \$virtual_mailbox_domains \$relay_recipient_maps \$relay_domains \$canonical_maps \$sender_canonical_maps \$recipient_canonical_maps \$relocated_maps \$transport_maps \$mynetworks \$sender_bcc_maps \$recipient_bcc_maps \$smtp_generic_maps \$lmtp_generic_maps \$smtpd_sender_login_maps # ============ Relay parameters ============ relayhost = EOF if $IS_SYMPA_LIST_SERVER ; then cat <> /etc/postfix/main.cf sympa_destination_recipient_limit = 1 sympabounce_destination_recipient_limit = 1 relay_domains = \$mydestination btree:/etc/postfix/relay_domains btree:/etc/postfix/sympa_domains EOF else cat <> /etc/postfix/main.cf relay_domains = \$mydestination btree:/etc/postfix/relay_domains EOF fi cat <> /etc/postfix/main.cf # ============ TLS parameters ============ # What mechanisms the Postfix SMTP client uses to look up a host's IP address. # This parameter is ignored when DNS lookups are disabled (see: disable_dns_lookups # and smtp_dns_support_level). The "dns" mechanism is always tried before "native" # if both are listed. # # Specify one of the following: # # dns # Hosts can be found in the DNS (preferred). # # native # Use the native naming service only (nsswitch.conf, or equivalent mechanism). # # dns, native # Use the native service for hosts not found in the DNS. # smtp_host_lookup = dns # Level of DNS support in the Postfix SMTP client. With "smtp_dns_support_level" # left at its empty default value, the legacy "disable_dns_lookups" parameter c # ontrols whether DNS is enabled in the Postfix SMTP client, otherwise the l # egacy parameter is ignored. # # Specify one of the following: # # disabled # Disable DNS lookups. No MX lookups are performed and hostname to address lookups # are unconditionally "native". This setting is not appropriate for hosts that # deliver mail to the public Internet. Some obsolete how-to documents recommend # disabling DNS lookups in some configurations with content_filters. This is no # longer required and strongly discouraged. # # enabled # Enable DNS lookups. Nexthop destination domains not enclosed in "[]" will be # subject to MX lookups. If "dns" and "native" are included in the "smtp_host_lookup" # parameter value, DNS will be queried first to resolve MX-host A records, followed by # "native" lookups if no answer is found in DNS. # # dnssec # Enable DNSSEC lookups. The "dnssec" setting differs from the "enabled" setting above # in the following ways: # # - Any MX lookups will set RES_USE_DNSSEC and RES_USE_EDNS0 to request DNSSEC-validated # responses. If the MX response is DNSSEC-validated the corresponding hostnames are # considered validated. # # - The address lookups of validated hostnames are also validated, (provided of course # "smtp_host_lookup" includes "dns", see below). # # - Temporary failures in DNSSEC-enabled hostname-to-address resolution block any # "native" lookups. Additional "native" lookups only happen when DNSSEC lookups # hard-fail (NODATA or NXDOMAIN). # # default: empty # # !! Notice !! # In order to support DNSSEC and DANE your resolver MUST support # DNSSEC too. # # If your resolver does not support DNSSEC, install "unbound". # smtp_dns_support_level = dnssec ## - Aktiviert TLS für den Mailempfang ## - # The SMTP TLS security level for the Postfix SMTP server; when a non-empty value is # specified, this overrides the obsolete parameters smtpd_use_tls and smtpd_enforce_tls. # This parameter is ignored with "smtpd_tls_wrappermode = yes". # # Specify one of the following security levels: # # none # TLS will not be used. # # may # Opportunistic TLS: announce STARTTLS support to remote SMTP clients, but do not # require that clients use TLS encryption. # # encrypt # Mandatory TLS encryption: announce STARTTLS support to remote SMTP clients, and # reject all plaintext commands except HELO, EHLO, XCLIENT, STARTTLS, NOOP, QUIT, # and (Postfix ≥ 3.9) HELP. According to RFC 2487 this MUST NOT be applied in case # of a publicly-referenced SMTP server. Instead, this should be used on dedicated # servers, for example submission (port 587). # smtpd_tls_security_level=may ## - Aktiviert TLS für den Mailversand ## - # The default SMTP TLS security level for the Postfix SMTP client. When a non-empty value # is specified, this overrides the obsolete parameters smtp_use_tls, smtp_enforce_tls, # and smtp_tls_enforce_peername; when no value is specified for smtp_tls_enforce_peername # or the obsolete parameters, the default SMTP TLS security level is none. # # Specify one of the following security levels: # # none # No TLS. TLS will not be used unless enabled for specific destinations # via smtp_tls_policy_maps. # # may # Opportunistic TLS. Use TLS if this is supported by the remote SMTP server, otherwise # use plaintext; after a failed TLS handshake or TLS session, fall back to plaintext # if the message has spent minimal_backoff_time in the mail queue. Since sending in the # clear is acceptable, demanding stronger than default TLS security merely reduces # interoperability. The "smtp_tls_ciphers" and "smtp_tls_protocols" (Postfix ≥ 2.6) # configuration parameters provide control over the protocols and cipher grade used # with opportunistic TLS. With earlier releases the opportunistic TLS cipher grade is # always "export" and no protocols are disabled. When TLS handshakes fail, the # connection is retried with TLS disabled. This allows mail delivery to sites with # non-interoperable TLS implementations. # # encrypt # Mandatory TLS encryption. Since a minimum level of security is intended, it is # reasonable to be specific about sufficiently secure protocol versions and ciphers. # At this security level and higher, the main.cf parameters smtp_tls_mandatory_protocols # and smtp_tls_mandatory_ciphers specify the TLS protocols and minimum cipher grade # which the administrator considers secure enough for mandatory encrypted sessions. # This security level is not an appropriate default for systems delivering mail to the # Internet. # # dane # Opportunistic DANE TLS. At this security level, the TLS policy for the destination # is obtained via DNSSEC. For TLSA policy to be in effect, the destination domain's # containing DNS zone must be signed and the Postfix SMTP client's operating system # must be configured to send its DNS queries to a recursive DNS nameserver that is # able to validate the signed records. Each MX host's DNS zone should also be signed, # and should publish DANE TLSA (RFC 7672) records that specify how that MX host's TLS # certificate is to be verified. TLSA records do not preempt the normal SMTP MX host # selection algorithm, if some MX hosts support TLSA and others do not, TLS security # will vary from delivery to delivery. # # dane-only # ... # # fingerprint # ... # # verify # ... # # secure # ... # smtp_tls_security_level=dane ## - 0 Disable logging of TLS activity. ## - 1 Log TLS handshake and certificate information. ## - 2 Log levels during TLS negotiation. ## - 3 Log hexadecimal and ASCII dump of TLS negotiation process. ## - 4 Also log hexadecimal and ASCII dump of complete transmission after STARTTLS. ## - smtpd_tls_loglevel = 1 smtp_tls_loglevel = 1 smtpd_tls_cert_file = $_TLS_CERT_FILE smtpd_tls_key_file = $_TLS_KEY_FILE ## - File with DH parameters that the Postfix SMTP server should use with EDH ciphers. ## - ## - Dont't forget to create it, e.g with openssl: ## - openssl dhparam -out /etc/postfix/ssl/dh_1024.pem -2 1024 ## - #smtpd_tls_dh1024_param_file = /etc/postfix/ssl/dh_1024.pem ## - also possible to use 2048 key with that parameter ## - smtpd_tls_dh1024_param_file = /etc/postfix/ssl/dh_2048.pem ## - File with DH parameters that the Postfix SMTP server should use with EDH ciphers. ## - ## - Dont't forget to create it, e.g with openssl: ## - openssl dhparam -out /etc/postfix/ssl/dh_512.pem -2 512 ## - smtpd_tls_dh512_param_file = /etc/postfix/ssl/dh_512.pem ## - File containing CA certificates of root CAs trusted to sign either remote SMTP ## - server certificates or intermediate CA certificates. These are loaded into ## - memory !! BEFORE !! the smtp(8) client enters the chroot jail. ## - smtp_tls_CAfile = $_TLS_CA_FILE ## - Directory with PEM format certificate authority certificates that the Postfix SMTP ## - client uses to verify a remote SMTP server certificate. Don't forget to create the ## - necessary "hash" links with, for example, " ## - /usr/bin/c_rehash /etc/postfix/certs". ## - ## - !! Note !! ## - To use this option in chroot mode, this directory (or a copy) must be inside ## - the chroot jail. ## - ## - Note that a chrooted daemon resolves all filenames relative to the Postfix ## - queue directory (/var/spool/postfix) ## - #smtpd_tls_CApath = /etc/postfix/certs # TLS protocols accepted by the Postfix SMTP server with opportunistic TLS encryption. # If the list is empty, the server supports all available TLS protocol versions. # # default: see 'postconf -d' output # smtpd_tls_protocols = >=TLSv1.1 # TLS protocols accepted by the Postfix SMTP server with mandatory TLS encryption. # smtpd_tls_mandatory_protocols = >=TLSv1.1 # TLS protocols that the Postfix SMTP client will use with opportunistic TLS encryption. # # default: see 'postconf -d' output # smtp_tls_protocols = >=TLSv1.2 # TLS protocols that the Postfix SMTP client will use with mandatory TLS encryption. # # default: see 'postconf -d' output # smtp_tls_mandatory_protocols = >=TLSv1.2 # The Postfix SMTP server security grade for ephemeral elliptic-curve # Diffie-Hellman (EECDH) key exchange. As of Postfix 3.6, the value of this # parameter is always ignored, and Postfix behaves as though the auto value # (described below) was chosen. # # auto # Use the most preferred curve that is supported by both the client and the server. # This setting requires Postfix ≥ 3.2 compiled and linked with OpenSSL ≥ 1.0.2. This # is the default setting under the above conditions (and the only setting used with # Postfix ≥ 3.6). # # none # Don't use EECDH. Ciphers based on EECDH key exchange will be disabled. This is the # default in Postfix versions 2.6 and 2.7. # # strong # Use EECDH with approximately 128 bits of security at a reasonable computational cost. # This is the default in Postfix versions 2.8-3.5. # # ultra # Use EECDH with approximately 192 bits of security at computational cost that is # approximately twice as high as 128 bit strength ECC. # #smtpd_tls_eecdh_grade = auto # With SSLv3 and later, use the Postfix SMTP server's cipher preference order instead # of the remote client's cipher preference order. # # By default, the OpenSSL server selects the client's most preferred cipher that the # server supports. With SSLv3 and later, the server may choose its own most preferred # cipher that is supported (offered) by the client. # # Setting "tls_preempt_cipherlist = yes" enables server cipher preferences. # # default: no # tls_preempt_cipherlist = yes # The minimum TLS cipher grade that the Postfix SMTP server will use with mandatory # TLS encryption. The default grade ("medium") is sufficiently strong that any benefit # from globally restricting TLS sessions to a more stringent grade is likely negligible, # especially given the fact that many implementations still do not offer any stronger # ("high" grade) ciphers, while those that do, will always use "high" grade ciphers. # So insisting on "high" grade ciphers is generally counter-productive. Allowing "export" # or "low" ciphers is typically not a good idea, as systems limited to just these are # limited to obsolete browsers. No known SMTP clients fail to support at least one # "medium" or "high" grade cipher. # # default: medium # #smtpd_tls_mandatory_ciphers = medium # The minimum TLS cipher grade that the Postfix SMTP server will use with opportunistic # TLS encryption. Cipher types listed in smtpd_tls_exclude_ciphers are excluded from the # base definition of the selected cipher grade. # # default: medium # smtpd_tls_ciphers = high # List of ciphers or cipher types to exclude from the SMTP server cipher list at all # TLS security levels. # # DO NOT exclude ciphers unless it is essential to do so. This is not an OpenSSL cipherlist; # it is a simple list separated by whitespace and/or commas. The elements are a single cipher, # or one or more "+" separated cipher properties, in which case only ciphers matching all the # properties are excluded. # #smtpd_tls_exclude_ciphers = # Additional list of ciphers or cipher types to exclude from the Postfix SMTP client cipher # list at mandatory TLS security levels. This list works in addition to the exclusions listed # with smtp_tls_exclude_ciphers # #smtp_tls_mandatory_exclude_ciphers = smtpd_tls_session_cache_database = btree:\${data_directory}/smtpd_scache smtp_tls_session_cache_database = btree:\${data_directory}/smtp_scache # produce Received: message headers that include information about the protocol and cipher used smtpd_tls_received_header = yes EOF if $IS_RELAY_HOST ; then cat <> /etc/postfix/main.cf #======= SASL Authentification ============ # Enable SASL authentication smtpd_sasl_auth_enable = $SASL_AUTH_ENABLED # Only offer SMTP AUTH when talking over an encrypted connection smtpd_tls_auth_only = yes smtpd_sasl_type = cyrus smtpd_sasl_path = smtpd # Disallow methods that allow anonymous authentication. smtpd_sasl_security_options = noanonymous smtpd_sasl_tls_security_options = \$smtpd_sasl_security_options # Report the SASL authenticated user name in the smtpd(8) Received message header. smtpd_sasl_authenticated_header = yes # Enable interoperability with remote SMTP clients that implement an obsolete version # of the AUTH command (RFC 4954). Examples of such clients are MicroSoft Outlook # Express version 4 and MicroSoft Exchange version 5.0. # # Specify "broken_sasl_auth_clients = yes" to have Postfix advertise AUTH support # in a non-standard way. # broken_sasl_auth_clients = yes ## - Optional lookup table with the SASL login names that own ## - sender (MAIL FROM) addresses. smtpd_sender_login_maps = #======= Virtual mailboxes ============ ## - Local Mailboxes ## - virtual_mailbox_base = virtual_uid_maps = virtual_gid_maps = EOF else cat <> /etc/postfix/main.cf #======= SASL Authentification ============ ## - Enable SASL authentication in the Postfix SMTP server. By default, ## - the Postfix SMTP server does not use authentication. ## - smtpd_sasl_auth_enable = no ## - Only offer SMTP AUTH when talking over an encrypted connection ## - smtpd_tls_auth_only = yes ## - The SASL plug-in type that the Postfix SMTP server should use for authentication. ## - The available types are listed with the "postconf -a" command. ## - ## - Available values are at least: cyrus, dovecot ## - smtpd_sasl_type = dovecot ## - Implementation-specific information that the Postfix SMTP server passes ## - through to the SASL plug-in implementation that is selected with smtpd_sasl_type. ## - Typically this specifies the name of a configuration file or rendezvous point. ## - smtpd_sasl_path = private/dovecot-auth # Disallow methods that allow anonymous authentication. smtpd_sasl_security_options = noanonymous smtpd_sasl_tls_security_options = \$smtpd_sasl_security_options # Report the SASL authenticated user name in the smtpd(8) Received message header. smtpd_sasl_authenticated_header = no # Enable interoperability with remote SMTP clients that implement an obsolete version # of the AUTH command (RFC 4954). Examples of such clients are MicroSoft Outlook # Express version 4 and MicroSoft Exchange version 5.0. # # Specify "broken_sasl_auth_clients = yes" to have Postfix advertise AUTH support # in a non-standard way. # broken_sasl_auth_clients = yes ## - Optional lookup table with the SASL login names that own ## - sender (MAIL FROM) addresses. smtpd_sender_login_maps = #======= Virtual mailboxes ============ ## - Local Mailboxes ## - virtual_mailbox_base = /var/vmail virtual_uid_maps = static:5000 virtual_gid_maps = static:5000 EOF fi cat <> /etc/postfix/main.cf ## - virtual_transport ## - ================= ## - ## - using postfix ## - virtual_transport = virtual ## - ## - using dovecot lda ## - virtual_transport = dovecot ## - dovecot_destination_recipient_limit = 1 ## - ## - using dovecot's lmtp service ## - virtual_transport = lmtp:unix:private/dovecot-lmtp ## - virtual_transport = virtual virtual_mailbox_maps = virtual_mailbox_domains = ## - Optional lookup tables that alias specific mail addresses or domains ## - to other local or remote address. The table format and lookups are ## - documented in virtual(5). For an overview of Postfix address ## - manipulations see the ADDRESS_REWRITING_README document. ## - virtual_alias_maps = btree:/etc/postfix/virtual_alias_maps EOF if $IS_SYMPA_LIST_SERVER ; then cat <> /etc/postfix/main.cf regexp:/etc/postfix/sympa_virtual_aliases EOF fi cat <> /etc/postfix/main.cf ## - mailman #hash:/var/lib/mailman/data/virtual-mailman ## - Postfix is final destination for the specified list of virtual alias ## - domains, that is, domains for which all addresses are aliased to addresses ## - in other local or remote domains. The SMTP server validates recipient ## - addresses with \$virtual_alias_maps and rejects non-existent recipients. ## - See also the virtual alias domain class in the ADDRESS_CLASS_README file ## - virtual_alias_domains = btree:/etc/postfix/virtual_alias_domains #======= Rate Limiting ============ # anvil_rate_time_unit (default: 60s) # # The time unit over which client connection rates and other rates are # calculated. # # The default interval is relatively short. Because of the high frequency of # updates, the anvil(8) server uses volatile memory only. Thus, information is # lost whenever the process terminates. # # Specify a non-zero time value (an integral value plus an optional one-letter # suffix that specifies the time unit). Time units: s (seconds), m (minutes), # h (hours), d (days), w (weeks). The default time unit is s (seconds). # # !! Note: # I basically only included it for conciseness. # #anvil_rate_time_unit = 60s # smtpd_soft_error_limit (default: 10) # # The number of errors a remote SMTP client is allowed to make without # delivering mail before the Postfix SMTP server slows down all # its responses. # #smtpd_soft_error_limit = 10 # ----- # Stay off of blacklists: Limit postfix recipients # ================================================ # # see also: # https://grovetech.co/blog/stay-off-of-blacklists-limit-postfix-recipients/ # ---- # smtpd_recipient_limit (default: 1000) # # The maximal number of recipients that the Postfix SMTP server accepts per # message delivery request. # # Note: # You can't restrict this to a to/cc/bcc field - it's for all recipients. # #smtpd_recipient_limit = 50 # smtpd_recipient_overshoot_limit (default: 1000) # # The number of recipients that a remote SMTP client can send in excess of # the limit specified with \$smtpd_recipient_limit, before the Postfix SMTP # server increments the per-session error count for each excess recipient. # #smtpd_recipient_overshoot_limit = 51 # smtpd_hard_error_limit (default: normal: 20, overload: 1) # # The maximal number of errors a remote SMTP client is allowed to make # without delivering mail. The Postfix SMTP server disconnects when the # limit is reached. Normally the default limit is 20, but it changes under # overload to just 1. Valid values are greater than zero. # #smtpd_hard_error_limit = 20 # --- # So you technically need to consider the 3 values here which affect both # inbound & outbound mail. Then there’s the throttling tools. # --- # smtpd_client_recipient_rate_limit (default: 0) # # The maximal number of recipient addresses that any client is allowed to # send to this service per time unit, regardless of whether or not Postfix # actually accepts those recipients. The time unit is specified with the # anvil_rate_time_unit configuration parameter. # # By default, a client can send as many recipient addresses per time unit # as Postfix can accept. # # To disable this feature, specify a limit of 0. # # WARNING: # The purpose of this feature is to limit abuse. It must not be used to # regulate legitimate mail traffic. # #smtpd_client_recipient_rate_limit = 50 # smtpd_client_connection_rate_limit (default: 0) # # The maximal number of connection attempts any client is allowed to make # to this service per time unit. The time unit is specified with the # anvil_rate_time_unit configuration parameter. # # By default, a client can make as many connections per time unit as Postfix # can accept. # # To disable this feature, specify a limit of 0. # # WARNING: # The purpose of this feature is to limit abuse. It must not be used to # regulate legitimate mail traffic. # #smtpd_client_connection_rate_limit = 10 # smtpd_client_message_rate_limit (default: 0) # # The maximal number of message delivery requests that any client is allowed # to make to this service per time unit, regardless of whether or not Postfix # actually accepts those messages. The time unit is specified with the # anvil_rate_time_unit configuration parameter. # # By default, a client can send as many message delivery requests per time unit # as Postfix can accept. # # To disable this feature, specify a limit of 0. # # WARNING: The purpose of this feature is to limit abuse. It must not be used # to regulate legitimate mail traffic. # #smtpd_client_message_rate_limit = 10 # --- # Set default 'Rate Limit' values # --- # default_recipient_limit (default: 20000) # # The default per-transport upper limit on the number of in-memory recipients. # These limits take priority over the global qmgr_message_recipient_limit after # the message has been assigned to the respective transports. # # See also default_extra_recipient_limit and qmgr_message_recipient_minimum. # #default_extra_recipient_limit = 50 # duplicate_filter_limit (default: 1000) # # The maximal number of addresses remembered by the address duplicate filter # for aliases(5) or virtual(5) alias expansion, or for showq(8) queue displays. # #duplicate_filter_limit = 50 # default_destination_recipient_limit (default: 50) # # The default maximal number of recipients per message delivery. This is the # default limit for delivery via the lmtp(8), pipe(8), smtp(8) and virtual(8) # delivery agents. # #default_destination_recipient_limit = 50 # smtp_destination_recipient_limit (default: \$default_destination_recipient_limit) # # The maximal number of recipients per message for the smtp message delivery # transport. This limit is enforced by the queue manager. The message delivery # transport name is the first field in the entry in the master.cf file. # # Note: # Setting this parameter to a value of 1 changes the meaning of # smtp_destination_concurrency_limit from concurrency per domain into concurrency # per recipient. # #smtp_destination_recipient_limit = \$default_destination_recipient_limit #======= smtpd Restrictions ============ # - Order of evaluating smtpd restriction lists: # - # - smtpd_client_restrictions # - smtpd_helo_restrictions # - smtpd_sender_restrictions # - smtpd_relay_restrictions # - smtpd_recipient_restrictions # - smtpd_data_restrictions # - smtpd_end_of_data_restrictions # - # - Note: # - all smtpd restrictions are evaluated until one of them # - results in 'REJECT' ## --- ## - Define smtpd Restrictions ## --- smtpd_restriction_classes = check_greylist check_greylist = check_policy_service unix:$postgrey_socket EOF if [[ -n "$postgrey_additional_options" ]]; then cat <> /etc/postfix/main.cf $postgrey_additional_options EOF fi cat <> /etc/postfix/main.cf # The time limit for delivery to 'postfwd' # # Note # This Parameter is used only if you've defined a 127.0.0.1:10040 spawn service # in master.cf to have postfix control starting/stopping of the service. # # If the service is started externally, such as by an init script, I # don't believe it's used or needed. # # The time limit for all external commands is controlled by command_time_limit # # EOF if [[ -n "$(which postfwd)" ]] ; then cat <> /etc/postfix/main.cf 127.0.0.1:10040_time_limit = 3600 EOF else cat <> /etc/postfix/main.cf #127.0.0.1:10040_time_limit = 3600 EOF fi if [[ -n "$(which policyd-spf)" ]] ; then cat <> /etc/postfix/main.cf # The time limit for delivery to '/usr/bin/policyd-spf' # # An entry in '/etc/postfix/master.cf' is needed: # # policyd-spf unix - n n - 0 spawn # user=policyd-spf argv=/usr/bin/policyd-spf # policyd-spf_time_limit = 3600 EOF fi cat <> /etc/postfix/main.cf # smtpd_delay_reject (default: yes) # # Wait until the RCPT TO command before evaluating \$smtpd_client_restrictions, # \$smtpd_helo_restrictions and \$smtpd_sender_restrictions, or wait until the # ETRN command before evaluating \$smtpd_client_restrictions and \$smtpd_helo_restrictions. # # This feature is turned on by default because some clients apparently mis-behave # when the Postfix SMTP server rejects commands before RCPT TO. # # The default setting has one major benefit: it allows Postfix to log recipient address # information when rejecting a client name/address or sender address, so that it is # possible to find out whose mail is being rejected. smtpd_delay_reject = yes ## --- ## smtpd Client Restrictions ## --- smtpd_client_restrictions = permit_sasl_authenticated, permit_mynetworks, # Whitelist clients # check_client_access btree:/etc/postfix/client_whitelist # White- / Blacklisting # check_sender_access btree:/etc/postfix/access_sender, check_recipient_access btree:/etc/postfix/access_recipient, # RBL check - !! comment out if postcreens postscreen_dnsbl_sites is in use # Whitelist (configured at a.ns.oopen.de) # permit_dnswl_client dnswl.oopen.de, # Blacklists # # - rhs stands for right hand side, i.e, the domain name. # # - reject_rhsbl_helo makes Postfix reject email when the client HELO or EHLO hostname is blacklisted. # # - reject_rhsbl_reverse_client: reject the email when the unverified reverse client hostname is # blacklisted. Postfix will fetch the client hostname from PTR record. If the hostname is # blacklisted, reject the email. # # - reject_rhsbl_sender makes Postfix reject email when the MAIL FROM domain is blacklisted. # # - reject_rbl_client: This is an IP-based blacklist. When the client IP address is backlisted, # reject the email. # reject_rhsbl_helo dbl.spamhaus.org, reject_rhsbl_reverse_client dbl.spamhaus.org, reject_rhsbl_sender dbl.spamhaus.org, reject_rbl_client zen.spamhaus.org, # Greylisting check # # check_policy_service inet:127.0.0.1:10023, # # # Using defined restriction class (see smtpd_restriction_classes): # # greylist all connections: # check_greylist, # # selctive greylisting: # check_client_access pcre:/etc/postfix/greylist_client_access_pcre, # #warn_if_reject, check_client_access pcre:/etc/postfix/greylist_client_access_pcre, #reject_rbl_client bl.spamcop.net, # Reject the request when # 1) the client IP address->name mapping fails # 2) the name->address mapping fails # 3) the name->address mapping does not match the client IP address. # # Note: # This is a stronger restriction than the reject_unknown_reverse_client_hostname # feature, which triggers only under condition 1) above. # #reject_unknown_client ## --- ## smtpd HELO Restrictions ## --- smtpd_helo_required = yes smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, # Whitelist clients # check_client_access btree:/etc/postfix/client_whitelist # Reject the request when the HELO or EHLO hostname is malformed. # # Note # specify "smtpd_helo_required = yes" to fully enforce this restriction # (without "smtpd_helo_required = yes", a client can simply skip # reject_invalid_helo_hostname by not sending HELO or EHLO). # reject_invalid_helo_hostname, # Reject the request when the HELO or EHLO hostname is not in fully-qualified # domain or address literal form, as required by the RFC. # reject_non_fqdn_helo_hostname # Don't talk to mail systems that don't know their own hostname. # reject_unknown_helo_hostname ## --- ## - smtpd Sender Restrictions ## --- smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unknown_sender_domain, reject_non_fqdn_sender reject_unknown_reverse_client_hostname ## --- ## - smtpd Recipient Restrictions ## --- # Applied in the context of a client RCPT TO command, after smtpd_relay_restrictions # smtpd_recipient_restrictions = # only special accounts (postmaster, abuse and other rolr accounts) check_recipient_access btree:/etc/postfix/access_recipient-rfc, # White- / Blacklisting check_sender_access btree:/etc/postfix/access_sender, check_recipient_access btree:/etc/postfix/access_recipient, # permit trusted network (mynetwork) permit_mynetworks, # permit our users permit_sasl_authenticated, # dont' accept misconfigured Mail reject_non_fqdn_recipient, # don't accept misconfigured recipients reject_unknown_recipient_domain, # Reject the request when the RCPT TO address is not listed in the list of valid # recipients for its domain class. See the smtpd_reject_unlisted_recipient # parameter description for details. # # smtpd_reject_unlisted_recipient (default: yes) # # Request that the Postfix SMTP server rejects mail for unknown recipient addresses, # even when no explicit reject_unlisted_recipient access restriction is specified. # This prevents the Postfix queue from filling up with undeliverable MAILER-DAEMON messages. # # An address is always considered "known" when it matches a virtual(5) alias or # a canonical(5) mapping. # - The recipient domain matches \$mydestination, \$inet_interfaces or \$proxy_interfaces, # but the recipient is not listed in \$local_recipient_maps, and \$local_recipient_maps # is not null. # - The recipient domain matches \$virtual_alias_domains but the recipient is not listed # in \$virtual_alias_maps. # - The recipient domain matches \$virtual_mailbox_domains but the recipient is not # listed in \$virtual_mailbox_maps, and \$virtual_mailbox_maps is not null. # - The recipient domain matches \$relay_domains but the recipient is not listed in # \$relay_recipient_maps, and \$relay_recipient_maps is not null. # reject_unlisted_recipient, # reject_unauth_destination # # Reject the request unless one of the following is true: # # - Postfix is mail forwarder: the resolved RCPT TO domain matches \$relay_domains # or a subdomain thereof, and contains no sender-specified routing (user@elsewhere@domain), # # # - Postfix is the final destination: the resolved RCPT TO domain matches # \$mydestination, \$inet_interfaces, \$proxy_interfaces, \$virtual_alias_domains, # or \$virtual_mailbox_domains, and contains no sender-specified routing (user@elsewhere@domain). # # Note: # reject_unauth_destination is not needed here if the mail # relay policy is specified under smtpd_relay_restrictions # (available with Postfix 2.10 and later). #reject_unauth_destination, # Reject the request when mail to the RCPT TO address is known to bounce, or when the # recipient address destination is not reachable. Address verification information is # managed by the verify(8) server; see http://www.postfix.org/ADDRESS_VERIFICATION_README.html # for more details reject_unverified_recipient, EOF if [[ -n "$(which policyd-spf)" ]] ; then cat <> /etc/postfix/main.cf # Check Postfix policy service .. # check_policy_service unix:private/policy-spf EOF fi cat <> /etc/postfix/main.cf # Policyd-Weight #check_policy_service inet:127.0.0.1:12525, # permit Backup MX permit_mx_backup, # permit, if all restrictions so far passed permit ## --- ## - smtpd Relay Restrictions (since version 2.11) ## --- # Access restrictions for mail relay control applied in the context of # the RCPT TO command, before smtpd_recipient_restrictions. # smtpd_relay_restrictions = # only special accounts (postmaster, abuse and other rolr accounts) check_recipient_access btree:/etc/postfix/access_recipient-rfc, # White- / Blacklisting check_client_access btree:/etc/postfix/client_allow_relay, check_sender_access btree:/etc/postfix/access_sender, check_recipient_access btree:/etc/postfix/access_recipient, # permit trusted network (mynetwork) permit_mynetworks, # permit our users permit_sasl_authenticated, # dont' accept misconfigured Mail reject_non_fqdn_recipient, # don't accept misconfigured recipients reject_unknown_recipient_domain, # Reject the request unless one of the following is true: # # - Postfix is mail forwarder: the resolved RCPT TO domain matches \$relay_domains # or a subdomain thereof, and contains no sender-specified routing (user@elsewhere@domain), # # - Postfix is the final destination: the resolved RCPT TO domain matches # \$mydestination, \$inet_interfaces, \$proxy_interfaces, \$virtual_alias_domains, # or \$virtual_mailbox_domains, and contains no sender-specified routing (user@elsewhere@domain). reject_unauth_destination, # Reject the request when mail to the RCPT TO address is known to bounce, or when the # recipient address destination is not reachable. Address verification information is # managed by the verify(8) server; see http://www.postfix.org/ADDRESS_VERIFICATION_README.html # for more details reject_unverified_recipient, # permit Backup MX permit_mx_backup, # permit, if all restrictions so far passed permit ## --- ## - smtpd DATA Restrictions ## --- smtpd_data_restrictions = # Block clients that speak too early. # reject_unauth_pipelining ## --- ## - smtpd END OF ATA Restrictions ## --- smtpd_end_of_data_restrictions = EOF if [[ -n "$(which postfwd)" ]] ; then cat <> /etc/postfix/main.cf # Check Postfix Firewall Daemon # check_policy_service inet:127.0.0.1:10040 EOF else cat <> /etc/postfix/main.cf EOF fi if [[ -n "$(which opendkim)" ]] || [[ -n "$(which opendmarc)" ]] ; then cat <> /etc/postfix/main.cf # ======= Milter configuration ======= # OpenDKIM milter_default_action = accept # Postfix ≥ 2.6 milter_protocol = 6, Postfix ≤ 2.5 milter_protocol = 2 milter_protocol = 6 # Note: # We will sign AFTER sending through AmaVIS, just befor sending out. So # set 'smtpd_milters =' to an emty string here and add to localhost:10025 # section in master.cf: 'smtpd_milters=local:/opendkim/opendkim.sock' # # If you want sign mails before sending through AmaVIS, set # 'smtpd_milters = local:/opendkim/opendkim.sock' here and add to # localhost:10025 section in master.cf: 'smtpd_milters=' # smtpd_milter_maps = cidr:/etc/postfix/smtpd_milter_map smtpd_milters = EOF fi if [[ -n "$(which opendkim)" ]] ; then if [[ -n "$(which opendmarc)" ]] ; then cat <> /etc/postfix/main.cf non_smtpd_milters = local:/opendkim/opendkim.sock,local:/opendmarc/opendmarc.sock EOF else cat <> /etc/postfix/main.cf non_smtpd_milters = local:/opendkim/opendkim.sock EOF fi elif [[ -n "$(which opendmarc)" ]] ; then cat <> /etc/postfix/main.cf non_smtpd_milters = local:/opendmarc/opendmarc.sock EOF fi echo_ok ## - /etc/mailname ## - echononl " Set \"/etc/mailname\"" echo $HOSTNAME > /etc/mailname if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi ## - /etc/aliases ## - echononl " Backup existing file '/etc/aliases'" if [[ -f /etc/aliases ]] ; then mv /etc/aliases "/etc/aliases.$backup_date" > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi echononl " Adjust \"/etc/aliases\"" cat << EOF > /etc/aliases # See man 5 aliases for format mailer-daemon: postmaster postmaster: root nobody: root hostmaster: root usenet: root news: root webmaster: root www: root ftp: root abuse: root noc: root security: root do-not-reply: /dev/null root: $ADMIN_EMAIL EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi ## - create directory for certificates and copy certificates ## - and coresponding keys to /etc/postfix/ssl/ ## - echononl " Create directory for certificates \"/etc/postfix/ssl\"" if [[ -d "/etc/postfix/ssl" ]] ; then echo_skipped else mkdir -p /etc/postfix/ssl if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi fi ## - generate DH parameters that the Postfix SMTP server should use ## - with EDH ciphers (length 512 and 1024 ## - echononl " Generate DH key length=512 \"/etc/postfix/ssl/dh_512.pem\"" if [[ ! -f /etc/postfix/ssl/dh_512.pem ]]; then if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then openssl dhparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1 else openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1 fi if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then if $(grep -q -E "X9.42" /etc/postfix/ssl/dh_512.pem 2> /dev/null); then openssl dhparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi else echo_skipped fi fi echononl " Generate DH key length=1024 \"/etc/postfix/ssl/dh_1024.pem\"" if [[ ! -f /etc/postfix/ssl/dh_1024.pem ]]; then if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then openssl dhparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1 else openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1 fi if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then if $(grep -q -E "X9.42" /etc/postfix/ssl/dh_1024.pem 2> /dev/null); then openssl dhparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi else echo_skipped fi fi echononl " Generate DH key length=2048 \"/etc/postfix/ssl/dh_2048.pem\"" if [[ ! -f /etc/postfix/ssl/dh_2048.pem ]]; then if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then openssl dhparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1 else openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1 fi if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then if $(grep -q -E "X9.42" /etc/postfix/ssl/dh_2048.pem 2> /dev/null); then openssl dhparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi else echo_skipped fi fi echononl " Create Symlink \"$_TLS_CERT_FILE\"" if [ ! -h "$_TLS_CERT_FILE" ]; then ln -s /etc/ssl/certs/ssl-cert-snakeoil.pem $_TLS_CERT_FILE if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi echononl " Create Symlink \"$_TLS_KEY_FILE\"" if [ ! -h "$_TLS_KEY_FILE" ]; then ln -s /etc/ssl/private/ssl-cert-snakeoil.key $_TLS_KEY_FILE if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi ## - rebuld alias database ## - echononl " Rebuld alias database" newaliases > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi ## - create files ## - echononl " Create file \"access_recipient-rfc\"" if [[ ! -f /etc/postfix/access_recipient-rfc ]]; then cat < /etc/postfix/access_recipient-rfc # if destination is ok, permit /^postmaster\@/ permit_auth_destination /^abuse\@/ permit_auth_destination EOF fi postmap btree:/etc/postfix/access_recipient-rfc if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi ## - Notice: ## - The access_sender list can also be used as white list: ## - backup@b3-bornim.de OK ## - backup_file-ah@oopen.de OK ## - backup_file-spr@oopen.de OK ## - root_file_spr@oopen.de OK ## - backup_anw-urban@oopen.de OK ## - anonymous@bbb-server.b3-bornim.de OK echononl " Create file \"access_sender\"" if [[ ! -f /etc/postfix/access_sender ]]; then cat < /etc/postfix/access_sender # ----- # /etc/postfix/sender_checks # # Restricts sender addresses this system accepts in MAIL FROM commands. # # Define the whitelist or blacklist with and OK or REJECT, # followed by an optional answer text. # # # Note: # # Checks from this file are already applied by 'smtpd_client_restrictions'! # # # Example: # # example.com REJECT env. from addr any@example.com rejected # .example.com REJECT env. from addr any@sub.example.com rejected # user@example.com REJECT We don't want your email # example2.com OK # ----- # - Whitelist for sender adresses # - # - bekannte Virus/Spam Absener blocken # - # annoying spammer domains acieu.co.uk REJECT # annoying spammer addresses error@mailfrom.com REJECT EOF fi postmap btree:/etc/postfix/access_sender if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"access_recipient\"" if [[ ! -f /etc/postfix/access_recipient ]]; then touch /etc/postfix/access_recipient fi postmap btree:/etc/postfix/access_recipient if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"client_whitelist\"" if [[ ! -f "/etc/postfix/client_whitelist" ]]; then cat < /etc/postfix/client_whitelist # onion - tor hidden service 127.0.0.25 OK EOF fi postmap btree:/etc/postfix/client_whitelist if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"client_allow_relay\"" if [[ ! -f "/etc/postfix/client_allow_relay" ]]; then cat < /etc/postfix/client_allow_relay # /etc/postfix/client_allow_relay # # Restricts which clients (IP addresses or hostnames) this system accepts # (or rejects) for relaying e-mails # # Example: # b.mx.oopen.de OK #lists.mx.warenform.de OK #b.mx.oopen.de OK #d.mx.oopen.de OK EOF fi postmap btree:/etc/postfix/client_allow_relay if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"sender_canonical\"" if [[ ! -f /etc/postfix/sender_canonical ]]; then cat < /etc/postfix/sender_canonical @localhost @$(hostname -f) EOF fi postmap btree:/etc/postfix/sender_canonical if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"generic\"" if [[ ! -f /etc/postfix/generic ]]; then cat < /etc/postfix/generic @localhost @$(hostname -f) EOF fi postmap btree:/etc/postfix/generic if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"virtual_alias_domains\"" if [[ ! -f /etc/postfix/virtual_alias_domains ]]; then cat < /etc/postfix/virtual_alias_domains # - File: /etc/postfix/virtual_alias_domains # - # - Note: # - a mapping file always has two columns. In such a 'one-dimensional' mapping (list of domains) # - Postfix does not care about your second column. It does not even have to be 'OK', it can be # - anything. # - # - Example: # - OK EOF fi postmap btree:/etc/postfix/virtual_alias_domains if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"virtual_alias_maps\"" if [[ ! -f /etc/postfix/virtual_alias_maps ]]; then cat < /etc/postfix/virtual_alias_maps # - File: /etc/postfix/virtual_alias_maps # - # - Redirect mail for one address to one or more addresses. # - # - Example: # - # incomming address 'no-reply@cloud-01.oopen.de' to local 'do-not-reply' address # - no-reply@cloud-01.oopen.de do-not-reply # - EOF fi postmap btree:/etc/postfix/virtual_alias_maps if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"transport\"" if [[ ! -f /etc/postfix/transport ]]; then cat < /etc/postfix/transport # - Force sending through IPv4 # - # - Take care your master.cf file ($postfix_master_cf) contains: # - # - smtp-ipv4-only unix - - n - - smtp # - -o inet_protocols=ipv4 # - #example.com smtp-ipv4-only: # - Force sending through IPv6 # - # - Take care your master.cf file ($postfix_master_cf) contains: # - # - smtp-ipv6-only unix - - n - - smtp # - -o inet_protocols=ipv6 # - #example.net smtp-ipv6-only: EOF fi postmap btree:/etc/postfix/transport if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"relay_domains\"" if [[ ! -f /etc/postfix/relay_domains ]] ; then touch /etc/postfix/relay_domains fi postmap btree:/etc/postfix/relay_domains if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Create file \"greylist_client_access_pcre\"" if [[ ! -f /etc/postfix/greylist_client_access_pcre ]]; then cat < /etc/postfix/greylist_client_access_pcre # --- # Check Client Access for greylisting (selective greylisting) # --- # # - Note: # - # - Action 'check_greylist' must be defined by 'smtpd_restriction_classes' # - and also set with an action (check_policy_service inet:127.0.0.1:10023) # - in file /etc/postfix/ main.cf. # - # - Your main.cf may looks like: # - # - smtpd_restriction_classes = check_greylist # - check_greylist = check_policy_service inet:127.0.0.1:10023 # - # - smtpd_recipient_restrictions = # - ... # - check_client_access pcre:/etc/postfix/greylist_client_access_pcre, # - ... # - # - smtpd_relay_restrictions = # - ... # - check_client_access pcre:/etc/postfix/greylist_client_access_pcre, # - ... # --- # - For clients matching the following rules greylisting check is applied. # --- # unkown clients /^unknown$/ check_greylist # everything with 3 or more hyphens in the hostname /(\\-.+){3}$/ check_greylist # everything with 4 or more dots in the hostname /(\\..+){4}$/ check_greylist # dialups /(^|[0-9.x_-])(abo|br(e|oa)dband|cabel|(hk)?cablep?|catv|cbl|cidr|d?client2?|cust(omer)?s?|dhcp|dial?(in|up)?|d[iu]p|[asx]?dsld?|dyn(a(dsl|mic)?)?|home|in-addr|modem(cable)?|(di)?pool|ppp|ptr|rev|static|user|YahooBB[0-9]{12}|c[[:alnum:]]{6,}(\\.[a-z]{3})?\\.virtua|[1-9]Cust[0-9]+|AC[A-Z][0-9A-F]{5}\\.ipt|pcp[0-9]{6,}pcs|S0106[[:alnum:]]{12,}\\.[a-z]{2})[0-9.x_-]/ check_greylist EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/header_checks.pcre" echononl " Create file '$_file' used for header replacing" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # - Replace headers # --- # - Replace recieved from #/^Received: from (.* \\([-._[:alnum:]]+ \\[[.[:digit:]]{7,15}\\]\\)).*?([[:space:]]+).*\\(Authenticated sender: ([^)]+)\\)(.*)/ REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1])\$2(Authenticated sender: \$3)\$4 # --- # - Ignore Headers # --- #/^\s*User-Agent/ IGNORE #/^\s*X-Enigmail/ IGNORE #/^\s*X-Mailer/ IGNORE #/^\s*X-Originating-IP/ IGNORE # --- # - Reject / Discard headers # --- /^To:.*<>/ REJECT Possible SPAM Blank email address To: header - Header-Spamschutzregel T0-1001 /\(envelope-from <>\)/ REJECT Possible SPAM - Header-Spamschutzregel RECIEV-1001 /^Reply-To: .+\@inx1and1\..+/ REJECT Possible SPAM - Header-Spamschutzregel REPLY-1001 /^From:.*<>/ REJECT Possible SPAM - Header-Spamschutzregel FROM-1001 /^Date: .* 19[0-9][0-9]/ REJECT Date from the past. Fix your system clock. - Header-Spamschutzregel DATE-1001 /^Date: .* 200[0-9]/ REJECT Date from the past. Fix your system clock. - Header-Spamschutzregel DATE-1002 /^Date: .* 201[0-9]/ REJECT Date from the past. Fix your system clock. - Header-Spamschutzregel DATE-1003 /^Date: .* 2020/ REJECT Date from the past. Fix your system clock. - Header-Spamschutzregel DATE-1004 EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/mime_header_check.pcre" echononl " Create file '$_file' used for header replacing" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # - MIME-Header Checks # --- /name=[^>]*\.exe/ REJECT No .exe files allowed - Mime--Spamschutzregel EXE-1001 /name=[^>]*\.bat/ REJECT No .bat files allowed - Mime--Spamschutzregel BAT-1002 /name=[^>](screensaver|movie)\.zip/ REJECT Sobig Virus found - Mime-Spamschutzregel VIR-1003 EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/body_check.pcre" echononl " Create file '$_file' used for header replacing" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # --- # - Body Checks # --- /See the attached file for details/ REJECT Sobig Virus found. - Body-Spamschutzregel TEXT-1001 /.*https?:\/\/click2eat.shop\/Installer\/updatedwebmails/ REJECT Maype fishing E-Mail credentials - Body-Spamschutzregel TEXT-1002 EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi _file="/etc/postfix/smtpd_milter_map" echononl " Create file '$_file' used disabling milter mail filter for client IP address(es)" if [[ ! -f "$_file" ]]; then cat << EOF > "$_file" # Disable Milters for local clients. #127.0.0.0/8 DISABLE #192.168.0.0/16 DISABLE #172.16.0.0/12 DISABLE #::/64 DISABLE # Disable Milters for b.mx.oopen.de 162.55.82.73 DISABLE 2a01:4f8:271:1266::73 DISABLE # Disable Milters for d.mx.oopen.de 95.217.204.227 DISABLE 2a01:4f9:4a:47e5::227 DISABLE # Disable Milters for lists.mx.warenform.de 83.223.86.78 DISABLE 2a01:30:0:13:223:35ff:fef5:84b6 DISABLE # Disable Milters for lists36.net 192.68.11.82 DISABLE 2001:678:a40:3000::82 DISABLE EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi if $IS_SYMPA_LIST_SERVER ; then _file_name=sympa_domains echononl "\tCreate (empty) file \"$_file_name\".." if [ -f "${postfix_conf_dir}/$_file_name" ];then echo_skipped else touch ${postfix_conf_dir}/$_file_name > /dev/null 2>&1 if [ "$?" = "0" ]; then echo_ok echononl "\tCreate concerning db-file \"${postfix_conf_dir}/${_file_name}.db\".." postmap btree:${postfix_conf_dir}/$_file_name > /dev/null 2>&1 if [ "$?" = "0" ]; then echo_ok else echo_failed fi else echo_failed fi fi _file_name=sympa_transport echononl "\tCreate (empty) file \"$_file_name\".." if [ -f "${postfix_conf_dir}/$_file_name" ];then echo_skipped else touch ${postfix_conf_dir}/$_file_name >> $_log_file 2>&1 if [ "$?" = "0" ]; then echo_ok else echo_failed fi fi _file_name=sympa_virtual_aliases echononl "\tCreate (empty) file \"$_file_name\".." if [ -f "${postfix_conf_dir}/$_file_name" ];then echo_skipped else touch ${postfix_conf_dir}/$_file_name >> $_log_file 2>&1 if [ "$?" = "0" ]; then echo_ok else echo_failed fi fi fi if ! $IS_RELAY_HOST ; then ## - Create Directory '/var/vmail' for virtual mailboxes ## - echononl " Create directory '/var/vmail'" if [[ ! -d "/var/vmail" ]]; then mkdir /var/vmail > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi ## - Create user (vmail) for virtual mailboxes ## - echononl " Create user 'vmail' for virtual mailboxes" if id -u vmail > /dev/null 2>&1; then echo_skipped else useradd -s /bin/false -d /var/vmail -M -u 5000 vmail > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi fi ## - Change ownership 'vmail:vmail' for dir '/var/vmail' ## - echononl " Change ownership 'vmail:vmail' for dir '/var/vmail'" chown vmail:vmail /var/vmail > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi ## - Change permissions for dir '/var/vmail' ## - echononl " Change permissions for dir '/var/vmail'" chmod 700 /var/vmail > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else if [[ "$SASL_AUTH_ENABLED" = "yes" ]]; then echononl " Create directory '/etc/postfix/sasl'.." if [[ ! -d "/etc/postfix/sasl" ]] ; then mkdir "/etc/postfix/sasl" > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else echo_skipped fi echononl " Backup existing file '/etc/postfix/sasl/smtpd.conf'" if [[ -f /etc/postfix/sasl/smtpd.conf ]] ; then mv /etc/postfix/sasl/smtpd.conf "/etc/postfix/sasl/smtpd.conf.$backup_date" > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi echononl " Create file '/etc/postfix/sasl/smtpd.conf'.." cat < /etc/postfix/sasl/smtpd.conf # - Take care only using provided login mechanisms. You can check this, by # - running command # - # - saslpluginviewer -x AUXPROP_MECHS # - pwcheck_method: auxprop auxprop_plugin: sasldb mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi fi fi ## - /etc/postfix/master.cf ## - ## - Create Listener for user authenticated smtp connection port 587 (submission) ## - and port 465 (smtps) ## - echononl " Backup file \"${postfix_master_cf}\"" cp -a $postfix_master_cf "${postfix_master_cf}.$backup_date" > /dev/null 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi if grep -iq -E "^submission\s+" $postfix_master_cf > /dev/null 2>&1 ; then submission_present=true else submission_present=false fi if grep -iq -E "^smtps\s+" $postfix_master_cf > /dev/null 2>&1 ; then smtps_present=true else smtps_present=false fi if grep -iq -E "^policyd-spf\s+" $postfix_master_cf > /dev/null 2>&1 ; then policyd_spf_present=true else policyd_spf_present=false fi _found=false echononl " Create new file \"${postfix_master_cf}\"" if [[ -f "${postfix_master_cf}.$backup_date" ]]; then > $postfix_master_cf while IFS='' read -r _line || [[ -n $_line ]] ; do if echo "$_line" | grep -i -E "^\s*smtp\s+inet\s+" > /dev/null 2>&1 ; then _found=true cat >> $postfix_master_cf << EOF smtp inet n - y - - smtpd EOF if ! $IS_RELAY_HOST ; then if ! $submission_present ; then cat >> $postfix_master_cf << EOF submission inet n - y - 20 smtpd -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject #-o milter_macro_daemon_name=ORIGINATING EOF fi if ! $smtps_present ; then cat >> $postfix_master_cf << EOF smtps inet n - y - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject #-o milter_macro_daemon_name=ORIGINATING EOF fi elif $LISTEN_ON_ADDITIONAL_RELAY_PORT ; then cat >> $postfix_master_cf << EOF ${ADDITIONAL_RELAY_LISTEN_PORT} inet n - y - - smtpd EOF fi continue fi if $submission_present && echo "$_line" | grep -iq -E "^submission\s+" 2> /dev/null ; then _found=true if ! $IS_RELAY_HOST ; then cat >> $postfix_master_cf << EOF submission inet n - y - 20 smtpd -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject # -o milter_macro_daemon_name=ORIGINATING EOF fi continue fi if $smtps_present && echo "$_line" | grep -iq -E "^smtps\s+" 2> /dev/null ; then _found=true if ! $IS_RELAY_HOST ; then cat >> $postfix_master_cf << EOF smtps inet n - y - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject # -o milter_macro_daemon_name=ORIGINATING EOF fi continue fi # - [[:blank:]] means space and tab. This makes it similar to: [ \t] # - [[:space;]] in addition to space and tab, includes newline, linefeed, formfeed, # - and vertical tab. This makes it similar to: [ \t\n\r\f\v] # - #if [[ $_line =~ ^[[:space:]]+[^[:space:]]+ ]] && $_smtp_found ; then # - if [[ $_line =~ ^[[:blank:]]+[^[:space:]]+ ]] && $_found ; then continue fi _found=false echo "$_line" >> $postfix_master_cf done < "${postfix_master_cf}.$backup_date" # - Add support for policyd-spf service # - if ! $(grep -iq -E "^policyd-spf\s+" "$postfix_master_cf" 2> /dev/null) ; then cat <> $postfix_master_cf policyd-spf unix - n n - 0 spawn user=policyd-spf argv=/usr/bin/policyd-spf EOF fi # - Add transport definitions for only sending over IPv4/IPv6 # - if ! $(grep -iq -E "^smtp-ipv4-only\s+" "$postfix_master_cf" 2> /dev/null) ; then cat <> $postfix_master_cf smtp-ipv4-only unix - - n - - smtp -o inet_protocols=ipv4 EOF fi if ! $(grep -iq -E "^smtp-ipv6-only\s+" "$postfix_master_cf" 2> /dev/null) ; then cat <> $postfix_master_cf smtp-ipv6-only unix - - n - - smtp -o inet_protocols=ipv6 EOF fi echo_done warn "Please check file \"$postfix_master_cf\" !" else echo_failed error "File \"${postfix_master_cf}.$backup_date\" not found!" fi echononl " Adjust $postfix_master_cf. Set DKIM after sending throuh AmaVIS.." if [[ -n "$(which opendkim)" ]] ; then _found=false _changed=false tmp_master_file="/tmp/postfix_master.cf" > $tmp_master_file while IFS='' read -r _line || [[ -n $_line ]] ; do if $_found && ! echo "$_line" | grep -i -q -E "^\s*-o" 2> /dev/null ; then if [[ -n "$(which opendmarc)" ]] ; then echo " -o smtpd_milters=local:/opendkim/opendkim.sock,local:/opendmarc/opendmarc.sock" >> "$tmp_master_file" else echo " -o smtpd_milters=local:/opendkim/opendkim.sock" >> "$tmp_master_file" fi _changed=true _found=false fi if $_found && echo "$_line" | grep -i -q -E "^\s*-o\s+smtpd_milters=\s*" ; then _found=false fi if echo "$_line" | grep -i -q -E "^\s*(127.0.0.1|localhost):10025\s+inet\s+" 2> /dev/null ; then _found=true fi echo "$_line" >> "$tmp_master_file" done < "$postfix_master_cf" if $_changed ; then cp $tmp_master_file $postfix_master_cf 2> $log_file postfix_needs_restart=true if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped warn "Postfix (master.cf) seems already be configured." echononl " Delete previosly saved file '$postfix_master_cf'.." rm ${postfix_master_cf}.$backup_date 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi rm -f $tmp_master_file else echo_skipped fi echononl " Adjust $postfix_master_cf to play with dovecot lda" if [[ -x "/usr/local/dovecot/libexec/dovecot/dovecot-lda" ]] ; then ## - /etc/postfix/master.cf ## - ## - add line ## - dovecot unix - n n - - pipe ## - flags=drhu user=vmail:vmail argv=/usr/local/dovecot/libexec/dovecot/dovecot-lda -f ${sender} -d ${user}@${nexthop} if ! grep -e dovecot-lda $postfix_master_cf > /dev/null ; then cp -a "$postfix_master_cf" "${postfix_master_cf}.$backup_date" echo -e "\ndovecot unix - n n - - pipe\n flags=drhu user=vmail:vmail argv=/usr/local/dovecot/libexec/dovecot/dovecot-lda -f \${sender} -d \${user}@\${nexthop}" >> $postfix_master_cf if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "Configuring $postfix_master_cf for use with dovecot-lda failed" fi else echo_skipped fi else echo_skipped fi SYMPA_BIN_DIR="/usr/local/sympa/bin" SYMPA_LIBEXEC_DIR="$SYMPA_BIN_DIR" echononl " Add transport declaration for sympa domains to file master.cf" if $IS_SYMPA_LIST_SERVER ; then if grep -q -e "^sympa\ " ${postfix_master_cf} 2>> /dev/null ; then echo_skipped else cat <> ${postfix_master_cf} sympa unix - n n - - pipe flags=FR user=sympa argv=${SYMPA_LIBEXEC_DIR}/queue \${recipient} sympabounce unix - n n - - pipe flags=FR user=sympa argv=${SYMPA_LIBEXEC_DIR}/bouncequeue \${user} EOF if [ "$?" = "0" ]; then echo_ok else echo_failed error "Adding transport declaration for sympa domains to \"${postfix_master_cf}\" failed!" fi fi else echo_skipped fi ## - Install a cronjob for checking if mailservice is running.. ## - echononl " Install a cronjob for checking if mailservice is running.." crontab -l > /tmp/tmp_crontab if ! grep -q -E "/root/bin/monitoring/check_postfix.sh" /tmp/tmp_crontab 2> /dev/null ; then echo "" >> /tmp/tmp_crontab echo "# - Check if postfix mailservice is running. Restart service if needed." >> /tmp/tmp_crontab echo "# -" >> /tmp/tmp_crontab echo "*/5 * * * * /root/bin/monitoring/check_postfix.sh" >> /tmp/tmp_crontab crontab /tmp/tmp_crontab > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi ## - Install a cronjob that checks the LOG file for fatal errors.. ## - echononl " Install a cronjob that checks the LOG file for fatal errors.." crontab -l > /tmp/tmp_crontab if ! grep -q -E "/root/bin/postfix/check-postfix-fatal-errors.sh" /tmp/tmp_crontab 2> /dev/null ; then echo "" >> /tmp/tmp_crontab echo "# - Check Postfix E-Mail LOG file for 'fatal' errors.." >> /tmp/tmp_crontab echo "# -" >> /tmp/tmp_crontab echo "*/5 * * * * /root/bin/postfix/check-postfix-fatal-errors.sh" >> /tmp/tmp_crontab crontab /tmp/tmp_crontab > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi ## - restart postfix ## - echononl " Restart postfix" if $systemd_exists ; then systemctl restart postfix > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else /etc/init.d/postfix restart > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi fi ## - Omitt logging into system.log ## - echononl " Create \"/etc/rsyslog.d/postfix.conf\"" cat << EOF > /etc/rsyslog.d/postfix.conf # Create an additional socket in postfix's chroot in order not to break # mail logging when rsyslog is restarted. If the directory is missing, # rsyslog will silently skip creating the socket. \$AddUnixListenSocket /var/spool/postfix/dev/log # # Logging for the mail system. Split it up so that # it is easy to write scripts to parse these files. # #mail.info -/var/log/mail.info #mail.warn -/var/log/mail.warn #mail.err /var/log/mail.err mail.* -/var/log/mail.log & stop EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi echononl " Restart rsyslog daemon" if $systemd_exists ; then systemctl restart rsyslog > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi else /etc/init.d/rsyslog restart > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fi fi if ${LISTEN_ON_ADDITIONAL_RELAY_PORT} ; then echo "" warn "Please do not forget to allow incomming traffic on port \033[1m${ADDITIONAL_RELAY_LISTEN_PORT}\033[m. Check your firewall settings.." fi if [[ -n "$(which amavisd-new)" ]] ; then warn "You have to run \033[1minstall_amavis.sh\033[m script to continue the configuration." fi echo "" clean_up 0