tor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +1 -0
- data/CONTRIBUTORS +0 -0
- data/README +77 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/lib/tor.rb +61 -0
- data/lib/tor/dnsel.rb +148 -0
- data/lib/tor/version.rb +22 -0
- metadata +98 -0
data/AUTHORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* Arto Bendiken <arto.bendiken@gmail.com>
|
data/CONTRIBUTORS
ADDED
File without changes
|
data/README
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
Tor.rb: Onion Routing for Ruby
|
2
|
+
==============================
|
3
|
+
|
4
|
+
This is a Ruby library for interacting with the [Tor][] anonymity network.
|
5
|
+
|
6
|
+
* <http://github.com/bendiken/tor-ruby>
|
7
|
+
|
8
|
+
Features
|
9
|
+
--------
|
10
|
+
|
11
|
+
* Supports checking whether Tor is installed in the user's current `PATH`,
|
12
|
+
and if it is, returning the version number.
|
13
|
+
* Supports querying the [Tor DNS Exit List (DNSEL)][TorDNSEL] to determine
|
14
|
+
whether a particular host is a Tor exit node or not.
|
15
|
+
|
16
|
+
Examples
|
17
|
+
--------
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'tor'
|
21
|
+
|
22
|
+
### Checking whether Tor is installed and which version it is
|
23
|
+
|
24
|
+
Tor.available? #=> true
|
25
|
+
Tor.version #=> "0.2.1.25"
|
26
|
+
|
27
|
+
### Checking whether a particular host is a Tor exit node
|
28
|
+
|
29
|
+
Tor::DNSEL.include?("208.75.57.100") #=> true
|
30
|
+
Tor::DNSEL.include?("1.2.3.4") #=> false
|
31
|
+
|
32
|
+
Documentation
|
33
|
+
-------------
|
34
|
+
|
35
|
+
* <http://cypherpunk.rubyforge.org/tor/>
|
36
|
+
|
37
|
+
Dependencies
|
38
|
+
------------
|
39
|
+
|
40
|
+
* [Ruby](http://ruby-lang.org/) (>= 1.8.7) or (>= 1.8.1 with [Backports][])
|
41
|
+
|
42
|
+
Installation
|
43
|
+
------------
|
44
|
+
|
45
|
+
The recommended installation method is via [RubyGems](http://rubygems.org/).
|
46
|
+
To install the latest official release of Tor.rb, do:
|
47
|
+
|
48
|
+
% [sudo] gem install tor # Ruby 1.8.7+ or 1.9.x
|
49
|
+
% [sudo] gem install backports tor # Ruby 1.8.1+
|
50
|
+
|
51
|
+
Download
|
52
|
+
--------
|
53
|
+
|
54
|
+
To get a local working copy of the development repository, do:
|
55
|
+
|
56
|
+
% git clone git://github.com/bendiken/tor-ruby.git
|
57
|
+
|
58
|
+
Alternatively, you can download the latest development version as a tarball
|
59
|
+
as follows:
|
60
|
+
|
61
|
+
% wget http://github.com/bendiken/tor-ruby/tarball/master
|
62
|
+
|
63
|
+
Author
|
64
|
+
------
|
65
|
+
|
66
|
+
* [Arto Bendiken](mailto:arto.bendiken@gmail.com) - <http://ar.to/>
|
67
|
+
|
68
|
+
License
|
69
|
+
-------
|
70
|
+
|
71
|
+
Tor.rb is free and unencumbered public domain software. For more
|
72
|
+
information, see <http://unlicense.org/> or the accompanying UNLICENSE file.
|
73
|
+
|
74
|
+
[Tor]: https://www.torproject.org/
|
75
|
+
[TorDNSEL]: https://www.torproject.org/tordnsel/
|
76
|
+
[OR]: http://en.wikipedia.org/wiki/Onion_routing
|
77
|
+
[Backports]: http://rubygems.org/gems/backports
|
data/UNLICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
4
|
+
distribute this software, either in source code form or as a compiled
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
6
|
+
means.
|
7
|
+
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
9
|
+
of this software dedicate any and all copyright interest in the
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
11
|
+
of the public at large and to the detriment of our heirs and
|
12
|
+
successors. We intend this dedication to be an overt act of
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
14
|
+
software under copyright law.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
For more information, please refer to <http://unlicense.org/>
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/tor.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
if RUBY_VERSION < '1.8.7'
|
2
|
+
# @see http://rubygems.org/gems/backports
|
3
|
+
begin
|
4
|
+
require 'backports/1.8.7'
|
5
|
+
rescue LoadError
|
6
|
+
begin
|
7
|
+
require 'rubygems'
|
8
|
+
require 'backports/1.8.7'
|
9
|
+
rescue LoadError
|
10
|
+
abort "Tor.rb requires Ruby 1.8.7 or the Backports gem (hint: `gem install backports')."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# @see https://www.torproject.org/
|
17
|
+
module Tor
|
18
|
+
autoload :DNSEL, 'tor/dnsel'
|
19
|
+
autoload :VERSION, 'tor/version'
|
20
|
+
|
21
|
+
##
|
22
|
+
# Returns `true` if Tor is available, `false` otherwise.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Tor.available? #=> true
|
26
|
+
#
|
27
|
+
# @return [Boolean]
|
28
|
+
def self.available?
|
29
|
+
!!program_path
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Returns the Tor version number, or `nil` if Tor is not available.
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# Tor.version #=> "0.2.1.25"
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
def self.version
|
40
|
+
if available? && `#{program_path} --version` =~ /Tor v(\d+)\.(\d+)\.(\d+)\.(\d+)/
|
41
|
+
[$1, $2, $3, $4].join('.')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Returns the path to the `tor` executable, or `nil` if the program could
|
47
|
+
# not be found in the user's current `PATH` environment.
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# Tor.program_path #=> "/opt/local/bin/tor"
|
51
|
+
#
|
52
|
+
# @param [String, #to_s] program_name
|
53
|
+
# @return [String]
|
54
|
+
def self.program_path(program_name = :tor)
|
55
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
56
|
+
program_path = File.join(path, program_name.to_s)
|
57
|
+
return program_path if File.executable?(program_path)
|
58
|
+
end
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
end
|
data/lib/tor/dnsel.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'resolv' unless defined?(Resolv)
|
2
|
+
|
3
|
+
module Tor
|
4
|
+
##
|
5
|
+
# Tor DNS Exit List (DNSEL) client.
|
6
|
+
#
|
7
|
+
# Unless the target IP address and port are explicitly specified, the
|
8
|
+
# query will be performed using a target IP address of "8.8.8.8" and a
|
9
|
+
# target port of 53. These correspond to the DNS protocol port on one of
|
10
|
+
# the [Google Public DNS](http://code.google.com/speed/public-dns/)
|
11
|
+
# servers, and they are guaranteed to be reachable from Tor's default exit
|
12
|
+
# policy.
|
13
|
+
#
|
14
|
+
# @example Checking source IP addresses
|
15
|
+
# Tor::DNSEL.include?("208.75.57.100") #=> true
|
16
|
+
# Tor::DNSEL.include?("1.2.3.4") #=> false
|
17
|
+
#
|
18
|
+
# @example Checking source hostnames
|
19
|
+
# Tor::DNSEL.include?("ennui.lostinthenoise.net") #=> true
|
20
|
+
# Tor::DNSEL.include?("myhost.example.org") #=> false
|
21
|
+
#
|
22
|
+
# @example Specifying an explicit target port
|
23
|
+
# Tor::DNSEL.include?("208.75.57.100", :port => 80) #=> true
|
24
|
+
# Tor::DNSEL.include?("208.75.57.100", :port => 25) #=> false
|
25
|
+
#
|
26
|
+
# @example Specifying an explicit target IP address and port
|
27
|
+
# Tor::DNSEL.include?(source_addr, :addr => target_addr, :port => target_port)
|
28
|
+
# Tor::DNSEL.include?("208.75.57.100", :addr => myip, :port => myport)
|
29
|
+
#
|
30
|
+
# @example Using from a Rack application
|
31
|
+
# Tor::DNSEL.include?(env['REMOTE_ADDR'] || env['REMOTE_HOST'], {
|
32
|
+
# :addr => env['SERVER_NAME'],
|
33
|
+
# :port => env['SERVER_PORT'],
|
34
|
+
# })
|
35
|
+
#
|
36
|
+
# @see https://www.torproject.org/tordnsel/
|
37
|
+
# @see https://trac.torproject.org/projects/tor/wiki/TheOnionRouter/TorDNSExitList
|
38
|
+
# @see http://gitweb.torproject.org/tor.git?a=blob_plain;hb=HEAD;f=doc/contrib/torel-design.txt
|
39
|
+
module DNSEL
|
40
|
+
RESOLVER = Resolv::DefaultResolver unless defined?(RESOLVER)
|
41
|
+
TARGET_ADDR = '8.8.8.8'.freeze unless defined?(TARGET_ADDR) # Google Public DNS
|
42
|
+
TARGET_PORT = 53 unless defined?(TARGET_PORT) # DNS
|
43
|
+
DNS_SUFFIX = 'ip-port.exitlist.torproject.org'.freeze
|
44
|
+
|
45
|
+
##
|
46
|
+
# Returns `true` if the Tor DNSEL includes `host`, `false` otherwise.
|
47
|
+
#
|
48
|
+
# If the DNS server is unreachable or the DNS query times out, returns
|
49
|
+
# `nil` to indicate that we don't have a definitive answer one way or
|
50
|
+
# another.
|
51
|
+
#
|
52
|
+
# @example
|
53
|
+
# Tor::DNSEL.include?("208.75.57.100") #=> true
|
54
|
+
# Tor::DNSEL.include?("1.2.3.4") #=> false
|
55
|
+
#
|
56
|
+
# @param [String, #to_s] host
|
57
|
+
# @param [Hash{Symbol => Object}] options
|
58
|
+
# @option options [String, #to_s] :addr ("8.8.8.8")
|
59
|
+
# @option options [Integer, #to_i] :port (53)
|
60
|
+
# @return [Boolean]
|
61
|
+
def self.include?(host, options = {})
|
62
|
+
begin
|
63
|
+
query(host, options) == '127.0.0.2'
|
64
|
+
rescue Resolv::ResolvError # NXDOMAIN
|
65
|
+
false
|
66
|
+
rescue Resolv::ResolvTimeout
|
67
|
+
nil
|
68
|
+
rescue Errno::EHOSTUNREACH
|
69
|
+
nil
|
70
|
+
rescue Errno::EADDRNOTAVAIL
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Queries the Tor DNSEL for `host`, returning "172.0.0.2" if it is an
|
77
|
+
# exit node and raising a `Resolv::ResolvError` if it isn't.
|
78
|
+
#
|
79
|
+
# @example
|
80
|
+
# Tor::DNSEL.query("208.75.57.100") #=> "127.0.0.2"
|
81
|
+
# Tor::DNSEL.query("1.2.3.4") #=> Resolv::ResolvError
|
82
|
+
#
|
83
|
+
# @param [String, #to_s] host
|
84
|
+
# @param [Hash{Symbol => Object}] options
|
85
|
+
# @option options [String, #to_s] :addr ("8.8.8.8")
|
86
|
+
# @option options [Integer, #to_i] :port (53)
|
87
|
+
# @return [String]
|
88
|
+
# @raise [Resolv::ResolvError] for an NXDOMAIN response
|
89
|
+
def self.query(host, options = {})
|
90
|
+
getaddress(dnsname(host, options))
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Returns the DNS name used for Tor DNSEL queries of `host`.
|
95
|
+
#
|
96
|
+
# @example
|
97
|
+
# Tor::DNSEL.dnsname("1.2.3.4") #=> "4.3.2.1.53.8.8.8.8.ip-port.exitlist.torproject.org"
|
98
|
+
#
|
99
|
+
# @param [String, #to_s] host
|
100
|
+
# @param [Hash{Symbol => Object}] options
|
101
|
+
# @option options [String, #to_s] :addr ("8.8.8.8")
|
102
|
+
# @option options [Integer, #to_i] :port (53)
|
103
|
+
# @return [String]
|
104
|
+
def self.dnsname(host, options = {})
|
105
|
+
source_addr = getaddress(host, true)
|
106
|
+
target_addr = getaddress(options[:addr] || TARGET_ADDR, true)
|
107
|
+
target_port = options[:port] || TARGET_PORT
|
108
|
+
[source_addr, target_port, target_addr, DNS_SUFFIX].join('.')
|
109
|
+
end
|
110
|
+
class << self; alias_method :hostname, :dnsname; end
|
111
|
+
|
112
|
+
protected
|
113
|
+
|
114
|
+
##
|
115
|
+
# Resolves `host` into an IPv4 address using Ruby's default resolver.
|
116
|
+
#
|
117
|
+
# Optionally returns the IPv4 address with its octet order reversed.
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
# Tor::DNSEL.getaddress("ruby-lang.org") #=> "221.186.184.68"
|
121
|
+
# Tor::DNSEL.getaddress("1.2.3.4") #=> "1.2.3.4"
|
122
|
+
# Tor::DNSEL.getaddress("1.2.3.4", true) #=> "4.3.2.1"
|
123
|
+
#
|
124
|
+
# @param [String, #to_s] host
|
125
|
+
# @param [Boolean] reversed
|
126
|
+
# @return [String]
|
127
|
+
def self.getaddress(host, reversed = false)
|
128
|
+
host = case host.to_s
|
129
|
+
when Resolv::IPv6::Regex
|
130
|
+
raise ArgumentError.new("not an IPv4 address: #{host}")
|
131
|
+
when Resolv::IPv4::Regex
|
132
|
+
host.to_s
|
133
|
+
else
|
134
|
+
begin
|
135
|
+
RESOLVER.each_address(host.to_s) do |addr|
|
136
|
+
return addr.to_s if addr.to_s =~ Resolv::IPv4::Regex
|
137
|
+
end
|
138
|
+
raise Resolv::ResolvError.new("no address for #{host}")
|
139
|
+
rescue NoMethodError
|
140
|
+
# This is a workaround for Ruby bug #2614:
|
141
|
+
# @see http://redmine.ruby-lang.org/issues/show/2614
|
142
|
+
raise Resolv::ResolvError.new("no address for #{host}")
|
143
|
+
end
|
144
|
+
end
|
145
|
+
reversed ? host.split('.').reverse.join('.') : host
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
data/lib/tor/version.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Tor
|
2
|
+
module VERSION
|
3
|
+
MAJOR = 0
|
4
|
+
MINOR = 1
|
5
|
+
TINY = 0
|
6
|
+
EXTRA = nil
|
7
|
+
|
8
|
+
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [String]
|
12
|
+
def self.to_s() STRING end
|
13
|
+
|
14
|
+
##
|
15
|
+
# @return [String]
|
16
|
+
def self.to_str() STRING end
|
17
|
+
|
18
|
+
##
|
19
|
+
# @return [Array(Integer, Integer, Integer)]
|
20
|
+
def self.to_a() [MAJOR, MINOR, TINY] end
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Arto Bendiken
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-08-01 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: yard
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 5
|
30
|
+
- 8
|
31
|
+
version: 0.5.8
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rspec
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 1
|
43
|
+
- 3
|
44
|
+
- 0
|
45
|
+
version: 1.3.0
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
description: Tor.rb is a pure-Ruby library for interacting with the Tor anonymity network.
|
49
|
+
email: or-talk@seul.org
|
50
|
+
executables: []
|
51
|
+
|
52
|
+
extensions: []
|
53
|
+
|
54
|
+
extra_rdoc_files: []
|
55
|
+
|
56
|
+
files:
|
57
|
+
- AUTHORS
|
58
|
+
- CONTRIBUTORS
|
59
|
+
- README
|
60
|
+
- UNLICENSE
|
61
|
+
- VERSION
|
62
|
+
- lib/tor/dnsel.rb
|
63
|
+
- lib/tor/version.rb
|
64
|
+
- lib/tor.rb
|
65
|
+
has_rdoc: false
|
66
|
+
homepage: http://github.com/bendiken/tor-ruby
|
67
|
+
licenses:
|
68
|
+
- Public Domain
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
segments:
|
79
|
+
- 1
|
80
|
+
- 8
|
81
|
+
- 1
|
82
|
+
version: 1.8.1
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
requirements:
|
91
|
+
- Tor (>= 0.2.1.25)
|
92
|
+
rubyforge_project: cypherpunk
|
93
|
+
rubygems_version: 1.3.6
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: Onion routing for Ruby.
|
97
|
+
test_files: []
|
98
|
+
|