MTA & Relay w/ Exim4

[UPDATE: Please use the Wiki post for this tutorial only as the images for this entry were lost (rather too tedious to relink)]

First off, a big thanks to jason an geoff for helping me get this banged out – it was painful and tiring, but I got it working – and even better, I broke it four times and rebuilt it. Anyway, here \ is how to set up a send-only MTA that duals as a relay for other servers, including TLS configuration. First, download and install the packages and run the configuration tool:

sudo apt install exim4 mailutils
sudo dpkg-reconfigure exim4-config

On the ncurses screen that follows, select internet site; mail is sent and received directly using SMTP

On the next screen, put in your fully qualified domain name (FQDN) as follows:

The next screen is asking you for the addresses you want this instance of exim to listen from. In my case, I did not want to listen to any external connections – only to this server itself, the localhost, and on both ip4 and ip6. This is also the default, and so my configuration looks like:

On the next screen, don’t get confused like I did. The question is “for which [DNS entry should] this machine should consider itself the final destination” and the answer is the DNS entry you have pointing to your relay server, or in my case

The next screen is equally confusing and you might be tempted to enter the domains you intend to relay email for in this parameter field, but do not. Leaving this blank means that your server will not be considered a “fallback MX or mail gateway” for any other server’s email:

The next screen is where you can enter the domains you authorize to relay email through your server as follows. Note that it clearly states “Machines to relay email for” on this parameter. I permitted two of the external servers I manage as follows:

In the next screen, you are prompted about whether you would like to enable normal mode or a mode that is more suited towards dial-up connections. Unless you are actually using dial-up still, leave this parameter at its default of no:

The next field is for the location of the mailbox. I left it at the default:

The next field has huge ramifications for configuring exim4, especially if you intend to configure a different instance as a full mail server (MTA and IMAP). In my case, I wanted to keep things simple and use this as a workhorse relay for other servers that I curate where the IP and DNS do not permit direct sending of email. For those reasons, I left this at its default of no:

The next screen asks for the postmaster. However, simply adding an email address here will not work. Setting up a postmaster with a smarthost relay requires a special configuration which I am still working on. For now, I left this blank:

Okay, now we just need to verify your primary exim configuration file. You will notice that I removed the commas and horizontal list because, in cases where the relay will function for many different domains, it is not feasible to keep this in a gigantic horizontal array.

sudo nano /etc/exim4/update-exim4.conf.conf


There are some other configurations necessary as well. There is the default configuration for exim4 and it needs to be revised as well. You need to adjust the last line to specify which ports this relay should listen on – exim’s directions tell you this right above the entry:

sudo nano /etc/default/exim4

The relay should function now, and should be listening on ports 25, 587, and 10025. You should probably restart the services and/or reboot the machine. In my case, however, I wanted to use port 587 with TLS enabled, so I did a bit more first. First, the auto-generated configuration file did not include a parameter enabling TLS. More importantly, every time I added it manually and restarted the service, it disappeared:

sudo nano /var/lib/exim4/config.autogenerated
sudo systemctl restart exim4

This is because it is autogenerated. And thanks to jason again for digging through resources at /usr/share/doc/exim4-base/README.Debian.gz in order to figure this out. The solution is to create a file called exim4.conf.localmacros inside /etc/exim4/ which will be consulted when the service is restarted and then accordingly populate the auto-generated configuration above. Here is how I did that:

sudo nano /etc/exim4/exim4.conf.localmacros
sudo systemctl restart exim4

Now that this is done, you should open up the auto-generated configuration and see a new entry:

Notice the MAIN_TLS_ENABLE = yes line is added and will this time, survive a service restart because of the localmacros file created above. Next, it is time to symlink your TLS certificate and keypair to the default location for exim4. In my case, I already had Let’s Encrypt set up on this server for my primary domain, so I just used that pair as follows (proceed with caution):

cd /etc/exim4
sudo -i
ln -s ../letsencrypt/live/ exim.crt
ln -s ../letsencrypt/live/ exim.key

When this is done, you will need to adjust the group owner and permissions on the certificate and key directories to allow the Debian-exim group to access these keys. Otherwise they will not be accessible. I think the following permissions should be safe and yet also permissible enough for your TLS-enabled services to function, but I welcome feedback (as always) if you think I got it wrong:

sudo -i
chown root:Debian-exim -R /etc/letsencrypt/live/
chown root:Debian-exim -R /etc/letsencrypt/archive/
chmod 0755 -R /etc/letsencrypt/live/
chmod 0755 -R /etc/letsencrypt/archive/

Try not to mess up on the symlinks and make sure you are using relative paths as I did above, and if you mess up, add the -sf flag to fix them or purge certbot and start over. Be careful here and best to run as root instead of using sudo so you can use tab completion. Once this is done, you should have some standard output like this:

Okay, it is now time to verify that your TLS is functioning correctly. If you are using a firewall, make sure to open up ports 25, 587, and 10025. Here is how I verified my relay’s TLS functionality using swaks. You can also nc and/or telnet:

swaks -a -tls -q HELO -s -au test -ap '<>'

In full disclosure, I am still debugging this on the testing host, but once it is working, the swaks output will look like my functioning relay. ;0

Okay, now that you have everything set up on the relay server, we need to set up an exim4 client to test and send an email to it with. First, install exim4 on the client and begin the setup for “mail sent by smarthost; no local mail”

sudo apt install exim4 mailutils

The next screen allows you to choose the name of the client machine – I stuck with the name of the host which it auto-populated for me:

The next screen asks you to specify where exim4 should listen. Again, you want it to listen on localhost since you are not (even more so in this case), listening to any external services:

Likewise, on the next screen you are also not accepting incoming connections to the client machine, so leave the next parameter empty as well indicating that you will not accept any connections besides localhost:

The next screen allows you to specify a name by which this client can identify itself to those servers it makes connections with – again, I left this as the default hostname:

The next screen – finally – is where you input the server name and port for the relay server you set up above. Since I have TLS activated on port 587 for my relay, I additionally specified that port, although I do allow connections from the others for other client workstations:

Again, unless you are using dial-up, say no on the next screen:

Unless you have a need to or the knowledge of why, leave the configuration as standalone:

Okay, restart the exim4 service for good measure and send a test email. First, let’s run a tail on the exim4 log on the relay server in case we need to debug or this test fails:

sudo tail -f /var/log/exim4/mainlog

With the log running on the relay server, let’s send a test email from the client workstation as follows :

sudo systemctl restart exim4
echo "Hi Relay Server, I am testing you" | mail -s "Subject - Test"

If everything was successful, you should get some log output like this:

Okay! Happy Hacking!

Leave a Reply

Your email address will not be published. Required fields are marked *

JavaScript licenses