spior 0.1.6 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/rubocop-analysis.yml +47 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +21 -0
- data/Gemfile +5 -0
- data/README.md +13 -3
- data/Rakefile +20 -9
- data/bin/spior +1 -0
- data/lib/auth.rb +46 -0
- data/lib/spior/dep.rb +38 -23
- data/lib/spior/helpers.rb +22 -25
- data/lib/spior/iptables/default.rb +19 -13
- data/lib/spior/iptables/root.rb +37 -37
- data/lib/spior/iptables/rules.rb +103 -0
- data/lib/spior/iptables/tor.rb +24 -23
- data/lib/spior/iptables.rb +4 -0
- data/lib/spior/ipv6.rb +35 -0
- data/lib/spior/menu.rb +18 -24
- data/lib/spior/msg.rb +30 -8
- data/lib/spior/options.rb +20 -22
- data/lib/spior/service/enable.rb +66 -0
- data/lib/spior/service/restart.rb +5 -12
- data/lib/spior/service/start.rb +7 -17
- data/lib/spior/service/stop.rb +14 -0
- data/lib/spior/service.rb +5 -0
- data/lib/spior/status.rb +32 -24
- data/lib/spior/tor/config.rb +137 -0
- data/lib/spior/tor/data.rb +53 -0
- data/lib/spior/tor/start.rb +65 -0
- data/lib/spior/tor/stop.rb +53 -0
- data/lib/spior/tor.rb +7 -1
- data/lib/spior/version.rb +3 -1
- data/lib/spior.rb +18 -23
- data/spior.gemspec +24 -21
- data/test/test_install.rb +2 -2
- data/test/test_options.rb +2 -0
- data.tar.gz.sig +2 -2
- metadata +59 -51
- metadata.gz.sig +0 -0
- data/lib/spior/clear.rb +0 -35
- data/lib/spior/copy.rb +0 -84
- data/lib/spior/persist.rb +0 -51
- data/lib/spior/tor/info.rb +0 -96
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'auth'
|
6
|
+
|
7
|
+
module Spior
|
8
|
+
module Tor
|
9
|
+
# Generate a config file (torrc) for Spior
|
10
|
+
class Config
|
11
|
+
# ==== Attributes
|
12
|
+
#
|
13
|
+
# * +filename+ - A reference to a tempfile like filename=Tempfile.new('foo')
|
14
|
+
#
|
15
|
+
def initialize(filename)
|
16
|
+
@filename = filename
|
17
|
+
@config_torrc = '/etc/tor/torrc'
|
18
|
+
@config_dir = '/etc/torrc.d'
|
19
|
+
@config_spiorrc = "#{@config_dir}/spior.conf"
|
20
|
+
@content = ['# Generated by Spior, don\'t edit.']
|
21
|
+
@content_torrc = []
|
22
|
+
end
|
23
|
+
|
24
|
+
# Generate a `torrc` compatible file for Spior
|
25
|
+
# Use value from Spior::CONFIG
|
26
|
+
def generate
|
27
|
+
create_config_dir
|
28
|
+
configure_torrc
|
29
|
+
generate_content(@content)
|
30
|
+
return if @content.length == 1
|
31
|
+
|
32
|
+
cn = @content.join("\n")
|
33
|
+
File.write(@filename.path, "#{cn}\n")
|
34
|
+
Msg.p "Generating #{@config_spiorrc}..."
|
35
|
+
move(@filename.path, @config_spiorrc)
|
36
|
+
end
|
37
|
+
|
38
|
+
def write_file(content, file, mode = 'a')
|
39
|
+
return if content.nil?
|
40
|
+
|
41
|
+
File.open(file, mode) do |f|
|
42
|
+
if content.is_a?(Array)
|
43
|
+
f.puts(content.join('\n'))
|
44
|
+
else
|
45
|
+
f.puts(content)
|
46
|
+
end
|
47
|
+
# f.chmod(644)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Save current Tor options (Spior::CONFIG) in /etc/tor/torrc
|
52
|
+
# Only if theses options are not alrealy present
|
53
|
+
def backup
|
54
|
+
generate_content(@content_torrc)
|
55
|
+
write_file @content_torrc, @filename.path, 'w'
|
56
|
+
|
57
|
+
Msg.p 'Saving Tor options...'
|
58
|
+
move(@filename.path, @config_spiorrc)
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def create_config_dir
|
64
|
+
return if Dir.exist? @config_dir
|
65
|
+
|
66
|
+
if Process::Sys.getuid == '0'
|
67
|
+
File.mkdir @config_dir
|
68
|
+
else
|
69
|
+
Auth.new.mkdir @config_dir
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def configure_torrc
|
74
|
+
temp = Tempfile.new('torrc')
|
75
|
+
content = File.read(@config_torrc)
|
76
|
+
adding content, "%include #{@config_dir}/*.conf"
|
77
|
+
write_file content, temp.path
|
78
|
+
move(temp.path, @config_torrc)
|
79
|
+
end
|
80
|
+
|
81
|
+
def generate_content(content)
|
82
|
+
adding content, 'AutomapHostsOnResolve 1'
|
83
|
+
adding content, "DNSPort #{CONFIG.dns_port}"
|
84
|
+
adding content, "VirtualAddrNetworkIpv4 #{CONFIG.virt_addr}"
|
85
|
+
adding content, "TransPort #{CONFIG.trans_port} IsolateClientAddr
|
86
|
+
IsolateClientProtocol IsolateDestAddr IsolateDestPort"
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def search(option_name)
|
92
|
+
File.open(@config_torrc) do |f|
|
93
|
+
f.each do |line|
|
94
|
+
return Regexp.last_match(1) if line.match(%r{^#{option_name} ([a-z0-9./*]*)}i)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
false
|
98
|
+
end
|
99
|
+
|
100
|
+
def adding(content, option)
|
101
|
+
o = option.split(' ')
|
102
|
+
all = o[1..o.length].join(' ')
|
103
|
+
return if search(o[0])
|
104
|
+
|
105
|
+
content << "#{o[0]} #{all}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def digest_match?(src, dest)
|
109
|
+
return unless File.exist?(dest)
|
110
|
+
|
111
|
+
md5_src = Digest::MD5.file src
|
112
|
+
md5_dest = Digest::MD5.file dest
|
113
|
+
md5_src == md5_dest
|
114
|
+
end
|
115
|
+
|
116
|
+
# Permission for Archlinux on a torrc are chmod 644, chown root:root
|
117
|
+
def fix_perm(file)
|
118
|
+
if Process::Sys.getuid == '0'
|
119
|
+
file.chown(0, 0)
|
120
|
+
else
|
121
|
+
Helpers::Exec.new('chown').run("root:root #{file}")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def move(src, dest)
|
126
|
+
return if digest_match? src, dest
|
127
|
+
|
128
|
+
fix_perm(@filename.path)
|
129
|
+
if Process::Sys.getuid == '0'
|
130
|
+
FileUtils.mv(src, dest)
|
131
|
+
else
|
132
|
+
Helpers::Exec.new('mv').run("#{src} #{dest}")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nomansland'
|
4
|
+
|
5
|
+
module Spior
|
6
|
+
module Tor
|
7
|
+
##
|
8
|
+
# Data
|
9
|
+
# Fill Spior::CONFIG with data found on `/etc/tor/torrc` or set default.
|
10
|
+
#
|
11
|
+
# ==== Attributes
|
12
|
+
#
|
13
|
+
# * +user+ - Username used by Tor on your distro, e.g 'tor' on Archlinux
|
14
|
+
# * +dns_port+ - Open this port to listen for UDP DNS requests, and resolve them anonymously
|
15
|
+
# * +uid+ - The uid value from the user attribute.
|
16
|
+
# * +trans_port+ - Port to open to listen for transparent proxy connections.
|
17
|
+
# * +virt_addr+ - Default use '10.192.0.0/10'.
|
18
|
+
#
|
19
|
+
class Data
|
20
|
+
attr_accessor :user, :dns_port, :trans_port, :virt_addr, :uid
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@user = search('User') || 'tor'
|
24
|
+
@dns_port = search('DNSPort') || '9061'
|
25
|
+
@trans_port = search('TransPort') || '9040'
|
26
|
+
@virt_addr = search('VirtualAddrNetworkIPv4') || '10.192.0.0/10'
|
27
|
+
@uid = search_uid || 0
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Search value of option_name in the /etc/tor/torrc
|
33
|
+
# Return false by default
|
34
|
+
def search(option_name)
|
35
|
+
File.open('/etc/tor/torrc') do |f|
|
36
|
+
f.each do |line|
|
37
|
+
return Regexp.last_match(1) if line.match(%r{#{option_name} ([a-z0-9./]*)}i)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def search_uid
|
44
|
+
case Nomansland.distro?
|
45
|
+
when :debian || :ubuntu
|
46
|
+
`id -u debian-tor`.chomp
|
47
|
+
else
|
48
|
+
`id -u #{@user}`.chomp
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nomansland'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module Spior
|
7
|
+
# Module Spior::Tor used to start/stop/restart Tor on the system.
|
8
|
+
module Tor
|
9
|
+
# start should start the Tor service on your distribution
|
10
|
+
class Start
|
11
|
+
def initialize
|
12
|
+
tmp_file = Tempfile.new('torrc')
|
13
|
+
|
14
|
+
Config.new(tmp_file).generate
|
15
|
+
|
16
|
+
nomansland
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def nomansland
|
22
|
+
case Nomansland.init?
|
23
|
+
when :systemd
|
24
|
+
start_systemd
|
25
|
+
when :openrc
|
26
|
+
start_openrc
|
27
|
+
when :runit
|
28
|
+
start_runit
|
29
|
+
else
|
30
|
+
Msg.report "Don't known yet how to start Tor for your system."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def start_systemd
|
37
|
+
state = `systemctl is-active tor`.chomp
|
38
|
+
return if state == 'active'
|
39
|
+
|
40
|
+
Msg.p 'Starting Tor with Systemd...'
|
41
|
+
Helpers::Exec.new('systemctl').run('start tor')
|
42
|
+
end
|
43
|
+
|
44
|
+
def start_openrc
|
45
|
+
Msg.p 'Starting Tor with OpenRC...'
|
46
|
+
Helpers::Exec.new('/etc/init.d/tor').run('start')
|
47
|
+
end
|
48
|
+
|
49
|
+
def start_runit
|
50
|
+
Msg.p 'Starting Tor with Runit...'
|
51
|
+
if File.exist? '/var/service/tor'
|
52
|
+
Helpers::Exec.new('sv').run('start tor')
|
53
|
+
else
|
54
|
+
Helpers::Exec.new('ln').run('-s /etc/sv/tor /var/service/tor')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def x(arg)
|
59
|
+
auth = (Process::Sys.getuid == '0' ? '' : 'sudo')
|
60
|
+
pid = spawn("#{auth} #{arg}", out: '/dev/null') or raise 'Error'
|
61
|
+
Process.wait pid
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spior
|
4
|
+
# Module Spior::Tor used to start/stop/restart Tor on the system.
|
5
|
+
module Tor
|
6
|
+
# Stop Tor service on your distribution (linux)
|
7
|
+
# It also kill previous instance run by Spior
|
8
|
+
class Stop
|
9
|
+
def initialize
|
10
|
+
old_pid = `pgrep -f "tor -f /tmp/torrc*"`.chomp
|
11
|
+
|
12
|
+
if old_pid != ''
|
13
|
+
Msg.p "Found old pid > #{old_pid}, killing it..."
|
14
|
+
Helpers::Exec.new('kill').run("-9 #{old_pid}")
|
15
|
+
end
|
16
|
+
|
17
|
+
nomansland
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def nomansland
|
23
|
+
case Nomansland.init?
|
24
|
+
when :systemd
|
25
|
+
stop_systemd
|
26
|
+
when :runit
|
27
|
+
stop_runit
|
28
|
+
when :openrc
|
29
|
+
stop_openrc
|
30
|
+
else
|
31
|
+
Msg.report 'Don\'t known how to stop Tor on your system.'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def stop_systemd
|
38
|
+
Msg.p 'Stopping Tor with Systemd...'
|
39
|
+
Helpers::Exec.new('systemctl').run('stop tor')
|
40
|
+
end
|
41
|
+
|
42
|
+
def stop_runit
|
43
|
+
Msg.p 'Stopping Tor with Runit...'
|
44
|
+
Helpers::Exec.new('sv').run('stop tor')
|
45
|
+
end
|
46
|
+
|
47
|
+
def stop_openrc
|
48
|
+
Msg.p 'Stopping Tor with Openrc...'
|
49
|
+
Helpers::Exec.new('/etc/init.d/tor').run('stop')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/spior/tor.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Spior
|
4
|
+
# The module Tor interract with Tor on your system.
|
2
5
|
module Tor
|
3
6
|
end
|
4
7
|
end
|
5
8
|
|
6
|
-
require_relative 'tor/
|
9
|
+
require_relative 'tor/data'
|
10
|
+
require_relative 'tor/config'
|
11
|
+
require_relative 'tor/start'
|
12
|
+
require_relative 'tor/stop'
|
data/lib/spior/version.rb
CHANGED
data/lib/spior.rb
CHANGED
@@ -1,44 +1,39 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
require_relative 'spior/dep'
|
4
4
|
require_relative 'spior/iptables'
|
5
5
|
require_relative 'spior/msg'
|
6
6
|
require_relative 'spior/options'
|
7
7
|
require_relative 'spior/status'
|
8
8
|
require_relative 'spior/tor'
|
9
|
-
require_relative 'spior/persist'
|
10
9
|
require_relative 'spior/menu'
|
11
10
|
require_relative 'spior/service'
|
12
11
|
require_relative 'spior/helpers'
|
12
|
+
require_relative 'spior/ipv6'
|
13
13
|
|
14
14
|
module Spior
|
15
|
+
# Contain value of Tor::Data
|
16
|
+
# Can be customized, e.g:
|
17
|
+
#
|
18
|
+
# Spior::CONFIG.dns_port = '5353'
|
19
|
+
# Spior::CONFIG.trans_port = '8888'
|
20
|
+
# Spior::CONFIG.uid = '666'
|
21
|
+
# Spior::CONFIG.user = 'Tor-User-System'
|
22
|
+
# Spior::CONFIG.virt_addr = '10.192.0.0/10'
|
23
|
+
CONFIG = Tor::Data.new
|
24
|
+
|
25
|
+
# Main for the CLI
|
15
26
|
class Main
|
16
27
|
def initialize(argv)
|
17
28
|
@argv = argv
|
18
|
-
|
29
|
+
x
|
19
30
|
end
|
20
31
|
|
21
32
|
private
|
22
33
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
if options.install
|
27
|
-
Msg.head
|
28
|
-
Dep.install
|
29
|
-
Copy.new.save
|
30
|
-
end
|
31
|
-
|
32
|
-
Dep.check
|
33
|
-
|
34
|
-
if options.tor
|
35
|
-
Msg.head
|
36
|
-
Iptables::Tor.new.run!
|
37
|
-
end
|
38
|
-
|
39
|
-
if options.persist
|
40
|
-
Persist.enable
|
41
|
-
end
|
34
|
+
def x
|
35
|
+
Msg.banner
|
36
|
+
Options.new(@argv)
|
42
37
|
end
|
43
38
|
end
|
44
39
|
end
|
data/spior.gemspec
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "#{File.dirname(__FILE__)}/lib/spior/version"
|
2
4
|
|
3
5
|
Gem::Specification.new do |s|
|
4
|
-
s.name =
|
6
|
+
s.name = 'spior'
|
5
7
|
s.version = Spior::VERSION
|
6
|
-
s.summary =
|
7
|
-
s.description = <<-
|
8
|
+
s.summary = 'A tool to make TOR your default gateway'
|
9
|
+
s.description = <<-DESC
|
8
10
|
A tool to make TOR your default gateway
|
9
|
-
|
11
|
+
DESC
|
10
12
|
s.metadata = {
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
'changelog_uri' => 'https://github.com/szorfein/spior/blob/master/CHANGELOG.md',
|
14
|
+
'bug_tracker_uri' => 'https://github.com/szorfein/spior/issues',
|
15
|
+
'wiki_uri' => 'https://github.com/szorfein/spior'
|
14
16
|
}
|
15
|
-
s.author =
|
17
|
+
s.author = 'szorfein'
|
16
18
|
|
17
19
|
s.platform = Gem::Platform::RUBY
|
18
20
|
|
@@ -20,24 +22,25 @@ Gem::Specification.new do |s|
|
|
20
22
|
s.email = 'szorfein@protonmail.com'
|
21
23
|
s.homepage = 'https://github.com/szorfein/spior'
|
22
24
|
|
23
|
-
s.files = `git ls-files`.split(
|
24
|
-
s.files.reject! { |fn| fn.include?
|
25
|
-
s.files.reject! { |fn| fn.include?
|
26
|
-
s.executables = [
|
25
|
+
s.files = `git ls-files`.split(' ')
|
26
|
+
s.files.reject! { |fn| fn.include? 'certs' }
|
27
|
+
s.files.reject! { |fn| fn.include? 'test' }
|
28
|
+
s.executables = ['spior']
|
29
|
+
|
30
|
+
s.extra_rdoc_files = Dir['README.md', 'CHANGELOG.md', 'LICENSE.txt']
|
27
31
|
|
28
|
-
s.
|
32
|
+
s.test_files = Dir['test/test_*.rb']
|
29
33
|
|
30
|
-
s.test_files = Dir["test/test_*.rb"]
|
31
34
|
s.cert_chain = ['certs/szorfein.pem']
|
32
|
-
s.signing_key = File.expand_path(
|
35
|
+
s.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
|
33
36
|
|
34
37
|
s.requirements << 'tor'
|
35
38
|
s.requirements << 'iptables'
|
36
39
|
|
37
|
-
s.required_ruby_version = '>=2.
|
40
|
+
s.required_ruby_version = '>= 2.6'
|
38
41
|
|
39
|
-
s.add_runtime_dependency('
|
40
|
-
s.add_runtime_dependency('
|
41
|
-
s.add_runtime_dependency('
|
42
|
-
s.add_runtime_dependency('tty-which', '0.
|
42
|
+
s.add_runtime_dependency('interfacez', '~> 1.0')
|
43
|
+
s.add_runtime_dependency('nomansland', '~> 0.0')
|
44
|
+
s.add_runtime_dependency('rainbow', '~> 3.1')
|
45
|
+
s.add_runtime_dependency('tty-which', '~> 0.5')
|
43
46
|
end
|
data/test/test_install.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'minitest/autorun'
|
2
4
|
require_relative '../lib/spior/install'
|
3
5
|
require 'pathname'
|
4
6
|
|
5
7
|
class TestInstall < Minitest::Test
|
6
|
-
|
7
8
|
def test_sudo_is_installed
|
8
9
|
sudo = `which sudo`
|
9
10
|
assert_match(/sudo/, sudo, "sudo isn't installed?")
|
10
11
|
end
|
11
|
-
|
12
12
|
end
|
data/test/test_options.rb
CHANGED
data.tar.gz.sig
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
A��@������s���D�.�뿹���;��������V}9���Jv�FX�Q.֬ڸK������S�(���v(��:&��]�}xoR�G)4F㎓��u�X ��F�1֠5���Rt��]�[�)р�==y~�r��S��KZ���LtM���j�F�V*����ƽC��o6��.�w��Nf�'kA��9�p�Z���)��2�X��:Q�Q���)�H�V�ߛ���)��=��}��k��H��k��OtH9zq�dB��P�}��;�����h�F
|
2
|
+
�}f�,�u�naKia����tQj�C�\^:�^�x@�s�jS(��.�@���z0���|!x�R�t��9�}�E��}�<o��evq䗎��ч�����7/de�
|