[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Запрет множественных запросов с одного IP
kirik
Ребят, возник такой вопрос, как защитить сайт от парсера?

Саму логику я представляю себе так:
приходит запрос с какого-то IP адреса, этот адрес пишется куда-то (в файл) с временем визита, при очередном обращении происходит проверка этого IP на существование, и если второй запрос пришел с разницей меньше одной секунды (от первого запроса) - посылаем запрос в exit();

Но что-то мне подсказывает, что такая система будет очень тормозить, или нет? Может есть варианты по-умнее?



Спустя 7 часов, 3 минуты, 9 секунд (22.05.2009 - 10:39) waldicom написал(а):
ИМХО такие вещи нвдо делть на уровне апача. 100% есть модуль для апача, который это может, но как называется - сейчас не упомню.

Спустя 3 часа, 17 минут, 42 секунды (22.05.2009 - 13:57) FatCat написал(а):
kirik
http://phpforum.ru/index.php?showtopic=18133
Гостям сессия жестко привязана к айпишнику. В сессии пишется время апдейта.
Условие
PHP
if(($this->time_now - $this->last_click) < 1)
это и есть сравнение время последнего апдейта с текущим времени в начале функции апдейта сессии.

Собственно, сам попробуй. Скинь авторизацию, войди в форум гостем и попробуй двойные клики по линкам. Увидишь эррорпейджи с предупреждением о недопустимости двойных кликов. Желательно не набрать 10 предупреждений: по идее тебя должно защитить от бана проверкой "на человека", но лучше не рисковать.

Спустя 6 минут, 17 секунд (22.05.2009 - 14:03) FatCat написал(а):
Цитата (kirik @ 22.05.2009 - 03:36)
такая система будет очень тормозить, или нет?

Само определение времени с прошлого запроса занимает меньше 0.001 секунды даже под денвером; на реальном сервере и того быстрее.

Спустя 6 часов, 44 минуты, 22 секунды (22.05.2009 - 20:47) kirik написал(а):
waldicom
Вообще хотелось что-то свое, чтобы если нужно сайт перекинуть на новый хостинг - не требовалась установка дополнительных модулей, да и такая система будет намного более гибкой (например можно убирать запрет на некоторые IP, или разрешать зарегистрированным на сайте юзерам открывать больше одной страницы в n-ный промежуток времени).

FatCat
Примерно ясно. Ну раз подобная модель уже работает на этом форуме, можно писАть smile.gif

Спасибо!

Спустя 2 часа, 38 минут, 39 секунд (22.05.2009 - 23:26) FatCat написал(а):
Цитата (kirik @ 22.05.2009 - 20:47)
или разрешать зарегистрированным на сайте юзерам открывать больше одной страницы в n-ный промежуток времени).

Вызов функции антибота происходит из функции update_guest_session.
В функциях апдейта сессий мемберов и поисковых ботов (по юзерагентам) таких проверок и вызовов антибота нет.
Плюс проверка "на человека" даже для гостей с выводом из-под бана, если есть признак человека.

Спустя 1 месяц, 22 часа, 19 минут, 11 секунд (23.06.2009 - 21:45) kirik написал(а):
Поднимаю тему в очередной раз.
Статья навеяла некоторые мысли по поводу защиты от назойливых айпишников.

Вариант с сессиями мне кажется слишком ресурсозатратным, тем более кривые боты не всегда принимают ID сессии, в итоге создавая тысячи записей в таблице сессий.
Схема описанная в статье мне приглянулась самим рассчетом рейтинга для каждого IP, в итоге родилась у меня такая штука:

PHP
// для каждого нового IP будет создаваться файл с "номером" IP адреса($_SERVER['REMOTE_ADDR'] обязательно проверяем на валидность)
// $file_ip = '/home/www/ips/'.ip2long($_SERVER['REMOTE_ADDR']);

$file_ip = '/home/www/test.txt'; // файл для теста

if(file_exists($file_ip))
{
    $access_time = filemtime($file_ip);
    list($access_num, $rating_num) = file($file_ip, FILE_IGNORE_NEW_LINES);
    $curr_rating = log(time() - $access_time);
    $rating_num += is_infinite($curr_rating) ? 0 : $curr_rating;
    $curr_rating = $rating_num / ++$access_num;

    file_put_contents($file_ip, $access_num."\n".$rating_num, LOCK_EX);
}
else
{
    $access_num = 1;
    $curr_rating = 1;
    file_put_contents($file_ip, $access_num."\n".$curr_rating, LOCK_EX);
}

if(
$access_num > 50 && $curr_rating < 0.8)
{
    exit('Hello, dear robot!'); // выводим капчу / записываем этот ip в бан
}

echo 'Access num: '.$access_num.'  Rating num:'.$curr_rating."\n";


Плюсы очевидны: не используется БД - скорость в разы выше, нагрузка меньше; не нужно создавать сессию, чтобы вычислить робота.

Насколько правильным вам кажется такой подход? Может какие-нибудь идеи будут.. smile.gif

ЗЫ. файлы IPшек конечно лучше раскладывать по папкам, чтобы не в одной папке было 100к файлов..
ЗЫ2. работает только в php>5

Спустя 2 часа, 24 минуты, 6 секунд (24.06.2009 - 00:09) PandoraBox2007 написал(а):
на джава можно кусок вставить и кодировать в PHP усложним ботам жизнь smile.gif

p.s. изменил eval на document.write

Спустя 22 минуты, 45 секунд (24.06.2009 - 00:32) kirik написал(а):
PandoraBox2007
Спасибо! В теории можно, но на практике это слишком жестко smile.gif

Спустя 50 минут, 33 секунды (24.06.2009 - 01:22) FatCat написал(а):
Цитата (kirik @ 23.06.2009 - 22:45)
не используется БД - скорость в разы выше

Чтение/запись файла всегда ли быстрее работы с БД?

На примере сервреа этого форума:
Код
KeepAlive On
KeepAliveTimeout 5
MaxClients 15

При среднем времени генерации страницы около 0,1 секунды это означает до 150 клиентов в секунду.
Один лишь Yahoo_bot элементарно генерит по 10-15 клиентских запросов в секунуду. То есть, движок не упадет и при 10 яхуботах одновременно; или при десятке парсеров, про прожорливости равных яхуботу.

Ты же предлагаешь на каждый клиентский запрос страницы создавать два клиентских запроса к файлам.
Эдак на обычных поисковых ботов начнутся вылеты в таймаут...

При работе с БД таких проблем нет. Не знаю, есть ли у MySQL лимит на количество запросов в секунду, но если и есть, то он намного выше выше лимита обращений к файлам у апача... При бекапе-ресторе больших баз видел вполне реальную скорость 10 000 запросов в секунду.



Цитата (kirik @ 23.06.2009 - 22:45)
кривые боты не всегда принимают ID сессии, в итоге создавая тысячи записей в таблице сессий.

Сессия пишется в БД и привязывается к айпишнику:
PHP
function create_guest_session() {
        global $DB, $INFO, $std, $ibforums;

        $DB->query("SELECT id, ip_address, running_time FROM ibf_sessions WHERE ip_address='".$this->ip_address."' AND member_name = ''");
        $result = $DB->fetch_row();
        if( $result['ip_address'] == $this->ip_address ){
            $this->session_id  = $result['id'];
            $this->last_click = $result['running_time'];
            $this->update_guest_session();
        }
//  кусок кода кошки съели
    }
Таким образом на одном айпишнике будет только одна гостевая сессия, апдейт которой в функции update_guest_session()

Спустя 10 минут, 27 секунд (24.06.2009 - 01:33) FatCat написал(а):
Цитата (PandoraBox2007 @ 24.06.2009 - 01:09)
усложним ботам жизнь

Гы!
Когда достоверно выявлен бот, в .htaccess его закрыть без вопросов.
Хотя, были идеи активно гадить.
Парсят же с серверов. А на серверах есть такая штука, что если исходящий трафик превышает входящий меньше чем в 4 раза, трафик становится лимитным и платным...
Соответственно, большая гадость - это дать парсеру много мусорного трафика. Отсюда и родилась идея "мягкого бана", описанная мной на http://forums.ibresource.ru/index.php?showtopic=57879

Ради эксперимента опробовал на своем айпишнике: для реального посетителя не смертельно, подтормаживание секунд 5 на 10-мегабитном канале. laugh.gif
А для бота-парсера, запущенного на ночь парсить сайт, это может за ночь наколотить счет к оплате трафика не на одну сотню долларов. rolleyes.gif

Спустя 24 минуты, 35 секунд (24.06.2009 - 01:58) kirik написал(а):
Цитата (FatCat @ 23.06.2009 - 17:22)
Чтение/запись файла всегда ли быстрее работы с БД?

В примере, который привел я чтение/запись будет проходить гораздо быстрее чем выборка из БД.

Цитата (FatCat @ 23.06.2009 - 17:22)
Не знаю, есть ли у MySQL лимит на количество запросов в секунду, но если и есть, то он намного выше выше лимита обращений к файлам у апача...

Да, у MySQL есть такой лимит, определяется переменной max_connections, а вот про "выше лимита обращений к файлам у апача" не понял.. Ведь при чтении/записи файлов из php апач не участвует. Идет прямое обращение к файлам и ограничения тут как такового нет, тоесть ограничение есть, и оно определяется возможностями самой файловой системы. При этом скорость доступа к файлу будет быстрее, потому как ФС быстрее чем выборка из БД.

Цитата (FatCat @ 23.06.2009 - 17:22)
Один лишь Yahoo_bot элементарно генерит по 10-15 клиентских запросов в секунуду.

Спасибо за инфу! Кстати гуглобот столько же запросов шлет? Просто как бы не получилось что в бан попадут поисковые боты..

Спустя 10 часов, 42 минуты, 36 секунд (24.06.2009 - 12:40) PandoraBox2007 написал(а):
по теме
PHP
<?php

 $bots 
= array();
 $bots['google']   = strpos($_SERVER['HTTP_USER_AGENT'], "Googlebot") ? true false;
 $bots['yandex']   = strpos($_SERVER['HTTP_USER_AGENT'], "Yandex") ? true false;
 $bots['rambler']  = strpos($_SERVER['HTTP_USER_AGENT'], "StackRambler") ? true false;
 $bots['aport']    = strpos($_SERVER['HTTP_USER_AGENT'], "Aport") ? true false;
 $bots['msn']      = strpos($_SERVER['HTTP_USER_AGENT'], "MSN") ? true false;
 $bots['yahoo']    = strpos($_SERVER['HTTP_USER_AGENT'], "Yahoo") ? true false;
 
  
//print_r($bots);

Спустя 6 минут, 29 секунд (24.06.2009 - 12:47) PandoraBox2007 написал(а):
Цитата (kirik @ 23.06.2009 - 22:58)
Спасибо за инфу! Кстати гуглобот столько же запросов шлет? Просто как бы не получилось что в бан попадут поисковые боты..

скорость индексации гуглом можно менять или в robots.txt или на Google Webmaster Central (Инструменты для веб-мастеров (включая Sitemaps))

Crawl-delay Яндекса

Спустя 6 часов, 30 минут, 34 секунды (24.06.2009 - 19:17) kirik написал(а):
PandoraBox2007
Да, про delay только вчера читал, спасибо! smile.gif

Я параноик ужасный, проверка по юзер агенту не прокатит smile.gif Я вчерась подумал что можно проверять ботов по DNS записям, чтобы определить принадлежность IP к какому-либо домену (из "белого списка"), потом нашел подтверждение своей выдумки у гугла. Но вот проблема.. гуглобота я смогу таким образом вычислить, а вот список доменов других ботов что-то никак не могу найти. Если у кого-нибудь есть, поделитесь пожалуйста smile.gif

Спустя 1 день, 2 часа, 23 минуты, 24 секунды (25.06.2009 - 21:41) PandoraBox2007 написал(а):
PHP
$bots['google'] = strpos(gethostbyaddr($_SERVER['REMOTE_ADDR']), "googlebot.com") ? true : false;
wink.gif

HTML
googlebot.com
yandex.ru
ramtel.ru, rambler.ru
aport.ru
sape.ru
msn.com

Спустя 30 минут, 20 секунд (25.06.2009 - 22:11) kirik написал(а):
PandoraBox2007
круто! Спасибо!

Я тут тоже небольшой ресёрч провел на основании данных IPшников отсюда:

AltaVista:
*.above.net
*.yahoo.com

Aport:
*.sovam.com

Google:
*.google.com
*.googlebot.com

MSN:
*.microsoft.com
*.msn.com
*.msn.net
*.live.net
*.live-int.com
*.live.com

Yahoo:
*.inktomisearch.com
*.yahoo.net
*.yahoo.com

Yandex:
*.yandex.ru


Но судя по тем IPшкам яндекс почти не ходит со своего домена (только одно совпадение)..

Если кому интересны все IP могу выложить.

Спустя 9 минут, 56 секунд (25.06.2009 - 22:21) glock18 написал(а):
файликом если не сложно rolleyes.gif

Спустя 6 минут, 57 секунд (25.06.2009 - 22:28) kirik написал(а):
Цитата (glock18 @ 25.06.2009 - 14:21)
файликом если не сложно rolleyes.gif

Прикрепил.
файл se-*.txt содержит все IP адреса, которые по идее должны пренадлежать поисковику
файл se-*_dns.txt содержит dns записи каждого IP адреса и имеет вид:

если IP не имеет домена
PHP
[141.185.0.209] => Array
        
(
            [0] => 141.185.0.209
        
)


если IP имеют домены
PHP
[ne.jp] => Array
        
(
            [0] => 202.212.5.32 :: network.goo
            
[1] => 202.212.5.33 :: gateway.goo
            
[2] => 202.212.5.36 :: ffm.goo
            
[3] => 202.212.5.47 :: broadcast.goo
            
[4] => 202.212.5.48 :: network.goo
        
)

где для IP 202.212.5.32 DNS запись будет network.goo.ne.jp

Спустя 4 минуты, 37 секунд (25.06.2009 - 22:32) kirik написал(а):
Да, и сам скрипт если нужно:
Свернутый текст
PHP
$src '/home/kirik/se-google.txt';

$file file($srcFILE_IGNORE_NEW_LINES);
$ips array_unique($file);
$hosts = array();
unset(
$file);

for(
$i 0$c count($ips); $i $c$i++)
{
    if(
$ip ip2long($ips[$i]))
    {
        
$ip long2ip($ip);
        
$host gethostbyaddr($ip);
        if(
preg_match('/^(\S+)\.(\S+\.\D{2,3})$/'$host$out))
        {
            
$hosts[$out[2]][] = $ip.' :: '.$out[1];
        }
        else
        {
            
$hosts[$host][] = $ip;
        }
    }
}

file_put_contents(str_replace('.txt''_dns.txt'$src), print_r($hoststrue));


В $src указываем путь до файла с адресами (1 ip на строчке), и в директории должна быть разрешена запись.

Спустя 5 минут, 10 секунд (25.06.2009 - 22:38) waldicom написал(а):
Спасиб. Мну тоже пригодится!

Спустя 3 минуты, 23 секунды (25.06.2009 - 22:41) glock18 написал(а):
Ага, спасибо!

Спустя 3 минуты, 41 секунда (25.06.2009 - 22:45) twin написал(а):
Очень кстати))) Как раз тоже собирался. СПС.

Спустя 1 год, 10 месяцев, 26 дней, 13 часов, 35 минут, 18 секунд (22.05.2011 - 12:20) ttl написал(а):
Для меня тоже актуальна эта тема, парсят сайт ежедневно. Есть ли решение?
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.