rogue_one 0.4.1 → 0.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a66b70adea810f6e952e08294a0323dc2be06c23d7ccbc28739045829696aae5
4
- data.tar.gz: 5d41ff1fa13254071aecef1cbf70168d818a963207922be4d44f134d9bb42f0d
3
+ metadata.gz: 36b1d9ea6171500c42fd1930ba0807e74d8df4908fdec5eb47f1b88b0262caf6
4
+ data.tar.gz: 3836ad7bc6a13b68e1fa07d5d584ccbe0da64c8a4c1ee31e16d8f6e5037ada7f
5
5
  SHA512:
6
- metadata.gz: c08f2049c42ac79a9a0256ae2f99761748660fa3bd1981f680196540e4525db9b4e8dbba54264d35cc2b7b5773b96441886a0a7acb4900e1626cd42c34089304
7
- data.tar.gz: a4cffb3b9d5c92f90ac267201417c459b334d38aa82a0631a43c7db15552bed00d11cc9f37291904f48bfad08c33f4bc7d051bf3946acf4c35fcdc9a7e927567
6
+ metadata.gz: 8659b118ceaf22a6ec4756d4f883f8bda633ddf1230aab126c2666ad967df887dd7b1fed576b2f3608ed0adefea695067030ed079b3a915af8c06b1398bd2bd0
7
+ data.tar.gz: 3c6debab123e645b9765627dda48bc5c2674ee9101f53da0c8bb967a72d54cea411213cc6b6d2354263f1034b73d75282058872779f75a1ac07ec3e5bb77a63d
data/README.md CHANGED
@@ -39,16 +39,16 @@ Usage:
39
39
  rogue_one report [DNS_SERVER]
40
40
 
41
41
  Options:
42
+ [--custom-list=CUSTOM_LIST] # A path to a custom list of domains
42
43
  [--default-list=DEFAULT_LIST] # A default list of top 100 domains (Alexa or Fortune)
43
44
  # Default: alexa
44
- [--custom-list=CUSTOM_LIST] # A path to a custom list of domains
45
+ [--record-type=RECORD_TYPE] # A type of the DNS resource to check
46
+ # Default: A
45
47
  [--threshold=N] # Threshold value for determining malicious or not
46
48
  [--verbose], [--no-verbose]
47
49
 
48
50
  Show a report of a given DNS server
49
51
 
50
- Show a report of a given DNS server
51
-
52
52
  $ rogue_one report 1.1.1.1
53
53
  {
54
54
  "verdict": "benign one",
@@ -4,7 +4,6 @@ require "rogue_one/version"
4
4
 
5
5
  require "rogue_one/domain_list"
6
6
 
7
- require "rogue_one/resolver"
8
7
  require "rogue_one/detector"
9
8
  require "rogue_one/ping"
10
9
  require "rogue_one/cli"
@@ -5,20 +5,36 @@ require "json"
5
5
 
6
6
  module RogueOne
7
7
  class CLI < Thor
8
+ class << self
9
+ def exit_on_failure?
10
+ true
11
+ end
12
+ end
13
+
8
14
  desc "report [DNS_SERVER]", "Show a report of a given DNS server"
9
- method_option :default_list, type: :string, default: "alexa", desc: "A default list of top 100 domains (Alexa or Fortune)"
10
15
  method_option :custom_list, type: :string, desc: "A path to a custom list of domains"
16
+ method_option :default_list, type: :string, default: "alexa", desc: "A default list of top 100 domains (Alexa or Fortune)"
17
+ method_option :record_type, type: :string, default: "A", desc: "A type of the DNS resource to check"
11
18
  method_option :threshold, type: :numeric, desc: "Threshold value for determining malicious or not"
12
19
  method_option :verbose, type: :boolean
13
20
  def report(dns_server)
14
21
  with_error_handling do
15
22
  Ping.pong? dns_server
16
23
 
17
- default_list = options["default_list"].downcase
18
24
  custom_list = options["custom_list"]
25
+ default_list = options["default_list"].downcase
26
+ record_type = options["record_type"].upcase
19
27
  threshold = options["threshold"]
20
28
  verbose = options["verbose"]
21
- detector = Detector.new(target: dns_server, default_list: default_list, custom_list: custom_list, threshold: threshold, verbose: verbose)
29
+
30
+ detector = Detector.new(
31
+ custom_list: custom_list,
32
+ default_list: default_list,
33
+ record_type: record_type,
34
+ target: dns_server,
35
+ threshold: threshold,
36
+ verbose: verbose,
37
+ )
22
38
  puts JSON.pretty_generate(detector.report)
23
39
  end
24
40
  end
@@ -11,18 +11,26 @@ require "etc"
11
11
 
12
12
  module RogueOne
13
13
  class Detector
14
- attr_reader :target
15
- attr_reader :default_list
16
14
  attr_reader :custom_list
17
- attr_reader :verbose
15
+ attr_reader :default_list
18
16
  attr_reader :max_concurrency
17
+ attr_reader :record_type
18
+ attr_reader :target
19
+ attr_reader :verbose
19
20
 
20
21
  GOOGLE_PUBLIC_DNS = "8.8.8.8"
21
22
 
22
- def initialize(target:, default_list: "alexa", custom_list: nil, threshold: nil, verbose: false)
23
+ def initialize(target:,
24
+ custom_list: nil,
25
+ default_list: "alexa",
26
+ record_type: "A",
27
+ threshold: nil,
28
+ verbose: false)
23
29
  @target = target
24
- @default_list = default_list
30
+
25
31
  @custom_list = custom_list
32
+ @default_list = default_list
33
+ @record_type = record_type.upcase.to_sym
26
34
  @threshold = threshold
27
35
  @verbose = verbose
28
36
 
@@ -59,7 +67,10 @@ module RogueOne
59
67
  def meta
60
68
  return nil unless verbose
61
69
 
62
- { threshold: threshold }
70
+ {
71
+ record_type: record_type,
72
+ threshold: threshold,
73
+ }
63
74
  end
64
75
 
65
76
  def landing_pages
@@ -89,13 +100,13 @@ module RogueOne
89
100
  return unless @memo.empty?
90
101
 
91
102
  # read domains outside of the async blocks
92
- domains
103
+ load_domains
93
104
 
94
- normal = bulk_resolve(normal_resolver, domains)
105
+ normal_resolutions = bulk_resolve(normal_resolver, domains)
95
106
  resolutions = bulk_resolve(target_resolver, domains)
96
107
 
97
108
  results = resolutions.map do |domain, addresses|
98
- normal_addresses = normal.dig(domain) || []
109
+ normal_addresses = normal_resolutions.dig(domain) || []
99
110
  address = (addresses || []).first
100
111
  [domain, address] if address && !normal_addresses.include?(address)
101
112
  end.compact.to_h
@@ -104,6 +115,10 @@ module RogueOne
104
115
  @verbose_memo = results if verbose
105
116
  end
106
117
 
118
+ def load_domains
119
+ domains
120
+ end
121
+
107
122
  def domains
108
123
  @domains ||= custom_list ? custom_domains : top_100_domains
109
124
  end
@@ -131,6 +146,7 @@ module RogueOne
131
146
 
132
147
  def bulk_resolve(resolver, domains)
133
148
  results = []
149
+
134
150
  Async do
135
151
  barrier = Async::Barrier.new
136
152
  semaphore = Async::Semaphore.new(max_concurrency, parent: barrier)
@@ -139,7 +155,7 @@ module RogueOne
139
155
  semaphore.async do
140
156
  addresses = []
141
157
  begin
142
- addresses = resolver.addresses_for(domain, Resolv::DNS::Resource::IN::A, { retries: 1 }).map(&:to_s)
158
+ addresses = resolver.addresses_for(domain, dns_resource_by_record_type, { retries: 1 }).map(&:to_s)
143
159
  rescue Async::DNS::ResolutionFailure
144
160
  # do nothing
145
161
  end
@@ -157,5 +173,16 @@ module RogueOne
157
173
  def target_resolver
158
174
  Async::DNS::Resolver.new([[:udp, target, 53], [:tcp, target, 53]])
159
175
  end
176
+
177
+ def dns_resource_by_record_type
178
+ @dns_resource_by_record_type ||= dns_resources.dig(record_type)
179
+ end
180
+
181
+ def dns_resources
182
+ {
183
+ A: Resolv::DNS::Resource::IN::A,
184
+ AAAA: Resolv::DNS::Resource::IN::AAAA,
185
+ }
186
+ end
160
187
  end
161
188
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RogueOne
4
- VERSION = "0.4.1"
4
+ VERSION = "0.4.2"
5
5
  end
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": [
3
+ "config:base"
4
+ ]
5
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rogue_one
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manabu Niseki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-29 00:00:00.000000000 Z
11
+ date: 2020-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -120,8 +120,8 @@ files:
120
120
  - lib/rogue_one/detector.rb
121
121
  - lib/rogue_one/domain_list.rb
122
122
  - lib/rogue_one/ping.rb
123
- - lib/rogue_one/resolver.rb
124
123
  - lib/rogue_one/version.rb
124
+ - renovate.json
125
125
  - rogue_one.gemspec
126
126
  homepage: https://github.com/ninoseki/rogue_one
127
127
  licenses:
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "resolv"
4
-
5
- module RogueOne
6
- class Resolver
7
- attr_reader :nameserver
8
-
9
- def initialize(nameserver:)
10
- @nameserver = nameserver
11
- end
12
-
13
- def get_resource(domain, type)
14
- _resolver.getresource(domain, resource_by_type(type)).address.to_s
15
- rescue Resolv::ResolvError => _e
16
- nil
17
- end
18
-
19
- def get_resources(domain, type)
20
- _resolver.getresources(domain, resource_by_type(type)).map { |r| r.address.to_s }
21
- rescue Resolv::ResolvError => _e
22
- nil
23
- end
24
-
25
- private
26
-
27
- def _resolver
28
- @_resolver ||= Resolv::DNS.new(nameserver: [nameserver])
29
- @_resolver.timeouts = 5
30
- @_resolver
31
- end
32
-
33
- def resource_by_type(type)
34
- resources.dig(type.upcase.to_sym)
35
- end
36
-
37
- def resources
38
- {
39
- ANY: Resolv::DNS::Resource::IN::ANY,
40
- NS: Resolv::DNS::Resource::IN::NS,
41
- CNAME: Resolv::DNS::Resource::IN::CNAME,
42
- SOA: Resolv::DNS::Resource::IN::SOA,
43
- HINFO: Resolv::DNS::Resource::IN::HINFO,
44
- MINFO: Resolv::DNS::Resource::IN::MINFO,
45
- MX: Resolv::DNS::Resource::IN::MX,
46
- TXT: Resolv::DNS::Resource::IN::TXT,
47
- A: Resolv::DNS::Resource::IN::A,
48
- WKS: Resolv::DNS::Resource::IN::WKS,
49
- PTR: Resolv::DNS::Resource::IN::PTR,
50
- AAAA: Resolv::DNS::Resource::IN::AAAA,
51
- SRV: Resolv::DNS::Resource::IN::SRV,
52
- }
53
- end
54
- end
55
- end