passivedns-client 2.1.6 → 2.1.7
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/lib/passivedns/client.rb +68 -36
- data/lib/passivedns/client/cli.rb +139 -139
- data/lib/passivedns/client/provider/bfk.rb +54 -52
- data/lib/passivedns/client/provider/circl.rb +39 -39
- data/lib/passivedns/client/provider/cn360.rb +21 -21
- data/lib/passivedns/client/provider/dnsdb.rb +56 -56
- data/lib/passivedns/client/provider/mnemonic.rb +62 -55
- data/lib/passivedns/client/provider/passivetotal.rb +43 -43
- data/lib/passivedns/client/provider/riskiq.rb +40 -40
- data/lib/passivedns/client/provider/tcpiputils.rb +18 -18
- data/lib/passivedns/client/provider/virustotal.rb +46 -46
- data/lib/passivedns/client/state.rb +236 -236
- data/lib/passivedns/client/version.rb +1 -1
- metadata +2 -2
@@ -8,7 +8,7 @@ module PassiveDNS #:nodoc: don't document this
|
|
8
8
|
# The Provider module contains all the Passive DNS provider client code
|
9
9
|
module Provider
|
10
10
|
# Queries Mnemonic's passive DNS database
|
11
|
-
|
11
|
+
class Mnemonic < PassiveDB
|
12
12
|
# Sets the modules self-reported name to "Mnemonic"
|
13
13
|
def self.name
|
14
14
|
"Mnemonic"
|
@@ -26,79 +26,86 @@ module PassiveDNS #:nodoc: don't document this
|
|
26
26
|
attr_accessor :debug
|
27
27
|
# === Options
|
28
28
|
# * :debug Sets the debug flag for the module
|
29
|
-
# * "APIKEY"
|
30
|
-
# * "URL"
|
29
|
+
# * "APIKEY" The API key associated with Mnemonic for doing automated queries
|
30
|
+
# * "URL" Alternate url for testing. Defaults to "https://api.mnemonic.no/pdns/v3/"
|
31
31
|
#
|
32
32
|
# === Example Instantiation
|
33
33
|
#
|
34
34
|
# options = {
|
35
35
|
# :debug => true,
|
36
36
|
# "APIKEY" => "01234567890abcdef01234567890abcdef012345",
|
37
|
-
# "URL" => "https://
|
37
|
+
# "URL" => "https://api.mnemonic.no/pdns/v3/"
|
38
38
|
# }
|
39
39
|
#
|
40
40
|
# PassiveDNS::Provider::Mnemonic.new(options)
|
41
41
|
#
|
42
|
-
|
42
|
+
def initialize(options={})
|
43
43
|
@debug = options[:debug] || false
|
44
|
-
@apikey = options["APIKEY"]
|
45
|
-
@url = options["URL"] || "https://
|
46
|
-
|
44
|
+
@apikey = options["APIKEY"]
|
45
|
+
@url = options["URL"] || "https://api.mnemonic.no/pdns/v3/"
|
46
|
+
if @url == "https://passivedns.mnemonic.no/api1/?apikey="
|
47
|
+
@url = "https://api.mnemonic.no/pdns/v3/"
|
48
|
+
end
|
49
|
+
end
|
47
50
|
|
48
51
|
# Takes a label (either a domain or an IP address) and returns
|
49
52
|
# an array of PassiveDNS::PDNSResult instances with the answers to the query
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
53
|
+
def lookup(label, limit=nil)
|
54
|
+
$stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
|
55
|
+
Timeout::timeout(240) {
|
56
|
+
url = "#{@url}#{label}"
|
57
|
+
$stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
|
58
|
+
url = URI.parse url
|
59
|
+
http = Net::HTTP.new(url.host, url.port)
|
60
|
+
http.use_ssl = (url.scheme == 'https')
|
61
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
62
|
+
http.verify_depth = 5
|
63
|
+
request = Net::HTTP::Get.new(url.path)
|
64
|
+
request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
|
65
|
+
if @apikey
|
66
|
+
request.add_field("Argus-API-Key", @apikey)
|
67
|
+
end
|
68
|
+
t1 = Time.now
|
69
|
+
response = http.request(request)
|
70
|
+
t2 = Time.now
|
71
|
+
recs = parse_json(response.body, label, t2-t1)
|
72
|
+
if limit
|
73
|
+
recs[0,limit]
|
74
|
+
else
|
75
|
+
recs
|
76
|
+
end
|
77
|
+
}
|
78
|
+
rescue Timeout::Error => e
|
79
|
+
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
80
|
+
end
|
75
81
|
|
76
82
|
private
|
77
83
|
|
78
84
|
# parses the response of mnemonic's JSON reply to generate an array of PDNSResult
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
+
def parse_json(page,query,response_time=0)
|
86
|
+
res = []
|
87
|
+
data = JSON.parse(page)
|
88
|
+
if data['data']
|
89
|
+
data['data'].each do |row|
|
90
|
+
if row['query']
|
85
91
|
query = row['query']
|
86
92
|
answer = row['answer']
|
87
|
-
rrtype = row['
|
88
|
-
|
89
|
-
firstseen = Time.at(row['
|
90
|
-
lastseen = Time.at(row['
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
93
|
+
rrtype = row['rrtype'].upcase
|
94
|
+
ttl = row['maxTtl'].to_i
|
95
|
+
firstseen = Time.at(row['firstSeenTimestamp'].to_i / 1000)
|
96
|
+
lastseen = Time.at(row['lastSeenTimestamp'].to_i / 1000)
|
97
|
+
tlp = row['tlp']
|
98
|
+
r = PDNSResult.new(self.class.name,response_time, query, answer, rrtype, ttl, firstseen, lastseen, tlp)
|
99
|
+
res << r
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
res
|
104
|
+
rescue Exception => e
|
105
|
+
$stderr.puts "#{self.class.name} Exception: #{e}"
|
106
|
+
raise e
|
107
|
+
end
|
101
108
|
|
102
|
-
|
109
|
+
end
|
103
110
|
end
|
104
|
-
end
|
111
|
+
end
|
@@ -9,7 +9,7 @@ module PassiveDNS #:nodoc: don't document this
|
|
9
9
|
# The Provider module contains all the Passive DNS provider client code
|
10
10
|
module Provider
|
11
11
|
# Queries PassiveTotal's passive DNS database
|
12
|
-
|
12
|
+
class PassiveTotal < PassiveDB
|
13
13
|
# Sets the modules self-reported name to "PassiveTotal"
|
14
14
|
def self.name
|
15
15
|
"PassiveTotal"
|
@@ -52,65 +52,65 @@ module PassiveDNS #:nodoc: don't document this
|
|
52
52
|
#
|
53
53
|
# PassiveDNS::Provider::PassiveTotal.new(options)
|
54
54
|
#
|
55
|
-
|
55
|
+
def initialize(options={})
|
56
56
|
@debug = options[:debug] || false
|
57
57
|
@username = options["USERNAME"] || raise("#{self.class.name} requires a USERNAME")
|
58
58
|
@apikey = options["APIKEY"] || raise("#{self.class.name} requires an APIKEY")
|
59
59
|
@url = options["URL"] || "https://api.passivetotal.org/v2/dns/passive"
|
60
|
-
|
60
|
+
end
|
61
61
|
|
62
62
|
# Takes a label (either a domain or an IP address) and returns
|
63
63
|
# an array of PassiveDNS::PDNSResult instances with the answers to the query
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
64
|
+
def lookup(label, limit=nil)
|
65
|
+
$stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
|
66
|
+
Timeout::timeout(240) {
|
67
|
+
url = @url+"?query=#{label}"
|
68
|
+
$stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
|
69
|
+
url = URI.parse url
|
70
|
+
http = Net::HTTP.new(url.host, url.port)
|
71
|
+
http.use_ssl = (url.scheme == 'https')
|
72
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
73
|
+
http.verify_depth = 5
|
74
|
+
request = Net::HTTP::Get.new(url.request_uri)
|
75
75
|
request.basic_auth(@username, @apikey)
|
76
|
-
|
76
|
+
request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
|
77
77
|
#request.set_form_data({"api_key" => @apikey, "query" => label})
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
78
|
+
t1 = Time.now
|
79
|
+
response = http.request(request)
|
80
|
+
t2 = Time.now
|
81
|
+
recs = parse_json(response.body, label, t2-t1)
|
82
|
+
if limit
|
83
|
+
recs[0,limit]
|
84
|
+
else
|
85
|
+
recs
|
86
|
+
end
|
87
|
+
}
|
88
|
+
rescue Timeout::Error => e
|
89
|
+
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
90
|
+
end
|
91
91
|
|
92
92
|
private
|
93
93
|
|
94
94
|
# parses the response of passivetotals's JSON reply to generate an array of PDNSResult
|
95
|
-
|
96
|
-
|
97
|
-
|
95
|
+
def parse_json(page,query,response_time=0)
|
96
|
+
res = []
|
97
|
+
data = JSON.parse(page)
|
98
98
|
query = data['queryValue']
|
99
|
-
|
100
|
-
|
99
|
+
if data['results']
|
100
|
+
data['results'].each do |row|
|
101
101
|
first_seen = (row['firstSeen'] == "None") ? nil : Time.parse(row['firstSeen']+" +0000")
|
102
102
|
last_seen = (row['lastSeen'] == "None") ? nil : Time.parse(row['lastSeen']+" +0000")
|
103
103
|
value = row['resolve']
|
104
104
|
source = row['source'].join(",")
|
105
|
-
|
106
|
-
query, value, "A", 0, first_seen, last_seen)
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
105
|
+
res << PDNSResult.new(self.class.name+"/"+source,response_time,
|
106
|
+
query, value, "A", 0, first_seen, last_seen, 'yellow')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
res
|
110
|
+
rescue Exception => e
|
111
|
+
$stderr.puts "#{self.class.name} Exception: #{e}"
|
112
|
+
raise e
|
113
|
+
end
|
114
|
+
end
|
115
115
|
end
|
116
116
|
end
|
@@ -9,7 +9,7 @@ module PassiveDNS #:nodoc: don't document this
|
|
9
9
|
# The Provider module contains all the Passive DNS provider client code
|
10
10
|
module Provider
|
11
11
|
# Queries RiskIQ's passive DNS database
|
12
|
-
|
12
|
+
class RiskIQ < PassiveDB
|
13
13
|
# Sets the modules self-reported name to "RiskIQ"
|
14
14
|
def self.name
|
15
15
|
"RiskIQ"
|
@@ -44,20 +44,20 @@ module PassiveDNS #:nodoc: don't document this
|
|
44
44
|
#
|
45
45
|
# PassiveDNS::Provider::RiskIQ.new(options)
|
46
46
|
#
|
47
|
-
|
47
|
+
def initialize(options={})
|
48
48
|
@debug = options[:debug] || false
|
49
49
|
@token = options["API_TOKEN"] || raise("#{self.class.name} requires an API_TOKEN")
|
50
50
|
@privkey = options["API_PRIVATE_KEY"] || raise("#{self.class.name} requires an API_PRIVATE_KEY")
|
51
51
|
@server = options["API_SERVER"] || "ws.riskiq.net"
|
52
52
|
@version = options["API_VERSION"] || "v1"
|
53
53
|
@url = "https://#{@server}/#{@version}"
|
54
|
-
|
54
|
+
end
|
55
55
|
|
56
56
|
# Takes a label (either a domain or an IP address) and returns
|
57
57
|
# an array of PassiveDNS::PDNSResult instances with the answers to the query
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
def lookup(label, limit=nil)
|
59
|
+
$stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
|
60
|
+
Timeout::timeout(240) {
|
61
61
|
url = nil
|
62
62
|
params = {"rrType" => "", "maxResults" => limit || 1000}
|
63
63
|
|
@@ -74,38 +74,38 @@ module PassiveDNS #:nodoc: don't document this
|
|
74
74
|
end
|
75
75
|
url.gsub!(/\&$/,"")
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
77
|
+
$stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
|
78
|
+
url = URI.parse url
|
79
|
+
http = Net::HTTP.new(url.host, url.port)
|
80
|
+
http.use_ssl = (url.scheme == 'https')
|
81
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
82
|
+
http.verify_depth = 5
|
83
|
+
request = Net::HTTP::Get.new(url.request_uri)
|
84
|
+
request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
|
85
85
|
request.add_field('Accept', 'Application/JSON')
|
86
86
|
request.add_field('Content-Type', 'Application/JSON')
|
87
87
|
request.basic_auth(@token, @privkey)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
88
|
+
t1 = Time.now
|
89
|
+
response = http.request(request)
|
90
|
+
t2 = Time.now
|
91
|
+
recs = parse_json(response.body, label, t2-t1)
|
92
|
+
if limit
|
93
|
+
recs[0,limit]
|
94
|
+
else
|
95
|
+
recs
|
96
|
+
end
|
97
|
+
}
|
98
|
+
rescue Timeout::Error => e
|
99
|
+
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
100
|
+
end
|
101
101
|
|
102
102
|
private
|
103
103
|
|
104
104
|
# parses the response of riskiq's JSON reply to generate an array of PDNSResult
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
105
|
+
def parse_json(page,query,response_time=0)
|
106
|
+
res = []
|
107
|
+
data = JSON.parse(page)
|
108
|
+
if data['records']
|
109
109
|
data['records'].each do |record|
|
110
110
|
name = record['name'].gsub!(/\.$/,'')
|
111
111
|
type = record['rrtype']
|
@@ -114,17 +114,17 @@ module PassiveDNS #:nodoc: don't document this
|
|
114
114
|
count = record['count']
|
115
115
|
record['data'].each do |datum|
|
116
116
|
datum.gsub!(/\.$/,'')
|
117
|
-
|
118
|
-
name, datum, type, 0, first_seen, last_seen, count)
|
117
|
+
res << PDNSResult.new(self.class.name,response_time,
|
118
|
+
name, datum, type, 0, first_seen, last_seen, count, 'yellow')
|
119
119
|
end
|
120
120
|
end
|
121
121
|
end
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
122
|
+
res
|
123
|
+
rescue Exception => e
|
124
|
+
$stderr.puts "#{self.class.name} Exception: #{e}"
|
125
|
+
raise e
|
126
|
+
end
|
127
127
|
|
128
|
-
|
128
|
+
end
|
129
129
|
end
|
130
|
-
end
|
130
|
+
end
|
@@ -54,17 +54,17 @@ module PassiveDNS #:nodoc: don't document this
|
|
54
54
|
url = "#{@url}#{@apikey}&type=#{type}&q=#{label}"
|
55
55
|
recs = []
|
56
56
|
Timeout::timeout(240) {
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
57
|
+
url = URI.parse url
|
58
|
+
http = Net::HTTP.new(url.host, url.port)
|
59
|
+
http.use_ssl = (url.scheme == 'https')
|
60
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
61
|
+
http.verify_depth = 5
|
62
|
+
request = Net::HTTP::Get.new(url.path+"?"+url.query)
|
63
|
+
request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
|
64
|
+
t1 = Time.now
|
65
|
+
response = http.request(request)
|
66
|
+
delta = (Time.now - t1).to_f
|
67
|
+
reply = JSON.parse(response.body)
|
68
68
|
if reply["status"] and reply["status"] == "succeed"
|
69
69
|
question = reply["data"]["question"]
|
70
70
|
recs = format_recs(reply["data"], question, delta)
|
@@ -76,10 +76,10 @@ module PassiveDNS #:nodoc: don't document this
|
|
76
76
|
else
|
77
77
|
recs
|
78
78
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
79
|
+
}
|
80
|
+
rescue Timeout::Error => e
|
81
|
+
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
82
|
+
end
|
83
83
|
|
84
84
|
private
|
85
85
|
|
@@ -110,13 +110,13 @@ module PassiveDNS #:nodoc: don't document this
|
|
110
110
|
when "domains"
|
111
111
|
data.each do |rec|
|
112
112
|
lastseen = (rec["updatedate"]) ? Date.parse(rec["updatedate"]) : nil
|
113
|
-
recs << PDNSResult.new(self.class.name, delta, rec, question, "A", nil, nil, nil, nil)
|
113
|
+
recs << PDNSResult.new(self.class.name, delta, rec, question, "A", nil, nil, nil, nil, 'yellow')
|
114
114
|
end
|
115
115
|
end
|
116
116
|
if add_records
|
117
117
|
data.each do |rec|
|
118
118
|
lastseen = (rec["updatedate"]) ? Date.parse(rec["updatedate"]) : nil
|
119
|
-
recs << PDNSResult.new(self.class.name, delta, question, rec[fieldname], rrtype, nil, nil, lastseen, nil)
|
119
|
+
recs << PDNSResult.new(self.class.name, delta, question, rec[fieldname], rrtype, nil, nil, lastseen, nil, 'yellow')
|
120
120
|
end
|
121
121
|
end
|
122
122
|
end
|
@@ -125,4 +125,4 @@ module PassiveDNS #:nodoc: don't document this
|
|
125
125
|
|
126
126
|
end
|
127
127
|
end
|
128
|
-
end
|
128
|
+
end
|