MailScanner

-------

---

Email Server With Postfix Dovecot and MailScanner (Part 1 - LEMP)

Posted on 2016-04-20   |   In Email Server , LEMP   |   2 Comments

Email server is quite complicate. It is not only just for sending and receiving emails, but also need lots features and protections. Recently I built such an email server for my company. The whole process is worth to document.

I know there are some solutions exist for easy and quick setup a mail server, such as iRedMail. But I prefer to build the server step by step from scratch. This way I can understand how these all different components put together and how they work with each other. It’s kind of like driving an automobile, knowing a little bit better how the engine and transmission works will help me when there is a problem or need improvement down the road.

Features and Components

I begin with a list of some important features I needed for the mail system:

Here I list the major components I will build on the new email server:

Domain name and DNS

Before I start to build the email server, I checked that I have these network related stuff ready:

CentOS installation

I installed CentOS 7.2 64bit which is my faverate OS for server platform. During the installation, I setup the static IP, time zone, and hard drive partitions.

I’ll save all the emails in /home/vmail later on, so make sure it has enough space for email storage.

Once I finished installation and reboot the server, I login in as root and start configration.

Disable SELinux

Install some packages

Firewall

Centos 7 come with Firewalld as the firewall but I like to use iptables for firewall, so let’s disable the default installed firewalld.

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

yum -y install net-tools nano wget man bind-utils git mailx telnet

systemctl stop firewalld

systemctl mask firewalld

systemctl disable firewalld

Install iptables:

yum -y install iptables-services

systemctl enable iptables

systemctl start iptables

Now install fail2ban:

yum install -y epel-release

yum install -y fail2ban jwhois

Create fail2ban local configration file:

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit this file to enable sshd jail. Set:

[sshd]

enabled = true

...

Now enable and start the fail2ban service:

systemctl start fail2ban.service

systemctl enable fail2ban.service

Now the ssh port 22 is protected by Fail2ban against brutal-force attack. In the future, anytime I need open up a new port for a service in iptables, I’ll also need to configure the corresponding fail2ban jail to have it protected.

 There are lots scan activities on the well-known ssh port 22. So I changed the sshd to listen on a different port. Also configured iptables and fail2ban accordingly.

NTP

CentOS 7 use chronyd to keep the clock synchronized.

If timezone is not set, then:

timedatectl set-timezone America/Vancouver

Now install Chrony:

yum install -y chrony

systemctl enable chronyd

systemctl start chronyd

Use the following commands to check the status:

timedatectl

chronyc tracking

chronyc sources

chronyc sourcestats

Update system then reboot

Bring the system up to date:

yum -y update && reboot

After reboot, log in and check:

# sestatus

SELinux status:                 disabled

LEMP

MariaDB

Install MariaDB server:

yum install -y mariadb-server

systemctl enable mariadb.service

systemctl start mariadb.service

Secure MariaDB. Run this command, set the root password, and answer Y to all other questions:

mysql_secure_installation

Install Nginx

Add Nginx Repo by create a configration file /etc/yum.repos.d/nginx.repo with the following content:

[nginx]

name=nginx repo

baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/

gpgcheck=0

enabled=1

Install Nginx:

yum install nginx

Edit /etc/nginx/nginx.conf:

worker_processes 4;

...

gzip on;

server_tokens off;

...

Set worker_processes to the CPU core number.

Start nginx:

systemctl enable nginx.service

systemctl start nginx.service

Check to see Nginx is running on port 80:

# netstat -ntlp | grep :80

tcp        0      0 0.0.0.0:80       0.0.0.0:*        LISTEN      9901/nginx: master

Now open up port 80 and 443 on iptables. I can access http://smtp.mydomain.com for the nginx’s default page.

Install PHP5

PHP5 works in nginx through PHP-FPM. So install some php packages:

yum install php-fpm php-cli php-mysql php-gd php-mcrypt php-intl php-ldap php-odbc php-pdo php-pecl-memcache php-pear php-mbstring php-xml php-xmlrpc php-mbstring php-snmp php-soap php-imap

Edit /etc/php.ini , set

date.timezone = America/Vancouver

cgi.fix_pathinfo = 0

Edit /etc/php-fpm.d/www.conf, use socket instead of TCP port for better performance:

;listen = 127.0.0.1:9000

listen = /var/run/php-fpm/php-fpm.sock

user = nginx

group = nginx

Next enable and start php-fpm:

systemctl enable php-fpm.service

systemctl start php-fpm.service

Let’s Encrypt SSL Certificate

I use the free LE SSL Cert for all the virtual hosts and SMTP/IMAP/POP3

First make sure all DNS record are pointed to the correct IP. This includes all A records for @, www, and smtp.

yum install git bc

git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

Also make sure port 443 is open on iptables.

Obtain a certicate:

systemctl stop nginx

cd /opt/letsencrypt

./letsencrypt-auto certonly --standalone

Fill in my email address, then agree the agreement, then fill in all the domain names:

mydomain.com, www.mydomain.com,smtp.mydomain.com, mailwatch.mydomain.com, postfixadmin.mydomain.com roundcube.mydomain.com

output:

IMPORTANT NOTES:

Let’s Encript SSL Cert is only valid for 90 days. To renew it, set a cron job (or wrote a script). The command to renew is:

/root/.local/share/letsencrypt/bin/letsencrypt renew --agree-tos

To test this command, add --dry-run flag at the end.

Here is my simple bash script le_renew.sh:

#!/bin/bash

systemctl stop nginx

/root/.local/share/letsencrypt/bin/letsencrypt renew --agree-tos

systemctl start nginx

 Tip:

To obtain LE SSL certificates in one liner command:

/opt/letsencrypt/letsencrypt-auto certonly --standalone --agree-tos --email myemail@domain.tld -d mydomain.com -d www.mydomain.com -d smtp.mydomain.com -d mailwatch.mydomain.com -d postfixadmin.mydomain.com -d smtp.mydomain.com -d roundcube.mydomain.com

Configure Virtual Host

I will have few web sites running on this server using named based virtual host. They are RoundCube webmail, Postfix Admin and MailWatch.

I need to create a 2048 bit DH params file(default is 1024 bit):

openssl dhparam -out /etc/nginx/dhparams.pem 2048

Now let’s configure the first virtual host postfixadmin.mydomain.com by create a new configration file /etc/nginx/conf.d/postfixadmin.conf with content:

server {

 listen 80;

 server_name postfixadmin.mydomain.com;

 return 301 https://$server_name$request_uri; # enforce https

}

server {

  listen          443 ssl;

  server_name     postfixadmin.mydomain.com;

  root            /var/www/html/postfixadmin;

  index           index.php;

  charset         utf-8;

  access_log      /var/log/nginx/pa-access.log;

  error_log       /var/log/nginx/pa-error.log;

  ## SSL settings

  ssl_certificate           /etc/letsencrypt/live/mydomain.com/fullchain.pem;

  ssl_certificate_key           /etc/letsencrypt/live/mydomain.com/privkey.pem;

  ssl_protocols             TLSv1.2 TLSv1.1 TLSv1;

  ssl_prefer_server_ciphers on;

  ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";

  ssl_dhparam               /etc/nginx/dhparams.pem;  

  ssl_session_cache         shared:SSL:10m;

  ssl_session_timeout       10m;

  ssl_ecdh_curve            secp521r1;

  add_header Strict-Transport-Security max-age=31536000;

  location / {

     try_files $uri $uri/ index.php;

  }

  location ~ \.php$ {

       try_files $uri =404;

       fastcgi_split_path_info ^(.+\.php)(/.+)$;

       fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

       include       fastcgi_params;

       fastcgi_pass  unix:/run/php-fpm/php-fpm.sock;

       fastcgi_index index.php;

  }

}

Let’s make a test page:

mkdir /var/www/html/postfixadmin

echo "<?php phpinfo(); ?>" > /var/www/html/postfixadmin/info.php

Restart Nginx and test by go to http://postfixadmin.mydomain.com/info.php, it should jump to https:// automatcally and show the PHP info page.

A good test for SSL can be done at SSL LABS. I got the highest score “A+“!

 Repeat the above steps to create other virtual host sites(mailwatch, roundcube). Later we will build these sites in their doc root directory.

Now I have a basic LEMP server with SSL and firewall protections. I’m now ready to build the mail server on this system.

Quick links:

Email Server With Postfix Dovecot and MailScanner (Part 2 - Postfix and Dovecot)

Posted on 2016-04-20   |   In Email Server   |   13 Comments

Postfix is the mail transfer agent (MTA) that routes and delivers email. Dovecot is the IMAP and POP3 server. The two works together make a perfect email server.

Postfix

Postfix is installed and running after default CentOS 7 installation. It is just a basic SMTP server lintening on local interface (127.0.0.1) and serve for existing local user only.

Database for virtual domain and user

We will install PostfixAdmin which use MaridDB as back-end to handle virtual domain and user accounts. When Postfix and Dovecot want authenticate users they will query the MariaDB database.

Login MariaDB as root and create a database postfix. Add user postfix and grant accesses to it.

mysql -uroot -p

Create a database

CREATE DATABASE postfix;

CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'PApassword';

GRANT ALL PRIVILEGES ON postfix.* TO 'postfix'@'localhost';

FLUSH PRIVILEGES;

QUIT;

Postfix Admin

Postfix Admin is a web based interface used to manage mailboxes, virtual domains and aliases

Get the Postfix Admin site ready:

cd /usr/local/src

wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.93/postfixadmin-2.93.tar.gz

tar zvxf postfixadmin-2.93.tar.gz

rm -rf /var/www/html/postfixadmin

mv postfixadmin-2.93 /var/www/html/postfixadmin

chown -R nginx:nginx /var/www/html/postfixadmin

Edit /var/www/html/postfixadmin/config.inc.php

With:

<?php

$CONF['configured'] = true;

$CONF['database_type'] = 'mysqli';

$CONF['database_user'] = 'postfix';

$CONF['database_password'] = 'PApassword';

$CONF['database_name'] = 'postfix';

?>

I also need to manual create a session dir:

mkdir /var/lib/php/session/

chown -R nginx:nginx /var/lib/php/session/

Postfix Admin web setup

Now go to https://postfixadmin.mydomain.com/setup.php to continue the setup in the web interface.

Type in “Setup Password” and generate password hash.

Copy this line back to /var/www/html/postfixadmin/config.inc.php, at line 30:

$CONF['setup_password'] = '82020bc067e2a6deaa3fba3632529114:0834f649bf09ee930910ab1b353e3f0722b77ee8';

Then create the superadmin account.

Now use the superadmin account to login at https://postfixadmin.mydomain.com/login.php. This is the admin login.

Once we create user email account, the user may login to manage their own account at https://postfixadmin.mydomain.com/users/login.php. Note the different address.

Bug Fix:

After login, click on “Fetch email” I got error “Invalid query: FUNCTION postfix.FROM_BASE64 does not exist”

To fix it, edit /var/www/html/postfixadmin/model/PFAHandler.php at line 572:

$base64_decode = "###KEY###";

Link Postfix to MariaDB

Create 5 database query configration files:

Change permission to protect this files:

chgrp postfix mysql-*.cf

chmod 640 /etc/postfix/mysql-*.cf

Make Postfix use these 5 files to qurey database, add the following lines to /etc/postfix/main.cf

relay_domains = proxy:mysql:/etc/postfix/mysql-relay_domains_maps.cf

virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_alias_maps.cf,regexp:/etc/postfix/virtual_regexp

virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains_maps.cf

virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf

virtual_mailbox_limit_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_limit_maps.cf

proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $smtpd_sender_login_maps $sender_bcc_maps $recipient_bcc_maps $smtp_generic_maps $lmtp_generic_maps $alias_maps $virtual_mailbox_limit_maps

Create virtual_regexp file

touch /etc/postfix/virtual_regexp

To enable postfix listen on all interface, edit /etc/postfix/main.cf line 113,116:

inet_interfaces = all

#inet_interfaces = localhost

vmail user

Create a local user vmail and set its home dir as maildir:

groupadd -g 5000 vmail

mkdir /home/vmail

chmod 770 /home/vmail/

useradd -r -u 5000 -g vmail -d /home/vmail/ -s /sbin/nologin -c "Virtual Mailbox" vmail

chown vmail:vmail /home/vmail/

Make postfix to use this vmail account, add to /etc/postfix/main.cf

virtual_uid_maps = static:5000

virtual_gid_maps = static:5000

virtual_mailbox_base = /home/vmail

Restart postfix:

systemctl restart postfix

Also open TCP port 25 in iptables.

Now the Postfix SMTP is running. I can test it from another computer:

$ telnet smtp.mydomain.com 25

Trying 11.22.33.44...

Connected to smtp.mydomain.com.

Escape character is '^]'.

220 smtp.mydomain.com ESMTP Postfix

Test virtual domain/mailbox

Setup test email account

Go to Postfix Admin site [https://postfixadmin.mydomain.com], log in as admin user, then create a virtual domain. In my case, I go to “Domain List” –> “New Domain”, add “mydomain.com”.

Next go to “Virtual List”, then “Add Mailbox”, add a newmail box(Username: “gao”). Make sure “Active” and “Send Welcome mail” are checked. Then click on “Add Mailbox”.

Test receiving email

If everything is ok, you should see an email has been sent to gao@mydomain.com in the /var/log/maillog log file:

Apr 20 15:47:13 smtp postfix/smtpd[27293]: connect from localhost[::1]

Apr 20 15:47:14 smtp postfix/smtpd[27293]: 5CC0199812: client=localhost[::1]

Apr 20 15:47:14 smtp postfix/cleanup[27300]: 5CC0199812: message-id=<20160420224714.5CC0199812@smtp.mydomain.com>

Apr 20 15:47:14 smtp postfix/smtpd[27293]: disconnect from localhost[::1]

Apr 20 15:47:14 smtp postfix/qmgr[27051]: 5CC0199812: from=<gao@mydomain.com>, size=485, nrcpt=1 (queue active)

Apr 20 15:47:14 smtp postfix/virtual[27309]: 5CC0199812: to=<gao@mydomain.com>, relay=virtual, delay=0.34, delays=0.11/0.07/0/0.17, dsn=2.0.0, status=sent (delivered to maildir)

Apr 20 15:47:14 smtp postfix/qmgr[27051]: 5CC0199812: removed

Check the maildir I saw the email has been put in the maildir:

# ls -l /home/vmail/mydomain.com/gao/new/

total 4

-rw------- 1 vmail vmail 568 Apr 20 15:47 1461192434.Vfd02I30000081M492053.smtp.mydomain.com

I also tested it by sending an email from my Gmail account and watch the maillog to see the mail arrived.

Test send email out

I still use telnet command from a remote PC to send a test email out:

$ telnet smtp.mydomain.com 25

Trying 11.22.33.44...

Connected to smtp.mydomain.com.

Escape character is '^]'.

220 smtp.mydomain.com ESMTP Postfix

EHLO jade

250-smtp.mydomain.com

250-PIPELINING

250-SIZE 10240000

250-VRFY

250-ETRN

250-ENHANCEDSTATUSCODES

250-8BITMIME

250 DSN

MAIL FROM: gao@mydomain.com

250 2.1.0 Ok

RCPT TO: mytestmail@gmail.com

250 2.1.5 Ok

DATA

354 End data with <CR><LF>.<CR><LF>

Subject: this is a telnet test

Hi,this is just a quick test form telnet.

.

250 2.0.0 Ok: queued as 2528F1A4E3

QUIT

221 2.0.0 Bye

Connection closed by foreign host.

Check the maillog to make sure the mail is send out.

At this stage, sending email to Gmail may fail. This will be fixed later by setup proper SPF and DKIM record in our DNS settings. If you have to test with Gmail then you may add mydomain.com as truseted domain at [https://postmaster.google.com]

SMTP Submission

I will enable SMTP submission on port 587, and use dovecot embebed SASL authentication to verify user identity.

Edit /etc/postfix/master.cf, remove comments in these lines:

submission inet n       -       n       -       -       smtpd

 -o syslog_name=postfix/submission

 -o smtpd_tls_security_level=encrypt

 -o smtpd_sasl_auth_enable=yes

 -o smtpd_reject_unlisted_recipient=no

 -o smtpd_client_restrictions=$mua_client_restrictions

 -o smtpd_helo_restrictions=$mua_helo_restrictions

 -o smtpd_sender_restrictions=$mua_sender_restrictions

 -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject

 -o milter_macro_daemon_name=ORIGINATING

Edit /etc/postfix/main.cf, add lines:

smtpd_sasl_type = dovecot

smtpd_sasl_path = private/auth

smtpd_sasl_auth_enable = yes

smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

smtpd_tls_cert_file = /etc/letsencrypt/live/mydomain.com/fullchain.pem

smtpd_tls_key_file = /etc/letsencrypt/live/mydomain.com/privkey.pem

smtpd_tls_security_level = may

#Disable sslv2 ad SSLv3

smtpd_tls_protocols= !SSLv2, !SSLv3

smtpd_tls_mandatory_protocols= !SSLv2, !SSLv3

#set minimum TLS ciphers grade for tls

smtpd_tls_mandatory_ciphers = high

#use server ciphers instead client preference

tls_preempt_cipherlist = yes

#ciphers to exclude

smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5 , DES, ADH, RC4, PSD, SRP, 3DES, eNULL

#disallow plain login

smtpd_tls_auth_only = yes

mua_client_restrictions = permit_sasl_authenticated,reject

mua_helo_restrictions = permit_sasl_authenticated,reject

mua_sender_restrictions = permit_sasl_authenticated,reject

Restart postfix

systemctl restart postfix

Dovecot

I use Dovecot to provide POP amd IMAP services so the user can use an email client(Thunderbird, Outlook.,etc) to retrive emails.

Install dovecot

dovecot main config file

Edit dovecot main config file /etc/dovecot/dovecot.conf

yum install dovecot dovecot-mysql dovecot-pigeonhole

protocols = imap pop3

listen = *

shutdown_clients = yes

Enable and start dovecot:

systemctl enable dovecot

systemctl start dovecot

Check use netstat to see dovecot is listening on port 110,143,993,995

# netstat -ntlp | grep dovecot

tcp        0      0 0.0.0.0:110       0.0.0.0:*      LISTEN      7564/dovecot       

tcp        0      0 0.0.0.0:143       0.0.0.0:*      LISTEN      7564/dovecot       

tcp        0      0 0.0.0.0:993       0.0.0.0:*      LISTEN      7564/dovecot       

tcp        0      0 0.0.0.0:995       0.0.0.0:*      LISTEN      7564/dovecot

Dovecot authentication

I configured Dovecot to use database created by PostfixAdmin for user authentication with Let’s Encript’s SSL certificate:

database query configration

Create a file /etc/dovecot/conf.d/dovecot-mysql.conf.ext

driver = mysql

connect = host=localhost dbname=postfix user=postfix password=PApassword

password_query = SELECT username as user, password, concat('/home/vmail/', maildir) as userdb_home,  concat('maildir:/home/vmail/', maildir) as userdb_mail, 5000 as userdb_uid, 5000 as userdb_gid FROM mailbox  WHERE username = '%u' AND active = '1'

user_query = SELECT concat('/home/vmail/', maildir) as home, concat('maildir:/home/vmail/', maildir) as mail,  5000 AS uid, 5000 AS gid, CONCAT('*:bytes=', quota) as quota_rule FROM mailbox WHERE  username = '%u' AND active = '1'

Also we need a file to provide information about accounts quota. Edit /etc/dovecot/conf.d/dovecot-mysql-quota.conf.ext

connect = host=localhost dbname=postfix user=postfix password=PApassword

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

}

Set file permission

chmod 640 /etc/dovecot/conf.d/dovecot-mysql*

With above files dovecot will query mariadb info about users idendity and mailbox quotas.

Make dovecot use MariaDB for authentication

Edit /etc/dovecot/conf.d/auth-sql.conf.ext

passdb {

 driver = sql

 args = /etc/dovecot/conf.d/dovecot-mysql.conf.ext

}

userdb {

 driver = sql

 args = /etc/dovecot/conf.d/dovecot-mysql.conf.ext

}

Enable dovecot to use sql_auth, edit /etc/dovecot/conf.d/10-auth.conf

disable_plaintext_auth = yes

auth_mechanisms = plain login cram-md5

#!include auth-system.conf.ext

!include auth-sql.conf.ext

Enable SSL/TLS support

Edit /etc/dovecot/conf.d/10-ssl.conf

ssl_cert = </etc/letsencrypt/live/mydomain.com/fullchain.pem

ssl_key = </etc/letsencrypt/live/mydomain.com/privkey.pem

# SSL protocols to use

ssl_protocols = !SSLv2 !SSLv3

# SSL ciphers to use

ssl_cipher_list = EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4


# Prefer the server's order of ciphers over client's.

ssl_prefer_server_ciphers = yes

Edit /etc/dovecot/conf.d/10-master.conf

service imap-login {

 inet_listener imap {

   port = 143

 }

 inet_listener imaps {

   port = 993

   ssl = yes

 }


service pop3-login {

 inet_listener pop3 {

   port = 110

 }

 inet_listener pop3s {

   port = 995

   ssl = yes

 }

}


service auth {


 unix_listener /var/spool/postfix/private/auth {

   mode = 0666

   user = vmail

   group = vmail

 }

Maildir and mail user

Edit /etc/dovecot/conf.d/10-mail.conf

mail_location = maildir:/home/vmail/%d/%n/:INDEX=/home/vmail/%d/%n/indexes

mail_uid =5000

mail_gid =5000

first_valid_uid = 5000

last_valid_uid = 5000

first_valid_gid = 5000

last_valid_gid = 5000

Test dovecot

Open TCP port 993,995 and 587 on iptables. (I force all clients to use SSL/TLS so I keep port 110 and 143 closed.)

Restart dovecot

systemctl restart dovecot

Test SSL login to IMAPS on port 993 from a remote PC:

#openssl s_client -connect smtp.mydomain.com:993 -quiet

depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X1

verify error:num=20:unable to get local issuer certificate

verify return:0

* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN AUTH=CRAM-MD5] Dovecot ready.

a1 LOGIN gao@mydomain.com my_password

a1 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE] Logged in

a2 LIST "" "*"

* LIST (\HasNoChildren) "." INBOX

a2 OK List completed.

a3 EXAMINE INBOX

* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)

* OK [PERMANENTFLAGS ()] Read-only mailbox.

* 4 EXISTS

* 4 RECENT

* OK [UNSEEN 1] First unseen.

* OK [UIDVALIDITY 1457462303] UIDs valid

* OK [UIDNEXT 5] Predicted next UID

a3 OK [READ-ONLY] Examine completed (2.716 secs).

a4 LOGOUT

* BYE Logging out

a4 OK Logout completed.

Mailbox quota

I enable imap_quota plugin:

Edit /etc/dovecot/conf.d/10-mail.conf, line 215 should be

mail_plugins = $mail_plugins quota

Edit /etc/dovecot/conf.d/20-imap.conf, line 56 should be

mail_plugins = $mail_plugins imap_quota

Edit /etc/dovecot/conf.d/90-quota.conf, line 68 should look like these

quota = maildir:User quota

Now restart dovecot service

Edit mailbox quota in PostfixAdmin, set to non-zero, then I can see the quota of INBOX.

Test the email server

Now I can create an new email account in Thunderbird to test.

Always use full email address as login name. Here is the setup with IMAP on port 993:

Now I can send out and receive email so the basic mail server is working.

Email Server With Postfix Dovecot and MailScanner (Part 3 - MailScanner and MailWatch)

http://blog.pztop.com/2016/04/21/Email-Server-With-Postfix-Dovecot-MailScanner-3/

I use MailScanner to scan emails for viruses, spam, phishing, malware, and other attacks against security vulnerabilities. Under the hood, MailScanner uses ClamAV(clamd) for virus scan, and uses Spamassassin to scan for spams.

MailWatch is the web UI frontend to manage MailScanner. I can manage qurantine and generate reports easily right in the web browser.

 MailScanner come with a installation script you may use it for easy setup. It will install all compoenets once you made your selection.

ClamAV

Clam AV can be load in 3 different mode. Here is the explaination:

clamscan: most expensive CPU-wise, but involves no extra setup. This just executes the clamscan command-line tool. This causes the signature database to be re-read for each object scanned and can be pretty CPU intensive compared to the others.

clamav module: less expensive than clamscan CPU-wise, but needs the Mail::ClamAV perl module. This method loads a copy of the libclamav scanner library into MailScanner and keeps it resident, using it to perform scans without needing to re-read the signature libraries, etc. It can be somewhat touchy about what versions of Mail::ClamAV work with various versions of clamav.

clamd: less expensive than clamscan CPU-wise, but needs clamd running and is relatively new code. This causes MailScanner to connect to clamd’s socket and use that for scanning. Since clamd is already resident, there’s no need to re-read signatures. Since it’s using clamd, which comes with clamav, there’s no real version-compatibility problems like with the module, at least in theory

So I decide to run ClamAV as a daemon (clamd) for better performance.

ClamAVInstallation

Install ClamAV:

yum install clamav-server clamav-data clamav-update clamav-filesystem clamav clamav-scanner-systemd clamav-devel clamav-lib clamav-server-systemd

ClamAV will need unrar, it can be installed from rpmforge repository, so:

cd /usr/local/src/

wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el7.rf.x86_64.rpm

rpm -ivh rpmforge-release-0.5.3-1.el7.rf.x86_64.rpm

yum install unrar

After install unrar, I disabled rpmforge repo:

sed -i 's/enabled = 1/enabled = 0/g' /etc/yum.repos.d/rpmforge.repo

freshclam

freshclam will update the virus signature database. To enable it and update:

sed -i -e 's/^Example/#Example/' /etc/freshclam.conf

freshclam -v

Also edit /etc/sysconfig/freshclam, comment out this line as:

#FRESHCLAM_DELAY=disabled-warn # REMOVE ME

The MailScanner will call /usr/local/bin/freshclam to update the database, so make the proper link:

ln -s /usr/bin/freshclam /usr/local/bin/freshclam

clamd daemon

Enable clamd by editing /etc/clamd.d/scan.conf like this:

# Example

LogFile /var/log/clamd.scan

LogTime yes

LogSyslog yes

LogFacility LOG_MAIL

PidFile /var/run/clamd.scan/clamd.pid

LocalSocket /var/run/clamd.scan/clamd.sock

Create the log file:

touch /var/log/clamd.scan

chown :clamscan $_

chmod 0660 $_

Now enable and start the service:

systemctl  enable clamd@scan

systemctl  start clamd@scan

systemctl  status clamd@scan

Test clamd service

I download a virus file (Eicar Test) and send to ClamAV

# cd /tmp

# wget http://www.eicar.org/download/eicar.com

# clamscan --infected --remove eicar.com

eicar.com: Eicar-Test-Signature FOUND

eicar.com: Removed.


----------- SCAN SUMMARY -----------

Known viruses: 4283601

Engine version: 0.98.7

Scanned directories: 0

Scanned files: 1

Infected files: 1

Data scanned: 0.00 MB

Data read: 0.00 MB (ratio 0.00:1)

Time: 21.513 sec (0 m 21 s)

Spamassassin

Install Spamassassin”

yum install spamassassin

Update database:

sa-update

Enable snd start Spamassassin:

systemctl enable spamassassin

systemctl start spamassassin

systemctl status spamassassin

MailScanner

MailScanner work like this:

Install MailScanner

First stop and disable postfix. We will use MailScanner in the future.

systemctl stop postfix

systemctl disable postfix

Download MailScanner and install:

cd /usr/local/src/

wget https://s3.amazonaws.com/mailscanner/release/v4/rpm/MailScanner-4.85.2-3.rpm.tar.gz

tar zvxf MailScanner-4.85.2-3.rpm.tar.gz

cd MailScanner-4.85.2-3

./install.sh

Start the installation. Answer Y to all questions except these three(they have been took care in the previous steps):

Do you want to install a Mail Transfer Agent (MTA)?

I can install an MTA via the Yum package manager to save you the trouble of having to do

this later. If you plan on using an MTA that is not listed below, you will have install

it manually yourself if you have not already done so.

1 - sendmail

2 - postfix

3 - exim

N - Do not install

Recommended: 1 (sendmail)

Install an MTA? [1] : N

Do you want to install or update Spamassassin?

This package is recommended unless you have your own spam detection solution.

Recommended: Y (yes)

Install or update Spamassassin? [n/Y] : N

Do you want to install or update Clam AV during this installation process?

This package is recommended unless you plan on using a different virus scanner.

Note that you may use more than one virus scanner at once with MailScanner.

Even if you already have Clam AV installed you should select this option so I

will know to check the clamav-wrapper and make corrections if required.

Recommended: Y (yes)

Install or update Clam AV? [n/Y] : N

MailScanner Configuration

Edit /etc/MailScanner/MailScanner.conf

%org-name% = mydomain

%org-long-name% = mydomain Ltd.

%web-site% = www.mydomain.com

Incoming Work Group = clamscan

Incoming Work Permissions = 0640

Virus Scanners = clamd

Clamd Socket = /var/run/clamd.scan/clamd.sock

Clamd Use Threads = yes

MTA = postfix

Run As User = postfix

Run As Group = postfix

Incoming Queue Dir = /var/spool/postfix/hold

Outgoing Queue Dir = /var/spool/postfix/incoming

Use SpamAssassin = yes

SpamAssassin User State Dir = /var/spool/MailScanner/spamassassin

SpamScore Number Instead Of Stars = yes

Always Include SpamAssassin Report = yes

Log Spam = yes

Correct a permission to allow write for group clamscan:

chmod -R 770 /var/spool/MailScanner/incoming/

Edit /etc/MailScanner/spam.assassin.prefs.conf

envelope_sender_header X-mydomain-MailScanner-From

Edit /etc/MailScanner/virus.scanners.conf

clamd           /bin/false                           /usr

clamd permission

When clamd scan emails, I want pass --fdpass to it, so it won’t have permssion issue:

mv /usr/bin/clamdscan /usr/bin/clamdscan-cmd

Now create a new file /usr/bin/clamdscan

#!/bin/bash

/usr/bin/clamdscan-cmd --fdpass $@

Make it executable:

chmod +x /usr/bin/clamdscan

Postfix hold queue

Let postfix hold all mails for scan, add line at bottom of /etc/postfix/header_checks

/^Received:/  HOLD

Enable header check in Postfix, edit /etc/postfix/main.cf, uncomment this line 548:

header_checks = regexp:/etc/postfix/header_checks

Check MailScanner configration to see if there is any error:

MailScanner --lint

Spamassassin Plugins

With plugins, Spamassassin can detect spam and bulk email better with online resources.

First, I need open some ports on iptables needed by DCC, pyzor and razor. Add these rules to /etc/sysconfig/iptables in the INPUT chain and reload iptables:

### razor DCC pyzor ###

-A INPUT -p tcp --dport 2703 -j ACCEPT

-A INPUT -p udp --dport 24441 -j ACCEPT

-A INPUT -p udp -m udp --dport 1024:65535 --sport 6277 -j ACCEPT

###End of razor DCC pyzor ###

Edit /etc/mail/spamassassin/mailscanner.cf

# paths to utilities

ifplugin Mail::SpamAssassin::Plugin::Pyzor

pyzor_path /usr/bin/pyzor

endif

ifplugin Mail::SpamAssassin::Plugin::DCC

dcc_path /usr/bin/dccproc

dcc_home /etc/dcc

endif

ifplugin Mail::SpamAssassin::Plugin::Razor2

razor_config  /etc/mail/spamassassin/razor/razor-agent.conf

endif

Enable these in spamassassin. Edit /etc/mail/spamassassin/v310.pre

loadplugin Mail::SpamAssassin::Plugin::DCC

loadplugin Mail::SpamAssassin::Plugin::Pyzor

loadplugin Mail::SpamAssassin::Plugin::Razor2

DCC

Install DCC

yum install sendmail-milter

rpm -Uvh  https://www.mirrorservice.org/sites/dl.atrpms.net/el7-x86_64/atrpms/stable/DCC-1.3.145-25.el7.x86_64.rpm

Test

cdcc info

Pyzor

Add a line in /etc/mail/spamassassin/local.cf

pyzor_options --homedir /etc/mail/spamassassin/.pyzor

Install Pyzor:

rpm -Uvh ftp://mirror.switch.ch/pool/4/mirror/fedora/linux/releases/22/Everything/x86_64/os/Packages/p/pyzor-0.5.0-10.fc21.noarch.rpm

pyzor --homedir /etc/mail/spamassassin discover

Test

spamassassin -t -D pyzor < /usr/share/doc/spamassassin-3.4.0/sample-spam.txt

Razor

mkdir  /etc/mail/spamassassin/razor

razor-admin -create -home=/etc/mail/spamassassin/razor

razor-admin -register

Edit /etc/mail/spamassassin/razor/razor-agent.conf

razorhome       = /etc/mail/spamassassin/razor

Test Razor2

spamassassin -t -D razor2 < /usr/share/doc/spamassassin-3.4.0/sample-spam.txt

Test

Check MailScanner configration again:

MailScanner --lint

Also check for SpamAssassin:

spamassassin -D --lint

Now restart services and check maillog to see if any error

systemctl restart clamd@scan

systemctl restart spamassassin

systemctl restart MailScanner

Now I can send some spam test email then check the maillog to see if it has need catched. Here are some test site:

[http://www.emailsecuritycheck.net/]

[https://www.mail-tester.com/]

MailWatch

Download code

cd /usr/local/src

git clone https://github.com/mailwatch/1.2.0.git

MariaDB database

Create a database with downloaded sql file:

cd /usr/local/src/1.2.0

mysql -uroot -p < create.sql

Create a DB user:

# mysql -uroot -p

Enter password:

MariaDB [(none)]> GRANT ALL ON mailscanner.* TO mailwatch@localhost IDENTIFIED BY 'MWpassword';

Query OK, 0 rows affected (1.27 sec)

MariaDB [(none)]> GRANT FILE ON *.* TO mailwatch@localhost IDENTIFIED BY 'MWpassword';

Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;

Query OK, 0 rows affected (0.05 sec)

Admin user

Create an Admin user gao:

# mysql mailscanner -umailwatch -pMWpassword

MariaDB [mailscanner]> INSERT INTO users SET username = 'gao', password = md5('mwpassword'), fullname = 'Gao', type = 'A';

Configure MailWatch

Move the mailscanner directory to the web server’s root

cp -r /usr/local/src/1.2.0/mailscanner /var/www/html/.

chown -R nginx:nginx /var/www/html/mailscanner/

Copy /var/www/html/mailscanner/conf.php.example to conf.php then edit the database setting:

define('DB_TYPE', 'mysql');

define('DB_USER', 'mailwatch');

define('DB_PASS', 'MWpassword');

define('DB_HOST', 'localhost');

define('DB_NAME', 'mailscanner');

define('DB_DSN',  DB_TYPE.'://'.DB_USER.":".DB_PASS."@".DB_HOST."/".DB_NAME);

define('TIME_ZONE', 'America/Vancouver');

// Log file location

define('MS_LOG', '/var/log/maillog');

define('MAIL_LOG', '/var/log/maillog');

// Date/Time settings

define('DATE_FORMAT', '%y-%m-%d');

define('TIME_FORMAT', '%H:%i:%s');

Now stop MailScanner

systemctl stop MailScanner

Edit /etc/MailScanner/MailScanner.conf

Always Looked Up Last = &MailWatchLogging

Detailed Spam Report = yes

Quarantine Whole Message = yes

Quarantine Whole Messages As Queue Files = no

Include Scores In SpamAssassin Report = yes

Quarantine User = root

Quarantine Group = nginx

Quarantine Permissions = 0660

Is Definitely Not Spam = &SQLWhitelist

Is Definitely Spam = &SQLBlacklist

Copy Perl module to CustomFunctions

cp /usr/local/src/1.2.0/MailScanner_perl_scripts/SQLBlackWhiteList.pm /usr/share/MailScanner/MailScanner/CustomFunctions/

cp /usr/local/src/1.2.0/MailScanner_perl_scripts/MailWatch.pm /usr/share/MailScanner/MailScanner/CustomFunctions/.

Edit /usr/share/MailScanner/MailScanner/CustomFunctions/SQLBlackWhiteList.pm

sub CreateList {

 my($type, $BlackWhite) = @_;

 my($dbh, $sth, $sql, $to_address, $from_address, $count, $filter);

 my($db_name) = 'mailscanner';

 my($db_host) = 'localhost';

 my($db_user) = 'mailwatch';

 my($db_pass) = 'MWpassword';

...

Edit /usr/share/MailScanner/MailScanner/CustomFunctions/MailWatch.pm

# Modify this as necessary for your configuration

my($db_name) = 'mailscanner';

my($db_host) = 'localhost';

my($db_user) = 'mailwatch';

my($db_pass) = 'MWpassword';

...

I also installed a perl module Encoding::FixLatin in CPAN:

# cpan

cpan[1]> install Encoding::FixLatin

...

Start MailScanner again, check /var/log/maillog for any error.

Nginx configuration

Create a new nginx virtual host configration file /etc/nginx/conf.d/mailwatch.conf

server {

 listen 80;

 server_name mailwatch.mydomain.com;

 return 301 https://$server_name$request_uri; # enforce https

}

server {

  listen          443 ssl;

  server_name     mailwatch.mydomain.com;

  root            /var/www/html/mailscanner;

  index           index.php;

  charset         utf-8;

  ## SSL settings

  ssl_certificate           /etc/letsencrypt/live/mydomain.com/fullchain.pem;

  ssl_certificate_key           /etc/letsencrypt/live/mydomain.com/privkey.pem;

  ssl_protocols             TLSv1.2 TLSv1.1 TLSv1;

  ssl_prefer_server_ciphers on;

  ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";

  ssl_dhparam     /etc/nginx/dhparams.pem;

  ssl_session_cache         shared:SSL:10m;

  ssl_session_timeout       10m;

  ssl_ecdh_curve            secp521r1;

  add_header Strict-Transport-Security max-age=31536000;

  # add_header X-Frame-Options DENY;

  # auth_basic "Restricted area";

  # auth_basic_user_file /etc/nginx/passwd;

  location / {

     try_files $uri $uri/ index.php;

  }

  location ~ \.php$ {

       try_files $uri =404;

       fastcgi_split_path_info ^(.+\.php)(/.+)$;

       fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

       include       fastcgi_params;

       fastcgi_pass  unix:/run/php-fpm/php-fpm.sock;

       fastcgi_index index.php;

  }

}

Mail queue

Configure mail queue directory:

chown -R postfix:nginx /var/spool/postfix/hold

chown -R postfix:nginx /var/spool/postfix/incoming

chmod -R 770 /var/spool/postfix/hold

chmod -R 770 /var/spool/postfix/incoming/

Test

Restart Nginx:

systemctl restart nginx

Now it’s time to go to https://mailwatch.mydomain.com/

Login as admin user “gao” with password “mwpassword”

Go to http://www.emailsecuritycheck.net/ and send myself some spam and virus, check MailWatch to see the result.

 There are few tools came with MailWatch souce code in the "tools" directory. You may need to setup them following the instruction.

SpamAssassin Bayes

SpamAssassin Bayes can try to identify spam (or ham) by learning tokens. Here I configrue it with MailWatch installed.

Edit /etc/MailScanner/spam.assassin.prefs.conf

bayes_path /etc/MailScanner/bayes/bayes

bayes_file_mode 0660

bayes_ignore_header X-mydomain-COM-MailScanner

bayes_ignore_header X-mydomain-COM-MailScanner-SpamCheck

bayes_ignore_header X-mydomain-COM-MailScanner-SpamScore

bayes_ignore_header X-mydomain-COM-MailScanner-Information

Create the ‘new’ bayes directory, make the directory owned by the same group as the web server user and make the directory setgid:

mkdir /etc/MailScanner/bayes

chown root:nginx /etc/MailScanner/bayes

chmod g+rws /etc/MailScanner/bayes

Since I already some spam mails in quarantine, so I force a sa-learn

sa-learn --spam /var/spool/MailScanner/quarantine/20160420

After this I see few files have been generated in bayes home directory:

# ll /etc/MailScanner/bayes/

total 28

-rw-rw---- 1 root nginx    50 Mar 11 21:18 bayes.mutex

-rw-rw---- 1 root nginx 12288 Mar 11 21:18 bayes_seen

-rw-rw---- 1 root nginx 12288 Mar 11 21:18 bayes_toks

Test to see bayes work

spamassassin -D -p /etc/MailScanner/spam.assassin.prefs.conf --lint

shoud see these lines:

Mar 11 21:20:27.020 [6494] dbg: bayes: tie-ing to DB file R/O /etc/MailScanner/bayes/bayes_toks

Mar 11 21:20:27.022 [6494] dbg: bayes: tie-ing to DB file R/O /etc/MailScanner/bayes/bayes_seen

Mar 11 21:20:27.024 [6494] dbg: bayes: found bayes db version 3

Mar 11 21:20:27.025 [6494] dbg: bayes: DB journal sync: last sync: 0

Mar 11 21:20:27.026 [6494] dbg: bayes: not available for scanning, only 2 spam(s) in bayes DB < 200

Mar 11 21:20:27.026 [6494] dbg: bayes: untie-ing

It can also be verified in MailWatch in “Tools/Link” –> “Spamassassin Bayes Database Info”

Now restart Spamassassin and MailScanner and check maillog.

 Now I have an email server with protections. Unforturnatly this is just a start. There are so many things need further configuration to improve the security of the mail system.

Quick links:

#MariaDB #Postfix #Dovecot #MailScanner

 Email Server With Postfix Dovecot and MailScanner (Part 2 - Postfix and Dovecot) Email Server With Postfix Dovecot and MailScanner (Part 4 - SPF DKIM and DMARC) 

Email Server With Postfix Dovecot and MailScanner (Part 4 - SPF DKIM and DMARC)

Posted on 2016-04-21   |   In Email Server   |   6 Comments

Both SPF and DKIM has two parts: One is the DNS records for SPF/DKIM serve the purpose of setting your own policy for others to check. The other is to check if the incoming mail message is in accordance with the SPF/DKIM that is set by the admins of the domain from which the message was sent.

SPF

DNS txt record

Add a txt record to DNS server:

@ TXT 300 v=spf1 a ip4:11.22.33.44/32 include:mydomain.com ~all

Test it by sending an email to check-auth@verifier.port25.com and will get a report back.

SPF on Postfix

To prevent sender address forgery, we setup The Sender Policy Framework (SPF) on the postfix. When there is an incoming email, postfix will check the SPF record.

yum install perl-Mail-SPF perl-Sys-Hostname-Long

cd /usr/local/src

wget https://launchpad.net/postfix-policyd-spf-perl/trunk/release2.010/+download/postfix-policyd-spf-perl-2.010.tar.gz

tar zvxf postfix-policyd-spf-perl-2.010.tar.gz

cd postfix-policyd-spf-perl-2.010

cp postfix-policyd-spf-perl /usr/local/sbin/.

Then edit /etc/postfix/master.cf and add the following stanza at the end:

[...]

policy     unix  -       n       n       -       -       spawn

       user=nobody argv=/usr/bin/perl /usr/local/sbin/postfix-policyd-spf-perl

(The leading spaces before user=nobody ... are important so that Postfix knows that this line belongs to the previous one!)

Then open /etc/postfix/main.cf and search for the smtpd_recipient_restrictions directive. You should have reject_unauth_destination in that directive, and right after reject_unauth_destination you add check_policy_service unix:private/policy like this:

smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, check_policy_service unix:private/policy

policy_time_limit = 3600

Restart MailScanner, send an email from gmail to gao@mydomain.com, in header:

Received-SPF: pass (gmail.com ... _spf.google.com: Sender is authorized to use 'gao@gmail.com' in 'mfrom' identity (mechanism 'include:_netblocks.google.com' matched)) receiver=szeta; identity=mailfrom; envelope-from="gao@gmail.com"; helo=mail-pa0-f48.google.com; client-ip=209.85.220.48

DKIM

OpenDKIM

Install OpenDKIM

yum install opendkim

Generate keys for signing

You need to generate a private and a public key for each of the domains for which you wish to sign mail. The private key is stored away on your server, while the public key gets published in your domain’s DNS records so that receiving mail servers can verify your DKIM-signed mail.

You need decide now what the name of your selector is going to be. A selector is a unique keyword that is associated with both keys (public and private), included in all the signatures, and published in your DNS records. For simplicity, I use the word szeta as my default selector.

mkdir -p /etc/opendkim/keys/mydomain.com

/usr/sbin/opendkim-genkey -D /etc/opendkim/keys/mydomain.com/ -d mydomain.com -s szeta

Now we have two files for each domain(the text file is the public key).

chown -R opendkim:opendkim /etc/opendkim/keys/*

Edit four configuration files:

Now enable OpenDKIM in Postfix, edit /etc/postfix/main.cf, add

smtpd_milters = inet:127.0.0.1:8891

non_smtpd_milters = $smtpd_milters

milter_default_action = accept

Now start services

systemctl enable opendkim

systemctl start opendkim

systemctl restart MailScanner

DNS txt record

Now that the mail server is signing outgoing mail and verifying incoming mail, you’ll need to put some information in your DNS records to tell other mail servers how your keys are set up, and provide the public key for them to check that your mail is properly signed.

Use the public key created above to add a DNS TEXT record to mydomain.com.

Check:

$ dig szeta._domainkey.mydomain.com TXT +noall +answer

szeta._domainkey.mydomain.com. 3599 IN TXT  "v=DKIM1\; k=rsa\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGYaonAHWmVitTa9p4QRmtjobBRyWflXwCa3akQ87aJ2iT8bg/25/t7dwzOq4nRS9CoW6vu9gVPBS6hWIumRoWFwYfwgUXGWCxMQLr6Nc7wuKnqPOoA6/JTa0s1o0QWiY18k1Rsh8p4/oRQilCEVjvdezRxsIigIEGUlEn9a+xqwIDAQAB"

Test

Restart MailScanner then send email to check-auth@verifier.port25.com then read the report, also analyse header as well.

DMARC

A DMARC policy allows a sender to indicate that their emails are protected by SPF and/or DKIM, and give instruction if neither of those authentication methods passes. Please be sure you have a DKIM and SPF set before using DMARC.

To enable DMARC, just add a TXT DNS record. Host name is _dmarc and text value is v=DMARC1; p=none ;rua=mailto:postmaster@mydomain.com

To check:

# dig _dmarc.mydomain.com TXT +noall +answer

_dmarc.mydomain.com.  7207  IN  TXT  "v=DMARC1\;p=none\;rua=mailto:postmaster@mydomain.com"

Email Server With Postfix Dovecot and MailScanner (Part 5 - Roundcube webmail)

Posted on 2016-04-25   |   In Email Server   |   0 Comments

Roundcube is a free opensource web-based IMAP email client. It provides full functionality you expect from an email client, including MIME support, address book, folder manipulation, message searching and spell checking. At the time of this writing, Roundcube just released v1.1.5.

Download souce code

cd /usr/local/src/

wget https://github.com/roundcube/roundcubemail/releases/download/1.1.5/roundcubemail-1.1.5-complete.tar.gz

tar zvxf roundcubemail-1.1.5-complete.tar.gz

Now copy the source code to web root:

cp -r /usr/local/src/roundcubemail-1.1.5 /var/www/html/roundcubemail

chown -R nginx:nginx /var/www/html/roundcubemail

Database

Roundcube uses MariaDB as the backend database. So create a database and add a database user:

#mysql -uroot -p

CREATE DATABASE roundcubemail;

GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost  IDENTIFIED BY 'RCpassword';

FLUSH PRIVILEGES;

quit

Nginx Configuration

Create a new Nginx site configrration file /etc/nginx/conf.d/roundcube.conf

server {

 listen 80;

 server_name roundcube.mydomain.com;

 return 301 https://$server_name$request_uri; # enforce https

}

server {

  listen          443 ssl;

  server_name     roundcube.mydomain.com;

  root            /var/www/html/roundcubemail;

  index           index.php;

  charset         utf-8;

  ## SSL settings

  ssl_certificate           /etc/letsencrypt/live/mydomain.com/fullchain.pem;

  ssl_certificate_key           /etc/letsencrypt/live/mydomain.com/privkey.pem;

  ssl_protocols             TLSv1.2 TLSv1.1 TLSv1;

  ssl_prefer_server_ciphers on;

  ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";

  ssl_dhparam               /etc/nginx/dhparams.pem;

  ssl_session_cache         shared:SSL:10m;

  ssl_session_timeout       10m;

  ssl_ecdh_curve            secp521r1;

  add_header Strict-Transport-Security max-age=31536000;

  # add_header X-Frame-Options DENY;

  # auth_basic "Restricted area";

  # auth_basic_user_file /etc/nginx/passwd;

  location / {

     try_files $uri $uri/ index.php;

  }

  location ~ \.php$ {

       try_files $uri =404;

       fastcgi_split_path_info ^(.+\.php)(/.+)$;

       fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

       include       fastcgi_params;

       fastcgi_pass  unix:/run/php-fpm/php-fpm.sock;

       fastcgi_index index.php;

  }

}

Reload Nginx

systemctl reload nginx

Web installation

Now I can start installation by go to https://roundcube.mydomain.com/installer/

Check environment

First the RouncCube installer will check the environment. There may be some items show as “NOT AVAILABLE”, for these items I only need make sure what I needed is “OK”

I found that it complain that “Mcrypt” and “Intl” PHP modules shows as “NOT AVALIABLE”, so let’s intall them and restart PHP-FPM”

yum -y install php-mcrypt php-intl

systemctl restart php-fpm

Then refreash the web page and now the environment is ready. Click “NEXT” button to go on.

Create config

Fill the “Database password”. Also fill in SMTP and IMAP configration. Create the config file

 Don't warray to much about put in wrong configration inforamtion on the IMAP and SMTP sections. I will fix them later by manually editing the configration file later.

Test config

Go ahead to inatialize database.

When test SMTP and IMAP there are errors. I manually edited the configured file config/config.inc.php

// ----------------------------------

// SQL DATABASE

// ----------------------------------

$config['db_dsnw'] = 'mysql://roundcube:RCpassword@localhost/roundcubemail';

// ----------------------------------

// IMAP

// ----------------------------------

$config['default_host'] = 'ssl://smtp.mydomain.com';

$config['default_port'] = 993;

$config['imap_auth_type'] = 'PLAIN';

// ----------------------------------

// SMTP

// ----------------------------------

$config['smtp_server'] = 'tls://smtp.mydomain.com';

$config['smtp_port'] = 587;

$config['smtp_auth_type'] = 'PLAIN';

$config['smtp_user'] = '%u';

$config['smtp_pass'] = '%p';

Save the configration file. To test again, go back to

https://roundcube.mydomain.com/installer/index.php?_step=1

All tests passed. Last remove the installer folder.

rm -rf /var/www/html/roundcubemail/installer

Now Roundcube wabmail is working. I can use it at https://roundcube.mydomain.com/

Sieve filter

One of the reason I use Dovecot is that I need to use Sieve filter in RoundCube Mail, so user can setup their own filter such as Vacation Autoresponse.

LMTP

Till now my mail server use Postfix as the LDA(Local Delivery Agent) to diliver mails to users maildir. For sieve to work we need to use dovecot as a LDA. This means that dovecot has to write the email to the email folder of the user for the final delivery.

We will configure dovecot acting as local delivery using LMTP. (The other option is using LDA, which works like a binary command, each time that postfix sends a email lda deliver is called.)

Configure LMTP by editing /etc/dovecot/conf.d/10-master.conf

service lmtp {

  unix_listener /var/spool/postfix/private/dovecot-lmtp {

    group = postfix

    mode = 0600

    user = postfix

   }

 unix_listener lmtp {

   #mode = 0666

  }


 # Create inet listener only if you can't use the above UNIX socket

 #inet_listener lmtp {

   # Avoid making LMTP visible for the entire internet

   #address =

   #port =

 #}

}

Also set up a postmaster addr at /etc/dovecot/conf.d/20-lmtp.conf

protocol lmtp {

postmaster_address = postmaster@yourdomain.com

}

Then we will enable lmtp protocol in /etc/dovecot/dovecot.conf

protocols = imap pop3  lmtp

Now I need tell Postfix to use Dovecot LDA, edit /etc/postfix/main.cf add lines:

#use dovecot lmtp as virtual transport

virtual_transport = lmtp:unix:private/dovecot-lmtp

Restart Dovecot and MailScanner, send a test email then check maillog to see LMTP in action for local delivery:

Apr 24 13:29:32 smtp dovecot: master: Dovecot v2.2.10 starting up for imap, pop3, lmtp (core dumps disabled)

...

Apr 24 13:32:34 smtp dovecot: lmtp(3544): Connect from local

Apr 24 13:32:35 smtp dovecot: lmtp(3544, gao@mydomain.com): ZIvkJGJx6FbYDQAA1qURPQ: msgid=<56E8714F.4060405@gmail.com>: saved mail to INBOX

Apr 24 13:32:35 smtp postfix/lmtp[3543]: D23571331C6: to=<gao@mydomain.com>, relay=smtp.mydomain.com[private/dovecot-lmtp], delay=12, delays=11/0.31/0.24/0.81, dsn=2.0.0, status=sent (250 2.0.0 <gao@mydomain.com> ZIvkJGJx6FbYDQAA1qURPQ Saved)

Apr 24 13:32:35 smtp dovecot: lmtp(3544): Disconnect from local: Successful quit

Apr 24 13:32:35 smtp postfix/qmgr[3461]: D23571331C6: removed

Managesieve

I use dovecot-pigeonhole and it’s been installed already.

Enable sieve filter, edit /etc/dovecot/conf.d/20-lmtp.conf

protocol lmtp {

 # Space separated list of plugins to load (default is global mail_plugins).

 mail_plugins = $mail_plugins sieve

 postmaster_address = postmaster@mydomain.com

}

Configure sieve, edit /etc/dovecot/conf.d/90-sieve.conf

plugin {

 # The path to the user's main active script. If ManageSieve is used, this the

 # location of the symbolic link controlled by ManageSieve.

 sieve = ~/sieve/.dovecot.sieve

 sieve_dir = ~/sieve

...

}

Configure managesieve, edit /etc/dovecot/conf.d/20-managesieve.conf

protocols = $protocols sieve

service managesieve-login {

 inet_listener sieve {

   port = 4190

 }

...

}

(Note, make sure all brackets are closed properly.)

Now restart Dovecot then test to see if managesieve works:

# telnet localhost 4190

Trying ::1...

telnet: connect to address ::1: Connection refused

Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

"IMPLEMENTATION" "Dovecot Pigeonhole"

"SIEVE" "fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date ihave"

"NOTIFY" "mailto"

"SASL" "PLAIN LOGIN CRAM-MD5"

"STARTTLS"

"VERSION" "1.0"

OK "Dovecot ready."

^]

telnet> quit

Connection closed.

Roundcube Plugin SieveRules

I will install the SieveRules plugin created by JohnDoh at Github:

https://github.com/JohnDoh/Roundcube-Plugin-SieveRules-Managesieve

Save to roundcube plugins folder as /var/www/html/roundcube/plugins/sieverules

Then make a config.inc.php from config.inc.php.dist

cd /usr/local/src/

git clone https://github.com/JohnDoh/Roundcube-Plugin-SieveRules-Managesieve

cp -r Roundcube-Plugin-SieveRules-Managesieve /var/www/html/roundcubemail/plugins/sieverules

cd /var/www/html/roundcubemail/plugins/sieverules

cp config.inc.php.dist config.inc.php

chown -R nginx:nginx /var/www/html/roundcubemail/plugins/sieverules

Edit /var/www/html/roundcubemail/plugins/sieverules/config.inc.php, set

$config['sieverules_auth_type'] = 'PLAIN';

Last add the plugin to /var/www/html/roundcube/config/config.inc.php:

// List of active plugins (in plugins/ directory)

$config['plugins'] = array(

   'archive',

   'zipdownload',

   'fail2ban',

   'password',

   'jqueryui',

   'sieverules',

);

(Note: jqueryui is needed for this plugin to work.)

Now login to Roundcube webmail to create a filter and test it.

---

--------