How to detect Tor exit nodes?

Intro

Tor is a high anonymity network used by privacy and security minded folks to avoid being tracked or identified when conducting activities on the Internet. The network is made up of relays or nodes which are servers that are contributed and operated by volunteers.

When users desire privacy, they can use the Tor browser to access the Internet via the Tor network. Traffic on the Tor network is encrypted and travels from one node to another randomly selected node, with each successive node only knowing the next node in line. This makes it difficult to trace the origin of the traffic.

Protect your website by checking for Tor exit node

The last node in the Tor network before traffic is decrypted and sent to the final destination is called an exit node or exit relay. This node’s IP address is what appears when the destination websites check the visitor’s IP address. This means fraudsters could use the Tor network to hide their identities when trying to make fraudulent purchases on your website. Therefore, it’s vital to check for Tor exit nodes to mitigate such activities on your website.

Using IP2Proxy to detect Tor exit nodes

First of all, you have to download the IP2Proxy PX10 CSV database. Download the PX10 CSV database from https://www.ip2location.com/database/px10-ip-proxytype-country-region-city-isp-domain-usagetype-asn-lastseen-threat-residential.

Once you have downloaded the zipped file, you will need to extract the IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL.CSV file and save it somewhere, e.g. C:\mydata\.

For this example, we’ll be using MySQL to store and query the data via PHP.

To create the database and table, use the SQL below:

CREATE DATABASE ip2proxy;
USE ip2proxy;
CREATE TABLE `ip2proxy_px10`(
    `ip_from` INT(10) UNSIGNED,
    `ip_to` INT(10) UNSIGNED,
    `proxy_type` VARCHAR(3),
    `country_code` CHAR(2),
    `country_name` VARCHAR(64),
    `region_name` VARCHAR(128),
    `city_name` VARCHAR(128),
    `isp` VARCHAR(256),
    `domain` VARCHAR(128),
    `usage_type` VARCHAR(11),
    `asn` VARCHAR(6),
    `as` VARCHAR(256),
    `last_seen` INT(10),
    `threat` VARCHAR(128),
    PRIMARY KEY (`ip_from`, `ip_to`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Next, import the data using the SQL below:

LOAD DATA LOCAL
INFILE 'C:\\mydata\\IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL.CSV'
INTO TABLE `ip2proxy_px10`
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';

In your PHP webpage, you will need the following codes (remember to modify the code for your own MySQL username and password):

<?php
$ipaddress = getenv("REMOTE_ADDR");

$host = "localhost";
$dbname = "ip2proxy";
$user = "your_username";
$pwd = "your_password";

function Dot2LongIP ($IPaddr) {
  if ($IPaddr == "") {
    return 0;
  }
  else {
    $ips = explode(".", "$IPaddr");
    return ($ips[3] + $ips[2] * 256 + $ips[1] * 256 * 256 + $ips[0] * 256 * 256 * 256);
  }
}

try {
  $pdo = new PDO('mysql:host=' . $host . ';dbname=' . $dbname . ';charset=utf8', $user, $pwd);
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  
  $sql = "select `ip_from`, `ip_to`, `proxy_type`, `country_code`, `country_name`, `region_name`, `city_name`, `isp`, `domain`, `usage_type`, `asn`, `as`, `last_seen`, `threat` ";
  $sql .= "from `ip2proxy_px10` where :ipnum between `ip_from` and `ip_to` limit 1";
  
  $st = $pdo->prepare($sql);
  $ipnum = Dot2LongIP($ipaddress);
  $st->bindParam(':ipnum', $ipnum, PDO::PARAM_STR);
  $st->execute();
  
  $data = $st->fetchAll(PDO::FETCH_ASSOC);
  
  if (($st->rowCount() > 0) && ($data[0]["proxy_type"] == "TOR")) {
    echo "IP: " . $ipaddress . " is a Tor exit node<br />\n";
    echo "Proxy Type: " . $data[0]["proxy_type"] . "<br />\n";
    echo "Country Code: " . $data[0]["country_code"] . "<br />\n";
    echo "Country Name: " . $data[0]["country_name"] . "<br />\n";
    echo "Region: " . $data[0]["region_name"] . "<br />\n";
    echo "City: " . $data[0]["city_name"] . "<br />\n";
    echo "ISP: " . $data[0]["isp"] . "<br />\n";
    echo "Domain: " . $data[0]["domain"] . "<br />\n";
    echo "Usage Type: " . $data[0]["usage_type"] . "<br />\n";
    echo "ASN: " . $data[0]["asn"] . "<br />\n";
    echo "AS: " . $data[0]["as"] . "<br />\n";
    echo "Last Seen: " . $data[0]["last_seen"] . "<br />\n";
    echo "Threat: " . $data[0]["threat"] . "<br />\n";
  else {
    echo "IP: " . $ipaddress . " is NOT a Tor exit node<br />\n";
  }
}
catch(PDOException $e) {
  echo "Error: " . $e->getMessage() . "<br />\n";
}

?>

What the PHP code above does is get the website visitor’s IP address and then convert it to the equivalent IP number before querying the MySQL server for the results. If the IP address is found in the table and the proxy type is TOR then that IP address is a Tor exit node.

Was this article helpful?

Related Articles