rogue_one 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5655a9f8e6b835c1ae68a9f10dd449ac4558a9efc582a2e8a8292f60f33a5c78
4
- data.tar.gz: f7c38f1d2eacdebf14f2aa9dfb89c99460a3c9ceaf4c707f63b38f0423933123
3
+ metadata.gz: a66b70adea810f6e952e08294a0323dc2be06c23d7ccbc28739045829696aae5
4
+ data.tar.gz: 5d41ff1fa13254071aecef1cbf70168d818a963207922be4d44f134d9bb42f0d
5
5
  SHA512:
6
- metadata.gz: 04fe47430be7c6a7bf2211620516a4dff785d8bcb61ca378b9c382e2d1eb1c3f3babed665345e23ab0a023b8201d073e567a554393f7af61272179dab6e0be63
7
- data.tar.gz: 698b1433133c836c10df144c65fd5e98663e48f8be07f6082960f8bc29eec74315a2e8b807dde47be5fdb8e42480d47e8ea30d21e2f01afbad7653ee6ac18895
6
+ metadata.gz: c08f2049c42ac79a9a0256ae2f99761748660fa3bd1981f680196540e4525db9b4e8dbba54264d35cc2b7b5773b96441886a0a7acb4900e1626cd42c34089304
7
+ data.tar.gz: a4cffb3b9d5c92f90ac267201417c459b334d38aa82a0631a43c7db15552bed00d11cc9f37291904f48bfad08c33f4bc7d051bf3946acf4c35fcdc9a7e927567
@@ -4,4 +4,5 @@ language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
6
  - 2.6
7
+ - 2.7
7
8
  before_install: gem install bundler -v 2.1
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Rogue one
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rogue_one.svg)](https://badge.fury.io/rb/rogue_one)
4
- [![Build Status](https://travis-ci.org/ninoseki/rogue_one.svg?branch=master)](https://travis-ci.org/ninoseki/rogue_one)
4
+ [![Build Status](https://travis-ci.com/ninoseki/rogue_one.svg?branch=master)](https://travis-ci.com/ninoseki/rogue_one)
5
5
  [![CodeFactor](https://www.codefactor.io/repository/github/ninoseki/rogue_one/badge)](https://www.codefactor.io/repository/github/ninoseki/rogue_one)
6
6
  [![Coverage Status](https://coveralls.io/repos/github/ninoseki/rogue_one/badge.svg?branch=master)](https://coveralls.io/github/ninoseki/rogue_one?branch=master)
7
7
 
@@ -79,7 +79,7 @@ $ rogue_one report 171.244.3.111 --custom-list tmp/roaming.yml
79
79
  ```
80
80
 
81
81
  | Key | Desc. |
82
- | ------------- | ------------------------------------------------------------------------ |
82
+ |---------------|--------------------------------------------------------------------------|
83
83
  | verdict | A detection result (`rogue one` or `benign one`) |
84
84
  | landing_pages | An array of IP of landing pages |
85
85
  | results | DNS resolution results (only available if --verbose option is specified) |
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "async"
4
+ require "async/barrier"
5
+ require "async/dns"
6
+ require "async/reactor"
7
+ require "async/semaphore"
8
+ require "resolv"
3
9
  require "yaml"
4
- require "parallel"
10
+ require "etc"
5
11
 
6
12
  module RogueOne
7
13
  class Detector
@@ -9,6 +15,7 @@ module RogueOne
9
15
  attr_reader :default_list
10
16
  attr_reader :custom_list
11
17
  attr_reader :verbose
18
+ attr_reader :max_concurrency
12
19
 
13
20
  GOOGLE_PUBLIC_DNS = "8.8.8.8"
14
21
 
@@ -19,6 +26,7 @@ module RogueOne
19
26
  @threshold = threshold
20
27
  @verbose = verbose
21
28
 
29
+ @max_concurrency = Etc.nprocessors * 2
22
30
  @memo = {}
23
31
  @verbose_memo = nil
24
32
  end
@@ -80,11 +88,16 @@ module RogueOne
80
88
  def inspect
81
89
  return unless @memo.empty?
82
90
 
83
- results = Parallel.map(domains) do |domain|
84
- normal_results = normal_resolver.get_resources(domain, "A")
85
- target_result = target_resolver.get_resource(domain, "A")
91
+ # read domains outside of the async blocks
92
+ domains
86
93
 
87
- [domain, target_result] if target_result && !normal_results.include?(target_result)
94
+ normal = bulk_resolve(normal_resolver, domains)
95
+ resolutions = bulk_resolve(target_resolver, domains)
96
+
97
+ results = resolutions.map do |domain, addresses|
98
+ normal_addresses = normal.dig(domain) || []
99
+ address = (addresses || []).first
100
+ [domain, address] if address && !normal_addresses.include?(address)
88
101
  end.compact.to_h
89
102
 
90
103
  @memo = results.values.group_by(&:itself).map { |k, v| [k, v.length] }.to_h
@@ -92,7 +105,7 @@ module RogueOne
92
105
  end
93
106
 
94
107
  def domains
95
- @domains ||= custom_domains || top_100_domains
108
+ @domains ||= custom_list ? custom_domains : top_100_domains
96
109
  end
97
110
 
98
111
  def custom_domains
@@ -105,22 +118,44 @@ module RogueOne
105
118
  read_domains File.expand_path("./data/alexa_100.yml", __dir__)
106
119
  when "fortune"
107
120
  read_domains File.expand_path("./data/fortune_100.yml", __dir__)
108
- else
109
- raise ArgumentError, "A list for #{default_list} is not existing"
110
121
  end
111
122
  end
112
123
 
113
124
  def read_domains(path)
114
125
  list = DomainList.new(path)
115
- list.valid? ? list.domains : nil
126
+ return list.domains if list.valid?
127
+
128
+ raise ArgumentError, "Inputted an invalid list. #{path} is not eixst." unless list.exists?
129
+ raise ArgumentError, "Inputted an invalid list. Please input a list as an YAML file." unless list.valid_format?
130
+ end
131
+
132
+ def bulk_resolve(resolver, domains)
133
+ results = []
134
+ Async do
135
+ barrier = Async::Barrier.new
136
+ semaphore = Async::Semaphore.new(max_concurrency, parent: barrier)
137
+
138
+ domains.each do |domain|
139
+ semaphore.async do
140
+ addresses = []
141
+ begin
142
+ addresses = resolver.addresses_for(domain, Resolv::DNS::Resource::IN::A, { retries: 1 }).map(&:to_s)
143
+ rescue Async::DNS::ResolutionFailure
144
+ # do nothing
145
+ end
146
+ results << [domain, addresses]
147
+ end
148
+ end
149
+ end
150
+ results.to_h
116
151
  end
117
152
 
118
153
  def normal_resolver
119
- @normal_resolver ||= Resolver.new(nameserver: GOOGLE_PUBLIC_DNS)
154
+ Async::DNS::Resolver.new([[:udp, GOOGLE_PUBLIC_DNS, 53], [:tcp, GOOGLE_PUBLIC_DNS, 53]])
120
155
  end
121
156
 
122
157
  def target_resolver
123
- @target_resolver ||= Resolver.new(nameserver: target)
158
+ Async::DNS::Resolver.new([[:udp, target, 53], [:tcp, target, 53]])
124
159
  end
125
160
  end
126
161
  end
@@ -18,8 +18,6 @@ module RogueOne
18
18
  @domains ||= exists? ? YAML.safe_load(File.read(path)) : nil
19
19
  end
20
20
 
21
- private
22
-
23
21
  def exists?
24
22
  File.exist?(path)
25
23
  end
@@ -1,16 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "resolv"
4
+
3
5
  module RogueOne
4
6
  class Ping
5
7
  attr_reader :resolver
8
+ attr_reader :nameserver
6
9
 
7
10
  def initialize(nameserver)
8
- @resolver = Resolver.new(nameserver: nameserver)
11
+ @nameserver = nameserver
12
+ @resolver = Resolv::DNS.new(nameserver: [nameserver])
13
+ @resolver.timeouts = 5
14
+ end
15
+
16
+ def get_a_record
17
+ resolver.getresource("example.com", Resolv::DNS::Resource::IN::A)
18
+ rescue Resolv::ResolvError => _e
19
+ nil
9
20
  end
10
21
 
11
22
  def pong?
12
- result = resolver.get_resource("example.com", "A")
13
- raise Error, "DNS resolve error: there is no resopnse from #{resolver.nameserver}" unless result
23
+ result = get_a_record
24
+ raise Error, "DNS resolve error: there is no resopnse from #{nameserver}" unless result
14
25
 
15
26
  true
16
27
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RogueOne
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.1"
5
5
  end
@@ -29,6 +29,6 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency "rake", "~> 13.0"
30
30
  spec.add_development_dependency "rspec", "~> 3.9"
31
31
 
32
- spec.add_dependency "parallel", "~> 1.19"
32
+ spec.add_dependency "async-dns", "~> 1.2"
33
33
  spec.add_dependency "thor", "~> 1.0"
34
34
  end
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.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manabu Niseki
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-19 00:00:00.000000000 Z
11
+ date: 2020-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,19 +67,19 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.9'
69
69
  - !ruby/object:Gem::Dependency
70
- name: parallel
70
+ name: async-dns
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.19'
75
+ version: '1.2'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.19'
82
+ version: '1.2'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: thor
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -127,7 +127,7 @@ homepage: https://github.com/ninoseki/rogue_one
127
127
  licenses:
128
128
  - MIT
129
129
  metadata: {}
130
- post_install_message:
130
+ post_install_message:
131
131
  rdoc_options: []
132
132
  require_paths:
133
133
  - lib
@@ -142,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
142
  - !ruby/object:Gem::Version
143
143
  version: '0'
144
144
  requirements: []
145
- rubygems_version: 3.0.3
146
- signing_key:
145
+ rubygems_version: 3.1.2
146
+ signing_key:
147
147
  specification_version: 4
148
148
  summary: A rogue DNS detector
149
149
  test_files: []