Connection rate limiting with Apache2::ConnectionUtil pnotes

Connection rate limiting with Apache2::ConnectionUtil pnotes

am 13.05.2009 03:50:34 von Fred Moyer

Greetings,

I ran into an issue today where I had a load surge in my application
server, so I looked around for a suitable throttling module and didn't
see anything simple.

So I put together this snippet (very rough) which uses the connection
pnotes data structure to track how many requests are made over a
connection, and return a 503 if the client requests too much. I
thought about using something that shared the data across processes,
but was in a jam and needed to slow down some egregious user agents
which were making multiple rapid requests in succession. I had to
turn on KeepAlives for this to work, but it has been working pretty
well.

Thought I would share this (the code was written under some duress so
isn't all that pretty). MIN_COUNT is the minimum number of requests
to trigger a violation, and MAX_RATE is the maximum allowed request
rate over one connection.

my $c = $r->connection;
if (my $attempts = $c->pnotes($c->remote_ip)) {

my $count = $attempts->{count};
my @times = @{$attempts->{times}};
my $idx;

if ($#times > 9) {

# take the last 10 points
$count = 10;
$idx=$#times-$count;
} else {

$idx=0;
}
my $total_time = $times[$#times] - $times[$idx];

push @{$attempts->{times}}, time();
$attempts->{count}++;
$c->pnotes($c->remote_ip => $attempts);

if ($total_time != 0) {

my $rate = ($count / $total_time);
$r->log->debug("throttle check ip $ip, count $count, time
$total_time, rate $rate") if DEBUG;
if (($count > MIN_COUNT) && ($rate > MAX_RATE)) {

$r->log->error("rate violation ip $ip, total time $total_time,
count $count, rate $rate");

# make 'em wait
sleep 5;
return Apache2::Const::HTTP_SERVICE_UNAVAILABLE;
}
}
} else {

# start tracking this client
my %attempts = ( 'count' => 1, 'times' => [ time() ]);
$r->log->debug("setting new limit check for ip $ip, count 1, time "
.. time()) if DEBUG;
$c->pnotes($c->remote_ip => \%attempts);
}

Re: Connection rate limiting with Apache2::ConnectionUtil pnotes

am 13.05.2009 04:57:41 von gozer

This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--------------enig0BE404CA16FD59A2CDDE9243
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

On 12/05/09 21:50 , Fred Moyer wrote:
> Greetings,
>=20
> I ran into an issue today where I had a load surge in my application
> server, so I looked around for a suitable throttling module and didn't
> see anything simple.

I personally have used mod_cband quite successfully for stuff like this,
give it a look.

Otherwise, nice solution! Especially if coded under the gun ;-)

Gozer out.

--=20
Philippe M. Chiasson GPG: F9BFE0C2480E7680 1AE53631CB32A107 88C3A5A5
http://gozer.ectoplasm.org/ m/gozer\@(apache|cpan|ectoplasm)\.org/


--------------enig0BE404CA16FD59A2CDDE9243
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)

iD8DBQFKCjclyzKhB4jDpaURAoa9AKCuQS+imOOHaS5/q7IeWlbAsgh7ygCg tlT4
90GXU0NCpCDoVHwbfl/JK7o=
=oMtH
-----END PGP SIGNATURE-----

--------------enig0BE404CA16FD59A2CDDE9243--