Deploying the eFa Spam Filter

So after deciding to use eFa Project I got around to deploying the eFa spam filter in our datacentre.

They provide the option of deploying either as a one line installer or using an ISO image. I’ve had some bad experiences in using premade or self building images, so where possible I prefer to deploy a fresh CentOS box and then install it.

Deploying the OS

Deploying the box was like any other and ensure you meet their minimal system requirements (https://efa-project.org/download/). CentOS 7 minimal installer, 2xCPU cores, 8GB RAM and 100GB disk space as per the system requirements.

The only difference being since it’s a 100GB disk I had to manually choose and select partitions to make one big directory. Otherwise CentOS deploys 40GB of the storage to the home directory – not useful if there’s no users!

Installing eFa

Once the OS is deployed then enable root SSH and install all pending updates. No need to set hostname, static IP’s or anything as eFa runs through all that for you (typically found out after doing it all…). It will also install all the pre-requirements for you.

Run the install script as per their documentation https://efa-project.org/download/ and follow the prompts. It’s all relatively obvious and easy to follow.

After rebooting log back to the box with the new credentials made. This will load the EFA Configuration with multiple choice options.

Configuring eFa

From here you can control nearly everything depending on your preferences and it’s recommended going through each option one by one and tweak what you need.

Option 7 / Mail Settings is where to add both inbound domains (Transport Settings / Option 4) and public IP’s (Outbound Mail Relay / Option 1) to relay through it. Mail relay is annoying and a major module I rewrote.

Settings are controlled via SSH/EFA Configure options but seeing email traffic, releasing, whitelisting and user creations are done via the WebUI.

Things to check/note after deployment

Root Password Change

Root password gets reset when EFA config runs. Whilst this is secure I don’t like having an unknown root password.

sudo passwd root

Running EFA Configure from Shell

From Shell it’s annoying getting back into EFA config… As root or as newly created user going into Shell from Option 1. So a simple “EFA” alias works nicely.
Modify the .bashrc file and add the below:

alias EFA='sudo /usr/sbin/eFa-Configure'

Maxmind Geolite2

IP lookups now need a MaxMind Geolite2 Key. Simple to create and add into EFA. Create account and get key: https://support.maxmind.com/account-faq/license-keys/how-do-i-generate-a-license-key/
Then Option 6 > Option 5 and paste in the key.


Configure LetsEncrypt

Seems obvious but you should always be using HTTPS to access everything and it comes with it’s own LetsEncrypt config which makes life simple. You will still need to port forward port 80 as well as 443 for it to work. Pick option 15 and follow the on-screen prompts for the certificate to generate and load.
You will then need to go to Apache Settings / Option 10 and configure HTTPS to make sure that HTTP content is redirected to HTTPS.


Disable mail scanned signature

Nothing more annoying than having EFA tag “this message has been scanned by EFA” to the bottom of all your emails. This can be disabled by going to Spam Settings / Option 8 and then Non-Spam Settings / Option 1.


Add Release links for quarantine notifications

When a user is created on the WebUI and daily quarantine notifications turned on they will just get sent a link with what’s been blocked and a link to view it. For emails users know they’re waiting for they normally just want to release it at the click of a button without having to login and then release it.

This can be enabled by editing /var/www/html/mailscanner/conf.php and setting the AUTO_RELEASE to true:

// Quarantine Auto Release
// Set true to allow auto release of quarantined items from quarantine report.
define('AUTO_RELEASE', true);

Searching for missing emails

Emails rejected by an RBL don’t show in the WebUI as they’re rejected prior to confirmation of delivery. There are options to disable this but it massively reduces load on the spam filter (our SpamTitan deployment had a ~70% rejection on RBL’s alone!) so really isn’t worth doing for the odd occurance. Plus it will show as rejected from the sender’s end anyway.

Really simple to search for them from Shell:

cat /var/log/maillog | grep "domain or IP"

Adding a DNS entry

One annoying thing about the filter is that it handles it’s own DNS entries (if recursive DNS is turned on, which it should be). Sometimes you may find that emails are rejected as they’re being sent from a domain that doesn’t exist. So for instance if you have an internal CRM system that sends from [email protected]. If crm.domain.com doesn’t publically exist then EFA will reject it since the domain doesn’t exist.

Obviously a DNS record should be created to stop this, but if the email is coming from a third party then sometimes it’s quicker to fix it at your end than persuade them it’s needed or disable the valuable spam check. Normally you’d add the entry to the hosts file but with recursive DNS this doesn’t work and therefore needs to be added to the Unbound DNS config.

Modify /etc/unbound/unbound.conf and find the local-data line.
Needs to be in the below format:

	# You can add locally served data with
        # local-zone: "local." static
        # local-data: "mycomputer.local. IN A 192.0.2.51"
        # local-data: 'mytext.local TXT "content of text record"'

local-data: "314742.cloudwaysapps.com. IN A 8.8.8.8"

Then reload Unbound with the below command

unbound-control reload

I believe this can also be used to create MX routes BUT you may as well just create it in the transport settings and control it like all the others.


Customising eFa for further changes

See the following post about full customisations on eFa: https://www.robachicken.co.uk/customising-the-efa-spam-filter/