- Joined
- Jan 17, 2009
- Messages
- 1,212
- Reaction score
- 976
Много хора са се питали как да предотвратят "requests flood-а" към техният уеб сайт и всичко да си работи нормално? Ето го начина който аз намерих и леко бутнах за да работи всичко както трябва.
Като начало нека създадем един файл под името example.php примерно и сложим това в него:
След като създадохме файл example.php е нужно да създадем още един с името class.floodblocker.php и в него да сложим ето това:
Така сега да обесня малко по-подробно за всичко това което написах по-горе.
За да работи всичко това е нужно да include: <?php include('example.php');?> в Вашия index.php или header.php . Когато някой тръгне да flood-и чрез заявки Вашият уеб сайт след даденият лимит който е зададен в example.php му показва страница 413.php примерно както съм направил и записва IP-то и дата на която е направен въпросният flood в файл floodlog.txt който се намира в папка floods. За тази цел след като направите всичко това трябва да си направите папка floods за да може да се записват всички тези неща. Ако случайно забравите ще Ви дава постоянно грешка
Ето и страница 413.php която да показва на потребителя който се мъчи да Ви направи гадно:
Като начало нека създадем един файл под името example.php примерно и сложим това в него:
Code:
<?php
require_once ( 'class.floodblocker.php' );
$flb = new FloodBlocker ( 'floods/' );
$floodfile = "floods/floodlog.txt";
$ipaddress = $_SERVER['REMOTE_ADDR'];
$addedtime = date("D dS M Y h:i a");
$flb->rules = array (
10=>10, // Правило 1 - максимум 10 заявки за 10 секунди
60=>30, // Правило 2 - максимум 30 заявки за 60 секунди
300=>50, // Правило 3 - максимум 50 заявки за 300 секунди
3600=>200 // Правило 4 - максимум 200 заявки за 3600 секунди
);
if ( ! $flb->CheckFlood ( ) ) {
$floodfp = fopen($floodfile, "a+");
fputs($floodfp, "Date and Time: $addedtime | IP Address: $ipaddress\n");
fclose($floodfp);
include("413.php"); exit;
}
?>
След като създадохме файл example.php е нужно да създадем още един с името class.floodblocker.php и в него да сложим ето това:
Code:
<?php
define ( 'E_TMP_DIR', 'Incorrect temprorary directory specified.' );
define ( 'E_IP_ADDR', 'Incorrect IP address specified.' );
define ( 'E_LOG_FILE', 'Log file access error! Check permissions to write.' );
define ( 'E_CRON_FNAME', 'The name of cron file must begin with dot.' );
define ( 'E_CRON_FILE', 'Cron file access error! Check permissions to write.' );
define ( 'E_CRON_JOB', 'Unable to perform the cron job.' );
class FloodBlocker
{
var $logs_path;
var $ip_addr;
var $rules;
var $cron_file;
var $cron_interval;
var $logs_timeout;
function FloodBlocker ( $logs_path, $ip = '' )
{
if ( ! is_dir ( $logs_path ) )
trigger_error ( E_TMP_DIR, E_USER_ERROR );
$logs_path = str_replace ( '\\', '/', $logs_path );
if ( substr ( $logs_path, -1 ) != '/' )
$logs_path .= '/';
$this->logs_path = $logs_path;
if ( empty ( $ip ) )
$ip = $_SERVER['REMOTE_ADDR'];
$ip = ip2long ( $ip );
if ( $ip == -1 || $ip === FALSE )
trigger_error ( E_IP_ADDR, E_USER_ERROR );
$this->ip_addr = $ip;
$this->rules = array ( );
$this->cron_file = '.time';
$this->cron_interval = 1800; // 30 minutes
$this->logs_timeout = 7200; // 2 hours
}
function RawCheck ( &$info )
{
$no_flood = TRUE;
foreach ( $this->rules as $interval=>$limit )
{
if ( ! isset ( $info[$interval] ) )
{
$info[$interval]['time'] = time ( );
$info[$interval]['count'] = 0;
}
$info[$interval]['count'] += 1;
if ( time ( ) - $info[$interval]['time'] > $interval )
{
$info[$interval]['count'] = 1;
$info[$interval]['time'] = time ( );
}
if ( $info[$interval]['count'] > $limit )
{
$info[$interval]['time'] = time ( );
$no_flood = FALSE;
}
}
return $no_flood;
}
function CheckFlood ( )
{
$this->CheckCron ( );
$path = $this->logs_path . $this->ip_addr;
if ( ! ( $f = fopen ( $path, 'a+' ) ) )
trigger_error ( E_LOG_FILE, E_USER_ERROR);
flock ( $f, LOCK_EX );
$info = fread ( $f, filesize ( $path ) + 10 );
$info = unserialize( $info );
$result = $this->RawCheck ( $info );
ftruncate ( $f, 0 );
fwrite ( $f, serialize( $info ) );
fflush ( $f );
flock($f, LOCK_UN);
fclose($f);
return $result;
}
function CheckCron ( )
{
if ( substr ( $this->cron_file, 0, 1 ) != '.' )
{
trigger_error ( E_CRON_FNAME, E_USER_WARNING );
return;
}
$path = $this->logs_path . $this->cron_file;
if ( ! ( $f = fopen ( $path, 'a+' ) ) )
{
trigger_error ( E_CRON_FILE, E_USER_WARNING );
return;
}
flock ( $f, LOCK_EX );
$last_cron = fread ( $f, filesize ( $path ) + 10 );
$last_cron = abs ( intval ( $last_cron ) );
if ( time ( ) - $last_cron > $this->cron_interval )
{
$this->CronJob ( );
$last_cron = time ( );
}
ftruncate ( $f, 0 );
fwrite ( $f, $last_cron );
fflush ( $f );
flock ( $f, LOCK_UN );
fclose ( $f );
}
function CronJob ( )
{
$path = $this->logs_path;
if ( ! ( $dir_hndl = opendir ( $this->logs_path ) ) )
{
trigger_error ( E_CRON_JOB, E_USER_WARNING);
return;
}
while ( $fname = readdir ( $dir_hndl ) )
{
if ( substr( $fname, 0, 1 ) == '.' )
continue;
clearstatcache ( );
$ftm = filemtime ( $path . $fname );
if ( time ( ) - $ftm > $this->logs_timeout )
@unlink ( $path . $fname );
}
closedir ( $dir_hndl );
}
}
?>
Така сега да обесня малко по-подробно за всичко това което написах по-горе.
За да работи всичко това е нужно да include: <?php include('example.php');?> в Вашия index.php или header.php . Когато някой тръгне да flood-и чрез заявки Вашият уеб сайт след даденият лимит който е зададен в example.php му показва страница 413.php примерно както съм направил и записва IP-то и дата на която е направен въпросният flood в файл floodlog.txt който се намира в папка floods. За тази цел след като направите всичко това трябва да си направите папка floods за да може да се записват всички тези неща. Ако случайно забравите ще Ви дава постоянно грешка
Ето и страница 413.php която да показва на потребителя който се мъчи да Ви направи гадно:
Code:
<HTML><HEAD>
<TITLE>413 Too many requests</TITLE>
</HEAD><BODY>
<H1>Too many requests</H1>
The requested will refuse for few seconds or minutes between requests. The request block.<br>
You have made too many requests per second. This is to stop flooding of our server. Please wait few secounds between requests.<P>
</BODY></HTML>