By Weldon Whipple <weldon@whipple.org>
These instructions describe how to modify sendmail's configuration file to enable the dnsbl (DNS Blacklist) feature to block incoming e-mail from IP addresses that are listed on one or more blacklists. These particular blacklists are checked by sendmail during the SMTP conversation, avoiding the generation of the bounce messages that are generated (for example) when SpamAssassin--called from procmail--consults DNS Blacklists. (The configuration of SpamAssassin to consult DNS Blacklists is outside the scope of this document.)
Here is how DNSBLs work:
At the time of this update (9/10/2009), my own sendmail configuration uses only the following blacklist:
I offer it only as a starting point. Jeff Makey's Blacklists Compared lists many other DNS blacklists. You will probably want to check Google or Yahoo to find out what others think of particular blacklists.
Add new lists very carefully! Some are overly aggressive in their blacklisting criteria: they might block mail from some of your best friends! Others list not only single IP addresses, but an entire network block that includes the offending IP address. (I generally try to avoid those blacklists ...)
After adding a new blacklist to your configuration, check the mail log, searching for "check_". Make sure that the blacklist isn't too agressive.
The location of mail logs varies from OS to OS. Try looking in /var/log/maillog or /var/log/messages for starters..
Modern sendmail.cf files are generated from macro configuration (mc) files.
If you use a standard sendmail.org distribution, follow the instructions in the cf/README file that ships with sendmail. The procedure for generating the sendmail.cf on FreeBSD is described in a FreeBSD sendmail FAQ. Check the documentation for your OS if neither of these applies.
To add a DNS Blacklist to the macro configuration file, add a dnsbl FEATURE line for each blacklist (in the section of the mc file that has other FEATURE lines):
FEATURE(`dnsbl',`name-of-blacklist')dnl
Note that the single quotation marks are not all the same: the first quotation mark in each pair is a backquote; the second is an apostrophe.
The following illustrates how to add the blacklist zen.spamhaus.org to your sendmail mc file.
FEATURE(`dnsbl',`zen.spamhaus.org')dnl
There are a variety of reasons to enable DNS Blacklisting for only a subset of your users: You might be skeptical of the DNSBL feature; you might want to charge extra for blacklisting; perhaps most of your users like receiving SPAM. Whatever the reason, you can configure sendmail to enable DNS Blacklisting for designated recipients only. Here is how to do it.
FEATURE(`dnsbl',`zen.spamhaus.org')dnl FEATURE(`access_db')dnl FEATURE(`delay_checks',`hater')dnl
Spam:legolas@whipple.org HATER Spam:bilbo@whipple.org HATER
The following commands might generate access.db on your platform:# cd /etc/mail # makemap hash access < access
In the option described above, we enabled DNS Blacklisting for a
list of enumerated local recipient e-mail addresses. You might want to
(instead) enable DNS Blacklisting for all local users except
for a handful of local users who want to receive all incoming
mail. (Maybe they are plastic surgeons that specialize in the
enhancement of gender-specific body parts, for example, and don't want
to miss the latest developments in their field
FEATURE(`dnsbl',`zen.spamhaus.org')dnl FEATURE(`access_db')dnl FEATURE(`delay_checks',`friend')dnl
Spam:legolas@whipple.org FRIEND Spam:bilbo@whipple.org FRIEND
Note: The "hater" and "friend" [of spam] arguments to the delay_checks feature are mutually exclusive--you must choose one or the other (if you choose to use the feature at all). For more information, see my document that gives steps for configuring per user spam control, or the cf/README or the Bat Book.
If you aren't satisfied with the default error message sendmail returns, you may specify one that you like better as a a third argument to the FEATURE macro. Here are two examples:
FEATURE(`dnsbl',`relays.ordb.org', `"550 5.7.1 Access denied(O): Unsolicited e-mail from " $&{client_addr} " refused. Request access at http://www.whipple.org/mailrequest.html"')dnl FEATURE(`dnsbl',`dnsbl.sorbs.net',`"554 Rejected " $&{client_addr} " found in dnsbl.sorbs.net"')dnl
There will undoubtedly be occasions when attempts to look up the pseudo-hostname timeout or name resolution attempts otherwise fail. Sendmail's default behavior in this case is not to reject the incoming mail. If you would prefer to return a temporary error to the incoming server, you can do so by specifying a fourth argument, the value `t', to the FEATURE macro:
FEATURE(`dnsbl',`dnsbl.sorbs.net', , `t')dnl
If you also customize the error message, the above will look something like:
FEATURE(`dnsbl',`dnsbl.sorbs.net',`"554 Rejected " $&{client_addr} " found in dnsbl.sorbs.net"',`t')dnl
Now when the lookup fails, your sendmail will return the following error to the sending server:
451 Temporary lookup failure of IP at name-of-blacklist
If you want to set up your own blacklisting service and offer the service to others, all you need is a domain name (a third-level subdomain of your main second-level domain, for example), a name server (well, two--or more--name servers), and a way of updating your name servers to add or delete subdomains. Oh yes, you probably need lots of bandwidth and computing power, if you plan on being a public blacklist.
I could, for example, designate the subdomain spammers.whipple.org as the name of a DNS blacklist, then set up two authoritative name servers for spammers.whipple.org (or just use the whipple.org name servers, if they are powerful enough and have sufficient bandwidth). Whenever I want to add an IP address to the spammers.whipple.org blacklist, I add an "A" resource record for 7th-level domain consisting of the IP address (reversed) followed by spammers.whipple.org. Then when other e-mail servers want to check my blacklist, they construct a 7th-level pseudo-hostname that ends with spammers.whipple.org and see if it resolves.
What should be on the right-hand-side of the "A" records that our blacklisting name server returns? For testing purposes (I guess?), most blacklists include a localhost-like sample entry (such as 127.0.0.2 or 127.0.0.3). Let's try looking up what kinds of "A" records the dnsbl.sorbs.net list returns when we chedk 127.0.0.2, using the dig command:
% dig 2.0.0.127.dnsbl.sorbs.net
The day I tried this, dig returned the following:
; <<>> DiG 8.3 <<>> 2.0.0.127.dnsbl.sorbs.net ;; res options: init recurs defnam dnsrch ;; got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49598 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 7, ADDITIONAL: 7 ;; QUERY SECTION: ;; 2.0.0.127.dnsbl.sorbs.net, type = A, class = IN ;; ANSWER SECTION: 2.0.0.127.dnsbl.sorbs.net. 2D IN A 127.0.0.6 2.0.0.127.dnsbl.sorbs.net. 2D IN A 127.0.0.7 2.0.0.127.dnsbl.sorbs.net. 2D IN A 127.0.0.9 2.0.0.127.dnsbl.sorbs.net. 2D IN A 127.0.0.10 2.0.0.127.dnsbl.sorbs.net. 2D IN A 127.0.0.2 2.0.0.127.dnsbl.sorbs.net. 2D IN A 127.0.0.5 2.0.0.127.dnsbl.sorbs.net. 2D IN A 127.0.0.3 2.0.0.127.dnsbl.sorbs.net. 2D IN A 127.0.0.4 ;; AUTHORITY SECTION: dnsbl.sorbs.net. 1d18h34m20s IN NS rbl1.oregonstate.edu. dnsbl.sorbs.net. 1d18h34m20s IN NS rbl2.oregonstate.edu. dnsbl.sorbs.net. 1d18h34m20s IN NS sorbs.bl.xs4all.nl. dnsbl.sorbs.net. 1d18h34m20s IN NS sorbs-sql1.vix.com. dnsbl.sorbs.net. 1d18h34m20s IN NS rbldns0.sorbs.net. dnsbl.sorbs.net. 1d18h34m20s IN NS rbldns2.sorbs.net. dnsbl.sorbs.net. 1d18h34m20s IN NS rbldns3.sorbs.net. ;; ADDITIONAL SECTION: rbl1.oregonstate.edu. 18h54m31s IN A 128.193.0.30 rbl2.oregonstate.edu. 18h54m31s IN A 128.193.0.130 sorbs.bl.xs4all.nl. 18h54m19s IN A 194.109.9.11 sorbs-sql1.vix.com. 47m6s IN A 204.152.186.189 rbldns0.sorbs.net. 3m3s IN A 203.15.51.34 rbldns2.sorbs.net. 3m3s IN A 209.209.1.20 rbldns3.sorbs.net. 3m3s IN A 209.142.2.10 ;; Total query time: 244 msec ;; FROM: gabriel.whipple.org to SERVER: 166.70.98.35 ;; WHEN: Mon May 17 14:02:05 2004 ;; MSG SIZE sent: 43 rcvd: 491
Notice in the "answer section" that the right-hand-side of the eight "A" resource records have values:
Using multiple resource records for a single (each with different right-hand-sides) lets you assign significance to the value that is returned on the right-hand-side. (Visit the blacklist's home page to find an explanation of the meaning of the possible right-hand-sides.)
Sendmail's dnsbl feature (described above), doesn't check the value of the right-hand-side. (All it cares about is whether something--anything--is returned.) If you want sendmail to check the right-hand-side value returned by DNS, see the enhdnsbl (Enhanced DNS Blacklist) feature below.
Because 2.0.0.127.dnsbl.sorbs.net resolves (returns at least one "A" record, above), we know that the test IP address 127.0.0.2 is blacklisted by dnsbl.sorbs.net.
Sendmail's enhanced DNS Blacklist feature (enhdnsbl) is identical to the dnsbl feature described earlier in this document, except that it allows you to specify an optional fifth argument. The fifth argument is for matching against the value returned in the right-hand-side of the blacklist's DNS resource record. (See the previous appendix for that discussion.)
Since all but the first argument are optional for both the dnsbl and enhdnsbl features, you could (if you prefer) substitute "enhdnsbl" for "dnsbl" in all the FEATURE statements in this document.
If (after visiting the dnsbl.sorbs.net web site and finding the meaning of the different values that can be returned on the right-hand-side of the blacklist's "A" resource records) you determine that you are interested in blocking e-mail only if the right-hand-side is 127.0.0.9 (for example), try one of the following:
FEATURE(`enhdnsbl',`dnsbl.sorbs.net', , , `127.0.0.9')dnl FEATURE(`enhdnsbl',`dnsbl.sorbs.net',`"554 Rejected " $&{client_addr} " found in dnsbl.sorbs.net"', , `127.0.0.9')dnl FEATURE(`enhdnsbl',`dnsbl.sorbs.net',`"554 Rejected " $&{client_addr} " found in dnsbl.sorbs.net"',`t', `127.0.0.9')dnl
Not all DNS blacklists are open to queries from all servers on the Internet. Probably the most well known blacklists are those of mail-abuse.org: blackholes.mail-abuse.org, relays.mail-abuse.org and dialups.mail-abuse.org. Those three became "subscriber-only" lists in 2001. (When you subscribe to their service, they ask for the IP address of your mail server. Then they add your server's IP address to an access control list (ACL). See the discussion about caching only name servers below if you decide to subscribe to mail-abuse.org. If you are a non-profit hobbyist, you might qualify for a free subscription.)
Although mail-abuse.org's lists require a subscription, most other blacklists can be queried by anyone.
It might be to your advantage to run a caching name server on your mail server. (If you have a subscription from mail-abuse.org, it is probably a requirement to run a caching name server: mail-abuse.org will list your mail server's IP address in its access control list; your ISP's name servers [for example] won't be able to resolve the pseudo-hostnames in mail-abuse.org's blacklists.) If you run a caching name server, you should limit the hosts that can query your name server to your mail server (and probably backup MX servers).
Here is an example of a possible BIND 9 named.conf configuration file for a caching name server. Note that the allow-query line restricts who can query the name server.
/* * A simple BIND 9 configuration */ options { directory "/etc/namedb"; allow-query { 166.70.98.35; 166.70.98.36; }; }; zone "0.0.127.in-addr.arpa" { type master; file "localhost.rev"; }; zone "." { type hint; file "named.root"; };
This document is a work in progress. Please send corrections or suggestions to me!