Raw import from Trac using Trac markup language. authored by Alexander Hansen Færøy's avatar Alexander Hansen Færøy
[[TOC]]
Note: This service is being replaced with [https://blog.torproject.org/blog/torbel-tor-bulk-exit-list-tools TorBEL]
= Introduction =
It is useful for a variety of reasons to determine if a connection is coming from a Tor node. Early attempts to determine if a given IP address was a Tor exit used the directory to match IP addresses and exit policies. This approach had a number of drawbacks, including false negatives when a Tor router exits traffic from a different IP address than its OR port listens on. The [https://www.torproject.org/svn/trunk/doc/contrib/torel-design.txt Tor DNS-based Exit List] was designed to overcome these problems and provide a simple interface for answering the question: is this a Tor exit?
= Implementation =
An implementation of the Tor DNS Exit List has been completed at [http://exitlist.torproject.org/ exitlist.torproject.org]. DNS queries are answered via this host in the manner described in the design document. The exit nodes are tested regularly to avoid the false negatives when inspecting the directory entries alone.
A web front end for this service is available at [http://check.torproject.org/ check.torproject.org].
Sources for the tordnsel are available at [http://p56soo2ibjkx23xo.onion/darcs/tordnsel p56soo2ibjkx23xo.onion/darcs/tordnsel]. You can sync with the following commands through an http proxy at port 8118 forwarding to Tor:
{{{
env http_proxy=http://127.0.0.1:8118/
darcs get http://p56soo2ibjkx23xo.onion/darcs/tordnsel
}}}
= Examples =
The following examples describe how to utilize this service in various ways. Please add to this list if you have implemented hooks for a language or framework not provided below.
[http://www.tokobungasabana.com Toko bunga] - [http://www.tokobungasabana.com Toko bunga jakarta] - [http://www.goldenfibreglass.com/product-tangki-fiberglass.php Tangki fiberglass] - [http://www.goldenfibreglass.com/product-atap-fiberglass.php Atap fiberglass] - [http://www.forklift.co.id Rental forklift] [https://www.floweradvisor.co.id Toko bunga jakarta]
== Ruby & Tor.rb ==
You will need the [http://cypherpunk.rubyforge.org/tor/ Tor.rb] gem installed for the following to work.
{{{
require 'rubygems'
require 'tor'
Tor::DNSEL.include?("208.75.57.100") #=> true
Tor::DNSEL.include?("1.2.3.4") #=> false
}}}
== PHP Pear Net_DNS ==
You will need the [http://pear.php.net/package/Net_DNS Pear Net_DNS module] for this to work properly:
{{{
include("Net/DNS.php");
// torel_check ($ip, $port, $destip) queries the Tor DNS Exit List server.
// The result of the query is one of the following:
// -1 : DNS lookup failed to get a response, or other error occurred.
// 0 : $ip does not appear to be a Tor exit.
// 1 : $ip is a known Tor exit for the provided destination IP / port.
function revaddr ($ip) {
list($a, $b, $c, $d) = split("[.]", $ip);
return("${d}.${c}.${b}.${a}");
}
function torel_qh ($ip, $port, $destip) {
$rsrcip = revaddr ($ip);
$rdstip = revaddr ($destip);
return("${rsrcip}.${port}.${rdstip}.ip-port.exitlist.torproject.org");
}
function torel_check ($ip, $port, $destip) {
$ndr = new Net_DNS_Resolver();
$qh = torel_qh($ip, $port, $destip);
// uncomment these two lines to query the server directly...
//$ns = "exitlist-ns.torproject.org";
//$ndr->nameservers( array($ns) );
// tune DNS params accordingly. this is just my preference.
$ndr->retrans = 2;
$ndr->retry = 3;
$ndr->usevc = 0;
// perform DNS query
if (! $pkt = $ndr->search($qh)) {
if (strcmp($ndr->errorstring, "NXDOMAIN") == 0) {
// response but no answer. does not appear to be Tor exit.
return (0);
}
// search failed: no response or other problem...
return(-1);
}
if (! isset($pkt->answer[0])) {
// response but no answer section. does not appear to be Tor exit.
// (this should only happen when authority sections are provided without answer)
return(0);
}
// is Tor exit
return(1);
}
// get client request parameters from Apache or equiv server:
$ip = $myip = $myport = 0;
if (isset ($_SERVER["REMOTE_ADDR"])) { $ip = $_SERVER["REMOTE_ADDR"]; }
if (isset ($_SERVER["SERVER_ADDR"])) { $myip = $_SERVER["SERVER_ADDR"]; }
if (isset ($_SERVER["SERVER_PORT"])) { $myport = $_SERVER["SERVER_PORT"]; }
$istor = torel_check($ip, $myport, $myip);
// use $istor as needed for altering page behavior:
if ($istor < 0) {
// DNS query failed to get an answer
}
elseif ($istor) {
// Endpoint is a known Tor exit
}
else {
// Endpoint does not appear to be a Tor exit
}
}}}
== Perl Net::DNS ==
You will need the [http://www.net-dns.org/ Net::DNS module] and its dependencies for this to work properly.
{{{
#!/usr/local/bin/perl
use strict;
use warnings;
# query_exitlist($srcip, $dstip, $dstport) queries the Tor DNS Exit List server.
# The result of the query is one of the following:
# undef : DNS lookup failed or an unexpected response was received.
# 0 : $srcip does not appear to be a Tor exit.
# 1 : $srcip is a known Tor exit for the provided destination IP / port.
use Getopt::Long;
use Net::DNS::Resolver;
# Construct a DNSEL query from a source address and destination address/port.
# IP addresses should be in dotted-decimal notation.
sub build_query {
my ($srcip, $dstip, $dstport) = @_;
# reverse address octets
($srcip, $dstip) = map { join '.', reverse split /\./ } $srcip, $dstip;
"$srcip.$dstport.$dstip.ip-port.exitlist.torproject.org.";
}
sub query_exitlist {
my ($srcip, $dstip, $dstport) = @_;
my $res = Net::DNS::Resolver->new;
# uncomment this line to query the server directly...
#$res->nameservers("exitlist-ns.torproject.org");
# tune DNS params accordingly. this is just my preference.
$res->retrans(2);
$res->retry(3);
$res->usevc(0);
# perform DNS query
if (defined(my $pkt = $res->send(build_query $srcip, $dstip, $dstport))) {
if (grep $_->type eq 'A', $pkt->answer) {
# an A record was returned: this is a Tor exit node
return 1;
} elsif ($pkt->header->rcode eq 'NXDOMAIN') {
# NXDOMAIN: this is not a Tor exit node
return 0;
}
}
# the DNS query failed or something unexpected was returned
return undef;
}
# defaults, get options...
my $srcip = "82.227.101.236";
my $dstip = "1.2.3.4";
my $dstport = 80;
my $pstatus = GetOptions(
"srcip=s" => \$srcip,
"dstip=s" => \$dstip,
"dstport=i" => \$dstport
);
$| = 1;
# perform the lookup...
print "Querying Tor DNS Exit List for IP $srcip to destination $dstip at port $dstport ... ";
my $result = query_exitlist $srcip, $dstip, $dstport;
print "Done.\n";
if ($result) {
print "$srcip is a known Tor exit to $dstip at port $dstport.\n";
} elsif (defined $result) {
print "$srcip does not appear to be a Tor exit.\n";
} else {
print "DNS query failed or an unexpected DNS response was received.\n";
exit 1;
}
}}}
Invocation:
{{{
# using defaults
torelcheck.pl
Querying Tor DNS Exit List for IP 82.227.101.236 to destination 1.2.3.4 at port 80 ... Done.
82.227.101.236 is a known Tor exit to 1.2.3.4 at port 80.
# using explicit check
torelcheck.pl --srcip 71.111.92.174 --dstip 66.135.40.74 --dstport 80
Querying Tor DNS Exit List for IP 71.111.92.174 to destination 66.135.40.74 at port 80 ... Done.
71.111.92.174 does not appear to be a Tor exit.
}}}
== Dig command line ==
The DNS query tool "dig" can also be used to make manual queries as described on the torel page. Remember to reverse the IP address octets in the query sent:
{{{
dig 236.101.227.82.80.74.40.135.66.ip-port.exitlist.torproject.org
}}}
In the response below, the 127.0.0.2 address in the answer section means this endpoint, 82.227.101.236, is indeed a Tor exit to port 80:
{{{
; <<>> DiG 9.3.2 <<>> 236.101.227.82.80.74.40.135.66.ip-port.exitlist.torproject.org
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56277
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;236.101.227.82.80.74.40.135.66.ip-port.exitlist.torproject.org. IN A
;; ANSWER SECTION:
236.101.227.82.80.74.40.135.66.ip-port.exitlist.torproject.org. 579 IN A 127.0.0.2
;; Query time: 31 msec
;; SERVER: 4.2.2.2#53(4.2.2.2)
;; WHEN: Sun Jun 17 21:57:12 2007
;; MSG SIZE rcvd: 96
}}}
\ No newline at end of file