Monday, November 23, 2009

DNSBL: Configuring Sendmail for DNS-Based Blacklisting

SkyHi @ Monday, November 23, 2009
Contents

* Introduction
* Step 1: Choose Which Blacklist(s) to Use
* Step 2: Modify sendmail.cf for Blacklisting
o Optional: Enable DNSBL for Designated Users Only
o Alternate Disabling Option: Exempt Specified Local Users from Blacklisting
o Optional: Customize the Error Message
o Optional: Change Default Behavior When Lookups Fail Temporarily
* Appendices
o Appendix A: Notes on Creating Your Own DNS Blacklist
o Appendix B: Enhanced DNS BlackLists
o Appendix C: Subscriber-Only Blacklists--mail-abuse.org
o Appendix D: Name Server Issues
* Afterword

Introduction

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:

1. A mail server that wants to send mail to your mail server establishes a connection to your server.
2. Your server examines the socket information to find the IP address of the server at the other end of the connection.
3. Your server creates a special "pseudo-hostname" by reversing the order of the components of the IP address, then concatenating them with the domain name of the blacklist:

Example:
If the incoming IP address is 166.70.98.32 and the name of the blacklist is dnsbl.sorbs.net, then the resulting "pseudo-hostname" is 32.98.70.166.dnsbl.sorbs.net

4. Your server does a regular DNS lookup of the pseudo-hostname 32.98.70.166.dnsbl.sorbs.net. If it resolves, then the owner of the blacklist considers the host 166.70.98.32 to be a spammer. If the lookup doesn't resolve, then the IP address isn't blacklisted.

Step 1: Choose Which Blacklist(s) to Use

At the time of this update (9/10/2009), my own sendmail configuration uses only the following blacklist:

* zen.spamhaus.org

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..

Step 2: Modify sendmail.cf for Blacklisting

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.

Example:


FEATURE(`dnsbl',`zen.spamhaus.org')dnl

Optional: Enable DNSBL for Designated Users Only

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.

1. Insert a special delay_checks feature line in your sendmail mc file--somewhere after the feature that enables the access database:


FEATURE(`dnsbl',`zen.spamhaus.org')dnl
FEATURE(`access_db')dnl
FEATURE(`delay_checks',`hater')dnl

2. Add a line to the access db for each local recipient that wants DNS Blacklisting:


Spam:legolas@whipple.org HATER
Spam:bilbo@whipple.org HATER

3. Regenerate the sendmail.cf and access.db

The following commands might generate access.db on your platform:


# cd /etc/mail
# makemap hash access < access

Alternate Disabling Option: Exempt Specified Local Users from Blacklisting

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.:-) If you are in this situation, you can configure sendmail to exempt specified local users from DNS Blacklisting. Here is how to do it.

1. Insert a special (but different from the above) delay_checks feature line in your sendmail mc file--somewhere after the feature that enables the access database:


FEATURE(`dnsbl',`zen.spamhaus.org')dnl
FEATURE(`access_db')dnl
FEATURE(`delay_checks',`friend')dnl

2. Add a line to the access db for each local recipient who does not want DNS Blacklisting:


Spam:legolas@whipple.org FRIEND
Spam:bilbo@whipple.org FRIEND

3. Regenerate the sendmail.cf and access.db

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.

Optional: Customize the Error Message

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

Optional: Change Default Behavior When Lookups Fail Temporarily

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

Appendix A: Notes on Creating Your Own DNS 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:

* 127.0.0.6
* 127.0.0.7
* 127.0.0.9
* 127.0.0.10
* 127.0.0.2
* 127.0.0.5
* 127.0.0.3
* 127.0.0.4

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.
Appendix B: Enhanced DNS BlackLists

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

Appendix C: Subscriber-Only Blacklists at mail-abuse.org

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.
Appendix D: Name Server Issues

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";
};


Afterword

This document is a work in progress. Please send corrections or suggestions to me!