HOME
 
 

Comment détecter un bot

Comment détecter un bot sur votre site web

1er février 2008

AddThis Social Bookmark Button

L'article ci-dessous vous décrit plusieurs méthodes et principes pour détecter un bot sur votre site web. Vous trouverez en bas de pages des exemples de scripts en php destiné à la détection des bots.

Il existe sur Internet de nombreux programmes automatisés appelé bots (abréviation de robots). Ces bots, ou crawler, ont été programmés dans des buts bien différents les uns des autres. Certains comme Googlebot, le bot de Google, explorent et indexent le web d'une façon raisonnable, c'est-à-dire en respectant les règles définies dans le fichier robots.txt et sans saturer votre serveur web. D'autre sont plus indélicats et possèdent d'autres buts, comme le récolte d'adresses e-mail ou le spam par referer. Dans ces derniers cas, il devient nécessaire de pouvoir détecter ces bots afin de pouvoir les bloquer.

 

 
 

 


Principes de détection de bots

  1. Ne pas faire confiance au bot en ce qui concerne le suivi des règles du w3c dans la gestion des cookies et des headers tels que referer, accept-lang, etc...

  2. Les seules données transmises par le visiteur qui seront prisent en considération sont son adresse ip et la résolution de son nom d'hôte.

  3. Un bot peut tenter de se faire passer pour un navigateur ou un autre bot en imitant le user-agent; il faut en outre tenir compte du fait que certains navigateurs possèdent la capacité de modifier leur user-agent afin de détecter un cloaking éventuel d'une page web. Le user-agent n'est donc pas suffisant pour détecter un bot.

  4. La résolution de l'adresse ip est toujours possible avec un bot connu tel que ceux de Google, Yahoo et autres. On peut déterminer dans ce cas le bot par son nom d'hôte.

  5. Un bot normal débute son exploration par la visite du fichier robots.txt. Il est possible de détecter la visite de ce fichier en effectuant de l'url rewriting vers un script php.

  6. Un bot voulant se faire passer pour un navigateur ne télécharge pas les fichiers .js, .css ainsi que les images. Cependant, cette règle n'est pas valide pour le premier accès au site. Pour détecter le téléchargement d'une image, on peut utiliser l'astuce suivante (le mieux est d'utiliser une image uniquement référencée depuis un fichier css):

    1. Choisir une image faisant partie de l'interface et présente sur toutes les pages à surveiller.
    2. Créer un script comprenant deux parties: la première enregistre la demande de l'image, la seconde ouvre l'image originale et l'envoie en sortie précédée d'un header Content-Type correct.
    3. Mettre en place une règle d'url rewriting de l'image vers le script, vous n'êtes donc pas obligé de modifier votre interface.


  7. Une autre méthode consiste à créer un lien caché (peu recommandable pour le référencement sur Google) que seuls les robots trouveront (ce genre de "piège à bots" sont appelés "pot de miel", ou "honey pot" en anglais). Faites pointer le lien sur une page spéciale qui peut se comporter de plusieurs façons, selon votre préférence. Vous pouvez créer une page vide contenant uniquement une balise meta robots afin qu'elle n'apparaisse pas dans l'index des moteurs de recherche ou alors utiliser une redirection 303 ou 307. Les deux scripts doivent enregistrer l'adresse ip comme étant celle d'un bot.

On peut alors détecter le passage d'un bot par les tests suivants:
   Le nom d'hôte correspond à une liste de bots reconnus, ou

   Le fichier robots.txt à été téléchargé, ou

   L'image de test n'à pas été téléchargée, ou

   L'adresse ip a visité le pot de miel

Il faut cependant garder en tête qu'il n'existe aucune méthode sûr à 100% pour détecter un bot. Surtout lors de la première visite.

La détection a besoin de quatre tables en base de données

hit_on_robots

idBIGINTNOTNULLauto-increment
ipVARCHAR(15)NOTNULL
lastvisitDATETIMENOTNULL


hit_on_images
idBIGINTNOTNULLauto-increment
ipVARCHAR(15)NOTNULL
lastvisitDATETIMENOTNULL


last_visits
idBIGINTNOTNULLauto-increment
ipVARCHAR(15)NOTNULL
lastvisitDATETIMENOTNULL


detected_bots
idBIGINTNOTNULLauto-increment
ipVARCHAR(15)NOTNULL
lastvisitDATETIMENOTNULL

Scripts php de détection

[Fichier de configuration]
<?php
    
// Configuration
    
$dbuser "root";
    
$dbpass "dbpass";
    
$dbhost "localhost";
    
$dbname "dbname";
    
$dbtblrobots "hit_on_robots";
    
$dbtblimage "hit_on_images";
    
$dbtbllastvisit "last_visits";
    
$dbtbldetected "detected_bots";
    
$robotfilepath "./robots.txt";
    
$imagefilepath "./image.gif";
    
// Connexion MySQL
    
$cnx mysql_connect($dbhost$dbuser$dbpass);
    if (
$cnx !== false)
        
mysql_select_db($dbname$cnx);
?>


[Vérification de la présence d'un bot]
<?php
//Détection par nom d'hôte des bots officiels (google, yahoo, …)
Function IsKnowBot($host)
{
    
$parts explode("."$host);
    
$ante "";
    if (
count($parts) > 2)
        
$ante $parts[count($parts– 2];

    if (
stristr($ante"google") ||
        
stristr($ante" yahoo") ||
        
stristr($ante" msn") ||
        
stristr($ante" live") ||
        
stristr($ante" exabot"))
        return 
true;
        
    return 
false;
}

Function 
IsBot()
{
    include_once(
"[Fichier de configuration]");    
    
    
//Récupération des informations
    
$ua $_SERVER["HTTP_USER_AGENT'"];
    
$ip $_SERVER["REMOTE_ADDR"];
    
$host = isset($_SERVER["REMOTE_HOST"]) ? $_SERVER["REMOTE_HOST"] : gethostbyaddr ($ip);
    if (
IsKnowBot($host)) 
        return 
true;

    if (
$cnx === false) return false;

    
$now time();
    
$datetimesqlnow date('Y-m-d H:i:s'$now)
    
$onehourago $now – 3600;    
    
$datetimesql date('Y-m-d H:i:s'$onehourago)

    
//Vérification de l'accès au "pot de miel"
    
$req "SELECT COUNT(*) FROM ".$dbtbldetected." WHERE ip='".$ip."' AND lastvisit >= '".$datetimesql."'";

    
$res mysql_query($req$cnx);
    if (
$res === false)    
        return 
false;

    if (
mysql_result($res00) > 0)
        return 
true;
    
    
//Vérification de l'accès au fichier robots.txt
    
$req "SELECT COUNT(*) FROM ".$dbtblrobots." WHERE ip='".$ip."' AND lastvisit >= '".$datetimesql."'";

    
$res mysql_query($req$cnx);
    if (
$res === false
        return 
false;

    if (
mysql_result($res00) > 0)
        return 
true;

    
//Vérification de l'accès à l'image
    
$req "SELECT COUNT(*) FROM ".$dbtblimage." WHERE ip='".$ip."' AND lastvisit >= '".$datetimesql."'";    
    
    
$res mysql_query($req$cnx);
    if (
$res === false
        return 
false;

    
//Attention, vrai lors de la première visite depuis un navigateur
    
$hit_on_image mysql_result($res00) > 0;

    
//Alors on vérifie si c'est la première visite
    
$req "SELECT COUNT(*) FROM ".$dbtbllastvisit." WHERE ip='".$ip."' AND lastvisit >= '".$datetimesql."'";

    
$res mysql_query($req$cnx);
    if (
$res === false
        return 
false;
    
$first_visit mysql_result($res00) == 0;

    
$req "DELETE FROM ".$dbtbllastvisit." WHERE ip='".$ip."'";
    
mysql_query($req$cnx);

    
$req "INSERT INTO ".$dbtbllastvisit." (ip, lastvisit) VALUES('".$ip."','".$datetimesqlnow."')";
    
mysql_query($req$cnx);

    if (!
hit_on_image && !first_visit)
        return 
true;

return 
false
?>


[Code du script lié au fichier robots.txt]
<?php
    
// Configuration
    
include_once("[Fichier de configuration]");

    if (
$cnx !== false)
    {
        
//Récupération des informations
        
$ip $_SERVER["REMOTE_ADDR"];
        
$req "DELETE FROM ".$dbtblrobots." WHERE ip='".$ip."'";
        
mysql_query($req$cnx);
        
$req "INSERT INTO ".$dbtblrobots." (ip, lastvisit) VALUES('".$ip."','".date('Y-m-d H:i:s'time())."')";
        
mysql_query($req$cnx);
    }

    
header("Content-type: text/plain");
    echo @
implode("", @file($robotfilepath));
?>


[Code du script lié à l'image.php]
<?php
    
// Configuration
    
include_once("[Fichier de configuration]");

    if (
$cnx !== false)
    {
        
//Récupération des informations
        
$ip $_SERVER["REMOTE_ADDR"];
        
$req "DELETE FROM ".$dbtblimage." WHERE ip='".$ip."'";
        
mysql_query($req$cnx);
        
$req "INSERT INTO ".$dbtblimage." (ip, lastvisit) VALUES('".$ip."','".date('Y-m-d H:i:s'time())."')";
        
mysql_query($req$cnx);
    }

    
$ext strtolower(substr($imagefilepathstrlen($imagefilepath – 4)));

    if (
$ext == "gif")
    {
        
$img createimagefromgif($imagefilepath);
        
header("Content-type: image/gif");
        
imagegif($img);
    }
    else if (
$ext == "jpg" || $ext == "peg")
    {
        
$img imagecreatefromjpeg($imagefilepath);
        
header("Content-type: image/jpeg");
        
imagejpeg($img);
    }
    else if (
$ext == "png")
    {
        
$img imagecreatefrompng($imagefilepath);
        
header("Content-type: image/png");
        
imagepng($img);
    }
    else
    {
        
$img imagecreate(1010);
        
header("Content-type: image/jpeg");
        
imagejpeg($img);
    }
?>


[Code du script du pot de miel]
<?php
    
// Configuration
    
include_once("[Fichier de configuration]");

    if (
$cnx !== false)
    {
        
//Récupération des informations
        
$ip $_SERVER["REMOTE_ADDR"];
        
$req "DELETE FROM ".$dbtbldetected." WHERE ip='".$ip."'";
        
mysql_query($req$cnx);
        
$req "INSERT INTO ".$dbtbldetected." (ip, lastvisit) VALUES('".$ip."','".date('Y-m-d H:i:s'time())."')";
        
mysql_query($req$cnx);
    }
?>

 
     Copyright © 2007 Thomas Mayor - WebKeySoft  
 
Flux rss webkeysoft.comArticles - News
Licence d'utilisation des logiciels - design by webkeysoft