[Raw Msg Headers][Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Anti-spamming (was Re: Huge amounts of resources)



On Fri, 4 Apr 1997, Matti Aarnio wrote:
> > Also some docs about new features (like filterings spam) would
> > be nice.
> 
> 	Filtering of spams is not yet available (aside of Gabor Kiss'
> 	solution).

I made the following changes to the 2.99.38 smtpserver for a WSP who has had
increasing problems with spammers using their machines as spam exploders.
Believe it or not, to add insult to injury, spammers were using them to send
spam selling spam mail software for windoze PC's!  Argh!

That meta-spam did it for me and I started to work...

I (ahem) would, of course, never suggest that you run such a modified SMTP
server in real production use. :-)

The changes do three things:

	- after 5 RCPT commands, sleep 5 minutes * numrecipients before
		ACking RCPT commands

	- after MAIL command, if there were more than 19 recipients
		specified, silently drop the spam on the floor - but only
		after wasting hours accepting their huge long recipient list

	- after 5 RSET commands in a single session, use the same sleeping
		strategy as above

I believe that the first and third change are actually "legal" since they
simply make the SMTP server respond slowly.  The second is definitely not
legal, but my client wasn't really concerned - they're a WSP, and they don't
have to allow large volume mailings.  Or just pretend it's a broken M$-MAIL
gateway and blame M$... :-)

The idea is to recognize behavior patterns of common spamming methodologies
and to react, making it very unprofitable to use this SMTP server as an
exploder.  It will take approximately 7.5 hrs to submit mail to 20
recipients.  At 100 recipients (quick calculation: about 8*10**146 hours
later) each RCPT is resulting in an 8 hr wait.  Needless to say, this will
not appeal to a spammer as a high-performance delivery method. :-) It also
prevents that spammer from loading down your system by hammering it with
their drivel.

These changes combat two types of spammers we were seeing - those that send
a single message to N (20 to 1000) addresses, and those that send N (20 to
10000) identical and individually addressed messages in a single SMTP
session/connection.

The second type of spamming appeared after we made the recipient counting
change (which actually surprised me - they actually adapted their methods in
two days - scary), necessitating the RSET counter.  I'm sure we'll soon have
to add a simple database to track abusers and stop them.

I'm just providing this as an example of the horrid gruesome hacks you can
use to combat spammers.  I reiterate that I do not recommend the use of this
code on a production server.  No, certainly not... that would be
irresponsible...

Context diff for 2.99.38 smtpserver/smtpserver.c below, though you might be
able to apply it against more recent versions.

Attached below that is a simple shell script (we call it show_senders) that
will perform a crude scan for the biggest senders (by msg count - not
recipient count) on your router log.  Edit it to change the router log
location to that for your system before test-driving it.  It's crude and
dumb, but it will give you an idea what's going on.  Attached below it is
sample output from one of our systems early in the day (before the numbers
get too big).  Before I modified the smtpserver, we used to see numbers like
4160 for certain bogus spamming addresses in the output of this shell
script... now they're not there at all.  Success!

-Andy

PS - These smtpserver changes also give you leisurely *hours* to track down
the offending spammer's ISP and catch the offender red-handed if you're so
inclined...

==============================================================================

*** smtpserver.c.orig	Tue Apr  1 00:12:51 1997
--- smtpserver.c	Fri Apr  4 13:40:10 1997
***************
*** 191,196 ****
--- 191,197 ----
  int	pid, routerpid;
  FILE	*logfp = NULL;
  int	D_alloc = 0;
+ int	ResetsSeen = 0;
  
  static char *m200 = "2.0.0";
  static char *m400 = "4.0.0";
***************
*** 702,707 ****
--- 703,711 ----
  		if (msgfd > 1)
  		  close(msgfd);
  
+ 		/* anti-spamming measure - ASP/MSI */
+ 		ResetsSeen = 0;
+ 
  		smtpserver(1);
  		if (routerpid > 0)
  		  killr(routerpid);
***************
*** 1400,1413 ****
  	} else if (sizeoptsum > availspace) {
  	  type(452, "4.3.1", "insufficient storage space, try again later");
  	} else if (s) {
! 	  type(atoi(s), s+4, "Ok", "Ok");
! 	  ++rcpt_count;
  	} else {
! 	  if (sizeoptval)
! 	    type(250, "2.1.5", "Ok; can accomodate %d byte message",sizeoptval);
  	  else
! 	    type(250, "2.1.5", (char *)NULL);
! 	  ++rcpt_count;
  	}
  	if (s)
  	  free(s);
--- 1404,1440 ----
  	} else if (sizeoptsum > availspace) {
  	  type(452, "4.3.1", "insufficient storage space, try again later");
  	} else if (s) {
! 	  /* anti-spamming measures - ASP/MSI */
! 	  if (rcpt_count >= 4)
! 	  {
! 		if (rcpt_count++ > 4)
! 			sleep(rcpt_count * 5 * 60);	/* sleep 5 minutes * numrecipients */
! 		type(atoi(s), s+4, "Ok spammer... now go away", "Ok spammer... now go away");
! 	  }
! 	  else
! 	  {
! 		type(atoi(s), s+4, "Ok", "Ok");
! 		++rcpt_count;
! 	  }
  	} else {
! 	  /* anti-spamming measures - ASP/MSI */
! 	  if (rcpt_count >= 4)
! 	  {
! 		if (rcpt_count++ > 4)
! 			sleep(rcpt_count * 5 * 60);	/* sleep 5 minutes * numrecipients */
! 		if (sizeoptval)
! 			type(250, "2.1.5", "Ok spammer... now go away; can accomodate %d byte message",sizeoptval);
! 		else
! 			type(250, "2.1.5", "Ok spammer... now go away");
! 	  }
  	  else
! 	  {
! 		if (sizeoptval)
! 			type(250, "2.1.5", "Ok; can accomodate %d byte message",sizeoptval);
! 		else
! 			type(250, "2.1.5", (char *)NULL);
! 		++rcpt_count;
! 	  }
  	}
  	if (s)
  	  free(s);
***************
*** 1522,1527 ****
--- 1549,1565 ----
  	  mfp = NULL;
  	  type(552, "5.3.4", "Message size exceeded fixed maximum size for acceptable email");
  	  fflush(stdout);
+ 	} else if (rcpt_count >= 19) {
+ 		/* anti-spamming measure - ASP/MSI */
+ 		mail_abort(mfp);
+ 		mfp = NULL;
+ #ifdef LOG_INFO
+ 		syslog(LOG_INFO, 
+ 		       "pretended to accept (but silently dropped) spam (%drecipients>19) from %s:%d",
+ 		       rcpt_count, rhostname, rport);
+ #endif
+ 		type(250, "2.6.0", "I thought I told you to go away...");
+ 		fflush(stdout);
  	} else if (mail_close(mfp) == EOF) {
  	  type(452,m430,(char *)NULL);
  	  fflush(stdout);
***************
*** 1923,1928 ****
--- 1961,1975 ----
  		if (mfp != NULL) {
  		  mail_abort(mfp);
  		  mfp = NULL;
+ 		}
+ 		/* anti-spamming measure - ASP/MSI */
+ 		if (++ResetsSeen > 4)
+ 		{
+ #ifdef LOG_INFO
+ 			syslog(LOG_INFO, "multiple (%d) RSET cmds in one session from %s:%d",
+ 			       ResetsSeen, rhostname, rport);
+ #endif
+ 			sleep(5 * 60 * ResetsSeen);
  		}
  		if (state != Hello)
  		  state = MailOrHello;


==============================================================================

#!/bin/sh

nawk '
($2 == "file:") {
        x = 4;
        while ( $x != "=>" && x < 20)
        {
                printf ("%s ", $x);
                x++;
        }
        printf ("\n");
}
' < /var/adm/mail/router \
| sort | uniq -c | sort -rn | head -23


==============================================================================

  68 owner-freebsd-questions@freefall.freebsd.org 
  66 MailProcessor@lasergo.com 
  49 <zvi@creditnet.com> 
  48 <undcom@undcom.com> 
  48 <70741.3507@CompuServe.COM> 
  34 staff@quote.com 
  34 <staff@quote.com> 
  34 <owner-freebsd-questions@freefall.freebsd.org> 
  33 <MailProcessor@lasergo.com> 
  23 owner-year2000-discuss@year2000.com 
  23 <owner-year2000-discuss@year2000.com> 
  21 <admin@stack.com> 
  20 scopus-users-owner@gateway.scopus.com 
  19 rmoore@fourthtier.com 
  19 Stephen Oskoui <websol> 
  16 otle@chat.carleton.ca 
  16 communicate@jit.com 
  15 error 
  15 London Virtual Mall <lvm> 
  14 webmaster-l-owner@cybercorp.net 
  14 philhbh@fourthtier.com 
  14 cte@rammaps.com 
  14 <webmaster-l-owner@cybercorp.net>