Ever since I got an iPhone I wanted to send email through my own mail server. To do this without making an open relay you can use a technique called SMTP authorization. It allows you to authenticate to your SMTP MTA and send message to the whole wide world. Unauthenticated connections will still only be able to send mail to mydestination, virtual_alias_domains and relay_domains. This guide is written using Debian Squeeze (6.0), but apart from the SASL installation and file paths it should be applicable to most Linux distros.

TLS

Whenever you send a password over the network it ought to be encrypted. Add the following parameters to your main.cf to enable TLS:

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

Of course you need to make sure the cert_file options are pointing to valid certificates. The default snakeoil certificates should be secure enough for most users, but you can always purchase some CA signed certificates.

You can test TLS using the OpenSSL utility

$ openssl s_client -starttls smtp -crlf -connect 127.0.0.1:25
CONNECTED(00000003)
[output truncated]
SSL handshake has read 1646 bytes and written 354 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 17C511889EDC11109C9F71C16F7F70AB9B8868129C4B796F96B2F0A68E581A8E
    Session-ID-ctx:
    Master-Key: E391BF9B8940CD36D5E98BC5FAF05860E86AAE4667D5E8E87081AD4A98A7EA91F770790C053A2ECCA42AD2937AD83F90
    Key-Arg   : None
    Start Time: 1365632805
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---
250 DSN
quit
221 2.0.0 Bye
closed
$

SASL

SMTP does not have any authentication capabilities built-in, but it can be extended using the SASL framework. SASL is described in RFC4422. To keep things simple we will use PAM as an authentication backend. Refer to saslauthd(8) for more information regarding authentication backends.

To set up SASL:

  • Install all the packages needed for SASL:
$ sudo apt-get install libsasl2-2 sasl2-bin libsasl2-modules
  • Edit /etc/default/saslauthd. You can leave the default settings but make sure these match:
[...]
START=yes
MECHANISMS="pam"
THREADS=1
[...]
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"
  • Create /etc/postfix/sasl/smtpd.conf:
saslauthd_version: 2
pwcheck_method: saslauthd
mech_list: plain login
  • Modify /etc/postfix/main.cf:
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions =
   permit_sasl_authenticated,
   permit_mynetworks,
   check_relay_domains
  • Add the postfix user to the sasl Unix group:
$ adduser postfix sasl
  • Start the SASL daemon and restart Postfix:
$ /etc/init.d/saslauthd start
$ /etc/init.d/postfix restart

You can test the SMTP AUTH functionality by creating a base64 hash of your password and using that to log on:

$ printf '\0%s\0%s' 'username' 'password' | openssl base64
AHVzZXJuYW1lAHBhc3N3b3Jk

$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.gallische-dorp.net ESMTP Postfix
EHLO localhost
250-mail.gallische-dorp.net
250-PIPELINING
250-SIZE 20480000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH PLAIN AHVzZXJuYW1lAHBhc3N3b3Jk
235 2.7.0 Authentication successful
quit
221 2.0.0 Bye
Connection closed by foreign host.