Module: Tor::DNSEL

Defined in:
lib/tor/dnsel.rb

Overview

Tor DNS Exit List (DNSEL) client.

Unless the target IP address and port are explicitly specified, the query will be performed using a target IP address of “8.8.8.8” and a target port of 53. These correspond to the DNS protocol port on one of the [Google Public DNS](code.google.com/speed/public-dns/) servers, and they are guaranteed to be reachable from Tor’s default exit policy.

Examples:

Checking source IP addresses

Tor::DNSEL.include?("208.75.57.100")               #=> true
Tor::DNSEL.include?("1.2.3.4")                     #=> false

Checking source hostnames

Tor::DNSEL.include?("ennui.lostinthenoise.net")    #=> true
Tor::DNSEL.include?("myhost.example.org")          #=> false

Specifying an explicit target port

Tor::DNSEL.include?("208.75.57.100", :port => 80)  #=> true
Tor::DNSEL.include?("208.75.57.100", :port => 25)  #=> false

Specifying an explicit target IP address and port

Tor::DNSEL.include?(source_addr, :addr => target_addr, :port => target_port)
Tor::DNSEL.include?("208.75.57.100", :addr => myip, :port => myport)

Using from a Rack application

Tor::DNSEL.include?(env['REMOTE_ADDR'] || env['REMOTE_HOST'], {
  :addr => env['SERVER_NAME'],
  :port => env['SERVER_PORT'],
})

See Also:

Constant Summary collapse

RESOLVER =
Resolv::DefaultResolver
TARGET_ADDR =

Google Public DNS

'8.8.8.8'.freeze
TARGET_PORT =

DNS

53
DNS_SUFFIX =
'ip-port.exitlist.torproject.org'.freeze

Class Method Summary collapse

Class Method Details

.dnsname(host, options = {}) ⇒ String Also known as: hostname

Returns the DNS name used for Tor DNSEL queries of ‘host`.

Examples:

Tor::DNSEL.dnsname("1.2.3.4")           #=> "4.3.2.1.53.8.8.8.8.ip-port.exitlist.torproject.org"

Parameters:

  • host (String, #to_s)
  • options (Hash{Symbol => Object}) (defaults to: {})

Options Hash (options):

  • :addr (String, #to_s) — default: "8.8.8.8"
  • :port (Integer, #to_i) — default: 53

Returns:

  • (String)


104
105
106
107
108
109
# File 'lib/tor/dnsel.rb', line 104

def self.dnsname(host, options = {})
  source_addr = getaddress(host, true)
  target_addr = getaddress(options[:addr] || TARGET_ADDR, true)
  target_port = options[:port] || TARGET_PORT
  [source_addr, target_port, target_addr, DNS_SUFFIX].join('.')
end

.include?(host, options = {}) ⇒ Boolean

Returns ‘true` if the Tor DNSEL includes `host`, `false` otherwise.

If the DNS server is unreachable or the DNS query times out, returns ‘nil` to indicate that we don’t have a definitive answer one way or another.

Examples:

Tor::DNSEL.include?("208.75.57.100")    #=> true
Tor::DNSEL.include?("1.2.3.4")          #=> false

Parameters:

  • host (String, #to_s)
  • options (Hash{Symbol => Object}) (defaults to: {})

Options Hash (options):

  • :addr (String, #to_s) — default: "8.8.8.8"
  • :port (Integer, #to_i) — default: 53

Returns:

  • (Boolean)


61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/tor/dnsel.rb', line 61

def self.include?(host, options = {})
  begin
    query(host, options) == '127.0.0.2'
  rescue Resolv::ResolvError   # NXDOMAIN
    false
  rescue Resolv::ResolvTimeout
    nil
  rescue Errno::EHOSTUNREACH
    nil
  rescue Errno::EADDRNOTAVAIL
    nil
  end
end

.query(host, options = {}) ⇒ String

Queries the Tor DNSEL for ‘host`, returning “172.0.0.2” if it is an exit node and raising a `Resolv::ResolvError` if it isn’t.

Examples:

Tor::DNSEL.query("208.75.57.100")       #=> "127.0.0.2"
Tor::DNSEL.query("1.2.3.4")             #=> Resolv::ResolvError

Parameters:

  • host (String, #to_s)
  • options (Hash{Symbol => Object}) (defaults to: {})

Options Hash (options):

  • :addr (String, #to_s) — default: "8.8.8.8"
  • :port (Integer, #to_i) — default: 53

Returns:

  • (String)

Raises:

  • (Resolv::ResolvError)

    for an NXDOMAIN response



89
90
91
# File 'lib/tor/dnsel.rb', line 89

def self.query(host, options = {})
  getaddress(dnsname(host, options))
end