This is a read-only archive. Find the latest Linux articles, documentation, and answers at the new!


Installing and configuring spamd

By Terrell Prudé, Jr. on April 12, 2007 (8:00:00 AM)

Share    Print    Comments   

Yesterday we looked at spamd, a service designed to reduce the flow of spam to your email inbox. Now that we know some of its advantages, let's put it to work.

The order of things is as follows:

  1. Decide on a physical hookup and IP addressing scheme.
  2. Get spamd configured and running.
  3. Tell OpenBSD to send any TCP 25 traffic to spamd for evaluation (yes, that is a required step). But we also must tell OpenBSD to forward email from "good" senders to our real email server. PF rules (OpenBSD's version of iptables) take care of that.
  4. Test, test, test!
I used the physical layout shown in the figure. "spamslayer" is the OpenBSD box running the spamd tarpit/greylister, as well as a stateful packet-filtering firewall. It is a 270MHZ Sun Ultra 5 with 256MB DRAM and a 20GB disk; /var, which holds my logs, is 4GB in size. The box has three interfaces:
  1. hme0, the outside interface
  2. fxp0, the inside "trusted" interface, and
  3. fxp1, the DMZ interface.
"mailhost" is my real mail server. It's another Sun Ultra 5 box running Ubuntu GNU/Linux 6.06 Dapper Drake. It runs Postfix and Dovecot in a maildir configuration, and uses a private IP address of

Topology diagram
Click to enlarge
Once you install and set up the IP addresses on the OpenBSD box, you need to edit three files:

/etc/rc.conf -- the system-wide config file. You can make the changes to /etc/rc.conf.local, if you prefer that instead; the settings in that file override the defaults in /etc/rc.conf.
/etc/pf.conf -- the PF ruleset; mandatory for anything to work
/etc/spamd.conf -- the default is pretty good, but you can make tweaks

A note about interfaces on any of the BSDs: Unlike GNU/Linux, which has eth0, eth1, eth2, and so on, *BSD interfaces are named by which device driver they take. I have an fxp0 and a fxp1 because I have two Intel EtherExpress Pro/100B cards that use the fxp driver -- equivalent to eepro100 in Linux, and an hme0, which stands for -- no, I'm not kidding -- Sun Happy Meal Ethernet. It's the built-in 10/100 NIC in nearly all Sun Ultra boxes.

/etc/rc.conf controls several boot-time settings. Change the existing lines with these settings so that they now look like the following:

Changes to /etc/rc.conf:
spamd_flags="-v -S 90 -n Postfix -h -G 60:4:864"

Watch out for this potential glitch
You will, as root, need to create a file that is not present in the default install, namely /var/db/spamd. Issue the command touch /var/db/spamd, which, of course, makes the owner root:wheel. However, that file needs to be owned by the spamd process's owner, which is _spamd. I suspect that the OpenBSD team already knows about this and that it will be fixed in a future version, given that their spamd man page mentions the permissions issue. But it's easy enough to correct by running chown _spamd:_spamd /var/db/spamd.
The default time for the initial greylist quarantine is 25 minutes. With a change to the -G parameter for spamd_flags I bumped it up to 60 minutes, since 25 minutes proved to be a bit too short in actual practice. The -v parameter tells spamd to log verbosely, so that when we send email to someone, that recipient gets automatically whitelisted.

The pf_rules line should already be there, but if it isn't, put it in.

The spamd man page will tell you about the rest.

Next up is /etc/pf.conf, which I wrote from scratch. If you understand what port forwarding, NAT, and stateful firewalling are, the following file should make sense. Lines that begin with "#" are comments:

# First, set up our macros
externalif = "hme0"
internalif = "fxp0"
dmzif = "fxp1"

internalnet = ""
dmznet = ""

# Here are addresses we should never see from the Internet
# We will use this table to block these IP addresses in a later rule
table <rfc1918> persist {,,,}

# Let's make our categories of spammers and non-spammers
# We do this with PF tables
table <spamd> persist
table <spamd-white> persist
table <whitelist> persist file "/etc/whitelist.txt"
table <blacklist> persist file "/etc/blacklist.txt"

# Let's normalize our packets; this is a really good idea
scrub on $externalif all fragment reassemble random-id reassemble tcp

# Turn on one-to-many NAT
nat on $externalif inet proto {tcp, udp, icmp} from $internalnet to any -> $externalif
nat on $externalif inet proto {tcp, udp, icmp} from $dmznet to any -> $externalif

# Stop the spammers!
# Redirect SMTP traffic to either our local spamd or the real mail server,
# depending on which PF table the sender's IP address is in.
# "Redirect" is OpenBSD PF-speak for Port Address Translation (PAT).
rdr pass on $externalif proto tcp from <whitelist> to $externalif port smtp -> port smtp
rdr pass on $externalif proto tcp from <blacklist> to $externalif port smtp -> port 8025
rdr pass on $externalif proto tcp from <spamd> to $externalif port smtp -> port 8025
rdr pass on $externalif proto tcp from <spamd-white> to $externalif port smtp -> port smtp
rdr pass on $externalif proto tcp from !<spamd-white> to $externalif port smtp -> port 8025

# Need to do some PAT for the real mail server so that IMAP and Secure IMAP work
rdr pass on $externalif proto tcp from any to $externalif port 143 -> port 143
rdr pass on $externalif proto tcp from any to $externalif port 993 -> port 993

#Filter out the spoofers, as defined in the previously-created "<rfc1918>" table
block in quick on $externalif inet from <rfc1918> to any

# Turn on stateful packet filtering
# We let back in any traffic whose session originated from the inside
pass out quick on $externalif inet proto tcp from $internalnet to any modulate state
pass out quick on $externalif inet proto udp from $internalnet to any keep state
pass out quick on $externalif inet proto icmp from $internalnet to any keep state
# Also have to explicitly allow the firewall's own traffic to come back in!
pass out quick on $externalif inet proto tcp from $externalif to any modulate state
pass out quick on $externalif inet proto udp from $externalif to any keep state
pass out quick on $externalif inet proto icmp from $externalif to any keep state

# We also let in any SMTP and SSH traffic, and log the SMTP traffic for spamlogd
pass in log quick on $externalif inet proto tcp from any to port smtp keep state
pass in log quick on $dmzif inet proto tcp from to any port smtp keep state
pass in quick on $externalif inet proto tcp from any to $externalif port 22

# Deny everything else!
block in on $externalif inet all

End /etc/pf.conf

You can tweak the interface names and use this file in your own three-interface OpenBSD box. Note that there are no IP addresses listed here except for that of mailhost (, which I'm using NAT for anyway. That's because PF allows you to specify interface names instead of IP addresses.

The section labeled "Stop the spammers!" deserves some attention. The order of the statements is important here; if the order is wrong, things won't work right.

First, there's the <whitelist> rule. <whitelist> is a table of IP addresses and/or netblocks; tables are how you group a bunch of IP addresses together in PF. This particular table is a manual whitelist, not maintained automatically by OpenBSD; it gets populated with the contents of a file I made, /etc/whitelist.txt. I keep this list to an absolute minimum. I have four IP addresses in there that I don't want to bother greylisting. Three are on my own network, and the fourth is that of a friend in China. If I ever need to add anything, the system will see it at next reboot. To have OpenBSD recognize an added entry without rebooting, run as root the command pfctl -t whitelist -T replace -f /etc/whitelist.txt.

Alternately, you could avoid replacing the entire whitelist table and just add the one that you want to whitelist:

pfctl -t whitelist -T add

or, for a whole network:

pfctl -t whitelist -T add

Next is the <blacklist> rule. If someone manages to slip by all of spamd's protections, you can put that IP address in here, and it will be tarpitted just as if it were in the SPEWS list. Try to keep the entries in this list to a minimum. I make additions to /etc/blacklist.txt and use the same syntax that we used with the whitelist to make them recognized:

# pfctl -t blacklist -T replace -f /etc/blacklist.txt

Here's what my blacklist file looks like:

# Tarpit/reject the mail server of a person who regularly tries to spam me
# Tarpit/reject a /8 in China that my other lists missed
# Tarpit/reject because they spam me; they use a /24

Whitelists take the same format.

Next comes the <spamd> rule. These are the spammers that SPEWS and others know about. Once we're done with everything, they'll all end up in the "spamd" PF table that we created in /etc/pf.conf above. This will result in spamd tarpitting them immediately upon connection.

The <spamd-white> rule follows that. This basically means, "everyone who got greylisted, but who has passed my initial 60-minute greylisting quarantine, I think you're probably legit, so just head on over to the real mail server." These folks are stored in the "spamd-white" table.

The !<spamd-white> section is the catch-all. It means, "everyone else, you're not a known spammer, but you're not whitelisted anywhere either, so you're getting greylisted. Come on back in 60 minutes and I'll let you send email to the real MTA here."

Next: /etc/spamd.conf configuration

Share    Print    Comments   


on Installing and configuring spamd

Note: Comments are owned by the poster. We are not responsible for their content.


Posted by: Anonymous Coward on April 18, 2007 07:38 AM
What tickles my funny-bone about this is that the article is put under a GNU licence, when the OpenBSD developers really hate the GNU everything.



Posted by: Anonymous Coward on April 21, 2007 03:53 AM
And don't forget, the author is one of those "Linux guys" that the OpenBSD developers also hate. How do I know? I'm that author.<nobr> <wbr></nobr>:-)

We can disagree on licenses--GNU vs. BSD--and as long as it doesn't devolve to name-calling, it's a healthy and necessary debate. But we cannot compromise on our fight for freedom. And that's why I wrote the article.



unverified claims about origins of spam

Posted by: Anonymous Coward on April 21, 2007 04:22 AM
Russian ISPs always take care of any spam-related complaints. I am Russian, I get a lot of Russian spam, and the vast majority of it comes from the LACNIC network, KR/CN, as well as North America and Western Europe. The number of spam received from Russian networks is just close to being negligible.

Could you please be so kind as to either provide reputable verification of your claims that Russian ISPs and government doesn't care about spam, or remove Russia from the default configuration that you provide in the article? Too many people just copy-paste the configuration these days, so I hope that you will act responsibly here and with duly promptness.

Thank you,


Re: unverified claims about origins of spam

Posted by: Anonymous [ip:] on July 22, 2007 02:04 PM
Actually, I have to agree with the author on this one. You oughta see my logs, there are lots of Russian bots trying to spam me (whois is great for determining this).


Re: unverified claims about origins of spam

Posted by: Anonymous [ip:] on November 09, 2007 02:50 AM

If only that were true, Constantine! I wish it were. Unfortunately, my server logs for the past seven months do show lots of Russian IP addresses trying to spam me with "V1agra" ads. This is right along with IP addresses from Romania, Bulgaria, Poland, and Hungary. It seems that Eastern Europe is as much a hotbed for "scam spams" as China and Nigeria are!

You correctly point out that a good chunk of the spam originates from LACNIC. A bunch of WHOIS queries shows that the chief source of spam from LACNIC is currently Brazil.

You also correctly point out that a lot of the spam is from the United States. I would add Canada to that list. That's why I also do my sleuthwork and find the IP ranges that Verizon, Comcast, Quest, Rogers, etc. use for their dynamic IP assignments. These are automatically blacklisted, since home broadband users with dynamic IP addresses don't typically run Internet mail servers. :-)

HOTMAIL ALERT: I have also been getting a lot of spam from Microsoft's HotMail in the last few months. After several notices to them, it still didn't stop. Therefore, MS HotMail is now also on my private blacklist ( Doggone shame. Yahoo currently seems to be better with that, from what I can see.

So, it's not just the Russians. Far from it. And my blacklist has grown since I first wrote the article



Installing and configuring spamd

Posted by: Anonymous [ip:] on October 18, 2007 09:18 PM
I have spam .This product is made in USA,the best quality.


Installing and configuring spamd

Posted by: Anonymous [ip:] on November 09, 2007 02:38 AM
There are minor changes for subsequent versions of OpenBSD. First, the greylisting is on by default. That means that, in /etc/rc.conf, you don't have to throw the -G switch in the list of spamd's parameters. Also, the default /etc/spamd.conf no longer points to the now-defunct SPEWS (it points elsewhere now). Other than that, it's the same on OpenBSD 4.1. A month and a half ago, I implemented this on 4.1 for a friend, using 3Com 3C905's instead of Intel EtherExpress cards, and everything transferred over. All I had to do in /etc/pf.conf was change the aliases for fxp0 and fxp1 to xl0 and xl1, respectively. Worked like a champ. And my friend is very happy with the reduction in spam.

I haven't yet tried it on 4.2 (released this month), but I'd expect it to work the same.

Other than that, I didn't have to make any other changes.



This story has been archived. Comments can no longer be posted.

Tableless layout Validate XHTML 1.0 Strict Validate CSS Powered by Xaraya