Installing Postfix and Courier with MySQL and SASL on Debian 7

I recently had to move to a new server and had some troube getting Postfix and Courier to work as I wanted. The tutorial I used to follow a bunch of years ago is gone and the tutorials I found were either outdated, wrong or didn’t do it my way. So with some inspiration from other tutorials including the old one I used to have, I have written my own modified version.

Step 1: Prepare your certificate now as you will be using it later
If you don’t already have one you can get one for free at StartSSL
This tutorial wont cover the steps at StartSSL as there are other documents for that.

Files that you will need:

– yourcert.crt
– yourprivatekey.key (in a decrypted state for server purpose)
– ca.pem
– sub.class1.server.ca.pem

Place them in a folder like /etc/ssl/StartCom/year-month-day
For example, I use /etc/ssl/StartCom/2015-08-10 since that is the expiration date for one of my certs.
When the files have been placed there you need to do the following:

cat yourcert.crt yourprivatekey.key ca.pem sub.class1.server.ca.pem > combined.pem

This is because Courier wants it in a pem file later, while Postfix wants them separated.
There might be a way to keep it consistent but I haven’t checked.

Also remember to set permissions to this folder!

chown -R root:root /etc/ssl/StartCom
chmod -R 640 /etc/ssl/StartCom

Your private key is in there and you need to protect it.

Step 2: Install required software

apt-get install postfix postfix-mysql postfix-doc mysql-client mysql-server courier-authdaemon courier-authlib-mysql courier-pop courier-pop-ssl courier-imap courier-imap-ssl libsasl2-2 libsasl2-modules libsasl2-modules-sql sasl2-bin libpam-mysql openssl apache2 libapache2-mod-php5 php5 php5-mysql libpam-smbpass

Step 3: Setup MySQL database

mysql -u root -p
CREATE mail;
GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail'@'localhost' IDENTIFIED BY 'mail_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail'@'localhost.localdomain' IDENTIFIED BY 'mail_password';
FLUSH PRIVILEGES;

USE mail;

CREATE TABLE domains (
domain varchar(50) NOT NULL,
PRIMARY KEY (domain) )
ENGINE=MyISAM;

CREATE TABLE forwardings (
source varchar(80) NOT NULL,
destination TEXT NOT NULL,
PRIMARY KEY (source) )
ENGINE=MyISAM;

CREATE TABLE users (
email varchar(80) NOT NULL,
password varchar(20) NOT NULL,
PRIMARY KEY (email)
) ENGINE=MyISAM;

CREATE TABLE transport (
domain varchar(128) NOT NULL default '',
transport varchar(128) NOT NULL default '',
UNIQUE KEY domain (domain)
) ENGINE=MyISAM;

exit

Step 4: Configure postfix

Create these files below and paste the content that follows.
Remember to replace the user and password with whatever you chose before.

vim /etc/postfix/mysql-virtual_domains.cf

user = mail
password = mail_password
dbname = mail
table = domains
select_field = 'virtual'
where_field = domain
hosts = 127.0.0.1
vim /etc/postfix/mysql-virtual_forwardings.cf

user = mail
password = mail_password
dbname = mail
table = forwardings
select_field = destination
where_field = source
hosts = 127.0.0.1
vim /etc/postfix/mysql-virtual_mailboxes.cf

user = mail
password = mail_password
dbname = mail
table = users
select_field = CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/')
where_field = email
hosts = 127.0.0.1
vim /etc/postfix/mysql-virtual_email2email.cf

user = mail
password = mail_password
dbname = mail
table = users
select_field = email
where_field = email
hosts = 127.0.0.1
vim /etc/postfix/mysql-virtual_transports.cf

user = mail
password = mail_password
dbname = mail
table = transport
select_field = transport
where_field = domain
hosts = 127.0.0.1

Change permissions of the files

chmod o= /etc/postfix/mysql-virtual_*.cf
chgrp postfix /etc/postfix/mysql-virtual_*.cf

Create user vmail

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /home/vmail -m

Set options in the Postfix configuration file.
Replace server1.example.com with a FQDN of your server.
Also replace the cert and key file with the cert and key file in your StartCom folder.
For example instead of /etc/postfix/smtpd.cert you write /etc/ssl/StartCom/2015-08-10/yourcert.crt

postconf -e 'myhostname = server1.example.com'
postconf -e 'mydestination = localhost, localhost.localdomain'
postconf -e 'mynetworks = 127.0.0.0/8'
postconf -e 'virtual_alias_domains ='
postconf -e 'virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf'
postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf'
postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf'
postconf -e 'virtual_mailbox_base = /home/vmail'
postconf -e 'virtual_uid_maps = static:5000'
postconf -e 'virtual_gid_maps = static:5000'
postconf -e 'smtpd_sasl_auth_enable = yes'
postconf -e 'broken_sasl_auth_clients = yes'
postconf -e 'smtpd_sasl_authenticated_header = yes'
postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination'
postconf -e 'smtpd_use_tls = yes'
postconf -e 'smtpd_tls_auth_only = yes'
postconf -e 'smtpd_tls_received_header = yes'
postconf -e 'smtpd_helo_required = yes'
postconf -e 'smtp_tls_note_starttls_offer = yes'
postconf -e 'smtpd_tls_cert_file = /etc/postfix/smtpd.cert'
postconf -e 'smtpd_tls_key_file = /etc/postfix/smtpd.key'
postconf -e 'smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3'
postconf -e 'transport_maps = proxy:mysql:/etc/postfix/mysql-virtual_transports.cf'
postconf -e '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 $virtual_mailbox_limit_maps'

Now open /etc/postfix/master.cf and uncomment the following section.
The format of these lines are important so only remove the comment characters (#) and nothing else.

#smtps     inet  n       -       -       -       -       smtpd
#  -o syslog_name=postfix/smtps
#  -o smtpd_tls_wrappermode=yes
#  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING

Step 5: Configure Saslauthd

Create a folder for saslauthd

mkdir -p /var/spool/postfix/var/run/saslauthd

Open the following file.
Set START to yes and change the line OPTIONS=”-c -m /var/run/saslauthd” to OPTIONS=”-c -m /var/spool/postfix/var/run/saslauthd -r”.

vim /etc/default/saslauthd

Open the following file and configure pam to use MySQL to authenticate you.

vim /etc/pam.d/smtp
auth    required   pam_mysql.so user=mail passwd=mail_password host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1
account sufficient pam_mysql.so user=mail passwd=mail_password host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1

Edit smtpd.conf and configure sasl to use the sql plugin to authenticate users.

vim /etc/postfix/sasl/smtpd.conf

pwcheck_method: saslauthd
mech_list: plain login
allow_plaintext: true
auxprop_plugin: sql
sql_engine: mysql
sql_hostnames: 127.0.0.1
sql_user: mail
sql_passwd: mail_password
sql_database: mail
sql_select: select password from users where email = '%u@%r'

Add the postfix user to the sasl group

adduser postfix sasl

Restart postfix and saslauthd

/etc/init.d/postfix restart
/etc/init.d/saslauthd restart

Step 6: Configure courier

Edit Courier to use MySQL to authenticate

vim /etc/courier/authdaemonrc

[...]
authmodulelist="authmysql"
[...]
cp /etc/courier/authmysqlrc /etc/courier/authmysqlrc_orig
cat /dev/null > /etc/courier/authmysqlrc
vim /etc/courier/authmysqlrc

MYSQL_SERVER localhost
MYSQL_USERNAME mail_admin
MYSQL_PASSWORD mail_password
MYSQL_PORT 0
MYSQL_DATABASE mail
MYSQL_USER_TABLE users
MYSQL_CRYPT_PWFIELD password
MYSQL_UID_FIELD 5000
MYSQL_GID_FIELD 5000
MYSQL_LOGIN_FIELD email
MYSQL_HOME_FIELD "/home/vmail"
MYSQL_MAILDIR_FIELD CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/')

Now configure Courier to use your StartSSL cert for imap.
Courier wants the combined pem file.

vim /etc/courier/imapd-ssl

Find the row TLS_CERTFILE and change the path.
For example: TLS_CERTFILE=/etc/ssl/StartCom/2015-08-10/combined.pem

Also find the the following rows and make sure they are set to the values below.

IMAPDSTARTTLS=YES
IMAP_TLS_REQUIRED=1
TLS_PROTOCOL=TLS1
TLS_STARTTLS_PROTOCOL=TLS1

Since I don’t use pop3 I will make sure to disable it.

vim /etc/courier/pop3-ssl

Find the the following row and make sure it’s set to the value below.

POP3DSSLSTART=NO
vim /etc/courier/pop3
POP3DSTART=NO

Restart courier

/etc/init.d/courier-authdaemon restart
/etc/init.d/courier-imap restart
/etc/init.d/courier-imap-ssl restart
/etc/init.d/courier-pop restart
/etc/init.d/courier-pop-ssl restart

Step 7: Modify aliases

vim /etc/aliases

[...]
postmaster: root
root: postmaster@yourdomain.tld
[...]

Issue this command to update the aliases

newaliases

That should be all.
Don’t forget to populate the database with a user and a domain.

INSERT INTO domains VALUES('somedomain.com');
INSERT INTO users VALUES('user@somedomain.com', ENCRYPT('mypassword'));

If you have any comments or feedback then feel free to leave them in the comment section below.
This tutorial will be updated later with some more security related settings to protect against certain SSL/TLS attacks.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.