Greylisting has proven to be a pretty effective method for reducing the amount of spam you receive. It works by temporarily rejecting emails. Valid email servers will then retry delivery, and be allowed through while spammers will (hopefully) give up. See http://www.greylisting.org/ for more info.
The postgrey application at http://postgrey.schweikert.ch/ provides a simple way to implement greylisting for postfix mail servers.
Recently Peter here at RimuHosting went to Samoa for a week (nice for some). He found himself on a 9600 baud internet connection. And there was no way it was keeping up with the 200-odd spam emails that arrived in his inbox each day. After implementing greylisting the spam has dropped down to less than a dozen or so a day.
Debian and Ubuntu have the package available in the main repositories. On CentOS/RHEL based distros, you will need to enable the rpmforge repository per http://rimuhosting.com/knowledgebase/linux/distros/centos/extra-packages-for-rhel4-and-centos5
Then just install postgrey with apt
apt-get install postgrey
Configure postgrey to start at boot:
Debian/Ubuntu:
update-rc.d postgrey defaults
CentOS/RHEL:
chkconfig postgrey on
And tell it to start up (any distro):
/etc/init.d/postgrey start
Now, tell postfix to use it:
Debian/Ubuntu:
The package listens on localhost:10023 by default, so edit /etc/postfix/main.cf, and add 'check_policy_service inet:127.0.0.1:10023' to smtpd_recipient_restrictions. Make sure to add it after permit_sasl_authenticated so you don't greylist authenticated users. Like this:
smtpd_recipient_restrictions =
permit_mynetworks
permit_sasl_authenticated
reject_unauth_destination
check_policy_service inet:127.0.0.1:10023
CentOS/RHEL:
This package listens on a unix socket by default, so edit /etc/postfix/main.cf and add 'check_policy_service unix:/var/spool/postfix/postgrey/socket' to 'smtpd_recipient_restrictions. Again, make sure to add it after permit_sasl_authenticated so as not to greylist yourself. Example:
smtpd_recipient_restrictions =
permit_mynetworks
permit_sasl_authenticated
reject_unauth_destination
check_policy_service unix:/var/spool/postfix/postgrey/socket
You can set it so that only particular users have their emails grey-listed. e.g. in /etc/postfix/main.cf have:
smtpd_restriction_classes = greylist
greylist = check_policy_service inet:127.0.0.1:10023
And add the following to smtpd_recipient_restrictions in /etc/postfix/main.cf:
smtpd_recipient_restrictions =
[other options that normally go here]
check_recipient_access hash:/etc/postfix/greylist_optin
(Note that you would have this set in smtpd_recipient_restrictions instead of the "check_policy_service unix:/var/spool/postfix/postgrey/socket" setting mentioned in the previous section.
In /etc/postfix/greylist_optin put users who should be greylisted followed by 'greylist' (the class defined above):
fred@example.com greylist
mary@example.com greylist
Sending mail to those users should now get greylisted (might need to 'postmap /etc/postfix/greylist_optin' before restarting postfix).
In /etc/postgrey/whitelist_clients you can add domains (domain names, one per line) that you think should not be greylisted. e.g. domains of users that you deal with frequently (maybe avoiding common sources of spam though like yahoo.com, hotmail.com, etc).
The following script will pull ranges from spf records publish at common ESPs
#!/bin/bash
ESPs="google.com amazonses.com hotmail.com facebook.com twitter.com spamhero.com"
VERBOSE='n'
function parsespf(){
SPF=$(dig TXT $1 +short | grep 'v=spf1' | sed 's~" "~~g' | tr -d '"')
[ "$VERBOSE" = "y" ] && echo "#### SPF: $SPF"
for p in $SPF; do
echo $p | grep -q '^v=spf1\|^~all\|^-all\|^?all' && continue
if echo $p | grep -q '^ip4:'; then
[ "$VERBOSE" = "y" ] && echo "$(echo $p | sed 's/^ip4://g') #SPF:$1"
[ "$VERBOSE" = "n" ] && echo "$(echo $p | sed 's/^ip4://g')"
fi
if echo $p | grep -q '^include:\|redirect='; then
[ "$VERBOSE" = "y" ] && echo "#### recursing include or redirect: $p"
parsespf $(echo $p | sed -e 's/^include://g' -e 's/^redirect=//g')
fi
done
}
# We parse the spfs and add them as uniq entries
for e in $ESPs; do
parsespf $e
done | sort -n | uniq
This script can be used to add a list of ips to postgrey as follows:
./whitelistclients.sh >>/etc/postgrey/whitelist_clients