it-swarm.com.de

Wie erkenne ich falsche Benutzer (Crawler) und cURL?

Einige andere Websites verwenden cURL und einen gefälschten http-Verweiser, um meinen Website-Inhalt zu kopieren. Gibt es eine Möglichkeit, cURL oder einen echten Webbrowser zu erkennen?

38
Ken Le

Es gibt keine magische Lösung, um automatisches Crawling zu vermeiden. Alles, was ein Mensch tun kann, kann auch ein Roboter. Es gibt nur Lösungen, die die Arbeit schwieriger machen, und zwar so schwer, dass nur starke Geeks versuchen, sie zu bestehen.

Ich war auch vor einigen Jahren in Schwierigkeiten und mein erster Rat ist, wenn Sie Zeit haben, selbst Crawler zu sein (ich nehme an, ein Crawler ist der Typ, der Ihre Website crawlt), ist dies die beste Schule für das Thema. Durch das Crawlen mehrerer Websites lernte ich verschiedene Arten von Schutzmaßnahmen kennen, und durch das Verknüpfen dieser Websites war ich effizient.

Ich gebe Ihnen einige Beispiele für Schutzmaßnahmen, die Sie möglicherweise versuchen.


Sitzungen pro IP

Wenn ein Benutzer pro Minute 50 neue Sitzungen verwendet, können Sie denken, dass dieser Benutzer ein Crawler ist, der keine Cookies verarbeitet. Natürlich verwaltet curl Cookies perfekt, aber wenn Sie es mit einem Besuchszähler pro Sitzung koppeln (wird später erklärt), oder wenn Ihr Crawler ein Noobie mit Cookie-Angelegenheiten ist, kann dies effizient sein.

Es ist schwer vorstellbar, dass 50 Personen derselben gemeinsamen Verbindung gleichzeitig auf Ihrer Website angezeigt werden (dies hängt natürlich von Ihrem Datenverkehr ab, das liegt an Ihnen). In diesem Fall können Sie Seiten Ihrer Website sperren, bis ein Captcha gefüllt ist.

Idee:

1) Sie erstellen 2 Tabellen: 1 zum Speichern gesperrter IPS und 1 zum Speichern von IP und Sitzungen

create table if not exists sessions_per_ip (
  ip int unsigned,
  session_id varchar(32),
  creation timestamp default current_timestamp,
  primary key(ip, session_id)
);

create table if not exists banned_ips (
  ip int unsigned,
  creation timestamp default current_timestamp,
  primary key(ip)
);

2) Am Anfang Ihres Skripts löschen Sie zu alte Einträge aus beiden Tabellen

3) Als Nächstes prüfen Sie, ob die IP Ihres Benutzers gesperrt ist oder nicht (Sie setzen ein Flag auf "True").

4) wenn nicht, zählen Sie, wie viel Sitzungen er für seine IP hat

5) Wenn er zu viele Sitzungen hat, fügen Sie ihn in Ihre verbotene Tabelle ein und setzen ein Flag

6) Sie fügen seine IP-Adresse in die Sitzung pro IP-Tabelle ein, wenn sie noch nicht eingefügt wurde

Ich habe ein Codebeispiel geschrieben, um meine Idee besser darzustellen.

<?php

try
{

    // Some configuration (small values for demo)
    $max_sessions = 5; // 5 sessions/ip simultaneousely allowed
    $check_duration = 30; // 30 secs max lifetime of an ip on the sessions_per_ip table
    $lock_duration = 60; // time to lock your website for this ip if max_sessions is reached

    // Mysql connection
    require_once("config.php");
    $dbh = new PDO("mysql:Host={$Host};dbname={$base}", $user, $password);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Delete old entries in tables
    $query = "delete from sessions_per_ip where timestampdiff(second, creation, now()) > {$check_duration}";
    $dbh->exec($query);

    $query = "delete from banned_ips where timestampdiff(second, creation, now()) > {$lock_duration}";
    $dbh->exec($query);

    // Get useful info attached to our user...
    session_start();
    $ip = ip2long($_SERVER['REMOTE_ADDR']);
    $session_id = session_id();

    // Check if IP is already banned
    $banned = false;
    $count = $dbh->query("select count(*) from banned_ips where ip = '{$ip}'")->fetchColumn();
    if ($count > 0)
    {
        $banned = true;
    }
    else
    {
        // Count entries in our db for this ip
        $query = "select count(*)  from sessions_per_ip where ip = '{$ip}'";
        $count = $dbh->query($query)->fetchColumn();
        if ($count >= $max_sessions)
        {
            // Lock website for this ip
            $query = "insert ignore into banned_ips ( ip ) values ( '{$ip}' )";
            $dbh->exec($query);
            $banned = true;
        }

        // Insert a new entry on our db if user's session is not already recorded
        $query = "insert ignore into sessions_per_ip ( ip, session_id ) values ('{$ip}', '{$session_id}')";
        $dbh->exec($query);
    }

    // At this point you have a $banned if your user is banned or not.
    // The following code will allow us to test it...

    // We do not display anything now because we'll play with sessions :
    // to make the demo more readable I prefer going step by step like
    // this.
    ob_start();

    // Displays your current sessions
    echo "Your current sessions keys are : <br/>";
    $query = "select session_id from sessions_per_ip where ip = '{$ip}'";
    foreach ($dbh->query($query) as $row) {
        echo "{$row['session_id']}<br/>";
    }

    // Display and handle a way to create new sessions
    echo str_repeat('<br/>', 2);
    echo '<a href="' . basename(__FILE__) . '?new=1">Create a new session / reload</a>';
    if (isset($_GET['new']))
    {
        session_regenerate_id();
        session_destroy();
        header("Location: " . basename(__FILE__));
        die();
    }

    // Display if you're banned or not
    echo str_repeat('<br/>', 2);
    if ($banned)
    {
        echo '<span style="color:red;">You are banned: wait 60secs to be unbanned... a captcha must be more friendly of course!</span>';
        echo '<br/>';
        echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png" />';
    }
    else
    {
        echo '<span style="color:blue;">You are not banned!</span>';
        echo '<br/>';
        echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png" />';
    }
    ob_end_flush();
}
catch (PDOException $e)
{
    /*echo*/ $e->getMessage();
}

?>

Besuchszähler

Wenn Ihr Benutzer dasselbe Cookie zum Crawlen Ihrer Seiten verwendet, können Sie seine Sitzung zum Blockieren verwenden. Diese Idee ist ganz einfach: Ist es möglich, dass Ihr Benutzer 60 Seiten in 60 Sekunden besucht?

Idee:

  1. Erstellen Sie in der Benutzersitzung ein Array, das Besuchszeit () enthält.
  2. Besuche älter als X Sekunden in diesem Array entfernen
  3. Fügen Sie einen neuen Eintrag für den tatsächlichen Besuch hinzu 
  4. Anzahl der Einträge in diesem Array
  5. Sperren Sie Ihren Benutzer, wenn er Y-Seiten besucht hat

Beispielcode :

<?php

$visit_counter_pages = 5; // maximum number of pages to load
$visit_counter_secs = 10; // maximum amount of time before cleaning visits

session_start();

// initialize an array for our visit counter
if (array_key_exists('visit_counter', $_SESSION) == false)
{
    $_SESSION['visit_counter'] = array();
}

// clean old visits
foreach ($_SESSION['visit_counter'] as $key => $time)
{
    if ((time() - $time) > $visit_counter_secs) {
        unset($_SESSION['visit_counter'][$key]);
    }
}

// we add the current visit into our array
$_SESSION['visit_counter'][] = time();

// check if user has reached limit of visited pages
$banned = false;
if (count($_SESSION['visit_counter']) > $visit_counter_pages)
{
    // puts ip of our user on the same "banned table" as earlier...
    $banned = true;
}

// At this point you have a $banned if your user is banned or not.
// The following code will allow us to test it...

echo '<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>';

// Display counter
$count = count($_SESSION['visit_counter']);
echo "You visited {$count} pages.";
echo str_repeat('<br/>', 2);

echo <<< EOT

<a id="reload" href="#">Reload</a>

<script type="text/javascript">

  $('#reload').click(function(e) {
    e.preventDefault();
    window.location.reload();
  });

</script>

EOT;

echo str_repeat('<br/>', 2);

// Display if you're banned or not
echo str_repeat('<br/>', 2);
if ($banned)
{
    echo '<span style="color:red;">You are banned! Wait for a short while (10 secs in this demo)...</span>';
    echo '<br/>';
    echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png" />';
}
else
{
    echo '<span style="color:blue;">You are not banned!</span>';
    echo '<br/>';
    echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png" />';
}
?>

Ein Bild zum Herunterladen

Wenn ein Crawler seine schmutzige Arbeit erledigen muss, bedeutet dies für eine große Datenmenge und in kürzester Zeit. Deshalb laden sie keine Bilder auf Seiten herunter. es nimmt zu viel Bandbreite und macht das Krabbeln langsamer.

Diese Idee (ich denke am elegantesten und am einfachsten zu implementieren) verwendet mod_rewrite , um Code in einer .jpg/.png /… einer Image-Datei auszublenden. Dieses Bild sollte auf jeder Seite, die Sie schützen möchten, verfügbar sein: Es könnte sich um Ihre Logo-Website handeln, Sie müssen jedoch ein kleines Bild auswählen (da dieses Bild nicht zwischengespeichert werden darf).

Idee:

1/Fügen Sie diese Zeilen zu Ihrem .htaccess hinzu 

RewriteEngine On
RewriteBase /tests/anticrawl/
RewriteRule ^logo\.jpg$ logo.php

2/Erstelle dein logo.php mit der Sicherheit

<?php

// start session and reset counter
session_start();
$_SESSION['no_logo_count'] = 0;

// forces image to reload next time
header("Cache-Control: no-store, no-cache, must-revalidate");

// displays image
header("Content-type: image/jpg");
readfile("logo.jpg");
die();

3/Erhöhen Sie Ihren no_logo_count auf jeder Seite, die Sie zum Hinzufügen von Sicherheit benötigen, und prüfen Sie, ob er Ihr Limit erreicht hat.

Beispielcode :

<?php

$no_logo_limit = 5; // number of allowd pages without logo

// start session and initialize
session_start();
if (array_key_exists('no_logo_count', $_SESSION) == false)
{
    $_SESSION['no_logo_count'] = 0;
}
else
{
    $_SESSION['no_logo_count']++;
}

// check if user has reached limit of "undownloaded image"
$banned = false;
if ($_SESSION['no_logo_count'] >= $no_logo_limit)
{
    // puts ip of our user on the same "banned table" as earlier...
    $banned = true;
}

// At this point you have a $banned if your user is banned or not.
// The following code will allow us to test it...

echo '<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>';

// Display counter
echo "You did not loaded image {$_SESSION['no_logo_count']} times.";
echo str_repeat('<br/>', 2);

// Display "reload" link
echo <<< EOT

<a id="reload" href="#">Reload</a>

<script type="text/javascript">

  $('#reload').click(function(e) {
    e.preventDefault();
    window.location.reload();
  });

</script>

EOT;

echo str_repeat('<br/>', 2);

// Display "show image" link : note that we're using .jpg file
echo <<< EOT

<div id="image_container">
    <a id="image_load" href="#">Load image</a>
</div>
<br/>

<script type="text/javascript">

  // On your implementation, you'llO of course use <img src="logo.jpg" />
  $('#image_load').click(function(e) {
    e.preventDefault();
    $('#image_load').html('<img src="logo.jpg" />');
  });

</script>

EOT;

// Display if you're banned or not
echo str_repeat('<br/>', 2);
if ($banned)
{
    echo '<span style="color:red;">You are banned: click on "load image" and reload...</span>';
    echo '<br/>';
    echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png" />';
}
else
{
    echo '<span style="color:blue;">You are not banned!</span>';
    echo '<br/>';
    echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png" />';
}
?>

Cookie überprüfen

Sie können Cookies auf der Javascript-Seite erstellen, um zu prüfen, ob Ihre Benutzer Javascript interpretieren (ein Crawler, der Curl nicht verwendet, zum Beispiel).

Die Idee ist ziemlich einfach: Dies ist ungefähr das Gleiche wie eine Bildprüfung.

  1. Setzen Sie einen $ _SESSION-Wert auf 1 und erhöhen Sie ihn bei jedem Besuch
  2. wenn ein Cookie (in JavaScript festgelegt) vorhanden ist, setzen Sie den Sitzungswert auf 0
  3. wenn dieser Wert ein Limit erreicht hat, verbieten Sie Ihren Benutzer

Code:

<?php

$no_cookie_limit = 5; // number of allowd pages without cookie set check

// Start session and reset counter
session_start();

if (array_key_exists('cookie_check_count', $_SESSION) == false)
{
    $_SESSION['cookie_check_count'] = 0;
}

// Initializes cookie (note: rename it to a more discrete name of course) or check cookie value
if ((array_key_exists('cookie_check', $_COOKIE) == false) || ($_COOKIE['cookie_check'] != 42))
{
    // Cookie does not exist or is incorrect...
    $_SESSION['cookie_check_count']++;
}
else
{
    // Cookie is properly set so we reset counter
    $_SESSION['cookie_check_count'] = 0;
}

// Check if user has reached limit of "cookie check"
$banned = false;
if ($_SESSION['cookie_check_count'] >= $no_cookie_limit)
{
    // puts ip of our user on the same "banned table" as earlier...
    $banned = true;
}

// At this point you have a $banned if your user is banned or not.
// The following code will allow us to test it...

echo '<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>';

// Display counter
echo "Cookie check failed {$_SESSION['cookie_check_count']} times.";
echo str_repeat('<br/>', 2);

// Display "reload" link
echo <<< EOT

<br/>
<a id="reload" href="#">Reload</a>
<br/>

<script type="text/javascript">

  $('#reload').click(function(e) {
    e.preventDefault();
    window.location.reload();
  });

</script>

EOT;

// Display "set cookie" link
echo <<< EOT

<br/>
<a id="cookie_link" href="#">Set cookie</a>
<br/>

<script type="text/javascript">

  // On your implementation, you'll of course put the cookie set on a $(document).ready()
  $('#cookie_link').click(function(e) {
    e.preventDefault();
    var expires = new Date();
    expires.setTime(new Date().getTime() + 3600000);
    document.cookie="cookie_check=42;expires=" + expires.toGMTString();
  });

</script>
EOT;


// Display "unset cookie" link
echo <<< EOT

<br/>
<a id="unset_cookie" href="#">Unset cookie</a>
<br/>

<script type="text/javascript">

  // On your implementation, you'll of course put the cookie set on a $(document).ready()
  $('#unset_cookie').click(function(e) {
    e.preventDefault();
    document.cookie="cookie_check=;expires=Thu, 01 Jan 1970 00:00:01 GMT";
  });

</script>
EOT;

// Display if you're banned or not
echo str_repeat('<br/>', 2);
if ($banned)
{
    echo '<span style="color:red;">You are banned: click on "Set cookie" and reload...</span>';
    echo '<br/>';
    echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png" />';
}
else
{
    echo '<span style="color:blue;">You are not banned!</span>';
    echo '<br/>';
    echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png" />';
}

Schutz vor Stimmrechtsvertretern

Einige Worte zu den verschiedenen Arten von Proxies, die wir im Internet finden können:

  • Ein "normaler" Proxy zeigt Informationen über die Benutzerverbindung an (insbesondere seine IP).
  • Ein anonymer Proxy zeigt keine IP-Adresse an, gibt jedoch Informationen zur Verwendung des Proxys im Header an.
  • Ein hochanonymer Proxy zeigt keine Benutzer-IP und keine Informationen an, die ein Browser möglicherweise nicht sendet.

Es ist leicht, einen Proxy zu finden, um eine Website zu verbinden, aber es ist sehr schwierig, anonyme Proxys zu finden. 

Einige $ _SERVER-Variablen können Schlüssel enthalten, insbesondere wenn sich Ihre Benutzer hinter einem Proxy befinden (erschöpfende Liste von dieser Frage ):

  • CLIENT_IP
  • Weitergeleitet
  • FORWARDED_FOR
  • FORWARDED_FOR_IP
  • HTTP_CLIENT_IP
  • HTTP_FORWARDED
  • HTTP_FORWARDED_FOR
  • HTTP_FORWARDED_FOR_IP
  • HTTP_PC_REMOTE_ADDR
  • HTTP_PROXY_CONNECTION '
  • HTTP_VIA
  • HTTP_X_FORWARDED
  • HTTP_X_FORWARDED_FOR
  • HTTP_X_FORWARDED_FOR_IP
  • HTTP_X_IMFORWARDS
  • HTTP_XROXY_CONNECTION
  • VIA
  • X_FORWARDED
  • X_FORWARDED_FOR

Sie können Ihren Anti-Crawling-Wertpapieren ein anderes Verhalten geben (niedrigere Grenzwerte usw.), wenn Sie einen dieser Schlüssel in Ihrer $_SERVER-Variablen erkennen.


Fazit

Es gibt viele Möglichkeiten, Missbräuche auf Ihrer Website zu erkennen, so dass Sie sicher eine Lösung finden. Sie müssen jedoch genau wissen, wie Ihre Website verwendet wird, damit Ihre Wertpapiere gegenüber Ihren "normalen" Nutzern nicht aggressiv sind. 

95
Alain Tiemblo

Denken Sie daran: HTTP ist keine Zauberei. Mit jeder HTTP-Anforderung wird eine definierte Gruppe von Headern gesendet. Wenn diese Header vom Webbrowser gesendet werden, können sie auch von jedem anderen Programm gesendet werden - einschließlich cURL (und libcurl).

Einige halten es für einen Fluch, aber andererseits ist es ein Segen, da es die Funktionsprüfung von Webanwendungen erheblich vereinfacht.

UPDATE: Wie unr3al011 richtig bemerkt, führt curl kein JavaScript aus, daher ist es theoretisch möglich, eine Seite zu erstellen, die sich bei der Anzeige durch Grabber anders verhält. ( zum Beispiel durch Setzen und späteres Prüfen eines bestimmten Cookies durch JS).

Trotzdem wäre es eine sehr fragile Verteidigung. Die Daten der Seite mussten noch vom Server abgerufen werden - und diese HTTP-Anfrage (und es ist immer HTTP-Anfrage) kann durch Drehen emuliert werden. Überprüfen Sie diese Antwort zum Beispiel, wie eine solche Verteidigung besiegt wird.

... und ich habe nicht einmal erwähnt, dass einige Grabber JavaScript ausführen können . )

2
raina77ow

Sie können cURL-Useragent auf folgende Weise ermitteln. Seien Sie jedoch gewarnt, dass der Useragent vom Benutzer überschrieben werden könnte. Die Standardeinstellungen können jedoch durch Folgendes erkannt werden:

function is_curl() {
    if (stristr($_SERVER["HTTP_USER_AGENT"], 'curl'))
        return true;
}
0
Fusca Software

Um gefälschte Verweise zu vermeiden, wird der Benutzer verfolgt

Sie können den Benutzer anhand einer oder mehrerer dieser Methoden verfolgen:

  1. Speichern Sie ein Cookie im Browser-Client mit einem speziellen Code (z. B. letzte besuchte URL, Zeitstempel) und überprüfen Sie es in jeder Antwort Ihres Servers.

  2. Wie zuvor, jedoch mit Sitzungen anstelle von expliziten Cookies

Für Cookies sollten Sie die kryptografische Sicherheit wie hinzufügen.

[Cookie]
url => http://someurl/
hash => dsafdshfdslajfd

hash wird auf diese Weise in PHP berechnet

$url = $_COOKIE['url'];
$hash = $_COOKIE['hash'];
$secret = 'This is a fixed secret in the code of your application';

$isValidCookie = (hash('algo', $secret . $url) === $hash);

$isValidReferer = $isValidCookie & ($_SERVER['HTTP_REFERER'] === $url)
0
Maks3w