simple_proxies_deploying 1.1.1
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/lib/remotehost.rb +476 -0
- data/lib/simple_proxies_deploying.rb +26 -0
- data/lib/simpleproxiesdeployingexception.rb +42 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c3086b055abad44698b019d6cb917ef2b55f2ed8
|
4
|
+
data.tar.gz: d6c6cce616fa968f9a18f3ab2f34ad476ff07aea
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1a215ad874f5704357045c0543b6c208ccda56fc242fc42afe4255f67750c84ce6350a10ef8ef6150ebe95b83e6774ddf230ccedfde443a5cb620c14de3a26ec
|
7
|
+
data.tar.gz: 3ba545757c18b259035a866e7f28814f720a2f4273a2d51423e6a4404beab3589cf79988a145a46f0991e43af5496d62a6ed6ecdad2cd55b127859e8b0bfb766
|
data/lib/remotehost.rb
ADDED
@@ -0,0 +1,476 @@
|
|
1
|
+
# TODO: replace RemoteHost class in SimpleHostsMonitoring library by this code
|
2
|
+
class RemoteHost
|
3
|
+
# TODO: this must be defined at class RemoteHost in the SimpleHostMonitoring library
|
4
|
+
attr_accessor :cpu_architecture, :cpu_speed, :cpu_load_average, :cpu_model, :cpu_type, :cpu_number, :mem_total, :mem_free, :disk_total, :disk_free, :net_hostname, :net_remote_ip, :net_mac_address
|
5
|
+
attr_accessor :stealth_browser_technology_code, :ssh_username, :ssh_password, :ssh_port, :ipv6_subnet_48
|
6
|
+
attr_accessor :ssh # this is the ssh connection
|
7
|
+
attr_accessor :logger
|
8
|
+
|
9
|
+
def initialize(the_logger=nil)
|
10
|
+
self.logger=the_logger
|
11
|
+
self.logger = BlackStack::DummyLogger.new(nil) if self.logger.nil? # assign a dummy logger that just generate output on the screen
|
12
|
+
end
|
13
|
+
|
14
|
+
# TODO: mover esto al modulo BaseHost de SimpleHostMonitoring
|
15
|
+
def self.valid_port_number?(n)
|
16
|
+
return false if !n.is_a?(Numeric)
|
17
|
+
return false if n < 1 || n > 65535
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# return the same hash as the class poll() method, but connecting the server via SSH.
|
22
|
+
# we are assuming the server is a Linux server.
|
23
|
+
# TODO: write the list of software packages that server must have installed.
|
24
|
+
def poll_thru_ssh()
|
25
|
+
# TODO: code me!
|
26
|
+
end
|
27
|
+
|
28
|
+
# TODO: this must be defined at module BaseHost in the SimpleHostMonitoring library
|
29
|
+
def parse(h)
|
30
|
+
# parameters regarding the current status of the host
|
31
|
+
self.cpu_architecture = h[:cpu_architecture]
|
32
|
+
self.cpu_speed = h[:cpu_speed]
|
33
|
+
self.cpu_load_average = h[:cpu_load_average]
|
34
|
+
self.cpu_model = h[:cpu_model]
|
35
|
+
self.cpu_type = h[:cpu_type]
|
36
|
+
self.cpu_number = h[:cpu_number]
|
37
|
+
self.mem_total = h[:mem_total]
|
38
|
+
self.mem_free = h[:mem_free]
|
39
|
+
self.disk_total = h[:disk_total]
|
40
|
+
self.disk_free = h[:disk_free]
|
41
|
+
self.net_hostname = h[:net_hostname]
|
42
|
+
self.net_mac_address = h[:net_mac_address]
|
43
|
+
|
44
|
+
# parameters regarding the remote controling of the server
|
45
|
+
self.net_remote_ip = h[:net_remote_ip]
|
46
|
+
self.ssh_username = h[:ssh_username]
|
47
|
+
self.ssh_password = h[:ssh_password]
|
48
|
+
self.ssh_port = h[:ssh_port]
|
49
|
+
|
50
|
+
# StealthBrowserAutomation monkey-patch add-on: parameters regarding the usage of stealth browser for automation
|
51
|
+
self.stealth_browser_technology_code = h[:stealth_browser_technology_code]
|
52
|
+
|
53
|
+
# SimpleProxyServer monkey-patch add-on: paremeters regarding the installation of proxies
|
54
|
+
self.ipv6_subnet_48 = h[:ipv6_subnet_48]
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.parse(h, logger=nil)
|
58
|
+
o = RemoteHost.new(logger)
|
59
|
+
o.parse(h)
|
60
|
+
o
|
61
|
+
end
|
62
|
+
|
63
|
+
# TODO: this must be defined at module BaseHost in the SimpleHostMonitoring library
|
64
|
+
def to_hash
|
65
|
+
{
|
66
|
+
# parameters regarding the current status of the host
|
67
|
+
:cpu_architecture => self.cpu_architecture,
|
68
|
+
:cpu_speed => self.cpu_speed,
|
69
|
+
:cpu_load_average => self.cpu_load_average,
|
70
|
+
:cpu_model => self.cpu_model,
|
71
|
+
:cpu_type => self.cpu_type,
|
72
|
+
:cpu_number => self.cpu_number,
|
73
|
+
:mem_total => self.mem_total,
|
74
|
+
:mem_free => self.mem_free,
|
75
|
+
:disk_total => self.disk_total,
|
76
|
+
:disk_free => self.disk_free,
|
77
|
+
:net_hostname => self.net_hostname,
|
78
|
+
:net_remote_ip => self.net_remote_ip,
|
79
|
+
:net_mac_address => self.net_mac_address,
|
80
|
+
|
81
|
+
# parameters regarding the remote controling of the server
|
82
|
+
:ssh_username => self.ssh_username,
|
83
|
+
:ssh_password => self.ssh_password,
|
84
|
+
:ssh_port => self.ssh_port,
|
85
|
+
|
86
|
+
# StealthBrowserAutomation monkey-patch add-on: parameters regarding the usage of stealth browser for automation
|
87
|
+
:stealth_browser_technology_code => self.stealth_browser_technology_code,
|
88
|
+
|
89
|
+
# SimpleProxyServer monkey-patch add-on: paremeters regarding the installation of proxies
|
90
|
+
:ipv6_subnet_48 => self.ipv6_subnet_48,
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def ssh_parameters?
|
96
|
+
self.net_remote_ip && self.ssh_username && self.ssh_password
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_ssh_port()
|
100
|
+
self.ssh_port.nil? ? 22 : self.ssh_port
|
101
|
+
end
|
102
|
+
|
103
|
+
def ssh_connect()
|
104
|
+
# validation: this host must have ssh parameters
|
105
|
+
raise SimpleProxiesDeployingException.new(1) if !self.ssh_parameters?
|
106
|
+
|
107
|
+
# connect
|
108
|
+
self.ssh = Net::SSH.start(self.net_remote_ip, self.ssh_username, :password => self.ssh_password, :port => self.get_ssh_port)
|
109
|
+
|
110
|
+
# validation: the connection must be established
|
111
|
+
raise SimpleProxiesDeployingException.new(4) if !self.ssh
|
112
|
+
end
|
113
|
+
|
114
|
+
# Parse the file /usr/local/etc/3proxy/cfg/3proxy.cfg
|
115
|
+
# Return an array of hash descriptors like this: {:port=>"3130", :external_ip=>"185.165.34.31"}
|
116
|
+
def get_ipv4_proxies()
|
117
|
+
# TODO: Code Me!
|
118
|
+
end
|
119
|
+
|
120
|
+
# Parse the file /usr/local/etc/3proxy/cfg/3proxy.cfg
|
121
|
+
# Return an array of hash descriptors like this: {:port=>"4248", :external_ip=>"2602:fed2:770f:df10:8dc9:556f:dfba:8ee3", :subnet64=>"2602:fed2:770f:df10"}
|
122
|
+
def get_ipv6_proxies()
|
123
|
+
# validation: this host must have defined an ipv6 subnet 48
|
124
|
+
raise SimpleProxiesDeployingException.new(5) if !self.ipv6_subnet_48
|
125
|
+
|
126
|
+
# validation: this host must have ssh connection
|
127
|
+
raise SimpleProxiesDeployingException.new(3) if !self.ssh
|
128
|
+
|
129
|
+
results = []
|
130
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'grep \"proxy -p\" /usr/local/etc/3proxy/cfg/3proxy.cfg'")
|
131
|
+
a = stdout.split("\n") # stdout.scan(MATCH_IPV6_STANDARD)
|
132
|
+
a.select { |x|
|
133
|
+
# filter all the IPv6 proxies
|
134
|
+
x.include?('-6')
|
135
|
+
}.each { |x|
|
136
|
+
# example: proxy -p4245 -6 -a -n -i0.0.0.0 -e2602:fed2:770f:e75c:dc88:fab6:7623:1f47
|
137
|
+
port = x.scan(MATCH_PORT_IN_3PROXY_CONF)[0].gsub(/\-p/, '')
|
138
|
+
external_ip = x.scan(MATCH_IPV6_STANDARD)[0]
|
139
|
+
subnet64 = external_ip.scan(MATCH_IPV6_64_SUBNET_STANDARD)[0]
|
140
|
+
results << { :port => port.to_i, :external_ip => external_ip.to_s, :subnet64 => subnet64.to_s }
|
141
|
+
}
|
142
|
+
results
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
# check a list of port numbers and return the list of ports that are missconfigured
|
147
|
+
# return an array of errors.
|
148
|
+
def check_all_ipv4_proxies()
|
149
|
+
# TODO: Code Me!
|
150
|
+
end
|
151
|
+
|
152
|
+
# check a list of port numbers and return the list of ports that are missconfigured
|
153
|
+
# return an array of errors.
|
154
|
+
# validate if there is more than one external ip address belonging the same /64 subnet.
|
155
|
+
# validate that each batch of 50 ports is all configured.
|
156
|
+
# raise an exception if there are ports outside the range
|
157
|
+
# raise an exception proxy_port_to is not higher than proxy_port_from.
|
158
|
+
def check_all_ipv6_proxies(proxy_port_from=DEFAULT_PROXY_PORT_FROM, proxy_port_to=DEFAULT_PROXY_PORT_TO)
|
159
|
+
#raise SimpleProxiesDeployingException.new(9, "#{proxy_port_from}") if proxy_port_from != DEFAULT_PROXY_PORT_FROM
|
160
|
+
raise SimpleProxiesDeployingException.new(10, "#{proxy_port_from} and #{proxy_port_to}") if proxy_port_from > proxy_port_to
|
161
|
+
#raise SimpleProxiesDeployingException.new(11, "from #{proxy_port_from} to #{proxy_port_to}") if (proxy_port_to-proxy_port_from+1) % DEFAULT_PROXY_PORTS_BATCH_SIZE != 0
|
162
|
+
|
163
|
+
# return this array with the list of glitches found
|
164
|
+
errors = []
|
165
|
+
|
166
|
+
# record all the /64 subnets of each external ip address, to check if there is more than one external ip address belonging the same /64 subnet
|
167
|
+
# records all the extenral ips of each port, to check that each batch of 50 ports is all configured, or it is empty
|
168
|
+
results = self.get_ipv6_proxies
|
169
|
+
|
170
|
+
# validate there is not ports outside the range
|
171
|
+
a = results.select { |x|
|
172
|
+
x[:port]<proxy_port_from || x[:port]>proxy_port_to
|
173
|
+
}.map { |x|
|
174
|
+
x[:port]
|
175
|
+
}
|
176
|
+
raise SimpleProxiesDeployingException.new(14, a.join(', ')) if a.size > 1
|
177
|
+
|
178
|
+
port = proxy_port_from
|
179
|
+
while port <= proxy_port_to
|
180
|
+
# map the external IPs to the port
|
181
|
+
a = results.select { |x| x[:port] == port }.map { |x| x[:external_ip] }
|
182
|
+
|
183
|
+
# validation: there is no extenral IP defined for this port
|
184
|
+
# raise SimpleProxiesDeployingException.new(8) if a.size == 0
|
185
|
+
|
186
|
+
if a.size > 0
|
187
|
+
# validation: there is no more than 1 extenral IP defined for this host
|
188
|
+
if a.size > 1
|
189
|
+
e = SimpleProxiesDeployingException.new(7, "#{port.to_s} - #{a.join(', ')}")
|
190
|
+
errors << { :proxy_port=>port, :code=>e.code, :description=>e.description, :simple_description=>e.simple_description }
|
191
|
+
end
|
192
|
+
|
193
|
+
# validation: the external ip must be belonging the subnet defined at ipv6 subnet 48
|
194
|
+
if !a[0].include?(self.ipv6_subnet_48)
|
195
|
+
e = SimpleProxiesDeployingException.new(6, "#{a[0]} and #{self.ipv6_subnet_48}")
|
196
|
+
errors << { :proxy_port=>port, :code=>e.code, :description=>e.description, :simple_description=>e.simple_description }
|
197
|
+
end
|
198
|
+
end # if a.size > 0
|
199
|
+
|
200
|
+
port += 1
|
201
|
+
end
|
202
|
+
|
203
|
+
# validation: there is more than one external ip address belonging the same /64 subnet.
|
204
|
+
self.logger.logs 'Check duplicated /64 subnets... '
|
205
|
+
i = 0
|
206
|
+
results.each { |r|
|
207
|
+
if !r[:external_ip].nil?
|
208
|
+
b = results.select { |s| s[:port]!=r[:port] && s[:subnet64]==r[:subnet64] }
|
209
|
+
if b.size > 1
|
210
|
+
e = SimpleProxiesDeployingException.new(12, b.join(', '))
|
211
|
+
errors << { :proxy_port=>r[:port], :code=>e.code, :description=>e.description, :simple_description=>e.simple_description }
|
212
|
+
i += 1
|
213
|
+
end
|
214
|
+
end # if !r[:external_ip].nil?
|
215
|
+
}
|
216
|
+
self.logger.logf "done (#{i.to_s} errors)"
|
217
|
+
|
218
|
+
# return
|
219
|
+
errors
|
220
|
+
end # def check_all_ipv6_proxies
|
221
|
+
|
222
|
+
|
223
|
+
# run linux command to get the interface name
|
224
|
+
# TODO: validate outout
|
225
|
+
def get_interface_name()
|
226
|
+
# validation: this host must have ssh connection
|
227
|
+
raise SimpleProxiesDeployingException.new(3) if !self.ssh
|
228
|
+
ssh.exec!("ip -o -4 route show to default | awk '{print $5}' | sed 1'!d'").strip
|
229
|
+
end
|
230
|
+
|
231
|
+
# run linux command to stop the proxy server
|
232
|
+
# TODO: validate outout
|
233
|
+
def stop_proxies()
|
234
|
+
# validation: this host must have ssh connection
|
235
|
+
raise SimpleProxiesDeployingException.new(3) if !self.ssh
|
236
|
+
ssh.exec!("sh /usr/local/etc/3proxy/scripts/rc.d/proxy.sh stop > /dev/null 2>&1")
|
237
|
+
end
|
238
|
+
|
239
|
+
# run linux command to stop the proxy server
|
240
|
+
# TODO: get this working
|
241
|
+
# TODO: validate outout
|
242
|
+
def start_proxies()
|
243
|
+
# validation: this host must have ssh connection
|
244
|
+
raise SimpleProxiesDeployingException.new(3) if !self.ssh
|
245
|
+
ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'sh /usr/local/etc/3proxy/scripts/rc.d/proxy.sh start > /dev/null 2>&1'")
|
246
|
+
end
|
247
|
+
|
248
|
+
|
249
|
+
# setup custom IP authorization for a proxy
|
250
|
+
def setup_custom_ip_auth(port)
|
251
|
+
# TODO: Code Me!
|
252
|
+
end
|
253
|
+
|
254
|
+
# setup custom user/pass authorization for a proxy
|
255
|
+
def setup_custom_pass_auth(port)
|
256
|
+
# TODO: Code Me!
|
257
|
+
end
|
258
|
+
|
259
|
+
|
260
|
+
# install ipv4 proxies
|
261
|
+
def install4(username, password, port=3130)
|
262
|
+
#raise SimpleProxiesDeployingException.new(9, "#{proxy_port_from}") if proxy_port_from != DEFAULT_PROXY_PORT_FROM
|
263
|
+
#raise SimpleProxiesDeployingException.new(10, "#{proxy_port_from} and #{proxy_port_to}") if proxy_port_from > proxy_port_to
|
264
|
+
#raise SimpleProxiesDeployingException.new(11, "from #{proxy_port_from} to #{proxy_port_to}") if (proxy_port_to-proxy_port_from+1) % DEFAULT_PROXY_PORTS_BATCH_SIZE != 0
|
265
|
+
|
266
|
+
# TODO: validate the output
|
267
|
+
logger.logs "Get interface name... "
|
268
|
+
interface = self.get_interface_name
|
269
|
+
logger.done #logf "done (#{interface})"
|
270
|
+
|
271
|
+
logger.logs "Get server main ip from configuration... "
|
272
|
+
mainip = self.net_remote_ip
|
273
|
+
logger.done #logf "done (#{mainip})"
|
274
|
+
|
275
|
+
# TODO: validate the output
|
276
|
+
logger.logs "Install packages... "
|
277
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c '
|
278
|
+
apt-get install nano
|
279
|
+
apt-get update
|
280
|
+
apt-get autoremove -y
|
281
|
+
apt-get autoclean -y
|
282
|
+
apt-get clean -y
|
283
|
+
apt-get install fail2ban software-properties-common -y
|
284
|
+
apt-get install build-essential libevent-dev libssl-dev -y
|
285
|
+
apt-get install ethtool -y
|
286
|
+
apt-get install curl -y
|
287
|
+
'")
|
288
|
+
logger.done #logf "done (#{stdout})"
|
289
|
+
|
290
|
+
# TODO: validate the output
|
291
|
+
logger.logs "Install 3proxy... "
|
292
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c '
|
293
|
+
cd /usr/local/etc
|
294
|
+
wget https://github.com/z3APA3A/3proxy/archive/0.8.12.tar.gz
|
295
|
+
tar zxvf 0.8.12.tar.gz
|
296
|
+
rm 0.8.12.tar.gz
|
297
|
+
mv 3proxy-0.8.12 3proxy
|
298
|
+
cd 3proxy
|
299
|
+
make -f Makefile.Linux
|
300
|
+
make -f Makefile.Linux install
|
301
|
+
mkdir log
|
302
|
+
cd cfg
|
303
|
+
'")
|
304
|
+
logger.done #logf "done (#{stdout})"
|
305
|
+
|
306
|
+
# TODO: validate the output
|
307
|
+
logger.logs "Setup 3proxy.cfg... "
|
308
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c '
|
309
|
+
echo \"#!/usr/local/bin/3proxy
|
310
|
+
daemon
|
311
|
+
pidfile /usr/local/etc/3proxy/3proxy.pid
|
312
|
+
nserver 1.1.1.1
|
313
|
+
nserver 1.0.0.1
|
314
|
+
nscache 65536
|
315
|
+
timeouts 1 5 30 60 180 1800 15 60
|
316
|
+
log /usr/local/etc/3proxy/log/3proxy.log D
|
317
|
+
logformat \\\"- +_L%t.%. %N.%p %E %U %C:%c %R:%r %O %I %h %T\\\"
|
318
|
+
archiver rar rar a -df -inul %A %F
|
319
|
+
rotate 30
|
320
|
+
internal 0.0.0.0
|
321
|
+
external 0.0.0.0
|
322
|
+
authcache ip 60
|
323
|
+
users #{username}:CL:#{password}
|
324
|
+
|
325
|
+
auth strong
|
326
|
+
allow #{username}
|
327
|
+
proxy -p#{port} -a -n
|
328
|
+
\" > /usr/local/etc/3proxy/cfg/3proxy.cfg'")
|
329
|
+
logger.done #logf "done (#{stdout})"
|
330
|
+
|
331
|
+
logger.logs "Start proxy service... "
|
332
|
+
self.start_proxies
|
333
|
+
logger.done
|
334
|
+
|
335
|
+
end # def install_3proxy
|
336
|
+
|
337
|
+
# install ipv6 proxies
|
338
|
+
# raise an exception proxy_port_to is not higher than proxy_port_from.
|
339
|
+
def install6(proxy_port_from=DEFAULT_PROXY_PORT_FROM, proxy_port_to=DEFAULT_PROXY_PORT_TO)
|
340
|
+
#raise SimpleProxiesDeployingException.new(9, "#{proxy_port_from}") if proxy_port_from != DEFAULT_PROXY_PORT_FROM
|
341
|
+
raise SimpleProxiesDeployingException.new(10, "#{proxy_port_from} and #{proxy_port_to}") if proxy_port_from > proxy_port_to
|
342
|
+
#raise SimpleProxiesDeployingException.new(11, "from #{proxy_port_from} to #{proxy_port_to}") if (proxy_port_to-proxy_port_from+1) % DEFAULT_PROXY_PORTS_BATCH_SIZE != 0
|
343
|
+
|
344
|
+
# TODO: validate the output
|
345
|
+
logger.logs "Get interface name... "
|
346
|
+
interface = self.get_interface_name
|
347
|
+
logger.logf "done (#{interface})"
|
348
|
+
|
349
|
+
logger.logs "Get server main ip from configuration... "
|
350
|
+
mainip = self.net_remote_ip
|
351
|
+
logger.logf "done (#{mainip})"
|
352
|
+
|
353
|
+
logger.logs "Install ethtool... "
|
354
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'apt-get install ethtool'")
|
355
|
+
logger.done
|
356
|
+
|
357
|
+
# get list of 4-hex-digits subnets
|
358
|
+
logger.logs "Initialize list of 4-hex-digit numbers... "
|
359
|
+
hex4digits = []
|
360
|
+
"123456789ABCDEF".split('').each { |a| # don't inclulude codes with leading 0, in order to get codes that are 4 digits even in STANDARD notation
|
361
|
+
"0123456789ABCDEF".split('').each { |b|
|
362
|
+
"0123456789ABCDEF".split('').each { |c|
|
363
|
+
"0123456789ABCDEF".split('').each { |d|
|
364
|
+
hex4digits << "#{a}#{b}#{c}#{d}".downcase
|
365
|
+
}
|
366
|
+
}
|
367
|
+
}
|
368
|
+
}
|
369
|
+
logger.logf "done (#{hex4digits.size} numbers)"
|
370
|
+
|
371
|
+
logger.logs "Shuffle list of 4-hex-digit numbers... "
|
372
|
+
hex4digits.shuffle!
|
373
|
+
logger.logf "done (#{hex4digits[0]}, #{hex4digits[1]}, #{hex4digits[2]}, ...)"
|
374
|
+
|
375
|
+
logger.logs "Initialize list proxies... "
|
376
|
+
results = get_ipv6_proxies
|
377
|
+
logger.logf "done (#{results.size} ports)"
|
378
|
+
|
379
|
+
# TODO: validate the output
|
380
|
+
logger.logs "Install ethtool... "
|
381
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'apt-get install ethtool'")
|
382
|
+
logger.done
|
383
|
+
|
384
|
+
# TODO: validate the output
|
385
|
+
logger.logs "Install curl... "
|
386
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'apt-get install curl'")
|
387
|
+
logger.done
|
388
|
+
|
389
|
+
logger.logs "Stop proxy server... "
|
390
|
+
stdout = self.stop_proxies
|
391
|
+
logger.done #logf "done (#{stdout})"
|
392
|
+
|
393
|
+
# TODO: validate this output
|
394
|
+
logger.logs "Add /48 subnet to interface... "
|
395
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'ifconfig #{interface} add #{self.ipv6_subnet_48}::/48'")
|
396
|
+
logger.done #logf "done (#{stdout})"
|
397
|
+
|
398
|
+
# TODO: validate this output
|
399
|
+
logger.logs "Add default route for IPv6... "
|
400
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'ip -6 route add default via #{self.ipv6_subnet_48}::1'")
|
401
|
+
logger.done #logf "done (#{stdout})"
|
402
|
+
|
403
|
+
# TODO: validate this output
|
404
|
+
logger.logs "Setup /etc/network.conf... "
|
405
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'echo \"ifconfig #{interface} add #{self.ipv6_subnet_48}::/48
|
406
|
+
ip -6 route add default via #{self.ipv6_subnet_48}::1\" >> /etc/network.conf'")
|
407
|
+
logger.done #.logf "done (#{stdout})"
|
408
|
+
|
409
|
+
# TODO: validate this output
|
410
|
+
logger.logs "Remove exit 0 FROM rc.local... "
|
411
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c \"sed -i '/exit 0/d' /etc/rc.local\"")
|
412
|
+
logger.done #.logf "done (#{stdout})"
|
413
|
+
|
414
|
+
# TODO: validate this output
|
415
|
+
logger.logs "Remove exit 0 FROM rc.local... "
|
416
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'echo \"bash /etc/network.conf\" >> /etc/rc.local'")
|
417
|
+
logger.done #.logf "done (#{stdout})"
|
418
|
+
|
419
|
+
logger.logs "Remove not available /64 subnets... "
|
420
|
+
available_hex4digits = hex4digits.reject { |hex|
|
421
|
+
results.map { |result|
|
422
|
+
result[:subnet64]
|
423
|
+
}.include?("#{self.ipv6_subnet_48}:#{hex}")
|
424
|
+
}
|
425
|
+
logger.logf("done (#{available_hex4digits.size})")
|
426
|
+
|
427
|
+
logger.logs "Iterate ports... "
|
428
|
+
port = proxy_port_from
|
429
|
+
while port<=proxy_port_to
|
430
|
+
logger.logs "Checking port #{port}... "
|
431
|
+
if results.map { |result| result[:port].to_i }.include?(port)
|
432
|
+
logger.logf "done (already installed)"
|
433
|
+
else
|
434
|
+
#logger.logs "Get an available subnet64... "
|
435
|
+
hex = available_hex4digits[0]
|
436
|
+
subnet64 = "#{self.ipv6_subnet_48}:#{hex}"
|
437
|
+
#logger.logf "done (#{subnet64})"
|
438
|
+
|
439
|
+
#logger.logs "Remove #{subnet64} from list of available subnets64... "
|
440
|
+
available_hex4digits.reject! { |x| x == hex }
|
441
|
+
#logger.logf("done (#{available_hex4digits.size})")
|
442
|
+
|
443
|
+
#logger.logs "Build random IPv6... "
|
444
|
+
ipv6 = "#{subnet64}:#{hex4digits.shuffle[0]}:#{hex4digits.shuffle[0]}:#{hex4digits.shuffle[0]}:#{hex4digits.shuffle[0]}"
|
445
|
+
#logger.logf("done (#{ipv6})")
|
446
|
+
|
447
|
+
#logger.logs "Add record to configuration file... "
|
448
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'echo proxy -p#{port} -6 -a -n -i0.0.0.0 -e#{ipv6} >> /usr/local/etc/3proxy/cfg/3proxy.cfg'")
|
449
|
+
#logger.logf("done (#{stdout})")
|
450
|
+
|
451
|
+
#logger.logs "Add IPv6 address... "
|
452
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'ip address add #{ipv6} dev #{interface} > /dev/null 2>&1'")
|
453
|
+
#logger.logf("done (#{stdout})")
|
454
|
+
|
455
|
+
logger.logf('done (installed)')
|
456
|
+
end
|
457
|
+
port += 1
|
458
|
+
end
|
459
|
+
|
460
|
+
# TODO: validate this output
|
461
|
+
logger.logs "Start proxy server... "
|
462
|
+
stdout = self.start_proxies
|
463
|
+
logger.done #logf "done (#{stdout})"
|
464
|
+
|
465
|
+
# TODO: validate this output
|
466
|
+
logger.logs "Add exit 0 TO rc.local... "
|
467
|
+
stdout = ssh.exec!("echo '#{self.ssh_password.gsub("'", "\\'")}' | sudo -S su root -c 'echo \"exit 0\" >> /etc/rc.local'")
|
468
|
+
logger.logf "done (#{stdout})"
|
469
|
+
|
470
|
+
end
|
471
|
+
|
472
|
+
def ssh_disconnect()
|
473
|
+
self.ssh.close
|
474
|
+
end
|
475
|
+
|
476
|
+
end # class RemoteHost
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'net/ssh'
|
2
|
+
require 'blackstack_commons'
|
3
|
+
require 'simple_cloud_logging'
|
4
|
+
require 'simple_command_line_parser'
|
5
|
+
|
6
|
+
# TODO: design the proxy server managment as an addon of SimpleHostMonitoring
|
7
|
+
|
8
|
+
# matching ipv6 addresses with standard notation (not compact. not mixed.)
|
9
|
+
MATCH_PORT_IN_3PROXY_CONF = /\-p[0-9][0-9][0-9][0-9]/
|
10
|
+
|
11
|
+
# Regular expressions to match IPv6 addresses in the 3proxy config file.
|
12
|
+
# reference: https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s17.html
|
13
|
+
#
|
14
|
+
# TODO: Research: which ipv6 notation use the 3cproxy configuration file? Is it standard or mixed or compresed?
|
15
|
+
#
|
16
|
+
MATCH_IPV6_STANDARD = /(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}/i
|
17
|
+
MATCH_IPV6_64_SUBNET_STANDARD = /^[A-F0-9]{1,4}:[A-F0-9]{1,4}:[A-F0-9]{1,4}:[A-F0-9]{1,4}/i # TODO: this is not supporting leading zeros
|
18
|
+
|
19
|
+
#
|
20
|
+
DEFAULT_PROXY_PORT_FROM = 4000
|
21
|
+
DEFAULT_PROXY_PORT_TO = 4499
|
22
|
+
DEFAULT_PROXY_PORTS_BATCH_SIZE = 50
|
23
|
+
|
24
|
+
#
|
25
|
+
require_relative './simpleproxiesdeployingexception.rb'
|
26
|
+
require_relative './remotehost.rb'
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class SimpleProxiesDeployingException < StandardError
|
2
|
+
attr_accessor :code, :custom_description
|
3
|
+
|
4
|
+
ERROR_CODES = [
|
5
|
+
{ :code => 1, :description => 'Host has not SSH parameters' },
|
6
|
+
{ :code => 2, :description => 'Proxy port is not a valid port' },
|
7
|
+
{ :code => 3, :description => 'No SSH connection' },
|
8
|
+
{ :code => 4, :description => 'SSH connection failed' },
|
9
|
+
{ :code => 5, :description => 'IPv6 subnet /48 is not defined for this host' },
|
10
|
+
{ :code => 6, :description => 'Extenral IP is not belonging the IPv6 subnet /48 defined for this host' },
|
11
|
+
{ :code => 7, :description => 'More than 1 external IP defined for this proxy port' },
|
12
|
+
{ :code => 8, :description => 'There is not external IP defined for this proxy port' },
|
13
|
+
|
14
|
+
# ports batch validations
|
15
|
+
{ :code => 9, :description => "By now proxy_port_from must be #{DEFAULT_PROXY_PORT_FROM}" },
|
16
|
+
{ :code => 10, :description => "proxy_port_to must be higher than proxy_port_from" },
|
17
|
+
{ :code => 11, :description => "[proxy_port_from..proxy_port_to] must be mod of batch size #{DEFAULT_PROXY_PORTS_BATCH_SIZE}" },
|
18
|
+
{ :code => 12, :description => "Other proxies are belonging the same /64 subnet" },
|
19
|
+
{ :code => 13, :description => "Each batch of 50 ports must be all configured or all empty" },
|
20
|
+
{ :code => 14, :description => "Ports outside the range found" },
|
21
|
+
]
|
22
|
+
|
23
|
+
def self.description(code)
|
24
|
+
ERROR_CODES.each do |error_code|
|
25
|
+
return error_code[:description] if error_code[:code] == code
|
26
|
+
end
|
27
|
+
return 'Unknown error code'
|
28
|
+
end
|
29
|
+
|
30
|
+
def simple_description
|
31
|
+
self.class.description(self.code)
|
32
|
+
end
|
33
|
+
|
34
|
+
def description
|
35
|
+
self.custom_description.nil? ? self.simple_description : self.custom_description
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(the_code, the_custom_description = nil)
|
39
|
+
self.code = the_code
|
40
|
+
self.custom_description = the_custom_description.nil? ? nil : "#{SimpleProxiesDeployingException.description(self.code)}: #{the_custom_description}"
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_proxies_deploying
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Leandro Daniel Sardi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-04-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: websocket
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.2.8
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.2.8
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.2.8
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.2.8
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: json
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 1.8.1
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.8.1
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 1.8.1
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.8.1
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: blackstack_commons
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.1.50
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.1.50
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.1.50
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.1.50
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: simple_command_line_parser
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 1.1.2
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.1.2
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.1.2
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.1.2
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: simple_cloud_logging
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 1.1.28
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.1.28
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.1.28
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 1.1.28
|
113
|
+
description: 'Find documentation here: https://github.com/leandrosardi/simple_proxies_deploying.'
|
114
|
+
email: leandro.sardi@expandedventure.com
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- lib/remotehost.rb
|
120
|
+
- lib/simple_proxies_deploying.rb
|
121
|
+
- lib/simpleproxiesdeployingexception.rb
|
122
|
+
homepage: https://rubygems.org/gems/simple_proxies_deploying
|
123
|
+
licenses:
|
124
|
+
- MIT
|
125
|
+
metadata: {}
|
126
|
+
post_install_message:
|
127
|
+
rdoc_options: []
|
128
|
+
require_paths:
|
129
|
+
- lib
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 2.4.5.1
|
143
|
+
signing_key:
|
144
|
+
specification_version: 4
|
145
|
+
summary: Install, monitor, and check configurations of proxy servers.
|
146
|
+
test_files: []
|