Files
shell_sequencer/seqs/mailserver.sh

456 lines
15 KiB
Bash
Executable File

#!/bin/bash
# Installing a mailserver including postfix postfixadmin and dovecot
#
# MTA = Mail Transport Agent (postfix)
# MDA = Mail Delivery Agent (dovecot)
# MUA = Mail User Agent (Mail program used by the user)
readonly toolName=mailserver
readonly mtaName=postfix
readonly mtaUser=postfix
readonly mtaDeps="$mtaName $mtaName-mysql"
readonly mtaConfLoc="/etc/$mtaName"
readonly mtaMysqlConfLoc="$mtaConfLoc/sql"
readonly mdaName=dovecot
readonly mdaConfLoc="/etc/$mdaName"
readonly mdaConfDir="$mdaConfLoc/conf.d"
readonly mdaDeps="dovecot-imapd dovecot-lmtpd dovecot-mysql dovecot-managesieved dovecot-sieve"
sq_aptOpt=
sq_config=0
seq_config() {
root || endReturn -o 1 "No root"
#initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if initSeqConfig "${seq_configName:?}" "${seq_configTemplate:?}" ; then
sq_config=1
info " Domain: ${MAS_DOMAIN:-}"
else
dry || return 1
fi
## Apt cmdline option to suppress user interaction
interactive || sq_aptOpt="-y"
return 0
}
step_1_info() { echo "Update apt repositories"; }
step_1_alias() { echo "install"; }
step_1() {
exe apt update
}
step_2_info() { echo "Install $mtaName"; }
step_2() {
confirm -n -y "In the following dialog chose \"Internet site\" and enter $MAS_DOMAIN as your domain. Enter to continue..."
exe apt install $mtaDeps ${sq_aptOpt:-}
}
step_3_info() { echo "Enable $mtaName"; }
step_3() {
exe systemctl enable $mtaName
info "Printing $mtaName status"
exe service $mtaName status
info "Installed postfix version: $(postconf mail_version)"
}
step_4_info() { echo "$mtaName basic domain configuration"; }
step_4() {
exe postconf -e "myhostname = mail.$MAS_DOMAIN"
exe postconf -e "mydomain = $MAS_DOMAIN"
exe postconf -e "myorigin = $MAS_DOMAIN"
exe postconf -e "mydestination = $MAS_DOMAIN, \$myhostname, mail.\$mydomain, localhost.\$mydomain, localhost"
}
step_5_info() { echo "$mtaName enable submission service"; }
step_5() {
local mtaConfSubmission="${seq_origin:?}/$toolName/submissionService"
local mtaConfSmtps="${seq_origin:?}/$toolName/smtpsService"
info "Copy following lines..."
exe cat "$mtaConfSubmission"
confirm -n -y "Press Enter to open the $mtaConfLoc/master.cf"
editor $mtaConfLoc/master.cf
info
exe cat "$mtaConfSmtps"
confirm -n -y "Press Enter to open the $mtaConfLoc/master.cf"
editor $mtaConfLoc/master.cf
}
step_6_info() { echo "Configure TLS"; }
step_6() {
exe postconf "smtpd_tls_cert_file = /etc/letsencrypt/live/$MAS_DOMAIN/fullchain.pem"
exe postconf "smtpd_tls_key_file = /etc/letsencrypt/live/$MAS_DOMAIN/privkey.pem"
#Force TLSv1.3 or TLSv1.2
exe postconf "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
exe postconf "smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
exe postconf "smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
exe postconf "smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
info "Restarting $mtaName"
exe service $mtaName restart
}
step_7_info() {
echo "Restrict client access"
echoinfo "Mainly PTR record check"
}
step_7() {
exe postconf -e "smtpd_client_restrictions = permit_mynetworks, reject_unknown_client_hostname"
}
step_8_info() { echo "Install $mdaName"; }
step_8() {
exe apt install $mdaDeps ${sq_aptOpt}
info "Installed version: $(dovecot --version)"
}
step_9_info() {
echo "Configure $mdaName"
}
step_9() {
color green
cat <<MDA_EOF
# Configuring Mailbox Location
[/etc/dovecot/conf.d/10-mail.conf]
mail_location = maildir:~/Maildir
mail_privileged_group = mail
usermod -aG mail dovecot
# Configuring Authentication Mechanism
[/etc/dovecot/conf.d/10-auth.conf]
disable_plaintext_auth = yes
# Login with full mail address
auth_username_format = %n
# "login" to support older mail clients
auth_mechanisms = plain login
# Configure SSL/TLS Encryption
[/etc/dovecot/conf.d/10-ssl.conf]
ssl = required
ssl_cert = </etc/letsencrypt/live/$MAS_DOMAIN/fullchain.pem
ssl_key = </etc/letsencrypt/live/$MAS_DOMAIN/privkey.pem
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
ssl_dh = </etc/dovecot/dh.pem
openssl dhparam -out /etc/dovecot/dh.pem 4096
# SASL Authentication Between Postfix and Dovecot
[/etc/dovecot/conf.d/10-master.conf]
# Add to service auth {
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0600
user = postfix
group = postfix
}
}
# Auto-subscribe Drafts, Sent, Junk and Trash Folder
and auto delete after 30 days
[/etc/dovecot/conf.d/15-mailboxes.conf]
# Add "auto = create" to folder e.g.:
mailbox Trash {
auto = subscribe
autoexpunge = 30d
special_use = \\Trash
}
# Using Dovecot to Deliver Email to Message Store
Make sure lmtp protocol is installed with dovecot-lmtp
[/etc/dovecot/conf.d/10-master.conf]
# Change lmtp service definition to:
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
postconf -e "mailbox_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "smtputf8_enable = no"
# Clean outgoing mail header from sensitiv information
[/etc/postfix/master.cf]
smtps inet n - y - - smtpd
[...]
-o cleanup_service_name=headclean
#add below "cleanup"
headclean unix n - - - 0 cleanup
-o header_checks=regexp:/etc/postfix/sender_header_checks
[/etc/postfix/sender_header_checks]
/^Received:/ IGNORE
/^X-PHP-Originating-Script:/ IGNORE
/^X-Originating-IP:/ IGNORE
/^X-Mailer:/ IGNORE
/^User-Agent:/ IGNORE
MDA_EOF
}
step_20_info() {
echo "Install postfixadmin and create mysql database"
echoinfo "Virtualize mailboxes, domains and aliases by using a mysql database"
}
step_20_alias() { echo "virtual"; }
step_20() {
exe ${seq_origin:?}/postfixadmin.sh ${sqr_args} install
}
step_21_info() { echo "Create $mtaName mysql query files"; }
step_21() {
exe mkdir -p "$mtaMysqlConfLoc"
local mtaFile
local mtaVar
local mtaMysqlFiles=(\
"mysql_virtual_domains_maps"\
"mysql_virtual_mailbox_maps"\
"mysql_virtual_alias_domain_mailbox_maps"\
"mysql_virtual_alias_maps"\
"mysql_virtual_alias_domain_maps"\
"mysql_virtual_alias_domain_catchall_maps"\
)
for mtaFile in ${mtaMysqlFiles[@]} ; do
mtaVar="MAS_${mtaFile}"
info "creating ${mtaFile}.cf"
exep echo -e "\"${MAS_VIRTUAL_USER_PART:?}\\n${!mtaVar:?}\"" \> \"$mtaMysqlConfLoc/${mtaFile}.cf\"
done
exe chown -R root:${mtaUser} "$mtaMysqlConfLoc"
exe chmod 640 "${mtaMysqlConfLoc}"/*
}
step_22_info() { echo "Modify $mtaName configuration for virtual mailboxes"; }
step_22() {
exe postconf -e "virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf"
exe postconf -e "virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf"
exe postconf -e "virtual_alias_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf"
exe postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
# Apex domain removed, it is handled as virtual domain now
exe postconf -e "mydestination = \$myhostname, localhost.\$mydomain, localhost"
# Base location for the virtual maildirs
exe postconf -e "virtual_mailbox_base = $MAS_VIRTUAL_FOLDER_BASE"
exe postconf -e "virtual_minimum_uid = $MAS_VIRTUAL_USER_ID"
exe postconf -e "virtual_uid_maps = static:$MAS_VIRTUAL_USER_ID"
exe postconf -e "virtual_gid_maps = static:$MAS_VIRTUAL_USER_ID"
}
step_23_info() { echo "Create virtual user ${MAS_VIRTUAL_USER:-} and folder ${MAS_VIRTUAL_FOLDER_BASE:-}"; }
step_23() {
exe mkdir -p "$MAS_VIRTUAL_FOLDER_BASE"
exe groupadd --gid $MAS_VIRTUAL_USER_ID $MAS_VIRTUAL_USER
exe adduser --disabled-login --disabled-password --home "$MAS_VIRTUAL_FOLDER_BASE" --uid $MAS_VIRTUAL_USER_ID --gid $MAS_VIRTUAL_USER_ID $MAS_VIRTUAL_USER
exe chown -R ${MAS_VIRTUAL_USER}: "$MAS_VIRTUAL_FOLDER_BASE"
exe chmod -R 770 "$MAS_VIRTUAL_FOLDER_BASE"
info "Restarting $mtaName"
exe service $mtaName restart
}
step_24_info() { echo "$mdaName virtualisation configuration instructions"; }
step_24() {
color green
cat <<END_STEP24
# Configuring Mailbox Location
[/etc/dovecot/conf.d/10-mail.conf]
mail_location = maildir:~/Maildir
mail_home = ${MAS_VIRTUAL_FOLDER_BASE}/%d/%n
# Configure authentication
[/etc/dovecot/conf.d/10-auth.conf]
# Username with domain
auth_username_format = %u
# Find and uncomment following line
!include auth-sql.conf.ext
# Comment following line to prevent local users from sending mail
# without having registered an email address
#!include auth-system.conf.ext
# Debug login issues in /var/log/maillog by adding:
auth_debug = yes
auth_debug_passwords = yes
# Adding mysql login information
[/etc/dovecot/dovecot-sql.conf.ext]
driver = mysql
connect = host=$MAS_DBHOST dbname=$MAS_DBNAME user=$MAS_DBUSER password='${MAS_DBPASS}'
default_pass_scheme = MD5
password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active='1'
user_query = SELECT maildir, $MAS_VIRTUAL_USER_ID AS uid, $MAS_VIRTUAL_USER_ID AS gid FROM mailbox WHERE username = '%u' AND active='1'
iterate_query = SELECT username AS user FROM mailbox
END_STEP24
}
step_25_info() {
echo "Configure sieve for virtual users"
}
step_25() {
color green
cat << END_STEP25
# Sieve script configuration
[$mdaConfDir/90-sieve.conf]
sieve = file:/var/vmail/%d/%n/sieve;active=/var/vmail/%d/%n/.dovecot.sieve
sieve_extensions = +notify +imapflags +vnd.dovecot.execute
sieve_plugins = sieve_extprograms
sieve_user_log = file:/var/vmail/%d/%n/sieve/sieve.log
# Enable sieve for lmtp
[$mdaConfDir/20-lmtp.conf]
postmaster_address = postmaster@$MAS_DOMAIN
mail_plugins = \$mail_plugins sieve
# Enable excution of external programs (e.g. to send xmpp messages on certain keywords)
[$mdaConfDir/90-sieve-extprograms.conf]
sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute
# Notes on execution of scripts
* Scripts are executed with the $MAS_VIRTUAL_USER user
* Scripts must no be writeable by others
(chown root:$MAS_VIRTUAL_USER script; chmod 750 script)
* \$HOME is set to the virtual users home
(e.g. /var/vmail/$MAS_DOMAIN/max)
# Notes about sendxmpp
* .sendxmpprc resides in every virtual users home
and must be owned by $MAS_VIRTUAL_USER
(chown $MAS_VIRTUAL_USER: .sendxmpprc; chmod 700 .sendxmpprc)
END_STEP25
}
step_50_info() { echo "Adding default relay host for sending mails"; }
step_50_alias() { echo "default_relay"; }
step_50() {
if [ ! -f "$saslPassFile" ] ; then
exe postconf -e "relayhost = $MAS_RELAYHOST"
exe postconf -e "smtp_sasl_auth_enable = yes"
exe postconf -e "smtp_sasl_password_maps = hash:$saslPassFile"
addConf -s "$MAS_RELAYHOST $MAS_RELAYUSER:$MAS_RELAYPASS" "$saslPassFile"
fi
info "Updating $saslPassFile"
exe postmap "$saslPassFile"
}
saslPassFile="$mtaConfLoc/sasl_password"
step_52_info() {
echo "Grant access for specific (local) hostnames"
echoinfo "Workaround when local clients connect to 25 with different ips (v6)"
}
step_52_alias() { echo "client_access"; }
step_52() {
if [ ! -f "$mtaClientAccessLoc" ] ; then
info "Generating $mtaClientAccessLoc"
exep echo "# myhost.lan OK" \> "$mtaClientAccessLoc"
info "Don't forget to add the following"
info -a "[$mtaConfLoc/main.cf]"
info -a " smtpd_relay_restrictions ="
info -a " check_client_access hash:$mtaClientAccessLoc"
fi
info "Updating $mtaClientAccessLoc"
exe postmap "$mtaClientAccessLoc"
}
mtaClientAccessLoc="$mtaConfLoc/client_access"
step_54_info() {
echo "Deny recipient access for listed mail addresses"
}
step_54_alias() { echo "recipient_access"; }
step_54() {
if [ ! -f "$mtaRecipientAccessLoc" ] ; then
info "Generating $mtaRecipientAccessLoc"
exep "echo \"# unwanted@${MAS_DOMAIN} 550 No mailbox. Nothing to see here.\" > \"$mtaRecipientAccessLoc\""
info "Don't forget to add the following"
info -a "[$mtaConfLoc/main.cf]"
info -a " smtpd_recipient_restrictions ="
info -a " check_recipient_access hash:$mtaRecipientAccessLoc"
fi
info "Updating $mtaRecipientAccessLoc"
exe postmap "$mtaRecipientAccessLoc"
}
mtaRecipientAccessLoc="$mtaConfLoc/recipient_access"
step_56_info() { echo "Add sender dependant relay with authentication"; }
step_56_alias() { echo "sender_relay"; }
step_56() {
if [ ! -f "$mtaSenderRelayLoc" ] ; then
info "Generating $mtaSenderRelayLoc"
exep "echo \"# user@extern.com smtp:[mail.extern.com]:587\" > \"$mtaSenderRelayLoc\""
exe postconf -e "smtp_sender_dependent_authentication = yes"
exe postconf -e "sender_dependent_relayhost_maps = hash:$mtaSenderRelayLoc"
exe postconf -e "smtp_sasl_security_options = noanonymous"
exe postconf -e "smtp_sasl_mechanism_filter = plain"
exe postconf -e "smtp_tls_security_level = encrypt"
exe postconf -e "smtp_tls_mandatory_ciphers = high"
info "Don't forget to add credentials for the new relay"
info -a "[$saslPassFile]"
info -a " user@extern.com username:passwort"
info -a "postmap $saslPassFile"
fi
info "Updating $mtaSenderRelayLoc"
exe postmap "$mtaSenderRelayLoc"
exe postmap "$saslPassFile"
}
mtaSenderRelayLoc="$mtaConfLoc/sender_relay"
step_100_info() {
echo "Send testmail [-u SYSTEMUSER | -f FROM] [TO]"
echoinfo "Send as current user to postmaster@\$MAS_DOMAIN by default"
}
step_100_alias() { echo "test"; }
step_100() {
shift
local fromAdr
local toAdr="postmaster@$MAS_DOMAIN"
local asUser=
for _ in "$@" ; do
case "$1" in
-f)
shift
fromAdr="-f ${1:-} "
shift ;;
-u)
shift
asUser="sudo -u ${1:-} "
shift ;;
*)
break ;;
esac
done
[ -n "${1:-}" ] && toAdr="$1"
exe ${asUser}sh -c "echo \"Subject: Test from Postfix\nIt is \$(date)\n\nGreetings \$(whoami)\" | sendmail ${fromAdr:-}${toAdr}"
}
step_102_info() { echo "Show mail queue"; }
step_102_alias() { echo "showqueue"; }
step_102() {
exe sendmail -bp
}
step_104_info() {
echo "Delete mail queue [ID]"
echoinfo "Delete all queued mails if [ID] is empty"
}
step_104_alias() { echo "delqueue"; }
step_104() {
shift
local msgId="ALL"
[ -n "${1:-}" ] && msgId="$1"
exe postsuper -d "$msgId"
}
# shellcheck disable=SC2034 # Appears unused
readonly sqr_minVersion=16
# shellcheck disable=SC1091 # Don't follow this source
. /usr/local/bin/sequencer.sh