passivedns-client 2.1.6 → 2.1.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|