Bayesian filters and pattern matching and RBLs are all part of the fight against spam. This setup is intended to augment rather than replace those.
Note that I'm NOT greylisting. Greylisting is great in theory but in practice it's extremely annoying to your users. Some people have great success with it. I'm not one of those people.
What I've done is setup a number of email addresses (I have around 10,000 but you can make do with a couple hundred) to act as spamtraps. Lists of these addresses are discretely linked off various high traffic sites where bots will find them but people won't. These addresses are harvested, sold to spammers, and now I know where spam is going to come in.
Postfix is configured to redirect messages to any of these addresses to my spamtrap script, which adds them to a table in PF so that any further messages from that client end up in my tarpit.
The advantages:
Zero false-positive rate (or as close as you can get, at least)
Resource-cheap
Blocks spammers at the firewall layer after their first infraction
Self-healing (trapped addresses expire after 24 hours)
The disadvantages:
Not plug-and-play
Quite a few moving parts
HOW?
Your mail server must be able to run PF and spamd. As far as I know, this means OpenBSD or FreeBSD. I'm sure these instructions can be adapted to flavors of Linux and their firewalls, but that's beyond the scope of my answer.
I've written this for FreeBSD. OpenBSD users should be able to adapt these steps mostly by changing paths.
Create /usr/local/etc/spamd/local-whitelist.txt. PF will read this file to generate the <local-whitelist> table. I recommend referencing http://www.greylisting.org/whitelisting.shtml for addresses that should never be tarpitted. An example file:
Create /usr/local/etc/spamd/spamd.conf. I recommend using the nixspam and ualbert.ca lists as well, but at the least you need the spamtrapped and override lists. (NOTE: I know override is redundant with PF's rdr rules - I move things around enough that I want this double-protection):
all:uatraps:override:nixspam:override:spamtrapped:override:
# University of Alberta greytrap hits.
# Addresses stay in it for 24 hours from time they misbehave.
uatraps:\
:black:\
:msg="Your address %A has sent mail to a ualberta.ca spamtrap\n\
within the last 24 hours":\
:method=http:\
:file=www.openbsd.org/spamd/traplist.gz:
# 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:
# Trapped IPs - so we can block them without using greylisting
spamtrapped:\
:black:\
:msg="Your address %A has sent mail to spamtrap on this server\n\
within the last 24 hours":\
:method=exec:\
:file=/usr/local/scripts/get-spamtrapped:
override:\
:white:\
:method=file:\
:file=/usr/local/etc/spamd/local-whitelist.txt:
Set spamd to run on bootup. Note that you're not running in blacklist-only mode and you are throwing 5xx errors when someone tries to send to a blacklist. The former is so spamdb will handle storing/expiring trapped addresses. The latter is good manners. Add to /etc/rc.conf:
obspamd_enable="YES"
obspamd_flags="-5"
Start spamd: /usr/local/etc/rc.d/obspamd start
Cronjob to run spamd-setup in blacklist-only mode once an hour. Blacklist mode forces it to update the <spamd> pf table rather than spamd's internal tables. Since spamd is just tarpitting and storing data, everything else needs to be in PF. (replace XX with whatever minute of the hour you want it to run)
# spamd-setup
XX * * * * root /usr/local/sbin/spamd-setup -b
Create a spamtrap user on your machine. I give him a home directory for future extensions:
#!/usr/local/bin/bash
# rudimentary checking - more complex checking will be done by
# the pfctl and spamdb commands
ADDRESS=${1%%[!0-9.]*}
if [[ ! ${#ADDRESS} = ${#1} ]]
then
echo "Invalid characters in IP address"
exit 1
fi
if [ ! ${ADDRESS} ]
then
echo "Usage: $0 <address>"
exit 1
fi
/usr/local/sbin/spamdb -t -a ${ADDRESS}
if [ "$?" -ne 0 ]
then
echo "Failed to add ${ADDRESS} to spamdb"
exit 1
fi
/sbin/pfctl -qt spamd -T add ${ADDRESS}
if [ "$?" -ne 0 ]
then
echo "Failed to add ${ADDRESS} to pf"
exit 1
fi
/usr/bin/logger -t spamtrap "Spamtrap caught ${ADDRESS}"
Configure a new transport service in Postfix's /usr/local/etc/postfix/master.cf. The X flag tells Postfix to consider this final delivery for the message so the spammer gets a success message. Note the user - it needs sudo access to the script.
# Spamtrap
spamtrapper unix - n n - - pipe
flags=X user=nobody argv=/usr/local/bin/sudo /usr/local/scripts/spamtrap ${client_address}
Add to sudoers:
nobody ALL= NOPASSWD: /usr/local/scripts/spamtrap
Create a transport rule that sends all messages sent to spamtrap@localhost to the spamtrapper service. See 'postconf transport_maps' for which file to edit. The default is /usr/local/etc/postfix/transport:
spamtrap@localhost spamtrapper
Restart postfix. Send a couple messages to spamtrap@localhost and verify that the sending client is loaded into spamdb and into the <spamd> pf table.
Two things need to happen for each of your spamtrapped email addresses. First, it must resolve to an actual mailbox so it's not rejected during the SMTP dialog. I used virtual users aliased to spamtrap@localhost. Second, it needs to match a check_recipient_access rule in Postfix and get redirected to spamtrap@localhost so legit users included in the recipient list never have to see it. How I did this part:
At this point, all clients sending mail to your spamtrap addresses should be added to spamdb and <spamd>. Nothing is yet being sent to spamd. To make the whole blocking mechanism live, add to /etc/pf.conf and reload pf:
no rdr proto tcp from <local-whitelist> to port 25
rdr pass proto tcp from <spamd> to port 25 -> 127.0.0.1 port 8025
And that's it.
POSSIBLE EXTENSIONS
It'd be trivial to modify the spamtrap script to store a copy of the message in a Bayesian spam corpus.
If you subscribe to any RBL rsync services, it's trivial to offload the bouncing of those message to spamd.
Well ok, looks like you're done with your own answer. Just don't blame postfix-policyd, it's much more flexible than you might think of as it provides several mechanisms for your fight against spam:
Policyd is an anti-spam plugin for Postfix (MySQL based) that
does Greylisting, Sender-(envelope or SASL)-based throttling
(on messages and / or volume per defined time unit), Spamtrap
monitoring / blacklisting and HELO auto blacklisting.
You don't need to use all that waepons and you would probably have some more rules setup in your smtpd_recipient_restrictions.
Anyway, give it a try (and read the docs) or build up your own solution - it's up to you.
Look for the smtpd_recipient_restrictions block, and put the corresponding rule before your network checks (less load), but after the authenticated users. E.g.:
Of course you need to reload postfix now, so your changes take effect. Depending on your distribution, this is done by either service postfix reload, /etc/init.d/postfix reload, or a similar command.
Step 4: Now keep those spammers out
This is an optional step you might wish to consider: Use Fail2ban, and have it watching your mail log file. As soon as someone addresses a spamtrap, have that IP banned (e.g. for 30 minutes, or maybe 1 hour – don't make it too long, as the spammer might use a dynamic IP which becomes "innocent" soon).
OVERVIEW
Bayesian filters and pattern matching and RBLs are all part of the fight against spam. This setup is intended to augment rather than replace those.
Note that I'm NOT greylisting. Greylisting is great in theory but in practice it's extremely annoying to your users. Some people have great success with it. I'm not one of those people.
What I've done is setup a number of email addresses (I have around 10,000 but you can make do with a couple hundred) to act as spamtraps. Lists of these addresses are discretely linked off various high traffic sites where bots will find them but people won't. These addresses are harvested, sold to spammers, and now I know where spam is going to come in.
Postfix is configured to redirect messages to any of these addresses to my spamtrap script, which adds them to a table in PF so that any further messages from that client end up in my tarpit.
The advantages:
The disadvantages:
HOW?
Your mail server must be able to run PF and spamd. As far as I know, this means OpenBSD or FreeBSD. I'm sure these instructions can be adapted to flavors of Linux and their firewalls, but that's beyond the scope of my answer.
I've written this for FreeBSD. OpenBSD users should be able to adapt these steps mostly by changing paths.
Finally, this is all for Postfix 2.5+
Reload PF
Create /usr/local/scripts/get-spamtrapped:
Start spamd: /usr/local/etc/rc.d/obspamd start
Cronjob to run spamd-setup in blacklist-only mode once an hour. Blacklist mode forces it to update the <spamd> pf table rather than spamd's internal tables. Since spamd is just tarpitting and storing data, everything else needs to be in PF. (replace XX with whatever minute of the hour you want it to run)
Two things need to happen for each of your spamtrapped email addresses. First, it must resolve to an actual mailbox so it's not rejected during the SMTP dialog. I used virtual users aliased to spamtrap@localhost. Second, it needs to match a check_recipient_access rule in Postfix and get redirected to spamtrap@localhost so legit users included in the recipient list never have to see it. How I did this part:
At this point, all clients sending mail to your spamtrap addresses should be added to spamdb and <spamd>. Nothing is yet being sent to spamd. To make the whole blocking mechanism live, add to /etc/pf.conf and reload pf:
And that's it.
POSSIBLE EXTENSIONS
It'd be trivial to modify the spamtrap script to store a copy of the message in a Bayesian spam corpus.
If you subscribe to any RBL rsync services, it's trivial to offload the bouncing of those message to spamd.
Well ok, looks like you're done with your own answer. Just don't blame postfix-policyd, it's much more flexible than you might think of as it provides several mechanisms for your fight against spam:
You don't need to use all that waepons and you would probably have some more rules setup in your
smtpd_recipient_restrictions
.Anyway, give it a try (and read the docs) or build up your own solution - it's up to you.
The solution presented by OP is rather complex. I've used an easier approach:
Step 1: Setup a filter file
/etc/postfix/spamtraps
This is just an easy "match list": a regular expression (for the spamtrap) with an action to apply when met:
Adjust with your addresses.
Step 2: Setup the rules in
/etc/postfix/main.cf
Look for the
smtpd_recipient_restrictions
block, and put the corresponding rule before your network checks (less load), but after the authenticated users. E.g.:Step 3: Reload the daemon
Of course you need to reload postfix now, so your changes take effect. Depending on your distribution, this is done by either
service postfix reload
,/etc/init.d/postfix reload
, or a similar command.Step 4: Now keep those spammers out
This is an optional step you might wish to consider: Use Fail2ban, and have it watching your mail log file. As soon as someone addresses a spamtrap, have that IP banned (e.g. for 30 minutes, or maybe 1 hour – don't make it too long, as the spammer might use a dynamic IP which becomes "innocent" soon).
just a quick hint: use postfix-policyd, examples are included in config...
set it up as a policy service in your
smtpd_recipient_restrictions
in your main.cf, ie:works like a charm spamtraping together with greylisting enabled. Good Luck!
if anyone needs a sample Script to Step 4, here we go...