(Ceci a été écrit pour une question spécifique à PHP qui a été par la suite supprimée et liée ici comme un duplicata).
Disclaimer : Considérez l'impact du blocage de tous les utilisateurs de Tor comme indiqué dans la meilleure réponse ici. Envisagez de ne bloquer que les fonctions telles que l'enregistrement, le paiement, les commentaires, etc. et non un blocage général de tout.
--
Voici deux solutions purement PHP. La première télécharge et met en cache une liste de nœuds Tor et compare l'IP du visiteur avec cette liste. La seconde utilise la méthode Liste des sorties DNS de Tor pour déterminer si le visiteur utilise Tor via des vérifications DNS.
Méthode #1 (Vérifier l'IP par rapport à une liste de relais Tor) :
En utilisant l'ensemble des fonctions suivantes, nous pouvons déterminer si une IP appartient au réseau Tor en la comparant à une base de données dynamique. liste de sortie qui est téléchargé et mis en cache pendant 10 minutes. N'hésitez pas à utiliser cette liste mais, dans la mesure du possible, mettez-les en cache pendant 10 minutes.
Lorsque vous voulez appliquer la vérification de Tor, vous pouvez simplement utiliser :
$isTorUser = isTorUser($_SERVER['REMOTE_ADDR']);
if ($isTorUser) {
// blocking action
}
Voici le code que vous pouvez placer dans un fichier de fonctions séparé et inclure lorsque vous voulez exécuter la vérification. Notez que vous pouvez en ajuster une partie pour modifier le chemin d'accès au fichier de cache.
<?php
function isTorUser($ip)
{
$list = getTorExitList();
if (arrayBinarySearch($ip, $list) !== false) {
return true;
} else {
return false;
}
}
function getTorExitList()
{
$path = __DIR__ . '/tor-list.cache';
if ( file_exists($path) && time() - filemtime($path) < 600 ) {
$list = include $path;
if ($list && is_array($list)) {
return $list;
}
}
$data = file('https://www2.openinternet.io/tor/tor-exit-list.txt');
if (!$data) {
return array();
}
$list = array();
foreach($data as $line) {
$line = trim($line);
if ($line == '' || $line[0] == '#') continue;
list($nick, $ip) = explode("\t", $line);
$list[] = $ip;
}
sort($list);
file_put_contents($path, sprintf("<?php return %s;", var_export($list, true)));
return $list;
}
/**
* Perform binary search of a sorted array.
* Credit: http://php.net/manual/en/function.array-search.php#39115
*
* Tested by VigilanTor for accuracy and efficiency
*
* @param string $needle String to search for
* @param array $haystack Array to search within
* @return boolean|number false if not found, or index if found
*/
function arrayBinarySearch($needle, $haystack)
{
$high = count($haystack);
$low = 0;
while ($high - $low > 1){
$probe = ($high + $low) / 2;
if ($haystack[$probe] < $needle){
$low = $probe;
} else{
$high = $probe;
}
}
if ($high == count($haystack) || $haystack[$high] != $needle) {
return false;
} else {
return $high;
}
}
Méthode #2 (Vérifier l'IP par rapport au projet de liste de sortie DNS de Tor) :
La vérification de la sortie DNS est un peu plus robuste dans la mesure où elle prend en compte la politique de sortie du relais et regarde à quelle IP et à quel port de votre serveur le client se connecte et si ce trafic de sortie est autorisé, elle renvoie une correspondance. Si le trafic de sortie est autorisé, il renvoie une correspondance. L'inconvénient potentiel est que si le projet DNS est temporairement en panne, les requêtes DNS peuvent être suspendues avant de se terminer, ce qui ralentit les choses.
Pour cet exemple, je vais utiliser une classe d'une bibliothèque que j'ai écrite et que je maintiens appelée TorUtils .
Tout d'abord, vous devrez l'installer avec Composer en utilisant composer require dapphp/torutils
et inclure la norme vendor/autoloader.php
dans votre application.
Le code pour le contrôle : $isTor = false ;
try {
// check for Tor using the remote (client IP)
if (TorDNSEL::isTor($_SERVER['REMOTE_ADDR'])) {
// do something special for Tor users
} else {
// not using Tor, educate them! :-D
}
} catch (\Exception $ex) {
// This would likely be a timeout, or possibly a malformed DNS response
error_log("Tor DNSEL query failed: " . $ex->getMessage());
}
if ($isTor) {
// blocking action
}
Considérations supplémentaires
Si votre application utilise des sessions PHP, je vous suggère fortement de mettre en cache la réponse "isTorUser" dans la session (avec l'IP source) et de n'exécuter la vérification qu'au début ou lorsque l'IP change (par ex. $_SERVER['REMOTE_ADDR'] != $_SESSION['last_remote_addr']
) afin de ne pas effectuer de nombreuses recherches en double. Même s'ils essaient d'être très efficaces, c'est un gaspillage de faire plusieurs recherches pour la même IP.