Tuesday, October 5, 2010

Hardening Sendmail against DDoS

SkyHi @ Tuesday, October 05, 2010
For some time now, I was experiencing a strange behavior of my server: from time to time, without an ascertainable pattern, the server would stop reacting to network-requests. The teamspeak-server, which runs on it, would kick anyone connected to it, and nothing particular special could be found in the logs. When this happened last Thursday, and I was kicked out of the teamspeak-server myself, I tried to ssh onto my server - which took about 30 seconds. This was irritating, and I run "uptime" to check the server's load - it was way beyond 70. The next thing was a call to top, and here I saw the culprit: sendmail. A call to ps verified the sendmail was running with way too many processes, all in "RCPT TO:" state or something similar. I stopped sendmail and killed remaining processes manually, so that I could work again in real time. Looking through maillog, I began to understand what going on: spammers were DDoSing my mail-server. Though I already had some settings in my sendmail.mc that would make the server unattractive for spammers, they were obviously not sufficient, and especially not against DDoS-attacks. So I changed my configuration a bit.

Connection Controlling

FEATURE(`delay_checks', `friend')dnl
FEATURE(`ratecontrol', `nodelay',`terminate')dnl
FEATURE(`conncontrol', `nodelay',`terminate')dnl
After the already existing line "FEATURE(`access_db')dnl" I added the lines to enable rate and connection-controlling.

The option "nodelay" is important, because I am using the delay-checks-feature, and these checks are not to be delayed.

The "terminate"-option tells sendmail to kill all connections exceeding the later defined limits with a temporary error-message. The properly configured and standard-compliant smtp-client will try again later, spammers usually don't.

The rate-control feature enables control over how often a single host is allowed to connect per a defined window. It was introduce by sendmail version 8.13.0, and uses the access.db for defining the limits for single hosts, groups of hosts or all hosts.
The window-size is defined using the this option:
with a default-value for window of "60s" (60 seconds).
My access.db-entries for the rate-control-feature look like this:
ClientRate:localhost                    0
ClientRate:localhost.localdomain        0
ClientRate:                    0
ClientRate:                             5
The first three lines tell sendmail to ingore rate-limits for the localhost, and the last line imposes a limit of 5 connections per window for all hosts.
In cases of a DDoS, it might not be sufficient to limit the connections of a single host per minute, because a DDoS comes from multiple hosts at the same time. This is why Sendmail come with another option:
define(`confCONNECTION_RATE_THROTTLE', `5')dnl
This defines the overall number of concurrent connection the server accepts per second, before queuing incoming connection-request regardless of the host. The connections will not be rejected but stalled until the next second. This means that for the above example that when 20 connection-requests arrive, the first five (1-5) are processed in second one, the second five (6-10) in second two, the third five (11-15) in second three, and the final five (16-20) in second four.

The conn-control feature enables control over the number of concurrent connections a single host is allowed to run simultaneously. Like rate-control, this feature was introduced with Sendmail 8.13, and the access.db is used to define settings for single-hosts, host-ranges and "all hosts", too.
My access.db-entries for the conn-control-feature look like this:
ClientConn:localhost                    0
ClientConn:localhost.localdomain        0
ClientConn:                    0
ClientConn:                             3
The entries are read similar to rate-control. The last line defines a default of 3 concurrent connections, the first three disable the feature for localhost.

Greeting Pause

A common technique of spammers, trojans and viruses is the so-called slamming. The SMTP-Standard requires the client to wait with the HELO/EHLO-Command until the server has sent its greeting line. Slamming is to ignore this, and to start sending immediately.
FEATURE(`greet_pause', `2000')dnl
With the above feature, Sendmail can be configured to delay the sending of this greeting. The value is in milliseconds, so in the example above, the greeting-pause would be two seconds. A client issuing the HELO/EHLO during this pause will cause Sendmail to answer with
554 smtp.nifelhei.info not accepting messages
and the greeting will not be send. Sendmail will log such attempts with a message like
rejecting messages from  due to pre-greeting traffic.
and terminate the connection.
You can use the access.db again to define host-specific greeting-pause times, or to exclude certain hosts from the pause. The following example would exclude localhost from the delay. You can use this to whitelist smtp-servers who do slamming but are otherwise "friendly".
GreetPause:localhost                    0
GreetPause:localhost.localdomain        0
GreetPause:                    0
Please note:
RFC 2821 specifies 5 minutes as the maximum timeout for the initial connection greeting. Therefore, if you specify a time longer than 300000 milliseconds (i.e. 5 minutes), sendmail will not wait longer than 5 minutes, to maintain RFC compliance.


After setting up the controlling mechanisms for incoming connections, there is a another level of control that can be applied. Many spammers try to send a single mail with hundreds of recipients. This is also known as "recipient flooding". Sendmail can be configured to limit the number of recipients a message may have, as well throttling down all those clients who try to add more recipient than a certain threshold by pausing a hardcoded full second between each accepted recipient. The options are as follows:
define(`confBAD_RCPT_THROTTLE', `2')dnl
define(`confMAX_RCPTS_PER_MESSAGE', `25')dnl
BAD_RCPT_THROTTLE sets the threshold which invokes the one-second-delay. For the example above this means that with the third RCPT TO: sendmail will pause one full second, before sending the response.

MAX_RCPTS_PER_MESSAGE limits the absolute maximum number of recipients for each message to the value given (25 for the above example). Every RCPT TO: exceeding this number will be rejected with an appropriate message. The standard-compliant server will collect the rejected RCPT TOs and requeue the message for all yet outstanding recipients. (Yes, spammers won't.)


Sendmail, in order to get as many as possible mails through, has very generous timeout-defaults. These values are often measured in days, where today seconds or minutes would suffice. Long timeouts mean long bound resources for probably unsolicited connections. I have defined much shorter values for several timeouts:
define(`confTO_INITIAL', `30s')dnl
define(`confTO_CONNECT', `30s')dnl
define(`confTO_ACONNECT', `1m')dnl
define(`confTO_ICONNECT', `30s')dnl
define(`confTO_HELO', `30s')dnl
define(`confTO_MAIL', `30s')dnl
define(`confTO_RCPT', `30s')dnl
define(`confTO_DATAINIT', `1m')dnl
define(`confTO_DATABLOCK', `1m')dnl
define(`confTO_DATAFINAL', `1m')dnl
define(`confTO_RSET', `30s')dnl
define(`confTO_QUIT', `30s')dnl
define(`confTO_MISC', `30s')dnl
define(`confTO_COMMAND', `30s')dnl
define(`confTO_CONTROL', `30s')dnl
define(`confTO_LHLO', `30s')dnl
define(`confTO_AUTH', `30s')dnl
define(`confTO_STARTTLS', `30s')dnl
I won't go into much detail about each timeout, because that would be beyond the scope of this posting, but these values are much more reasonable than the defaults.

Other means of protecting your server agains spammers:


Besides everything sendmail can be configured to do and not to do, sendmail has another advantage: It can be compiled to use TCP Wrapper.
While scanning the logs for the causes of the astronomous load, I noticed millions of attempts from hosts of dial-in providers, which usually strongly indicates spam-bot afflicted private hosts.
I have added theses networks to my /etc/hosts.deny file, with the effect that the number of connections to the server was reduced almost immediately. While one might ask for the wisdom of blocking whole networks, think about this: by what necessity does a private dial-in host have to have its own smtp-server attempting to connect to your smtp-server? Usually, a private person can use the mail-server of his/her provider,  and that one won't be blocked, because I am blocking the dial-in-subnets specifically.
Here is the current (March 29, 2009) list of blocked networks:
sendmail: .adsl.alicedsl.de
sendmail: .tukw.qwest.net
sendmail: .internetdsl.tpnet.pl
sendmail: .dynamicIP.rima-tde.net
sendmail: .staticIP.rima-tde.net
sendmail: .home.otenet.gr
sendmail: .pppoe.mtu-net.ru
sendmail: .static.link.com.eg
sendmail: .adsl-1.sezampro.yu
sendmail: .speedy.telkom.net.id
sendmail: .pool.ukrtel.net
sendmail: .taiwanmobile.net
sendmail: .veloxzone.com.br
sendmail: .bielskpodlaski.mm.pl
sendmail: .bb-static.vsnl.net.in
sendmail: .dynamic.163data.com.cn
sendmail: .vsnl.net.in
sendmail: .adsl.tpnet.pl
sendmail: .airtelbroadband.in
sendmail: .ip.adsl.hu
sendmail: .tktelekom.pl
sendmail: .radiocom.ro
sendmail: .static.asianet.co.th
sendmail: .static.versatel.nl
sendmail: .dsl.telesp.net.br
sendmail: .cable.telstraclear.net
sendmail: .bb.netvision.net.il
sendmail: .ip.fastwebnet.it
sendmail: .pppoe.avangarddsl.ru
sendmail: .adsl.proxad.net
sendmail: .adsl.sta.mcn.ru
sendmail: .adsl.paltel.net
sendmail: .iam.net.ma
sendmail: .mobile.playmobile.pl
sendmail: .broadband3.iol.cz
sendmail: .business.telecomitalia.it
sendmail: .sonora.tx.cebridge.net
sendmail: .3g.claro.net.br
sendmail: .wi.res.rr.com
sendmail: .mtnl.net.in
sendmail: .static.gvt.net.br
sendmail: .dynamic.orange.es
sendmail: .ttnet.net.tr
sendmail: .ip.cybergrota.com.pl
sendmail: .static.user.ono.com
sendmail: .dsl.brasiltelecom.net.br
sendmail: .bk21-dsl.surnet.cl


After changing the configuration using the above described possibilities, the load of the sever decreased enormously, and there are far less sendmail-processes now running at the same time, thus binding far less resources. DDoS-spam-attacks are still not impossible, but they will have a harder time to get the machine down now.


sendmail limit connections

Whenever a sendmail receives SMTP request and connection from a remote host, it spawn’s a new copy of itself to deal with incoming mail messages. This approach makes it useful for sendmail to process multiple incoming mails simultaneously. However, the nature of linux application always comes with a trade off thing. This issue of spawning another sendmail daemon child would consume another portion of system and thus could hogged down your email server.
Considering the openness of email address nature, an email bomber could launch a malicious flood attack to an email server with bunch of emails for delivery that could easily be done automatically using automated software. This scenario could cause sendmail denial of service.
The below sendmail directives option could restrict and limit the number of sendmail children to spawn, limit the number of connections to receive per second, restrict sendmail process incoming header size, and lastly, limit the maximum acceptable size of one message. By setting this sendmail directive, the effectiveness of such denial of sevice attack to sendmail could be limited and/or delayed.

Sendmail Directives

This is number of connections sendmail server can receive per second. By default rpm installation, Sendmail does not limit the number of connections per second it can receive. If the value configured here is set and reached, any further connections are then delayed.

This is the number of child processes that can be spawned by the server, or refers to sendmail children. By default rpm installation, Sendmail does not define a limit to the number of spawned child daemon. If this limit is reached, further connections are also delayed.

This is the minimum number of free blocks is available for sendmail server when accepting mails. The default is 100 blocks. Once the value specified with this sendmail directive is reached, sendmail is instructed to stop accepting mails.

This is the maximum acceptable size (in bytes) of an email’s message header. Any email message headers that reached this limit would not be accepted and denied from being queued for delivery.


Limiting the the maximum acceptable size (in bytes) of an email message could also limit the possible attachment bomb attack against sendmail server. Implementing a maximum message size could set a limit to email message maximum size. An example sendmail.mc entry would likely be\

This is the number of recipients per message. Limiting the maximum recipient one email message could have could restrict any email bomber trying to send an email to multiple recipients.
A sample entry of the above directive would be
define(`confMAX_DAEMON_CHILDREN’, 10)
define(`confMAX_HEADERS_LENGTH’, `32768′)
define(`confMAX_MESSAGE_SIZE’, 10000000)
define(`confMAXRCPTSPERMESSAGE’, `30′)
To implement the above sendmail directive, simply backup and modify your /etc/mail/sendmail.mc and recompile it again. For the changes to take effect, simply restart your sendmail service like so
# vi /etc/mail/sendmail.mc
# m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
# service sendmail restart
All is done.


Help My Mail Server Is Being DoSsed

The recent flood of spam, viruses and trojaned Windows machines has brought a dramatic increase in attacks on e-mail servers, including (but not limited to) denial-of-service (DoS) attacks, distributed denial-of-service (DDoS) attacks, Joe Jobs, dictionary attacks, slamming, and other assorted nuisances. This document describes some sendmail facilities–many of them new in version 8.13–that can help foil these attacks.
1. Limiting the Rate of Incoming Connections

1.1. The ratecontrol Feature

Version 8.13.0 of Sendmail introduced the ratecontrol feature, which uses the access database to limit the number of incoming connections a single server, group of servers or all unspecified (”wildcard”) servers can make to your server per minute. When an incoming server exceeds those limits, sendmail returns a temporary failure, causing the (standards compliant) incoming server to queue the mail and retry delivery later.
The “per minute” connection rate window is configurable. If, as you configure the ratecontrol feature, you decide that you want to change the connection rate window, add the following to your sendmail macro configuration (mc) file:
where secs is an integer that specifies the number of seconds you want in the window.
The ratecontrol feature declaration must follow the access db declaration (somewhere) in your sendmail mc file:
FEATURE(`access_db')dnl FEATURE(`ratecontrol', ,`terminate')dnl
If your existing configuration uses the delay_checks feature to whitelist recipients (for example), you must tell the ratecontrol feature not to delay those checks, by specifying “nodelay” as the second argument to the ratecontrol feature:
FEATURE(`access_db')dnl FEATURE(`delay_checks',`friend')dnl FEATURE(`ratecontrol', `nodelay',`terminate')dnl
The delay_checks feature is outside the scope of this document. See the cf/README file (in the sendmail distribution) or section 7.5.6 of the Bat Book.
The third argument (”terminate”, above) causes sendmail to immediately terminate an excessive incoming connection with a 421 status code. If you omit the third argument (declaring the feature something like FEATURE(`ratecontrol’), for example), sendmail will issue a 452 status, which leaves it up to the incoming mail server to issue an SMTP QUIT. If you omit “terminate”, an unfriendly incoming server can continue to issue (failing) SMTP commands–probably not what you want to have happen.
After modifying your mc file, generate and install a new sendmail.cf file and restart sendmail.
The method of generating a sendmail.cf varies from platform to platform. This link describes how to do it on FreeBSD. To restart sendmail on FreeBSD, enter the commands:
# cd /etc/mail # make restart
After modifying sendmail.cf and restarting sendmail, edit /etc/mail/access (or wherever your distribution stores the source for the access database) and add entries something like the following:
ClientRate: 2 ClientRate: 0 ClientRate: 10 ClientRate:10.3.4 2
The above limits incoming server to two connections per minute, localhost is unlimited, each individual host in the subnet 10.3.4 can have at most 2 connections per minute, and any other host can have up to 10 connections per minute
Note about mail clients that relay mail through the server. Remote e-mail clients that (legitimately, using SMTP AUTH, for example) relay mail through the server are subject to the ClientRate settings in access db. In the above example, if the “wildcard” is changed from 10 to 1, and a client not matched by other ClientRate: entries attempts to send more than one e-mail in a minute’s time, all but the first e-mail will fail. … So be aware of your clients that use your server as their outgoing SMTP server as you configure ratecontrol in the access database.
After editing the access source file, regenerate access db with something like:
# cd /etc/mail # makemap hash access < access
On FreeBSD, you can generate access.db with the simpler
# cd /etc/mail # make

1.2. The Connection Rate Throttle

There are times when the ratecontrol feature might not give adequate protection. In a distributed denial-of-service (DDoS) attack, for example, an “army” of attacking servers individually limited to as few as 1 connection per minute might collectively overwhelm sendmail. The ConnectionRateThrottle causes sendmail to accept no more than a specified number of new connections per second.
If (for example) you set the ConnectionRateThrottle at 3, and 9 incoming connections arrive simultaneously, sendmail will handle the first three during the first second, the second three during the second second, and the third three during the third second. Connections that exceed the specified ConnectionRateThrottle are forced to wait their turn.
To set the ConnectionRateThrottle, insert the following in your sendmail mc file:
define(`confCONNECTION_RATE_THROTTLE', `num')dnl
where num is a positive integer.
If you specify a value or 0 or a negative integer–or omit the line completely–then sendmail will not enforce a connection rate throttle.

2. Limiting Simultaneous Connections with the conncontrol Feature
Limiting the rate of incoming connections alone might not protect your server from a DoS attack. In order to ensure that the “mail will go through,” sendmail’s default timeout values for each phase of a mail transaction are very generous (in keeping with values recommended by Internet standards documents). As a result, it is conceivable (in fact not uncommon) for a single envelope delivery to take well over an hour. Unless prevented from doing so, malevolent attackers can slowly accumulate connections to your server, causing it to exhaust its resources.
Fortunately, sendmail 8.13 introduced the conncontrol feature to limit the number of simultaneous connections a single server can maintain with your server.
If you’ve read and understood the ratecontrol feature (above), conncontrol will seem familiar. Begin by editing your sendmail mc file. The conncontrol feature declaration must com after the access db declaration in the mc file:
FEATURE(`access_db')dnl FEATURE(`conncontrol', ,`terminate')dnl
If your existing configuration uses the delay_checks feature to whitelist recipients (for example), you must tell the conncontrol feature not to delay those checks, by specifying “nodelay” as the second argument to the conncontrol feature:
FEATURE(`access_db')dnl FEATURE(`delay_checks',`friend')dnl FEATURE(`conncontrol', `nodelay',`terminate')dnl
The delay_checks feature is outside the scope of this document. See the cf/README file (in the sendmail distribution) or section 7.5.6 of the Bat Book.
As with ratecontrol, conncontrol’s third (”terminate”) argument causes sendmail to immediately terminate an excessive incoming connection with a 421 status code. If you omit the third argument (declaring the feature something like FEATURE(`conncontrol’), for example), sendmail will issue a 452 status, which leaves it up to the incoming mail server to issue an SMTP QUIT and break the connection(!). If you omit “terminate”, an unfriendly incoming server can continue to issue (failing) SMTP commands–holding the connection open!! (definitely not what you want to happen).
After modifying sendmail.cf and restarting sendmail, add ClientConn: entries to the access db. For example:
ClientConn: 2 ClientConn: 0 ClientConn: 10 ClientConn:10.3.4 2
will limit incoming server to a maximum of two simultaneous connections, allow localhost to have unlimited connections, limit each host in the subnet 10.3.4 to two simultaneous connections, and any other individual host can have up to 10 simultaneous connections.
After adding ClientConn-tagged entries to access source file, regenerate access.db.

3. Thwarting Dictionary Attacks
In a typical dictionary attack, the attacking server sends a single message to a list of well-known or “promising” e-mail addresses at the target domain. After exchanging greetings and issuing the MAIL FROM: command to identify the (probably spurious) sender, the attacker issues a series of RCPT TO: commands, something like:
RCPT TO:<info@yourdomain.com> RCPT TO:<sales@yourdomain.com> RCPT TO:<support@yourdomain.com> RCPT TO:<webmaster@yourdomain.com> RCPT TO:<root@yourdomain.com> RCPT TO:<john@yourdomain.com> [more recipients ...] RCPT TO:<mary@yourdomain.com>
After identifying the recipients, the attacker continues the transmission by issuing the DATA command and sending the message headers and body.
Because of the guessing involved, dictionary attacks have sometimes been called Rumpelstiltskin attacks (named after the dwarf in the Grimms’ fairy tale who tells a woman he will not hold her to a promise if she can guess his name–Rumpelstiltskin).

3.1. Limiting the Number of Recipients per Message
At least one major ISP makes dictionary attacks more difficult by limiting the number of RCPT TO: commands allowed in a single incoming “envelope”. You can configure sendmail to impose the limitation by adding the following to your sendmail mc file:
define(`confMAX_RCPTS_PER_MESSAGE', `25')dnl
(substituting your own preferred maximum for the `25′ used above).
If (for example) the maximun is configured at 25 and the sender specifies a 26th recipient, sendmail will respond with
452 4.5.3 Too many recipients
If the sending server ignores the 452 response and continues issuing RCPT TO: commands, the receiving sendmail will send the same response to all remaining RCPT TO: commands. Then, when the sender issues the DATA command and completes the message envelope, the message will be delivered only to the first 10 (in this example) recipients.
The idea here is that RFC-compliant sending servers will detect the temporary failure(s) and queue the message for later delivery to the temporarily rejected recipients. A spammer or trojan will likely never retry the failed recipients.
Caution: Remote mail users that specify your sendmail server as their outgoing SMTP server are subject to the same constraints as incoming SMTP servers that connect to your server: If you limit the maximum recipients to 25 and a user sends a message to 26 users via your sendmail server, sendmail will respond with a (possibly hard-to-understand) temporary failure. You should therefore set the number high enough to accomodate legitimate client senders but low enough to discourage dictionary attackers.

3.2. Reacting to “Bad” Recipients
“Bad” recipients are those that your server doesn’t receive mail for–addresses not listed in virtusertable, aliases, /etc/passwd (or whatever mechanism(s) your server uses for identifying legitimate recipients).
I have heard of some sites that block no mail, but instead route mail for unknown recipients to /dev/null. This seems like a particularly bad idea to me. Not only are spammers and attackers lead to believe that all their mail is being delivered, but legitimate senders that mistype the recipient’s address receive no notification that the e-mail they sent was delivered to the “bit bucket.”
Use of the option described in this section requires that mail to unknown users be rejected during the SMTP conversation.
You can tell sendmail to respond more slowly to the incoming server after a specified number of unknown recipient addresses have been specified, by inserting the following line in your mc file:
If, for example, you specify num as 2, sendmail will respond normally to the first RCPT TO: commands. As soon as 2 unknown users have been identified, sendmail will record the following in the mail log:
Possible SMTP RCPT flood, throttling.
and sleep for one second (hardcoded) after all subsequent RCPT TO: commands.

4. Blocking Slammers with the greet_pause Feature
When an incoming mail server connects to yours, it is supposed to wait for your server’s welcome greeting before commencing the SMTP conversation with the EHLO or HELO command. It is common for attackers and poorly written trojans and viruses to send the EHLO/HELO command without waiting for your server’s greeting. The practice of not waiting for the greeting is called “slamming.”
There are rumors that at least one large ISP’s servers practice slamming. If you identify such an ISP, you can whitelist it in your access database (See below.)
The greet_pause feature (new in sendmail 8.13) causes sendmail to pause for a specified period of time at the beginning of the connection, before returning its greeting. If the incoming server issues the EHLO/HELO command during the pause, then sendmail will issue something like the following
554 mail.whipple.org not accepting messages
instead of the standard greeting
220 mail.whipple.org ESMTP Sendmail 8.13.3/8.13.3; Thu, 3 Mar 2005 18:16:23 GMT
and an entry is written to the mail log:
rejecting commands from 169.sub-166-180-49.myvzw.com [] due to pre-greeting traffic
The following line (inserted in sendmail’s mc file) will cause sendmail to pause a default 700 milliseconds before issuing its greeting:
FEATURE(`greet_pause', `700')dnl
If you omit the second argument (using just FEATURE(`greet_pause’) in the mc file), or if you want to override the default, then you need to add entries to the access database. In the following example
GreetPause:host.domain.com 5000 GreetPause:domain.com 0 GreetPause: 0 GreetPause:192.168.120 5000
the first and last lines will force a greet pause of 5 seconds (5000 milliseconds); the second and third lines tell sendmail not to wait at all.
All other connecting hosts (or domains or addresses or networks) will have to wait the default time specified as the second argument to the FEATURE macro. (If the second argument was omitted from the FEATURE macro, hosts that don’t match any access db GreetPause-tagged lines will not have to wait).
RFC 2821 specifies 5 minutes as the maximum timeout for the initial connection greeting. Therefore, if you specify a time longer than 300000 milliseconds (i.e. 5 minutes), sendmail will not wait longer than 5 minutes, to maintain RFC compliance.

5. Other Ways to Protect Your sendmail Server
Strictly speaking, this section is beyond the scope of this document. As you think about protecting your sendmail server, however, you will likely want to consider the following:
* DNS Blacklists. My DNSBL: Configuring Sendmail for DNS-Based Blacklisting is one source of information on the subject. (There are many other good sources.)
Hint: My current favorite DNS blacklist–if I were forced to use only one–is sbl-xbl.spamhaus.org
* Greylisting. The greylisting milter I use on my main mail server is responsible for the rejection of more unwanted mail than any other other filtering mechanism. See Greylisting.org or Google to find more about the greylisting milters available.
* Virus Scanning. I use a combination of ClamAV and Procmail to scan all incoming mail for viruses.
I scan (for viruses and spam) only the mail that gets past my DoS-blocking measures, DNS blacklists, access db entries and greylisting milter. This cuts down on server load required by the relatively CPU-intensive content scanning.
* Spam Filtering. There are many choices for filtering spam. My current favorite is SpamAssassin and (good old) Procmail rules. With SpamAssassin you can scan
1. During the SMTP conversation. The MIMEDefang and spamass-milter milters are popular for scanning at this stage of delivery.
2. During local delivery. Using procmail to scan during local delivery is probably the most common way of using SpamAssassin.
3. When mail is retrieved from one’s mailbox, using a POP proxy.

6. Afterword
I have personally used most of the techniques discussed above, so I know that they work–on my server, at least. If you decide to implement them on your server, be careful to avoid typos. You will probably want to keep a backup copy of your old configuration file in case a rollback is necessary. After configuring any of the features and options described above, be sure to send test messages and monitor the mail logs to make sure that sendmail behaves as expected.




* High Volume Mail

For high volume mail it is necessary to be able to control the load
on the system.  Therefore the 'queue' delivery mode should be used,
and all options related to number of processes and the load should
be set to reasonable values.  It is important not to accept mail
faster than it can be delivered otherwise the system will be
overwhelmed.  Hence RefuseLA should be lower than QueueLA, the number
of daemon children should probably be lower than the number of queue
runnners (MaxChildren vs. MaxQueueChildren).  DelayLA is a new option
in 8.12 which allows delaying connections instead of rejecting them.
This may result in a smoother load distribution depending on how
the mails are submitted to sendmail. 
There are two important settings in the sendmail.mc file:

confQUEUE_LA            QueueLA         [varies] Load average at which
                                         queue-only function kicks in.
                                         Default values is (8 * numproc)
                                         where numproc is the number of
                                         processors online (if that can be
confREFUSE_LA           RefuseLA        [varies] Load average at which
                                         incoming SMTP connections are
                                         refused.  Default values is (12 *
                                         numproc) where numproc is the
                                         number of processors online (if
                                         that can be determined).

On a dedicated mail server, you want to set QueueLA *higher* than
RefuseLA - the other way around will cause your queue to explode when
the load is high (assuming you reach QueueLA of course), you accept lots
of new messages but can't get rid of them as the load average hovers
around RefuseLA - the many messages in the queue drive up disk I/O and
thereby the load average.

The default of QueueLA lower than RefuseLA only makes sense for a server
that does other things besides mail, where you want to reduce the impact
of the mail load on the other functions by queuing instead of delivering
when the load is high.

Your original sendmail.mc file may state:

dnl define(`confQUEUE_LA', `12')dnl
dnl define(`confREFUSE_LA', `18')dnl

I normaly change it to for a web server, that uses sendmail for formmail scripts etc:

dnl define(`confQUEUE_LA', `3')dnl
dnl define(`confREFUSE_LA', `6')dnl

You will need to remake the config files before restarting the server so the changes 
take effect, to do this run the following command:

make -C /etc/mail

With Redhat make sure you have the "sendmail-cf" packaged installed to do this.








Recipe 10.17 Denying DoS Attacks


You want to limit the possibility that a denial-of-service (DoS) attack aimed at sendmail will cripple other services offered by the sendmail server.


Add confCONNECTION_RATE_THROTTLE and confMAX_DAEMON_CHILDREN defines to the sendmail configuration to set limits on how fast sendmail accepts mail connections and how many concurrent connections are accepted. Here are examples:
dnl Accept up to 10 connections per second
define(`confCONNECTION_RATE_THROTTLE', `10')
dnl Allow no more than 200 concurrent connections
define(`confMAX_DAEMON_CHILDREN', `200')
Following the guidance in Recipe 1.8, build the sendmail.cf file, copy it to /etc/mail/sendmail.cf, and restart sendmail.


A denial-of-service (DoS) attack can overwhelm a server and effectively block useful inbound and outbound mail. For example, a mail-bombing attack delivers so much mail so rapidly to a single target that the target system is unable to keep up with the workload. Worse yet, sendmail can becomes so busy handling the attack, it takes all of the system's resources and thus prevents other useful services from running. This recipe uses two configuration commands that lessen the impact that a DoS attack aimed at sendmail has on its other services.
The confMAX_DAEMON_CHILDREN define sets the maximum number of sendmail processes that this sendmail daemon can run simultaneously. Every system has an upper limit on the number of processes it can effectively handle. A variety of DoS attacks are designed to overwhelm a system by launching so many mail processes that the system is no longer able to do any productive work. The confMAX_DAEMON_CHILDREN define protects the operating system from this type of attack.
By default, sendmail sets no upper limit on the number of child processes that can be launched to process mail. This recipe limits sendmail to 200 children so that sendmail accepts mail only when fewer than 200 children are running. This is not a recommended value; it is just an example. Study the actual usage patterns of your system before you select a value, and then set the value at least 50 percent above the observed value to allow for usage spikes.
confMAX_DAEMON_CHILDREN is most useful for systems that do more than just provide sendmail service. A good example is a general purpose server that has a relatively light email workload and that provides many other important user services. The confMAX_DAEMON_CHILDREN define protects the other services from runaway sendmail daemons. It makes sure that the user can still open an X window or start an editor even if the sendmail server is under attack. confMAX_DAEMON_CHILDREN provides this protection for the other services at the cost of making it simple for the attacker to shut down mail service. Simply sending enough mail to exceed the maximum number of children shuts down the SMTP port. Use this define carefully.
The confCONNECTION_RATE_THROTTLE define sets the maximum number of SMTP connections that are permitted for any one-second period. Like confMAX_DAEMON_CHILDREN, the confCONNECTION_RATE_THROTTLE command protects the server from being overwhelmed by email. Neither of these defines protects sendmail from attack; they both protect the system when sendmail is under attack.
By default, no limit is set on the rate at which new SMTP connections are accepted. sendmail handles connections as fast as they arrive. This recipe limits sendmail to 10 new connections per second so that sendmail rejects any network connections after the first 10 in any 1-second period. As before, this is not a recommended value; it is just an example. Study the actual usage patterns of your system before you select a value, and then set the value at least 50 percent above the observed value to allow for usage spikes.
Often, confCONNECTION_RATE_THROTTLE and confMAX_DAEMON_CHILDREN are used together. confMAX_DAEMON_CHILDREN sets an upper limit on the number of simultaneous email connections and confCONNECTION_RATE_THROTTLE sets the rate at which the system climbs to that maximum. An attacker can easily overrun the connection rate you set in order to deny mail access. However, setting the rate protects the other services on the system so that the system remains operational to help you deal with the attack.
It is impossible to completely protect sendmail from denial-of-service attacks. Limiting the amount of damage done by the attack is the real purpose of the defines used in this recipe, which is really meant to protect the system as a whole.

See Also

The sendmail book covers the confCONNECTION_RATE_THROTTLE define in Section 24.9.21 and the confMAX_DAEMON_CHILDREN define in Section 24.9.60.