Scripts
------
http://www.htt-consult.com/Centos7-mailserver.html
yum install httpd mod_ssl php mariadb-server php-mysql telnet
yum install dovecot dovecot-mysql dovecot-pigeonhole policycoreutils
yum install perl-MIME-EncWords perl-MIME-Charset php-imap
yum install perl-Email-Valid perl-Test-Pod
yum install perl-Mail-Sender imapsync offlineimap
yum install roundcubemail php-mcrypt php-enchant aspell-en
yum install spamassassin amavisd-new clamav clamav-devel perl-Convert-BinHex
yum install clamav-server clamav-update clamav-server-systemd clamav-scanner
http://sourceforge.net/projects/postfixadmin/
Let's assume that the current version you downloaded is: 3.2. Place it in /usr/share.
cd /usr/share
wget https://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-3.2/postfixadmin-3.2.tar.gz
tar -xzvf postfixadmin-3.2.tar.gz
mv postfixadmin-3.2/ postfixadmin
rm -f postfixadmin-3.2*
chown -R root:root postfixadmin
chmod 700 postfixadmin/templates/
chown apache:apache postfixadmin/templates/
sed -i -e "s';date.timezone ='date.timezone = $date_timezone'w /dev/stdout" /etc/php.ini
mkdir /home/vmail
chmod 770 /home/vmail
useradd -r -u 101 -g mail -d /home/vmail -s /sbin/nologin -c "Virtual mailbox" vmail
chown vmail:mail /home/vmail
chcon -Rv --type=mail_home_rw_t /home/vmail/
Setting up MariaDB
systemctl enable mariadb
systemctl start mariadb
mysql_secure_installation <<EOF || exit 1
y
$Mysql_Root_Password
$Mysql_Root_Password
y
y
y
y
EOF
postfixadmin.
mysql -u root -p$Mysql_Root_Password <<EOF || exit 1
CREATE DATABASE postfix;
CREATE USER postfix@localhost IDENTIFIED BY "$Postfix_Database_Password";
GRANT ALL PRIVILEGES ON postfix.* TO postfix@localhost;
EOF
Roundcube database.
mysql -u root -p$Mysql_Root_Password <<EOF || exit 1
CREATE DATABASE roundcubemail;
CREATE USER roundcube@localhost IDENTIFIED BY "$Roundcube_Database_Password";
GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost;
FLUSH PRIVILEGES;
EOF
mysql -u root -p$Mysql_Root_Password roundcubemail < /usr/share/roundcubemail/SQL/mysql.initial.sql
Setting up Apache
bind 'set disable-completion on'
cat <<EOF>/etc/httpd/conf.d/00-init.conf || exit 1
ServerAdmin $admin_email
ServerName $your_host_tld
<VirtualHost *:80>
<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:443>
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/$your_host_tld.crt
SSLCertificateKeyFile /etc/pki/tls/private/$your_host_tld.key
<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
EOF
bind 'set disable-completion off'
sed -i -e "s/all granted/ip 192.168.0.0\/16/gw /dev/stdout" /etc/httpd/conf.d/00-init.conf
postfixadmin's Apache conf file.
bind 'set disable-completion on'
cat <<EOF>/etc/httpd/conf.d/postfixadmin.conf || exit 1
alias /mailadmin /usr/share/postfixadmin/public
<Directory "/usr/share/postfixadmin/public">
AllowOverride AuthConfig
Require all granted
</Directory>
EOF
bind 'set disable-completion off'
Postfixadmin is a Security Risk; Postfixadmin access can be restricted to your IP addresses. Finer control can be added into a /usr/share/postfixadmin/.htaccess file.
sed -i -e "s/all granted/ip 192.168.0.0\/16/gw /dev/stdout" /etc/httpd/conf.d/postfixadmin.conf
Postfixadmin access is via 'http://your_host_tld/mailadmin'.
cp -b /etc/httpd/conf.d/roundcubemail.conf /etc/httpd/conf.d/roundcubemail.conf.save
bind 'set disable-completion on'
cat <<EOF>/etc/httpd/conf.d/roundcubemail.conf || exit 1
<VirtualHost *:80>
# Alias /roundcubemail /usr/share/roundcubemail
# Alias /webmail /usr/share/roundcubemail
ServerName webmail.$your_domain_tld
ServerAlias webmail
Redirect permanent / https://webmail.$your_domain_tld/
ExpiresDefault "access plus 1 years"
php_admin_flag session.cookie_secure "1"
</VirtualHost>
<VirtualHost *:443>
# Round Cube Webmail is a browser-based multilingual IMAP client
#
# Alias /roundcubemail /usr/share/roundcubemail
# Alias /webmail /usr/share/roundcubemail
ServerName webmail.$your_domain_tld
ServerAlias webmail
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/webmail.$your_domain_tld.crt
SSLCertificateKeyFile /etc/pki/tls/private/webmail.$your_domain_tld.key
DocumentRoot /usr/share/roundcubemail
<Directory /usr/share/roundcubemail/>
Require ip 192.168.0.0/16
# You can enlarge permissions once configured
# Require all granted
php_admin_flag session.cookie_secure "1"
</Directory>
</VirtualHost>
# Define who can access the installer
# keep this secured once configured
Alias /roundcubemail /usr/share/roundcubemail
<Directory /usr/share/roundcubemail/installer/>
# You may want to restrict the installer to a single IP address
Require ip 192.168.0.0/16
</Directory>
# Those directories should not be viewed by Web clients.
<Directory /usr/share/roundcubemail/bin/>
Require all denied
</Directory>
<Directory /usr/share/roundcubemail/plugins/enigma/home/>
Require all denied
</Directory>
EOF
bind 'set disable-completion off'
Last step for setting up Apache is creating the SSL certificates. Three certificates are needed. One for webmail.$your_domain_tld, another for $your_host_tld, and the third for localhost. Follow how you setup the roundcubemail.conf and how your users will access your server. The following commands will create the RSA 2048/SHA256 certificates with a 10 years life.
These are self-signed certificates. You can purchase your certificates from a recognized CA. You can find instructions on how to create your own CA and issue these certificates from it. Future work will add a section on using Let's Encrypt certificates.
restore_mask=$(umask -p)
umask 077
cd /etc/pki/tls
commonName=$your_host_tld
openssl req -new -outform PEM -out certs/$commonName.crt -newkey rsa:2048 -nodes -keyout private/$commonName.key -keyform PEM -days 3650 -x509 -extensions v3_req -subj "/countryName=$countryName/stateOrProvinceName=$stateOrProvinceName/localityName=$localityName/organizationName=$organizationName/organizationalUnitName=$organizationalUnitName/commonName=$commonName/emailAddress=$emailAddress"
chmod 640 private/$commonName.key
openssl req -new -outform PEM -out certs/localhost.crt -newkey rsa:2048 -nodes -keyout private/localhost.key -keyform PEM -days 3650 -x509 -extensions v3_req -subj "/countryName=$countryName/stateOrProvinceName=$stateOrProvinceName/localityName=$localityName/organizationName=$organizationName/organizationalUnitName=$organizationalUnitName/commonName=$commonName/emailAddress=$emailAddress"
chmod 640 private/localhost.key
commonName=webmail.$your_domain_tld
openssl req -new -outform PEM -out certs/$commonName.crt -newkey rsa:2048 -nodes -keyout private/$commonName.key -keyform PEM -days 3650 -x509 -extensions v3_req -subj "/countryName=$countryName/stateOrProvinceName=$stateOrProvinceName/localityName=$localityName/organizationName=$organizationName/organizationalUnitName=$organizationalUnitName/commonName=$commonName/emailAddress=$emailAddress"
chmod 640 private/$commonName.key
$restore_mask
openssl x509 -in certs/$commonName.crt -text -nameopt multiline -noout|more
systemctl enable httpd
systemctl start httpd
Configuring Postfix
Now on to configure the actual packages starting with Postfix.
Postfix is a real task to configure. It will be easier in versions of Postfix beyond 2.10 that is supplied in Centos 7. The following modifies the existing config files, rather than replacing them.
This is a 'best effort' from reviewing a number of sources.
The place to start is with main.cf. Note that message_size_limit limits a message to ~20Meg. Change this as needed.
cp /etc/postfix/main.cf /etc/postfix/main.cf.save
# postfix config file
# uncomment for debugging if needed
#postconf -e 'soft_bounce=yes'
# postfix main
postconf -e 'delay_warning_time = 4'
# network settings
postconf -e 'inet_interfaces = all'
postconf -e "mydomain = $your_domain_tld"
postconf -e "myhostname = $your_host_tld"
postconf -e 'mynetworks = $config_directory/mynetworks'
postconf -e 'relay_domains = proxy:mysql:/etc/postfix/mysql-relay_domains_maps.cf'
# mail delivery
postconf -e 'recipient_delimiter = +'
postconf -e 'content_filter = amavisfeed:[127.0.0.1]:10024'
# mappings
postconf -e 'alias_maps = hash:/etc/aliases'
postconf -e 'transport_maps = hash:/etc/postfix/transport'
# virtual setup
postconf -e 'virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_alias_maps.cf, regexp:/etc/postfix/virtual_regexp'
postconf -e 'virtual_mailbox_base = /home/vmail'
postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains_maps.cf'
postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf'
postconf -e 'virtual_minimum_uid = 101'
postconf -e 'virtual_uid_maps = static:101'
postconf -e 'virtual_gid_maps = static:12'
postconf -e 'virtual_transport = dovecot'
postconf -e 'dovecot_destination_recipient_limit = 1'
# authentication
postconf -e 'smtpd_sasl_auth_enable = yes'
# postconf -e 'smtpd_sasl_security_options = noanonymous'
postconf -e 'smtpd_sasl_local_domain = $mydomain'
postconf -e 'broken_sasl_auth_clients = yes'
postconf -e 'smtpd_sasl_type = dovecot'
postconf -e 'smtpd_sasl_path = private/auth'
# tls config
postconf -e 'smtp_use_tls = yes'
postconf -e 'smtp_tls_exclude_ciphers = RC4, aNULL'
postconf -e 'smtp_tls_loglevel = 1'
postconf -e 'smtp_tls_note_starttls_offer = yes'
postconf -e 'smtp_tls_protocols = !SSLv2, !SSLv3'
postconf -e 'smtp_tls_security_level = may'
postconf -e 'smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache'
postconf -e 'smtpd_tls_cert_file = /etc/pki/tls/certs/$myhostname.crt'
postconf -e 'smtpd_tls_exclude_ciphers = RC4, aNULL'
postconf -e 'smtpd_tls_key_file = /etc/pki/tls/private/$myhostname.key'
postconf -e 'smtpd_tls_loglevel = 1'
postconf -e 'smtpd_tls_mandatory_exclude_ciphers = aNULL, eNULL, EXPORT, DES, RC4, MD5, PSK, aECDH, EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CDC3-SHA, KRB5-DE5, CBC3-SHA'
postconf -e 'smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3'
postconf -e 'smtpd_tls_protocols = !SSLv2, !SSLv3'
postconf -e 'smtpd_tls_received_header = yes'
postconf -e 'smtpd_tls_security_level = may'
postconf -e 'smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache'
postconf -e 'smtpd_use_tls = yes'
# rules restrictions
postconf -e 'smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_recipient_domain'
postconf -e 'smtpd_sender_login_maps = mysql:/etc/postfix/mysql-virtual_alias_maps.cf'
# others
postconf -e 'smtpd_helo_required = yes'
postconf -e 'disable_vrfy_command = yes'
postconf -e 'message_size_limit = 20480000'
postconf -e 'smtpd_data_restrictions = reject_unauth_pipelining'
postconf -e 'smtpd_banner = $myhostname ESMTP'
master.cf is next.
cp /etc/postfix/master.cf /etc/postfix/master.cf.save
bind 'set disable-completion on'
cat <<\EOF>>/etc/postfix/master.cf || exit 1
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtpd pass - - n - - smtpd
submission inet n - n - - smtpd
-o smtpd_recipient_restrictions=
check_policy_service inet:127.0.0.1:12340
relay unix - - n - - smtp
-o fallback_relay=
maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient}
uucp unix - n n - - pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
ifmail unix - n n - - pipe
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp unix - n n - - pipe
flags=Fq. user=bsmtp argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient
#
# spam/virus section
#
amavisfeed unix - - y - 2 lmtp
-o lmtp_data_done_timeout=1200
-o lmtp_send_xforward_command=yes
-o disable_dns_lookups=yes
-o max_use=20
127.0.0.1:10025 inet n - n - - smtpd
-o content_filter=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o smtpd_restriction_classes=
-o mynetworks=127.0.0.0/8
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
-o local_header_rewrite_clients=
-o smtpd_milters=
-o local_recipient_maps=
-o relay_recipient_maps=
#
# Dovecot LDA
dovecot unix - n n - - pipe
flags=DRhu user=vmail:mail argv=/usr/libexec/dovecot/deliver -d ${recipient}
#
# Vacation mail
vacation unix - n n - - pipe
flags=Rq user=vacation argv=/var/spool/vacation/vacation.pl -f ${sender} -- ${recipient}
EOF
bind 'set disable-completion off'
And if you have to support Outlook TLS connections, then
bind 'set disable-completion on'
cat <<EOF>>/etc/postfix/master.cf || exit 1
# Enable only if you have to support Outlook TLS connections
smtps inet n - n - - smtpd
#
EOF
bind 'set disable-completion off'
Next a number of files in /etc/postfix
mynetworks
mysql-virtual_alias_maps.cf
mysql-virtual_domains_maps.cf
mysql-relay_domains_maps.cf
mysql-virtual_mailbox_maps.cf
virtual_regexp
cat <<EOF>/etc/postfix/mynetworks || exit 1
# This specifies the list of subnets that Postfix considers as
# "trusted" SMTP clients that have more privileges than "strangers".
#
# In particular, "trusted" SMTP clients are allowed to relay mail
# through Postfix.
#
# Be sure to add your public ip address block if needed.
#
192.168.0.0/16
10.0.0.0/8
127.0.0.0/8
EOF
cat <<EOF>/etc/postfix/mysql-virtual_alias_maps.cf || exit 1
hosts = localhost
user = postfix
password = $Postfix_Database_Password
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
EOF
cat <<EOF>/etc/postfix/mysql-virtual_domains_maps.cf || exit 1
hosts = localhost
user = postfix
password = $Postfix_Database_Password
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
EOF
cat <<EOF>/etc/postfix/mysql-relay_domains_maps.cf || exit 1
hosts = localhost
user = postfix
password = $Postfix_Database_Password
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = '1'
EOF
cat <<EOF>/etc/postfix/mysql-virtual_mailbox_maps.cf || exit 1
hosts = localhost
user = postfix
password = $Postfix_Database_Password
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
EOF
touch /etc/postfix/virtual_regexp
Edit /etc/postfix/mynetworks as needed,
The last step for postfix is the Vacation Email Functionality
useradd -r -d /var/spool/vacation -s /sbin/nologin -c "Virtual vacation" vacation
mkdir /var/spool/vacation
chmod 770 /var/spool/vacation
cp /usr/share/postfixadmin/VIRTUAL_VACATION/vacation.pl /var/spool/vacation/
echo "autoreply."$your_domain_tld" vacation:" > /etc/postfix/transport
postmap /etc/postfix/transport
chown -R vacation:vacation /var/spool/vacation
echo "127.0.0.1 autoreply."$your_domain_tld >> /etc/hosts
mkdir /etc/postfixadmin
And finally create /etc/postfixadmin/vacation.conf
cat <<\EOF>/etc/postfixadmin/vacation.conf || exit 1
# ========== begin configuration ==========
$db_type = 'mysql';
$db_username = 'user';
$db_password = 'postfixsqlpassword';
$db_name = 'postfix';
$vacation_domain = 'autoreply.change-this-to-your.domain.tld';
EOF
sed -i -e "s/postfixsqlpassword/$Postfix_Database_Password/w /dev/stdout" /etc/postfixadmin/vacation.conf
sed -i -e "s/change-this-to-your.domain.tld/$your_domain_tld/w /dev/stdout" /etc/postfixadmin/vacation.conf
systemctl restart postfix
Dovecot is next. There are a number of Dovecot conf files to edit. Instead, this guide uses the local.conf file which is loaded after the default conf files. By using the default files and local.conf, these modifications should work in future versions of Dovecot. The files altered by the local.conf are:
dovecot.conf
10-auth.conf
auth-sql.conf.ext
10-mail.conf
10-master.conf
10-ssl.conf
15-lda.conf
20-imap.conf
20-lmtp.conf
20-managesieve.conf
20-pop3.conf
90-acl.conf
90-quota.conf
90-sieve.conf
bind 'set disable-completion on'
cat <<EOF>/etc/dovecot/local.conf || exit 1
# Developed on Dovecot 2.2.36
# dovecot.conf
protocols = imap pop3 lmtp sieve
dict {
sqlquota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
}
service quota-status {
executable = quota-status -p postfix
inet_listener {
port = 12340
# You can choose any port you want
}
client_limit = 1
}
# 10-auth.conf
!include conf.d/auth-sql.conf.ext
# auth-sql.conf.ext
userdb {
driver = prefetch
}
# 10-mail.conf
mail_location = maildir:/home/vmail/%d/%n
first_valid_uid = 101
first_valid_gid = 12
# Space separated list of plugins to load for all services. Plugins specific to
# IMAP, LDA, etc. are added to this list in their own .conf files.
mail_plugins = $mail_plugins quota
mailbox_list_index = yes
# Avoid spending excessive time waiting for the quota calculation to finish when
# mails' vsizes aren't already cached. If this many mails are opened, finish the
# quota calculation on background in indexer-worker process. Mail deliveries will
# be assumed to succeed, and explicit quota lookups will return internal error.
mail_vsize_bg_after_count = 100
# 10-master.conf
service auth {
unix_listener auth-userdb {
mode = 0666
user = vmail
group = mail
}
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
}
service dict {
unix_listener dict {
mode = 0666
user = vmail
group = mail
}
}
# 10-ssl.conf
ssl_cert = </etc/pki/tls/certs/$your_host_tld.crt
ssl_key = </etc/pki/tls/private/$your_host_tld.key
# 15-lda.conf
postmaster_address = postmaster@$your_domain_tld
protocol lda {
mail_plugins = quota sieve
}
lda_mailbox_autocreate = yes
lda_mailbox_autosubscribe = yes
# 20-imap.conf
imap_client_workarounds = delay-newmail
protocol imap {
# Space separated list of plugins to load (default is global mail_plugins).
mail_plugins = $mail_plugins imap_quota trash
}
# 20-lmtp.conf
lmtp_save_to_detail_mailbox = yes
protocol lmtp {
mail_plugins = sieve
}
# 20-managesieve.conf
service managesieve-login {
inet_listener sieve {
port = 4190
}
service_count = 1
process_min_avail = 0
vsz_limit = 64M
}
# 20-pop3.conf
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
protocol pop3 {
mail_plugins = quota
}
# 90-acl.conf
plugin {
acl = vfile:/etc/dovecot/global-acls:cache_secs=300
}
# 90-quota.conf
plugin {
quota = dict:user::proxy::sqlquota
trash = /etc/dovecot/dovecot-trash.conf.ext
}
plugin {
quota_grace = 10%%
# 10% is the default
quota_status_success = DUNNO
quota_status_nouser = DUNNO
quota_status_overquota = "552 5.2.2 Mailbox is full"
}
# 90-sieve.conf
plugin {
sieve_before = /home/sieve/globalfilter.sieve
}
EOF
bind 'set disable-completion off'
Next the following files are added into /etc/dovecot
dovecot-trash.conf.ext
dovecot-sql.conf.ext
dovecot-dict-sql.conf.ext
Note that the user_query limits an imap mailbox to 30,000 messages. Change this as needed.
mv /etc/dovecot/dovecot-trash.conf.ext /etc/dovecot/dovecot-trash.conf.ext.save
mv /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.save
mv /etc/dovecot/dovecot-dict-sql.conf.ext /etc/dovecot/dovecot-dict-sql.conf.ext.save
bind 'set disable-completion on'
cat <<EOF>/etc/dovecot/dovecot-trash.conf.ext || exit 1
# Spam mailbox is emptied before Trash
1 Spam
# Trash mailbox is emptied before Sent
# 2 Trash
# If both Sent and "Sent Messages" mailboxes exist, the next oldest message
# to be deleted is looked up from both of the mailboxes.
# 3 Sent
# 3 Sent Messages
EOF
cat <<EOF>/etc/dovecot/dovecot-sql.conf.ext || exit 1
driver = mysql
connect = host=/var/lib/mysql/mysql.sock dbname=postfix user=postfix password=$Postfix_Database_Password
default_pass_scheme = $cryptsha-CRYPT
# following should all be on one line.
password_query = SELECT username as user, password, concat('/home/vmail/', maildir) as userdb_home, concat('maildir:/home/vmail/', maildir) as userdb_mail, 101 as userdb_uid, 12 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
# following should all be on one line
user_query = SELECT concat('/home/vmail/', maildir) as home, concat('maildir:/home/vmail/', maildir) as mail, 101 AS uid, 12 AS gid, CONCAT('*:messages=30000:bytes=', quota) as quota_rule FROM mailbox WHERE username = '%u' AND active = '1'
EOF
cat <<EOF>/etc/dovecot/dovecot-dict-sql.conf.ext || exit 1
connect = host=/var/lib/mysql/mysql.sock dbname=postfix user=postfix password=$Postfix_Database_Password
map {
pattern = priv/quota/storage
table = quota2
username_field = username
value_field = bytes
}
map {
pattern = priv/quota/messages
table = quota2
username_field = username
value_field = messages
}
EOF
bind 'set disable-completion off'
Now create the sieve filter for SPAM filtering
bind 'set disable-completion on'
mkdir /home/sieve
cat <<EOF>/home/sieve/globalfilter.sieve || exit 1
require "fileinto";
if anyof
(
header :contains "X-Spam-Flag" "YES",
header :contains "subject" "***SPAM***"
)
{
fileinto "Spam";
}
EOF
bind 'set disable-completion off'
sievec /home/sieve/globalfilter.sieve
chown -R vmail:mail /home/sieve
chcon -Rv --type=mail_home_rw_t /home/sieve/
SELinux needs a policy to allow Dovecot to access the mysql unix socket. As of Feb 5, 2019, this policy has been rolled into Fedora 28 and up, and in time will be included in CentOS.
bind 'set disable-completion on'
cat <<\EOF>dovecot_mysql.te || exit 1
policy_module(dovecot_mysql,1.0.0)
gen_require(`
type dovecot_t;
')
mysql_read_config(dovecot_t)
mysql_stream_connect(dovecot_t)
EOF
bind 'set disable-completion off'
make -f /usr/share/selinux/devel/Makefile dovecot_mysql.pp
semodule -i dovecot_mysql.pp
systemctl enable dovecot
systemctl start dovecot
Configuring Amavis and Clamav
These two packages work together, along with Spamassassin, to provide anti-spam and anti-virus protection. Their configuration is simple.
With some guidance from https://ismailyenigul.wordpress.com/2015/01/05/install-clamav-on-centos-7/
And more from http://forums.sentora.org/showthread.php?tid=1132
We can get clamav working with the following:
cp /etc/clamd.d/scan.conf /etc/clamd.d/scan.conf.save
cp /etc/freshclam.conf /etc/freshclam.conf.save
sed -i -e "s/^Example/#Example/w /dev/stdout" /etc/freshclam.conf
sed -i -e "s/^Example/#Example/w /dev/stdout" /etc/clamd.d/scan.conf
sed -i -e "s/clamd.scan /clamd.amavisd /w /dev/stdout" /etc/clamd.d/scan.conf
sed -i -e "s/^#LocalSocket /LocalSocket /w /dev/stdout" /etc/clamd.d/scan.conf
sed -i -e "s/^FRESHCLAM_DELAY/#FRESHCLAM_DELAY/w /dev/stdout" /etc/sysconfig/freshclam
setsebool -P antivirus_can_scan_system 1
setsebool -P clamd_use_jit 1
freshclam
Next edit /etc/amavisd/amavisd.conf.
cp /etc/amavisd/amavisd.conf /etc/amavisd/amavisd.conf.save
cat <<\EOF>>/etc/amavisd/amavisd.conf || exit 1
$mydomain = 'your_domain_tld';
$myhostname = 'your_host_tld'; # must be a fully-qualified domain name!
$log_level = 1; # set the log level to one
$sa_tag_level_deflt = -99; # I want to see the headers so change to -99
$sa_tag2_level_deflt = 5.0; # start with 5
$sa_kill_level_deflt = 9;
$sa_dsn_cutoff_level = 9;
$sa_quarantine_cutoff_level = 50;
$notify_method = 'smtp:[127.0.0.1]:10025';
$forward_method = 'smtp:[127.0.0.1]:10025';
$final_banned_destiny = D_BOUNCE;
$final_spam_destiny = D_PASS;
@mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10
10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 your_ipv4_address_block);
@lookup_sql_dsn =
( ['DBI:mysql:database=postfix;host=localhost;mysql_socket=/var/lib/mysql/mysql.sock', 'postfix', 'postfixsqlpassword'] );
$sql_select_white_black_list = undef;
$sql_select_policy = 'SELECT "Y" as local, 1 as id FROM domain WHERE CONCAT("@",domain) IN (%k)';
1; # insure a defined return value
EOF
sed -i -e "s/your_domain_tld/$your_domain_tld/w /dev/stdout" /etc/amavisd/amavisd.conf
sed -i -e "s/your_host_tld/$your_host_tld/w /dev/stdout" /etc/amavisd/amavisd.conf
sed -i -e "s/your_ipv4_address_block/$your_ipv4_address_block/w /dev/stdout" /etc/amavisd/amavisd.conf
sed -i -e "s/postfixsqlpassword/$Postfix_Database_Password/w /dev/stdout" /etc/amavisd/amavisd.conf
Finally start it all:
gpasswd -a clamscan amavis
sa-update
systemctl enable amavisd
systemctl enable spamassassin
systemctl stop postfix
systemctl start spamassassin
systemctl start amavisd # This will also run ClamAV
systemctl start postfix
A simple test of clamav is
clamdscan -c /etc/clamd.d/scan.conf /etc/hosts
Test the amavis connection with
telnet localhost 10024
ehlo localhost
quit
telnet localhost 10025
ehlo localhost
quit
Configuring Postfixadmin
Postfixadmin is the email domain and email account management tool.
Create a base /usr/share/postfixadmin/config.local.php
bind 'set disable-completion on'
cat <<\EOF>/usr/share/postfixadmin/config.local.php || exit 1
<?php
/**
* Contains configuration options that override the default config file
*/
/*****************************************************************
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* You have to set \$CONF['configured'] = true; before the
* application will run!
* Doing this implies you have changed this file as required.
* i.e. configuring database etc; specifying setup.php password etc.
*/
$CONF['configured'] = true;
// In order to setup Postfixadmin, you MUST specify a hashed password here.
// To create the hash, visit /postfixadmin/setup.php in a browser and type a password into the field,
// on submission it will be echoed out to you as a hashed value.
$CONF['setup_password'] = 'changeme';
$CONF['database_password'] = 'postfixsqlpassword';
// Default Aliases
// The default aliases that need to be created for all domains.
$CONF['default_aliases'] = array (
'abuse' => 'abuse@change-this-to-your.domain.tld',
'hostmaster' => 'hostmaster@change-this-to-your.domain.tld',
'postmaster' => 'postmaster@change-this-to-your.domain.tld',
'webmaster' => 'webmaster@change-this-to-your.domain.tld'
);
$CONF['admin_email'] = 'postfixadmin_email';
$CONF['dovecotpw'] = "/usr/bin/doveadm pw";
$CONF['page_size'] = '20';
$CONF['aliases'] = '50';
$CONF['mailboxes'] = '50';
$CONF['maxquota'] = '100';
$CONF['transport'] = 'YES';
$CONF['vacation'] = 'YES';
$CONF['vacation_domain'] = 'autoreply.change-this-to-your.domain.tld';
$CONF['special_alias_control'] = 'YES';
$CONF['footer_text'] = 'Return to change-this-to-your.domain.tld';
$CONF['footer_link'] = 'http://change-this-to-your.domain.tld';
$CONF['create_mailbox_subdirs']=array('Drafts','Spam','Sent','Trash');
$CONF['create_mailbox_subdirs_host']='localhost';
$CONF['create_mailbox_subdirs_prefix']='';
$CONF['quota'] = 'YES';
$CONF['used_quotas'] = 'YES';
$CONF['new_quota_table'] = 'YES';
// $CONF['create_mailbox_subdirs_hostoptions']=array('notls');
$CONF['create_mailbox_subdirs_hostoptions']=array('novalidate-cert','norsh');
$CONF['encrypt'] = 'dovecot:cryptsha-CRYPT';
$CONF['dovecotpw'] = "/usr/bin/doveadm pw ";
//
// END OF CONFIG FILE
//
?>
EOF
bind 'set disable-completion off'
sed -i -e "s/postfixadmin_email/$admin_email/w /dev/stdout" /usr/share/postfixadmin/config.local.php
sed -i -e "s/postfixsqlpassword/$Postfix_Database_Password/w /dev/stdout" /usr/share/postfixadmin/config.local.php
sed -i -e "s/cryptsha/$cryptsha/w /dev/stdout" /usr/share/postfixadmin/config.local.php
sed -i -e "s/change-this-to-your.domain.tld/$your_domain_tld/gw /dev/stdout" /usr/share/postfixadmin/config.local.php
SELinux seems to be a problem for Postfixadmin (and Roundcubemail which needs the setsebool).
chcon -R -t httpd_sys_content_rw_t /usr/share/postfixadmin/templates
setsebool -P httpd_can_network_connect on
Now go to host/mailadmin/setup.php
Configuring Roundcubemail
chown root:apache /etc/roundcubemail
chmod 775 /etc/roundcubemail
Roundcubemail is written in php and a couple php defaults may not be right for Roundcubemail, particularly the file upload size and message size maximums. The following will comment out the defaults and add new maximums. Change them as you need.
sed -i -e "/^upload_max_filesize/s/^/#/w /dev/stdout" /etc/php.ini
sed -i -e '/^#upload_max_filesize/ a upload_max_filesize = 5M' /etc/php.ini
sed -i -e "/^post_max_size/s/^/#/w /dev/stdout" /etc/php.ini
sed -i -e '/^#post_max_size/ a post_max_size = 20M' /etc/php.ini
http://*FQDN*/roundcubemail/installer
If in your system 0 quota means no limit
cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1
$config['quota_zero_as_unlimited'] = true;
EOF
To allow browser-autocompletion of username and host on login form.
cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1
$config['login_autocomplete'] = 1;
EOF
To directly delete messages in Junk instead of moving to Trash.
cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1
$config['delete_junk'] = true;
EOF
This quide uses 'Spam' for the 'Junk' folder. To force Roundcubemail to display 'Spam', rather than 'Junk' as default.
cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1
$config['show_real_foldernames'] = true;
EOF
Apache is configured to redirect to secure connections. Roundcubemail can check and redirect if the Apache configuration is wrong with:
cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1
$config['force_https'] = true;
EOF
Now we set up the manage sieve plugin.
cp /usr/share/roundcubemail/plugins/managesieve/config.inc.php.dist /usr/share/roundcubemail/plugins/managesieve/config.inc.php
For the password plugin:
cp /usr/share/roundcubemail/plugins/password/config.inc.php.dist /usr/share/roundcubemail/plugins/password/config.inc.php
cat <<\EOF>>/usr/share/roundcubemail/plugins/password/config.inc.php || exit 1
$config['password_db_dsn'] = 'mysql://postfix:postfixsqlpassword@localhost/postfix';
$config['password_query'] = 'UPDATE mailbox SET password=%c WHERE username=%u limit 1;';
EOF
sed -i -e "s/postfixsqlpassword/$Postfix_Database_Password/w /dev/stdout" /usr/share/roundcubemail/plugins/password/config.inc.php
systemctl restart httpd
For more on Dovecot testing see
http://wiki.dovecot.org/TestInstallation
For anti-virus testing, find sample.tar.gz.compl (check the version of amavisd-new) and change to that folder and untar it
cd /usr/share/doc/amavisd-new-2.11.1/test-messages
perl -pe 's/./chr(ord($&)^255)/sge' <sample.tar.gz.compl | zcat | tar xvf -
Then send the following emails. virus-sample should be dropped, GTUBE should be moved to Spam, and README should end up in INBOX.
sendmail -i useremail < sample-virus-simple.txt
sendmail -i useremail < sample-spam-GTUBE-junk.txt
sendmail -i useremail < README
Updated 06/19/2019
-----