dns-sniper 0.0.1.pre4 → 0.0.1.pre5
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/bin/dns-sniper +14 -17
- data/dns-sniper.gemspec +2 -2
- data/lib/dns-sniper.rb +7 -2
- data/lib/dns-sniper/{formatter.rb → exporter.rb} +5 -3
- data/lib/dns-sniper/exporters.rb +30 -0
- data/lib/dns-sniper/{formatters/bind8.rb → exporters/bind8_exporter.rb} +1 -6
- data/lib/dns-sniper/{formatters/dnsmasq.rb → exporters/dnsmasq_exporter.rb} +2 -7
- data/lib/dns-sniper/{formatters/hosts.rb → exporters/hosts_exporter.rb} +2 -7
- data/lib/dns-sniper/{formatters/netgear.rb → exporters/netgear_exporter.rb} +2 -7
- data/lib/dns-sniper/exporters/text_exporter.rb +9 -0
- data/lib/dns-sniper/{formatters/unbound.rb → exporters/unbound_exporter.rb} +2 -7
- data/lib/dns-sniper/hostnames.rb +14 -138
- data/lib/dns-sniper/importer.rb +53 -0
- data/lib/dns-sniper/importers.rb +27 -0
- data/lib/dns-sniper/importers/configuration_importer.rb +38 -0
- data/lib/dns-sniper/importers/domains_importer.rb +22 -0
- data/lib/dns-sniper/importers/hosts_importer.rb +26 -0
- metadata +15 -10
- data/lib/dns-sniper/formatters.rb +0 -30
- data/lib/dns-sniper/formatters/text.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61bc06052722d5ac53448692a1c4cfb8e52a86ebe41fe2ef3973b5f36a0ff1da
|
4
|
+
data.tar.gz: '058667f512cdaa447c377325a0cc17df712f05c0d1aac2d82c09337f1faa2b3b'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2ab89c5edd6fa0ee2be7fee4078859ee15b4af1f8598ea12cc4925103d6155d0ddc1d2da313ada9b055635ec76dcf5c6cab1a2be3d3a1a45e6bd12f2fcb53f2
|
7
|
+
data.tar.gz: 05d1dc924c958d1172da20cce2795498c60c33278db0738fbf0b1bed4539b28ab291a8f6fd7aa3b64db010b3ffa1a7f58ee872cb936705114e4c7819b43ae225
|
data/bin/dns-sniper
CHANGED
@@ -5,19 +5,16 @@ require 'optparse'
|
|
5
5
|
require 'set'
|
6
6
|
require 'dns-sniper'
|
7
7
|
|
8
|
-
VALID_FORMATS = DNSSniper::
|
9
|
-
Options = Struct.new(:
|
8
|
+
VALID_FORMATS = DNSSniper::Exporters.all.inject([]) { |arr, f| arr << f.name.to_s.sub('DNSSniper::', '').sub('Exporter', '').downcase }
|
9
|
+
Options = Struct.new(:conf_path, :format)
|
10
10
|
|
11
11
|
class Parser
|
12
12
|
def self.parse(options)
|
13
13
|
args = Options.new('world')
|
14
14
|
opt_parser = OptionParser.new do |opts|
|
15
15
|
opts.banner = "Usage: #{File.basename(__FILE__)} -f PATH -o FORMAT [options]\n#{File.basename(__FILE__)} combines online DNS blacklists and combines them into the desired configuration FORMAT.\n\n"
|
16
|
-
opts.on('-
|
17
|
-
args.
|
18
|
-
end
|
19
|
-
opts.on('-w', '--whitelist=path', 'Path to file with line-separated list of whitelisted hostnames') do |path|
|
20
|
-
args.whitelisted_hosts_file = path
|
16
|
+
opts.on('-c', '--conf=PATH', 'PATH to YAML configuration file') do |path|
|
17
|
+
args.conf_path = path
|
21
18
|
end
|
22
19
|
opts.on('-o', '--output=FORMAT', "FORMAT to output — one of #{VALID_FORMATS.join(', ')}") do |format|
|
23
20
|
args.format = format
|
@@ -34,20 +31,20 @@ end
|
|
34
31
|
|
35
32
|
options = Parser.parse ARGV
|
36
33
|
|
37
|
-
unless
|
38
|
-
warn
|
34
|
+
unless File.exist?(options[:conf_path])
|
35
|
+
warn "Error: Unable to access ”#{options[:conf_path]}”"
|
39
36
|
exit(-1)
|
40
37
|
end
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
if options[:whitelisted_hosts_file] && !File.exist?(options[:whitelisted_hosts_file])
|
48
|
-
warn "Error: Unable to access ”#{options[:whitelisted_hosts_file]}”"
|
39
|
+
exporter = DNSSniper.const_get("#{options[:format].to_s.split('_').map(&:capitalize).join}Exporter")
|
40
|
+
if !exporter
|
41
|
+
warn "Error: Invalid format #{options[:format]}"
|
49
42
|
exit(-1)
|
50
43
|
end
|
51
44
|
|
52
45
|
hostnames = DNSSniper::Hostnames.new
|
53
|
-
|
46
|
+
hostnames.blacklist += DNSSniper::ConfigurationImporter.new(options[:conf_path], list: :reject).hostnames
|
47
|
+
hostnames.whitelist += DNSSniper::ConfigurationImporter.new(options[:conf_path], list: :allow).hostnames
|
48
|
+
|
49
|
+
exporter = exporter.new(hostnames.blocklist)
|
50
|
+
puts exporter.data
|
data/dns-sniper.gemspec
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'dns-sniper'
|
5
5
|
spec.license = 'MIT'
|
6
|
-
spec.version = '0.0.1.
|
7
|
-
spec.date = '2020-11-
|
6
|
+
spec.version = '0.0.1.pre5'
|
7
|
+
spec.date = '2020-11-10'
|
8
8
|
|
9
9
|
spec.authors = ['Brody Hoskins']
|
10
10
|
spec.email = ['brody@brody.digital']
|
data/lib/dns-sniper.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'resolv'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
require 'dns-sniper/exporter'
|
7
|
+
require 'dns-sniper/exporters'
|
3
8
|
require 'dns-sniper/hostnames'
|
4
|
-
require 'dns-sniper/
|
5
|
-
require 'dns-sniper/
|
9
|
+
require 'dns-sniper/importer'
|
10
|
+
require 'dns-sniper/importers'
|
@@ -1,13 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DNSSniper
|
4
|
-
class
|
4
|
+
class Exporter
|
5
|
+
attr_accessor :data, :hostnames
|
6
|
+
|
5
7
|
def initialize(hostnames, options = {})
|
6
8
|
@hostnames = hostnames
|
7
|
-
@
|
9
|
+
@data = output(options)
|
8
10
|
end
|
9
11
|
|
10
|
-
def output
|
12
|
+
def output(*)
|
11
13
|
raise NotImplementedError, "Error: #output isn’t supported by #{self.class.name}"
|
12
14
|
end
|
13
15
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DNSSniper
|
4
|
+
module Exporters
|
5
|
+
module_function
|
6
|
+
|
7
|
+
attr_reader :registered
|
8
|
+
@registered = []
|
9
|
+
|
10
|
+
def register(class_name, autoload_require)
|
11
|
+
DNSSniper.autoload(class_name, autoload_require)
|
12
|
+
@registered << class_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def all
|
16
|
+
@registered.map { |name| DNSSniper.const_get(name) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def find(name)
|
20
|
+
all.find { |c| c.name.downcase == name.to_s.downcase } or raise NameError, "Unknown exporter \"#{name}\""
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
DNSSniper::Exporters.register :Bind8Exporter, 'dns-sniper/exporters/bind8_exporter'
|
26
|
+
DNSSniper::Exporters.register :DnsmasqExporter, 'dns-sniper/exporters/dnsmasq_exporter'
|
27
|
+
DNSSniper::Exporters.register :HostsExporter, 'dns-sniper/exporters/hosts_exporter'
|
28
|
+
DNSSniper::Exporters.register :NetgearExporter, 'dns-sniper/exporters/netgear_exporter'
|
29
|
+
DNSSniper::Exporters.register :TextExporter, 'dns-sniper/exporters/text_exporter'
|
30
|
+
DNSSniper::Exporters.register :UnboundExporter, 'dns-sniper/exporters/unbound_exporter'
|
@@ -1,12 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DNSSniper
|
4
|
-
class
|
5
|
-
def initialize(hostnames, options = {})
|
6
|
-
@hostnames = hostnames
|
7
|
-
@options = options
|
8
|
-
end
|
9
|
-
|
4
|
+
class Bind8Exporter < Exporter
|
10
5
|
def output(options = {})
|
11
6
|
raise ArgumentError, 'zone_file is required' unless defined?(options[:zone_file])
|
12
7
|
|
@@ -1,13 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DNSSniper
|
4
|
-
class
|
5
|
-
def
|
6
|
-
@hostnames = hostnames
|
7
|
-
@options = options
|
8
|
-
end
|
9
|
-
|
10
|
-
def output(_options = {})
|
4
|
+
class DnsmasqExporter < Exporter
|
5
|
+
def output(*)
|
11
6
|
str = ''.dup
|
12
7
|
@hostnames.each do |hostname|
|
13
8
|
str << "server=/#{hostname}/#{$/}"
|
@@ -1,13 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DNSSniper
|
4
|
-
class
|
5
|
-
def
|
6
|
-
@hostnames = hostnames
|
7
|
-
@options = options
|
8
|
-
end
|
9
|
-
|
10
|
-
def output(_options = {})
|
4
|
+
class HostsExporter < Exporter
|
5
|
+
def output(*)
|
11
6
|
str = ''.dup
|
12
7
|
@hostnames.each do |hostname|
|
13
8
|
str << "127.0.0.1\t#{hostname}#{$/}"
|
@@ -1,13 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DNSSniper
|
4
|
-
class
|
5
|
-
def
|
6
|
-
@hostnames = hostnames
|
7
|
-
@options = options
|
8
|
-
end
|
9
|
-
|
10
|
-
def output(_options = {})
|
4
|
+
class NetgearExporter < Exporter
|
5
|
+
def output(*)
|
11
6
|
str = ''.dup
|
12
7
|
@hostnames.each_with_index do |hostname, i|
|
13
8
|
str << "[517003_e]: #{i + 1}) #{hostname}\n"
|
@@ -1,13 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DNSSniper
|
4
|
-
class
|
5
|
-
def
|
6
|
-
@hostnames = hostnames
|
7
|
-
@options = options
|
8
|
-
end
|
9
|
-
|
10
|
-
def output(_options = {})
|
4
|
+
class UnboundExporter < Exporter
|
5
|
+
def output(*)
|
11
6
|
str = ''.dup
|
12
7
|
str << "server:#{$/}"
|
13
8
|
@hostnames.each do |hostname|
|
data/lib/dns-sniper/hostnames.rb
CHANGED
@@ -7,152 +7,28 @@ require 'resolv'
|
|
7
7
|
|
8
8
|
module DNSSniper
|
9
9
|
class Hostnames
|
10
|
-
|
11
|
-
|
12
|
-
self
|
13
|
-
end
|
10
|
+
attr_accessor :blacklist
|
11
|
+
attr_accessor :whitelist
|
14
12
|
|
15
|
-
def
|
16
|
-
|
17
|
-
@
|
13
|
+
def initialize
|
14
|
+
@blacklist = [].to_set
|
15
|
+
@whitelist = [].to_set
|
18
16
|
self
|
19
17
|
end
|
20
18
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
paths_or_urls = [paths_or_urls] if paths_or_urls.class == String
|
25
|
-
|
26
|
-
paths_or_urls.each do |path_or_url|
|
27
|
-
path_or_url.chomp!
|
28
|
-
|
29
|
-
if File.exist?(path_or_url)
|
30
|
-
contents = File.open(path_or_url).readlines(chomp: true)
|
31
|
-
else
|
32
|
-
begin
|
33
|
-
down = Down.download(path_or_url)
|
34
|
-
path_or_url = down.path
|
35
|
-
contents = down.readlines(chomp: true)
|
36
|
-
rescue Down::InvalidUrl
|
37
|
-
warn "\"#{path_or_url}\" does not exist, nor is it a valid URL"
|
38
|
-
rescue Down::NotFound
|
39
|
-
warn "\"#{path_or_url}\" does not exist"
|
40
|
-
return self
|
41
|
-
rescue Down::ResponseError
|
42
|
-
warn "\"#{path_or_url}\": No data from server"
|
43
|
-
return self
|
44
|
-
end
|
45
|
-
end
|
19
|
+
def blocklist
|
20
|
+
blacklist = @blacklist
|
21
|
+
whitelist = @whitelist
|
46
22
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
add from_hosts_file(path_or_url)
|
53
|
-
when 'hostnames'
|
54
|
-
add from_hostnames_file(contents)
|
23
|
+
whitelist.each do |domain|
|
24
|
+
domain_parts = domain.split('.')
|
25
|
+
domain_parts.count.times do |count|
|
26
|
+
next if count == 1
|
27
|
+
whitelist += [domain_parts[count - 1, domain_parts.length].join('.')]
|
55
28
|
end
|
56
29
|
end
|
57
30
|
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
def remove(hostnames)
|
62
|
-
hostnames = clean(hostnames.class == String ? [hostnames] : hostnames)
|
63
|
-
@hostnames -= hostnames unless hostnames.empty?
|
64
|
-
self
|
65
|
-
end
|
66
|
-
|
67
|
-
def remove_from(paths_or_urls)
|
68
|
-
return self unless paths_or_urls
|
69
|
-
|
70
|
-
paths_or_urls = [paths_or_urls] if paths_or_urls.class == String
|
71
|
-
|
72
|
-
paths_or_urls.each do |path_or_url|
|
73
|
-
path_or_url = path_or_url.strip
|
74
|
-
|
75
|
-
if File.exist?(path_or_url)
|
76
|
-
contents = File.open(path_or_url).readlines
|
77
|
-
else
|
78
|
-
begin
|
79
|
-
down = Down.download(path_or_url)
|
80
|
-
path_or_url = down.path
|
81
|
-
contents = down.readlines
|
82
|
-
rescue Down::NotFound
|
83
|
-
warn "\"#{path_or_url}\" does not exist"
|
84
|
-
return self
|
85
|
-
rescue Down::ResponseError
|
86
|
-
warn "\"#{path_or_url}\": No data from server"
|
87
|
-
return self
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
case syntax(path_or_url, contents)
|
92
|
-
when nil
|
93
|
-
warn "Error: Syntax: Syntax of \"#{path_or_url}\" not recognized, ignored"
|
94
|
-
return self
|
95
|
-
when 'hosts'
|
96
|
-
remove from_hosts_file(path_or_url)
|
97
|
-
when 'hostnames'
|
98
|
-
remove from_hostnames_file(contents)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
self
|
103
|
-
end
|
104
|
-
|
105
|
-
def to_format(format, options = {})
|
106
|
-
format = format.capitalize
|
107
|
-
begin
|
108
|
-
klass = DNSSniper.const_get(format)
|
109
|
-
klass.new(@hostnames.to_a).output(options)
|
110
|
-
rescue NameError
|
111
|
-
false
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def to_a
|
116
|
-
@hostnames.to_a
|
117
|
-
end
|
118
|
-
|
119
|
-
private
|
120
|
-
|
121
|
-
def clean(hostnames)
|
122
|
-
cleaned_hostnames = []
|
123
|
-
hostnames.each do |hostname|
|
124
|
-
hostname = hostname.downcase.strip
|
125
|
-
hostname = hostname.sub('www.', '')
|
126
|
-
hostname_top_domain = "#{hostname.split('.')[-2]}.#{hostname.split('.')[-1]}"
|
127
|
-
|
128
|
-
if !hostname.include?('#') && !['broadcasthost', 'localhost', ''].include?(hostname) && !@hostnames.include?(hostname_top_domain)
|
129
|
-
cleaned_hostnames << hostname
|
130
|
-
end
|
131
|
-
end
|
132
|
-
cleaned_hostnames
|
133
|
-
end
|
134
|
-
|
135
|
-
def syntax(path_or_url, contents)
|
136
|
-
contents.each do |line|
|
137
|
-
next if line.include?('#')
|
138
|
-
|
139
|
-
line = line.downcase
|
140
|
-
if line.strip.split(/\s/).first =~ Regexp.union([Resolv::IPv4::Regex, Resolv::IPv6::Regex])
|
141
|
-
return 'hosts'
|
142
|
-
elsif line.include?('.') && !URI.parse(line).is_a?(URI::HTTP)
|
143
|
-
return 'hostnames'
|
144
|
-
end
|
145
|
-
end
|
146
|
-
nil
|
147
|
-
end
|
148
|
-
|
149
|
-
def from_hosts_file(path_or_url)
|
150
|
-
# TODO: Remove downloading file twice
|
151
|
-
HostsFile.load(path_or_url).map(&:name)
|
152
|
-
end
|
153
|
-
|
154
|
-
def from_hostnames_file(contents)
|
155
|
-
contents.each { |line| add(line) }
|
31
|
+
blacklist - whitelist
|
156
32
|
end
|
157
33
|
end
|
158
34
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DNSSniper
|
4
|
+
class Importer
|
5
|
+
attr_accessor :uri, :hostnames
|
6
|
+
|
7
|
+
def initialize(uri, *)
|
8
|
+
@uri = uri
|
9
|
+
@hostnames = File.exist?(uri) ? import_file(uri) : import_uri(uri)
|
10
|
+
end
|
11
|
+
|
12
|
+
def import_file(*)
|
13
|
+
raise NotImplementedError, "#{self.class.name}: #import_file not supported"
|
14
|
+
end
|
15
|
+
|
16
|
+
def import_uri(*)
|
17
|
+
raise NotImplementedError, "#{self.class.name}: #import_uri not supported"
|
18
|
+
end
|
19
|
+
|
20
|
+
# Helper methods
|
21
|
+
|
22
|
+
def clean(domain)
|
23
|
+
domain = domain.split('#')[0] if domain[0] != '#' && domain.include?('#')
|
24
|
+
domain = domain.split(':')[0] if domain.include?(':') && !ip_addr?(domain)
|
25
|
+
domain = domain.sub('www.', '') if domain.start_with?('www.') && domain.scan('www.').count == 1
|
26
|
+
|
27
|
+
domain.chomp.gsub(/\s+/, '').downcase
|
28
|
+
end
|
29
|
+
|
30
|
+
def rejector(domain)
|
31
|
+
!domain?(domain)
|
32
|
+
end
|
33
|
+
|
34
|
+
def domain?(domain)
|
35
|
+
return false if domain == ''
|
36
|
+
return false if domain.gsub('#', '').gsub(/\s+/, '').empty?
|
37
|
+
return false if domain[0] == '#'
|
38
|
+
return false unless domain.include?('.')
|
39
|
+
return false if domain.include?(':')
|
40
|
+
return false if ip_addr?(domain)
|
41
|
+
return false unless /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/.match?(domain)
|
42
|
+
|
43
|
+
begin
|
44
|
+
return false if URI.parse(domain).is_a?(URI::HTTP)
|
45
|
+
rescue URI::InvalidURIError; end
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def ip_addr?(domain)
|
50
|
+
domain =~ Regexp.union([Resolv::IPv4::Regex, Resolv::IPv6::Regex])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DNSSniper
|
4
|
+
module Importers
|
5
|
+
module_function
|
6
|
+
|
7
|
+
attr_reader :registered
|
8
|
+
@registered = []
|
9
|
+
|
10
|
+
def register(class_name, autoload_require)
|
11
|
+
DNSSniper.autoload(class_name, autoload_require)
|
12
|
+
@registered << class_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def all
|
16
|
+
@registered.map { |name| DNSSniper.const_get(name) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def find(name)
|
20
|
+
all.find { |c| c.name.downcase == name.to_s.downcase } or raise NameError, "Unknown Importer \"#{name}\""
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
DNSSniper::Importers.register :ConfigurationImporter, 'dns-sniper/importers/configuration_importer'
|
26
|
+
DNSSniper::Importers.register :DomainsImporter, 'dns-sniper/importers/domains_importer'
|
27
|
+
DNSSniper::Importers.register :HostsImporter, 'dns-sniper/importers/hosts_importer'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DNSSniper
|
4
|
+
class ConfigurationImporter < Importer
|
5
|
+
def initialize(uri, list:)
|
6
|
+
@uri = uri
|
7
|
+
@hostnames = File.exist?(uri) ? import_file(uri, list: list) : import_uri(uri, list: list)
|
8
|
+
end
|
9
|
+
|
10
|
+
def import_file(path, list:)
|
11
|
+
raise ArgumentError, "#{self.class.name}: #from_path requies list to be defined" unless list
|
12
|
+
return [].to_set unless File.exist?(path)
|
13
|
+
|
14
|
+
yaml = YAML.safe_load(File.read(path), permitted_classes: [Symbol])
|
15
|
+
return [].to_set unless yaml.dig(:sources)&.dig(list.to_sym)
|
16
|
+
|
17
|
+
hostnames = [].to_set
|
18
|
+
yaml.dig(:sources).dig(list.to_sym).each do |source|
|
19
|
+
return [].to_set unless source.dig(:importer)
|
20
|
+
return [].to_set unless source.dig(:uri)
|
21
|
+
|
22
|
+
importer = DNSSniper.const_get("#{source.dig(:importer).to_s.split('_').map(&:capitalize).join}Importer")
|
23
|
+
if !importer
|
24
|
+
next
|
25
|
+
else
|
26
|
+
importer = importer.new(source.dig(:uri))
|
27
|
+
hostnames += importer.hostnames
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
hostnames
|
32
|
+
end
|
33
|
+
|
34
|
+
def import_uri(_uri, list:)
|
35
|
+
raise NotImplementedError, "#{self.class.name}: #from_uri not supported"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DNSSniper
|
4
|
+
class DomainsImporter < Importer
|
5
|
+
def import_file(path)
|
6
|
+
return [].to_set unless File.exist?(path)
|
7
|
+
|
8
|
+
File.open(path).readlines(chomp: true).map { |hostname| clean(hostname) }.reject { |hostname| rejector(hostname) }.to_set
|
9
|
+
end
|
10
|
+
|
11
|
+
def import_uri(uri)
|
12
|
+
begin
|
13
|
+
down = Down.download(uri)
|
14
|
+
return down.readlines(chomp: true).map { |hostname| clean(hostname) }.reject { |hostname| rejector(hostname) }.to_set
|
15
|
+
rescue Down::InvalidUrl => e
|
16
|
+
warn "#{self.class.name}: #{e}"
|
17
|
+
end
|
18
|
+
|
19
|
+
[].to_set
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DNSSniper
|
4
|
+
class HostsImporter < Importer
|
5
|
+
def import_file(path, *)
|
6
|
+
return [].to_set unless File.exist?(path)
|
7
|
+
|
8
|
+
HostsFile.load(path).map(&:name).map { |hostname| clean(hostname) }.reject { |hostname| rejector(hostname) }.to_set
|
9
|
+
end
|
10
|
+
|
11
|
+
def import_uri(uri, *)
|
12
|
+
begin
|
13
|
+
down = Down.download(uri)
|
14
|
+
path = down.path
|
15
|
+
rescue Down::InvalidUrl => e
|
16
|
+
warn "#{self.class.name}: #{e}"
|
17
|
+
end
|
18
|
+
|
19
|
+
if path
|
20
|
+
return HostsFile.load(path).map(&:name).map { |hostname| clean(hostname) }.reject { |hostname| rejector(hostname) }.to_set
|
21
|
+
end
|
22
|
+
|
23
|
+
[].to_set
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dns-sniper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.
|
4
|
+
version: 0.0.1.pre5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brody Hoskins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11-
|
11
|
+
date: 2020-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: down
|
@@ -56,15 +56,20 @@ files:
|
|
56
56
|
- bin/dns-sniper
|
57
57
|
- dns-sniper.gemspec
|
58
58
|
- lib/dns-sniper.rb
|
59
|
-
- lib/dns-sniper/
|
60
|
-
- lib/dns-sniper/
|
61
|
-
- lib/dns-sniper/
|
62
|
-
- lib/dns-sniper/
|
63
|
-
- lib/dns-sniper/
|
64
|
-
- lib/dns-sniper/
|
65
|
-
- lib/dns-sniper/
|
66
|
-
- lib/dns-sniper/
|
59
|
+
- lib/dns-sniper/exporter.rb
|
60
|
+
- lib/dns-sniper/exporters.rb
|
61
|
+
- lib/dns-sniper/exporters/bind8_exporter.rb
|
62
|
+
- lib/dns-sniper/exporters/dnsmasq_exporter.rb
|
63
|
+
- lib/dns-sniper/exporters/hosts_exporter.rb
|
64
|
+
- lib/dns-sniper/exporters/netgear_exporter.rb
|
65
|
+
- lib/dns-sniper/exporters/text_exporter.rb
|
66
|
+
- lib/dns-sniper/exporters/unbound_exporter.rb
|
67
67
|
- lib/dns-sniper/hostnames.rb
|
68
|
+
- lib/dns-sniper/importer.rb
|
69
|
+
- lib/dns-sniper/importers.rb
|
70
|
+
- lib/dns-sniper/importers/configuration_importer.rb
|
71
|
+
- lib/dns-sniper/importers/domains_importer.rb
|
72
|
+
- lib/dns-sniper/importers/hosts_importer.rb
|
68
73
|
homepage: https://github.com/brodyhoskins/dns-sniper
|
69
74
|
licenses:
|
70
75
|
- MIT
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DNSSniper
|
4
|
-
module Formatters
|
5
|
-
extend self
|
6
|
-
|
7
|
-
attr_reader :registered
|
8
|
-
@registered = []
|
9
|
-
|
10
|
-
def register(class_name, autoload_require)
|
11
|
-
DNSSniper.autoload(class_name, autoload_require)
|
12
|
-
@registered << class_name
|
13
|
-
end
|
14
|
-
|
15
|
-
def all
|
16
|
-
@registered.map { |name| DNSSniper.const_get(name) }
|
17
|
-
end
|
18
|
-
|
19
|
-
def find(name)
|
20
|
-
all.find { |c| c.name.downcase == name.to_s.downcase } or raise NameError, "Unknown formatter \"#{name}\""
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
DNSSniper::Formatters.register :Bind8, 'dns-sniper/formatters/bind8'
|
26
|
-
DNSSniper::Formatters.register :Dnsmasq, 'dns-sniper/formatters/dnsmasq'
|
27
|
-
DNSSniper::Formatters.register :Hosts, 'dns-sniper/formatters/hosts'
|
28
|
-
DNSSniper::Formatters.register :Netgear, 'dns-sniper/formatters/netgear'
|
29
|
-
DNSSniper::Formatters.register :Text, 'dns-sniper/formatters/text'
|
30
|
-
DNSSniper::Formatters.register :Unbound, 'dns-sniper/formatters/unbound'
|