On Wed, 19 Mar 2003 08:09 am, Rasjid Wilcox wrote:
>
> Another possible way to deal with this is the way that MessageWall catches
> these ones (http://www.messagewall.org/features.html#errors).  Namely, to
> disconnect any client that issues a threshold level of invalid commands. 
> It should not be hard to put in a 'invalid command' hook, and write a
> plugin based on that.

A bit later than expected, but here it is.

Currently it simply keeps a tally of the number of unrecognised commands, and 
closes the connection if the threshold is reached.  (Defaults to 4, but can 
be changed in the config/plugins entry calling the plugin.)

I have never seem more than one unrecognized command from a valid sender (and 
that may have been me testing something with telnet... not sure) so I think a 
default threshold of 4 is probalby okay.  However, all of the 'HTTP' sent 
spam in my logs triggers 6 unrecognized commands, so if someone is certain 
what the minimun number of http headers is (ie, how many bad commands will be 
triggered) the default could be set to that.

NOTE: I have not tested this very much, so please test it yourself before 
putting into a production server.

Cheers,

Rasjid.
--- SMTP.pm.orig	2003-03-25 21:52:54.000000000 +1100
+++ SMTP.pm	2003-03-25 21:58:30.000000000 +1100
@@ -46,8 +46,16 @@
   #$self->respond(553, $state{dnsbl_blocked}), return 1
   #  if $state{dnsbl_blocked} and ($cmd eq "rcpt");
 
-  $self->respond(500, "Unrecognized command"), return 1
-    if ($cmd !~ /^(\w{1,12})$/ or !exists $self->{_commands}->{$1});
+  if ($cmd !~ /^(\w{1,12})$/ or !exists $self->{_commands}->{$1}) {
+    my ($rc, $msg) = $self->run_hooks("unrec_cmd", $cmd);
+    if ($rc == DENY) {
+      $self->respond(421, $msg);
+      $self->disconnect;
+    } else {
+      $self->respond(500, "Unrecognized command");
+    }
+    return 1
+  }
   $cmd = $1;
 
   if (1 or $self->{_commands}->{$cmd} and $self->can($cmd)) {
sub register {
  my ($self, $qp, @args) = @_;
  $self->register_hook("unrec_cmd", "check_unrec_cmd");

  if (@args > 0) {
    $self->{_unrec_cmd_max} = $args[0];
    $self->log(1, "WARNING: Ignoring additional arguments.") if (@args > 1);
  } else {
    $self->{_unrec_cmd_max} = 4;
  }

  $self->{_unrec_cmd_count} = 0;
}

sub check_unrec_cmd {
  my ($self, $transaction, $cmd) = @_;
  
  $self->log(5, "Unrecognized cmd '$cmd'");

  $self->{_unrec_cmd_count}++;

  my $badcmdcount = $self->{_unrec_cmd_count};

  if ($badcmdcount >= $self->{_unrec_cmd_max}) {
    $self->log(5, "Closing connection. Too many unrecognized commands.");
    return (DENY, "Closing connection. $badcmdcount unrecognized commands.  Perhaps 
you should read RFC 821 etc.");
  }

  return DECLINED;
}

Reply via email to