Fight against spams before receiving one : OpenBSD's spamd

You can sort incoming spams into a Junk folder. But imagine annoying spammers 😁? That's what spamd can do, faking being a mail server and holding spammers so they can't deliver spams while it's talking to them veeery slowly.

How does it work ?

You can let somewhere on the web a fake mail address : a spamtrap. Everyone sending a message to this address will be blacklisted and trapped.

In the meantime, new senders are greylisted. They're told to try again later. Every proper email server will try again. Spammers won't, so you don't get the spam. Others who try again correctly are put on a whitelist.

There is also a blacklist-only mode, trapping IPs from lists you already have.

However, this means senders do things correctly. That's is sadly not always true for commercial senders. This said, it is easy to put a server on a whitelist.

To keep track of good and bad senders, the command "spamd-setup" should be run periodically.

Everything is very well explained in spamd(8) manpage. You must read it since the following are just advices, not a complete howto.

Setup

# rcctl enable spamd
# rcctl set spamd flags "-v -G 25:4:864"
# rcctl start spamd

Also enable spamlogd to keep track of servers already whitelisted and to add to whitelist servers you write to.

# rcctl enable spamlogd
# rcctl start spamlogd

spamd is running in front of smtpd (like a shield, or a janitor 😉). To do so, edit packet-filter configuration : spamd should redirect mails to smtpd if it is not a spam.

Add in /etc/pf.conf :

table <spamd-white> persist
table <nospamd> persist file "/etc/mail/nospamd"
pass in on egress proto tcp to any port smtp divert-to 127.0.0.1 port spamd
pass in on egress proto tcp from <nospamd> to any port smtp
pass in log on egress proto tcp from <spamd-white> to any port smtp

On line order :

Remember to reload pf :

# pfctl -ef /etc/pf.conf

It is necessary to reload spamd blacklist in pf. Edit root's crontab with "# crontab -e" then uncomment the line below :

~  *  *  *  *  /usr/libexec/spamd-setup

With "~", spamd-setup is run at a random schedule 😉.

Spamtrap

Let somewhere on the web fake email addresses : spamtraps. Everyone writing to these addresses is a spammer and will be trapped. It is important thos addresses don't really exist!

To keep these spamtraps for bots only, you can add such html snippets on your website so they are invisible for human eyes :

<a href="mailto:trap@athome.tld"></a>

You can copy it on public pastebins.

To teach spamd what are spamtraps, use the command :

# spamdb -T -a 'trap@athome.tld'

Use pre-existing black/white lists

Some nice people gather IP lists and let everyone download them. To use such lists, edit /etc/mail/spamd.conf.

As example, the default configuration uses :

nixspam's list

Add in /etc/mail/spamd.conf the following lines :

all:\
        :nixspam
# Nixspam recent sources list.
# Mirrored from http://www.heise.de/ix/nixspam
nixspam:\
        :black:\
        :msg="Your address %A is in the nixspam list\n\
        See http://www.heise.de/ix/nixspam/dnsbl_en/ for details":\
        :method=http:\
        :file=www.openbsd.org/spamd/nixspam.gz

At the beginning, you can read "all". Then are written lists you want to use and configured below, separated with ":".

Use an URL to download the list with spamd-setup automatically or a file already on your server.

bsdly's blacklist

Peter N.M.Hansteen publish a blacklist, gathered with its own spamtraps.

Avoid to download it too often or you'll be put on a blacklist. Be king with Peter's bandwidth 😉.

To get the list every hour past 20 minutes :

20 * * * *   /usr/local/sbin/bsdly-spamd

Here is bsdly-spamd script you should copy and make executable :

#!/bin/sh
# update bsdly.net traplist into DST
URL="https://www.bsdly.net/~peter/bsdly.net.traplist"
# alternative URL
#URL="https://home.nuug.no/~peter/bsdly.net.traplist"
DST=/var/db/bsdly.traplist
ftp -o "${DST}" "${URL}"

Then add the new list in /etc/mail/spamd.conf so spamd uses /var/db/bsdly.traplist file :

all:\
      :nixspam:bsdlyblack:
nixspam:\
      :black:\
      :msg="Your address %A is in the nixspam list\n\
      See http://www.heise.de/ix/nixspam/dnsbl_en/ for details":\
      :method=https:\
      :file=www.openbsd.org/spamd/nixspam.gz
bsdlyblack:\
      :black:\
      :msg="SPAM.  Your address %A has sent spam within the last 24 hours.  See http://www.bsdly.net/~peter/traplist.shtml for details.":\
      :method=file:\
      :file=/var/db/bsdly.traplist

uceprotect black and whitelists

See official website.

Below we describe how to periodically download lists provided by uceprotect. We will use rsync to reduce bandwidth usage.

Add a new cronjob to call a script downloading lists. Not too often or you'll be blacklisted.

10 * * * *     /usr/local/sbin/uceprotect-spamd 

/usr/local/sbin/uceprotect-spamd is the script below :

#!/bin/sh
RSYNC="/usr/bin/openrsync -a"
URLS="rsync-mirrors.uceprotect.net::RBLDNSD-ALL/dnsbl-1.uceprotect.net
rsync-mirrors.uceprotect.net::RBLDNSD-ALL/dnsbl-2.uceprotect.net
rsync-mirrors.uceprotect.net::RBLDNSD-ALL/ips.whitelisted.org"
OUT="/var/db/RBLDNSD-ALL/"
mkdir -p "${OUT}"
for URL in ${URLS}; do
      ${RSYNC} "${URL}" "${OUT}"
done

Load the lises in /etc/mail/spamd.conf. There are white and blacklists.

all:\
      :nixspam:bgp-spamd:bsdlyblack:\
      rbldnsd-1:rbldnsd-2:rbldnsd-white:
...
rbldnsd-1:\
      :black:\
      :msg="Your address %A is listed on UCEPROTECT-Level 1\n \
      see http://www.uceprotect.net/en":\
      :method=file:\
      :file=/var/db/RBLDNSD-ALL/dnsbl-1.uceprotect.net
rbldnsd-2:\
      :black:\
      :msg="Your address %A is listed on UCEPROTECT-Level 2\n \
      see http://www.uceprotect.net/en":\
      :method=file:\
      :file=/var/db/RBLDNSD-ALL/dnsbl-2.uceprotect.net
rbldnsd-white:\
      :white:\
      :method=file:\
      :file=/var/db/RBLDNSD-ALL/ips.whitelisted.org

Do not hesitate do donate to uceprotect.net for all their work 😄.

Common issues with greylisting

Some big mail provider uses multiple servers to send mails. If you do greylisting, the IP trying to send an email from a provider might change between two tries. This means spamd can't recognize a legitimate server, never whitelist the IP and you never get the mail.

However, you can whitelists those domains if you want.

Create a file containing domains not to greylist : /etc/mail/nospamd_domains_list.txt :

gmail.com
hotmail.com
facebookmail.com
apple.com
microsoft.com
lists.openbsd.org
linkedin.com
freebsd.org
twitter.com
amazon.com
yahoo.com
yahoo.fr
live.fr
mail-out.ovh.net
mxb.ovh.net
gandi.net
laposte.net
protonmail.com

Add more domains if you need to.

Now create a script to get sending IP of above domains : /usr/local/sbin/generate-nospamd :

#!/bin/sh
# /usr/local/sbin/generate-nospamd
# Auteur :      prx <prx@si3t.ch>
# licence :     MIT
DOMAINS=/etc/mail/nospamd_domains_list.txt
WHITELIST=/etc/mail/nospamd
echo "#$(date)" > "$WHITELIST"
smtpctl spf walk < "${DOMAINS}" >> "$WHITELIST"
exit 0

Call this script daily with /etc/daily.local and reload nospamd table :

# /etc/daily.local
/usr/local/sbin/generate-nospamd
pfctl -t nospamd -T replace -f /etc/mail/nospamd

See spamd activity

Run "spamdb" command to see what's happening :

WHITE|62.4.1.33|||1462699174|1462699174|1465809574|1|0
GREY|182.70.43.24|abts-mum-dynamic-024.43.70.182.airtelbroadband.in|<Estella32@thunderguy.co.uk>|<toto@athome.tld>|1473409924|1473424324|1473424324|1|0
GREY|14.183.132.63|static.vnpt.vn|<Abby5@toddelliott.com>|<kiki@athome.tld>|1473410586|1473424986|1473424986|1|0

Read spamdb(8) manpage to learn what it means.

To translate times in human-readable format, run "date" with -r flag :

$ date -r 1462699174
    Sun May  8 11:19:34 CEST 2016

You can put on whitelist an IP with "spamdb -a" :

# spamdb -a "62.4.1.37"

Share spamd data between backups

Remember to keep spamd databases synchroniszd between your server and backups (secondary MX). Read about -Y and -y flags in spamd manpage.