spior 0.1.2 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,59 @@
1
+ module Spior
2
+ module Iptables
3
+ class Tor < Iptables::Root
4
+ def initialize
5
+ super
6
+ @tor = Spior::Tor::Info.new
7
+ @non_tor = ["#{@lo_addr}/8", "192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"]
8
+ @tables = ["nat", "filter"]
9
+ end
10
+
11
+ private
12
+
13
+ def redirect
14
+ @tables.each { |table|
15
+ target = "ACCEPT"
16
+ target = "RETURN" if table == "nat"
17
+
18
+ ipt "-t #{table} -F OUTPUT"
19
+ ipt "-t #{table} -A OUTPUT -m state --state ESTABLISHED -j #{target}"
20
+ ipt "-t #{table} -A OUTPUT -m owner --uid #{@tor.uid} -j #{target}"
21
+
22
+ match_dns_port = @tor.dns
23
+ if table == "nat"
24
+ target = "REDIRECT --to-ports #{@tor.dns}"
25
+ match_dns_port = "53"
26
+ end
27
+
28
+ ipt "-t #{table} -A OUTPUT -p udp --dport #{match_dns_port} -j #{target}"
29
+ ipt "-t #{table} -A OUTPUT -p tcp --dport #{match_dns_port} -j #{target}"
30
+
31
+ target = "REDIRECT --to-ports #{@tor.trans_port}" if table == "nat"
32
+ ipt "-t #{table} -A OUTPUT -d #{@tor.virt_addr} -p tcp -j #{target}"
33
+
34
+ target = "RETURN" if table == "nat"
35
+ @non_tor.each { |ip|
36
+ ipt "-t #{table} -A OUTPUT -d #{ip} -j #{target}"
37
+ }
38
+
39
+ target = "REDIRECT --to-ports #{@tor.trans_port}" if table == "nat"
40
+ ipt "-t #{table} -A OUTPUT -p tcp -j #{target}"
41
+ }
42
+ end
43
+
44
+ def input
45
+ # SSH
46
+ ipt "-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT"
47
+ # Allow loopback
48
+ ipt "-A INPUT -i #{@lo} -j ACCEPT"
49
+ # Accept related
50
+ ipt "-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT"
51
+ end
52
+
53
+ def all
54
+ ipt "-t filter -A OUTPUT -p udp -j REJECT"
55
+ ipt "-t filter -A OUTPUT -p icmp -j REJECT"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,186 +1,8 @@
1
- require 'interfacez'
2
- require_relative 'tor'
3
- require_relative 'msg'
4
- require_relative 'helpers'
5
-
6
1
  module Spior
7
- class Iptables
8
-
9
- def self.tor(interface = false)
10
- initialize(interface)
11
- flush_rules
12
- bogus_tcp_flags
13
- bad_packets
14
- spoofing
15
- icmp
16
- dns
17
- nat
18
- input
19
- forward
20
- output
21
- drop_all
22
- end
23
-
24
- def self.flush_rules
25
- @i = Helpers::Exec.new("iptables")
26
- ipt "-F"
27
- ipt "-X"
28
- ipt "-t nat -F"
29
- ipt "-t nat -X"
30
- ipt "-t mangle -F"
31
- ipt "-t mangle -X"
32
- end
33
-
34
- private
35
-
36
- def self.initialize(interface)
37
- @lo = Interfacez.loopback
38
- @lo_addr = Interfacez.ipv4_address_of(@lo)
39
- @tor = Spior::Tor.new
40
- @non_tor = ["#{@lo_addr}/8", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
41
- @incoming = interface
42
- @incoming_addr = Interfacez.ipv4_address_of(@incoming)
43
- end
44
-
45
- def self.check_dep
46
- Spior::Copy::config_files
47
- end
48
-
49
- def self.ipt(line)
50
- @i.run("#{line}")
51
- #puts "added - #{@i} #{line}"
52
- end
53
-
54
- def self.drop_all
55
- ipt "-P INPUT DROP"
56
- ipt "-P FORWARD DROP"
57
- ipt "-P OUTPUT DROP"
58
- end
59
-
60
- def self.bogus_tcp_flags
61
- puts "bogus"
62
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP"
63
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP"
64
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP"
65
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP"
66
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP"
67
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP"
68
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags ACK,FIN FIN -j DROP"
69
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP"
70
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP"
71
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP"
72
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP"
73
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP"
74
- ipt "-t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP"
75
- end
76
-
77
- def self.bad_packets
78
- puts "bad_packets"
79
- # new packet not syn
80
- ipt "-t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP"
81
- # fragment packet
82
- ipt "-A INPUT -f -j DROP"
83
- # XMAS
84
- ipt "-A INPUT -p tcp --tcp-flags ALL ALL -j DROP"
85
- # null packet
86
- ipt "-A INPUT -p tcp --tcp-flags ALL NONE -j DROP"
87
- end
88
-
89
- def self.spoofing
90
- subs=["224.0.0.0/3", "169.254.0.0/16", "172.16.0.0/12", "192.0.2.0/24", "0.0.0.0/8", "240.0.0.0/5"]
91
- subs.each do |sub|
92
- ipt "-t mangle -A PREROUTING -s #{sub} -j DROP"
93
- end
94
- ipt "-t mangle -A PREROUTING -s #{@lo_addr}/8 ! -i #{@lo} -j DROP"
95
- end
96
-
97
- def self.icmp
98
- puts "icmp"
99
- ipt "-N port-scanning"
100
- ipt "-A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURN"
101
- ipt "-A port-scanning -j DROP"
102
-
103
- ipt "-N syn_flood"
104
- ipt "-A INPUT -p tcp --syn -j syn_flood"
105
- ipt "-A syn_flood -m limit --limit 1/s --limit-burst 3 -j RETURN"
106
- ipt "-A syn_flood -j DROP"
107
-
108
- ipt "-A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j ACCEPT"
109
- ipt "-A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix PING-DROP:"
110
- ipt "-A INPUT -p icmp -j DROP"
111
- ipt "-A OUTPUT -p icmp -j ACCEPT"
112
- end
113
-
114
- def self.dns
115
- puts "dns"
116
- ipt "-t nat -A PREROUTING ! -i #{@lo} -p udp -m udp --dport 53 -j REDIRECT --to-ports #{@tor.dns}"
117
- ipt "-t nat -A OUTPUT -p udp -m udp --dport 53 -j REDIRECT --to-ports #{@tor.dns}"
118
- ipt "-t nat -A OUTPUT -p tcp -m tcp --dport 53 -j REDIRECT --to-ports #{@tor.dns}"
119
- end
120
-
121
- def self.nat
122
- puts "nat"
123
- # nat .onion addresses
124
- ipt "-t nat -A OUTPUT -d #{@tor.virt_addr} -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j REDIRECT --to-ports #{@tor.trans_port}"
125
-
126
- # Don't nat the Tor process, the loopback, or the local network
127
- ipt "-t nat -A OUTPUT -m owner --uid-owner #{@tor.uid} -j RETURN"
128
- ipt "-t nat -A OUTPUT -o #{@lo} -j RETURN"
129
-
130
- # Allow lan access for hosts in $non_tor
131
- @non_tor.each do |lan|
132
- ipt "-t nat -A OUTPUT -d #{lan} -j RETURN"
133
- end
134
-
135
- # Redirects all other pre-routing and output to Tor's TransPort
136
- ipt "-t nat -A OUTPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j REDIRECT --to-ports #{@tor.trans_port}"
137
-
138
- # Redirects all other pre-routing and output to Tor's TransPort
139
- ipt "-t nat -A OUTPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j REDIRECT --to-ports #{@tor.trans_port}"
140
- end
141
-
142
- def self.input
143
- puts "input"
144
- ipt "-A INPUT -i #{@incoming} -p tcp -s #{@incoming_addr} --dport 22 -m conntrack --ctstate NEW -j ACCEPT"
145
-
146
- # Allow loopback, rules
147
- ipt "-A INPUT -m state --state ESTABLISHED -j ACCEPT"
148
- ipt "-A INPUT -i #{@lo} -j ACCEPT"
149
-
150
- # Allow DNS lookups from connected clients and internet access through tor.
151
- ipt "-A INPUT -d #{@incoming_addr} -i #{@incoming} -p udp -m udp --dport #{@tor.dns} -j ACCEPT"
152
- ipt "-A INPUT -d #{@incoming_addr} -i #{@incoming} -p tcp -m tcp --dport #{@tor.trans_port} --tcp-flags FIN,SYN,RST,ACK SYN -j ACCEPT"
153
-
154
- # Default
155
- ipt "-A INPUT -j DROP"
156
- end
157
-
158
- def self.output
159
- puts "output"
160
- ipt "-A OUTPUT -m conntrack --ctstate INVALID -j LOG --log-prefix \"DROP INVALID \" --log-ip-options --log-tcp-options"
161
- ipt "-A OUTPUT -m conntrack --ctstate INVALID -j DROP"
162
- ipt "-A OUTPUT -m state --state ESTABLISHED -j ACCEPT"
163
-
164
- # output
165
- ipt "-A OUTPUT -m owner --uid-owner #{@tor.uid} -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT"
166
-
167
- # Accept, allow loopback output
168
- ipt "-A OUTPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT"
169
- ipt "-A OUTPUT -d #{@lo_addr}/32 -o #{@lo} -j ACCEPT"
170
-
171
- # tor transparent magic
172
- ipt "-A OUTPUT -d #{@lo_addr}/32 -p tcp -m tcp --dport #{@tor.trans_port} --tcp-flags FIN,SYN,RST,ACK SYN -j ACCEPT"
173
-
174
- ipt "-A OUTPUT -j DROP"
175
- end
176
-
177
- def self.forward
178
- puts "forward"
179
- ipt "-A FORWARD -m conntrack --ctstate INVALID -j LOG --log-prefix \"DROP INVALID \" --log-ip-options --log-tcp-options"
180
- ipt "-A FORWARD -m conntrack --ctstate INVALID -j DROP"
181
- ipt "-A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT"
182
- ipt "-A FORWARD -i #{@incoming} ! -s #{@incoming_addr} -j LOG --log-prefix \"SPOOFED PKT \""
183
- ipt "-A FORWARD -i #{@incoming} ! -s #{@incoming_addr} -j DROP"
184
- end
2
+ module Iptables
185
3
  end
186
4
  end
5
+
6
+ require_relative 'iptables/root'
7
+ require_relative 'iptables/tor'
8
+ require_relative 'iptables/default'
data/lib/spior/menu.rb CHANGED
@@ -1,11 +1,3 @@
1
- require_relative 'msg'
2
- require_relative 'mac'
3
- require_relative 'iptables'
4
- require_relative 'network'
5
- require_relative 'reload'
6
- require_relative 'clear'
7
- require_relative 'status'
8
-
9
1
  module Spior
10
2
  module Menu
11
3
  extend self
@@ -16,30 +8,25 @@ module Spior
16
8
  Msg.head
17
9
  puts %q{Please select an option:
18
10
 
19
- 1. Forge a new MAC address
20
- 2. Redirect traffic through tor
21
- 3. Reload tor and change your ip
22
- 4. Clear and restore your files
23
- 5. Check info on your current ip
24
- 6. Quit}
11
+ 1. Redirect traffic through tor
12
+ 2. Reload tor and change your ip
13
+ 3. Clear and restore your files
14
+ 4. Check info on your current ip
15
+ 5. Quit}
25
16
 
26
17
  puts
27
18
  print ">> "
28
19
  case gets.chomp
29
- when '1'
30
- check_network
31
- Spior::MAC::randomize(@network.card)
32
- when '2'
33
- check_network
34
- Spior::Iptables::tor(@network.card)
35
- when '3'
36
- Spior::Reload::tor
37
- when '4'
38
- Spior::Clear::all
39
- when '5'
40
- Spior::Status::info
41
- when '6'
42
- exit
20
+ when '1'
21
+ Spior::Iptables::Tor.new.run!
22
+ when '2'
23
+ Spior::Serice.restart
24
+ when '3'
25
+ Spior::Clear.all
26
+ when '4'
27
+ Spior::Status.info
28
+ when '5'
29
+ exit
43
30
  end
44
31
  end
45
32
  end
@@ -52,11 +39,5 @@ module Spior
52
39
  puts "┗━┛╹ ╹┗━┛╹┗╸"
53
40
  # generated with toilet -F crop -f future spior
54
41
  end
55
-
56
- def check_network
57
- if not @network
58
- @network = Spior::Network.new
59
- end
60
- end
61
42
  end
62
43
  end
data/lib/spior/msg.rb CHANGED
@@ -1,30 +1,28 @@
1
1
  require 'rainbow'
2
2
 
3
3
  module Msg
4
- def self.head
4
+ extend self
5
+
6
+ def head
5
7
  puts Rainbow("------------------------------------------------").cyan
6
8
  end
7
9
 
8
- def self.p(text)
10
+ def p(text)
9
11
  puts Rainbow("[").cyan + Rainbow("+").white + Rainbow("]").cyan + " " + text
10
12
  end
11
13
 
12
- def self.err(text)
14
+ def err(text)
13
15
  puts Rainbow("[").red + Rainbow("-").white + Rainbow("]").red + " " + text
14
16
  end
15
17
 
16
- def self.info(text)
18
+ def info(text)
17
19
  puts Rainbow("-").blue + Rainbow("-").white + Rainbow("-").blue + " " + text + " " + Rainbow("-").blue + Rainbow("-").white + Rainbow("-").blue
18
20
  end
19
21
 
20
- def self.report(text)
22
+ def report(text)
21
23
  puts ""
22
24
  info text
23
25
  puts "Please, report this issue at https://github.com/szorfein/spior/issues"
24
26
  puts ""
25
27
  end
26
-
27
- def self.for_no_systemd
28
- puts "Init system is not yet supported. You can contribute to add it."
29
- end
30
28
  end
data/lib/spior/options.rb CHANGED
@@ -1,16 +1,11 @@
1
1
  require 'optparse'
2
- require_relative 'reload'
3
- require_relative 'status'
4
- require_relative 'clear'
5
- require_relative 'menu'
6
2
 
7
3
  module Spior
8
4
  class Options
9
- attr_reader :install , :mac , :interface , :tor , :persist
5
+ attr_reader :install , :tor , :persist
10
6
 
11
7
  def initialize(argv)
12
8
  @install = false
13
- @mac = false
14
9
  @tor = false
15
10
  @persist = false
16
11
  parse(argv)
@@ -20,32 +15,26 @@ module Spior
20
15
 
21
16
  def parse(argv)
22
17
  OptionParser.new do |opts|
23
- opts.on("-i", "--install", "Install and update dependencies") do
18
+ opts.on("-i", "--install", "Install the dependencies") do
24
19
  @install = true
25
20
  end
26
21
 
27
- opts.on("-n", "--net-card NAME", "The name of the target network card") do |net|
28
- @interface = net
29
- end
30
-
31
- opts.on("-m", "--mac", "Change your mac") do
32
- @mac = true
33
- end
34
-
35
22
  opts.on("-t", "--tor", "Redirect traffic through TOR") do
36
23
  @tor = true
37
24
  end
38
25
 
39
26
  opts.on("-r", "--reload", "Reload TOR to change your ip") do
40
- Spior::Reload::tor
27
+ Spior::Service.restart
28
+ exit
41
29
  end
42
30
 
43
- opts.on("-c", "--clear", "Clear iptables rules and restore files") do
44
- Spior::Clear::all
31
+ opts.on("-c", "--clearnet", "Reset iptables and return to clearnet navigation") do
32
+ Spior::Clear.all
45
33
  end
46
34
 
47
35
  opts.on("-s", "--status", "Look infos about your current ip") do
48
- Spior::Status::info
36
+ Spior::Status.info
37
+ exit
49
38
  end
50
39
 
51
40
  opts.on("-p", "--persist", "Active Spior at every boot.") do
@@ -53,7 +42,7 @@ module Spior
53
42
  end
54
43
 
55
44
  opts.on("-m", "--menu", "Display an interactive menu") do
56
- Spior::Menu::run
45
+ Spior::Menu.run
57
46
  end
58
47
 
59
48
  opts.on("-h", "--help", "Show this message") do
data/lib/spior/persist.rb CHANGED
@@ -1,46 +1,50 @@
1
1
  require 'nomansland'
2
2
  require 'tty-which'
3
- require_relative 'copy'
4
- require_relative 'msg'
5
- require_relative 'helpers'
6
3
 
7
4
  module Spior
8
5
  module Persist
9
6
  extend self
10
7
 
11
- def all(card_name)
12
- @card_name = card_name
13
- @services=[ "tor", "iptables", "deceitmac@" + @card_name ]
14
- search_for_systemd
8
+ def enable
9
+ case Nomansland::distro?
10
+ when :gentoo
11
+ for_gentoo
12
+ else
13
+ Msg.p "Your distro is not yet supported."
14
+ end
15
15
  end
16
16
 
17
17
  private
18
18
 
19
- def search_for_systemd
20
- return if !TTY::Which.exist?('systemctl')
21
- @systemctl = Helpers::Exec.new("systemctl")
22
- @iptables_save = Helpers::Exec.new("iptables-save")
23
- Spior::Copy::systemd_services
24
- @services.each do |service|
25
- Msg.p "Search for service #{service}..."
26
- `systemctl is-enabled #{service}`
27
- if not $?.success? then
28
- @systemctl.run("enable #{service}")
29
- end
19
+ def for_gentoo
20
+ if TTY::Which.exist?('systemctl')
21
+ systemd_start("iptables-store")
22
+ systemd_enable("iptables-restore")
23
+ systemd_enable("tor")
24
+ else
25
+ system("sudo /etc/init.d/iptables save")
26
+ rc_upd = Helpers::Exec.new("rc-update")
27
+ rc_upd.run("rc-update add iptables boot")
28
+ rc_upd.run("rc-update add tor")
29
+ rc_upd.run("rc-update add tor default")
30
30
  end
31
- iptables_systemd
32
31
  end
33
32
 
34
- def iptables_systemd
35
- case Nomansland::installer?
36
- when :pacman
37
- @iptables_save.run("-f /etc/iptables/iptables.rules")
38
- when :emerge
39
- @systemctl.run("start iptables-store")
40
- when :apt_get
41
- @iptables_save.run("> /etc/iptables/rules.v4")
42
- else
43
- Msg.report "Fail for save iptables-rule, your system is not yet supported"
33
+ def systemd_enable(service)
34
+ systemctl = Helpers::Exec.new("systemctl")
35
+ Msg.p "Search for service #{service}..."
36
+ `systemctl is-enabled #{service}`
37
+ if not $?.success? then
38
+ systemctl.run("enable #{service}")
39
+ end
40
+ end
41
+
42
+ def systemd_start(service)
43
+ systemctl = Helpers::Exec.new("systemctl")
44
+ Msg.p "Search for service #{service}..."
45
+ `systemctl is-active #{service}`
46
+ if not $?.success? then
47
+ systemctl.run("start #{service}")
44
48
  end
45
49
  end
46
50
  end
@@ -0,0 +1,21 @@
1
+ require 'tty-which'
2
+
3
+ module Spior
4
+ module Service
5
+ module_function
6
+
7
+ def restart
8
+ if TTY::Which.exist?('systemctl')
9
+ Helpers::Exec.new("systemctl").run("restart tor")
10
+ Msg.p "ip changed."
11
+ elsif TTY::Which.exist? 'sv'
12
+ Helpers::Exec.new('sv').run('restart tor')
13
+ Msg.p 'ip changed.'
14
+ elsif File.exist? '/etc/init.d/tor'
15
+ Helpers::Exec.new('/etc/init.d/tor').run('restart')
16
+ else
17
+ Msg.report "Don't known yet how to restart Tor for your system."
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ require 'tty-which'
2
+
3
+ module Spior
4
+ module Service
5
+ module_function
6
+
7
+ def start
8
+ if TTY::Which.exist?('systemctl')
9
+ state = `systemctl is-active tor`.chomp
10
+ unless state == 'active'
11
+ Helpers::Exec.new("systemctl").run("start tor")
12
+ Msg.p "TOR started."
13
+ end
14
+ elsif TTY::Which.exist? 'sv'
15
+ unless File.exist? '/var/service/tor'
16
+ Helpers::Exec.new('ln').run('-s /etc/sv/tor /var/service/tor')
17
+ Msg.p "TOR started."
18
+ end
19
+ elsif File.exist? '/etc/init.d/tor'
20
+ Helpers::Exec.new('/etc/init.d/tor').run('start')
21
+ else
22
+ Msg.report "Don't known yet how to start Tor for your system."
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,7 @@
1
+ module Spior
2
+ module Service
3
+ end
4
+ end
5
+
6
+ require_relative 'service/start'
7
+ require_relative 'service/restart'
data/lib/spior/status.rb CHANGED
@@ -1,20 +1,38 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  require 'open-uri'
2
+ require 'json'
4
3
 
5
4
  module Spior
6
- class Status
5
+ module Status
6
+ def self.enable
7
+ begin
8
+ status = "Disable"
9
+ api_check = "https://check.torproject.org/api/ip"
10
+ URI.open(api_check) do |l|
11
+ hash = JSON.parse l.read
12
+ status = "Enable" if hash["IsTor"] == true
13
+ end
14
+ status
15
+ rescue OpenURI::HTTPError => error
16
+ res = error.io
17
+ puts "Fail to join server #{res.status}"
18
+ end
19
+ end
7
20
 
8
- # TODO: if someone want help, i have trouble to make JSON.parse() work here
9
- # the output is very very ugly !
10
21
  def self.info
11
- uri = URI.parse("https://ipleak.net/json")
12
- uri.open {|f|
13
- f.each_line {|line|
14
- p line.chomp.delete("/\",{}")
15
- }
16
- }
22
+ begin
23
+ api_check = "https://ipleak.net/json"
24
+ URI.open(api_check) do |l|
25
+ hash = JSON.parse l.read
26
+ puts
27
+ puts " Current ip ===> #{hash["ip"]}"
28
+ puts " Continent ===> #{hash["continent_name"]}"
29
+ puts " Timezone ===> #{hash["time_zone"]}"
30
+ end
31
+ puts " Status ===> #{enable}"
32
+ rescue OpenURI::HTTPError => error
33
+ res = error.io
34
+ puts "Fail to join server #{res.status}"
35
+ end
17
36
  end
18
-
19
37
  end
20
38
  end