|
|
ru.cgi.perl- RU.CGI.PERL ------------------------------------------------------------------ From : Michael Smirnov 2:5020/400 19 Jul 2001 18:10:50 To : All Subject : Speedlimit.pm и защита от http-атак --------------------------------------------------------------------------------
Для защиты от http-атак при Basic auth
я установил на FreeBSD 4.2
apache_1.3.20rusPL30.5, mod_perl-1.26 как DSO.
Взял модуль SpeedLimit.pm из
http://www.modperl.com/book/source/wrapmod-code-1.02.tar.gz
про который написано в
http://www.modperl.com/book/chapters/ch6.html#Blocking_Greedy_Clients
Модуль заработал, параметры такие:
PerlSetVar SpeedLimit 100
# max accesses/minute
PerlSetVar SpeedSamples 5
# hits before counting statistics
PerlSetVar SpeedForgive 1
# amnesty after ... minutes
после нескольких Refresh в браузере выдается Forbidden,
а после какого-то времени доступ вновь разрешается.
Hо вот что непонятно -
если перезапустить Apache (apachectl stop, apachectl stop),
то все равно выдается Forbidden,
а после какого-то времени "амнистируется".
Добавив запись в errorlog переменной $hits,
я точно выяснил, что speedlimit умудряеся хранить данные после остановки
Apache.
Как и где он это делает?
Как вручную "убить" эти данные?
И еще - как переделать Speedlimit.pm подсчитывать
только число неудачных аутентификаций?
package Apache::SpeedLimit;
use strict;
use Apache::Constants qw(:common);
use Apache::Log ();
use IPC::Shareable ();
use vars qw(%DB);
sub handler {
my $r = shift;
return DECLINED unless $r->is_main; # don't handle sub-requests
my $speed_limit = $r->dir_config('SpeedLimit') || 10; # Accesses per
minute
my $samples = $r->dir_config('SpeedSamples') || 10; # Sampling
threshold (hits)
my $forgive = $r->dir_config('SpeedForgive') || 20; # Forgive after
this period (minutes)
my $content_type = $r->lookup_uri($r->uri)->content_type;
return OK if $content_type =~ m:^image/:i; # ignore images
tie %DB, 'IPC::Shareable', 'SPLM', {create => 1, mode => 0644}
unless defined %DB;
my($ip, $agent) = ($r->connection->remote_ip,
$r->header_in('User-Agent'));
my $id = "$ip:$agent";
my $now = time()/60; # minutes since the epoch
# lock the shared memory while we work with it
tied(%DB)->shlock;
my($first, $last, $hits, $locked) = split ' ', $DB{$id};
my $result = OK;
my $l = $r->server->log;
CASE:
{
unless ($first) { # we're seeing this client for the first time
$l->debug("First request from $ip. Initializing speed
counter.");
$first = $last = $now;
$hits = $locked = 0;
last CASE;
}
if ($now - $last > $forgive) { # beyond the grace period. Treat
like first
$l->debug("$ip beyond grace period. Reinitializing speed
counter.");
$last = $first = $now;
$hits = $locked = 0;
last CASE;
}
# update the values now
$last = $now; $hits++;
if ($hits < $samples) {
$l->debug("$ip not enough samples to calculate speed.");
last CASE;
}
if ($locked) { # already locked out, so forbid access
$l->debug("$ip locked");
$result = FORBIDDEN;
last CASE;
}
my $interval = $now - $first;
$l->debug("$ip speed = ", $hits/$interval);
if ($hits/$interval > $speed_limit) {
$l->debug("$ip exceeded speed limit. Blocking.");
$locked = 1;
$result = FORBIDDEN;
last CASE;
}
}
$r->log_reason("Client exceeded speed limit. hits=$hits", $r->filename)
if $result == FORBIDDEN;
$DB{$id} = join " ", $first, $now, $hits, $locked;
tied(%DB)->shunlock;
return $result;
}
1;
__END__
--- ifmail v.2.15dev5
* Origin: Demos online service (2:5020/400)
Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.cgi.perl/27252a5f84990.html, оценка из 5, голосов 10
|