OpenDKIM-OpenDMARC and a Chrooted Postfix Instance

No Postfix installation is complete without OpenDKIM and OpenDMARC.

While some people go for all-in-one solutions that does all of these for them with a single command or two (and then cry to their gods as soon as the system fails as they have no idea how to debug it), the rest of us rather to be our own boss and set things up manually and carefully based on our needs, so we can troubleshoot it if when things go wrong.

This however, is easier to be said than done. In this post, rather than trying to explain what they are and how they can be set up (which can be found everywhere on the web), I am mainly going to address the issues that you might encounter when running your Postfix and these Milters on the same system running Ubuntu.

Background

OpenDKIM and OpenDMARC are designed to be used as Milters. They are two different programs for two different -and yet related- tasks.

They show a lot of similarities in their configuration files and both suffer from the same limitations when running along with a chrooted Postfix instance.

While in a recent enough version of Postfix, daemons are not being chrooted by default anymore, Debian/Ubuntu Postfix package is an exception and still chroots most of Postfix daemons.

This is great for security but raises compatibility issues.

Overview of the issues

Unix Socket Location

Like any other Milter program, you have the option of running the socket over TCP or Unix.

As a rule of thumb, we should always use Unix sockets and only fallback to TCP if we have to (e.g, running them on another server).

Since Postfix’ smtpd daemon is being run chrooted however, it can not access the Milters Unix sockets.

Compatibility with systemd

While in theory, we should be able to change the default location of the Unix sockets via the programs respective config files, as of writing this, it does not work as expected due to some inconsistencies in their Debian installation packages.

These packages were originally written to run in an init environment. But their package’s so called control data (specially postinst), are supposed to do the conversion and make them compatible with systemd.

They however do a lousy job doing so. They end up deleting /etc/default/open{dkim,dmarc} files on a clean system and overriding any Unix socket configuration settings by passing a hardcoded location to the applications via command line parameter. The funny thing is that the deleted files are still listed in dpkg --listfiles open{dkim,dmarc} which made it easy to debug!

Unix Sockets permissions

Even if the sockets were somehow placed in the right place inside the Postfix chrooted directory, Postfix still wouldn’t be able to access them as these sockets have also permission restrictions.

The solution

Well, you could just use a TCP socket and get it over with. This is pretty much what most admins do.

That however wasn’t good enough for me so I decided to develop my own solution.

After much considerations, I came to this multi step non-aggressive solution that would enable Postfix to connect to the Unix sockets of the said services without sacrificing anything.

1. Fix broken systemd units

As much as i dislike systemd, it comes with a solution to override units settings without touching the package files. Create a file named override.conf in these paths:

/etc/systemd/system/opendkim.service.d/
/etc/systemd/system/opendmarc.service.d/

The contents of the opendkim override file is as follows (adjust it accordingly for opendmarc)

[Service]
ExecStart=
ExecStart=/usr/sbin/opendkim -P /var/run/opendkim/opendkim.pid

And then reload systemd manager configuration:
systemctl daemon-reload

This would effectively override the hardcoded Unix socket path provided in the original packages.

2. Create an accessible path for the Unix sockets

We have to put the sockets to the place where chrooted Postfix as well as open{dkim,dmarc} daemons can access them.

cd /var/spool/postfix/
mkdir open{dkim,dmarc}
chown postfix:opendkim opendkim
chown postfix:opendmarc opendmarc/

3. Add Postfix to open{dkim,dmarc} group

This is required so the Postfix would be able to access the sockets without making them world accessible.

adduser postfix opendkim
adduser postfix opendmarc

4. Edit the Milters configuration files

Now you can start editing /etc/open{dkim,dmarc}.conf files.

This is an example of the added lines in opendkim.conf:

# An override file placed in /etc/systemd/system/opendkim.service.d/override.conf
# was needed for this to work
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

# Postfix is added in opendkim group so access could be limited by umask
UMask			007

You can now restart the services and verify the Unix sockets path:

systemctl restart open{dkim,dmarc}.service
ls /var/spool/postfix/open{dkim,dmarc}/

Configure Postfix

Postfix configuration file for the default instance, is located in /etc/postfix/main.cf. Edit that file so it would start using the Milters:

# Setting up milters
smtpd_milters =
  unix:opendkim/opendkim.sock
  unix:opendmarc/opendmarc.sock

# It might not make much sense running opendmarc on non_smtps_milters
non_smtpd_milters =
  unix:opendkim/opendkim.sock

And then reload the instance:
postfix reload

Related

comments powered by Disqus