See the Change History section for information on updates and changes to these rulesets.
At the University of Oregon, we want to prevent general use of our mail systems to relay mail from outside users to other outside users. But we also have complicating factors that make most of the methods currently proposed unsuitable for our purposes. Many of our users want to relay mail through a few well-known server hosts to other users on campus at different hosts. Many users use local ISPs to avoid our congested modem pool, come from clients with many different domain names and IP addresses not in our own network, and (as our support staff assure me) are not particularly willing to change their client SMTP server settings depending on where they dial in from. We also want the flexibility to add or remove permissions for particular domains or IP addresses without having to edit the sendmail configuration directly or restart sendmail.
The rulesets below are my attempt to address these requirements. They also have an uncommon feature: they handle more legal address formats than many commonly-suggested check_rcpt implementations, especially "source route" mail addresses. The user%host@relay and @relay:user@host formats are blessed by the RFCs and handled by sendmail. Many relay-prevention rulesets I've looked at don't even try to handle these address forms, and it's only a matter of time before spammers figure out that they can get around many relaying blocks by using addresses like spam%victim@your.domain. The only other implementation I have seen that attempts to deal thoroughly with such addresses was presented by Robert Harker in his paper "Selectively Rejecting Spam Using Sendmail" in the LISA '97 proceedings. My implementation was influenced by some of the techniques in Harker's paper.
Note that these rulesets are not designed for blocking spam mail to users at your site, although limiting mail relaying will help prevent your systems from being exploited by spammers. A variety of techniques for blocking spam mail to your own systems are presented in references at the end of this page.
The behavior of these rulesets is primarily controlled by four special database maps:
All of the database maps are optional, in that if they do not exist, they are treated as empty. You can safely leave out the maps that you don't need. To provide increased performance and some insurance against missing or trashed maps, these rules also check sendmail classes w (all the hosts you accept mail for) and R (domains that you are willing to relay to). You will probably want to put your own domain, and any other critical domains, in class R. An option is also provided to let you accept mail from any client in a host or domain in class R.
In the domain maps, domain names are matched on the right -- uoregon.edu matches darkwing.uoregon.edu, cs.uoregon.edu, asterix.cs.uoregon.edu, etc. In the IP maps, IP addresses of the form 1.2.3.4 are matched on the left -- 128.223 matches all addresses of the form 128.223.*.* and 198.68.17 matches all addresses of the form 198.68.17.*. Note that the rulesets won't match pure top-level domains (com, net, org, uk, etc.). They also won't match "class A" single-octet IP addresses by default, but you can optionally enable such matching.
An example relay_to_domain source file might look like this:
uoregon.edu *OK* tzadkiel.efn.org *OK*
And a relay_from_ip source file might look like this:
128.223 *OK* 198.68.17 *OK* 204.214.99.68 *OK*
All maps use *OK* as the thing that has to go on the right-hand side (RHS) of the database mapping to avoid the possibility of confusion with valid host names and user names, since the RHS value is substituted into a match. You can also make exceptions for individual hosts by making an entry for that host and using something other than *OK* for the RHS.
The general logic of this check_rcpt implementation is:
Much of the work is done by the Relay_to ruleset. First the address is passed through ruleset 3, which puts it in a canonical format that's easier to check and places the next recipient domain in a "focus" delimited by <@...>. The domain in the focus is then checked against class w (synonyms for this host), class R (a list of hosts or domains you want to permit relaying to), and finally the database maps that list the domains or bracketed IP addresses you're also willing to relay mail to. If the domain in the focus is permitted, then the focus is removed and Relay_to is invoked on the remaining part of the address. Eventually either the address is stripped down to just a local user part, and Relay_to returns *OK* to indicate the RCPT TO: should be permitted, or a domain that you won't relay to is in the focus, and Relay_to returns *NOTOK*.
This version includes support for FEATURE(mailertable) and for UUCP. If your configuration uses a mailertable, then a recipient domain is looked up in it, and permitted if the domain is found. Recipient domains are also checked against any UUCP relays you have specified in your configuration via the SITECONFIG macro.
While this ruleset is in production use at our site and a couple of others, you are advised to use it at your own risk. I'm not guaranteeing its fitness or effectiveness, but I'm also not placing any restrictions on the use or distribution of this code, other than that you are not to represent it as your own.
If you are a sendmail novice then you should proceed with caution. These instructions assume you have some familiarity with configuring and operating sendmail.
Eric Allman has his own set of experimental anti-spam measures for sendmail 8.8. My ruleset is largely compatible with the one presented there, including the use of class R to list relay hosts, except that mine is tolerant of more different address formats and uses database maps to extend the set of addresses permitted for relaying.
A variety of other sendmail check_* rulesets (including many other implementations of check_rcpt) are available at Claus Aßmann's Using check_* in sendmail 8.8 page. Some (but not all) of his available check_rcpt rules attempt to check source route addresses.
Chip Rosenthal's MAPS Transport Security Initiative site has more links on relay limitation, including information on how to implement it for other MTA software.
Thanks also go to Bob Jones <bj@oregon.uoregon.edu>, Jacques Distler <distler@golem.ph.utexas.edu>, and Christopher Masto <chris@netmonger.net> for spotting bugs in these rulesets.
Please feel free to contact me with questions or bug reports at the address below.