We want to allow users to relay mail using SMTP, but we don’t want anyone else to be able to. SASL is used to add authentication to the SMTP protocol, which in itself does not include any authentication. The package postfix-tls will enable SASL support in postfix.

NOTE: you must install the package libsasl-modules-plain or smptd will die a horrible death when trying to use sasl. The sasl package doesn’t come with any auth modules by itself. We need at least some, and we choose to use plaintext, since we are requiring the session is ssl anyway.

Postfix and SASL

A note from /usr/share/doc/postfix/SASL_README.gz:

“To run software chrooted with SASL support is an interesting exercise. It probably is not worth the trouble.”

Ok, so we disable chroot for smtpd in /etc/postfix/master.cf. To do so, change
the 5th entry for smptd to ‘n’ from ‘-’:

It is possible to run postfix chrooted, but it causes a whole lot of confusion to all involved and when you look at the postfix-users list people are told constantly by the postfix author not to run it chroot (he disagrees with the debian package maintainer to ship it chrooted)

Allow postfix access to the saslauthd mux (socket) located in /var/run/saslauthd postfix by putting it in the sasl group:

gpasswd -a postfix sasl

Configure postfix to rely mail via sasl, require authentication and tsl:

/etc/postfix/main.cf

smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
broken_sasl_auth_clients = yes
smtpd_tls_auth_only = yes

If using saslauthd, make sure its started:

/etc/init.d/saslauthd start

SASL authentication via PAM

A note from /usr/share/doc/postfix/SASL_README.gz:

“To run software chrooted with SASL support is an interesting exercise. It probably is not worth the trouble.”

Ok, so we disable chroot for smtpd in /etc/postfix/master.cf. To do so, change the entry for smtp to ‘n’ from ‘-’, so it looks like this:

smtp inet n - n - - smtpd

Configure sasl to use the pam in /etc/postfix/sasl/smtpd.conf:

pwcheck_method: pam

SASL authentication via saslauthd

Configure sasl to use the saslauthd:

/etc/postfix/sasl/smtpd.conf

pwcheck_method: saslauthd
mech_list: plain login

We need the following packages in order to get saslauthd to work:

apt-get install sasl2-bin libsasl2-modules

/etc/default/saslauthd

START=yes
MECHANISMS="ldap"
PARAMS="-O /etc/sasl/saslauthd.conf"

create /etc/sasl/saslauthd.conf and edit it:

> mkdir /etc/sasl
> cat >> /etc/sasl/saslauthd.conf
ldap_servers: ldap://localhost/
ldap_search_base: ou=People,dc=riseup,dc=net
ldap_auth_method: bind
ldap_filter: uid=%u

Note: since saslauthd just does a ldap bind as the user trying to
authenticate, i think that it could be run as any user. Ergo, it
should not be run as root.

See /usr/local/src/cyrus-sasl-2.1.12/saslauthd/LDAP_SASLAUTHD for more information.

Postfix and TLS

You will need the following TLS options configured:

# common TLS parameters
tls_random_source = dev:/dev/urandom
tls_daemon_random_source = dev:/dev/urandom

# Client side TLS
smtp_use_tls = yes
smtp_tls_key_file = /etc/certs/your.domain.here/key.pem
smtp_tls_cert_file = /etc/certs/your.domain.here/cert.pem
smtp_tls_CApath = /etc/ssl/certs
smtp_tls_CAfile = /etc/certs/roots/cacert-root.pem
smtp_tls_session_cache_database = sdbm:/var/postfix/smtp_scache
smtp_tls_per_site = hash:$tls_dir/tls_per_site
smtp_tls_loglevel = 1

# Server side TLS
smtpd_use_tls = yes
smtpd_tls_key_file = /etc/certs/your.domain.here/key.pem
smtpd_tls_cert_file = /etc/certs/your.domain.here/cert.pem
smtpd_tls_CAfile = /etc/certs/roots/cacert-root.pem
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_database = sdbm:/var/postfix/smtpd_scache
smtpd_tls_ask_ccert = yes

You will need to have a valid certificate created and installed in the directory referenced above. If
you dont have one, you need to create one now.

In order to actually do SMTPAuth over TLS, you need to enable the smtps daemon, which runs on port 465. To do this, you may need to uncomment these lines from the postfix/master.cf:

smtps    inet  n       -       -       -       -       smtpd
-o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes

Also, be sure any firewall you have allows this port.

Anonymized SMTP

If you do not anonymize your authenticated SMTP, then every email that a user sends out will include their home IP address!

Versions of postfix prior to 2.3 made it difficult to anonymize SMTP. Newer versions of postfix have the option that makes this much easier. You need to enable smtpd_sasl_authenticated_header = yes, which adds SASL information to your header. Once this information is there, header_checks can be put into place that rewrite the headers to anonymize their content.

The regular expression needs to be on one line, with a newline between the expression and the REPLACE line. If anyone knows how to get newlines in there, I’d like to know. This works for postfix >= 2.5):

/^Received: from (.* \([-._[:alnum:]]+ \[[.[:digit:]]{7,15}\]\)).*\(Authenticated sender: ([^)]+)\).*by ($HOSTNAME\.$DOMAIN\.$TLD) \(([^)]+)\) with (E?SMTPS?A?) id ([A-F[:digit:]]+).*/
  REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: $2) with $5 id $6

This will replace the SASL authenticated hostname with ‘localhost’ and the resulting header will look like this:

Received: from [127.0.0.1] (localhost [127.0.0.1])   (Authenticated sender: micah@petrel.riseup.net) with ESMTP id 17E6C86A for <micah@riseup.net>;   Sun, 12 Nov 2006 16:54:56 -0800 (PST)

NOTE: Be careful if you decide to use this regexp, you will need to replace $HOSNAME, $DOMAIN and $TLD to match your system. Also, be careful if you change this regexp, some clients present different headers, I’ve seen some people have different information sent as ‘helo’ and not all say where the message is for.

Testing authenticated SMTP

For testing you are going to need the special telnet that supports SSL/TLS connections:

apt-get install telnet-ssl

This package will allow you to telnet over a ssl connection. For example telnet -z ssl mail.riseup.net 25 will establish a ssl connection to port 25 of host mail.riseup.net.

Step 1: ensure no unecrypted auth

Since we only want to allow authentication when using TLS, first lets check to make sure we are not advertising AUTH to mail clients when they are not using TSL:

shell> telnet auk.riseup.net
out> Trying 204.13.164.27...
out> Connected to auk.riseup.net.
out> Escape character is '^]'.
out> 220 auk.riseup.net ESMTP
you> EHLO me
out> 250-riseup.net
out> 250-PIPELINING
out> 250-SIZE 10240000
out> 250-ETRN
out> 250-STARTTLS
out> 250-XVERP
out> 250 8BITMIME
you> quit
out> 221 Bye

(out> is what is printed out by postfix, you> is what you type).

If you see 250-AUTH in the response to the EHLO, then you have a problem!

Step 2: ensure encrypted auth is supported

Connect to postfix using ssl and make sure that it lists the AUTH mechs (the second line is for the broken outlook clients):

telnet -z ssl willow.riseup.net 25
Trying 216.162.217.193...
Connected to willow.riseup.net.
Escape character is '^]'.
220 riseup.net ESMTP Postfix
EHLO me
250-riseup.net
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-STARTTLS
250-AUTH NTLM LOGIN PLAIN DIGEST-MD5 CRAM-MD5
250-AUTH=NTLM LOGIN PLAIN DIGEST-MD5 CRAM-MD5
250 8BITMIME 

Step 3: generate a base64 encoded username and password pair

In order to auth with postfix, we need to base64 encode a string that consists of:

username + \0 + username + \0 + password

Usename is repeated and there is a \0 twice in there!

perl -MMIME::Base64 -e 'print encode_base64("micah\0micah\0passwd");'
l7ajTWgJbs4jfWgBGW4hZFBXbg==

Step 4: attempt to authenticate with base64 string

AUTH PLAIN l7ajTWgJbs4jfWgBGW4hZFBXbg==
235 Authentication successful