tornados 0.1.0 → 0.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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +11 -4
- data/lib/tornados/cli_client.rb +61 -32
- data/lib/tornados/filter.rb +19 -0
- data/lib/tornados/geo_enrich.rb +15 -8
- data/lib/tornados/max_db_fetcher.rb +5 -4
- data/lib/tornados/nodes_fetcher.rb +1 -1
- data/lib/tornados/version.rb +1 -1
- data/lib/tornados.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db771b465f7959bd5544df4738b70261ee53ac2424924495ca32f99ab0f3c844
|
4
|
+
data.tar.gz: 350485c2fc597319c63fb8b3f815310e82f31aa41a4b5e44585ee67dea29ca7c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b8f5f3b8f0ef2ccfd67cccc49eab4af0651e51d4724245b8bc3f0db7cdc727186a4ae10401be7ecce1a50ae66d8728cc0cef93abbf37727b51cc1ab1b937ae1
|
7
|
+
data.tar.gz: e70bb40a3d8c955807188c47ea6877232cc2d6c8fea710175f479b847b76cf7405a6fe39100cccb5ee54d2c7d87fab14d6ed1ed0a7a8f169618284bbd67605e8
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -14,14 +14,21 @@ To install
|
|
14
14
|
```bash
|
15
15
|
gem install tornados
|
16
16
|
```
|
17
|
-
|
18
|
-
|
17
|
+
To use (-k - is a MaxMind secret key):
|
18
|
+
```bash
|
19
|
+
tornados -k key
|
20
|
+
```
|
21
|
+
or (MaxMind keys as environmet variable and -i key define what country nodes to include into result):
|
19
22
|
```bash
|
20
|
-
tornados
|
23
|
+
GEO_API_DATABASE_LICENSE_KEY=key tornados -i RU
|
21
24
|
```
|
22
25
|
After this, tor_exit_nodes_list.csv will be created in current directory.
|
23
26
|
|
24
27
|
You can use this file in SIEM, for example, to detection malicious network traffic.
|
28
|
+
To display help info:
|
29
|
+
```ruby
|
30
|
+
tornados -h
|
31
|
+
```
|
25
32
|
|
26
33
|
## Library
|
27
34
|
|
@@ -47,7 +54,7 @@ returns array of arrays whith next format
|
|
47
54
|
### Tornados::MaxDbFetcher
|
48
55
|
|
49
56
|
```ruby
|
50
|
-
Tornados::MaxDbFetcher.call
|
57
|
+
Tornados::MaxDbFetcher.call(key)
|
51
58
|
```
|
52
59
|
download to disk max db file and return path to it
|
53
60
|
|
data/lib/tornados/cli_client.rb
CHANGED
@@ -1,37 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "optparse"
|
4
|
+
|
3
5
|
module Tornados
|
4
6
|
class CliClient
|
7
|
+
private
|
8
|
+
|
9
|
+
attr_reader :options
|
10
|
+
|
11
|
+
public
|
12
|
+
|
5
13
|
def start
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
else
|
10
|
-
print_prompt_with_input
|
11
|
-
end
|
12
|
-
prepare_result(user_args)
|
14
|
+
prepare_options
|
15
|
+
print_prompt
|
16
|
+
prepare_result
|
13
17
|
print_finish_message
|
14
18
|
end
|
15
19
|
|
16
20
|
private
|
17
21
|
|
18
|
-
def print_prompt
|
19
|
-
puts <<~TEXT
|
20
|
-
Example of usage:
|
21
|
-
GEO_API_KEY=key tornado <uri>, <result file>
|
22
|
-
Runs with default args:
|
23
|
-
tor nodes URI = #{Tornados::NodesFetcher.default_url}
|
24
|
-
result_file = #{Tornados::FileWriter.default_result_file}
|
25
|
-
TEXT
|
26
|
-
end
|
27
|
-
|
28
|
-
def print_prompt_with_input
|
22
|
+
def print_prompt()
|
29
23
|
puts <<~TEXT
|
30
|
-
Example of usage:
|
31
|
-
GEO_API_KEY=key tornado <uri>, <result file>
|
32
24
|
Runs with args:
|
33
|
-
tor nodes URI = #{
|
34
|
-
result_file = #{
|
25
|
+
tor nodes URI = #{options[:nodes_list] || Tornados::NodesFetcher.default_url}
|
26
|
+
result_file = #{options[:result_file] || Tornados::FileWriter.default_result_file}
|
35
27
|
TEXT
|
36
28
|
end
|
37
29
|
|
@@ -39,18 +31,55 @@ module Tornados
|
|
39
31
|
puts "Work done. See result in #{Tornados::FileWriter.default_result_file}. Bye!"
|
40
32
|
end
|
41
33
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
34
|
+
def prepare_result
|
35
|
+
tor_exit_nodes = Tornados::NodesFetcher.call(options[:exit_nodes_uri])
|
36
|
+
geobase_file_path = Tornados::MaxDbFetcher.call(options[:max_mind_key] || ENV["GEO_API_DATABASE_LICENSE_KEY"])
|
37
|
+
enriched_tor_exit_nodes = Tornados::GeoEnrich.call(tor_exit_nodes, geobase_file_path, filter)
|
38
|
+
csv_enriched_tor_exit_nodes = Tornados::CsvFormater.call(enriched_tor_exit_nodes)
|
39
|
+
Tornados::FileWriter.call(csv_enriched_tor_exit_nodes, options[:result_file])
|
46
40
|
end
|
41
|
+
|
42
|
+
def filter
|
43
|
+
return nil unless options[:included_iso_codes]
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
45
|
+
l = -> (checked_value) { options[:included_iso_codes].include?(checked_value) }
|
46
|
+
Tornados::Filter.new(l)
|
47
|
+
end
|
48
|
+
|
49
|
+
def prepare_options
|
50
|
+
@options = {}
|
51
|
+
optparse = OptionParser.new do |opts|
|
52
|
+
opts.banner = usage_example_message
|
53
|
+
|
54
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
55
|
+
puts opts
|
56
|
+
exit
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on("-u", "--uri <URI>", "Uri with tor exit nodes list") do |v|
|
60
|
+
@options[:exit_nodes_uri] = v
|
61
|
+
end
|
62
|
+
|
63
|
+
opts.on("-f", "--file <file>", "Result file with path") do |v|
|
64
|
+
@options[:result_file] = v
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on("-k", "--key <file>", "MaxMind API key") do |v|
|
68
|
+
puts 111
|
69
|
+
puts ENV["GEO_API_DATABASE_LICENSE_KEY"]
|
70
|
+
@options[:max_mind_key] = v
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on("-i", "--include <ISO code1, ISO codeN>", "Include only ip with this iso codes") do |v|
|
74
|
+
@options[:included_iso_codes] = v.split(",").map(&:strip)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
optparse.parse!
|
79
|
+
end
|
80
|
+
|
81
|
+
def usage_example_message
|
82
|
+
"GEO_API_KEY=key tornado -u <exit nodes uri> -f <result file> -i <ip country iso codes>"
|
54
83
|
end
|
55
84
|
end
|
56
85
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tornados
|
4
|
+
class Filter
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :condition
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
def initialize(lambda)
|
12
|
+
@condition = lambda
|
13
|
+
end
|
14
|
+
|
15
|
+
def accept?(checked_value)
|
16
|
+
condition.call(checked_value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/tornados/geo_enrich.rb
CHANGED
@@ -6,26 +6,33 @@ module Tornados
|
|
6
6
|
class GeoEnrich < Service
|
7
7
|
private
|
8
8
|
|
9
|
-
attr_reader :ip_list, :reader
|
9
|
+
attr_reader :ip_list, :filter, :reader
|
10
10
|
|
11
11
|
public
|
12
12
|
|
13
|
-
def initialize(ip_list, max_db_file_path)
|
14
|
-
|
15
|
-
|
13
|
+
def initialize(ip_list, max_db_file_path, filter = nil)
|
14
|
+
@filter = filter
|
15
|
+
@ip_list = ip_list
|
16
|
+
@reader = MaxMind::GeoIP2::Reader.new(database: max_db_file_path)
|
16
17
|
end
|
17
18
|
|
18
19
|
private
|
19
20
|
|
20
21
|
def execute
|
21
|
-
|
22
|
-
|
22
|
+
ip_list.each_with_object([]) do |arr, result|
|
23
|
+
ip = arr.first
|
24
|
+
iso_code, name = *country_code_by_ip(ip)
|
25
|
+
if filter
|
26
|
+
result << [ip, iso_code, name] if filter.accept?(iso_code)
|
27
|
+
else
|
28
|
+
result << [ip, iso_code, name]
|
23
29
|
end
|
30
|
+
end
|
24
31
|
end
|
25
32
|
|
26
33
|
def country_code_by_ip(ip)
|
27
|
-
|
28
|
-
|
34
|
+
record = reader.country(ip)
|
35
|
+
[record.country.iso_code, record.country.name]
|
29
36
|
end
|
30
37
|
end
|
31
38
|
end
|
@@ -21,11 +21,12 @@ module Tornados
|
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
|
-
attr_accessor :max_db_file_path
|
24
|
+
attr_accessor :key, :max_db_file_path
|
25
25
|
|
26
26
|
public
|
27
27
|
|
28
|
-
def initialize(max_db_storage = nil)
|
28
|
+
def initialize(key, max_db_storage = nil)
|
29
|
+
@key = key
|
29
30
|
max_db_storage = max_db_storage || MAX_DB_STORAGE
|
30
31
|
@max_db_file_path = File.join(max_db_storage, MAX_DB_FILE_NAME)
|
31
32
|
end
|
@@ -47,9 +48,9 @@ module Tornados
|
|
47
48
|
end
|
48
49
|
|
49
50
|
def license_key_option
|
50
|
-
raise MaxDbKeyNotFoundError unless
|
51
|
+
raise MaxDbKeyNotFoundError unless key
|
51
52
|
|
52
|
-
{license_key:
|
53
|
+
{license_key: key}
|
53
54
|
end
|
54
55
|
|
55
56
|
def extract_tar_gz_file(file)
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Tornados
|
4
4
|
TOR_NODES_LIST_URI = "https://raw.githubusercontent.com"
|
5
|
-
TOR_NODES_LIST_PATH ="SecOps-Institute/Tor-IP-Addresses/master/tor-nodes.lst"
|
5
|
+
TOR_NODES_LIST_PATH = "SecOps-Institute/Tor-IP-Addresses/master/tor-exit-nodes.lst"
|
6
6
|
|
7
7
|
# Service for download exit tor nodes IP list.
|
8
8
|
# Result is array of arrays:
|
data/lib/tornados/version.rb
CHANGED
data/lib/tornados.rb
CHANGED
@@ -13,6 +13,7 @@ require_relative "tornados/file_writer"
|
|
13
13
|
require_relative "tornados/http_client"
|
14
14
|
require_relative "tornados/nodes_fetcher"
|
15
15
|
require_relative "tornados/max_db_fetcher"
|
16
|
+
require_relative "tornados/filter"
|
16
17
|
require_relative "tornados/geo_enrich"
|
17
18
|
require_relative "tornados/cli_client"
|
18
19
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tornados
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexey Slivka
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-04-
|
11
|
+
date: 2022-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -116,6 +116,7 @@ files:
|
|
116
116
|
- lib/tornados/csv_formater.rb
|
117
117
|
- lib/tornados/errors.rb
|
118
118
|
- lib/tornados/file_writer.rb
|
119
|
+
- lib/tornados/filter.rb
|
119
120
|
- lib/tornados/formater.rb
|
120
121
|
- lib/tornados/geo_enrich.rb
|
121
122
|
- lib/tornados/http_client.rb
|