On Mon, 5 Jul 2004 08:29:37 +0100 Matt Sergeant <[EMAIL PROTECTED]> wrote: > On 4 Jul 2004, at 20:37, Devin Carraway wrote: > > On Sun, Jul 04, 2004 at 07:40:51PM +0100, Mark Powell wrote: > >> Had some dialup joker today, opening 45 smtp connections and > >doing> nothing on them, but a NOOP every 30s. Four hours later they > >were all> still there, until I killed them and blocked the IP. > >> Can we have the possibility of a noop handler, so a plugin could > >> prevent > >> this? > > > > Hm. While we might as well have a no-op hook, the attacker could > > have staged the same sort of attack with a gradual cycle of > > mail/rcpt/rset commands. A better countermeasure for this one would > > be a per-client max-connections limit. Won't do much against a > > zombie attack, but it'd deal with this sort. > > http://linux.voyager.hr/ucspi-tcp/tcpserver-limits-2004-03-27.diff This diff adds a MAXCONNIP to qpsmtpd-forkserver. I set the default to my $MAXCONNIP = 5;
Diff is against qpsmtpd-forkserver 0.28 Hanno
--- qpsmtpd-forkserver.orig Mon Jul 5 18:05:23 2004 +++ qpsmtpd-forkserver Mon Jul 5 18:04:39 2004 @@ -20,6 +20,7 @@ my $PORT = 25; # port number my $LOCALADDR = '0.0.0.0'; # ip address to bind to my $USER = 'smtpd'; # user to suid to +my $MAXCONNIP = 5; # max simultaneous connections from one IP delete $ENV{ENV}; $ENV{PATH} = '/bin:/usr/bin:/var/qmail/bin'; @@ -73,10 +74,30 @@ # possible something condition... next; } + my ($port, $iaddr) = sockaddr_in($hisaddr); + if ($MAXCONNIP) { + my $num_conn = 0; + foreach my $rip (values %childstatus) { + if ($rip eq $iaddr) { + ++$num_conn; + } + } + ++$num_conn; # count this connection, too :) + if ($num_conn > $MAXCONNIP) { + my $rem_ip = inet_ntoa($iaddr); + ::log(LOGINFO,"Too many connections from $rem_ip: " + ."$num_conn > $MAXCONNIP. Denying connection."); + $client->autoflush(1); + print $client "451 Sorry, too many connections from $rem_ip, try again later\r\n"; + close $client; + next; + } + } my $pid = fork; if ($pid) { # parent - $childstatus{$pid} = 1; # add to table + $childstatus{$pid} = $iaddr; # add to table + # $childstatus{$pid} = 1; # add to table $running++; close($client); next; @@ -92,7 +113,7 @@ my $localsockaddr = getsockname($client); my ($lport, $laddr) = sockaddr_in($localsockaddr); $ENV{TCPLOCALIP} = inet_ntoa($laddr); - my ($port, $iaddr) = sockaddr_in($hisaddr); + # my ($port, $iaddr) = sockaddr_in($hisaddr); $ENV{TCPREMOTEIP} = inet_ntoa($iaddr); $ENV{TCPREMOTEHOST} = gethostbyaddr($iaddr, AF_INET) || "Unknown";