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;
}