U.H.A.C.C. Join today! Linux Free BSD OSX (Darwin) Open BSD GNU - Free Software Foundation IBM AIX Sun - Solaris, Open Office SGI IRIX
home club info listserv sysblogd forums geeky links tech help webmail contact
hacker emblem


LDP Mirror
Forums RSS

Past club events:

UHACC @ Penguicon
LinuxFest 2004
SCO-B-Q
UHACC @ Flatcon

Club Pages:

ISU chapter: ISUnix
Member's Sites

Projects:

UHACC CVS

Club Documents:

Our Guiding Principles
UHACC Constitution
Operating Code
Membership App
AUP


Valid CSS!

Quelling spam Using
sendmail

By Chuck "mongoose" Geigner

The following notes are taken from the "Quelling spam Using Sendmail" presentation to UHACC on 12 May 2004, updated on 16 June 2006 to add sendmail 8.13.x features.



A PREFACE

Sendmail seems to get a bad rap these days by a lot of people. The most frequest detraction I hear from the mouths of sendmail naysayers is "sendmail is insecure."
Now I must admit that sendmail has had its fair share of vulnerabilities, but I counter that with the fact that sendmail has always been very good about releasing timely patches and being proactive about security. - and by the way, if you don't apply patches, they generally don't work! That applies to anything you run, of course. So if you complain that your sendmail 8.8.8 box got totally compromised and imply that it is somehow the fault of the software, you probably won't get a lot of sympathy here. If you just prefer postfix or qmail, that's cool too. They are very good smtp servers. They are also single purpose, which makes them easier to set up (unlike sendmail, that has so many options it makes the head spin). I focus on sendmail because I have been admining enterprise sendmail boxen since 1999, and if you are going into business or consulting, there is a pretty good chance that you'll be faced with one of these along the way. Heck, once you get used to it, you may even find yourself preferring it! It happens. --CTG



First Line of defense: Use an Access List /etc/mail/access.db



Step #1) Enable your access list: Put in the access_list m4 definition in your .mc (configuration) build file like so:

FEATURE (`access_list')dnl

Step #2) define directives in /etc/mail/access
Valid entries have the (generic) following form:

(TYPE)HOST  DIRECTIVE

TYPE


The TYPE refers to the type of activity to match on the SMTP server. It is not required and if left out, defaults to a combo of From: and Connect:.
EXAMPLES:

To:HOST          DIRECTIVE  <-- blocks outgoing mail to HOST
From:HOST        DIRECTIVE  <-- blocks incoming mail from HOST
Connect:HOST     DIRECTIVE  <-- block server connections from HOST
GreetPause:HOST  TIME IN mSEC <-- overrides standard pause duration defined in sendmail.cf

HOST


The HOST refers to the hostname, email user, or IP address to match. This is a required element.
EXAMPLES:
by hostname/domain/e-mail user:

user@example.com             DIRECTIVE <-- 1 user
user@                        DIRECTIVE <-- all users named "user"
host.subdomain.example.com   DIRECTIVE <-- all users on 1 host
subdomain.example.com        DIRECTIVE <-- all in subdomain
example.com                  DIRECTIVE <-- all domain
com                          DIRECTIVE <-- all in TLD

by IP address:

123.123.123.123  DIRECTIVE <-- 1 host
123.123.123      DIRECTIVE  <-- whole /24
123.123          DIRECTIVE  <-- whole /16
123              DIRECTIVE  <-- whole /8. totally draconian

(notice that you can only isolate by octet, CIDR notation will unfortunately NOT work here)

DIRECTIVE


the DIRECTIVE is the action you want taken when the server matches an access rule on the LHS.
EXAMPLES:

REJECT  - rejects all matches with smtp 550 error
OK      - allows mail through, use to "excuse"
DISCARD - silently places all matches in /dev/null
RELAY   - relays mail for all matches
ERROR:5.7.1:550 (add msg here)  - sends custom 550 access denied messages

Step #3) Convert access list to a hash, dbm, or btree table for use in production. dbm's are slow, use hash tables if possible. Do so like this:

# makemap hash /etc/mail/access.db < /etc/mail/access

My production access list has been dutifully updated since I started admining my first large scale mail server back in 1998. It has almost 10K entries and can be used as a reference (NOT as your production list please, you will probably get false positives, which defeats the purpose)

Pay Attention to Your .cf Definitions


The conf options listed in the V3 O'Reilly bat book number around 140 (!). Obviously you will probably not use all of these, but if you do, be sure not to configure a convenience for the enemy.
The conf options covered here are not exhaustive, but do illustrate some ones I've used and on which have developed some practical insight.



SMTP_LOGIN_MSG


Configuring SMTP_LOGIN allows you to define how your MTA will answer when a session is opened. When setting this, try not to give out info attackers can readily use, such as disclosing the fact that we run Sendmail and giving the exact version string. Note that by default the login message is defined as this:

define(`confSMTP_LOGIN_MSG', `$j Sendmail $v ready at $b')

...which gives the following login message on connect:

220 mail.uhacc.org ESMTP Sendmail 8.12.9 ready at Fri, 16 Dec 2005 20:56:41 -0600

In contrast, our login message is defined like so:

define(`confSMTP_LOGIN_MSG', `$j U.H.A.C.C. MTA:  $b')

...which when connecting gives the following greeting:

220 mail.uhacc.org ESMTP U.H.A.C.C. MTA:  Fri, 16 Dec 2005 20:56:41 -0600

Some folks put legal foo in there, others get quite creative, but again, no matter how you customize it, be wary of giving too much information. Sure, a dedicated attacker could ferret the product and version info using more creative methods, but why make it easy? As you can see in my greeting, I mention neither sendmail, nor give the version ($v macro), but do confirm that you've connected to the mail.uhacc.org ($j macro, canonical server name) MTA and that my timestamp ($b macro) is correct.



PRIVACY_FLAGS


PrivacyOptions can (and should) be set to disable some tools which allow clients to glean too much info or submit weirdly ordered directives. Most notably, we want to disable smtp VRFY and EXPN, which allow attackers to discover our alias mapping, mail lists, and even who gets root's mail. There are many more directives possible that you can research on your own. In the interest of being brief, if you want to be pretty safe, just use the following definition on your sendmail macro config:

define(`confPRIVACY_FLAGS', `goaway')


BAD_RCPT_THROTTLE


Ever notice spammers connecting and, since you disabled the VRFY option (see PRIVACY_FLAGS, above), they just start issuing smtp MAIL TO: requests with what appears to be a dictionary of possible usernames? Every time your server answers with an smtp 250 reply, they add the address to their spam list. Lovely. Well, no prob. Set BAD_RCPT_THROTTLE to, say 5, and then after 5 failed RCPT To:'s and your server will start sleeping 1 second between requests. May not seem that long, but believe me, due to the size of the dictionary they run when trying to scrape good accounts from you, 1 second between requests is a flipping eternity. You'll be happy to set this option. Why? Cause it frustrates spammers, that's why!

define(`confBAD_RCPT_THROTTLE', `5')



Using the GreetPause FEATURE


Slamming, occurs when a connecting client shoves a whole session's input on one submission. The practice not only violates the RFC, it is pretty rude. And you guessed it, it's a favorite method of time-optimizing spammers. To foil, use the greet_pause feature, which takes a numeric parameter which is the time wait measured in milliseconds. If a client connects and shoves commands before the smtp login message banner appears (after the wait specified), the session invlidates itself. Spammers doing this will likely not notice, being that the ones that do this really don't wait around to see the errors. Set up as follows:

FEATURE(`greet_pause', `1000')dnl


Using the Blacklist Recipients FEATURE


Another way to block people from replying to spammers is to enable the "blacklisted recipients" feature in your sendmail configuration. Once enabled, it will apply every untagged (no TYPE, see above) rule in your access list to all outbound mail.
configuration m4 entry:

FEATURE `(blacklist_recipients)'dnl Block outgoing mail to unfriendlies

CAVEAT: As with using the "To:" TYPE in your access list, be extremely careful using outgoing mail block options. As a mail admin, I often received complaints from people who, for whatever reason, wanted the freedom to contact their spammers (as well as a few 419 baiters, but that's another story!). As much as I disagreed, I could not refute the assertion that they put forth that I had no right to block their outgoing e-mail, regardless of my good intentions. I no longer use blacklisted recipients. Instead I focus on educating folks on why you do not respond to spammers, and let them make their own decisions. After all, they are big kids, even if I don't think that responding to a spammer is excercising very good judgment.



Using DNSBL's


Don't have a list already made? Not to worry, there are legions of netizens out there who maintain servers containing information on spammers, spam support, open relays, open proxies, spamhausen, spam supporters, and other baddies. They are kept as DNS zones and are accessed as such. These are called DNS Block Lists, or DNSBL's. At first, the MAPS rbl was the only game in town, but nowadays with the proliferation of a whole bunch of different DNSBL's, you can configure in one or more of your favorite DNSBL's, or even start one of your own! Here's how:
configuration m4 entry:

FEATURE(dnsbl,`dnsbl.example.org'`"550 5.7.1 Access Declined for
"$&{client_name}" See: http://example.com/yousuck.html "', `')dnl using Spamhaus

See? You can even put in a custom error message so that those who get netted in your filter can learn why (although most spammers will know why). How polite of us :)

It works like this: mailserver looks up ip address in all dnsbl's, if it is not listed in the zone record, mail gets processed further. If it IS listed, mail is blocked with a nice 550 error and any added message we provide (see config above).

NOTE: The OK directive in your /etc/mail/access file will whitelist for any dnsbl entries as well.

Using Regular Expressions in LOCAL_CONFIG and LOCAL_RULESET to Filter spam


To put custom build definitions in sendmail, edit devtools/Site/site.config.m4 and add the following line:

 APPENDDEF(`confMAPDEF', `-DMAP_REGEX')

then build the sendmail binary.

At the end of your sendmail.cf, you can now add (this is the only time you would ever need to edit sendmail.cf by hand)

        LOCAL_CONFIG
        #
        # Names that cant be in that To: line
        #
        C{RejectToLocalparts}  hgh viagra
        C{RejectToDomains}     friend.com

        Kcheckaddress regex -a@MATCH
           ^([Vv].*[Ii|\/()].*([Aa4]|\/\).*[Gg].*[Rr].*([Aa4]|\/\))<@\.?>


        LOCAL_RULESETS
        HTo: $>CheckTo
        SCheckTo
        R$={RejectToLocalparts}@$*        $#error $: "553 Baaaaant - wrong answer"
        R$*@$={rejectToDomains}           $#error $: "553 Baaaaant - wrong answer"
      
        SLocal_check_mail
        #  check against our predefined regexes
        R$*                $: $>Parse0 $>3 $1
        R$+                $: $(checkaddress $1 $)
        R@MATCH        $#error $: "553 Baaaaant - wrong answer"

Test by using:

# sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> CheckTo hgh@amazingoffersandwhatever.com
CheckTo            input: hgh @ amazingoffersandwhatever . com
CheckTo          returns: $#error $: "553 Baaaaant - wrong answer"
> CheckTo alltheworld@friend.com
CheckTo            input: alltheworld @ friend . com
CheckTo          returns: $#error $: "553 Baaaaant - wrong answer"        
> Local_check_mail V|4gR/\@butthead.com
Local_check_mail   input: V|4gR/\ @ butthead . com
canonify           input: V|4gR/\ @ butthead . com
Canonify2          input: V|4gR/\ < @ butthead . com >
Canonify2        returns: V|4gR/\ < @ butthead . com . >
canonify         returns: V|4gR/\ < @ butthead . com . >
Parse0             input: V|4gR/\ < @ butthead . com . >
Parse0           returns: V|4gR/\ < @ butthead . com . >
Local_check_mail returns: $#error $: "553 Baaaaant - wrong answer"
> /quit



Well, hopefully this explains a few tools that you can use to help prevent your users from seeing more spam than legitimate e-mail. If you need help fighting spam on the local side rather than on a mail server, I would recommend reading up on procmail filtering, bayesian filtering, and spamassassin.

Go give 'em hell. If you haven't noticed, it is a war out there.

CTG

Upcoming Events


UHACC Pre-Meeting


Wednesday Evenings, ~5:15-6:30pm

- Lunker's


Officially unofficial pre-meeting meeting.
Come. Eat. Geek.


UHACC Meeting


Every Wednesday - 7:00-9:00pm

IWU Center for Natural Science Learning and Research, Fishbowl, floor 2. [Directions]



Join us every Wednesday for our usual gratuitous display of geekiness. Meetings are free and attendance is open.

Hope to see you there!


[Home] [Acceptable Usage] [Privacy Policy] [Downloads] [LDP Mirror] [Member's Sites] [Archives]

Copyright © 2006: Unix Hobbyists' Administrators' & Coders' Club. All Rights Reserved.
UHACC, P.O. Box 6376 - Bloomington, Illinois 61702-6376
"First they ignore you, then they laugh at you, then they fight you, then you win." - Mahatma Gandhi