Adding Spam Protection to Postfix

If you’ve followed my first tutorial, you already have a fully functional email server.  Unfortunately, where there is email, there is also spam.  We can easily add some protection against unwanted messages using some tools in Postfix as well as adding SpamAssassin, SPF checking and optionally, greylisting.

First lets install SpamAssassin: [1]

apt-get install spamassassin spamc libmail-dkim-perl

Now lets add a new user for SpamAssassin, and create a few directories for it to use:

groupadd spamd
useradd -g spamd -s /bin/false -d /var/log/spamassassin spamd
mkdir /var/log/spamassassin
chown spamd:spamd /var/log/spamassassin

Now we can configure SpamAssassin:

nano /etc/default/spamassassin

Replace ENABLED=0 with ENABLED=1 and replace CRON=0 with CRON=1.

Next, create a new line:

SAHOME="/var/log/spamassassin/"

Now, find the OPTIONS= line and replace it with:

OPTIONS="--create-prefs --max-children 2 --username spamd -H ${SAHOME} -s ${SAHOME}spamd.log"

Exit nano by pressing CTRL-X and press Y to save your changes.

Now lets configure SpamAssassin’s rules:

nano /etc/spamassassin/local.cf

Edit and uncomment the following lines to look like: [2]

report_safe 0
required_score 3.0
use_bayes 1
bayes_auto_learn 1

Now add the line:

skip_rbl_checks 1

This will stop SpamAssassin from checking blacklist servers, as we will be adding this to Postfix a little later.  There is no point in checking twice as it adds unnecessary extra processing on your server and wastes bandwidth for the blacklist providers.

Exit nano saving your changes.  Now we can (re)start SpamAssissin:

service spamassassin restart

Next we’ll be configuring Postfix to use SpamAssissin:

nano /etc/postfix/master.cf

The first uncommented line should look like:

smtp     inet     n     -     -     -     -     smtpd

Add -o content_filter=spamassassin just below that line, so it looks like:

smtp     inet     n     -     -     -     -     smtpd
  -o content_filter=spamassassin

Notice the space before -o? You need to make sure there is a space between smtpd and the lines you have just added, otherwise Postfix will report an error.

Page down to the bottom of the file and add these lines:

spamassassin     unix     -     n     n     -     -     pipe
  user=spamd argv=/usr/bin/spamc -f -e
  /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Exit nano and save your changes.

Now restart Postfix to apply your changes:

service postfix restart

Now is a good time to stop and test your changes.  Send an outbound email and send an incoming email to your server.  You can check the headers of the messages you send a receive to make sure SpamAssassin is adding headers to you messages.  You can also check the SpamAssassin log file:

nano /var/log/spamassassin/spamd.log

 

Adding DNSBL (Blacklists), Rate Limiting & Other Protection

Next we’re going configure Postfix to check two blacklists before receiving messages, as well as adding some other protection.  We go back to configuring Postfix:

nano /etc/postfix/main.cf

Find the line smtpd_recipient_restrictions and edit it to look like: [3]

smtpd_recipient_restrictions =
  permit_sasl_authenticated,
  reject_invalid_hostname,
  reject_non_fqdn_hostname,
  reject_non_fqdn_sender,
  reject_non_fqdn_recipient,
  reject_unknown_sender_domain,
  reject_unknown_recipient_domain,
  permit_mynetworks,
  reject_unauth_pipelining,
  reject_unauth_destination,
  reject_rbl_client zen.spamhaus.org,
  reject_rbl_client bl.spamcop.net,
  permit

And add the following lines: [4] [5]

disable_vrfy_command = yes
smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_helo_hostname, reject_invalid_helo_hostname
strict_rfc821_envelopes = yes
smtpd_error_sleep_time = 1s
smtpd_soft_error_limit = 10
smtpd_hard_error_limit = 20
smtpd_client_connection_count_limit = 10
smtpd_client_connection_rate_limit = 60

These lines add checks to Postfix, making sure that the hostnames connecting to your mail server actually exist and are valid.  As mentioned before, we have also added in two blacklist checks here.  This prevents sites that have been blacklisted from even sending their messages to your server, saving processing power and bandwidth.

The two blacklists I have selected are the Spamhaus Zen list and Spamcop‘s list.  Spamhaus seems to block the majority of spam and SpamCop blocks most of the rest. If something does make it through, you are able to report these messages to SpamCop and they will be blocked in the future.  Zarafa is configured by default to put any message that is marked as spam in the Junk E-Mail folder.

We’ve also added rate limiting here, so that spamming mail servers don’t flood your server with connections.

Blacklists are a great and effective way of blocking a large amount of spam.  Occasionally a legitimate email server can find itself added to blacklist, this can happen for a variety of reasons.  You can request to be added to a whitelist which can help this problem.  You can also create your own whitelist with servers you know you can trust.

To create our own whitelist: [6]

nano /etc/postfix/rbl_override

Add the IP addresses or hostnames of mail servers you trust:

1.2.3.4 OK
5.6.7.8 OK
mail.importantclient.com OK

Exit and save your changes. Now run: (You will also need to run this command each time you modify this file)

postmap /etc/postfix/rbl_override

Now we tell Postfix to use this whitelist:

nano /etc/postfix/main.cf

We will need to add the line check_client_access hash:/etc/postfix/rbl_override to smtpd_recipient_restrictions after reject_unauth_destination and just before the blacklist checks:

smtpd_recipient_restrictions =
  [...]
  reject_unauth_destination,
  check_client_access hash:/etc/postfix/rbl_override,
  reject_rbl_client zen.spamhaus.org,
  reject_rbl_client bl.spamcop.net,
  permit

After any change we make in Postfix, we need to reload to apply our changes:

service postfix reload

 

Adding SPF (Sender Policy Framework) Checking

Next we will add SPF (Sender Policy Framework) checking to Postfix: [7]

apt-get install postfix-policyd-spf-python

Back to editing main.cf:

nano /etc/postfix/main.cf

Add this line:

policy-spf_time_limit = 3600s

Now add check_policy_service unix:private/policy-spf to smtpd_recipient_restrictions just before the whitelist line we just added:

smtpd_recipient_restrictions =
  [...]
  reject_unauth_destination,
  check_policy_service unix:private/policy-spf,
  check_client_access hash:/etc/postfix/rbl_override,
  reject_rbl_client zen.spamhaus.org,
  reject_rbl_client bl.spamcop.net,
  permit

Next we edit /etc/postfix/master.cf:

nano /etc/postfix/master.cf

Add this section to the bottom of the file:

policy-spf  unix  -       n       n       -       -       spawn
  user=nobody argv=/usr/bin/policyd-spf

And reload Postfix:

service postfix reload

We can test to make sure SPF checking is working by using the Wormly SMTP Server Test. Try sending a test message to your server, but use example@example.com as the sender email. You should see your server reject the message as Wormly is not authorized to send email messages on behalf of example.com.

You should make sure you have a valid SPF record for your domain in your DNS server. If you are just using your new Digital Ocean VPS, your SPF record could be as simple as "v=spf1 mx ~all". This will help prevent spammers from spoofing messages using your domain name.  For more information on creating a SPF record, visit SPF Wizard.  For more information on SPF in general, visit OpenSPF.

 

[Optional] Greylisting with postgrey

We already have blacklists and whitelists, why not add one more list into the mix?

A greylist works by delaying mail from untrusted servers.  If the sending mail server is standards-compliant, it will try resending the message, and then the server will accept it. Spam mailers do not typically try resending a message, and so the spam is blocked. Servers that do try resending mail will be added to postgrey’s white list, and will not be delayed in future. In other words, the first message from any given sender will be delayed, but subsequent ones will not.

This approach may not be appropriate for everyone. If you need to receive messages in a timely manner, you may not want to install postgrey.  I have come across certain servers that only retry sending messages every four hours.  Servers you have added to your own whitelist listed above will not be greylisted.

First we need to install postgrey: [8]

apt-get install postgrey

The default wait time for postgrey is 5 minutes, lets bring that down to one:

nano /etc/default/postgrey

Add --delay=60 to the end of POSTGREY_OPTS=:

POSTGREY_OPTS="--inet=10023 --delay=60"

Now to add postgrey to Postfix, we edit main.cf:

nano /etc/postfix/main.cf

Add the line check_policy_service inet:127.0.0.1:10023 to smtpd_recipient_restrictions just before permit:

smtpd_recipient_restrictions =
  [...]
  reject_unauth_destination,
  check_policy_service unix:private/policy-spf,
  check_client_access hash:/etc/postfix/rbl_override,
  reject_rbl_client zen.spamhaus.org,
  reject_rbl_client bl.spamcop.net,
  check_policy_service inet:127.0.0.1:10023,
  permit

Now restart both postgrey and Postfix:

service postgrey restart
service postfix restart

Head over to the Wormly SMTP Test once again and try to send a test message to your server. The message should fail. Checking the reason on the Wormly page, you should see Greylisted as the reason.  If you wait one or two minutes and then try again, you’ll see that the message will go through.

You can also check your logs:

tail /var/log/mail.log
Jul 10 13:23:53 hostname postgrey[4656]: action=greylist, reason=new, client_name=mail.example.com, client_address=xxx.xx.xxx.xx, sender=user@example.com, recipient=user@example.com
[...]
Jul 10 13:24:30 hostname postgrey[4656]: action=greylist, reason=early-retry (23s missing), client_name=mail.example.com, client_address=xxx.xx.xxx.xx, sender=user@example.com, recipient=user@example.com
[...]
Jul 10 13:24:58 hostname postgrey[4656]: action=pass, reason=triplet found, delay=65, client_name=mail.example.com, client_address=xxx.xx.xxx.xx, sender=user@example.com, recipient=user@example.com

 

And that should do it.  Using this configuration, I receive very little spam in my Junk E-Mail folder.  Those that do manage to make their way through, I promptly report to SpamCop and they usually stop rather quickly.

In my next tutorial we will be adding SSL/TLS protection to the webmail interface, Postfix and the POP/IMAP interfaces.  We will also be adding DKIM signing to outgoing messages.

As always, if you notice any errors, omissions or have anything to add that would make this tutorial better, please let me know in the comments below.

References:
1. https://www.digitalocean.com/community/tutorials/how-to-install-and-setup-spamassassin-on-ubuntu-12-04
2. http://spamassassin.apache.org/full/3.1.x/doc/Mail_SpamAssassin_Conf.html#item_skip_rbl_checks
3. http://www.howtoforge.com/hardening-postfix-for-ispconfig-3
4. http://www.postfix.org/postconf.5.html#disable_vrfy_command
5. http://www.e-rave.nl/rate-limit-incoming-mail-on-postfix
6. http://www.howtoforge.com/how-to-whitelist-hosts-ip-addresses-in-postfix
7. https://help.ubuntu.com/community/Postfix/SPF
8. https://help.ubuntu.com/community/PostfixGreylisting

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s