« HOWTO: Install Ubuntu Server as a VirtualBox GuestHOWTO: Convert from single disk to RAID 1 without reinstalling »

Setting up a Professional Quality Mail Server with Ubuntu Karmic Server 9.10.

07/11/09

Setting up a Professional Quality Mail Server with Ubuntu Karmic Server 9.10.

Introduction

Why I wrote this.

I wrote this HOWTO after following many other HOWTOs for Postfix and Exim and finding that parts did not work or did not explain how things worked. In short I spent many hours installing and reinstalling, playing around with settings and generally having fun. (I need to get a life) I wrote this HOWTO as record of what I did to get my own mail server up and running. I can now and in the future follow these steps again and rebuild my own mail server. I hope it is of use to others too.

Follow up:


We will run through the setup of this one step at a time, hopefully not making any huge steps. You will be able to test the parts installed as we go, no huge big bangs. All this as we move gently towards our goal of a professional quality mail server running on Ubuntu Karmic Koala 9.10.

I am not a Linux expert or security guru so there are probably some holes in the security of this server. If you believe that, please, let me know what and why.

Backups are important
Note: You are strongly recommended to take backup copies of your system and all files before you start and as we progress through the HOWTO.

Feedback.

Feedback is most certainly welcome for this HOWTO. Send your comments, criticisms and suggestions for additions or changes using the comment options below or via email using the link. I will try to reply as needed.

What This HOWTO Will Be Building.

Overview of the system.

The mail server this HOWTO will be building is called mailserver and will be running Ubuntu Karmic Koala 9.10 server edition. mailserver will run as a Vmware guest which allows for simple backups if nothing else. mailserver will be part of the example.com domain with a sister domain example.net.

mailserver.example.com local IP 192.168.0.11
internet IP 1.2.3.4

Services provided on mailserver

The server called mailserver will end up running the following servers and services.

  • Postfix mail server.
    • Delivering email to one or more local users.
    • Email recipients will not have to have a Linux account.
    • Forwarding mail to remote users, from a lookup list only
    • Relaying emails to the outside world
    • Authentication and encryption TLS/SSL
    • Emails will be checked with anti-virus service ClamAV or AVG Free
    • Emails will be checked with anti-spam filters from Spamassassin
    • Grey listing of incoming mail servers
  • Apache Web server.
    • Secure HTTPS access
    • Automatic rewriting of URLs
    • Setting up virtual servers
    • User friendly URLs
  • MySQL Database
  • Firewall
  • SqurirrelMail
    • Add-on for Changing passwords
    • Add-on for creating aliases or forwarding addresses

Install Karmic Koala Server Edition.

We are starting from a new install of Ubuntu Karmic Koala Server with no other software installed. During the installation process there will be a menu asking what other servers should be installed. Do not select any at this time.

See my HOWTO: Install Ubuntu Server as a VirtualBox Guest For step by step instructions on how to set this up.

After the install is done make sure it is all up to date with the latest patches and security updates.

sudo apt-get update
sudo apt-get dist-upgrade



Install and setup ssh. You can then ssh to mailserver. Copy and paste work better and you can make the terminals bigger. The bigger terminals make editing much easier. :!:


install nfs autofs. These make transfering files simpler. I used these mappings a lot while writing this HOWTO as I installed the complete system a number of times. If at first you don't succeed, go and have another beer.


network interface. Get this sorted out so mailserver has a static IP address.

Make sure that the full qualified domain name is setup and displayed correctly.

hostname --fqdn

The command above should be displaying the following for the example server.

mailserver.example.com

It is does not the problem can be solved by editing the hosts file as fiollows.

sudo nano /etc/hosts
192.168.0.11 mailserver.example.com mailserver

Note that the FQDN is first in the list and the short name without the domain part is not.

Backup point
This would be a good backup point! 
You can always restore back to this point if you mess up on the way. 

MySQL

How Postfix talks to MySQL

We are going to create a bunch of map files that tell Postfix how to get the information out of the MySQL database. They are fairly simple and I am sure you will work out how they do their mapping without explanation. In each file change

to be what you used as your password for the MySQL user mail. Also, when setting the hosts value do not use localhost, Use the IP address 127.0.0.1, which although it is also localhost it will force postfix to use TCP/IP and not a local socket. This will allow you to run Postfix chrooted and is slightly more secure.

Installing MySQL

Installing MySQL we need the server and front end tools these will all be installed with the following command.

Install MySQL Server
sudo apt-get install mysql-server

When the installation process starts you will be asked for a root password. This is the password for the root user of MySQL this is not the same as the root user on the Linux system

Configuring MySQL

We will edit the system MySQL my.cnf file to check on access and get some logging to happen.

/etc/mysql/my.cnf
sudo nano /etc/mysql/my.cnf

We want to bind to 127.0.0.1 not localhost. This a means there can be no connections from remote machines, which means that we have a security advantage in that only local users can access the MySQL database. It should already be set as it is the default.

bind-address = 127.0.0.1

I find it is helpful to see what the mysql DB is doing especially in the early stages. Use this option to start the logging of any calls that are made to MySQL. It is probably commented out.

general_log_file        = /var/log/mysql/mysql.log 
general_log             = 1 

Then in a few weeks comment those out again when everything is working, as the logging slows mysql down. Restart the MySQL daemon

sudo /etc/init.d/mysql restart

Creating the Database

To create a MySQL database is very simple from the command line. We will be calling our database 'postfix' as it is
for Postfix and I like to keep things simple. :) We need to login as then user root and tell the command to ask for a password. We do that with the following command:

Create the Postfix database
mysqladmin -u root -p create postfix

When you run the command above you will be asked for a password. It is the MySQL password for root, it is the one you entered when you installed MySQL server. There is no feedback in the way of text output to say the database was created. If you want to check you can login to the database using the mysql command and issue the show databases command.If all went well you will see a line with postfix.

mysql -u root -p
mysql> show databases; 
+--------------------+ 
| Database           | 
+--------------------+ 
| information_schema |  
| mysql              |  
| postfix            |  
+--------------------+ 
3 rows in set (0.00 sec)

The other way to monitor what is going on behind the scenes with MySQL is to watch the mysql log file. Open a new terminal and use the following command to follow the end of the log file as it is written.

tail -f /var/log/mysql/mysql.log

Creating our MySQL User

We will be needing a user with restricted permissions to access the tables for lookups. This user will only need to SELECT data never INSERTing or UPDATEing if you are not intending to allow users to change their own passwords and aliases with SquirrelMail. If you are going to allow them to change their own password then read on a little further. From the command line we will open up a session as we did above.

mysql -u root -p

and enter this SQL command when you see the mysql> prompt:

GRANT SELECT ON postfix.* TO mail@localhost IDENTIFIED BY 'yourpassword';

This will create a new user called mail who just has SELECT access to our database. To get these new permissions noticed by Mysql you need to flush them. So before you exit the mysql prompt use the following command.

flush privileges;

If you are intending on using Squirrelmail as web front end to allow users to create, amend and delete their aliases or change their passwords. Then we need to give mail some extra privileges. We will do it now while we are here. Use the line below from the mysql> prompt and then flush the privileges.

GRANT SELECT, INSERT, UPDATE, DELETE ON postfix.* TO mail@localhost IDENTIFIED BY 'your-password';
use mysql
SELECT user, Password FROM user where user = 'mail';
Query OK, 0 rows affected (0.00 sec) 
 
use mysql 
Reading table information for completion of table and column names 
You can turn off this feature to get a quicker startup with -A 
 
Database changed 
 
+------+-------------------------------------------+ 
| user | Password                                  | 
+------+-------------------------------------------+ 
| mail | *E18AD7C50020B1483DHD5OP0D92C2AA45DDDD123 | 
+------+-------------------------------------------+ 
1 row in set (0.00 sec)

Creating the tables

We will be using three tables to interface between Postfix and MySQL. The way I create them it to add the SQL commands to a text file and then load them in via the mysql command. This saves a lot of typing. It also means that when you are testing it is easy to delete all the data and start again.

USE postfix;  
 
DROP TABLE IF EXISTS domain;  
CREATE TABLE domain (  
  domain       VARCHAR(50) NOT NULL,  
  PRIMARY KEY (domain)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
 
DROP TABLE IF EXISTS user;  
CREATE TABLE user (  
   email        VARCHAR(100) NOT NULL,  
   domain       VARCHAR(50)  NOT NULL,  
   password     VARCHAR(32)  NOT NULL,  
   PRIMARY KEY (email) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
 
DROP TABLE IF EXISTS alias; 
CREATE TABLE alias (  
   id           INT NOT NULL auto_increment, 
   source       VARCHAR(100) NOT NULL,  
   destination  VARCHAR(100) NOT NULL,  
PRIMARY KEY (id) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
 
/* Squirrelmail tables below */ 
DROP TABLE IF EXISTS address; 
CREATE TABLE address (  
   owner varchar(128) NOT NULL default '', 
   nickname varchar(16) NOT NULL default '', 
   firstname varchar(128) NOT NULL default '', 
   lastname varchar(128) NOT NULL default '', 
   email varchar(128) NOT NULL default '', 
   label varchar(255) default NULL, 
   PRIMARY KEY (owner,nickname),  
   KEY firstname (firstname,lastname) 
)  ENGINE=InnoDB DEFAULT CHARSET=utf8; 
 
DROP TABLE IF EXISTS userprefs; 
CREATE TABLE userprefs ( 
   user varchar(128) NOT NULL default '', 
   prefkey varchar(50) NOT NULL default '', 
   prefval varchar(255) default NULL, 
   modified timestamp(14) NOT NULL, 
   PRIMARY KEY (user,prefkey) 
)  ENGINE=InnoDB DEFAULT CHARSET=utf8;  

Create an blank file and add the text above to a file called create_postfix_mysql_tables.sql and save it. You can then load that file and issue the commands it contains with the following:

mysql -u root -p < create_postfix_mysql_tables.sql

If you want to see that the tables have now been created use the following.

mysql -u root -p postfix
mysql> show tables; 
+-------------------+ 
| Tables_in_postfix | 
+-------------------+ 
| address           |  
| alias             |  
| domain            |  
| user              |  
| userprefs         |  
+-------------------+ 
5 rows in set (0.00 sec) 
Backup point
This would be a good backup point! 
 

Postfix

Installing Postfix

Now we get to install the star of this HOWTO, postfix. we need the MySQL add-ons which we get from postfix-mysql. That will in turn install postfix.

sudo apt-get install postfix-mysql

While these packages are installing you will be asked some questions:


General type of mail configuration: Internet Site
System mail name: mailserver.example.com

Create Postfix map files for MySQL

The Postfix map files are how we tell Postfix to talk to the MySQL database. Each file contains data telling Postfix how it can connect and send a query to the database and therefore retrieve the data it requires. Once these map files are created we will add them to the Postfix configuration file /etc/postfix/main.cf using the command line tool postconf. The resulting change will automatically be written to the file and the postfix configuration will be reloaded.

Mapping valid Domains

How to find valid domains within our system. This table holds one row for each domain that our mailserver will be accepting mail for and that it will deliver to the end user. With an editor create the domain lookup file with the following details. You will need to change the password from

to whatever you are using as the password for your MySQL user "mail".
sudo nano /etc/postfix/mysql-virtual-mailbox-domains.cf
/etc/postfix/mysql-virtual-mailbox-domains.cf
user = mail  
hosts = 127.0.0.1  
dbname = postfix  
password = <mysqlpasswd>  
table = domain  
query = SELECT domain FROM domain WHERE domain = '%s'

Add the line to /etc/postfix/main.cf from the command line.

/etc/postfix/main.cf
sudo postconf -e virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf

Mapping Users

As we are intending to use our mailserver to deliver emails to users including but not limited to those that also have Linux accounts. We need to use virtual mappings. This is so Postfix will know where to deliver the email to. That is the directory on the file system. We certainly do not want to create a user account and home directory for all our email users. We will define a top level directory /var/vmail where the email will be stored. The data held in the mappings in the virtual tables will be used to construct the bottom of the directory tree. The actual location of the Maildir subdirectory. For each user we will have:

TOP_LEVEL/<domain>/<email_name>/



Following the Postfix specification, we put a '/' at the end to tell Postfix it is a Maildir and not a mbox file.

sudo nano /etc/postfix/mysql-virtual-mailbox-maps.cf
/etc/postfix/mysql-virtual-mailbox-maps.cf
user = mail  
hosts = 127.0.0.1  
dbname = postfix  
password = <mysqlpasswd>  
query =  SELECT email FROM user WHERE email='%s' 
/etc/postfix/main.cf
sudo postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

Mapping aliases to Users

This maps aliases to real email addresses. This means that one destination can have many email addresses. In a company all the emails for support@example.com and info@example.com will be delivered to fred@example.com. Harry is the IT administrator and therefore gets mail that is not addressed to anyone inparticular. Harry will get mail that cannot be delivered anywhere else. This is a catch all email alias. This can also be used as an effective anti-spam system. Whenever you deal with a new company simply create a new email alias from_

@example.com aliased to your own real email address. If you start getting spam on that address you know they are spamming you or they have sold your address on. Either way you know it's a company you no longer wish to deal with. You can remove the email listing and no more spam from them. If there is no catch all email setup then those spam emails get thrown away.
sudo nano /etc/postfix/mysql-virtual-alias-maps.cf
/etc/postfix/mysql-virtual-alias-maps.cf
user = mail  
hosts = 127.0.0.1  
dbname = postfix  
password = <mysqlpasswd>  
query = SELECT destination FROM alias WHERE source = '%s' 
/etc/postfix/main.cf
sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Assuming that all worked as before we can move on to that last mapping.

This mapping table is used as part of the virtual_alias_maps mapping and saves you having to map every user back to themselves. Why would you need to do that? You ask. See below it is to do with the way catch all addresses work.

sudo nano /etc/postfix/mysql-virtual-alias-maps-self.cf
/etc/postfix/mysql-virtual-alias-maps-self.cf
user = mail 
hosts = 127.0.0.1  
dbname = postfix  
password = <mysqlpasswd>  
query = SELECT email FROM user WHERE email = '%s'  
sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf, \
                                   mysql:/etc/postfix/mysql-virtual-alias-maps-self.cf
As these lookup tables all contain passwords in open text they should not be world readable. We can do that by restricting the group and removing all world permissions.
sudo chgrp postfix /etc/postfix/mysql-*.cf  sudo chmod 640 /etc/postfix/mysql-*.cf  
ls -l /etc/postfix/mysql-*.cf
-rw-r----- 1 root postfix 124 2009-11-12 16:46 /etc/postfix/mysql-virtual-alias-maps.cf 
-rw-r----- 1 root postfix 116 2009-11-12 16:46 /etc/postfix/mysql-virtual-alias-maps-self.cf 
-rw-r----- 1 root postfix 135 2009-11-12 16:45 /etc/postfix/mysql-virtual-mailbox-domains.cf 
-rw-r----- 1 root postfix 114 2009-11-12 16:46 /etc/postfix/mysql-virtual-mailbox-maps.cf 

Aliases are the mechanism that allows mail to be delivered in a very flexible way with a very simple setup. That is the users get their mail and you don't have too much extra work. ;)

Creating Some Test Users

To test those MySQL tables and the interface between Postfix and MySQL we will add some test data to the database. We can them test that this is working by adding some test data and using the postmap command to read it back.

I also put the SQL required to build up some test data into a file so it can be loaded again when necessary while testing is on going.

USE postfix; 
 
DELETE from domain; 
DELETE from user; 
DELETE from alias; 
 
INSERT INTO domain (domain) values ('example.com'), ('example.net'); 
 
INSERT INTO user (domain, email, password) values 
    ('example.com', 'fred@example.com', MD5('yourpassword')), 
    ('example.net', 'harry@example.net', MD5('yourpassword')); 
 
INSERT INTO alias (source, destination) VALUES 
    ('root', 'fred@example.com'), 
    ('bert@example.com', 'fred@example.com'), 
    ('@example.com', 'harry@example.net');  

You can then rebuild your data base with test data with the following command.

mysql -u root -p postfix < insert_test_data.sql

We can now do some very simple tests to check the Postfix-MySQL interface it working. The fist test will lookup example.com to see if it is valid domain for our system. If it is it will return example.com. Also try this with a domain name that is not valid.

sudo postmap -q example.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf

We can lookup a user to see if they are a real use. This test should return fred@example.com as he is valid.

sudo postmap -q fred@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

This final test checks that aliases are working bert@example.com is an alias for fred@example.com.

sudo postmap -q bert@example.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf
Backup point
This would be a good backup point! 
 

Dovecot

Installing Dovecot

To get POP3 and IMAP features from your mail server we will need Dovecot, it is installed with the command below.

sudo apt-get install dovecot-postfix

Creating a vmail user

As the recipient, for the mail that will have a final destination here, does not require a Linux account some users will not have any home directory to store mails. It is therefore wise and less work to create a virtual user for all incoming mail.

sudo groupadd -g 5010 vmail  
sudo useradd -g vmail -u 5010 vmail -d /var/vmail -m  

Get Dovecot to talk to Postfix

To tell Postfix that Dovecot will be the mail delivery service we add it to the Postfix configuration file /etc/postfix/master.cf.
The second line must be indented or Postfix will think it is the first line for the next service.

sudo nano /etc/postfix/master.cf
dovecot   unix  -       n       n       -       -       pipe 
    flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}

(Note: the second line has to start with white space or it will not be taken as an extension of the line above)


At this point I start monitoring /var/log/mail.log in a separate terminal. It will help you when mistakes
are made :) Run the following in a terminal window and leave it running. It will display the end of the log file and then follow it as it grows longer.

Monitor the mail log file
tail -fn90 /var/log/mail.log
Restart Postfix
sudo postfix reload

You should see the output from postfix as it reloads its config files in the window where you are tailing the file.

Also make Postfix use the Dovecot service for virtual delivery by adding these lines to your /etc/postfix/main.cf

sudo postconf -e virtual_transport=dovecot
sudo postconf -e dovecot_destination_recipient_limit=1

Set up Dovecot

Setting up Dovecot is performed by editing its two configuration files. We will not be editing dovecot.cont as Ubuntu has added a new file dovecot-postfix.conf. If the new file exists then it is used and dovecot.conf is not read in. We will not be using that as there are problems with it not creating the Maildir directory structure if it does not already exist. Since we are not usibng the new Ubuntu file we need to move it out of the way and use the main file /etc/dovecot/dovecot.conf.

Backing up is never a waste of time
Make a backup of the original file as this is a file where it is easy to make mistakes. I know I did, all those nested comments.
sudo mv /etc/dovecot/dovecot-postfix.conf /etc/dovecot/dovecot-postfix.conf.not_used
sudo nano /etc/dovecot/dovecotconf

Search for the protocols line and this is where we say which protocols you want to offer to our users. The default line what we will be using with Dovecot. It is already setup for using POP3 and IMAP as well as the secure alternatives over a SSL connection. The default file also has managesieve which can be left in if you are going to use that feature.

protocols = imap imaps pop3 pop3s

There appears to be a problem with some Microsoft mail clients and they need disable_plaintext_auth set to no.
It is less secure if this is done. Another joy of using that software :-( If none of your users are unfortunate to be limited to using that email client you can leave it commented.


While we do the initial testing we will require to enable plain text auth, so set the variable to no.

disable_plaintext_auth = no

Next stop is the option mail_location. If you see the comments above this line the variables are explained. We are setting the MailDir to be under /var/vmail and then using the domain name and then the username as further subdirectories to store this users email. The directories are automatically generated as required hich is rather nice :)

mail_location = maildir:/var/vmail/%d/%n/Maildir

The next setting we need to check is to change is in the section "auth default". You will see that the majority of it is commented out. The first option is to the authentication mechanisms we want to use. Change the line to read as below as necessary.

mechanisms = plain login

As we are using an SQL db to store the users data and their passwords we need to tell dovecot. This is done in the section that is call passwd sql, what a surprise. :) Uncomment the section. This is where the second Dovecot configuration file it effectively turned on. Also uncomment the section userdb sql.

passdb sql { 
    args = /etc/dovecot/dovecot-sql.conf 

 
userdb sql { 
  # Path for SQL configuration file 
  args = /etc/dovecot/dovecot-sql.conf 

Remember when we created the vmail user above we forced the user ID and the group ID to be 5010 this is where we tell dovecot what they are and to point out where the mail boxes will be stored on disk.

userdb static { 
    args = uid=5010 gid=5010 home=/var/vmail/%d/%n allow_all_users=yes 
}

We can also comment out the section called "passdb pam and the one for passdb passwd as these deal with system users. We are only going to be looking for users and passwords in the sql DB so this is not needed. If you leave them live you will see two lines for each in the log file one for the lookup and the other to say the user is unknown.

Comment the entire section
#  passdb pam {
Comment the entire section
#  userdb passwd {



Searching a little further down you will find the section socket listen. This section defines how Dovecot will talk to Postfix for the authentication of the users.

socket listen { 
    master { 
        path = /var/run/dovecot/auth-master 
        mode = 0600 
        user = vmail 
    } 
 
    client { 
        path = /var/spool/postfix/private/dovecot-auth 
        mode = 0660 
        user = postfix 
        group = postfix 
    } 

The Master socket provides access to userdb information. It's typically used to give Dovecot's local delivery agent access to userdb so it can find mailbox locations. The client socket is generally safe to export to everyone. Typical use is to export it to your SMTP server so it can do SMTP AUTH lookups using it.

protocol lda { 
    postmaster_address = postmaster@example.com 
    auth_socket_path = /var/run/dovecot/auth-master 
    log_path = /var/vmail/dovecot-deliver.log 
}

You should change the postmaster email address to a valid one. The address should probably be your email address or an alias to yours, as you are the Administrator. The auth_socket_path is the same path as the one you entered in "socket listen" in the "master" section. While we are testing if you add the log_path value, you can monitor the delivery of emails it will help find errors if they occur.


All done with that configuration file. Save and exit. We can now move on to setting up the SQL connection to Dovecot. These settings are in the file we specified above the section "passdb sql"

sudo nano  /etc/dovecot/dovecot-sql.conf

We only need to change a few settings from the generic values that are given in the original file. Set the drive to mysql as that is the database we are using. The default_pass_scheme list is a list of parameter to allow Dovecot to log into your SQL database. We will be encrypting the passwords that are held on the SQL database so we need to tell Dovecot here. The final value is so Dovecot can check the password against the user as they login.

driver = mysql 
connect = host=127.0.0.1 dbname=postfix user=mail password=yourpassword 
default_pass_scheme = PLAIN-MD5 
password_query = SELECT email as user, password FROM user WHERE email='%u';

We need to fix file system permissions for the /etc/dovecot/dovecot-sql.conf file as it contains the password for the mysql database. Since this file is only read by the app Dovecot while it is being run by root we can restrict these files like we did for the postfix map files. The dovecot.conf file on the other hand needs to be made readable by root and the user vmail. We do that by making the file owned by the group vmail and allowing group read permissions.

sudo  chmod 640 /etc/dovecot/dovecot.conf
sudo chgrp vmail /etc/dovecot/dovecot.conf
sudo  chmod 600 /etc/dovecot/dovecot-sql.conf

We can now restart the Dovecot daemon.

sudo  /etc/init.d/dovecot restart

We can check everything went well and is working by looking at the mail.log file with the tail command.

dovecot: dovecot v1.1.11 starting up 
dovecot: auth-worker(default): mysql: Connected to 127.0.0.1 (mailserver)

Sending Your First Email

Testing SMTP connection with Telnet

Now it's time to send our first email :) Are you sitting down this is a momentous occasion after all! We can use telnet to emulate an email client. We can connect and send our email as below. I have indented the text that is output from the mailserver to make this part a little clearer.

telnet localhost smtp 
    Trying ::1... 
    Trying 127.0.0.1... 
    Connected to localhost. 
    Escape character is '^]'. 
    220 mailserver.example.com ESMTP Postfix (Ubuntu) 
ehlo example.com 
    250-mailserver.example.com 
    250-PIPELINING 
    250-SIZE 10240000 
    250-VRFY 
    250-ETRN 
    250-STARTTLS 
    250-AUTH PLAIN LOGIN 
    250-ENHANCEDSTATUSCODES 
    250-8BITMIME 
    250 DSN 
mail from:<fred@example.com> 
    250 2.1.0 Ok 
rcpt to:<fred@example.com> 
    250 2.1.5 Ok 
data 
    354 End data with <CR><LF>.<CR><LF> 
Subject:Your First Test Email 
Hi Fred, 
I wanted to send you an email. The very first from my new mail server! 
This is just so good. 
regards 
Fred 

    250 2.0.0 Ok: queued as EFD0AB521 
quit 
    221 2.0.0 Bye 
    Connection closed by foreign host. 
tail of mail.log
Nov 12 11:56:34 mailserver postfix/smtpd[1866]: connect from localhost[127.0.0.1] 
Nov 12 11:56:34 mailserver dovecot: auth(default): new auth connection: pid=1866 
Nov 12 11:56:57 mailserver postfix/smtpd[1866]: 03FEBB521: client=localhost[127.0.0.1] 
Nov 12 11:57:14 mailserver postfix/cleanup[1870]: 03FEBB521: message-id=<20091112115657.03FEBB521@mailserver.example.com> 
Nov 12 11:57:14 mailserver postfix/qmgr[1400]: 03FEBB521: from=<fred@example.com>, size=478, nrcpt=1 (queue active) 
Nov 12 11:57:14 mailserver dovecot: auth(default): master in: USER#0111#011fred@example.com#011service=deliver 
Nov 12 11:57:14 mailserver dovecot: auth(default): master out: USER#0111#011fred@example.com#011uid=5010#011gid=5010#011home=/var/vmail/example.com/fred 
Nov 12 11:57:14 mailserver postfix/pipe[1872]: 03FEBB521: to=<fred@example.com>, relay=dovecot, delay=30, delays=30/0/0/0.09, dsn=2.0.0, status=sent (delivered via dovecot service) 
Nov 12 11:57:14 mailserver postfix/qmgr[1400]: 03FEBB521: removed 
Nov 12 11:57:23 mailserver postfix/smtpd[1866]: disconnect from localhost[127.0.0.1] 

If all went well the email has been sent and you can see the log entries to prove it.
We sent the mail to Fred at example.com so there should now be an email sitting in the directory
/var/vmail/example.com/fred/Maildir. Go and have a look. Remember that the directory structure
is owned by the user vmail. I just open a root shell and use ls :)

sudo -i  ls -l /var/vmail/example.com/fred/Maildir/new
exit
total 12 
-rw------- 1 vmail vmail  560 2009-11-08 14:44 1257691471.M715041P2552.mailserver,W=577
Backup point
This would be a good backup point! 
 

Fetching Mail via Dovecot

We can send mails now we need to allow reads to fetch their emails and then read them. We can test this with telnet again. We will test first with IMAP and then with POP3.

Test fetching emails with IMAP

With an IMAP login after the initial connection (telnet in our case) you need to add a character or string at the beginning of each command this text will be returned in the status output from the IMAP server. The text can be anything. By convention it is usually a counter, but we will use test with an incrementing number at the end.

telnet localhost imap 
    Trying ::1... 
    Trying 127.0.0.1... 
    Connected to localhost. 
    Escape character is '^]'. 
    * OK Dovecot ready. 
 
test1 login fred@example.com yourpassword 
    test1 OK Logged in. 
test2 list "" "*" 
    * LIST (\HasNoChildren) "." "INBOX" 
    test2 OK List completed. 
test3 select "INBOX" 
    * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) 
    * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permitted. 
    * 1 EXISTS 
    * 1 RECENT 
    * OK [UNSEEN 2] First unseen. 
    * OK [UIDVALIDITY 1257691471] UIDs valid 
    * OK [UIDNEXT 14] Predicted next UID 
    test3 OK [READ-WRITE] Select completed. 
test4 fetch 1 all 
    * 1 FETCH (FLAGS (\Recent) INTERNALDATE "12-Nov-2009 17:19:46 +0000" RFC822.SIZE 573 ENVELOPE ("Thu, 12 Nov 2009 17:18:34 +0000 (GMT)" NIL ((NIL NIL "fred" "example.com")) ((NIL NIL "fred" "example.com")) ((NIL NIL "fred" "example.com")) ((NIL NIL "undisclosed-recipients" NIL)(NIL NIL "MISSING_MAILBOX" "MISSING_DOMAIN")(NIL NIL NIL NIL)) NIL NIL NIL "<20091112171839.6555DE7B1@mailserver.example.com>")) 
    test4 OK Fetch completed. 
 
test5 fetch 1 body[] 
    * 1 FETCH (BODY[] {359} 
    Return-Path: <fred@example.com> 
    Delivered-To: fred@example.com 
    Received: from example.com (localhost [127.0.0.1]) 
            by mailserver.example.com (Postfix) with ESMTP id 03FEBB521 
            for <fred@example.com>; Thu, 12 Nov 2009 11:56:45 +0000 (GMT) 
    Message-Id: <20091112115657.03FEBB521@mailserver.example.com> 
    Date: Thu, 12 Nov 2009 11:56:45 +0000 (GMT) 
    From: fred@example.com 
    To: undisclosed-recipients:; 
 
    Hi Fred, 
    I wanted to send you an email. The very first from my new mail server! 
    This is just so good. 
    regards 
    Fred 
    ) 
    test5 OK Fetch completed. 
test6 logout 
    * BYE Logging out 
    test6 OK Logout completed. 
    Connection closed by foreign host. 
tail from mail.log pre=
Nov 12 12:13:56 mailserver dovecot: auth-worker(default): mysql: Connected to 127.0.0.1 (postfix)
Nov 12 12:13:56 mailserver dovecot: auth-worker(default): sql(fred@example.com,127.0.0.1): query: SELECT email as user, password FROM user WHERE email='fred@example.com';
Nov 12 12:13:56 mailserver dovecot: auth(default): client out: OK#0111#011user=fred@example.com
Nov 12 12:13:56 mailserver dovecot: auth(default): master in: REQUEST#0111#0111863#0111
Nov 12 12:13:56 mailserver dovecot: auth(default): master out: USER#0111#011fred@example.com#011uid=5010#011gid=5010#011home=/var/vmail/example.com/fred
Nov 12 12:13:56 mailserver dovecot: imap-login: Login: user=<fred@example.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, secured
Nov 12 12:13:56 mailserver dovecot: IMAP(fred@example.com): Effective uid=5010, gid=5010, home=/var/vmail/example.com/fred
Nov 12 12:13:56 mailserver dovecot: IMAP(fred@example.com): maildir: data=/var/vmail/example.com/fred/Maildir
Nov 12 12:13:56 mailserver dovecot: IMAP(fred@example.com): maildir++: root=/var/vmail/example.com/fred/Maildir, index=, control=, inbox=/var/vmail/example.com/fred/Maildir
Nov 12 12:15:45 mailserver dovecot: IMAP(fred@example.com): Disconnected: Logged out bytes=94/1001

There you go you have sent and delivered your first email via your very own mail server. Time for a coffee to celebrate. Lets do the same thing again this time accessing the mail with POP3. It is a good way to test it is working as you can see each stage and monitor the logs at the same time.


We should do the same test again from another IP address that is another host to test we can login from machines other than localhost. You should see a similar set of output and log entries. The difference being you use "telnet mailserver imap" as the initial login string.

Test fetching emails with POP3

telnet localhost pop3 
    Trying ::1... 
    Trying 127.0.0.1... 
    Connected to localhost. 
    Escape character is '^]'. 
    +OK Dovecot ready. 
user fred@example.com 
    +OK 
pass yourpassword 
    +OK Logged in. 
list 
    +OK 2 messages: 
    1 568 
    . 
retr 1 
    +OK 543 octets 
    Return-Path: <fred@example.com> 
    Delivered-To: fred@example.com 
    Received: from example.com (localhost [127.0.0.1]) 
            by mailserver.example.com (Postfix) with ESMTP id 03FEBB521 
            for <fred@example.com>; Thu, 12 Nov 2009 11:56:45 +0000 (GMT) 
    Message-Id: <20091112115657.03FEBB521@mailserver.example.com> 
    Date: Thu, 12 Nov 2009 11:56:45 +0000 (GMT) 
    From: fred@example.com 
    To: undisclosed-recipients:; 
 
    Your first test email 
 
    Hi Fred, 
    I wanted to send you an email. The very first from my new mail server! 
    This is just so good. 
    regards 
    Fred 
    . 
quit 
    +OK Logging out. 
    Connection closed by foreign host. 

Again you need to repeat the process above but from a host other than mailserver to ensure that your users will be able to log in.

Setting up Evolution

Although we can now send and read emails, I don't think your users would be too impressed if telnet was the only way to access their mail.:> Just think of all the help calls from end users trying to access their email and getting the commands in the wrong order.


At this point we can set up Thunderbird or Evolution or any other email client. Using Evolution it is easy to create a new account that points at our new server. I'm sure you can work this out but here is a very quick and dirty description.

  • Edit->Properties. Mail Accounts tab. Click the + Add button.
  • Email address: fred@example.com. Forward button.
  • Server Type: IMAP
  • Server: mailserver@example.com
  • Username: fred@example.com
  • No Encryption & Password
  • Forward button. Forward button.
  • Server Type: SMTP
  • Server: mailserver@example.com
  • No encryption & login
  • Username: fred@example.com, Forward button.
  • Account Info: Fred POP3 no encryption

You will be asked for your password, Click on the Folder for "Fred POP3 no encryption" you may need to refresh it. Your first email will appear in the client. Set up a POP3 account also with no encryption as we have not turned that on yet. POP3 will actually download the email from the mailserver and store it with your client.

If All is working. Now would be a good time to make a full backup of your new server

Authenticated SMTP

We can send and receive emails now we need to make it a little bit more secure by using TLS and SSL. First of all we need to generate the self-signed certificates that will make this all possible.

sudo openssl req -new -x509 -days 1825 -nodes -out /etc/ssl/certs/dovecot.pem \
                       -keyout /etc/ssl/private/dovecot.key
Generating a 1024 bit RSA private key 
................................++++++ 
....................++++++ 
writing new private key to '/etc/ssl/private/dovecot.key' 
----- 
You are about to be asked to enter information that will be incorporated 
into your certificate request. 
What you are about to enter is what is called a Distinguished Name or a DN. 
There are quite a few fields but you can leave some blank 
For some fields there will be a default value, 
If you enter '.', the field will be left blank. 
----- 
Country Name (2 letter code) [AU]:UK 
State or Province Name (full name) [Some-State]:Hampshire 
Locality Name (eg, city) []:Mailsville  
Organization Name (eg, company) [Internet Widgits Pty Ltd]: Dragons Can Fly Ltd 
Organizational Unit Name (eg, section) []:IT 
Common Name (eg, YOUR name) []:mailserver.example.com 
Email Address []:

The Common Name must be the FQDN for your mailserver. The days option sets the number of days that this certificate will be valid. I have used 1825 days or 5 years, give or take. I doubt very much I'll still be using the same hardware and Ubuntu, Postfix etc. would have moved on anyway. You will need to set the permissions on the private certificate so only root and the members of the group 'root' can read it. You should also restart Dovecot

sudo chmod 640 /etc/ssl/private/dovecot.key

We need to change the certificates that are being used by Dovecot as we now have our own. Re-edit the dovecot.conf file.

sudo nano /etc/dovecot/dovecot.conf
ssl_cert_file = /etc/ssl/certs/dovecot.pem 
ssl_key_file = /etc/ssl/private/dovecot.key
sudo /etc/init.d/dovecot restart

Setting PostFix Authentication.

sudo postconf -e mynetworks=192.168.50.0/24
sudo postconf -e smtpd_sasl_type=dovecot
sudo postconf -e smtpd_sasl_path=private/dovecot-auth
sudo postconf -e smtpd_sasl_auth_enable=yes
sudo postconf -e smtpd_recipient_restrictions=permit_mynetworks, 
permit_sasl_authenticated,reject_unauth_destination 

To generate the authentication string needed for the next test use the following Perl command line to Base64-encode your password.

perl -MMIME::Base64 -e 'print encode_base64("fred\@example.com\0fred\@example.com\0yourpassword")';
ZnJlZEBleGFtcGxlLmNvbQBmcmVkQGV4YW1wbGUuY29tAHlvdXJwYXNzd29yZA==

You will need to change the fred@example.com text to the domain name of your test user. Also change
"yourpassword" will have to be what ever you chose as your password.

To use smtps you need to uncomment some lines in master.cf, Only uncomment the first two extension lines as shown below:

sudo nano /etc/postfix/master.cf
smtps     inet  n       -       -       -       -       smtpd 
  -o smtpd_tls_wrappermode=yes 
  -o smtpd_sasl_auth_enable=yes
sudo  postfix reload
sudo postconf -e smtpd_tls_cert_file=/etc/ssl/certs/dovecot.pem
sudo postconf -e smtpd_tls_key_file=/etc/ssl/private/dovecot.key

We can use the same certificates here as we did for Dovecot as long as we are on the same server.

Also add the ssl certificates to the postfix configuration file main.cf

sudo postconf -e smtpd_tls_security_level=may
sudo postconf -e smtpd_tls_auth_only=no
It is the users choice to use SSL/TSL or not with the settings so far. 
 

Once that is all in place you can test it out with a real world test site. This will test your mail is configured correctly and is not an open-relay that spammers can use. The site connects to your mail server repeatedly with different parameters and takes about a minute to finish.

sudo telnet relay-test.mail-abuse.org

You should see a message

System appeared to reject relay attempts
Backup point
This would be a good backup point! 
 

Receiving mail over a secure connection

We can now enable dovecot so it only accepts authenticated connections. We will no longer accept remote plain text authorizations unless TLS/SSL is being used. Edit the dovecot.conf file and and comment out the disable_plain-text_auth line.

sudo nano /etc/dovecot/dovecot.conf
#disable_plaintext_auth = no
sudo /etc/init.d/dovecot reload

When you try to connect to mailserver with either POP3 or IMAP you should now see an error message saying,

Unable to connect to POP server mailserver.
Error sending username: Err Plaintext authorization  disallowed on non-secure (SSL/TLS) connections.
Tail from mail.log
Nov 12 15:13:32 mailserver dovecot: pop3-login: Aborted login (tried to use disabled plaintext auth): rip=192.168.0.5, lip=192.168.0.11 
Nov 12 15:13:33 mailserver dovecot: imap-login: Aborted login (tried to use disabled plaintext auth): rip=192.168.0.5, lip=192.168.0.11

In the account settings for your mail client change the encryption to SSL for POP and IMAP connections. You should now be able to connect to mailserver and see your test mails again.


We can now send and receive emails over encrypted connections (SSL/TLS). The SMTP connection will only allow authorized users to use our server to relay messages.
Pretty damn good, don't you think.;)

Backup point
This would be a good backup point! 
 

Amavis

It is a necessary evil that we should scan all incoming and outgoing email for viruses and all incoming email for possible spam content. We do that with a service called Amavis this plugs into Postfix and accepts mail before it is delivered.

Installing Amavis

sudo apt-get install amavisd-new spamassassin

Add some extra tools for extracting files from archives and compressed files.

sudo apt-get install lha unrar arj unrar zoo p7zip-full nomarch lzop cabextract

The extra compression modules are not normally installed by default as they are supplied on a less then free GPL license. The choice is yours whether you install them or not. If you do add them then you will need to turn them on by editing the file 01-debian.

sudo nano /etc/amavis/conf.d/01-debian

Find the unrar and lha lines and uncomment them. When you restart Amavis look in the mail log to see if there are any other missing modules.

$unrar      = ['rar', 'unrar']; #disabled (non-free, no security support) 
#$unrar      = ['unrar-free']; 
$zoo    = 'zoo'; 
$lha    = 'lha'; #disabled (non-free, no security support) 
#$lha   = undef;



if the output you get from running the following command is the fully qualified domain name for your server. You can skip the edit in 05-node.

hostname --fqdn
mailserver.example.com

As you are reading this part you need to update the $myhostname line to be the FQDN for your server this is used for ESMTP EHLO, and loop detection. You can also comment out the line that starts "chomp" as it is no longer needed as you have hard coded the value it finds.

sudo nano /etc/amavis/conf.d/05-node_id
$myhostname = "mailserver.example.com";

Spamassassin is already configured for us we just need to turn in on by uncomment the bypass_spam line in 15-content_filter_mode.

sudo nano /etc/amavis/conf.d/15-content_filter_mode
@bypass_spam_checks_maps = (  
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

There are some other changes we need to make these should go into the file 50-user. Any changes you make there will override those of the earlier files. (with a smaller number at the start of the file name).

sudo nano /etc/amavis/conf.d/50-user
New content for 50-user
$sa_spam_subject_tag = '[**SPAM**] '; 
$final_spam_destiny  = D_PASS; 
 
@lookup_sql_dsn = ( 
    ['DBI:mysql:database=postfix;host=127.0.0.1;port=3306', 
     'mail', 
     'yourpassword']); 
$sql_select_policy = 'SELECT domain FROM domain WHERE CONCAT("@",domain) IN (%k)'; 

I like to see that the spam detector is working so I get it to update the subject line for any emails it the scanner believes are spam. This is purely cosmetic, it simply changes the string that is added to the subject line emails it believes are spam. Since I already have a rule in my email client looking for the string "[**SPAM**] that is what I change it to.

The variable $final_spam_destiny is used to determine the outcome of finding an email that is believed to be spam. Since one man's spam is another man's valuable message. e shall let the user decide, It will be marked as suspected spam but allow it to be delivered.

The last variable for lookup_sql_dsn, is required because AMaViS tries to find out whether an email is incoming (sent from the internet to your domains) or outgoing (sent from your system to the internet) by looking at the @acl_local_domains setting. You need to tell AMaVis where to check if a certain domain is one of your destination domains. The reason is that you usually don't want to scan your outgoing emails. Imagine that an email is accidentally deemed to be spam and your customer gets warned of your emails.


While debugging you can also set the following variable so that the spam header flags are always added to the delivered mail.

$sa_tag_level_deflt  = undef;

And the now usual change of ownership as this file now contains our Mysql password in open text.

sudo chmod 640 /etc/amavis/conf.d/50-user

Restart amavis, take a look at the log file to check for any missuing compression modules.

sudo /etc/init.d/amavis restart

Now setup the interface configuration for Postfix to talk to Amavis

sudo postconf -e content_filter=amavisfeed:[127.0.0.1]:10024
sudo postconf -e receive_override_options=no_address_mappings

And the follow long set of lines need to go into the master.cf file.

sudo nano /etc/postfix/master.cf
amavisfeed unix -      -       n     -       2  smtp 
    -o smtp_data_done_timeout=1200 
    -o smtp_send_xforward_command=yes 
    -o disable_dns_lookups=yes 
    -o max_use=20 
 
127.0.0.1:10025 inet n    -       n       -       -     smtpd 
    -o content_filter= 
    -o smtpd_delay_reject=no 
    -o smtpd_client_restrictions=permit_mynetworks,reject 
    -o smtpd_helo_restrictions= 
    -o smtpd_sender_restrictions= 
    -o smtpd_recipient_restrictions=permit_mynetworks,reject 
    -o smtpd_data_restrictions=reject_unauth_pipelining 
    -o smtpd_end_of_data_restrictions= 
    -o smtpd_restriction_classes= 
    -o mynetworks=127.0.0.0/8 
    -o smtpd_error_sleep_time=0 
    -o smtpd_soft_error_limit=1001 
    -o smtpd_hard_error_limit=1000 
    -o smtpd_client_connection_count_limit=0 
    -o smtpd_client_connection_rate_limit=0 
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters 
    -o local_header_rewrite_clients= 

Do not forget to reload the postfix files now you have updated them.

sudo postfix reload

Configuring Spamassassin

To turn on Spamassassin you need to edit the spamassassin file in /etc/default.

sudo nano /etc/default/spamassassin

Now change the two lines for ENABLE and CRON to a number larger than zero (0). Save the changes.

sudo nano /etc/cron.daily/spamassassin

we also need to change the line for CRON to a number larger than zero (0). Save the changes and restart the Spamassassin service.

sudo /etc/init.d/spamassassin restart

The application that updates the rules for Spamassassin is called "sa-update" and is normally run via a daily crontab job when the value in the file above is set. To update any existing rules now we can run it now. As it will not restart "spamd" or otherwise cause a scanner to reload the now-updated ruleset automatically. We need to run the update and then restart the server.

sudo sa-update  sudo /etc/init.d/spamassassin reload

************************************************************
************************************************************
************************************************************
FIXME:run sa_update with thw -d option to see a list or possibly required modules.
************************************************************
************************************************************
************************************************************

Testing Spam Filtering

You can test that Spamassassin is working by sending an email containing a know spam signature. One such signature was installed already in the following file.

/usr/share/doc/spamassassin/examples/sample-spam.txt

Copy/Paste the contents to an email and send it to yourself. If should be flagged as spam and you should also see some messages in the mail.log.

Clamav Anti-Virus

Installing Clamav

sudo apt-get install clamav-daemon

Configuring Clamav

Clamav is already configured in the file "15-av_scanners, but to call any scanner you need to uncommented the bypass_spam line in 15-content_filter_mode.

sudo nano /etc/amavis/conf.d/15-content_filter_mode
@bypass_virus_checks_maps = (  
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);  

So that the user that is going to be running clamav can "talk" to the amavis service we need to add it to the amavis group.

sudo adduser clamav amavis
sudo /etc/init.d/clamav-daemon restart

Make sure the clanav databases are up to date.

sudo freshclam
ClamAV update process started at Fri Nov 13 15:43:28 2009 
main.cvd is up to date (version: 51, sigs: 545035, f-level: 42, builder: sven) 
daily.cld is up to date (version: 10022, sigs: 105525, f-level: 44, builder: ccordes 

Testing Clamav

sudo dpkg-reconfigure clamav-freshclam

As your server will be connected 24/7 to the internet use the daemon option for updating to clamav. If you use the daemon update method select

to notify clamd of updates. Select a server close to you
Choose the method for virus database updates.  daemon 
Choose the closest mirror site:                Pick one   
Number of freshclam updates per day            6 
Should clamd be notified to reload the database after successful updates. Yes 

sudo dpkg-reconfigure clamav-base

There are a number of questions to answer here, The options below are the ones that I changed or needed a mention. The rest I used the defaults

Socket Type      Unix 
Local Socket     This should be the same as in /etc/amavis/conf.d/15-av_scanners (the default works) 
Do you want to use the system logger    Yes   not default for testing only 
Groups for Clamav-daemon         amavis   (should already be set) 

Now that keeps the virus-DB upto date but not the engine. To keep the engine up to date is some what harder. I used the following to get a more up to date version of clamav. This worked for a while and then I received a broken package and had to go digging into the use of aptitude. https://help.ubuntu.com/community/ClamAV

Testing that Calmav is working is simple once you get a virus you can email around. Don't panic the test virus will not do anything, harmful in fact it won't do anything at all. Go to the following link and have a read

http://www.eicar.org/anti_virus_test_file.htm

Copy the string 68 characters and save them to a file. Now attach the file to an email and send it. You SHOULD see some lines in the mail.log that indicate :) that the file was infected. Also try out the same text file but packed in an archive, tar, zip or compressed file .gzip, tgz zip.

AVG Free Anti-Virus

Download the latest binaries from AVG http://free.avg.com/us-en/download

On 64-bit systems you will need to install the 32 bit compatibility libs and to use the '--force-architecture' switch.

sudo apt-get install ia32-libs
sudo dpkg --force-architecture -i avg85flx-r290-a2950.i386.deb

The above installs the software into /opt/avg/avg8

AVG Free via Amavis

AVG Free is already configured in the file "15-av_scanners, but to call any scanner you need to uncommented the bypass_spam line in 15-content_filter_mode.

sudo nano /etc/amavis/conf.d/15-content_filter_mode
@bypass_virus_checks_maps = (  
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);  
sudo nano /etc/amavis/conf.d/15-av_scanners
@av_scanners = ( 
  ['AVG Free Anti-Virus', 
      \&ask_daemon, ["SCAN {}\n", '127.0.0.1:54322'], 
      qr/^200 [oO][kK]/m, qr/^403/m, qr/^403 .*?: ([^\r\n]+)/m ], 
); 

In the above file you can squeeze a few extra milliseconds of speed by commenting out all the scanners you will not be using.


The people that use my mailserver are, actually sensible. There machines are also not on the same network as mine. 7| Therefore I do not quarantine mails that are marked as infected with a virus. They have their subject's updated to clearly show the mail is infected. This maens I also PASS infected mail on to their mail box for them to deal with.

sudo nano /etc/amavis/conf.d/50-user
/etc/amavis/conf.d/50-user
$final_virus_destiny = D_PASS;

Set the following parameters for communication via INET socket:

sudo avgcfgctl -w Default.tcpd.avg.enabled=true
sudo avgcfgctl -w Default.tcpd.avg.address=127.0.0.1
sudo avgcfgctl -w Default.tcpd.avg.ports="|54322|"
sudo /etc/init.d/avgd start
sudo /etc/init.d/amavis restart
sudo postfix reload

Updating AVG Free Engine and Database

sudo nano /etc/cron.daily/avgfree
contents of avgfree
#!/bin/sh  /usr/bin/avgupdate
sleep 45
/etc/init.d/avgd restart

Make the script executable by root so the daily cron can run it.

sudo chmod 744 /etc/cron.daily/avgfree

We can do the first update now so we can start with an upto date AV system.

sudo /usr/bin/avgupdate
AVG command line update 
Copyright (c) 2009 AVG Technologies CZ 
 
Running update. 
Initializing...                                                                                     
Downloading file:  avginfoavi.ctf                                                                   
Downloading file:  avginfolx.ctf                                                                    
Analyzing...                                                                                        
Downloading file:  u7avi1822u1323w3.bin               1 /  5  608.06 K 
Downloading file:  lx8core292b290zj.bin               3 /  5  100.57 K 
Downloading file:  u7iavi2581u2321wc.bin              5 /  5    6.70 M 
Analyzing...                                                                                        
Preparing installation...                                                                           
Updating...                                                                                         
100% [========================================================>] 
Update was successfully completed.

Testing that AVG Free is working is simple once you get a virus you can email around. Don't panic the test virus will not do anything harmful in fact it won't do anything at all. Go to the following link and have a read

http://www.eicar.org/anti_virus_test_file.htm

Copy the string 68 characters and save them to a file. Now attach the file to an email and send it. You SHOULD see some lines in the mail.log that indicate :) that the file was infected. Also try out the same text file but packed in an archive or compressed file such as a tar or tar gzip file.

Postgrey

There are a number of ways to stop spam from reaching your inbox, we have already setup Amavis and Spamassassin to do some spam filtering. Grey-listing is not designed to replace this but to work with it. By providing a first hurdle for spam to get past before hitting your inbox. It is yet another tool in your arsenal against the endless barrage of pointless emails we all receive. Grey-listing is very simple and requires very little CPU or processing time. It simply looks at the senders name and if they are not known already, it politely says to them "Please try again later". For any well setup mail server this is not a problem and the mail will be redelivered later as requested. But for spammers that want to get as many emails out there as possible, they never bother to "try again later". :-/

Installing Postgery

To install Postgrey is just a apt-get away with:

sudo apt-get install postgrey

Configuring Postgrey

We need to tell postfix how to talk to postgrey. Add the following lines to your /etc/postfix/main.cf Postgey defaults to port 10023.

sudo postfix -e smtpd_recipient_restrictions=permit_mynetworks, \ 
    permit_sasl_authenticated,reject_unauth_destination, \ 
    check_policy_service inet:127.0.0.1:10023 
sudo postfix reload

You can adjust some other settings. These are available in /etc/default/postgrey. There are also some white lists you can add to if you feel lucky.

Backup point
This would be a good backup point! 
 

Apache Web server

Installing Apache

sudo apt-get install apache2

You should at this point be able to see a web page displayed that says "It works!" if you use the URL http://www.example.com Give it a try, it you do not see the test page from the Apache install then you'll need to sort that out before continuing.

When you stop and start your Apache server you may see an error message like the one below. Lets start by getting that sorted out.

Example Error Message
apache2: Could not determine the server's fully qualified domain name, using 192.168.0.10 for ServerName

Apache cannot work out the domain name of your server machnice or perhaps you simply do not have a domain name setup. Not to worry it is simple to fix. Edit /etc/apache2/apache2.conf add the ServerName option. Use the output from the Linux command hostname as the value. I add the line after ServerRoot. Then restart the Apache server and you are done. We should see the following forthe example server.

hostname --fqdn
mailserver.example.com

Add these lines to /etc/apache2/apache2.conf

sudo nano /etc/apache2/apache2.conf
ServerRoot "/etc/apache2"
ServerName "mailserver.example.com"

Test that all is still well with the Apache configuration files with the following command. This is usful as if there are errors the server is left up and running in the pre-edit state. We can then use reload it take the changes into use without shutting down the server and bringing back up again. On a live server this is less likely to be noticed that the restart.

sudo apache2ctl -t
sudo /etc/init.d/apache2 reload

Configuring Apache

You now have Apache serving pages locally on your LAN, but you also want to be able to access the same Web site via the Internet. With Apache it is simple, once you know how. We will setup Apache to serve web pages for a number of Domains by using the virtual hosts feature.


We will be using two different ports to access our web pages 80 the standard http port and the https port 443. We need to tell Apache these will be setup so add the lines below to /etc/apache2/apache2.conf anywhere before line towards the bottom that includes the files in sites-available. I tend to place then just after the ServerRoot and ServerName lines.

sudo nano /etc/apache2/apache2.conf

#  We are going to be running some virtual hosts. 

NameVirtualHost *:80 
NameVirtualHost *:443 

By using the'*' wild card we do not differentiate between different IP addresses we will only use the URL to guide us to the right virtual host.

Configure the Default Web Site

We will create the web site and index.html page that will be the fall back when there are no rules to use any other site. We will place it in /var/www/default for want of a better place. Start by changing the default web site config file.

sudo nano /etc/apache2/sites-available/default
default virtual host
# The Default web site, when there are no matches to the URL we end up here 
# There must not be a ServerName in this config file or it will not function 
# as we hope it will do. 
<VirtualHost *:80> 
        ServerAdmin webmaster@example.com 
 
        # Indexes + Directory Root. 
        DirectoryIndex index.html 
        DocumentRoot /var/www/default/ 
 
        # CGI Directory 
        ScriptAlias /cgi-bin/ /var/www/default/cgi-bin/ 
        <Location /cgi-bin> 
                Options +ExecCGI 
        </Location> 
 
        # Logfiles 
        ErrorLog   /var/log/apache2/default_error.log 
        CustomLog  /var/log/apache2/default_custom.log combined 
</VirtualHost> 
sudo mkdir -p /var/www/default

Create the index page for the default site, Nothing to fancy at this point :)

sudo nano /var/www/default/index.html
/var/www/default/index.html
<html><body><h1> Default start page for my web server</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>
sudo chown -R www-data:www-data /var/www/default

We need to comment out one line in the following file it will remove the warning about unconfigured virtual host. Place a # at the start of the line for NameVirtualHost *:80.

/etc/apache/ports.conf
sudo nano /etc/apache2/ports.conf
#NameVirtualHost *:80
Listen 80

Check the files are ok. Also from now :!: on I will only mention to reload the Apache files and miss off the part to check in for errors. I assume you will do that bit yourself. It's been a lot of typing so far.

sudo apache2ctl -t
sudo /etc/init.d/apache2 restart

You should now be able you use the URL for mailserver, mailserver.example.com and example.com and even example.net and they all go to the default web page from above.

Setting up the example.com Virtual Host

Let us create the top level virtual host for example.com. This is similar to the default we created above, but hard codes a server name in the virtual host definition.

sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/example.com
sudo nano /etc/apache2/sites-available/example.com
example.com virtual host
<VirtualHost *:80> 
        ServerAdmin webmaster@example.com 
        ServerName  www.example.com 
        ServerAlias example.com 
 
        # Indexes + Directory Root. 
        DirectoryIndex index.html 
        DocumentRoot /var/www/example.com/ 
 
        # CGI Directory 
        ScriptAlias /cgi-bin/ /var/www/example.com/cgi-bin/ 
        <Location /cgi-bin> 
                Options +ExecCGI 
        </Location> 
 
        # Logfiles 
        ErrorLog   /var/log/apache2/example.com_error.log 
        CustomLog  /var/log/apache2/example.com_custom.log combined 
</VirtualHost> 
sudo mkdir -p /var/www/example.com

Create the index page for example.com site. No need to go too mad on this temporary marker page.

sudo nano /var/www/example.com/index.html
/var/www/example.com/index.html
<html><body><h1> Default start page for example.com</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>
sudo chown www-data:www-data /var/www/example.com

We will need to tell the Apache server that this new virtual site exists so we enable it. The enable command makes a symbolic link in sites-enabled back to sites-available.

sudo a2ensite example.com

Now test the syntax and reload the files when there are no errors.

sudo /etc/init.d/apache2 reload

Now you will see that example.com goes to the new virtual host whereas mailserver.example.com goes to the default host. You may have noticed the ServerName we used for this site was www.example.com and the we had aServerAlias of example.com. This means you can use either of those URLs to find this web site.

Rewrite URLs on the fly

One more little tweak to the example.com virtual host configuration file. We can get Apache to rewrite the URL so users will always see http://example.com even if the original URL was www.example.com.

We need to add three lines which will see if the URL matches and then rewrite it to something else as necessary. We will use this trick later on too for the HTTPS connection with Squirrelmail.

sudo nano /etc/apache2/sites-available/example.com
        ServerAlias www.example.com 
 
        # Redirect all requests for a www host 
        RewriteEngine On 
        RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] 
        RewriteRule ^(.*)$ http://%1/$1 [R=301,QSA,L] 

Before that can work we need to enable the rewrite module.

sudo a2enmod rewrite

Do not forget to reload the changes, before tying this new feature out.

sudo /etc/init.d/apache2 reload

If you have more domains linking to this one Apache server you can set those you by repeating the process above that we used for example.com. All that is left is to add the Web site contents in the normal way starting at the temporary index.html.

Backup point
This would be a good backup point! 
 

SquirrelMail

Installing SquirrelMail

sudo apt-get install php5-mysql php-pear squirrelmail ibritish wbritish
sudo apt-get remove iamerican wamerican

When I install Squirrelmail I remove the American English dictionaries and replace then with er, um the English dictionaries, "Like what I speak" :). You can do the same but install the dictionaries for your own language are required. These should automatically be configured by ispell. But if you use Firefox you already have access to the great feature of auto-spell checking as you type.

Configuring the Apache Server for SquirrelMail

You need make a link from SquirrelMail configuration to the Apache site-available directory.

sudo ln -s /etc/squirrelmail/apache.conf /etc/apache2/sites-available/squirrelmail

The default supplied setup does not provide a secure connection between the client and the server. Communication between the web browser and the mail server will be in plain text, which is not good. We can run the connection over SSL (HTTPS) by enabling the ssl module and using the same self-signed certificates we are using for Dovecot. You can always generate another set if you want to. Also we can change the default URL to access the web mail server from one like these

example.com/squirrelmail
www.example.com/squirrelmail

It is much better to provide our users with something that is easier to remember. The Apache setup for this web service is already designed to run as virtual hosts and that allows us to access Squirrelmail with a URL such as

squirrelmail.example.com
www.squirrelmail.example.com

We can also use the Apache mod_rewrite module to rewrite the URL we use to access Squirrelmail so that it will always access the web interface through HTTPS. First we need to enable the Apache modules for ssl and rewrite.

sudo a2enmod ssl

Now to make some changes to the supplied Squirrelmail config file for Apache. There are a lot of changes so here is one that is ready to use. Change the domain name to suite your environment.

sudo nano  /etc/apache2/sites-available/squirrelmail
<VirtualHost  *:80> 
  ServerName    www.webmail.example.com 
  ServerAlias   webmail.example.com 
 
  RewriteEngine on 
  RewriteCond %{HTTPS} off [NC] 
  RewriteCond %{HTTP_HOST} webmail [NC] 
  RewriteRule . https://%{HTTP_HOST}%{REQUEST_URI}  [L] 
  RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] 
  RewriteRule ^(.*)$ https://%1/$1 [R=301,QSA,L] 
</VirtualHost> 
 
# users will prefer a simple URL like https://webmail.example.com 
<VirtualHost  *:443> 
  ServerName    www.webmail.example.com 
  ServerAlias   webmail.example.com 
  ServerAdmin   webmaster@example.com 
 
  RewriteEngine on 
  RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] 
  RewriteRule ^(.*)$ https://%1/$1 [R=301,QSA,L] 
 
  DocumentRoot  /usr/share/squirrelmail 
 
  SSLEngine on 
  SSLOptions +StrictRequire 
  SSLCertificateFile      /etc/ssl/certs/webmail.pem 
  SSLCertificateKeyFile   /etc/ssl/private/webmail.key 
 
  # Logfiles 
  ErrorLog   /var/log/apache2/webmail_error.log 
  CustomLog  /var/log/apache2/webmail_custom.log combined 
 
</VirtualHost> 
 
&ltirectory /usr/share/squirrelmail> 
  Options Indexes FollowSymLinks 
  <IfModule mod_php5.c> 
    php_flag register_globals off 
  </IfModule> 
  <IfModule mod_dir.c> 
    DirectoryIndex index.php 
  </IfModule> 
 
# access to configtest is limited by default to prevent information leak 
#  <Files configtest.php> 
#    order deny,allow 
#    deny from all 
#    allow from 127.0.0.1 
#  </Files> 
</Directory> 

As we will be using a virtual host for webmail via HTTPS and the SSL keys we have are not for webmail.example.com the Apache server will warn us that the host name and the Common name (CN) are not the same. If we generate another pair of self-signed certificates with the corret CN. This warning is removed. :) You can of course use the same certificates as we used for dovecot and put up with the warnings.

sudo openssl req -new -x509 -days 1825 -nodes -out /etc/ssl/certs/webmail.pem \
                  -keyout /etc/ssl/private/webmail.key
Generating a 1024 bit RSA private key
................................++++++
....................++++++
writing new private key to '/etc/ssl/private/webmail.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:UK
State or Province Name (full name) [Some-State]:Hampshire
Locality Name (eg, city) []:Mailsville  Organization Name (eg, company) [Internet Widgits Pty Ltd]: Dragons Can Fly Ltd
Organizational Unit Name (eg, section) []:IT
Common Name (eg, YOUR name) []:webmail.example.com
Email Address []:

Update the permissions and the owner of the private file as it will be read by the Apache server.

sudo chmod 640 /etc/ssl/private/webmail.key 
sudo chown www-data:www-data /etc/ssl/private/webmail.key
Note: The commented out section at the bottom of the configuration allows us to run the script configtest.php. This should be uncommented again after everything is sorted out. It poses a security risk if left open.

Now to enable your new Apache configuration for Sqiurellmail and then reload the Apache configuration.

sudo a2ensite squirrelmail
sudo /etc/init.d/apache2 reload

With that all in place you should be able to access your mailserver via Squirrelmail with the test user, fred@example.com, and his password. The user will not have to remember to use HTTPS:// as we have told Apache to rewrite the URL to force the secure access. It is one less thing for the users to do so one less thing to get wrong :>>

Configuring SquirrelMail

Load up the URL https://webmail.example.com/src/configtest.php in your web browser this will run the Squirrelmail test script and show any errors it finds there. You will most likely see an error message like the one below.

ERROR: You have enabled any one of magic_quotes_runtime, magic_quotes_gpc or magic_quotes_sybase in your PHP configuration. We recommend all those settings to be off. SquirrelMail may work with them on, but when experiencing stray backslashes in your mail or other strange behaviour, it may be advisable to turn them off.

To turn these off edit the php.ini from found in /etc/php5/apache2 and search for "magic_quotes_gpc" and set it to off. This was the only offending setting that was turned on.

sudo nano /etc/php5/apache2/php.ini

Make the changes and then restart the Apcahe server, yes you must restart it reloading will not bring the changes into action.

sudo /etc/init.d/apache2 reload

Now to configure Squirrelmail a little bit more. In a terminal start the configuration script for squirrel mail. Do not change anything to start with just have look around to get the idea of what is there. :idea:

sudo squirrelmail-configure

Ok, you are back from looking at the Squirrelmail configuration.

Start with the D option for "D. Set pre-defined settings for specific IMAP Servers" and
set it to "dovecot" as that is what we are using.

Please select your IMAP server: 
    bincimap    = Binc IMAP server 
    courier     = Courier IMAP server 
    cyrus       = Cyrus IMAP server 
    dovecot     = Dovecot Secure IMAP server 
    exchange    = Microsoft Exchange IMAP server 
    hmailserver = hMailServer 
    macosx      = Mac OS X Mailserver 
    mercury32   = Mercury/32 
    uw          = University of Washington's IMAP server 
 
    quit        = Do not change anything 
Command >> dovecot

Return to the main menu and select "2. Server Settings." Then using the 'A' and 'B' options to setup IMAP and SMTP settings. The settings below are the ones I am using.

IMAP Settings 
-------------- 
4.  IMAP Server            : localhost 
5.  IMAP Port              : 993 
6.  Authentication type    : login 
7.  Secure IMAP (TLS)      : true 
8.  Server software        : dovecot 
9.  Delimiter              : detect 
 
SMTP Settings 
 ------------- 
4.   SMTP Server           : localhost 
5.   SMTP Port             : 465 
6.   POP before SMTP       : false 
7.   SMTP Authentication   : login (with IMAP username and password) 
8.   Secure SMTP (TLS)     : true 
9.   Header encryption key :

We are also going to use the SQL DB as a backend to hold the address and preferences data. From the main menu select '9 databases' it is options 1 and 3 you should need to change. When the options are set it should look similar to this

SquirrelMail Configuration : Read: config.php (1.4.0) 
--------------------------------------------------------- 
Database 
1.  DSN for Address Book   : mysql://mail:<mysqlpassword>@127.0.0.1/postfix 
2.  Table for Address Book : address 
 
3.  DSN for Preferences    : mysql://mail:<mysqlpassword>@127.0.0.1/postfix 
4.  Table for Preferences  : userprefs 
5.  Field for username     : user 
6.  Field for prefs key    : prefkey 
7.  Field for prefs value  : prefval 


Remember to save the settings before exiting and reload the Apache settings.

The Pear plugins are required to access the MySQL DB with Php. Checking pear is loaded and also that the DB access module and also the newer MDB2 modules are loaded. We do need both if you are going to be adding the plugin below. Start by making sure that the Pear libraries are installed.You get install this extra software with the following the commands below. Use the pear list command to see which packages are installed you need to to have:

sudo pear list
DB               1.7.13  stable 
MDB2              2.4.1   stable 
MDB2_Driver_mysql 1.4.1   stable 
sudo pear install DB  
sudo pear install pear/MDB2#mysql 
sudo /etc/init.d/apache2 reload

Load up the URL https://webmail.example.com/src/configtest.php again in your web browser to check all is working as expected.

Remember to uncomment the securtiy option in /etc/apache2/sites-available/squirrelmail once this is all sorted and tested and of course remember to reload the apache configuration.

Testing Squirrel mail

From another machine test that you can send and receive emails with Squirrelmail. If the tests you did with Evolution or thunderbird worked this should be a simple case of send your test user an email from within Squirrelmail. Waiting a second and then seeing if it have arrived by clicking the "Check mail" link in Squirrelmail.

Backup point
This would be a good backup point! 
 

Squirrelmail plugins

There are two plugins I like to use with Squirrelmail.

  1. Change SQL password - Allows anyone to update their own password when logged into Squirrel mail.
  2. Mail Aliases - Allow you to maintain your own aliases mappings.

Change Passwords plugin.

Download change_sqlpass (not change_mysqlpass) from the Squirrelmail web site. Also get the latest "Compatibility plugin". (This plugin requires the DB module from above). You will need that too!


Unzip the compatibility plugin somewhere safe, like /tmp so you can read the README and INSTALL instructions. When I installed the compatibility plugin, I simply had to

cd /usr/share/squirrelmail/plugins 
sudo tar zxvf compatibility-2.0.15-1.0.tar.gz 

Now for change_sqlpass, remove the software you unzipped into /tmp and unzip the change_sqlpass tar/zip file. Again read the README and INSTALL file. Follow the instructions. This is what I had to do.

cd /usr/share/squirrelmail/plugins  
sudo tar zxvf change_sqlpass-3.3-1.2.tar.gz 
cd change_sqlpass 
sudo cp config.php.sample config.php 
sudo nano config.php 

There are some small changes that needed to be made at this point. The first change sets the login parameters for the mysql DB. in the case below they are.

$csp_dsn = 'mysql://mail:<mysqlpassword>@localhost/postfix'; 
$lookup_password_query = 'SELECT count(*) FROM user WHERE email = "%1" AND password = %4'; 
$password_update_queries = array('UPDATE user SET password = %4 WHERE email = "%1"', ); 
$password_encryption = 'MD5'; 
$csp_salt_static = ''; 
$csp_salt_query = ''; 
$csp_secure_port = 443; 

Save the changes you made and as this file has a password it should not be world readable so we change the group and permissions to suit.

sudo chown root:www-data  /usr/share/squirrelmail/plugins/change_sqlpass/config.php 
sudo chmod 640 /usr/share/squirrelmail/plugins/change_sqlpass/config.php

Now we can run the squirrelmail config program and get the plugin taken into use.

sudo squirrelmail-configure

Then navigate you way to the plugin selection screen. '8 Plugins'. Find change_pass on the list of available plugins and enter the number. It should change to the top of the screen under Installed plugins. Do not forget to save the changes before leaving the script. Load up Squirrelmail goto the options link and follow the link to change password.


Remove the software you unzipped into /tmp.

Adding the Mail Alias plugin

(This plugin requires the MDB2 modules from above). Download the mail_alias tar file from the Squirrelmail web site and unzip into /tmp. Read the README and INSTALL file. Follow the instructions. This is what I did.

cd /usr/share/squirrelmail/plugins 
sudo tar zxvf mail_alias-2.0.0-1.4.4.tar.gz 
cd mail_alias 
sudo cp config.php.sample config.php 
sudo nano config.php 

The lines I changed in the config.php are these

$mailbox_dir = '/var/vmail/[DOMAIN]/[USERNAME]'; 
 
$max_alias = '-1'; 
 
$ma_db_dsn = 'mysql://mail:<mysqlpassword>@localhost/postfix'; 
 
$sql_get_user = 'SELECT email FROM user WHERE email = ?'; 
 
$sql_get_domains = 'SELECT domain FROM domain'; 
 
$sql_get_aliases = 'SELECT a.source FROM alias as a, user as u' 
                  . ' WHERE a.destination = ? AND u.email = a.destination' 
                  . ' ORDER BY a.source'; 
 
$sql_add_alias_user = 'INSERT INTO alias (source, destination) VALUES (?, ?)'; 
 
$sql_add_alias_forward = 'INSERT INTO alias (source, destination) VALUES (?, ?)'; 
 
$sql_del_alias_user = 'DELETE FROM alias WHERE source = ?'; 
 
$sql_del_alias_forward = 'DELETE FROM alias WHERE source = ?'; 

Save the changes you made and as this file has a password it should not be world readable
so we change the group and permissions to suit.

sudo chown root:www-data  /usr/share/squirrelmail/plugins/mail_alias/config.php  
sudo chmod 640  /usr/share/squirrelmail/plugins/mail_alias/config.php

Now we need to do some major surgery on the file functions.php. This is the script that reads and writes the new aliases. Search for the line that sets $sql_data, we need to remove the last parameter as shown below

sudo nano functions.php
$sql_data = array($username);

Find the function heading add_db_alias_for_user scroll down to the select_search1 part and comment out the parts shown below.

function add_db_alias_for_user($emlalias, $identsynch) { 
 
//    $select_result1 = $dbConn->query($sql_add_alias_user, $data1);  
 
//    if (DB::isError($select_result1) || $dispErr) {  
//        echo '<p align=center><b>' . _("Error - Could not insert the alias record into th$  
//           . '&nbsp;&nbsp;' . _("Please contact the system administrator.") . '</b></p>';  
//      if (DB::isError($select_result1))  
//          $rollback = 1;  
//    }  

Now do the same thing again in this function.

function del_db_alias_for_user($emlalias, $identsynch) { 
 
//    $select_result1 = $dbConn->query($sql_del_alias_user, $emlalias);  
 
//    if (DB::isError($select_result1) || $dispErr) {  
//        echo '<p align=center><b>' . _("Error - Could not delete the alias record from th$  
//           . '&nbsp;&nbsp;' . _("Please contact the system administrator.") . '</b></p>';  
//      if (DB::isError($select_result1))  
//          $rollback = 1;  
//    }  

Lastly replace the function validate_email with this code. This is necessary as the function eregi has been deprieciated.

function validate_email($email) {
    global $dom_list, $not_local_part;
    // check for an empty alias
    //
    if (empty($email)){
       return false;
    }
    // check for a valid email format and that the domain is in the domain list
    // regular expression checks adapted from www.weberdev.com/get_example-980.html
    //
    if (preg_match('(@.*@)',$email) ||          preg_match('(\.\.)',$email) ||
        preg_match('(@\.)',$email) ||
        preg_match('(\.@)',$email) ||
        preg_match('(^\.)',$email) ||
        !preg_match('(^.+\@(\[?)[-_a-zA-Z0-9\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$)',$email)) {
        return false;
    }
    else {
        list($user, $domain) = explode('@',$email);
        if ((!preg_match('(^[_a-zA-Z0-9\.\-]+$)',$user)) || (!preg_match('(^[a-zA-Z0-9\.\-]+$)',$domain)) || (!strpos($dom_list,$domain))
           || (strpos($not_local_part,(':'.$user.':')))) {
            return false;
        }
        else {
            return true;
        }
    }
}

Save the changes you made and then run the configure script to add the plugin to SquirrelMail.

sudo squirrelmail-configure

Then navigate you way to the plugin selection screen. '8 Plugins'. Find mail_alias on the list
of available plugins and enter the number. It should change to the top of the sceen under
Installed plugins. Load up Squirrelmail goto the options link and follow the link to Mail Alias.


Remove the software you unzipped into /tmp.

Backup point
This would be a good backup point! 
 

UFW

Installing UFW

Configuring UFW

You have backed up your mailserver haven't you? This is where things can go wrong and panic really sets in.

We will be opening ports to allow access to mailserver and using port numbers. These port numbers come from /etc/services.

It is recommended that by default you deny all access to the server and then add rules to open ports and allow IP addresses through your firewall. If you are accessing your mailserver via an ssh connection, like I do then we need to make sure that connection stays open. :) We will therefore start the setup with a rule so we can access mailserver via ssh from one specific IP address and then enable UFW. This will stop all other traffic until we open the ports. I setup mailserver as a virtual machine on an Ubuntu box. The host system for the examples used in this part will have an IP address of say 192.168.0.22. Remember that the local LAN IP address for mailserver was 192.168.0.11.

sudo ufw default deny 
sudo ufw allow proto tcp from 192.168.0.22 to any port 22 
sudo ufw enable 
sudo ufw status 
Status: active 
 
To                         Action      From 
--                         ------      ---- 
22/tcp                     ALLOW       192.168.0.22

If you try and connect from a machine other then 192.168.0.22 your connection request will timeout. This is good and shows we have climbed the first step ;) Try accessing the test mail account from Evolution from a different machine. it will time out.


We need to allow the outside world access to the ports for POP3, IMAP, SMTP and web access and also the secure alternative to each. If we just add a rule to open those ports we are still open to brute force attacks. Where the hacker scum >:XX sends thousands of login attempts hoping one will allow entry. We can add a limiting option to make our firewall more secure. For instance what happens when (yes I did mean when not if) someone tries to hack your server. We can limit the number of login attempts from an individual IP address with one rule. Once enabled anyone trying to access your server six or more times in the last 30 seconds will be banned for one minute. All the connection attempts within that minute will be simply dropped.

sudo ufw allow 80,443/tcp 
sudo ufw allow 80,443/udp 
sudo ufw limit 25,110,143,465,993,995/tcp 
sudo ufw limit 25,110,143,465,993,995/udp 
Status: active 
 
To                         Action      From 
--                         ------      ---- 
22/tcp                     ALLOW       192.168.0.5 
80,443/tcp                 ALLOW       Anywhere 
80,443/udp                 ALLOW       Anywhere 
25,110,143,465,993,995/tcp LIMIT       Anywhere 
25,110,143,465,993,995/udp LIMIT       Anywhere 

The backup software I use is called BackupPC and it uses rsync to connect to the servers and workstations. Rsync sites on port 873. So I open that up to the local LAN.

sudo ufw allow from 192.168.0.10 to any port 873

You may have a few other services that need to connect from a specific machine (IP addreess) or you may want to open all ports from the local LAN. This is a security issue.

sudo ufw allow from 192.168.0.10 
sudo ufw allow from 192.168.0.0/24 

If you later see that IP 58.151.230.42 is trying to hack your server with repeated logins. It would be nice to deny all access to that IP address. But on problem with IPTABLES is that once access is granted with a rule it will not be removed again. for example we all ready granted access for SMPTS connections. To add the new deny rule for the scum hacker >:XX at 58.151.230.42. We need to addthe rule at the top of the list. Upto now we have just added them at the bottom. We can see the line number forthe existing rules witht he following command

sudo ufw status numbered
Status: active 
 
     To                         Action      From 
     --                         ------      ---- 
[ 1] 22/tcp                     ALLOW       192.168.0.5 
[ 2] 80,443/tcp                 ALLOW       Anywhere 
[ 3] 80,443/udp                 ALLOW       Anywhere 
[ 4] 25,110,143,465,993,995/tcp LIMIT IN    Anywhere 
[ 5] 25,110,143,465,993,995/udp LIMIT IN    Anywhere

We can then use the number to add a new rule. We want to add our rule to deny all access to the hacker as our new rule two. We can use the following command.

sudo ufw insert 2 deny from 58.151.230.42

We then end up with the following output, note the new rule on line two.

Status: active 
 
     To                         Action      From 
     --                         ------      ---- 
[ 1] 22/tcp                     ALLOW       192.168.0.5 
[ 2] Anywhere                   DENY IN     58.151.230.42 
[ 3] 80,443/tcp                 ALLOW       Anywhere 
[ 4] 80,443/udp                 ALLOW       Anywhere 
[ 5] 25,110,143,465,993,995/tcp LIMIT IN    Anywhere 
[ 6] 25,110,143,465,993,995/udp LIMIT IN    Anywhere

Ports used by the mailserver

ssh 22
SMTP 25
www 80
POP3 110
IMAP 143
HTTPS 443
SMTPs 465
IMAPs 993
POP3s 995
MySQL 3306

System Maintenance

When you are happy its working.

Turn off the extra logging

MySQL logging

sudo nano /etc/mysql/my.cnf
general_log_file = /var/log/mysql/mysql.log 
general_log = 1 

Dovecot

sudo nano /etc/dovecot/dovecot.conf
    log_path = /var/vmail/dovecot-deliver.log  

Rotating log files

Something to think about is that these log files can grow to a large size rather quickly. If you add them to the logrotate configuration, they can be kept under some control.

/etc/logrotate.d/dovecot-deliver
/var/vmail/dovecot-deliver.log { 
 
        weekly 
        rotate 4 
        compress 

Files we Updated or Modified

MySQL

/etc/mysql/my.cnf
$HOME/create_postfix_mysql_tables.sql

Postfix

/etc/postfix/mysql-virtual-mailbox-domains.cf
/etc/postfix/mysql-virtual-mailbox-maps.cf
/etc/postfix/mysql-virtual-alias-maps.cf
/etc/postfix/mysql-virtual-alias-maps-self.cf

/etc/postfix/main.cf
/etc/postfix/master.cf

Dovecot

/etc/dovecot/dovecot.conf
/etc/dovecot/dovecot-sql.conf

Amavis

/etc/amavis/conf.d/01-debian
/etc/amavis/conf.d/05-node_id
/etc/amavis/conf.d/15-av_scanners
/etc/amavis/conf.d/15-content_filter_mode
/etc/amavis/conf.d/50-user

Spamassassin

/etc/default/spamassassin
/etc/cron.daily/spamassassin

AVG Free

/etc/cron.daily/avgfree

Postgrey

/etc/postgrey/whitelist_clients
/etc/postgrey/whitelist_recipients

Apache

/etc/apache2/apache2.conf
/etc/apache2/ports.conf
/etc/apache2/sites-available/default
/etc/apache2/sites-available/example.com

Squirrelmail

/etc/apache2/sites-available/squirrelmail
/etc/php5/apache2/php.ini
/usr/share/squirrelmail/plugins/change_sqlpass/config.php
/usr/share/squirrelmail/plugins/mail_alias/config.php
/usr/share/squirrelmail/plugins/mail_alias/functions.php

Trouble shooting

Turn on logging

Postfix

For debugging the smpt service add a -v ti the smpt line in master.cf

smtp      inet  n       -       -       -       -       smtpd -v

Dovecot

If you get problem with authentication, try setting these in /etc/dovecot/dovecot.conf and then restart Dovecot

auth_verbose = yes
auth_debug = yes
auth_debug_passwords = yes
mail_debug=yes

enable auth_debug setting. See http://wiki.dovecot.org/WhyDoesItNotWork

MySQL

sudo nano /etc/mysql/my.cnf
general_log_file        = /var/log/mysql/mysql.log
general_log             = 1

Stuff to read

No feedback yet

Leave a comment


Your email address will not be revealed on this site.

Your URL will be displayed.
PoorExcellent
(Line breaks become <br />)
(Name, email & website)
(Allow users to contact you through a message form (your email will not be revealed.)
What can birds and aeroplanes both do?
antispam test