We needed a set of servers that could easily be load balanced and did nothing but send mail via SMTP. Many clients need to send their mail from remote locations and will most often not be connected to our network. To avoid allowing the servers to be used to send spam we had to be sure that only our clients could send mail through the servers. To do this we chose to authenticate the users on the SMTP servers and store the user credentials in MySQL.
This setup allows for the following:
Users are required to authenticate against the SMTP servers to send mail.
Users can use an alternate port (587) if their ISP is blocking SMTP port 25.
Users can connect using TLS to encrypt traffic between their mail client and the server.
This document does not describe how to get data into the MySQL database from the front end mail servers.
As of the writing of this how-to the port versions were as follows:
MySQL – 5.1.22
courier-authlib (authdaemond) – 0.60.2
Postfix – 2.4.6,1
Install MySQL
# cd /usr/ports/databases/mysql51-server
# make install clean
# cd /usr/ports/databases/mysql51-client
# make install clean
Allow MySQL to run:
# echo “mysql_enable=YES” >> /etc/rc.conf
Create a data directory:
# mkdir /usr/local/mysql
# mkdir /usr/local/mysql/data
# chown -R mysql /usr/local/mysql/
# chgrp -R mysql /usr/local/mysql/
Configure MySQL:
# cp /usr/local/share/mysql/my-medium.cnf /etc/my.cnf
# /usr/local/bin/mysql_install_db –user=mysql –datadir=/usr/local/mysql/data
# ln -s /usr/local/mysql /var/db/mysql
# chown -R mysql /var/db/mysql/
# chgrp -R mysql /var/db/mysql/
Start MySQL:
# /usr/local/etc/rc.d/mysql-server start
Change passwords and create new users
Set the root password:
# /usr/local/bin/mysqladmin -u root password ‘newpassword’
Access the MySQL console:
# /usr/local/bin/mysql -u root -p{password}
Allow remote access via root user if desired:
mysql> GRANT ALL PRIVILEGES ON *.* TO ‘root’@'%’ IDENTIFIED BY ‘{password}’;
Access the MySQL console:
# /usr/local/bin/mysql -u root -p{password}
Create the SMTP auth database and table:
mysql> CREATE DATABASE smtpauthdata;
mysql> USE smtpauthdata;
mysql>
DROP TABLE IF EXISTS `smtpauthusers`;
CREATE TABLE `smtpauthusers` (
`id` int(10) unsigned NOT NULL auto_increment,
`username` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
Add a user for authdeamon access:
mysql> GRANT SELECT ON smtpauthdata.* TO ’smtpauthuser’@'localhost’ IDENTIFIED BY ‘{password}’;
Add a user for the sync script access (we will be inserting user auth data from another database):
mysql> GRANT SELECT, INSERT, DELETE ON smtpauthdata.* TO ’smtpauthsync’@'%’ IDENTIFIED BY ‘{password}’;
Install Courier-Authlib (authdaemond)
# cd /usr/ports/security/courier-authlib
# make install clean
Select AUTH_MYSQL in the configuration menu.
Allow authdaemond to run:
# echo “courier_authdaemond_enable=YES” >> /etc/rc.conf
Configure authdaemond:
# pico /usr/local/etc/authlib/authdaemonrc
Reduce the value of ‘authmodulelist’ to just ‘authmysql’:
Comment the default authmodulelist= line
Add:
authmodulelist=”authmysql”
# pico /usr/local/etc/authlib/authmysqlrc
Modify as follows:
MYSQL_SERVER localhost
MYSQL_USERNAME smtpauthuser
MYSQL_PASSWORD {yourpassword}
MYSQL_SOCKET /tmp/mysql.sock
MYSQL_PORT 0
MYSQL_OPT 0
MYSQL_DATABASE smtpauthdata
MYSQL_USER_TABLE smtpauthusers
MYSQL_CLEAR_PWFIELD password
MYSQL_UID_FIELD 999
MYSQL_GID_FIELD 999
MYSQL_LOGIN_FIELD username
MYSQL_HOME_FIELD ‘/home/nofolder’
Install Postfix
# cd /usr/ports/mail/postfix
# make install clean
Select SASL2, TLS at the configuration menu.
Allow Postfix to run:
# echo “postfix_enable=YES” >> /etc/rc.conf
Enable SASL for Postfix:
# mkdir /usr/local/etc/sasl2
# pico /usr/local/etc/sasl2/smtpd.conf
Add:
pwcheck_method: authdaemond
log_level: 3
mech_list: PLAIN LOGIN
authdaemond_path: /var/run/authdaemond/socket
# These two lines exist to keep errors from showing up in the logs
auxprop_plugin: mysql
sql_select: select password from users where email = ‘%u@%r’
Enable TLS for Postfix.
Generate an SSL certificate:
# mkdir /usr/local/postfix
# mkdir /usr/local/postfix/ssl
# cd /usr/local/postfix/ssl
# openssl req -new -x509 -nodes -out smtpd.pem -keyout smtpd.pem -days 3650
(answer questions)
Enter configuration options for Postfix:
# pico /usr/local/etc/postfix/main.cf
Add:
# tls config
smtp_use_tls = yes
smtpd_use_tls = yes
smtp_tls_note_starttls_offer = yes
smtpd_tls_key_file = /usr/local/postfix/ssl/smtpd.pem
smtpd_tls_cert_file = /usr/local/postfix/ssl/smtpd.pem
smtpd_tls_CAfile = /usr/local/postfix/ssl/smtpd.pem
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
# sasl config
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
#smtp restrictions
smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, check_relay_domains
# The email gateway is supposed to accept emails to postmaster and abuse.
# Define a virtual alias map
virtual_alias_maps = hash:/usr/local/etc/postfix/virtual
NOTE:
There are other configurations settings for postfix in main.cf that you may want to look into for your environment.
myhostname = server FQDN
local_transport = error:local mail delivery is disabled
mynetworks = 127.0.0.0/8
myorigin = server FQDN
Set Postfix to listen on the RFC standard alternate TCP ports:
# pico /usr/local/etc/postfix/master.cf
Add:
# listen on the RFC alternate SMTP port
587 inet n – n – - smtpd
Set basic email addresses:
# pico /usr/local/etc/postfix/virtual
Add:
sysadmin sysadmin@opusnet.com
postmaster sysadmin
abuse sysadmin
#root sysadmin
Generate the file:
# postmap /usr/local/etc/postfix/virtual
# newaliases
Allow postfix access to the authdaemond socket:
# chown -R postfix:postfix /var/run/authdaemond
Start the applications
Start Postfix
# /usr/local/etc/rc.d/postfix start
Start authdaemond
# /usr/local/etc/rc.d/courier-authdaemond start
Testing
First create a Base 64 encoded username / password string:
(install the mmencode port if it doesn’t exist – /usr/ports/converters/mmencode)
# printf ‘yourusername’ | mmencode
# printf ‘yourpassword’ | mmencode
These will yield a cryptic set of characters
Next, connect to Postfix on the server via Telnet:
# telnet localhost 25
You should see: 220 servername ESMTP Postfix
Next say hello:
> EHLO example.com
You should see something like:
250-smtp02-opus.opusnet.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
You will want to see three key lines that show that TLS and SMTP Auth are enabled:
250-STARTTLS
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
Next attempt your login:
> AUTH LOGIN
You will see a Base 64 encoded login prompt – paste your encoded username string and press enter.
You will see a Base 64 encoded password prompt – paste your encoded password string and press enter.
Hopefully you will see something like:
> 235 2.0.0 Authentication successful
To send a test message once authenticated:
> MAIL FROM:<sender@domain.com>
Then press ENTER. If the sender is not permitted to send mail, the SMTP server will return an error.
> RCPT TO:<recipient@remotedomain.com>
Then press ENTER. If the recipient is not a valid recipient or the server does not accept mail for this domain, the SMTP server will return an error.
> DATA.
Type your message text, press ENTER, type a period (.), and then press ENTER again.