Многие задаются вопросом, возможно ли бороться с DDOS при помощи PhP? Казалось бы, ответ очевиден — нет. Другие скажут, что это полнейший бред и не нужно страдать ерундой. Я, конечно же, никого переубеждать не стану. Однако, хотелось бы рассказать о своем подходе к решению этой столь нетривиальной задачи.
Перед тем, как меня вот-вот закидают камнями, хотелось бы отметить, что данный пример не применим к использованию на high-load серверах, которые могут подвергаться или подвергаются сильным ддос атакам. Так как в этом случае, Вам нужны более серьезные методы решения данной проблемы. (Возможно в дальнейшем, я расскажу о некоторых из них) Это скорей игрушка для вашего блога. Однако, как показала практика, эта штука, что-то, все-таки умеет.
Ничего сверхъестественного для работы скрипта нам не понадобиться: iptables и, непосредственно, сам php интерпретатор.
Собственно, код скрипта довольно простой, поэтому в особых комментариях не нуждается:
И, конечно же, конфиг файл к скрипту. Так же, ничего особенного.
Запускать можно по крону. Либо как вариант:
На этом, моя первая статья закончена. Прошу прощения за возможные синтаксические или пунктуационные ошибки. Хотелось бы услышать Ваше мнение, по поводу моихне всегда умных мыслей.
Всем спасибо.
Перед тем, как меня вот-вот закидают камнями, хотелось бы отметить, что данный пример не применим к использованию на high-load серверах, которые могут подвергаться или подвергаются сильным ддос атакам. Так как в этом случае, Вам нужны более серьезные методы решения данной проблемы. (Возможно в дальнейшем, я расскажу о некоторых из них) Это скорей игрушка для вашего блога. Однако, как показала практика, эта штука, что-то, все-таки умеет.
Ничего сверхъестественного для работы скрипта нам не понадобиться: iptables и, непосредственно, сам php интерпретатор.
Собственно, код скрипта довольно простой, поэтому в особых комментариях не нуждается:
$config = 'conf.ini';
$config = parse_ini_file($config, true);
/** некоторые настройки php, для localhost **/
header('Content-Type: text/plain; charset=UTF-8');
ob_implicit_flush();
set_time_limit(0);
$skip = array();
$data = array();
while(true): /* По желанию, можно запускать из крона */
$content = $config['logs']['use'] == 'file' ? file($config['logs']['file'])
: explode("\n", shell_exec($config['logs']['command']));
/**
* Функция проверяет значение максимального лимита для заданного ip на какой-либо параметр
* @param string $e параметр
* @param string $ip ip
*/
function check($e, $ip){
global $data, $config, $skip;
$ipdata = $data[$ip][$e];
if(($d = count($ipdata)) >= $config['block']['max_' . $e]){
block($ip, 'max_' . $e . '=' . $config['block']['max_' . $e]);
$skip[] = $ip;
}
}
/**
* Функция блокирования ip
* @param string $ip ip
*/
function block($ip, $r = false){
print "block: {$ip}" . ($r !== false ? ", $r" : '') . "\n";
shell_exec('/sbin/iptables -I INPUT -j DROP -s ' . $ip);
file_put_contents('/a/' . date('d-m-Y') . '.log', "{$ip}\n", FILE_APPEND);
}
/**
* Возвращает массив с распознанными данными.
* @param string $line
* @return array
*/
function recognize($line){
while(strstr($line, '[[') || strstr($line, ']]'))
$line = str_replace(array(']]', '[['), array(']', '['), $line);
preg_match_all('|\-([a-z]{1,})\[(.*)]|U', $line, $arr);
$recognize = array();
foreach($arr[1] AS $i => $j){
$recognize[$j] = $arr[2][$i];
}
return (array) $recognize;
}
foreach($content AS $line){
$request = recognize($line);
if(!isset($request['ip'])){
continue;
}
if(in_array($request['ip'], $skip)){
unset($data[$request['ip']]);
continue;
}
if(!isset($data[$request['ip']])){
$data[$request['ip']] = array('ua' => array(), 'referer' => array());
}
if($request['ua'] == '' || $request['ua'] == '-'
|| $request['referer'] == '' || $request['referer'] == '-'){
if(strtoupper($config['block']['empty']) == 'ON'){
block($request['ip']); continue;
}
}
if($request['ua'] = trim($request['ua'])){
if(! in_array($request['ua'], $data[$request['ip']]['ua'])){
$data[$request['ip']]['ua'][] = $request['ua'];
if(check('ua', $request['ip']))
continue;
}
}
$referer = @parse_url($request['referer']);
if($referer['host'] = trim($referer['host']) && $referer['host'] != $request['host']){
if(! in_array($referer['host'], $data[$request['ip']]['referer'])){
$data[$request['ip']]['referer'][] = $referer['host'];
check('referer', $request['ip']);
}
}
}
sleep(1);
endwhile;
И, конечно же, конфиг файл к скрипту. Так же, ничего особенного.
[logs]
;команда для получения логов
;command = "cat /var/log/* | grep 192.168.15.7"
command = "cat logs/deweber.org.acc_log * | grep 192.168.15.7"
;файл с логами
file = "httpd-traffic.log"
;доставать логи из файла или выполнять команду
;command/file
use = "command"
[ban]
empty = On
max_ua = 5
max_referer = 10
Запускать можно по крону. Либо как вариант:
/usr/bin/php -dsafe_mode=Off -ddisable_functions= -dallow_url_fopen=On /root/tools/antiddos.php > /dev/null &
На этом, моя первая статья закончена. Прошу прощения за возможные синтаксические или пунктуационные ошибки. Хотелось бы услышать Ваше мнение, по поводу моих
Всем спасибо.