tor 0.1.0 → 0.1.5
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.
- checksums.yaml +7 -0
- data/AUTHORS +1 -0
- data/{CONTRIBUTORS → CREDITS} +0 -0
- data/README +1 -0
- data/VERSION +1 -1
- data/lib/tor.rb +30 -2
- data/lib/tor/config.rb +103 -0
- data/lib/tor/control.rb +310 -0
- data/lib/tor/dnsel.rb +11 -59
- data/lib/tor/version.rb +1 -1
- metadata +55 -66
- data/README +0 -77
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7be2c2b80fea90e1b3e9567624a442d4b3d1a92946f72d6b465280ad4b5d0ec8
|
4
|
+
data.tar.gz: 96358536b8479ea4fba83fb236dabb6b743074c058a48a6fbfe435bf00ab5bbc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b961dc19ac6f692cbade5226a895782c311cf6463fd228595ee4044085de9340f6948e852c981649c63abfd0abd01665d3fd7cabf2970815be6f87541b8158ee
|
7
|
+
data.tar.gz: cbecd4beddfd8d543d79233ea2f116609204550f0366a091aacac9573eae593e08c2d5c663020b56713ea6fc46b6dbb2ca39aa6b4e0e1686bb30d6ae7c7b2a7c
|
data/AUTHORS
CHANGED
data/{CONTRIBUTORS → CREDITS}
RENAMED
File without changes
|
data/README
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
./README.md
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.5
|
data/lib/tor.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
1
3
|
if RUBY_VERSION < '1.8.7'
|
2
4
|
# @see http://rubygems.org/gems/backports
|
3
5
|
begin
|
@@ -15,8 +17,32 @@ end
|
|
15
17
|
##
|
16
18
|
# @see https://www.torproject.org/
|
17
19
|
module Tor
|
18
|
-
|
19
|
-
|
20
|
+
require_relative 'tor/config'
|
21
|
+
require_relative 'tor/control'
|
22
|
+
require_relative 'tor/dnsel'
|
23
|
+
require_relative 'tor/version'
|
24
|
+
|
25
|
+
##
|
26
|
+
# Returns `true` if the Tor process is running locally, `false` otherwise.
|
27
|
+
#
|
28
|
+
# This works by attempting to establish a Tor Control Protocol (TC)
|
29
|
+
# connection to the standard control port 9051 on `localhost`. If Tor
|
30
|
+
# hasn't been configured with the `ControlPort 9051` option, this will
|
31
|
+
# return `false`.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# Tor.running? #=> false
|
35
|
+
#
|
36
|
+
# @return [Boolean]
|
37
|
+
# @since 0.1.2
|
38
|
+
def self.running?
|
39
|
+
begin
|
40
|
+
Tor::Controller.new.quit
|
41
|
+
true
|
42
|
+
rescue Errno::ECONNREFUSED
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
20
46
|
|
21
47
|
##
|
22
48
|
# Returns `true` if Tor is available, `false` otherwise.
|
@@ -39,6 +65,8 @@ module Tor
|
|
39
65
|
def self.version
|
40
66
|
if available? && `#{program_path} --version` =~ /Tor v(\d+)\.(\d+)\.(\d+)\.(\d+)/
|
41
67
|
[$1, $2, $3, $4].join('.')
|
68
|
+
elsif available? && `#{program_path} --version` =~ /Tor version (\d+)\.(\d+)\.(\d+)\.(\d+)/
|
69
|
+
[$1, $2, $3, $4].join('.')
|
42
70
|
end
|
43
71
|
end
|
44
72
|
|
data/lib/tor/config.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module Tor
|
2
|
+
##
|
3
|
+
# Tor configuration.
|
4
|
+
#
|
5
|
+
# @example Parsing a Tor configuration file (1)
|
6
|
+
# torrc = Tor::Config.load("/etc/tor/torrc")
|
7
|
+
#
|
8
|
+
# @example Parsing a Tor configuration file (2)
|
9
|
+
# Tor::Config.open("/etc/tor/torrc") do |torrc|
|
10
|
+
# puts "Tor SOCKS port: #{torrc['SocksPort']}"
|
11
|
+
# puts "Tor control port: #{torrc['ControlPort']}"
|
12
|
+
# puts "Tor exit policy:"
|
13
|
+
# torrc.each('ExitPolicy') do |key, value|
|
14
|
+
# puts " #{value}"
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# @see https://www.torproject.org/tor-manual.html.en
|
19
|
+
# @since 0.1.2
|
20
|
+
class Config
|
21
|
+
CONFDIR = '/etc/tor' unless defined?(CONFDIR)
|
22
|
+
|
23
|
+
##
|
24
|
+
# Opens a Tor configuration file.
|
25
|
+
#
|
26
|
+
# @param [String, #to_s] filename
|
27
|
+
# @param [Hash{Symbol => Object}] options
|
28
|
+
# @yield [config]
|
29
|
+
# @yieldparam [Config] config
|
30
|
+
# @return [Config]
|
31
|
+
def self.open(filename, options = {}, &block)
|
32
|
+
if block_given?
|
33
|
+
block.call(self.load(filename, options))
|
34
|
+
else
|
35
|
+
self.load(filename, options)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Loads the configuration options from a Tor configuration file.
|
41
|
+
#
|
42
|
+
# @param [String, #to_s] filename
|
43
|
+
# @param [Hash{Symbol => Object}] options
|
44
|
+
# @return [Config]
|
45
|
+
def self.load(filename, options = {})
|
46
|
+
self.new(options) do |config|
|
47
|
+
File.open(filename.to_s, 'rb') do |file|
|
48
|
+
file.each_line do |line|
|
49
|
+
case line = line.strip.chomp.strip
|
50
|
+
when '' then next # skip empty lines
|
51
|
+
when /^#/ then next # skip comments
|
52
|
+
else line = line.split('#').first.strip
|
53
|
+
end
|
54
|
+
# TODO: support for unquoting and unescaping values
|
55
|
+
config << line.split(/\s+/, 2)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# @param [Hash{Symbol => Object}] options
|
63
|
+
# @yield [config]
|
64
|
+
# @yieldparam [Config] config
|
65
|
+
def initialize(options = {}, &block)
|
66
|
+
@lines, @options = [], options.dup
|
67
|
+
block.call(self) if block_given?
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Appends a new configuration option.
|
72
|
+
#
|
73
|
+
# @param [Array(String, String)]
|
74
|
+
# @return [Config]
|
75
|
+
def <<(kv)
|
76
|
+
@lines << kv
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Looks up the last value of a particular configuration option.
|
82
|
+
#
|
83
|
+
# @param [String, Regexp] key
|
84
|
+
# @return [String]
|
85
|
+
def [](key)
|
86
|
+
values = each(key).map(&:last)
|
87
|
+
values.empty? ? nil : values.last
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Enumerates configuration options.
|
92
|
+
#
|
93
|
+
# @param [String, Regexp] key
|
94
|
+
# @yield [key, value]
|
95
|
+
# @yieldparam [String] key
|
96
|
+
# @yieldparam [String] value
|
97
|
+
# @return [Enumerator]
|
98
|
+
def each(key = nil, &block)
|
99
|
+
return enum_for(:each, key) unless block_given?
|
100
|
+
key ? @lines.find_all { |k, v| key === k }.each(&block) : @lines.each(&block)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/tor/control.rb
ADDED
@@ -0,0 +1,310 @@
|
|
1
|
+
require 'socket' unless defined?(Socket)
|
2
|
+
|
3
|
+
module Tor
|
4
|
+
##
|
5
|
+
# Tor Control Protocol (TC) client.
|
6
|
+
#
|
7
|
+
# The Tor control protocol is used by other programs (such as frontend
|
8
|
+
# user interfaces) to communicate with a locally running Tor process. It
|
9
|
+
# is not part of the Tor onion routing protocol.
|
10
|
+
#
|
11
|
+
# @example Establishing a controller connection (1)
|
12
|
+
# tor = Tor::Controller.new
|
13
|
+
#
|
14
|
+
# @example Establishing a controller connection (2)
|
15
|
+
# tor = Tor::Controller.new(:host => '127.0.0.1', :port => 9051)
|
16
|
+
#
|
17
|
+
# @example Authenticating the controller connection
|
18
|
+
# tor.authenticate
|
19
|
+
#
|
20
|
+
# @example Obtaining information about the Tor process
|
21
|
+
# tor.version #=> "0.2.1.25"
|
22
|
+
# tor.config_file #=> #<Pathname:/opt/local/etc/tor/torrc>
|
23
|
+
#
|
24
|
+
# @see http://gitweb.torproject.org/tor.git?a=blob_plain;hb=HEAD;f=doc/spec/control-spec.txt
|
25
|
+
# @see http://www.thesprawl.org/memdump/?entry=8
|
26
|
+
# @since 0.1.1
|
27
|
+
class Controller
|
28
|
+
PROTOCOL_VERSION = 1
|
29
|
+
|
30
|
+
##
|
31
|
+
# @param [Hash{Symbol => Object}] options
|
32
|
+
# @option options [String, #to_s] :host ("127.0.0.1")
|
33
|
+
# @option options [Integer, #to_i] :port (9051)
|
34
|
+
# @option options [String, #to_s] :cookie (nil)
|
35
|
+
# @option options [Integer, #to_i] :version (PROTOCOL_VERSION)
|
36
|
+
def self.connect(options = {}, &block)
|
37
|
+
if block_given?
|
38
|
+
result = block.call(tor = self.new(options))
|
39
|
+
tor.quit
|
40
|
+
result
|
41
|
+
else
|
42
|
+
self.new(options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# @param [Hash{Symbol => Object}] options
|
48
|
+
# @option options [String, #to_s] :host ("127.0.0.1")
|
49
|
+
# @option options [Integer, #to_i] :port (9051)
|
50
|
+
# @option options [String, #to_s] :cookie (nil)
|
51
|
+
# @option options [Integer, #to_i] :version (PROTOCOL_VERSION)
|
52
|
+
def initialize(options = {}, &block)
|
53
|
+
@options = options.dup
|
54
|
+
@host = (@options.delete(:host) || '127.0.0.1').to_s
|
55
|
+
@port = (@options.delete(:port) || 9051).to_i
|
56
|
+
@version = (@options.delete(:version) || PROTOCOL_VERSION).to_i
|
57
|
+
connect
|
58
|
+
if block_given?
|
59
|
+
block.call(self)
|
60
|
+
quit
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
attr_reader :host, :port
|
65
|
+
|
66
|
+
##
|
67
|
+
# Establishes the socket connection to the Tor process.
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# tor.close
|
71
|
+
# tor.connect
|
72
|
+
#
|
73
|
+
# @return [void]
|
74
|
+
def connect
|
75
|
+
close
|
76
|
+
@socket = TCPSocket.new(@host, @port)
|
77
|
+
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Returns `true` if the controller connection is active.
|
83
|
+
#
|
84
|
+
# @example
|
85
|
+
# tor.connected? #=> true
|
86
|
+
# tor.close
|
87
|
+
# tor.connected? #=> false
|
88
|
+
#
|
89
|
+
# @return [Boolean]
|
90
|
+
def connected?
|
91
|
+
!!@socket
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Closes the socket connection to the Tor process.
|
96
|
+
#
|
97
|
+
# @example
|
98
|
+
# tor.close
|
99
|
+
#
|
100
|
+
# @return [void]
|
101
|
+
def close
|
102
|
+
@socket.close if @socket
|
103
|
+
@socket = nil
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Tells the Tor process to hang up on this controller connection.
|
109
|
+
#
|
110
|
+
# This command can be used before authenticating.
|
111
|
+
#
|
112
|
+
# @example
|
113
|
+
# C: QUIT
|
114
|
+
# S: 250 closing connection
|
115
|
+
# ^D
|
116
|
+
#
|
117
|
+
# @example
|
118
|
+
# tor.quit
|
119
|
+
#
|
120
|
+
# @return [void]
|
121
|
+
def quit
|
122
|
+
send_line('QUIT')
|
123
|
+
reply = read_reply
|
124
|
+
close
|
125
|
+
reply
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Returns information about the authentication method required by the
|
130
|
+
# Tor process.
|
131
|
+
#
|
132
|
+
# This command may be used before authenticating.
|
133
|
+
#
|
134
|
+
# @example
|
135
|
+
# C: PROTOCOLINFO
|
136
|
+
# S: 250-PROTOCOLINFO 1
|
137
|
+
# S: 250-AUTH METHODS=NULL
|
138
|
+
# S: 250-VERSION Tor="0.2.1.25"
|
139
|
+
# S: 250 OK
|
140
|
+
#
|
141
|
+
# @example
|
142
|
+
# tor.authentication_method #=> nil
|
143
|
+
# tor.authentication_method #=> :hashedpassword
|
144
|
+
# tor.authentication_method #=> :cookie
|
145
|
+
#
|
146
|
+
# @return [Symbol]
|
147
|
+
# @since 0.1.2
|
148
|
+
def authentication_method
|
149
|
+
@authentication_method ||= begin
|
150
|
+
method = nil
|
151
|
+
send_line('PROTOCOLINFO')
|
152
|
+
loop do
|
153
|
+
# TODO: support for reading multiple authentication methods
|
154
|
+
case reply = read_reply
|
155
|
+
when /^250-AUTH METHODS=(\w*)/
|
156
|
+
method = $1.strip.downcase.to_sym
|
157
|
+
method = method.eql?(:null) ? nil : method
|
158
|
+
when /^250-/ then next
|
159
|
+
when '250 OK' then break
|
160
|
+
end
|
161
|
+
end
|
162
|
+
method
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Returns `true` if the controller connection has been authenticated.
|
168
|
+
#
|
169
|
+
# @example
|
170
|
+
# tor.authenticated? #=> false
|
171
|
+
# tor.authenticate
|
172
|
+
# tor.authenticated? #=> true
|
173
|
+
#
|
174
|
+
# @return [Boolean]
|
175
|
+
def authenticated?
|
176
|
+
@authenticated || false
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# Authenticates the controller connection.
|
181
|
+
#
|
182
|
+
# @example
|
183
|
+
# C: AUTHENTICATE
|
184
|
+
# S: 250 OK
|
185
|
+
#
|
186
|
+
# @example
|
187
|
+
# tor.authenticate
|
188
|
+
#
|
189
|
+
# @return [void]
|
190
|
+
# @raise [AuthenticationError] if authentication failed
|
191
|
+
def authenticate(cookie = nil)
|
192
|
+
cookie ||= @options[:cookie]
|
193
|
+
send(:send_line, cookie ? "AUTHENTICATE #{cookie}" : "AUTHENTICATE")
|
194
|
+
case reply = read_reply
|
195
|
+
when '250 OK' then @authenticated = true
|
196
|
+
else raise AuthenticationError.new(reply)
|
197
|
+
end
|
198
|
+
self
|
199
|
+
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# Returns the version number of the Tor process.
|
203
|
+
#
|
204
|
+
# @example
|
205
|
+
# C: GETINFO version
|
206
|
+
# S: 250-version=0.2.1.25
|
207
|
+
# S: 250 OK
|
208
|
+
#
|
209
|
+
# @example
|
210
|
+
# tor.version #=> "0.2.1.25"
|
211
|
+
#
|
212
|
+
# @return [String]
|
213
|
+
def version
|
214
|
+
send_command(:getinfo, 'version')
|
215
|
+
reply = read_reply.split('=').last
|
216
|
+
read_reply # skip "250 OK"
|
217
|
+
reply
|
218
|
+
end
|
219
|
+
|
220
|
+
##
|
221
|
+
# Returns the path to the Tor configuration file.
|
222
|
+
#
|
223
|
+
# @example
|
224
|
+
# C: GETINFO config-file
|
225
|
+
# S: 250-config-file=/opt/local/etc/tor/torrc
|
226
|
+
# S: 250 OK
|
227
|
+
#
|
228
|
+
# @example
|
229
|
+
# tor.config_file #=> #<Pathname:/opt/local/etc/tor/torrc>
|
230
|
+
#
|
231
|
+
# @return [Pathname]
|
232
|
+
def config_file
|
233
|
+
send_command(:getinfo, 'config-file')
|
234
|
+
reply = read_reply.split('=').last
|
235
|
+
read_reply # skip "250 OK"
|
236
|
+
Pathname(reply)
|
237
|
+
end
|
238
|
+
|
239
|
+
##
|
240
|
+
# Returns the current (in-memory) Tor configuration.
|
241
|
+
# Response is terminated with a "."
|
242
|
+
#
|
243
|
+
# @example
|
244
|
+
# C: GETINFO config-text
|
245
|
+
# S: 250+config-text=
|
246
|
+
# S: ControlPort 9051
|
247
|
+
# S: RunAsDaemon 1
|
248
|
+
# S: .
|
249
|
+
def config_text
|
250
|
+
send_command(:getinfo, 'config-text')
|
251
|
+
reply = ""
|
252
|
+
read_reply # skip "250+config-text="
|
253
|
+
while line = read_reply
|
254
|
+
break unless line != "."
|
255
|
+
reply.concat(line + "\n")
|
256
|
+
end
|
257
|
+
read_reply # skip "250 OK"
|
258
|
+
return reply
|
259
|
+
end
|
260
|
+
|
261
|
+
##
|
262
|
+
# Send a signal to the server
|
263
|
+
#
|
264
|
+
# @example
|
265
|
+
# tor.signal("newnym")
|
266
|
+
#
|
267
|
+
# @return [String]
|
268
|
+
def signal(name)
|
269
|
+
send_command(:signal, name)
|
270
|
+
read_reply
|
271
|
+
end
|
272
|
+
|
273
|
+
protected
|
274
|
+
|
275
|
+
##
|
276
|
+
# Sends a command line over the socket.
|
277
|
+
#
|
278
|
+
# @param [Symbol, #to_s] command
|
279
|
+
# @param [Array<String>] args
|
280
|
+
# @return [void]
|
281
|
+
def send_command(command, *args)
|
282
|
+
authenticate unless authenticated?
|
283
|
+
send_line(["#{command.to_s.upcase}", *args].join(' '))
|
284
|
+
end
|
285
|
+
|
286
|
+
##
|
287
|
+
# Sends a text line over the socket.
|
288
|
+
#
|
289
|
+
# @param [String, #to_s] line
|
290
|
+
# @return [void]
|
291
|
+
def send_line(line)
|
292
|
+
@socket.write(line.to_s + "\r\n")
|
293
|
+
@socket.flush
|
294
|
+
end
|
295
|
+
|
296
|
+
##
|
297
|
+
# Reads a reply line from the socket.
|
298
|
+
#
|
299
|
+
# @return [String]
|
300
|
+
def read_reply
|
301
|
+
@socket.readline.chomp
|
302
|
+
end
|
303
|
+
|
304
|
+
##
|
305
|
+
# Used to signal an authentication error.
|
306
|
+
#
|
307
|
+
# @see Tor::Controller#authenticate
|
308
|
+
class AuthenticationError < StandardError; end
|
309
|
+
end
|
310
|
+
end
|
data/lib/tor/dnsel.rb
CHANGED
@@ -1,66 +1,26 @@
|
|
1
1
|
require 'resolv' unless defined?(Resolv)
|
2
2
|
|
3
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
4
|
module DNSEL
|
40
5
|
RESOLVER = Resolv::DefaultResolver unless defined?(RESOLVER)
|
41
|
-
|
42
|
-
TARGET_PORT = 53 unless defined?(TARGET_PORT) # DNS
|
43
|
-
DNS_SUFFIX = 'ip-port.exitlist.torproject.org'.freeze
|
6
|
+
DNS_SUFFIX = 'dnsel.torproject.org'.freeze
|
44
7
|
|
45
8
|
##
|
46
|
-
# Returns `true` if
|
9
|
+
# Returns `true` if `host` is a Tor Exit Node, `false` otherwise.
|
47
10
|
#
|
48
11
|
# If the DNS server is unreachable or the DNS query times out, returns
|
49
12
|
# `nil` to indicate that we don't have a definitive answer one way or
|
50
13
|
# another.
|
51
14
|
#
|
52
15
|
# @example
|
53
|
-
# Tor::DNSEL.include?("
|
16
|
+
# Tor::DNSEL.include?("185.220.101.21") #=> true
|
54
17
|
# Tor::DNSEL.include?("1.2.3.4") #=> false
|
55
18
|
#
|
56
19
|
# @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
20
|
# @return [Boolean]
|
61
|
-
def self.include?(host
|
21
|
+
def self.include?(host)
|
62
22
|
begin
|
63
|
-
query(host
|
23
|
+
query(host) == '127.0.0.2'
|
64
24
|
rescue Resolv::ResolvError # NXDOMAIN
|
65
25
|
false
|
66
26
|
rescue Resolv::ResolvTimeout
|
@@ -77,35 +37,27 @@ module Tor
|
|
77
37
|
# exit node and raising a `Resolv::ResolvError` if it isn't.
|
78
38
|
#
|
79
39
|
# @example
|
80
|
-
# Tor::DNSEL.query("
|
40
|
+
# Tor::DNSEL.query("185.220.101.21") #=> "127.0.0.2"
|
81
41
|
# Tor::DNSEL.query("1.2.3.4") #=> Resolv::ResolvError
|
82
42
|
#
|
83
43
|
# @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
44
|
# @return [String]
|
88
45
|
# @raise [Resolv::ResolvError] for an NXDOMAIN response
|
89
|
-
def self.query(host
|
90
|
-
getaddress(dnsname(host
|
46
|
+
def self.query(host)
|
47
|
+
getaddress(dnsname(host))
|
91
48
|
end
|
92
49
|
|
93
50
|
##
|
94
51
|
# Returns the DNS name used for Tor DNSEL queries of `host`.
|
95
52
|
#
|
96
53
|
# @example
|
97
|
-
# Tor::DNSEL.dnsname("1.2.3.4") #=> "4.3.2.1.
|
54
|
+
# Tor::DNSEL.dnsname("1.2.3.4") #=> "4.3.2.1.dnsel.torproject.org"
|
98
55
|
#
|
99
56
|
# @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
57
|
# @return [String]
|
104
|
-
def self.dnsname(host
|
58
|
+
def self.dnsname(host)
|
105
59
|
source_addr = getaddress(host, true)
|
106
|
-
|
107
|
-
target_port = options[:port] || TARGET_PORT
|
108
|
-
[source_addr, target_port, target_addr, DNS_SUFFIX].join('.')
|
60
|
+
"#{source_addr}.#{DNS_SUFFIX}"
|
109
61
|
end
|
110
62
|
class << self; alias_method :hostname, :dnsname; end
|
111
63
|
|
data/lib/tor/version.rb
CHANGED
metadata
CHANGED
@@ -1,98 +1,87 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: tor
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
segments:
|
6
|
-
- 0
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
version: 0.1.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.5
|
10
5
|
platform: ruby
|
11
|
-
authors:
|
6
|
+
authors:
|
12
7
|
- Arto Bendiken
|
13
8
|
autorequire:
|
14
9
|
bindir: bin
|
15
10
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2021-03-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
21
14
|
name: yard
|
22
|
-
|
23
|
-
|
24
|
-
requirements:
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
25
17
|
- - ">="
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
version: 0.5.8
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.6.0
|
20
|
+
- - "~>"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0.6'
|
32
23
|
type: :development
|
33
|
-
version_requirements: *id001
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: rspec
|
36
24
|
prerelease: false
|
37
|
-
|
38
|
-
requirements:
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
39
27
|
- - ">="
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.6.0
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.6'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rspec
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3'
|
46
40
|
type: :development
|
47
|
-
|
48
|
-
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3'
|
47
|
+
description: Tor.rb is a Ruby library for interacting with the Tor anonymity network.
|
49
48
|
email: or-talk@seul.org
|
50
49
|
executables: []
|
51
|
-
|
52
50
|
extensions: []
|
53
|
-
|
54
51
|
extra_rdoc_files: []
|
55
|
-
|
56
|
-
files:
|
52
|
+
files:
|
57
53
|
- AUTHORS
|
58
|
-
-
|
54
|
+
- CREDITS
|
59
55
|
- README
|
60
56
|
- UNLICENSE
|
61
57
|
- VERSION
|
58
|
+
- lib/tor.rb
|
59
|
+
- lib/tor/config.rb
|
60
|
+
- lib/tor/control.rb
|
62
61
|
- lib/tor/dnsel.rb
|
63
62
|
- lib/tor/version.rb
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
- Public Domain
|
63
|
+
homepage: http://cypherpunk.rubyforge.org/tor/
|
64
|
+
licenses:
|
65
|
+
- Unlicense
|
66
|
+
metadata: {}
|
69
67
|
post_install_message:
|
70
68
|
rdoc_options: []
|
71
|
-
|
72
|
-
require_paths:
|
69
|
+
require_paths:
|
73
70
|
- lib
|
74
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
-
requirements:
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
76
73
|
- - ">="
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
segments:
|
79
|
-
- 1
|
80
|
-
- 8
|
81
|
-
- 1
|
74
|
+
- !ruby/object:Gem::Version
|
82
75
|
version: 1.8.1
|
83
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
-
requirements:
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
85
78
|
- - ">="
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
|
88
|
-
|
89
|
-
version: "0"
|
90
|
-
requirements:
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements:
|
91
82
|
- Tor (>= 0.2.1.25)
|
92
|
-
|
93
|
-
rubygems_version: 1.3.6
|
83
|
+
rubygems_version: 3.0.3
|
94
84
|
signing_key:
|
95
|
-
specification_version:
|
85
|
+
specification_version: 4
|
96
86
|
summary: Onion routing for Ruby.
|
97
87
|
test_files: []
|
98
|
-
|
data/README
DELETED
@@ -1,77 +0,0 @@
|
|
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
|