Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Patches to add option BadRcptKill

14 views
Skip to first unread message

Thomas Schulz

unread,
Dec 14, 2005, 4:40:00 PM12/14/05
to
Following is a set of patches against sendmail-8.13.5 to add an option
BadRcptKill. I have sent this to the Sendmail people, but I thought
that I should also post it here as I think I remember someone wanting
something like this.

The motivation for this is that we recently had a very large number of
external machines doing address harvesting. The BadRcptThrottle option
just made this worse as we were saturated at the maximun number of children
and the connections lasted for several hours. I started to manually kill
off processes that were in cmd read for over an hour and they were
immediately replaced by other connections sitting in cmd read. I made a
quick hack to replace the sleep in BadRcptThrottle with an exit and the
connections were now being dropped in a few seconds to a minute. With this
change, the number of connections dropped below the limit and we were able
to get the mail through.

The following is my attempt at the proper way to implement this.

*** sendmail/sendmail.h Thu Jun 23 19:11:22 2005
--- sendmail/sendmail.h Mon Dec 12 20:12:19 2005
***************
*** 2191,2196 ****
--- 2191,2197 ----
EXTERN char OpMode; /* operation mode, see below */
EXTERN char SpaceSub; /* substitution for <lwsp> */
EXTERN int BadRcptThrottle; /* Throttle rejected RCPTs per SMTP message */
+ EXTERN int BadRcptKill; /* Kill connection if too many rejected RCPTs */
EXTERN int CheckpointInterval; /* queue file checkpoint interval */
EXTERN int ConfigLevel; /* config file level */
EXTERN int ConnRateThrottle; /* throttle for SMTP connection rate */
*** sendmail/readcf.c Sun Sep 4 02:15:15 2005
--- sendmail/readcf.c Tue Dec 13 11:59:39 2005
***************
*** 2191,2196 ****
--- 2191,2198 ----
# define O_HELONAME 0xd8
{ "HeloName", O_HELONAME, OI_NONE },
#endif /* _FFR_HELONAME */
+ #define O_RCPTKILL 0xd9
+ { "BadRcptKill", O_RCPTKILL, OI_NONE },

{ NULL, '\0', OI_NONE }
};
***************
*** 3711,3716 ****
--- 3713,3722 ----
break;
#endif /* _FFR_HELONAME */

+ case O_RCPTKILL:
+ BadRcptKill = atoi(val);
+ break;
+
default:
if (tTd(37, 1))
{
*** sendmail/srvrsmtp.c Tue Jun 14 19:33:21 2005
--- sendmail/srvrsmtp.c Tue Dec 13 16:11:48 2005
***************
*** 117,122 ****
--- 117,137 ----
macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
} while (0)

+ #define BADRCPTSEXIT \
+ do \
+ if (BadRcptKill > 0 && \
+ (BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \
+ ? n_badrcpts - 1 : n_badrcpts) >= BadRcptKill) \
+ { \
+ if (LogLevel > 5) \
+ { \
+ sm_syslog(LOG_INFO, e->e_id, \
+ "%s: Possible SMTP RCPT flood, exiting.", \
+ CurSmtpClient); \
+ } \
+ (void) exit(0); \
+ } while (0)
+
#define SKIP_SPACE(s) while (isascii(*s) && isspace(*s)) \
(s)++

***************
*** 2671,2676 ****
--- 2686,2692 ----
if (Errors > 0)
{
++n_badrcpts;
+ BADRCPTSEXIT;
NBADRCPTS;
}
}
***************
*** 2679,2684 ****
--- 2695,2701 ----
/* An exception occurred while processing RCPT */
e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
++n_badrcpts;
+ BADRCPTSEXIT;
NBADRCPTS;
}
SM_END_TRY
*** cf/README Fri Sep 16 16:18:14 2005
--- cf/README Wed Dec 14 11:30:43 2005
***************
*** 4061,4066 ****
--- 4061,4071 ----
transaction have been rejected, sleep
for one second after each subsequent
RCPT command in that transaction.
+ confBAD_RCPT_KILL BadRcptKill [infinite] If set and the specified
+ number of recipients in a single SMTP
+ transaction have been rejected, assume
+ a hostile sender and drop the
+ connection.
confDONT_PROBE_INTERFACES DontProbeInterfaces
[False] If set, sendmail will _not_
insert the names and addresses of any
*** cf/m4/proto.m4 Wed Aug 24 14:07:23 2005
--- cf/m4/proto.m4 Wed Dec 14 10:43:50 2005
***************
*** 578,583 ****
--- 578,587 ----
# once the threshold number of recipients have been rejected
_OPTION(BadRcptThrottle, `confBAD_RCPT_THROTTLE', `0')

+ # once the threshold number of recipients have been rejected
+ # assume a hostile sender and drop the connection
+ _OPTION(BadRcptKill, `confBAD_RCPT_KILL', `0')
+
# shall we get local names from our installed interfaces?
_OPTION(DontProbeInterfaces, `confDONT_PROBE_INTERFACES', `False')

*** doc/op/op.me Fri Sep 16 16:40:14 2005
--- doc/op/op.me Wed Dec 14 13:13:23 2005
***************
*** 6499,6504 ****
--- 6499,6509 ----
If set and the specified number of recipients in a single SMTP
transaction have been rejected, sleep for one second after each subsequent
RCPT command in that transaction.
+ .ip BadRcptKill=\fIN\fP
+ [no short name]
+ If set and the specified number of recipients in a single SMTP
+ transaction have been rejected, assume a hostile sender and drop the
+ connection.
.ip BlankSub=\fIc\fP
[B]
Set the blank substitution character to
--
Tom Schulz
sch...@adi.com

ska

unread,
Dec 15, 2005, 5:35:26 AM12/15/05
to
Hey, I like this idea!

Claus Aßmann

unread,
Dec 15, 2005, 12:45:20 PM12/15/05
to
Thomas Schulz wrote:
> Following is a set of patches against sendmail-8.13.5 to add an option
> BadRcptKill. I have sent this to the Sendmail people, but I thought
> that I should also post it here as I think I remember someone wanting
> something like this.

There's a different thread where someone is asking about Dictionary
Attacks.

> The motivation for this is that we recently had a very large number of
> external machines doing address harvesting. The BadRcptThrottle option

The attack came from different machines (e.g., a botnet)?
That is, the connection controls in 8.13 don't help, right?

> just made this worse as we were saturated at the maximun number of children

That's the problem with MaxDaemonChildren. There needs to be a more
sophisticated mechanism combined with connection control, e.g., some
adaptive behavior (if almost all connections are in use, be more
aggressive about timeouts and rejecting "bogus" connections).

> and the connections lasted for several hours. I started to manually kill
> off processes that were in cmd read for over an hour and they were
> immediately replaced by other connections sitting in cmd read. I made a
> quick hack to replace the sleep in BadRcptThrottle with an exit and the

Don't just exit(), return a 421 error (search for "421" and use
the same code to terminate the session).

--
Note: please read the netiquette before posting. I will almost never
reply to top-postings which include a full copy of the previous
article(s) at the end because it's annoying, shows that the poster
is too lazy to trim his article, and it's wasting the time of all readers.

Alex Moore

unread,
Dec 18, 2005, 5:20:42 PM12/18/05
to
On Thu, 15 Dec 2005 17:45:20 +0000, Claus Aßmann wrote:

> Don't just exit(), return a 421 error (search for "421" and use
> the same code to terminate the session).

Would something like work for replacing exit() with a returning a 421
error? Hopefully, the text does not wrap too much.

--- ./sendmail/orig-srvrsmtp.c 2005-06-14 18:33:21.000000000 -0500
+++ ./sendmail/srvrsmtp.c 2005-12-18 16:07:42.250266000 -0600
@@ -117,6 +117,28 @@


macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
} while (0)

+#define BADRCPTSEXIT


+ do
+ if (BadRcptKill > 0 &&
+ (BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle
+ ? n_badrcpts - 1 : n_badrcpts) >= BadRcptKill)
+ {
+ if (LogLevel > 5)
+ {
+ sm_syslog(LOG_INFO, e->e_id,
+ "%s: Possible SMTP RCPT flood, exiting.",
+ CurSmtpClient);
+ }

+ tempfail = true;
+ smtp.sm_milterize = false;
+ message("421 4.7.0 %s closing connection",
+ MyHostName);
+
+ /* arrange to ignore send list */
+ e->e_sendqueue = NULL;
+ goto doquit;


+ } while (0)
+
#define SKIP_SPACE(s) while (isascii(*s) && isspace(*s)) \
(s)++

---
Thanks, Alex

Message has been deleted

Alex Moore

unread,
Dec 18, 2005, 8:33:37 PM12/18/05
to
On Sun, 18 Dec 2005 23:02:07 +0000, D. Stussy wrote:

> RE: The 421 error line
>
> Extended code "4.7.0"? Not "4.7.1" (policy reasons) or "4.5.3" (too many
> recipients - in this case, bad recipients) - though my preference is for
> "4.7.1" in this case?

Yes, 4.7.1 is more appropriate. However, this code does not compile. I
added the backslash to the end of the lines, but I still have something
wrong.

Thanks, Alex

jma...@ttec.com

unread,
Dec 23, 2005, 8:40:27 AM12/23/05
to
I have a patch that does something pretty much exactly like that

http://www.jmaimon.com/sendmail/patches/badrcpt_shutdown.v1.81301.patch
http://www.jmaimon.com/sendmail/

Works pretty good.

Alex Moore

unread,
Dec 25, 2005, 6:02:43 PM12/25/05
to

Thanks for posting this.

Alex

0 new messages