Help! My Mail Server Is Being DoSsed!

By Weldon Whipple <weldon@whipple.org>


Contents


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:

define(`confCONNECTION_RATE_WINDOW_SIZE',`secs')dnl
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:192.168.2.3		2
ClientRate:127.0.0.1		0
ClientRate:			10
ClientRate:10.3.4		2
The above limits incoming server 192.168.2.3 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:192.168.2.3          2
ClientConn:127.0.0.1            0
ClientConn:                     10
ClientConn:10.3.4               2
will limit incoming server 192.168.2.3 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:


define(`confBAD_RCPT_THROTTLE',`num')dnl
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 [166.180.49.169] 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:127.0.0.1		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:

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.

Feel free to report errors or omissions, or to suggest additions. Good luck!