Last update: December 21st, 2006.
This is a fairly complete example configuration for the OpenBSD spamd daemon and PF.
The OpenBSD system is a firewall for a small network, providing Internet access through NAT for the internal systems. Also on the inside are a web server and e-mail server.
Overall, I'm very pleased with spamd so far, it is blocking a lot of spam. We've been running it for about 4 months at the time of writing.
TODO: Also explain the logging needed using pflog and spamdlogd. This is currently covered in other spamd documentation, but should be included here for completeness' sake. I've also updated the whitelist generation... but not actually updated the whitelist on this page.
Please feel to contact me with questions and suggestions at: ansible atsign xnet dotty com.
I did need to tweak the spamd startup in /etc/rc.conf:
spamd_flags="-v -G7:4:864 -r451"
Note, however, that in our setup, the reduced retry time does let through a slight amount of spam, but it was deemed worth it, to reduce the delays for legitimate email.
I've read somewhere that we should really be using 451 as the return code instead of 450 (which is the default for spamd). It is said (from unverified sources) that some mail servers only retry once with 450 (mailbox locked). And that they retry normally with 451. If someone can confirm this, and maybe give an example, that would be great. I have some indications that using 451 does help, but I haven't conclusively tested it.
Spamhaus is now a for-pay service, so it isn't included in 'all'.
You must be aware, however, that what they call the 'whitelists' in the spamd.conf file are more like 'anti-blacklists'. They just take entries off the preceding blacklist. They do not globally, add entries to any whitelist.
If you want a true whitelist, then you have to make it yourself, and make sure you are intercepting that traffic before spamd. See the section on the PF below.
I've deleted a lot of stuff that I wasn't using, so look at the example file provided with OpenBSD to see how to block Korean mail servers, etc.
all:\ :spews1: # Mirrored from http://spfilter.openrbl.org/data/sbl/SBL.cidr.bz2 spamhaus:\ :black:\ :msg="SPAM. Your address %A is in the Spamhaus Block List\n\ See http://www.spamhaus.org/sbl and\ http://www.abuse.net/sbl.phtml?IP=%A for more details":\ :method=http:\ :file=www.openbsd.org/spamd/SBL.cidr.gz: # Mirrored from http://www.spews.org/spews_list_level1.txt spews1:\ :black:\ :msg="SPAM. Your address %A is in the spews level 1 database\n\ See http://www.spews.org/ask.cgi?x=%A for more details":\ :method=http:\ :file=www.openbsd.org/spamd/spews_list_level1.txt.gz: # Mirrored from http://www.spews.org/spews_list_level2.txt spews2:\ :black:\ :msg="SPAM. Your address %A is in the spews level 2 database\n\ See http://www.spews.org/ask.cgi?x=%A for more details":\ :method=http:\ :file=www.openbsd.org/spamd/spews_list_level2.txt.gz:
This is the section that I mainly had problems with during my initial setup.
I've also been informed that some of my filter rules may be redundant, so advice there would be appreciated.
# PF configuration for example.com
# Standard small-office NAT, with e-mail and webserver
# behind the firewall.
# Also added spamd running in greylisting mode.
#####################
# Macros
#####################
# internal and external network interfaces
int_if = "xl0"
ext_if = "rl0"
# internal servers
mail_host = "mail.example.com"
external_web = "www.example.com"
icmp_types = "{ echoreq, unreach }"
# We should never see these coming from the Internet.
martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
0.0.0.0/8, 240.0.0.0/4 }"
# options
set block-policy return
set loginterface $ext_if
# scrub
scrub in all
#######################
# NAT / Redirection
#######################
# NAT the internal network to the Internet.
nat on $ext_if from $int_if:network to any -> ($ext_if)
# FTP
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
rdr on $int_if proto tcp from any to any port ftp -> 127.0.0.1 \
port 8021
# our WWW appears on the Internet
rdr pass on $ext_if proto tcp from any to \
$ext_if port http -> $external_web port http
############
# Spamd
############
# grey host list
table <spamd> persist
# white host lists
table <spamd-white> persist
# This whitelist we are manually maintaining.
table <whitelist> persist file "/etc/whitelist.txt"
# The order of these rules is very, very important.
# send manually whitelisted hosts to the actual mail server
rdr on $ext_if proto tcp from <whitelist> to \
$ext_if port smtp -> $mail_host port smtp
# send all previously seen but still suspect senders the spamd daemon
rdr pass on $ext_if inet proto tcp from <spamd> to \
$ext_if port smtp -> 127.0.0.1 port 8025
# send all unknown senders to the spamd daemon
rdr pass on $ext_if inet proto tcp from !<spamd-white> to \
$ext_if port smtp -> 127.0.0.1 port 8025
# send whitelisted hosts to the actual mail server
rdr on $ext_if proto tcp from <spamd-white> to \
$ext_if port smtp -> $mail_host port smtp
#################
# Filter Rules
#################
block all
set skip on lo0
antispoof for $ext_if
antispoof for $int_if
# Martians
block drop in quick on $ext_if from $martians to any
block drop out quick on $ext_if from any to $martians
# Allow ping and path MTU discovery
pass in inet proto icmp all icmp-type $icmp_types keep state
# FTP
# Is this all that is really needed?
anchor "ftp-proxy/*"
# for spamlogd to update the whitelists
# don't need to log static whitelist
pass in quick on $ext_if inet proto tcp from <whitelist> \
to port smtp flags S/SA keep state
pass in log quick on $ext_if inet proto tcp from <spamd-white> \
to port smtp flags S/SA keep state
pass out log quick on $ext_if inet proto tcp \
to any port smtp flags S/SA keep state
# Allow anything on the internal interface
pass in on $int_if from $int_if:network to any keep state
pass out on $int_if from any to $int_if:network keep state
# Allow anything from the internal network out onto the Internet
pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state
Here's the whitelist I generated. A chunk of that came from this script for listing SPF servers. It would be handy if more people created SPF records (I'm looking at you, Yahoo). Thanks to Jean for some improvements to the script.
#!/bin/sh
FILE=spamd-spf.txt
rm -f $FILE
touch $FILE
for domain in \
aol.com \
apple.com \
amazon.com \
gmx.net \
_spf.google.com \
spf-a.hotmail.com \
spf-b.hotmail.com \
spf-c.hotmail.com \
spf-d.hotmail.com \
_spf-a.microsoft.com \
_spf-b.microsoft.com \
_spf-c.microsoft.com \
mynethost.com
do
echo \#$domain >> $FILE;
dig $domain TXT +short | tr "\ " "\n" | grep ^ip4: | cut -d: -f2 >> $FILE;
done
echo '# http://cvs.puremagic.com/viewcvs/*checkout*/greylisting/schema/whitelist_ip.txt' >> $FILE;
ftp -o - http://cvs.puremagic.com/viewcvs/*checkout*/greylisting/schema/whitelist_ip.txt \
| awk '/^[^#]/ {print $0}' >> $FILE;
Here's the whitelist itself.
12.5.136.141 # Southwest Airlines (unique sender, no retry) 12.5.136.142 # Southwest Airlines (unique sender, no retry) 12.5.136.143 # Southwest Airlines (unique sender, no retry) 12.5.136.144 # Southwest Airlines (unique sender, no retry) 12.107.209.244 # kernel.org mailing lists (high traffic, unique sender per mail) 63.82.37.110 # SLmail 63.169.44.143 # Southwest Airlines (unique sender, no retry) 63.169.44.144 # Southwest Airlines (unique sender, no retry) 64.7.153.18 # sentex.ca (common pool) 64.124.204.39 # moveon.org (unique sender per attempt) 64.125.132.254 # collab.net (unique sender per attempt) #65.82.241.160 # Groupwise? 66.94.237.0/24 # Yahoo Groups servers (common pool, no retry) 66.100.210.82 # Groupwise? 66.135.209.0/24 # Ebay (for time critical alerts) 66.135.197.0/24 # Ebay (common pool) 66.162.216.166 # Groupwise? 66.206.22.82 # PLEXOR 66.206.22.83 # PLEXOR 66.206.22.84 # PLEXOR 66.206.22.85 # PLEXOR 66.218.66.0/24 # Yahoo Groups servers (common pool, no retry) 66.218.67.0/24 # Yahoo Groups servers (common pool, no retry) 66.218.69.0/24 # Yahoo Groups servers (common pool, no retry) #66.249.82 # gmail (common server pool, bad 451 handling) 66.27.51.218 # ljbtc.com (Groupwise) #66.89.73.101 # Groupwise? #68.15.115.88 # Groupwise? 72.14.204.0/24 # qproxy.gmail.com (common server pool, bad 451 handling?) 152.163.225.0/24 # AOL (common pool) 194.245.101.88 # Joker.com (email forwarding server) 195.235.39.19 # Tid InfoMail Exchanger v2.20 195.238.2.0/24 # skynet.be (wierd retry pattern, common pool) 195.238.3.0/24 # skynet.be (wierd retry pattern, common pool) #204.60.8.162 # Groupwise? 204.107.120.10 # Ameritrade (no retry) 205.206.231.0/24 # SecurityFocus.com (unique sender per attempt) 205.211.164.50 # sentex.ca (common pool) 207.115.63.0/24 # Prodigy (broken software that retries continually with no delay) #209.104.63 # Ticketmaster (poor retry config) 209.132.176.174 # sourceware.org mailing lists (high traffic, unique sender per mail) 211.29.132.0/24 # optusnet.com.au (wierd retry pattern and more than 48hrs) 213.136.52.31 # Mysql.com (unique sender) #216.136.226.0 # Yahoo Mail? #216.157.204.5 # Groupwise? 217.158.50.178 # AXKit mailing list (unique sender per attempt) # # #aol.com 152.163.225.0/24 205.188.139.0/24 205.188.144.0/24 205.188.156.0/23 205.188.159.0/24 64.12.136.0/23 64.12.138.0/24 152.163.225.0/24 205.188.139.0/24 205.188.144.0/24 205.188.156.0/23 205.188.159.0/24 64.12.136.0/23 64.12.138.0/24 #amazon.com 207.171.160.0/19 87.238.80.0/21 72.21.196.0/24 72.21.208.0/24 207.171.160.32/28 207.171.180.176/28 207.171.164.32/28 207.171.190.0/28 87.238.80.24/29 87.238.84.24/29 72.21.196.0/24 72.21.208.0/24 #gmx.net 213.165.64.0/23 #_spf.google.com 216.239.56.0/23 64.233.160.0/19 66.249.80.0/20 72.14.192.0/18 #spf-a.hotmail.com 209.240.192.0/19 65.52.0.0/14 131.107.0.0/16 157.54.0.0/15 157.56.0.0/14 157.60.0.0/16 167.220.0.0/16 204.79.135.0/24 204.79.188.0/24 204.79.252.0/24 207.46.0.0/16 199.2.137.0/24 #spf-b.hotmail.com 199.103.90.0/23 204.182.144.0/24 204.255.244.0/23 206.138.168.0/21 64.4.0.0/18 65.54.128.0/17 207.68.128.0/18 207.68.192.0/20 207.82.250.0/23 207.82.252.0/23 209.1.112.0/23 #spf-c.hotmail.com 209.185.128.0/23 209.185.130.0/23 209.185.240.0/22 216.32.180.0/22 216.32.240.0/22 216.33.148.0/22 216.33.151.0/24 216.33.236.0/22 216.33.240.0/22 216.200.206.0/24 204.95.96.0/20 #spf-d.hotmail.com 65.59.232.0/23 65.59.234.0/24 209.1.15.0/24 64.41.193.0/24 216.34.51.0/24 #_spf-a.microsoft.com 213.199.128.139 213.199.128.145 207.46.50.72 207.46.50.82 #_spf-b.microsoft.com 131.107.65.22 131.107.65.131 131.107.1.101 131.107.1.102 217.77.141.52 217.77.141.59 #_spf-c.microsoft.com 131.107.1.18 131.107.1.19 131.107.1.20 131.107.70.12 131.107.70.16 #mynethost.com 64.207.205.0/24 64.207.194.0/24 82.165.241.165/32 #