Added TorProject to ThirdParty

This commit is contained in:
Zi Xing 2021-12-18 00:03:05 -05:00
parent a836a24826
commit 260535840f
10 changed files with 517 additions and 4 deletions

33
database/onion.sql Normal file
View File

@ -0,0 +1,33 @@
create table if not exists onion
(
ip_address varchar(126) not null comment 'The primary IP address for this record'
primary key,
ip_version int null comment 'The version of the IP address',
nickname varchar(19) null comment 'Relay nickname consisting of 119 alphanumerical characters. ',
fingerprint varchar(40) null comment 'Relay fingerprint consisting of 40 upper-case hexadecimal characters. ',
or_addresses mediumblob null comment 'Array of IPv4 or IPv6 addresses and TCP ports or port lists where the relay accepts onion-routing connections. The first address is the primary onion-routing address that the relay used to register in the network, subsequent addresses are in arbitrary order. IPv6 hex characters are all lower-case. ',
exit_addresses mediumblob null comment 'Array of IPv4 addresses that the relay used to exit to the Internet in the past 24 hours. Omitted if array is empty. ',
dir_address varchar(126) null comment 'IPv4 address where the relay accepts directory connections. Omitted if the relay does not accept directory connections. ',
dir_port int null comment 'The TCP port used for the dir address',
last_seen_timestamp int null comment 'The Unix Timestamp for when this relay was last seen in the network status consensus',
last_changed_address_or_port int null comment 'Unix Timestamp for when this relay last stopped announcing an IPv4 or IPv6 address or TCP port where it previously accepted onion-routing or directory connections. This timestamp can serve as indicator whether this relay would be a suitable fallback directory. ',
first_seen int null comment 'Unix Timestamp when this relay was first seen in a network status consensus. ',
flags mediumblob null comment 'ZiProto encoded array of relay flags that the directory authorities assigned to this relay. May be omitted if empty. ',
running tinyint(1) null comment 'Boolean field saying whether this relay was listed as running in the last relay network status consensus. ',
`exit` tinyint(1) null comment 'Indicates if the exit flag is present',
fast tinyint(1) null comment 'Indicates if the fast flag is present',
guard tinyint(1) null comment 'Indicates if the guard flag is present',
stable tinyint(1) null comment 'Indicates if the stable flag is present',
valid tinyint(1) null comment 'Indicates if the valid flag is present',
contact text null comment 'Contact address of the relay operator. Omitted if empty or if descriptor containing this information cannot be found. ',
platform varchar(255) null comment 'Platform string containing operating system and Tor version details. Omitted if empty or if descriptor containing this information cannot be found. ',
version varchar(32) null comment 'Tor software version without leading "Tor" as reported by the directory authorities in the "v" line of the consensus. Omitted if either the directory authorities or the relay did not report which version the relay runs or if the relay runs an alternative Tor implementation. ',
version_status varchar(64) null comment 'Status of the Tor software version of this relay based on the versions recommended by the directory authorities. Possible version statuses are: "recommended" if a version is listed as recommended; "experimental" if a version is newer than every recommended version; "obsolete" if a version is older than every recommended version; "new in series" if a version has other recommended versions with the same first three components, and the version is newer than all such recommended versions, but it is not newer than every recommended version; "unrecommended" if none of the above conditions hold. Omitted if either the directory authorities did not recommend versions, or the relay did not report which version it runs. ',
consensus_weight int null comment 'Weight assigned to this relay by the directory authorities that clients use in their path selection algorithm. The unit is arbitrary; currently it''s kilobytes per second, but that might change in the future. ',
last_updated_timestamp int null comment 'The Unix Timestamp for when this record was last updated',
created_timestamp int null comment 'The Unix Timestamp for when this record was registered into the database',
constraint onion_ip_address_uindex
unique (ip_address)
)
comment 'Table for housing known Onion relays';

View File

@ -2,7 +2,7 @@
namespace khm\Abstracts;
class GeoLookupSource
abstract class GeoLookupSource
{
const ipApi = 'ip-api.com';

View File

@ -0,0 +1,16 @@
<?php
namespace khm\Abstracts;
abstract class OnionVersionStatus
{
const Recommended = 'recommended';
const Experimental = 'experimental';
const Obsolete = 'obsolete';
const NewInSeries = 'new in series';
const Unrecommended = 'unrecommended';
}

View File

@ -0,0 +1,328 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace khm\Objects;
use khm\Abstracts\OnionVersionStatus;
class OnionRelay
{
/**
* The IP address of the relay
*
* @var string
*/
public $IPAddress;
/**
* The version of the IP address being used
*
* @var int
*/
public $IPVersion;
/**
* Relay nickname consisting of 119 alphanumerical characters.
*
* @var string
*/
public $Nickname;
/**
* Relay fingerprint consisting of 40 upper-case hexadecimal characters.
*
* @var string
*/
public $Fingerprint;
/**
* Array of IPv4 or IPv6 addresses and TCP ports or port lists where the relay accepts onion-routing connections.
* The first address is the primary onion-routing address that the relay used to register in the network,
* subsequent addresses are in arbitrary order. IPv6 hex characters are all lower-case.
*
* @var string[]
*/
public $OrAddresses;
/**
* Array of IPv4 addresses that the relay used to exit to the Internet in the past 24 hours.
* Omitted if array is empty.
*
* @var string[]
*/
public $ExitAddresses;
/**
* IPv4 address where the relay accepts directory connections.
* Omitted if the relay does not accept directory connections.
*
* @var string|null
*/
public $DirAddress;
/**
* TCP port where the relay accepts directory connections.
* Omitted if the relay does not accept directory connections.
*
* @var int|null
*/
public $DirPort;
/**
* Unix Timestamp for when this relay was last seen in a network status consensus.
*
* @var int
*/
public $LastSeenTimestamp;
/**
* Unix Timestamp for when this relay last stopped announcing an IPv4 or IPv6 address or TCP port where it
* previously accepted onion-routing or directory connections. This timestamp can serve as indicator whether
* this relay would be a suitable fallback directory.
*
* @var int
*/
public $LastChangedAddressOrPort;
/**
* Unix Timestamp for when this relay was first seen in a network status consensus.
*
* @var int
*/
public $FirstSeen;
/**
* Array of relay flags that the directory authorities assigned to this relay. May be omitted if empty.
*
* @var array
*/
public $Flags;
/**
* Boolean field saying whether this relay was listed as running in the last relay network status consensus.
*
* @var bool
*/
public $Running;
/**
* Indicates if the exit flag is present
*
* @var bool
*/
public $Exit;
/**
* Indicates if the fast flag is present
*
* @var bool
*/
public $Fast;
/**
* Indicates if the guard flag is present
*
* @var bool
*/
public $Guard;
/**
* Indicates if the stable flag is present
*
* @var bool
*/
public $Stable;
/**
* Indicates if the valid flag is present
*
* @var bool
*/
public $Valid;
/**
* Contact address of the relay operator. Omitted if empty or if descriptor containing this information
* cannot be found.
*
* @var string|null
*/
public $Contact;
/**
* Platform string containing operating system and Tor version details. Omitted if empty or if descriptor
* containing this information cannot be found.
*
* @var string|null
*/
public $Platform;
/**
* Tor software version without leading "Tor" as reported by the directory authorities in the "v" line of the
* consensus. Omitted if either the directory authorities or the relay did not report which version the
* relay runs or if the relay runs an alternative Tor implementation.
*
* @var string|null
*/
public $Version;
/**
* Status of the Tor software version of this relay based on the versions recommended by the directory
* authorities. Possible version statuses are: "recommended" if a version is listed as recommended;
* "experimental" if a version is newer than every recommended version; "obsolete" if a version is older
* than every recommended version; "new in series" if a version has other recommended versions with the
* same first three components, and the version is newer than all such recommended versions, but it is not
* newer than every recommended version; "unrecommended" if none of the above conditions hold. Omitted if
* either the directory authorities did not recommend versions, or the relay did not report which version it runs.
*
* @var string|OnionVersionStatus|null
*/
public $VersionStatus;
/**
* Weight assigned to this relay by the directory authorities that clients use in their path selection
* algorithm. The unit is arbitrary; currently it's kilobytes per second, but that might change in the future.
*
* @var int
*/
public $ConsensusWeight;
/**
* The Unix Timestamp for when this record was last updated
*
* @var int
*/
public $LastUpdatedTimestmap;
/**
* The Unix Timestamp for when this record was first registered into the database
*
* @var int
*/
public $CreatedTimestmap;
/**
* Returns an array representation of the object
*
* @return array
* @noinspection PhpCastIsUnnecessaryInspection
*/
public function toArray(): array
{
return [
'ip_address' => $this->IPAddress,
'ip_version' => (int)$this->IPVersion,
'nickname' => $this->Nickname,
'fingerprint' => $this->Fingerprint,
'or_addresses' => $this->OrAddresses,
'exit_addresses' => $this->ExitAddresses,
'dir_address' => $this->DirAddress,
'dir_port' => (int)$this->DirPort,
'last_seen_timestamp' => (int)$this->LastSeenTimestamp,
'last_changed_address_or_port' => (int)$this->LastChangedAddressOrPort,
'first_seen' => (int)$this->FirstSeen,
'flags' => $this->Flags,
'running' => (bool)$this->Running,
'exit' => (bool)$this->Exit,
'fast' => (bool)$this->Fast,
'guard' => (bool)$this->Guard,
'stable' => (bool)$this->Stable,
'valid' => (bool)$this->Valid,
'contact' => $this->Contact,
'platform' => $this->Platform,
'version' => $this->Version,
'version_status' => $this->VersionStatus,
'consensus_weight' => (int)$this->ConsensusWeight,
'last_updated_timestamp' => (int)$this->LastUpdatedTimestmap,
'created_timestamp' => (int)$this->CreatedTimestmap
];
}
/**
* Constructs object from an array representation
*
* @param array $data
* @return OnionRelay
*/
public static function fromArray(array $data): OnionRelay
{
$OnionRelayObject = new OnionRelay();
if(isset($data['ip_address']))
$OnionRelayObject->IPAddress = $data['ip_address'];
if(isset($data['ip_version']))
$OnionRelayObject->IPVersion = (int)$data['ip_version'];
if(isset($data['nickname']))
$OnionRelayObject->Nickname = $data['nickname'];
if(isset($data['fingerprint']))
$OnionRelayObject->Fingerprint = $data['fingerprint'];
if(isset($data['or_addresses']))
$OnionRelayObject->OrAddresses = $data['or_addresses'];
if(isset($data['exit_addresses']))
$OnionRelayObject->ExitAddresses = $data['exit_addresses'];
if(isset($data['dir_address']))
$OnionRelayObject->DirAddress = $data['dir_address'];
if(isset($data['dir_port']))
$OnionRelayObject->DirPort = (int)$data['dir_port'];
if(isset($data['last_seen_timestamp']))
$OnionRelayObject->LastSeenTimestamp = (int)$data['last_seen_timestamp'];
if(isset($data['last_changed_address_or_port']))
$OnionRelayObject->LastChangedAddressOrPort = (int)$data['last_changed_address_or_port'];
if(isset($data['first_seen']))
$OnionRelayObject->FirstSeen = (int)$data['first_seen'];
if(isset($data['flags']))
$OnionRelayObject->Flags = $data['flags'];
if(isset($data['running']))
$OnionRelayObject->Running = (bool)$data['running'];
if(isset($data['exit']))
$OnionRelayObject->Exit = (bool)$data['exit'];
if(isset($data['fast']))
$OnionRelayObject->Fast = (bool)$data['fast'];
if(isset($data['guard']))
$OnionRelayObject->Guard = (bool)$data['guard'];
if(isset($data['stable']))
$OnionRelayObject->Stable = (bool)$data['stable'];
if(isset($data['valid']))
$OnionRelayObject->Valid = (bool)$data['valid'];
if(isset($data['contact']))
$OnionRelayObject->Contact = $data['contact'];
if(isset($data['platform']))
$OnionRelayObject->Platform = $data['platform'];
if(isset($data['version']))
$OnionRelayObject->Version = $data['version'];
if(isset($data['version_status']))
$OnionRelayObject->VersionStatus = $data['version_status'];
if(isset($data['consensus_weight']))
$OnionRelayObject->ConsensusWeight = $data['consensus_weight'];
if(isset($data['last_updated_timestamp']))
$OnionRelayObject->LastUpdatedTimestmap = (int)$data['last_updated_timestamp'];
if(isset($data['created_timestamp']))
$OnionRelayObject->CreatedTimestmap = (int)$data['created_timestamp'];
return $OnionRelayObject;
}
}

View File

@ -149,7 +149,7 @@
* @return GeoLookup[]
* @throws Exception
*/
public function get_batch(array $query): array
public function getBatch(array $query): array
{
$payload = $this->buildPayload($query);
return $this->wait()->request_batch($payload);

117
src/khm/ThirdParty/TorProject.php vendored Normal file
View File

@ -0,0 +1,117 @@
<?php
namespace khm\ThirdParty;
use khm\Objects\OnionRelay;
use WpOrg\Requests\Requests;
class TorProject
{
/**
* Returns an array of onion relays from the Tor network
*
* @return OnionRelay[]
*/
public static function getRelays(): array
{
$data = json_decode(Requests::get('https://onionoo.torproject.org/details')->body, true);
$results = [];
foreach($data['relays'] as $relay)
{
$onion_relay = new OnionRelay();
// match the main ip address
foreach ($relay['or_addresses'] as $or_address)
{
preg_match('/^\[?([0-9a-f:.]*)]?:\d+$/', $or_address, $or_address_matches);
if (count($or_address_matches) === 2)
{
$onion_relay->IPAddress = $or_address_matches[1];
}
}
if (filter_var($onion_relay->IPAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
$onion_relay->IPVersion = 4;
if (filter_var($onion_relay->IPAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
$onion_relay->IPVersion = 6;
if(isset($relay['nickname']))
$onion_relay->Nickname = $relay['nickname'];
if(isset($relay['fingerprint']))
$onion_relay->Fingerprint = $relay['fingerprint'];
if(isset($relay['or_addresses']))
{
$onion_relay->OrAddresses = $relay['or_addresses'];
}
else
{
$onion_relay->OrAddresses = [];
}
if(isset($relay['exit_addresses']))
{
$onion_relay->ExitAddresses = $relay['exit_addresses'];
}
else
{
$onion_relay->ExitAddresses = [];
}
if(isset($relay['dir_address']))
{
$parsed = explode(':', $relay['dir_address']);
$onion_relay->DirAddress = $parsed[0];
$onion_relay->DirPort = (int)$parsed[1];
}
if(isset($relay['last_seen']))
$onion_relay->LastSeenTimestamp = strtotime($relay['last_seen']);
if(isset($relay['last_changed_address_or_port']))
$onion_relay->LastChangedAddressOrPort = strtotime($relay['last_changed_address_or_port']);
if(isset($relay['first_seen']))
$onion_relay->FirstSeen = strtotime($relay['first_seen']);
if(isset($relay['running']))
$onion_relay->Running = (bool)$relay['running'];
if(isset($relay['flags']))
{
$onion_relay->Flags = $relay['flags'];
$onion_relay->Exit = in_array('Exit', $relay['flags']);
$onion_relay->Fast = in_array('Fast', $relay['flags']);
$onion_relay->Guard = in_array('Guard', $relay['flags']);
$onion_relay->Stable = in_array('Stable', $relay['flags']);
$onion_relay->Valid = in_array('Valid', $relay['flags']);
}
/** @noinspection DuplicatedCode */
if(isset($relay['contact']))
$onion_relay->Contact = $relay['contact'];
if(isset($relay['platform']))
$onion_relay->Platform = $relay['platform'];
if(isset($relay['version']))
$onion_relay->Version = $relay['version'];
if(isset($relay['version_status']))
$onion_relay->VersionStatus = $relay['version_status'];
if(isset($relay['consensus_weight']))
$onion_relay->ConsensusWeight = $relay['consensus_weight'];
$onion_relay->LastUpdatedTimestmap = time();
$onion_relay->CreatedTimestmap = time();
$results[] = $onion_relay;
}
return $results;
}
}

View File

@ -241,6 +241,7 @@
* @param array $query
* @return array
* @throws Exceptions\DatabaseException
* @throws Exception
*/
public function multipleGeoLookup(array $query): array
{
@ -276,7 +277,7 @@
}
}
foreach($api->get_batch(array_merge($new_queries, $update_queries)) as $lookup)
foreach($api->getBatch(array_merge($new_queries, $update_queries)) as $lookup)
{
if(in_array($lookup->IPAddress, $update_queries))
{

View File

@ -45,6 +45,10 @@
"required": true,
"file": "Abstracts/GeoLookupSource.php"
},
{
"required": true,
"file": "Abstracts/OnionVersionStatus.php"
},
{
"required": true,
"file": "Classes/Curl.php"
@ -73,6 +77,10 @@
"required": true,
"file": "Exceptions/BadGeoSourceException.php"
},
{
"required": true,
"file": "ThirdParty/TorProject.php"
},
{
"required": true,
"file": "ThirdParty/IpAPI.php"
@ -93,6 +101,10 @@
"required": true,
"file": "Objects/GeoLookup.php"
},
{
"required": true,
"file": "Objects/OnionRelay.php"
},
{
"required": true,
"file": "Managers/GeoManager.php"

View File

@ -34,7 +34,7 @@
]);
var_dump($api->get('91.198.174.192'));
var_dump($api->get_batch([
var_dump($api->getBatch([
'100.142.29.254',
'100.142.39.218'
]));

6
tests/tor_lookup.php Normal file
View File

@ -0,0 +1,6 @@
<?php
require 'ppm';
require 'net.intellivoid.khm';
var_dump(\khm\ThirdParty\TorProject::getRelays());