Professional Documents
Culture Documents
Mail Server Setup - With PMG - Alma9
Mail Server Setup - With PMG - Alma9
Table of Contents
Prerequisites ................................................................................................................................................................................ 4
How an Email server works .......................................................................................................................................................... 5
System Environment Setup.......................................................................................................................................................... 6
Disabling SELinux ..................................................................................................................................................................... 6
FIREWALL Configuration .......................................................................................................................................................... 6
Changing SSH port ................................................................................................................................................................... 7
Date and Time ......................................................................................................................................................................... 8
Set hostname and package update ......................................................................................................................................... 8
DNS Setup for mail Server ........................................................................................................................................................... 9
Installation and Configuration of Postfix ..................................................................................................................................... 9
Mysql Database Setup ............................................................................................................................................................... 12
Installation and Configuration of Dovecot ................................................................................................................................. 13
Installation and Configuration of NGINX with Certbot .............................................................................................................. 16
Prerequisites.......................................................................................................................................................................... 16
Install NGINX and Certbot ..................................................................................................................................................... 16
Set up NGINX ......................................................................................................................................................................... 16
Obtain the SSL/TLS Certificate ............................................................................................................................................... 18
Automating Renewal ............................................................................................................................................................. 18
Installation and Configuration of Roundcube ............................................................................................................................ 19
PHP 8.0 setup in AlmaLinux ................................................................................................................................................... 19
Set up Roundcube ................................................................................................................................................................. 20
Installation and Configuration of ViMbAdmin ........................................................................................................................... 24
Set up ViMbAdmin ................................................................................................................................................................ 25
Setup nginx for ViMbAdmin .................................................................................................................................................. 26
MAIL GATEWAY ......................................................................................................................................................................... 29
DNS Setup for Mail Gateway ................................................................................................................................................. 29
Set Up Proxmox Mail Gateway (PMG)................................................................................................................................... 30
Basic Configuration via GUI ................................................................................................................................................... 35
Integrating Mail Server with Gateway................................................................................................................................... 39
How to Enhance Email Deliverability and Security .................................................................................................................... 40
SPF (Sender Policy Framework) ............................................................................................................................................. 40
Adding SPF records to DNS (For outgoing mails) .............................................................................................................. 40
Adding SPF policy agent to Postfix (For Incoming mails) .................................................................................................. 41
DKIM (Domain Keys Identified Mail) ..................................................................................................................................... 42
Setting up OpenDKIM Package ......................................................................................................................................... 43
2
Hook OpenDKIM into Postfix ............................................................................................................................................ 46
Adding DNS Record for DKIM ............................................................................................................................................ 47
ADSP (Author Domain Signing Practices) .............................................................................................................................. 49
DMARC (Domain Message Authentication, Reporting and Conformance) ........................................................................... 49
Verify that everything’s fully operational (Testing of SPF, DKIM and DMARC) ..................................................................... 50
Additional Settings on Mail Server ............................................................................................................................................ 51
Branding of your Organization .............................................................................................................................................. 51
Enabling Password Plugin on Roundcube ............................................................................................................................. 52
Enabling Filter using Managesieve ........................................................................................................................................ 53
Install sieve ............................................................................................................................................................................ 53
Changing Size of Attachment and Mail ................................................................................................................................. 54
Logging ....................................................................................................................................................................................... 57
Postfix .............................................................................................................................................................................. 57
Dovecot .............................................................................................................................................................................. 57
NGINX ................................................................................................................................................................................... 57
PHP........................................................................................................................................................................................ 57
MySQL ................................................................................................................................................................................... 57
Let’s Encrypt ................................................................................................................................................................ 57
ViMbAdmin ......................................................................................................................................................................... 57
3
Prerequisites
❖ 2 (two) physical or virtual servers with minimum requirement of 2 core CPUs, 4 GB RAM. One is for
mail server where AlmaLinux OS initially installed. In another server, proxmox mail gateway is to be
deployed through iso image. The storage depends on your email users.
4
How an Email server works
5
System Environment Setup
cat /etc/*release
Disabling SELinux
Security-Enhanced Linux (SELinux) is a Linux kernel security module that provides a mechanism for supporting
access control security policies, including mandatory access controls.
In RHEL, CentOS, AlmaLinux or several derivatives, the SELinux feature is enabled by default. But, some
applications may not actually support this security mechanism. Therefore, to make such applications function
normally, you have to disable or turn off SELinux.
FIREWALL Configuration
At first, need to check which zone is currently activated and available interfaces under the active zone.
6
firewall-cmd --get-active-zones
Now run the following commands for functioning the whole mailing system.
Change the default SSH port for enhancing the system security.
Open the configuration file of SSH
vi /etc/ssh/sshd_config
7
Next, reload the service.
If, you find mismatched date or time, then need to adjust your time zone by running the below command.
Then, confirm that the change has been made with the timedatectl command.
8
DNS Setup for mail Server
Before starting to deploy the mail server, must give A and PTR record for your emailing domain against IP in
DNS.
Also, must need to give MX (mail exchange) record that directs all incoming emails to the designated mail
server. The MX record indicates how email messages should be routed in accordance with the Simple Mail
Transfer Protocol (SMTP)
If you’re using bind DNS, the records look like the following snap.
mail.training.bdren.net.bd. IN A 103.157.135.95
training.bdren.net.bd. IN MX 10 mail.training.bdren.net.bd.
If you’re using cPanel, go to the domain Zone Editor file and add new records which look like the following
screenshot.
Initially, modify just 2 (two) files named main.cf and master.cf in postfix. At first, move the shipped
configuration file of main.cf with different name.
mv /etc/postfix/main.cf /etc/postfix/main.cf.bk
vi /etc/postfix/main.cf
9
smtpd_banner = $myhostname ESMTP $mail_name
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level=2
# TLS parameters
smtp_use_tls = yes
smtp_tls_security_level = may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.training.bdren.net.bd/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.training.bdren.net.bd/privkey.pem
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
virtual_transport = lmtp:unix:private/dovecot-lmtp
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
mail_owner = postfix
myhostname = mail.training.bdren.net.bd
mydomain = training.bdren.net.bd
myorigin = $mydomain
# RECEIVING MAIL
inet_interfaces = all
inet_protocols = all
mydestination = $myhostname, localhost.$mydomain, localhost
mynetworks_style = host
mynetworks = 103.157.135.128/25, 127.0.0.0/8
#relayhost = [mailgw.training.bdren.net.bd]:26
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
recipient_delimiter = +
default_destination_concurrency_limit = 10
smtpd_client_connection_rate_limit = 5
smtpd_client_message_rate_limit = 20
smtpd_recipient_limit = 30
default_extra_recipient_limit = 30
10
#message_size_limit = 52428800
meta_directory = /etc/postfix
shlib_directory = /usr/lib64/postfix
smtpd_recipient_restrictions =
permit_sasl_authenticated,
permit_mynetworks,
reject_unauth_destination
Next, open the master.cf file and then uncomment the following lines.
vi /etc/postfix/master.cf
-----------------------------------------------------------------
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_sasl_auth_enable=yes
To see the installed postfix configuration and version, the commands are respectively below.
11
postconf
postconf mail_version
N.B: at this moment, postconf may give few warnings due to not configuring mysql up to this step. But, after
configuring the following steps in this manual, those warning will be resolved.
mysql -u root -p
FLUSH PRIVILEGES;
quit;
12
mysql -u root -p
FLUSH PRIVILEGES;
quit;
Open 10-mail.conf file. Comment out any default mail_location and add the following line.
vi /etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:/home/mail/vhosts/%d/%n/Maildir
Open 10-master.conf file and modify the following parameters only. Others remain untouched.
13
vi /etc/dovecot/conf.d/10-master.conf
inet_listener imaps {
port = 993
ssl = yes
}
inet_listener pop3s {
port = 995
ssl = yes
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
service auth {
unix_listener auth-userdb {
mode = 0600
user = vmail
#group =
}
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
user = dovecot
}
service auth-worker {
user = vmail
}
Also, open the following files and change the configuration accordingly.
vi /etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = no
auth_mechanisms = plain login
#!include auth-system.conf.ext
!include auth-sql.conf.ext
vi /etc/dovecot/conf.d/auth-sql.conf.ext
14
comment out the followings,
#userdb {
# driver = sql
# args = /etc/dovecot/dovecot-sql.conf.ext
#}
userdb {
driver = static
args = uid=vmail gid=vmail home=/home/mail/vhosts/%d/%n allow_all_users=yes
}
vi /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=vimbadmin user=vimbadmin password=password
password_query = \
SELECT username AS user, password, \
homedir AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \
FROM mailbox WHERE username = '%u'
iterate_query = SELECT username AS user FROM mailbox
vi /etc/dovecot/conf.d/10-ssl.conf
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.training.bdren.net.bd/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.training.bdren.net.bd/privkey.pem
vi /etc/dovecot/conf.d/10-logging.conf
log_path = /var/log/dovecot.log
auth_debug = yes
mail_debug = yes
vi /etc/dovecot/dovecot.conf
15
To see the currently configured dovecot parameters,
doveconf -n
netstat -ltn
Prerequisites
As a requirement, need to install the Extra Packages for Enterprise Linux (EPEL) release.
Then update the packages in the system to add the new package to the package manager list
yum update -y
Set up NGINX
16
certbot can automatically configure nginx for SSL/TLS. It looks for and modifies the server block in the
nginx configuration that contains a server_name for what a certificate will be requesting for.
vi /etc/nginx/nginx.conf
Add the following configuration at the end of file before the last second ‘}’ bracket. This configuration is for
roundcube webmail portal in which users will login via browser.
server {
server_name mail.training.bdren.net.bd;
root /usr/share/nginx/html/roundcube;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ ^/(README.md|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ {
deny all;
}
location ~ ^/(config|temp|logs)/ {
deny all;
}
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Save the file, then to verify the syntax of nginx configuration and to restart NGINX, run the following command.
17
nginx -t && nginx -s reload
Respond to prompts from certbot by entering your email address and agreeing to the Let’s Encrypt terms of
service.
This command will automatically modify the Nginx existing configuration by adding the relevant lines containing
the paths to the certificate and private key.
server {
if ($host = mail.training.bdren.net.bd) {
} # managed by Certbot
server_name mail.training.bdren.net.bd;
listen 80;
Automating Renewal
A Let’s Encrypt-issued SSL certificate is valid for 90 days. Need to automate the process of renewing the
certificate by adding a cronjob that periodically checks the expiry status of the certificate and renews the
certificate if needed.
18
Open the crontab file:
crontab -e
This will open a text editor and add the following lines.
MAILTO=""
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/usr/local/bin
# minute (m), hour (h), day of month (dom), month (mon), day of week (dow) or use '*' (for 'any').
# m h dom mon dow command
0 2 * * * /usr/bin/certbot renew --quiet
It will check at 2:00 am, every day to see if the certificate on the server will expire within the next 30 days, and
renews it if so. The --quiet directive tells certbot not to generate output.
Save and close the file. All installed certificates will be automatically renewed and reloaded.
Now, PHP 8.0 has been installed via the remi repository.
To verify the php version installed,
php -v
yum install -y php-pdo php-zip php-mysqlnd php-gd php-intl php-imagick php-ldap php-fpm
19
Then, need to set time zone in php. Open the below file.
vi /etc/php.ini
date.timezone = Asia/Dhaka
Set up Roundcube
Download the latest available release of Roundcubemail from their official github repository. At the time of
writing this manual, Roundcube Webmail 1.6.0 is the latest available version.
wget https://github.com/roundcube/roundcubemail/releases/download/1.6.0/roundcubemail-1.6.0-complete.tar.gz
mv roundcubemail-1.6.0 /usr/share/nginx/html/roundcube
In defaults.inc.php file, all default settings are shipped automatically during installation. But, shouldn’t edit
anything in this file. Rather, copy any desired configurations to config.inc.php which is called local
configuration file. Any configuration in config.inc.php will override the default configurations in
defaults.inc.php.
vi /usr/share/nginx/html/roundcube/config/config.inc.php
Copy the below configurations to config.inc.php file. These will override the default settings in
defaults.inc.php
<?php
// ----------------------------------
// SQL DATABASE
// ----------------------------------
20
// Format: db_provider://user:password@host/database
$config['db_dsnw'] = 'mysql://roundcube:password@localhost/roundcube';
// ----------------------------------
// IMAP
// ----------------------------------
// Enter hostname with prefix ssl:// to use Implicit TLS, or use prefix tls:// to use STARTTLS.
$config['default_host'] = 'ssl://mail.training.bdren.net.bd';
$config['default_port'] = 993;
// ----------------------------------
// SMTP server host (for sending mails)
// ----------------------------------
// Enter hostname with prefix ssl:// to use Implicit TLS, or use prefix tls:// to use STARTTLS.
$config['smtp_server'] = 'ssl://mail.training.bdren.net.bd';
// SMTP port. Use 25 for cleartext, 465 for Implicit TLS, or 587 for STARTTLS (default)
$config['smtp_port'] = 465;
// ----------------------------------
// SYSTEM
// ----------------------------------
$config['skin_logo'] = array();
$config['force_https'] = true;
$config['use_https'] = true;
$config['username_domain'] = 'training.bdren.net.bd';
$config['mail_domain'] = 'training.bdren.net.bd';
$config['email_dns_check'] = true;
// ----------------------------------
// LOGGING/DEBUGGING
// ----------------------------------
$config['log_logins'] = true;
$config['session_debug'] = true;
$config['imap_debug'] = true;
$config['smtp_debug'] = true;
// ----------------------------------
// PLUGINS
21
// ----------------------------------
$config['plugins'] = array('archive', 'zipdownload');
// ----------------------------------
// USER INTERFACE
// ----------------------------------
$config['create_default_folders'] = true;
$config['quota_zero_as_unlimited'] = true;
$config['enable_spellcheck'] = true;
// ----------------------------------
// USER PREFERENCES
// ----------------------------------
$config['skin'] = 'larry';
$config['htmleditor'] = 1;
$config['default_list_mode'] = 'threads';
$config['reply_mode'] = 1;
$config['enable_installer'] = true;
?>
In each time when any settings in roundcube config.inc.php file is to be changed, must reload the web server.
The skins Larry and Classic are no longer part of the latest release packages. Need to install them separately.
cd /usr/share/nginx/html/roundcube/
curl -sS https://getcomposer.org/installer | php
php composer.phar require roundcube/larry
22
chown -R nginx:nginx /usr/share/nginx/html/roundcube
To check whether all PHP related dependencies are perfectly installed or not, visit the following site.
mail.training.bdren.net.bd/installer
N.B: We have already integrated roundcube with nginx site configuration in the previous stage. Also, we have already created
config.inc.php file. So, no need to generate this file again from the installer portal.
After conforming of all php modules installed perfectly, must have to remove the installer directory from
roundcube installation path for security. Many sensitive configuration data become exposed to outside.
rm /usr/share/nginx/html/roundcube/installer/
$config['enable_installer'] = false;
service nginx restart
23
Installation and Configuration of ViMbAdmin
Create a separate directory from where postfix can find out the domains, mailboxes, aliases etc.
mkdir /etc/postfix/mysql
vi /etc/postfix/mysql/virtual_alias_maps.cf
user = vimbadmin
password = password
hosts = 127.0.0.1
dbname = vimbadmin
query = SELECT goto FROM alias WHERE address = '%s' AND active = '1'
vi /etc/postfix/mysql/virtual_domains_maps.cf
user = vimbadmin
password = password
hosts = 127.0.0.1
dbname = vimbadmin
query = SELECT domain FROM domain WHERE domain = '%s' AND backupmx = '0' AND active = '1'
vi /etc/postfix/mysql/virtual_mailbox_maps.cf
user = vimbadmin
password = password
hosts = 127.0.0.1
dbname = vimbadmin
query = SELECT maildir FROM mailbox WHERE username = '%s' AND active = '1'
In the postfix main.cf file, we have already hooked postfix to use the above 3 files. Now, integrate them by
running postmap command. postmap - postfix lookup table management.
postmap /etc/postfix/mysql/virtual_mailbox_maps.cf
postmap /etc/postfix/mysql/virtual_domains_maps.cf
postmap /etc/postfix/mysql/virtual_alias_maps.cf
24
Set up ViMbAdmin
cd /usr/share/nginx/html/
cd vimbadmin/
cp application/configs/application.ini.dist application/configs/application.ini
vi application/configs/application.ini
In the application.ini file, need to adjust database name, user and password to use the mysql DB created
previously for vimbadmin.
Also, need to change UID and GID of mailbox (as specified in main.cf file of postfix), the default mailbox’s mail
and home directory (as specified in 10-mail.conf file of dovecot) according to the followings.
defaults.mailbox.uid = 5000
defaults.mailbox.gid = 5000
defaults.mailbox.maildir = "maildir:/home/mail/vhosts/%d/%u/Maildir:LAYOUT=fs"
defaults.mailbox.homedir = "/home/mail/vhosts/%d/%u"
25
cp public/.htaccess.dist public/.htaccess
./bin/doctrine2-cli.php orm:schema-tool:create
/usr/share/nginx/html/vimbadmin
vi /etc/nginx/nginx.conf
Add the following configuration at the end of file before the last second ‘}’ bracket. This configuration is for
ViMbAdmin administrative portal in which mail admin will create and manage domain, users, aliases, and so on.
server {
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ ^/(README.md|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ {
deny all;
}
location ~ ^/(config|temp|logs)/ {
deny all;
}
location ~ /\. {
deny all;
26
access_log off;
log_not_found off;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
ssl_certificate /etc/letsencrypt/live/mail.training.bdren.net.bd/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mail.training.bdren.net.bd/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
Save the file, then to verify the syntax of nginx configuration and to restart NGINX, run the following command.
https://mail.training.bdren.net.bd:8787
27
Next, login the installed ViMbAdmin portal through this mailadmin administrative user and create domain, user
mailboxes and aliases according to needs.
28
MAIL GATEWAY
There are lots of mail gateway appliances in the market. In this manual, Proxmox Mail Gateway is to be deployed
in front of the mail server.
Also, need to change MX (mail exchange) record that directs all incoming emails to the mail gateway server.
If you’re using bind DNS, the records look like the following snap.
mailgw.training.bdren.net.bd. IN A 103.140.181.84
29
training.bdren.net.bd. IN MX 10 mailgw.training.bdren.net.bd.
If you’re using cPanel, go to the domain Zone Editor file and add new records which look like the following
screenshot.
Proxmox Mail Gateway can run on dedicated server hardware or inside a virtual machine.
Download Proxmox mail gateway ISO image from their official website and boot a physical or virtual machine by
attaching the downloaded ISO from USB or CD/DVD.
After booting up the machine with the installer ISO, a welcome page of proxmox mail gateway is displayed.
30
31
32
33
34
After completing the installation of Proxmox mail Gateway, a confirmation page is to be appeared.
Proxmox Mail Gateway is usually configured using the web-based Graphical User Interface (GUI).
https://mailgw.training.bdren.net.bd:8006
As network and time are configured during the installation, these generally do not need to be configured again in
the GUI.
Initial configuration can be done from Mail Proxy menu under Configuration tab.
35
36
37
38
Lastly, configure Mail Filter. The below screenshot gives an example of set of rules. Please adjust those according
to your needs.
Open the Postfix main.cf configuration file and just add the following line on anywhere in the file.
vi /etc/postfix/main.cf
relayhost = [mailgw.training.bdren.net.bd]:26
39
How to Enhance Email Deliverability and Security
The following settings are used to increase email deliverability along with security.
N.B: some of the optional parameters/tags in the following settings are not included for simplicity. Only required
and recommended settings are focused in production level.
A system or protocol that verifies mail servers whether they (IPv4 and/or IPv6) are allowed to send emails on
behalf of a domain.
Setting up SPF helps to prevent emails from being classified as spam, and also helps servers to detect incoming
mails whether the sending hosts are eligible to send emails or not. SPF works on two ways:
❖ One is for outgoing mails for which need to publish SPF DNS record so that the receiving servers can
validate the mail server’s IPv4/IPv6 by matching the DNS record.
❖ Another way is for incoming mails for which need to hook up SPF policy agent to postfix so that mail
server can validate the sending server’s eligibility whether that IP is allowed or not. if it matches, the mail
is to be handled accordingly, otherwise the mail is to be marked as per domain policy. (We’ll talk about
the policy in the DMARC sections)
The value in an SPF DNS record looks similar to the following. Allow mail from a specific host:
-all indicates that any emails coming from others host, which is not listed in the SPF string, will be rejected.
An alternative is ~all, that tells mail servers to accept emails from others host and flag it as forged instead of
rejecting.
If you’re using cPanel, go to the domain zone page for the selected domain and add a new TXT record.
40
Adding SPF policy agent to Postfix (For Incoming mails)
As we have deployed mail gateway, the SPF functionality for incoming mails is to be handled by mail gateway. No need to
configure this step to mail server. This step is required in case of without mail gateway.
2. If you are using SpamAssassin to filter spam, you may want to edit /etc/python-policyd-
spf/policyd-spf.conf to change the HELO_reject and Mail_From_reject settings to False.
The Python based SPF policy agent adds SPF policy-checking to Postfix.
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
check_policy_service unix:private/policyd-spf
#SPF_POLICY
policyd-spf_time_limit = 3600
Make sure to add the check_policy_service entry after the reject_unauth_destination to avoid the
system from being an open relay.
41
systemctl restart postfix
A system or protocol or you can say as technique that adds a signature (by means of private key) to headers of the
outgoing emails and identifies the domain’s public key published in DNS so other mail servers can verify the
signature (by means of the domain’s public key). It follows the asymmetric encryption algorithm.
1. Every outgoing emails can be authenticated by receiving servers and by that can be kept the emails from
being considered as spam.
2. On other way, the mail server can also authenticate to all incoming mails so that it can
reject/quarantine/spam the received illegitimate mails based on the policies published by the sending
domain. (we’ll talk about this policies in next section)
3. It also helps mail servers to detect when any email has been tampered with in transit.
In summary, without implementing DKIM for your domain, your outgoing mails will be unauthenticated and
treated as spam on those receiving servers who have implemented DKIM. Also, your incomings mails will not be
authenticated and filtered against DKIM. So, this protocol implementation is really impactful on production
environment.
The implementation of DKIM involves setting up the OpenDKIM package, hooking it into Postfix, and adding
DNS records.
42
Setting up OpenDKIM Package
As we have deployed mail gateway, the DKIM functionality is to be handled by mail gateway. No need to configure this step
to mail server. This step is required in case of without mail gateway. Please skip to Adding DNS Record for DKIM section.
2. Add user postfix to the opendkim group so that Postfix can access OpenDKIM’s socket.
# Log to syslog
Syslog yes
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
UMask 002
# OpenDKIM user
# Remember to add user postfix to group opendkim
UserID opendkim
43
OversignHeaders From
mkdir /etc/opendkim/keys
6. Create the signing table /etc/opendkim/signing.table. It needs to have one line per domain that
you handle email for.
*@training.bdren.net.bd training
Replace training.bdren.net.bd with your domain and training with a short name for the domain. The first
field is a pattern that matches e-mail addresses. The second field is a name for the key table entry that is used to
sign mail from that address.
7. Create the key table /etc/opendkim/key.table. It needs to have one line per short domain name in
the signing table.
training training.bdren.net.bd:202209:/etc/opendkim/keys/training.private
Replace training with the value you used for short name of the domain in the signing table. Make sure to catch
the second occurrence at the end, where it’s followed by .private.
Replace training.bdren.net.bd with your domain name for which the key is used, and replace 202209 with
the format of YYYYMM in where current 4-digit year and 2-digit month. This is the selector which will be used for
declaration of the public key in DNS.
8. Create the trusted hosts file /etc/opendkim/trusted.hosts. Its contents need to be like the
following.
44
127.0.0.1
::1
localhost
mail.training.bdren.net.bd
training.bdren.net.bd
9. Make sure the ownership and permissions on /etc/opendkim (opendkim should own everything, the
keys directory should only be accessible by the owner)
This generates two files, YYYYMM formatted 202209.private file containing the key and 202209.txt
containing the TXT record that you need to set up DNS.
11. Rename the files so they have names matching the third section of the second field of the key table for the
domain.
mv /etc/opendkim/keys/202209.private /etc/opendkim/keys/training.private
mv /etc/opendkim/keys/202209.txt /etc/opendkim/keys/training.txt
Repeat the commands in this step for every entry in the key table. The -b 2048 indicates the number of bits in
the RSA key pair used for signing and verification. 1024 bits is the minimum, but with modern hardware 2048
bits is safer. (It’s possible 4096 bits are required at some point.)
12. Make sure the ownership, permissions and contents on /etc/opendkim are correct by running the
following commands.
45
cd /etc
You should not get error messages, but if you do, use the following command to get the status, and untruncated
error messages:
Test the keys for correct signing and verification using the opendkim-testkey command:
If everything is OK you shouldn’t get any output. If you want to see more information, add -vvv to the end of the
command. That produces verbose debugging output. The last message should be “key OK”. Just before that you
may see a “key not secure” message. That’s normal and doesn’t signal an error, it just means your domain isn’t
set up for DNSSEC yet.
1. Create the OpenDKIM socket directory in Postfix’s work area and make sure it has the correct ownership:
mkdir /var/spool/postfix/opendkim
46
2. Set the correct socket for Postfix in the OpenDKIM defaults file /etc/default/opendkim
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
Uncomment the first SOCKET line and edit it so it matches the uncommented line in the above file.
3. Edit /etc/postfix/main.cf and add the following section to activate processing of emails through
the OpenDKIM daemon. You can put this anywhere in the file. But the better is to put it after
smtpd_recipient_restrictions entry.
# Milter configuration
# OpenDKIM
milter_default_action = accept
# Postfix ≥ 2.6 milter_protocol = 6, Postfix ≤ 2.5 milter_protocol = 2
milter_protocol = 6
smtpd_milters = local:opendkim/opendkim.sock
non_smtpd_milters = local:opendkim/opendkim.sock
Scenario#1: If you have optionally deployed DKIM on mail server, then you can find the public
domain key from the below file.
vi /etc/opendkim/keys/training.txt
Select and copy the entire region from and do not include the double-quote before v=DKIM1. Also do not include
the final double-quote before the closing parentheses. Then edit out the double-quotes within the copied text and
the whitespace between them. Also change h=rsa-sha256 to h=sha256.
Scenario#2: With mail gateway you can find the public domain key from the DKIM tab under
Mail Proxy menu.
47
In case of bind DNS, just copy the whole things in between the box indicating DNS TXT Record and paste it to
DNS.
In case of cPanel, first need to copy the text into notepad or MS word or something like that, then remove all
double-quotes within the text. The whole text needs to be divided into 2 parts. The ultimate record looks like the
below snap.
48
ADSP (Author Domain Signing Practices)
As a final item, you can add an ADSP policy saying that all emails from your domain should be DKIM-signed.
As usual, it’s done with a TXT record for host _adsp._domainkey in your domain with a value of dkim=all.
In case of cPanel,
ADSP is not required to be setup, but doing so makes it harder for anyone to forge emails from your domain.
Because recipient mail servers see the lack of a DKIM signature and reject the message.
The DMARC DNS record can advise mail servers what to do with emails claiming to be from your domain that
fail SPF or DKIM validations. DMARC also allows to request authentication failure reports of SPF and DKIM
sent to the administrator. DMARC should only be set up if you have SPF and DKIM set up and operating
successfully.
The DMARC record is a TXT record. The tags of a DMARC record control the authentication policies of a
domain.
✓ sp - determines the policy for subdomains. It takes the same arguments as the p tag.
✓ rua - specifies an email address that receives aggregate reports. Aggregate reports are usually generated
once per day.
49
· 0 requests a report if all authentication methods fail together.
· 1 requests a report if any authentication check fails.
· d requests a report if a DKIM check fails.
· s requests a report if an SPF check fails.
Verify that everything’s fully operational (Testing of SPF, DKIM and DMARC)
Send a test mail to any gmail/yahoo account and check whether it lands on inbox or spam folder.
Go to https://www.mail-tester.com and send an email to their given email address. Then, check your score out of
10.
50
Additional Settings on Mail Server
Change the default mail, favicon and login logo by customized logo.
In roundcube, there are 2 types of scenarios for logo. One is for login portal and favicon. Another is to be
displayed after user login.
Adjust the width and height size according to your organizational logo. For login_logo, make sure the logo size is
less than 200x200. For mail_logo, the pixel height must be less than 50. Copy those 2 types of images to the mail
server via SCP from linux terminal or WinSCP for windows.
cp login_logo.jpg /usr/share/nginx/html/roundcube/skins/larry/images/login_logo.png
cp mail_logo.jpg /usr/share/nginx/html/roundcube/skins/larry/images/mail_logo.png
After that, copy paste the following contents on the skin_logo configuration parameter in the
config.inc.php file.
$config['skin_logo'] = array(
51
Lastly, restart the NGINX service.
systemctl restart nginx
Rouncube does not come with a feature to enable email users to change their passwords. Edit roundcube main
config.inc.php and add the plugin name 'password' to the plugins array() to activate the plugin.
cd /usr/share/nginx/html/roundcube/
cp plugins/password/config.inc.php.dist plugins/password/config.inc.php
vi plugins/password/config.inc.php
Open the above config file and edit the lines as like the followings. Rest of the config lines remain unchanged.
$config['password_algorithm'] = 'sha512-crypt';
52
$config['password_log'] = true;
$config['password_db_dsn'] = 'mysql://vimbadmin_db_user:password@127.0.0.1/db_name';
$config['password_crypt_hash'] = 'sha512';
chown -R nginx:nginx
Install sieve
plugin {
sieve=~/.dovecot.sieve
sieve_dir = ~/sieve
sieve_global_dir = /home/sieve
sieve_max_script_size = 1M
}
service managesieve-login {
inet_listener sieve {
port = 4190
53
}
$mail_plugins = sieve
Also, edit roundcube main config.inc.php file and add the plugin name 'managesieve' to the plugins
array() to activate the plugin.
Find the following parameters, and change the value as per your need.
upload_max_filesize = 30M
post_max_size = 32M
2. To change the message size limit in postfix, open the main.cf file and add the following line.
message_size_limit = 52428800
54
$config['max_message_size'] = '100M';
Also, need to set the following parameter to nginx.conf file under http section.
client_max_body_size 55M;
Go to your master configuration file in postfix and comment out the line as shown below –
To check the Listening ports in the server for ensuring that 25 port is completely disabled.
netstat -ltn
Go to the proxmox mail gateway and change the following parameters as shown in the
screenshot –
Replace by-default 25 port to 587 meaning that the gateway server will use submission port-587
in spite of insecure 25 port to communicate with the mail server.
55
Lastly, deny the previously permitted 25 port on firewall in the mail server –
Now run the following command for disabling the previously added rule.
56
Logging
Postfix
/var/log/maillog
Dovecot
/var/log/dovecot.log
NGINX
/var/log/nginx/
access.log error.log
PHP
/var/log/php-fpm/www-error.log
MySQL
/var/log/mysql/mysqld.log
Let’s Encrypt
/var/log/letsencrypt/letsencrypt.log
ViMbAdmin
/usr/share/nginx/html/vimbadmin/var/log/vimbadmin.log
57
Spam-Filtering
Though it’s not important to setup spam-filtering in our mail server, as in this manual we use an
external gateway server which controls spam filter by its own. Optionally, you can implement the
following spam-filters in the mail server for extra security and most importantly, when you want
to understand the spam-filtering process, this will guide you to be realized how a spam-filtering
server or gateway server filters the spam.
SMTP Rules:
Tip #1: Reject Email if SMTP Client Has no PTR record
Tip #3: Reject Email if SMTP Client Hostname doesn’t have valid A Record
Tip #4: Reject Email If MAIL FROM Domain Has Neither MX Record Nor A Record
Tip #6: Check sender’s SPF, DKIM signature and DMARC policy
58
Postfix Configuration ( main.cnf )
smtpd_helo_required = yes
smtpd_helo_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
check_helo_access hash:/etc/postfix/helo_access,
reject_invalid_helo_hostname,
reject_non_fqdn_helo_hostname,
reject_unknown_helo_hostname
smtpd_sender_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unknown_sender_domain,
reject_unlisted_sender,
reject_unauthenticated_sender_login_mismatch,
reject_unknown_reverse_client_hostname,
reject_unknown_client_hostname
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
check_policy_service unix:private/policyd-spf,
check_client_access hash:/etc/postfix/rbl_override,
reject_rhsbl_helo dbl.spamhaus.org,
reject_rhsbl_reverse_client dbl.spamhaus.org,
reject_rhsbl_sender dbl.spamhaus.org,
permit_dnswl_client swl.spamhaus.org,
reject_rbl_client zen.spamhaus.org,
reject_rbl_client smtp.dnsbl.sorbs.net,
reject_rbl_client bl.spamcop.net,
reject_rbl_client combined.rbl.msrbl.net,
reject_rbl_client multihop.dsbl.org
vi /etc/postfix/helo_access
59
Whitelist legitimate mail server’s HELO/EHLO hostname like below.
test.localdomain OK
mail.bdren.net.bd OK
postmap /etc/postfix/helo_access
Create A Whitelist
Often you need to create a whitelist so they won’t be blocked. Create the following file.
vi /etc/postfix/rbl_override
bdren.net.bd OK
postmap /etc/postfix/rbl_override
60
Content-Filtering using SpamAssassin:
• header_checks
• mime_header_checks
• nested_header_checks
• body_checks
Postfix will check all inbound emails when any of the above parameters is being used. Each parameter points to
a lookup table containing regular expression patterns and actions. If Postfix finds a match, the specified action is
executed. Header and body checks are done by the Postfix cleanup daemon.
There are mainly two types of regular expressions that can be used by Postfix.
PCRE is way faster. To use PCRE in Postfix, you need to install the postfix-pcre package.
Run the following command and you will see pcre is now supported.
postconf -m
61
Header Checks
vi /etc/postfix/main.cf
header_checks = pcre:/etc/postfix/header_checks
Save and close the file. Then you need to create the /etc/postfix/header_checks lookup file.
vi /etc/postfix/header_checks
The lefthand key is a regular expression enclosed by two forward slashes. If any of the strings on the
left-hand appear in any of the headers of an email message (these would most likely show up in the
Subject: header), the message is rejected during the SMTP dialog. By default regular expression
checking is not case-sensitive.
62
/free mortgage quote/ DISCARD
/repair your credit/ DISCARD
This will cause Postfix to claim successful delivery and silently discard the message.
Some spammers use blank email address in the From: or To: header, you can add the following checks.
/To:.*<>/ DISCARD
/From:.*<>/ DISCARD
Once you finish editing the header_checks lookup file, you need to build the index file.
postmap /etc/postfix/header_checks
Body Checks
In addition to header checks, Postfix can check the body of an email message. To enable body_checks
in Postfix, open the main configuration file.
vi /etc/postfix/main.cf
body_checks = pcre:/etc/postfix/body_checks
Save and close the file. Then you need to create the /etc/postfix/body_checks lookup file.
vi /etc/postfix/body_checks
The patterns indicated by the body_checks parameter are checked against each line of the body of the
message. If any of the strings on the leftland appear in the body of an email message, the message is
rejected or discarded.
63
Once you finish editing the body_checks lookup file, you need to build the index file.
postmap /etc/postfix/body_checks
The built-in content checking in Postfix is very simple. However, there is no way to whitelist individual
messages that you might want to receive. For more sophisticated analysis, we need to use a dedicated
content filter (such as SpamAssassin) specifically designed to detect spam.
SpamAssassin is a score-based system. It will check email message against a large set of rules. Each rule
adds or removes points in the message’s score. If the score is high enough (by default 5.0), the message
is considered spam.
Install SpamAssassin
dnf install spamassassin -y
Configuration
vi /etc/mail/spamassassin/local.cf
required_hits 5
report_safe 0
required_score 5
rewrite_header Subject [SPAM]
64
Integrating Postfix and SpamAssassin
In order to efficiently integrate Postfix and spamassassin, we will need to create a dedicated user and group to
run the spam filter daemon:
groupadd spamd
And indicate (at the top) that spamassassin will serve as content_filter:
-o content_filter=spamassassin
65
To verify that SpamAssassin is working properly and detecting incoming spam, a test known as GTUBE
(Generic Test for Unsolicited Bulk Email) can be performed.
To perform this test, send an email from a domain outside your network (such as Yahoo!, Hotmail, or
Gmail) to an account residing in your email server. Set the Subject line to whatever you want and
include the following text in the message body:
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
Whitelist
You can use the whitelist_from parameter to add a particular email address or domain to your
Spamassassin whitelist. For example, add the following two lines at the end of local.cf file.
whitelist_from xiao@linuxbabe.com
whitelist_from *@canonical.com
A whitelisted sender has a -100 default score. They will still be tested by SpamAssassin rules, but it’s
super hard for them to reach a 5.0 score.
After saving the local.cf file. You should run the spamassassin command in lint mode to check if
there’s any syntax errors.
spamassassin --lint
vi /etc/dovecot/conf.d/15-lda.conf
protocol lda {
mail_plugins = $mail_plugins sieve
}
66
vi /etc/dovecot/conf.d/20-lmtp.conf
protocol lmtp {
mail_plugins = sieve
}
Save and close the file. Then open the 90-sieve.conf file.
vi /etc/dovecot/conf.d/90-sieve.conf
Go to line 79 and add the following line, which tells Sieve to always execute the SpamToJunk.sieve
script before any user-specific scripts.
sieve_before = /home/mail/vhosts/SpamToJunk.sieve
Save and close the file. Then create the sieve script.
vi /home/mail/vhosts/SpamToJunk.sieve
Add the following lines, which tells Dovecot to move any email messages with the X-Spam-Flag: YES
header into Junk folder.
require "fileinto";
Save and close the file. Now need to compile this script.
sievec /home/mail/vhosts/SpamToJunk.sieve
67