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 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: []