tormanager 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/lib/tormanager.rb +1 -0
- data/lib/tormanager/create_eye_config.rb +27 -0
- data/lib/tormanager/ip_address_control.rb +4 -2
- data/lib/tormanager/process_helper.rb +7 -5
- data/lib/tormanager/tor_process.rb +16 -28
- data/lib/tormanager/version.rb +1 -1
- metadata +3 -3
- data/lib/tormanager/eye/tor.god.rb +0 -105
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1d766b2c286eacb7f7efa82f21dc1662e212f4d
|
4
|
+
data.tar.gz: 32410bc4be8b53b6b655bb769d670685bf822a98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a82a54925256086092b0077286a4d550367281dcad947ffbe31aeb022643c215c34042fbf2ab2d75d63f76225d9eb24e8843792446a67a01f49f2116aada385b
|
7
|
+
data.tar.gz: f5abb39b3cec9703b81731696d8e9e36f1c3103f65ec47202b2436081e6b445e8b24a517d9b80439f02f1c1e913c82d96098f94dcaf5b8f78d2ef22e1fdcf2bd
|
data/lib/tormanager.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
module TorManager
|
2
|
+
class CreateEyeConfig
|
3
|
+
def initialize params={}
|
4
|
+
@settings = params
|
5
|
+
end
|
6
|
+
|
7
|
+
def create
|
8
|
+
File.open(@settings[:eye_tor_config_path], "w") do |file|
|
9
|
+
file.puts read_eye_tor_config_template_and_substitute_keywords
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def read_eye_tor_config_template_and_substitute_keywords
|
16
|
+
text = File.read(@settings[:eye_tor_config_template])
|
17
|
+
eye_tor_config_template_substitution_keywords.each do |keyword|
|
18
|
+
text = text.gsub(/\[\[\[#{keyword}\]\]\]/, @settings[keyword.to_sym].to_s)
|
19
|
+
end
|
20
|
+
text
|
21
|
+
end
|
22
|
+
|
23
|
+
def eye_tor_config_template_substitution_keywords
|
24
|
+
@settings.keys.map(&:to_s)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'rest-client'
|
2
2
|
|
3
3
|
module TorManager
|
4
|
+
TorUnavailable = Class.new(StandardError)
|
5
|
+
|
4
6
|
class IpAddressControl
|
5
7
|
attr_accessor :ip
|
6
8
|
|
@@ -24,7 +26,7 @@ module TorManager
|
|
24
26
|
private
|
25
27
|
|
26
28
|
def ensure_tor_is_available
|
27
|
-
raise "Cannot proceed, Tor is not running on port " +
|
29
|
+
raise TorUnavailable, "Cannot proceed, Tor is not running on port " +
|
28
30
|
"#{@tor_process.settings[:tor_port]}" unless
|
29
31
|
TorProcess.tor_running_on? port: @tor_process.settings[:tor_port],
|
30
32
|
parent_pid: @tor_process.settings[:parent_pid]
|
@@ -70,7 +72,7 @@ module TorManager
|
|
70
72
|
|
71
73
|
def tor_switch_endpoint
|
72
74
|
Tor::Controller.connect(:port => @tor_process.settings[:control_port]) do |tor|
|
73
|
-
tor.authenticate(
|
75
|
+
tor.authenticate(@tor_process.settings[:control_password])
|
74
76
|
tor.signal("newnym")
|
75
77
|
sleep 10
|
76
78
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'socket'
|
2
2
|
|
3
3
|
module TorManager
|
4
|
+
CannotKillProcess = Class.new(StandardError)
|
5
|
+
|
4
6
|
class ProcessHelper
|
5
7
|
class << self
|
6
8
|
def query_process query
|
@@ -12,14 +14,14 @@ module TorManager
|
|
12
14
|
|
13
15
|
def kill_process pids
|
14
16
|
to_array(pids).each do |pid|
|
15
|
-
try_to_kill pid: pid, attempts: 5
|
17
|
+
try_to_kill pid: Integer(pid), attempts: 5
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
21
|
def process_pid_running? pid
|
20
22
|
begin
|
21
23
|
return false if pid.to_s == ''.freeze
|
22
|
-
ipid = pid
|
24
|
+
ipid = Integer(pid)
|
23
25
|
return false if ipid <= 0
|
24
26
|
Process.kill(0, ipid)
|
25
27
|
return true
|
@@ -63,12 +65,12 @@ module TorManager
|
|
63
65
|
def try_to_kill params={}
|
64
66
|
pid = params.fetch(:pid, nil)
|
65
67
|
return unless pid && process_pid_running?(pid)
|
66
|
-
params.fetch(:attempts, 5).times do |
|
67
|
-
|
68
|
+
params.fetch(:attempts, 5).times do |i|
|
69
|
+
i < 3 ? Process.kill('TERM', pid) :
|
68
70
|
Process.kill('KILL', pid)
|
69
71
|
sleep 0.5
|
70
72
|
break unless process_pid_running? pid
|
71
|
-
raise "Couldnt kill pid: #{pid}" if
|
73
|
+
raise CannotKillProcess, "Couldnt kill pid: #{pid}" if i >= 4
|
72
74
|
end
|
73
75
|
end
|
74
76
|
end
|
@@ -4,6 +4,12 @@ require 'fileutils'
|
|
4
4
|
require 'securerandom'
|
5
5
|
|
6
6
|
module TorManager
|
7
|
+
Error = Class.new(StandardError)
|
8
|
+
TorPortInUse = Class.new(Error)
|
9
|
+
TorControlPortInUse = Class.new(Error)
|
10
|
+
TorFailedToStart = Class.new(Error)
|
11
|
+
TorFailedToStop = Class.new(Error)
|
12
|
+
|
7
13
|
class TorProcess
|
8
14
|
attr_accessor :settings
|
9
15
|
|
@@ -88,31 +94,29 @@ module TorManager
|
|
88
94
|
end
|
89
95
|
|
90
96
|
def tor_port_is_open?
|
91
|
-
raise "Cannot spawn Tor process as port " +
|
97
|
+
raise TorPortInUse, "Cannot spawn Tor process as port " +
|
92
98
|
"#{@settings[:tor_port]} is in use" unless
|
93
99
|
ProcessHelper.port_is_open?(@settings[:tor_port])
|
94
100
|
true
|
95
101
|
end
|
96
102
|
|
97
103
|
def control_port_is_open?
|
98
|
-
raise "Cannot spawn Tor process as control port " +
|
104
|
+
raise TorControlPortInUse, "Cannot spawn Tor process as control port " +
|
99
105
|
"#{@settings[:control_port]} is in use" unless
|
100
106
|
ProcessHelper.port_is_open?(@settings[:control_port])
|
101
107
|
true
|
102
108
|
end
|
103
109
|
|
104
110
|
def prepare_tor_start_and_monitor
|
105
|
-
build_eye_config_from_template
|
111
|
+
#build_eye_config_from_template
|
112
|
+
eye_config = CreateEyeConfig.new(
|
113
|
+
@settings.merge(
|
114
|
+
eye_tor_config_path: eye_config_filename))
|
115
|
+
eye_config.create
|
106
116
|
make_dirs
|
107
117
|
start_tor_and_monitor
|
108
118
|
end
|
109
119
|
|
110
|
-
def build_eye_config_from_template
|
111
|
-
File.open(eye_config_filename, "w") do |file|
|
112
|
-
file.puts read_eye_tor_config_template_and_substitute_keywords
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
120
|
def eye_config_filename
|
117
121
|
@eye_config_filename || File.join(@settings[:log_dir],
|
118
122
|
"tormanager.tor.#{@settings[:tor_port]}.#{Process.pid}.eye.rb")
|
@@ -122,23 +126,6 @@ module TorManager
|
|
122
126
|
@eye_app_name || "tormanager-tor-#{@settings[:tor_port]}-#{Process.pid}"
|
123
127
|
end
|
124
128
|
|
125
|
-
def read_eye_tor_config_template_and_substitute_keywords
|
126
|
-
text = File.read(@settings[:eye_tor_config_template])
|
127
|
-
eye_tor_config_template_substitution_keywords.each do |keyword|
|
128
|
-
text = text.gsub(/\[\[\[#{keyword}\]\]\]/, @settings[keyword.to_sym].to_s)
|
129
|
-
end
|
130
|
-
text
|
131
|
-
end
|
132
|
-
|
133
|
-
def eye_tor_config_template_substitution_keywords
|
134
|
-
remove_settings_that_are_not_eye_tor_config_template_keywords(
|
135
|
-
@settings.keys.map(&:to_s))
|
136
|
-
end
|
137
|
-
|
138
|
-
def remove_settings_that_are_not_eye_tor_config_template_keywords keywords
|
139
|
-
keywords - ['eye_tor_config_template', 'control_password', 'dont_remove_tor_config']
|
140
|
-
end
|
141
|
-
|
142
129
|
def make_dirs
|
143
130
|
[@settings[:log_dir], @settings[:pid_dir],
|
144
131
|
@settings[:tor_data_dir]].each do |path|
|
@@ -159,7 +146,7 @@ module TorManager
|
|
159
146
|
application: eye_app_name,
|
160
147
|
process: 'tor') == 'up'
|
161
148
|
sleep 2
|
162
|
-
raise "Tor didnt start up after 20 seconds! See log: " +
|
149
|
+
raise TorFailedToStart, "Tor didnt start up after 20 seconds! See log: " +
|
163
150
|
"#{File.join(@settings[:log_dir],
|
164
151
|
eye_app_name + ".log")}" if i >= 9
|
165
152
|
end
|
@@ -172,7 +159,8 @@ module TorManager
|
|
172
159
|
process: 'tor')
|
173
160
|
break if ['unknown','unmonitored'].include?(tor_status)
|
174
161
|
sleep 2
|
175
|
-
raise
|
162
|
+
raise TorFailedToStop,
|
163
|
+
"Tor didnt stop after 20 seconds! Last status: #{tor_status} See log: " +
|
176
164
|
"#{File.join(@settings[:log_dir],
|
177
165
|
eye_app_name + ".log")}" if i >= 9
|
178
166
|
end
|
data/lib/tormanager/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tormanager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- joshweir
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-08-
|
11
|
+
date: 2017-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -155,9 +155,9 @@ files:
|
|
155
155
|
- bin/setup
|
156
156
|
- lib/tormanager.rb
|
157
157
|
- lib/tormanager/control.rb
|
158
|
+
- lib/tormanager/create_eye_config.rb
|
158
159
|
- lib/tormanager/eye/eye.tor.test.rb
|
159
160
|
- lib/tormanager/eye/sugar.rb
|
160
|
-
- lib/tormanager/eye/tor.god.rb
|
161
161
|
- lib/tormanager/eye/tor.template.eye.rb
|
162
162
|
- lib/tormanager/ip_address_control.rb
|
163
163
|
- lib/tormanager/process_helper.rb
|
@@ -1,105 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
opts = {}
|
4
|
-
opts[:parent_id] = ARGV[0]
|
5
|
-
opts[:tor_port] = ARGV[1] || 9050
|
6
|
-
opts[:control_port] = ARGV[2] || 50500
|
7
|
-
opts[:pid_dir] = ARGV[3] || "/tmp"
|
8
|
-
opts[:log_dir] = ARGV[4] || "/tmp"
|
9
|
-
opts[:tor_data_dir] = ARGV[5] || "/tmp/tor_data/"
|
10
|
-
opts[:tor_new_circuit_period] = ARGV[6] || 60
|
11
|
-
opts[:max_tor_memory_usage_mb] = ARGV[7] || 200
|
12
|
-
opts[:max_tor_cpu_percentage] = ARGV[8] || 10
|
13
|
-
opts[:max_tor_memory_usage_times] = [3,5]
|
14
|
-
opts[:max_tor_cpu_percentage_times] = [3,5]
|
15
|
-
|
16
|
-
raise 'parent_id is required' unless opts[:parent_id]
|
17
|
-
|
18
|
-
module God
|
19
|
-
module Behaviors
|
20
|
-
class WaitBehavior < Behavior
|
21
|
-
attr_accessor :delay
|
22
|
-
|
23
|
-
def after_start
|
24
|
-
sleep delay.to_i if delay.to_i > 0
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
God.watch do |w|
|
31
|
-
the_name = "tormanager-tor-#{opts[:tor_port]}-#{opts[:parent_id]}"
|
32
|
-
w.name = the_name
|
33
|
-
w.start = "tor --SocksPort #{opts[:tor_port]} --ControlPort #{opts[:control_port]} " +
|
34
|
-
"--CookieAuthentication 0 --HashedControlPassword \"16:3E49D6163CCA95F2605B339" +
|
35
|
-
"E07F753C8F567DE4200E33FDF4CC6B84E44\" --NewCircuitPeriod " +
|
36
|
-
"#{opts[:tor_new_circuit_period]} --DataDirectory " +
|
37
|
-
File.join(opts[:tor_data_dir], opts[:tor_port]) + " --Log \"notice syslog\""
|
38
|
-
#w.pid_file = File.join(opts[:pid_dir], "#{the_name}.pid")
|
39
|
-
#w.log = File.join(opts[:log_dir], "#{the_name}.log") if opts[:log_dir].length > 0
|
40
|
-
w.keepalive
|
41
|
-
|
42
|
-
# clean pid files before start if necessary
|
43
|
-
w.behavior(:clean_pid_file)
|
44
|
-
w.behavior(:wait_behavior) do |b|
|
45
|
-
b.delay = 10
|
46
|
-
end
|
47
|
-
|
48
|
-
=begin
|
49
|
-
# determine the state on startup
|
50
|
-
w.transition(:init, { true => :up, false => :start }) do |on|
|
51
|
-
sleep 5
|
52
|
-
on.condition(:process_running) do |c|
|
53
|
-
c.interval = 5
|
54
|
-
c.running = true
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# determine when process has finished starting
|
59
|
-
w.transition([:start, :restart], :up) do |on|
|
60
|
-
on.condition(:process_running) do |c|
|
61
|
-
c.interval = 20
|
62
|
-
c.running = true
|
63
|
-
end
|
64
|
-
|
65
|
-
# failsafe
|
66
|
-
on.condition(:tries) do |c|
|
67
|
-
c.interval = 20
|
68
|
-
c.times = 5
|
69
|
-
c.transition = :start
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# start if process is not running
|
74
|
-
#w.transition(:up, :start) do |on|
|
75
|
-
# on.condition(:process_exits) do |c|
|
76
|
-
# c.interval = 20
|
77
|
-
# end
|
78
|
-
#end
|
79
|
-
|
80
|
-
# restart if memory or cpu is too high
|
81
|
-
w.transition(:up, :restart) do |on|
|
82
|
-
on.condition(:memory_usage) do |c|
|
83
|
-
c.interval = 20
|
84
|
-
c.above = opts[:max_tor_memory_usage_mb]
|
85
|
-
c.times = opts[:max_tor_memory_usage_times]
|
86
|
-
end
|
87
|
-
|
88
|
-
on.condition(:cpu_usage) do |c|
|
89
|
-
c.interval = 10
|
90
|
-
c.above = opts[:max_tor_cpu_percentage]
|
91
|
-
c.times = opts[:max_tor_cpu_percentage_times]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
# lifecycle
|
96
|
-
w.lifecycle do |on|
|
97
|
-
on.condition(:flapping) do |c|
|
98
|
-
c.to_state = [:start, :restart]
|
99
|
-
c.times = 5
|
100
|
-
c.within = 5.minute
|
101
|
-
c.transition = :unmonitored
|
102
|
-
end
|
103
|
-
end
|
104
|
-
=end
|
105
|
-
end
|