DæmonNews: News and views for the BSD community

Daemon News Ezine BSD News BSD Mall BSD Support Forum BSD Advocacy BSD Updates

Postfix with SASL Authentication over TLS

Grzegorz Czapliñski <gregory@prioris.mini.pw.edu.pl>

In today's internet there is a lot of spam, forged mails and people who make use of this. It is importatnt to be secure, secure your users and the rest of the community from your users as well. It's better to be secure than to be sorry if an accident happens. You may not know that your users send spam until you get on the spamming list. I hope I don't have to explain why mechanisms such as: identification, authentication and authorization have to be implemented. In this article I will show you how to force users to authenticate before sending mail through Postfix. Ready?

Postfix installation

To install postfix-current, go to /usr/ports/mail/postfix. Before making anything check your umask. Preferably it should be set to 022. Now type make. You should get a "Postfix configuration options" screen. Select: PCRE, SASL2, DB3, TLS. If you need any other options just mark them with "X" by pressing space. If your system is 5.0-RELEASE, remember there is no PERL installed by default. Now type make. The installation will take a while so sit back and relax but don't go away. Before the installation of cyrus-sasl your system will prompt you to set "Additional SASL options". Choose DB3, SASLAUTHD and accept. If the build process finished without any problems type make install. The installation script will add postfix user and group. It will also ask you about changing contents of the /etc/mail/mailer.conf. Accept the change and don't worry, you can find the old file under /etc/mail/mailer.conf.old. All configuration files you will find in the /usr/local/etc/postfix directory.

To disable sendmail set these variables in /etc/rc.conf:

	sendmail_enable="NONE"
	mta_start_script=""
	sendmail_outbound_enable="NO"
	sendmail_submit_enable="NO"
	sendmail_msp_queue_enable="NO"

Create a simple postfix.sh script for starting/stopping postfix and save it in /usr/local/etc/rc.d. It may look like:

	#!/bin/sh
	case $1 in
		start)
		  if [ -x /usr/local/sbin/postfix ]; then
		       /usr/local/sbin/postfix start
		  fi
		  ;;
		stop)
		       /usr/local/sbin/postfix stop
		  ;;
		reload)
		      /usr/local/sbin/postfix reload
		  ;;
		*)
		  echo "USAGE $0 (start|stop|reload)"
		  exit 1
	esac

Postfix configuration

After the installation I usually create a link from /etc/postfix to /usr/local/etc/postfix. Just for simplicity.

	tahoe# ln -s /usr/local/etc/postfix /etc/postfix

To make aliases work correctly, create a link from /etc/aliases to /usr/local/etc/postfix/aliases.

	tahoe# ln -s /usr/local/etc/postfix/aliases /etc/aliases

Change aliases as appropriate to your site and type newaliases. You should see two files:

	tahoe# ls -l /etc/aliases*
	lrwxr-xr-x  1 root  wheel     20 Feb 15 18:00 /etc/aliases ->
	/usr/local/etc/postfix/aliases
	-rw-r--r--  1 root  wheel  49152 Feb 15 18:00 /etc/aliases.db

Now edit main.cf file to configure postfix. Set: myhostname, myorigin equal to the output of the hostname command.

	myhostname = Your hostname here
	myorigin = Your hostname here
	inet_interfaces = $myhostname, localhost
	mydestination = $myhostname, localhost.$mydomain, $mydomain
	mynetworks_style = host 
	
	local_recipient_maps = $alias_maps unix:passwd.byname
	mail_spool_directory = /var/mail - That is default.

Remember that your configuration may need different options. Consult an original main.cf file as the comments are superb.

Start postfix with this command:

	/usr/local/sbin/postfix start

or if it's already running type:

	/usr/local/sbin/postfix reload

If you make any changes to main.cf file, remember to reload Postfix! Otherwise the changes will not take effect.

Check the config

Send a test mail to yourself to check that everything is OK before we start SASL configuration. Now connect to port 25 on your machine and see if ESMTP is working.

	prioris% telnet tahoe.acn.waw.pl 25
	Trying 212.76.41.193...
	Connected to tahoe.acn.waw.pl.
	Escape character is '^]'.
	220 tahoe.acn.waw.pl ESMTP Postfix
	ehlo prioris.mini.pw.edu.pl
	250-tahoe.acn.waw.pl
	250-PIPELINING
	250-SIZE 10240000
	250-VRFY
	250-ETRN
	250-STARTTLS
	250-XVERP
	250 8BITMIME

If you see similar output, it's okay. Type quit to disconnect.

SASL configuration

Now go to /usr/local/lib/sasl2, create smtpd.conf file with these contents:

	pwcheck_method: saslauthd
	mech_list: plain login

Edit /usr/local/etc/rc.d/saslauthd.sh and change sasl_saslauthd_flags variable from "-a pam" to "-a getpwent". The correct line will now look like:

	sasl_saslauthd_flags="-a getpwent"

stop and start saslauthd again.

	/usr/local/etc/rc.d/saslauthd.sh stop
	/usr/local/etc/rc.d/saslauthd.sh start

Tweak Postfix

Now, go back and edit main.cf again. Somewhere at the end add:

	enable_sasl_authentication = yes
	smtpd_recipient_restrictions =
	   permit_sasl_authenticated,
	   permit_mynetworks,
	   check_relay_domains
	smtpd_sasl_auth_enable = yes
	smtpd_sasl_security_options = noanonymous
	smtpd_sasl_local_domain =
	broken_sasl_auth_clients = yes

Now you have to edit master.cf for postfix. Change the smtp line to look like:

	smtp      inet  n       n       n       -       -       smtpd

Yes, we don't chroot smtpd. Otherwise it will not work.

Test Postfix with SASL

Before testing SASL authentication we have to encode our credentials with Base64. To do that let's issue a command:

	tahoe% perl -MMIME::Base64 -e 'print encode_base64("gregory\0gregory\0test");'
	Z3JlZ29yeQBncmVnb3J5AHRlc3Q=

The syntax is:

	perl -MMIME::Base64 -e 'print encode_base64("username\0username\0password");'

Don't forget to put "\0" before username and password.

Reload your new Postfix configuration and telnet again to port 25.

	prioris% telnet tahoe.acn.waw.pl 25  
	Trying 212.76.41.193...
	Connected to tahoe.acn.waw.pl.
	Escape character is '^]'.
	220 tahoe.acn.waw.pl ESMTP Postfix
	ehlo prioris.mini.pw.edu.pl
	250-tahoe.acn.waw.pl
	250-PIPELINING
	250-SIZE 10240000
	250-VRFY
	250-ETRN
	250-AUTH LOGIN PLAIN
	250-AUTH=LOGIN PLAIN
	250-XVERP
	250 8BITMIME
	AUTH PLAIN Z3JlZ29yeQBncmVnb3J5AHRlc3Q=
	235 Authentication successful
	quit
	221 Bye
	Connection closed by foreign host.

Hullawrerrr! It's working!

Not so fast, what about TLS?

Not so fast, all of the credentials are sent in cleartext which means they can be sniffed out from the wire. Here comes TLS into play. Before we put it to work we need a certificate. Either you get it from a Certificate Authority whom you have to pay, or you create it for yourself. I will not describe how to become a Certificate Authority; instead I will show you how you can create a self signed .pem certificate.

TLS configuration

OpenSSL is installed by default, so these are the steps you have to take to put TLS to work.

Create /usr/local/etc/postfix/ssl directory.

	tahoe# mkdir /usr/local/etc/postfix/ssl
	tahoe# chmod 700 /usr/local/etc/postfix/ssl

Because /etc/postfix is a symlink to /usr/local/etc/postfix I will use shorter names here.

Create a configuration file for your certificate. Name it pst.cnf.

	RANDFILE = /etc/postfix/ssl/post.rand
	
	[ req ]
	default_bits = 1024
	encrypt_key = yes
	distinguished_name = req_dn
	x509_extensions = cert_type
	prompt = no
	
	[ req_dn ]
	C=countryName Two letters!
	ST=stateOrProvinceName
	L=localityName
	O=organizationName
	OU=OrganizationalUnitName
	CN=commonName
	emailAddress=emailAddress
	
	[ cert_type ]
	nsCertType = server

Generate certificate:

	tahoe# dd if=/dev/urandom of=/etc/postfix/ssl/post.rand count=1 2>/dev/null
	tahoe# /usr/bin/openssl req -new -x509 -days 365 -nodes \
		-config /etc/postfix/ssl/pst.cnf -out /etc/postfix/ssl/post.pem \
		-keyout  /etc/postfix/ssl/post.pem
	tahoe# /usr/bin/openssl gendh -rand /etc/postfix/ssl/post.rand 512  \
		>>/etc/postfix/ssl/post.pem 
	tahoe# /usr/bin/openssl x509 -subject -dates -fingerprint -noout -in \ 
		/etc/postfix/ssl/post.pem

Now you should have a valid certificate in /etc/postfix/ssl directory under post.pem name.

Tweak Postfix again

And of course we have to add some config options to our main.cf file:

	#TLS
	smtp_use_tls = yes
	smtpd_use_tls = yes
	smtpd_tls_auth_only = yes
	smtp_tls_note_starttls_offer = yes
	smtpd_tls_key_file = /etc/postfix/ssl/post.pem
	smtpd_tls_cert_file = /etc/postfix/ssl/post.pem
	smtpd_tls_CAfile = /etc/postfix/ssl/post.pem
	smtpd_tls_loglevel = 3
	smtpd_tls_received_header = yes
	smtpd_tls_session_cache_timeout = 3600s
	tls_random_source = dev:/dev/urandom

Save the file, reload postfix and enjoy SASL authentication over TLS.

Are we safe now?

Default postfix installation is not an open relay. No one can relay through your Postfix unless you allow so. The problem occurs when a spammer obtains a valid list of usernames and aliases on your server. For example he may know there are accounts for root and user gregory. It is enough for him to telnet to your Postfix, issue helo instead of ehlo and forge mail from gregory to root. And root might be disappointed with gregory especially when he is a BOFH.

How to solve the problem? Edit main.cf and add:

	smtpd_sender_restrictions =  permit_mynetworks,
		reject_sender_login_mismatch
	smtpd_sender_login_maps = hash:/usr/local/etc/postfix/sender_login_maps

/usr/local/etc/postfix/sender_login_maps is a hash map which consists of valid usernames and aliases. If my login is gregory and I have an alias G.Czaplinski I have put both values into the map. It might be like this:

gregory gregory
G.Czaplinski gregory

The second column in the map is a username you are logged in via SASL. That indicates user gregory owns the alias.

This simple script may give you an idea how to generate the map automatically from /etc/passwd:

	#!/bin/sh -
	username=`cat /etc/passwd | awk -F: '{print $1}'`
	
	for i in `echo $username`
	do
		echo  "$i       $i"
	done

To create a map do:

	tahoe# postmap /usr/local/etc/postfix/sender_login_maps

Now every user wanting to send a mail has to authenticate. No forged mails from gregory to root!

Remember to consult the manual or howto on UCE controls. Read the Postfix documentation at http://www.postfix.org, especially Configuration. I hope someone will find this article useful and the hints given here will save you time. Good luck and till the next time...


Important! After the publication, several questions were asked and also I came up with some useful conclusions. Follow the link to find how to make the config even more secure.

Google
Web daemonnews.org

More Articles
  • Interview with Jan Schaumann
  • Interview with Theo de Raadt
  • Book Review: Virtualization with VMware ESX Server
  • Editorial: Not Quite Dead Yet
  • The Design of OpenBGPd
  • Interview with der Mouse
  • Letter to Steve Jobs
  • Interview with Manuel Bouyer on Xen
  • Apple and Open Source
  • BSDCan 2006
  • BSD Certification Survey Results
  • Lab in a Box
  • Ike Notes on BSDCan 2005
  • BSDCan 2005 Photos
  • FreeBSD Developer Summit Pictures

  • Advertisements




    Author maintains all copyrights on this article.
    Images and layout Copyright © 1998-2006 Dæmon News. All Rights Reserved.