Adventures with Postfix - Part 2.

This post focuses on my outgoing email setup for a custom domain. Read my previous post for the initial setup with Postfix to forward incoming email.

Adventures with Postfix: Part 1

Sender Authentication #

For outgoing email from Postfix (using Gmail or another client), I setup authentication to only allow known senders to send email. Postfix works with Cyrus (default) or Dovecat for SASL authentication.

# Installs Cyrus SASL
$ sudo apt-get install sasl2-bin libsasl2-modules

# Creates user name & password
$ sudo saslpasswd2 -c -u example.com recipient1

# List users
$ sudo sasldblistusers2

# Restricts access to password file
$ sudo chmod 400 /etc/sasldb2
$ sudo chown postfix /etc/sasldb2

Edited SASL config file /etc/postfix/sasl/smtpd.conf

pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM
log_level: 7

Enable saslauthd in /etc/default/saslauthd

# This needs to be uncommented before saslauthd will be run automatically
START=yes

PWDIR="/var/spool/postfix/var/run/saslauthd"
PARAMS="-m ${PWDIR}"
PIDFILE="${PWDIR}/saslauthd.pid"

MECHANISMS="sasldb"

# for chrooted postfix services
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -r"
# Some more changes / hacks I found to get things working
$ sudo dpkg-statoverride --force --update --add root sasl 755 /var/spool/postfix/var/run/saslauthd
$ sudo ln -s /etc/default/saslauthd /etc/saslauthd
$ sudo service saslauthd start

# Test sasl auth
$ sudo testsaslauthd -u recipient1 -r example.com -p <password> -f /var/spool/postfix/var/run/saslauthd/mux

SASL authentication is PLAIN text. Next, I setup TLS encryption to avoid snooping.

TLS Encryption #

Postfix comes with self-signed certificates to use for TLS Encryption. I even tried with my own generated self-signed certificates. But I found out the hard way, that Gmail started enforcing strict email security starting around April 2020. Fortunately, Let's Encrypt makes it easy and free to get a properly CA signed certificate. I used the following guide for this setup.

πŸ‘ How to secure Postfix using Let’s Encrypt

# Installs certbot to manage generating keys and
# interacting with Let's Encrypt via their ACME process
$ sudo apt install certbot

# Runs certbot in standalone mode since we don't have a web server.
# Ensure Port 80 is open though since certbot uses a temporary web server during the process.
$ sudo certbot certonly --standalone -d mail.example.com

E-mail Relay #

Next, I configure Postfix to enable email relay for authenticated users by editing /etc/postfix/master.cf.

smtp       inet n       -       y       -       -       smtpd

submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=may
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_local_domain=$mydomain
-o smtpd_tls_auth_only=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING

Some of the above TLS settings seemed to be overridden by defaults in main.cf. It's not obvious the right way to avoid repeating this info.

# Adds the location of letsencrypt certificate and private key
$ sudo postconf -e smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.com/fullchain.pem
$ sudo postconf -e smtpd_tls_key_fie=/etc/letsencrypt/live/mail.example.com/privkey.pem

$ sudo postfix reload

Verify TLS Setup #

I used a random website I found www.checktls.com to validate my setup.

To validate the actual TLS authentication, I used OpenSSL.

# Generate base64 encoded text of username and password
$ echo -ne '\000recipient1\000secret' | openssl base64
AHJlY2lwaWVudDEAc2VjcmV0

# Connect to SMTP server over a TLS encrypted connection
$ openssl s_client -connect mail.example.com:587 -starttls smtp
# lots of output
# Use EHLO to check if server supports auth
EHLO localhost

250-mail.example.com
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-AUTH PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING

# Using the supported AUTH PLAIN method with base64 credentials
AUTH PLAIN AHJlY2lwaWVudDEAc2VjcmV0

235 2.7.0 Authentication successful

# Yay! Authentication successful. Time to quit.
quit

221 2.0.0 Bye
closed

References #

Some references I used when debugging my setup

πŸ™πŸ™πŸ™

Since you've made it this far, sharing this article on your favorite social media network would be highly appreciated πŸ’–! For feedback, please ping me on Twitter.

Published