passivedns-client 2.1.12 → 2.1.13
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/.gitignore +0 -0
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +34 -52
- data/Rakefile +0 -0
- data/lib/passivedns/client.rb +1 -3
- data/lib/passivedns/client/cli.rb +2 -7
- data/lib/passivedns/client/passivedb.rb +0 -0
- data/lib/passivedns/client/provider/circl.rb +0 -0
- data/lib/passivedns/client/provider/dnsdb.rb +0 -0
- data/lib/passivedns/client/provider/passivetotal.rb +0 -0
- data/lib/passivedns/client/provider/riskiq.rb +0 -0
- data/lib/passivedns/client/provider/virustotal.rb +0 -0
- data/lib/passivedns/client/state.rb +0 -0
- data/lib/passivedns/client/version.rb +1 -1
- data/passivedns-client.gemspec +0 -0
- data/test/helper.rb +0 -0
- data/test/test_cli.rb +26 -41
- data/test/test_passivedns-client.rb +0 -100
- metadata +1 -5
- data/lib/passivedns/client/provider/bfk.rb +0 -109
- data/lib/passivedns/client/provider/cn360.rb +0 -122
- data/lib/passivedns/client/provider/mnemonic.rb +0 -112
- data/lib/passivedns/client/provider/tcpiputils.rb +0 -129
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c2b55f21b59fb20d9167e1893d86aa500e3d020932d7b6e3fe5f2eed7e3113b
|
4
|
+
data.tar.gz: 7a48256ee4739a8a432a4a5f7aff6c7a9d8fcd1e5922b07caaf6d3557ffa5ca5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e75a301a616818187ba3ea036b2ae39b8b3b562c37115cf4b6d1ece009748838d76477ef58b353f654a81e890c1f5aaa2aeb151b45c23cb5bec692845f52f732
|
7
|
+
data.tar.gz: 6a549456ebbc19920f00129ee0371742790f288324ade26441349cd407d9e7f8f42e49ecaac49da3b59ed5ba36267fb925d77cfc33e996d58df4d8284a28f5d2
|
data/.gitignore
CHANGED
File without changes
|
data/Gemfile
CHANGED
File without changes
|
data/LICENSE.txt
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -2,14 +2,10 @@
|
|
2
2
|
|
3
3
|
This rubygem queries the following Passive DNS databases:
|
4
4
|
|
5
|
-
* BFK.de
|
6
5
|
* CIRCL
|
7
6
|
* DNSDB (FarSight)
|
8
|
-
* Mnemonic
|
9
|
-
* PassiveDNS.cn (Qihoo 360 Technology Co.,Ltd)
|
10
7
|
* PassiveTotal
|
11
8
|
* RiskIQ
|
12
|
-
* TCPIPUtils
|
13
9
|
* VirusTotal
|
14
10
|
|
15
11
|
Passive DNS is a technique where IP to hostname mappings are made by recording the answers of other people's queries.
|
@@ -40,16 +36,8 @@ From version 2.0.0 on, all configuration keys for passive DNS providers are in o
|
|
40
36
|
|
41
37
|
[dnsdb]
|
42
38
|
APIKEY = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
43
|
-
[cn360]
|
44
|
-
API = http://some.web.address.for.their.api
|
45
|
-
API_ID = a username that is given when you register
|
46
|
-
API_KEY = a long and random password of sorts that is used along with the page request to generate a per page API key
|
47
|
-
[tcpiputils]
|
48
|
-
APIKEY = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
49
39
|
[virustotal]
|
50
40
|
APIKEY = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
51
|
-
[mnemonic]
|
52
|
-
APIKEY = 01234567890abcdef01234567890abcdef012345
|
53
41
|
[passivetotal]
|
54
42
|
USERNAME = tom@example.com
|
55
43
|
APIKEY = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
@@ -66,61 +54,55 @@ CIRCL also can use and authorization token. In that case, you should drop the U
|
|
66
54
|
AUTH_TOKEN = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
67
55
|
|
68
56
|
## Getting Access
|
69
|
-
* 360.cn : http://www.passivedns.cn
|
70
|
-
* BFK.de : No registration required, but please, please ready their usage policy at http://www.bfk.de/bfk_dnslogger.html
|
71
57
|
* CIRCL : https://www.circl.lu/services/passive-dns/
|
72
58
|
* DNSDB (Farsight Security) : https://api.dnsdb.info/
|
73
|
-
* Mnemonic : mss .at. mnemonic.no
|
74
59
|
* PassiveTotal : https://www.passivetotal.org
|
75
60
|
* RiskIQ : https://github.com/RiskIQ/python_api/blob/master/LICENSE
|
76
|
-
* TCPIPUtils : http://www.tcpiputils.com/premium-access
|
77
61
|
* VirusTotal : https://www.virustotal.com
|
78
62
|
|
79
63
|
## Usage
|
80
64
|
|
81
65
|
require 'passivedns/client'
|
82
66
|
|
83
|
-
c = PassiveDNS::Client.new(['
|
67
|
+
c = PassiveDNS::Client.new(['riskiq','dnsdb'])
|
84
68
|
results = c.query("example.com")
|
85
69
|
|
86
70
|
|
87
71
|
Or use the included tool...
|
88
72
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
Getting Help
|
123
|
-
-v debugging information
|
73
|
+
Usage: bin/pdnstool [-d [cdprv]] [-g|-v|-m|-c|-x|-y|-j|-t] [-os <sep>] [-f <file>] [-r#|-w#|-v] [-l <count>] [--config <file>] <ip|domain|cidr>
|
74
|
+
Passive DNS Providers
|
75
|
+
-dcdprv uses all of the available passive dns database
|
76
|
+
-dc use CIRCL
|
77
|
+
-dd use DNSDB
|
78
|
+
-dp use PassiveTotal
|
79
|
+
-dr use RiskIQ
|
80
|
+
-dv use VirusTotal
|
81
|
+
-dvr uses VirusTotal and RiskIQ (for example)
|
82
|
+
|
83
|
+
Output Formatting
|
84
|
+
-g link-nodal GDF visualization definition
|
85
|
+
-z link-nodal graphviz visualization definition
|
86
|
+
-m link-nodal graphml visualization definition
|
87
|
+
-c CSV
|
88
|
+
-x XML
|
89
|
+
-y YAML
|
90
|
+
-j JSON
|
91
|
+
-t ASCII text (default)
|
92
|
+
-s <sep> specifies a field separator for text output, default is tab
|
93
|
+
|
94
|
+
State and Recursion
|
95
|
+
-f[file] specifies a sqlite3 database used to read the current state - useful for large result sets and generating graphs of previous runs.
|
96
|
+
-r# specifies the levels of recursion to pull. **WARNING** This is quite taxing on the pDNS servers, so use judiciously (never more than 3 or so) or find yourself blocked!
|
97
|
+
-w# specifies the amount of time to wait, in seconds, between queries (Default: 0)
|
98
|
+
-l <count> limits the number of records returned per passive dns database queried.
|
99
|
+
|
100
|
+
Specifying a Configuration File
|
101
|
+
--config <file> specifies a config file. default: /home/chris/.passivedns-client
|
102
|
+
|
103
|
+
Getting Help
|
104
|
+
-h hello there. This option produces this helpful help information on how to access help.
|
105
|
+
-v debugging information
|
124
106
|
|
125
107
|
## Writing Your Own Database Adaptor
|
126
108
|
|
data/Rakefile
CHANGED
File without changes
|
data/lib/passivedns/client.rb
CHANGED
@@ -12,9 +12,7 @@ provider_path = File.dirname(__FILE__)+"/client/provider/*.rb"
|
|
12
12
|
Dir.glob(provider_path).each do |provider|
|
13
13
|
name = File.basename(provider, '.rb')
|
14
14
|
require "passivedns/client/provider/#{name}.rb"
|
15
|
-
|
16
|
-
$passivedns_providers << name
|
17
|
-
end
|
15
|
+
$passivedns_providers << name
|
18
16
|
end
|
19
17
|
|
20
18
|
require 'configparser'
|
@@ -133,12 +133,7 @@ module PassiveDNS # :nodoc:
|
|
133
133
|
ARGV.replace(origARGV)
|
134
134
|
|
135
135
|
if options[:pdnsdbs].length == 0
|
136
|
-
options[:pdnsdbs] << "
|
137
|
-
end
|
138
|
-
|
139
|
-
if options[:pdnsdbs].index("bfk") and options[:recursedepth] > 1 and options[:wait] < 60
|
140
|
-
options[:wait] = 60
|
141
|
-
$stderr.puts "Enforcing a minimal 60 second wait when using BFK for recursive crawling"
|
136
|
+
options[:pdnsdbs] << "virustotal"
|
142
137
|
end
|
143
138
|
|
144
139
|
if options[:debug]
|
@@ -168,7 +163,7 @@ module PassiveDNS # :nodoc:
|
|
168
163
|
letter_map.keys.sort.each do |l|
|
169
164
|
help_text << " -d#{l} use #{letter_map[l][0]}\n"
|
170
165
|
end
|
171
|
-
help_text << " -
|
166
|
+
help_text << " -dvr uses VirusTotal and RiskIQ (for example)\n"
|
172
167
|
help_text << "\n"
|
173
168
|
help_text << "Output Formatting\n"
|
174
169
|
help_text << " -g link-nodal GDF visualization definition\n"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/passivedns-client.gemspec
CHANGED
File without changes
|
data/test/helper.rb
CHANGED
File without changes
|
data/test/test_cli.rb
CHANGED
@@ -13,26 +13,22 @@ require_relative '../lib/passivedns/client/cli.rb'
|
|
13
13
|
class TestCLI < Minitest::Test
|
14
14
|
def test_letter_map
|
15
15
|
letter_map = PassiveDNS::CLI.get_letter_map
|
16
|
-
assert_equal("
|
16
|
+
assert_equal("cdprv", letter_map.keys.sort.join(""))
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_help_text
|
20
20
|
helptext = PassiveDNS::CLI.run(["--help"])
|
21
21
|
helptext.gsub!(/Usage: .*?\[/, "Usage: [")
|
22
22
|
assert_equal(
|
23
|
-
"Usage: [-d [
|
23
|
+
"Usage: [-d [cdprv]] [-g|-v|-m|-c|-x|-y|-j|-t] [-os <sep>] [-f <file>] [-r#|-w#|-v] [-l <count>] [--config <file>] <ip|domain|cidr>
|
24
24
|
Passive DNS Providers
|
25
|
-
-
|
26
|
-
-d3 use 360.cn
|
27
|
-
-db use BFK.de
|
25
|
+
-dcdprv uses all of the available passive dns database
|
28
26
|
-dc use CIRCL
|
29
27
|
-dd use DNSDB
|
30
|
-
-dm use Mnemonic
|
31
28
|
-dp use PassiveTotal
|
32
29
|
-dr use RiskIQ
|
33
|
-
-dt use TCPIPUtils
|
34
30
|
-dv use VirusTotal
|
35
|
-
-
|
31
|
+
-dvr uses VirusTotal and RiskIQ (for example)
|
36
32
|
|
37
33
|
Output Formatting
|
38
34
|
-g link-nodal GDF visualization definition
|
@@ -62,7 +58,7 @@ Getting Help
|
|
62
58
|
|
63
59
|
def test_provider_parsing
|
64
60
|
options_target = {
|
65
|
-
:pdnsdbs => ["
|
61
|
+
:pdnsdbs => ["virustotal"],
|
66
62
|
:format => "text",
|
67
63
|
:sep => "\t",
|
68
64
|
:recursedepth => 1,
|
@@ -78,24 +74,14 @@ Getting Help
|
|
78
74
|
options, items = PassiveDNS::CLI.parse_command_line([])
|
79
75
|
assert_equal(options_target, options)
|
80
76
|
assert_equal([], items)
|
81
|
-
|
82
|
-
options_target[:pdnsdbs] = ["
|
83
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
84
|
-
assert_equal(options_target, options)
|
85
|
-
assert_equal([], items)
|
86
|
-
|
87
|
-
options_target[:pdnsdbs] = ["bfk"]
|
88
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-db"])
|
89
|
-
assert_equal(options_target, options)
|
90
|
-
assert_equal([], items)
|
91
|
-
|
92
|
-
options_target[:pdnsdbs] = ["circl", "dnsdb", "mnemonic", "riskiq"]
|
93
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-dcdmr"])
|
77
|
+
|
78
|
+
options_target[:pdnsdbs] = ["circl", "dnsdb", "riskiq"]
|
79
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dcdr"])
|
94
80
|
assert_equal(options_target, options)
|
95
81
|
assert_equal([], items)
|
96
82
|
|
97
|
-
options_target[:pdnsdbs] = ["passivetotal", "
|
98
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
83
|
+
options_target[:pdnsdbs] = ["passivetotal", "virustotal"]
|
84
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv"])
|
99
85
|
assert_equal(options_target, options)
|
100
86
|
assert_equal([], items)
|
101
87
|
|
@@ -103,7 +89,7 @@ Getting Help
|
|
103
89
|
|
104
90
|
def test_output_parsing
|
105
91
|
options_target = {
|
106
|
-
:pdnsdbs => ["passivetotal", "
|
92
|
+
:pdnsdbs => ["passivetotal", "virustotal"],
|
107
93
|
:format => "text",
|
108
94
|
:sep => "\t",
|
109
95
|
:recursedepth => 1,
|
@@ -117,48 +103,48 @@ Getting Help
|
|
117
103
|
}
|
118
104
|
|
119
105
|
options_target[:sep] = ","
|
120
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
106
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-c", "8.8.8.8"])
|
121
107
|
assert_equal(options_target, options)
|
122
108
|
assert_equal(["8.8.8.8"], items)
|
123
109
|
|
124
110
|
options_target[:sep] = "|"
|
125
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
111
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-s", "|", "8.8.8.8"])
|
126
112
|
assert_equal(options_target, options)
|
127
113
|
assert_equal(["8.8.8.8"], items)
|
128
114
|
|
129
115
|
options_target[:sep] = "\t"
|
130
116
|
|
131
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
117
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-t", "8.8.8.8"])
|
132
118
|
assert_equal(options_target, options)
|
133
119
|
assert_equal(["8.8.8.8"], items)
|
134
120
|
|
135
121
|
options_target[:format] = "json"
|
136
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
122
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-j", "8.8.8.8"])
|
137
123
|
assert_equal(options_target, options)
|
138
124
|
assert_equal(["8.8.8.8"], items)
|
139
125
|
|
140
126
|
options_target[:format] = "xml"
|
141
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
127
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-x", "8.8.8.8"])
|
142
128
|
assert_equal(options_target, options)
|
143
129
|
assert_equal(["8.8.8.8"], items)
|
144
130
|
|
145
131
|
options_target[:format] = "yaml"
|
146
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
132
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-y", "8.8.8.8"])
|
147
133
|
assert_equal(options_target, options)
|
148
134
|
assert_equal(["8.8.8.8"], items)
|
149
135
|
|
150
136
|
options_target[:format] = "gdf"
|
151
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
137
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-g", "8.8.8.8"])
|
152
138
|
assert_equal(options_target, options)
|
153
139
|
assert_equal(["8.8.8.8"], items)
|
154
140
|
|
155
141
|
options_target[:format] = "graphviz"
|
156
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
142
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-z", "8.8.8.8"])
|
157
143
|
assert_equal(options_target, options)
|
158
144
|
assert_equal(["8.8.8.8"], items)
|
159
145
|
|
160
146
|
options_target[:format] = "graphml"
|
161
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
147
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-m", "8.8.8.8"])
|
162
148
|
assert_equal(options_target, options)
|
163
149
|
assert_equal(["8.8.8.8"], items)
|
164
150
|
|
@@ -167,7 +153,7 @@ Getting Help
|
|
167
153
|
|
168
154
|
def test_help_debug_parsing
|
169
155
|
options_target = {
|
170
|
-
:pdnsdbs => ["passivetotal", "
|
156
|
+
:pdnsdbs => ["passivetotal", "virustotal"],
|
171
157
|
:format => "text",
|
172
158
|
:sep => "\t",
|
173
159
|
:recursedepth => 1,
|
@@ -180,19 +166,19 @@ Getting Help
|
|
180
166
|
:configfile => "#{ENV['HOME']}/.passivedns-client"
|
181
167
|
}
|
182
168
|
|
183
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
169
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-h", "8.8.8.8"])
|
184
170
|
assert_equal(options_target, options)
|
185
171
|
assert_equal(["8.8.8.8"], items)
|
186
172
|
|
187
173
|
options_target[:debug] = true
|
188
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
174
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-h", "-v", "8.8.8.8"])
|
189
175
|
assert_equal(options_target, options)
|
190
176
|
assert_equal(["8.8.8.8"], items)
|
191
177
|
end
|
192
178
|
|
193
179
|
def test_state_recursion_parsing
|
194
180
|
options_target = {
|
195
|
-
:pdnsdbs => ["passivetotal", "
|
181
|
+
:pdnsdbs => ["passivetotal", "virustotal"],
|
196
182
|
:format => "text",
|
197
183
|
:sep => "\t",
|
198
184
|
:recursedepth => 5,
|
@@ -205,14 +191,14 @@ Getting Help
|
|
205
191
|
:configfile => "#{ENV['HOME']}/.passivedns-client"
|
206
192
|
}
|
207
193
|
|
208
|
-
options, items = PassiveDNS::CLI.parse_command_line(["-
|
194
|
+
options, items = PassiveDNS::CLI.parse_command_line(["-dpv", "-f", "test.db", "-r", "5", "-w", "30", "-l", "10", "8.8.8.8"])
|
209
195
|
assert_equal(options_target, options)
|
210
196
|
assert_equal(["8.8.8.8"], items)
|
211
197
|
end
|
212
198
|
|
213
199
|
def test_configuration_file
|
214
200
|
options_target = {
|
215
|
-
:pdnsdbs => ["
|
201
|
+
:pdnsdbs => ["virustotal"],
|
216
202
|
:format => "text",
|
217
203
|
:sep => "\t",
|
218
204
|
:recursedepth => 1,
|
@@ -225,7 +211,6 @@ Getting Help
|
|
225
211
|
:configfile => "#{ENV['HOME']}/.passivedns-client"
|
226
212
|
}
|
227
213
|
|
228
|
-
|
229
214
|
options, items = PassiveDNS::CLI.parse_command_line(["--config", "#{ENV['HOME']}/.passivedns-client"])
|
230
215
|
assert_equal(options_target, options)
|
231
216
|
assert_equal([], items)
|
@@ -46,31 +46,6 @@ class TestPassiveDnsQuery < Minitest::Test
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
def test_BFK
|
50
|
-
assert_raises RuntimeError do
|
51
|
-
PassiveDNS::Client.new(['bfk'])
|
52
|
-
end
|
53
|
-
|
54
|
-
assert_raises RuntimeError do
|
55
|
-
PassiveDNS::Provider::BFK.new(@cp['bfk'] || {})
|
56
|
-
end
|
57
|
-
|
58
|
-
# refute_nil(d)
|
59
|
-
# rows = d.lookup("example.org",3)
|
60
|
-
# refute_nil(rows)
|
61
|
-
# refute_nil(rows.to_s)
|
62
|
-
# refute_nil(rows.to_xml)
|
63
|
-
# refute_nil(rows.to_json)
|
64
|
-
# refute_nil(rows.to_yaml)
|
65
|
-
# assert_equal(3, rows.length)
|
66
|
-
# rows = d.lookup("8.8.8.8")
|
67
|
-
# refute_nil(rows)
|
68
|
-
# refute_nil(rows.to_s)
|
69
|
-
# refute_nil(rows.to_xml)
|
70
|
-
# refute_nil(rows.to_json)
|
71
|
-
# refute_nil(rows.to_yaml)
|
72
|
-
end
|
73
|
-
|
74
49
|
def test_DNSDB
|
75
50
|
PassiveDNS::Client.new(['dnsdb'])
|
76
51
|
d = PassiveDNS::Provider::DNSDB.new(@cp['dnsdb'] || {})
|
@@ -109,81 +84,6 @@ class TestPassiveDnsQuery < Minitest::Test
|
|
109
84
|
refute_nil(rows.to_yaml)
|
110
85
|
end
|
111
86
|
|
112
|
-
def test_TCPIPUtils
|
113
|
-
PassiveDNS::Client.new(['tcpiputils'])
|
114
|
-
d = PassiveDNS::Provider::TCPIPUtils.new(@cp['tcpiputils'] || {})
|
115
|
-
refute_nil(d)
|
116
|
-
rows = d.lookup("example.org")
|
117
|
-
refute_nil(rows)
|
118
|
-
refute_nil(rows.to_s)
|
119
|
-
refute_nil(rows.to_xml)
|
120
|
-
refute_nil(rows.to_json)
|
121
|
-
refute_nil(rows.to_yaml)
|
122
|
-
rows = d.lookup("example.org",3)
|
123
|
-
refute_nil(rows)
|
124
|
-
refute_nil(rows.to_s)
|
125
|
-
refute_nil(rows.to_xml)
|
126
|
-
refute_nil(rows.to_json)
|
127
|
-
refute_nil(rows.to_yaml)
|
128
|
-
assert_equal(3, rows.length)
|
129
|
-
rows = d.lookup("8.8.8.8")
|
130
|
-
refute_nil(rows)
|
131
|
-
refute_nil(rows.to_s)
|
132
|
-
refute_nil(rows.to_xml)
|
133
|
-
refute_nil(rows.to_json)
|
134
|
-
refute_nil(rows.to_yaml)
|
135
|
-
end
|
136
|
-
|
137
|
-
def test_cn360
|
138
|
-
PassiveDNS::Client.new(['cn360'])
|
139
|
-
d = PassiveDNS::Provider::CN360.new(@cp['cn360'] || {})
|
140
|
-
refute_nil(d)
|
141
|
-
rows = d.lookup("example.org")
|
142
|
-
refute_nil(rows)
|
143
|
-
refute_nil(rows.to_s)
|
144
|
-
refute_nil(rows.to_xml)
|
145
|
-
refute_nil(rows.to_json)
|
146
|
-
refute_nil(rows.to_yaml)
|
147
|
-
rows = d.lookup("example.org",3)
|
148
|
-
refute_nil(rows)
|
149
|
-
refute_nil(rows.to_s)
|
150
|
-
refute_nil(rows.to_xml)
|
151
|
-
refute_nil(rows.to_json)
|
152
|
-
refute_nil(rows.to_yaml)
|
153
|
-
assert_equal(3, rows.length)
|
154
|
-
rows = d.lookup("8.8.8.8")
|
155
|
-
refute_nil(rows)
|
156
|
-
refute_nil(rows.to_s)
|
157
|
-
refute_nil(rows.to_xml)
|
158
|
-
refute_nil(rows.to_json)
|
159
|
-
refute_nil(rows.to_yaml)
|
160
|
-
end
|
161
|
-
|
162
|
-
def test_nmemonic
|
163
|
-
PassiveDNS::Client.new(['mnemonic'])
|
164
|
-
d = PassiveDNS::Provider::Mnemonic.new(@cp['mnemonic'] || {})
|
165
|
-
refute_nil(d)
|
166
|
-
rows = d.lookup("example.org")
|
167
|
-
refute_nil(rows)
|
168
|
-
refute_nil(rows.to_s)
|
169
|
-
refute_nil(rows.to_xml)
|
170
|
-
refute_nil(rows.to_json)
|
171
|
-
refute_nil(rows.to_yaml)
|
172
|
-
rows = d.lookup("example.org",3)
|
173
|
-
refute_nil(rows)
|
174
|
-
refute_nil(rows.to_s)
|
175
|
-
refute_nil(rows.to_xml)
|
176
|
-
refute_nil(rows.to_json)
|
177
|
-
refute_nil(rows.to_yaml)
|
178
|
-
assert_equal(3, rows.length)
|
179
|
-
rows = d.lookup("8.8.8.8")
|
180
|
-
refute_nil(rows)
|
181
|
-
refute_nil(rows.to_s)
|
182
|
-
refute_nil(rows.to_xml)
|
183
|
-
refute_nil(rows.to_json)
|
184
|
-
refute_nil(rows.to_yaml)
|
185
|
-
end
|
186
|
-
|
187
87
|
def test_passivetotal
|
188
88
|
PassiveDNS::Client.new(['passivetotal'])
|
189
89
|
d = PassiveDNS::Provider::PassiveTotal.new(@cp['passivetotal'] || {})
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passivedns-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- chrislee35
|
@@ -127,14 +127,10 @@ files:
|
|
127
127
|
- lib/passivedns/client.rb
|
128
128
|
- lib/passivedns/client/cli.rb
|
129
129
|
- lib/passivedns/client/passivedb.rb
|
130
|
-
- lib/passivedns/client/provider/bfk.rb
|
131
130
|
- lib/passivedns/client/provider/circl.rb
|
132
|
-
- lib/passivedns/client/provider/cn360.rb
|
133
131
|
- lib/passivedns/client/provider/dnsdb.rb
|
134
|
-
- lib/passivedns/client/provider/mnemonic.rb
|
135
132
|
- lib/passivedns/client/provider/passivetotal.rb
|
136
133
|
- lib/passivedns/client/provider/riskiq.rb
|
137
|
-
- lib/passivedns/client/provider/tcpiputils.rb
|
138
134
|
- lib/passivedns/client/provider/virustotal.rb
|
139
135
|
- lib/passivedns/client/state.rb
|
140
136
|
- lib/passivedns/client/version.rb
|
@@ -1,109 +0,0 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
|
3
|
-
module PassiveDNS #:nodoc: don't document this
|
4
|
-
# The Provider module contains all the Passive DNS provider client code
|
5
|
-
module Provider
|
6
|
-
|
7
|
-
# Queries BFK.de's passive DNS database
|
8
|
-
class BFK < PassiveDB
|
9
|
-
# Sets the modules self-reported name to "BFK.de"
|
10
|
-
def self.name
|
11
|
-
"BFK.de"
|
12
|
-
end
|
13
|
-
# Sets the configuration section name to "bfk"
|
14
|
-
def self.config_section_name
|
15
|
-
"bfk"
|
16
|
-
end
|
17
|
-
# Sets the command line database argument to "b"
|
18
|
-
def self.option_letter
|
19
|
-
"b"
|
20
|
-
end
|
21
|
-
|
22
|
-
# :debug enables verbose logging to standard output
|
23
|
-
attr_accessor :debug
|
24
|
-
# === Options
|
25
|
-
# * :debug Sets the debug flag for the module
|
26
|
-
# * "URL" Alternate url for testing. Defaults to "http://www.bfk.de/bfk_dnslogger.html?query="
|
27
|
-
#
|
28
|
-
# === Example Instantiation
|
29
|
-
#
|
30
|
-
# options = {
|
31
|
-
# :debug => true,
|
32
|
-
# "URL" => "http://www.bfk.de/bfk_dnslogger.html?query="
|
33
|
-
# }
|
34
|
-
#
|
35
|
-
# PassiveDNS::Provider::BFK.new(options)
|
36
|
-
#
|
37
|
-
def initialize(options={})
|
38
|
-
@debug = options[:debug] || false
|
39
|
-
@timeout = options[:timeout] || 20
|
40
|
-
@base = options["URL"] || "http://www.bfk.de/bfk_dnslogger.html?query="
|
41
|
-
raise "Due to the EU GDPR policy, this service has been shut down until further notice."
|
42
|
-
end
|
43
|
-
|
44
|
-
# Takes a label (either a domain or an IP address) and returns
|
45
|
-
# an array of PassiveDNS::PDNSResult instances with the answers to the query
|
46
|
-
def lookup(label, limit=nil)
|
47
|
-
$stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
|
48
|
-
Timeout::timeout(@timeout) {
|
49
|
-
t1 = Time.now
|
50
|
-
open(
|
51
|
-
@base+label,
|
52
|
-
"User-Agent" => "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}"
|
53
|
-
) do |f|
|
54
|
-
t2 = Time.now
|
55
|
-
recs = parse(f.read,t2-t1)
|
56
|
-
if limit
|
57
|
-
recs[0,limit]
|
58
|
-
else
|
59
|
-
recs
|
60
|
-
end
|
61
|
-
end
|
62
|
-
}
|
63
|
-
rescue Timeout::Error
|
64
|
-
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
# parses the webpage returned by BFK to generate an array of PDNSResult
|
70
|
-
def parse(page,response_time)
|
71
|
-
line = page.unpack('C*').pack('U*').split(/<table/).grep(/ id=\"logger\"/)
|
72
|
-
return [] unless line.length > 0
|
73
|
-
line = line[0].gsub(/[\t\n]/,'').gsub(/<\/table.*/,'')
|
74
|
-
rows = line.split(/<tr.*?>/)
|
75
|
-
res = []
|
76
|
-
rows.collect do |row|
|
77
|
-
r = row.split(/<td>/).map{|x| x.gsub(/<.*?>/,'').gsub(/\&.*?;/,'')}[1,1000]
|
78
|
-
if r and r[0] =~ /\w/
|
79
|
-
# BFK includes the MX weight in the answer response. First, find the MX records,
|
80
|
-
# then dump the weight to present a consistent record name to the collecting
|
81
|
-
# array. Otherwise the other repositories will present the same answer and
|
82
|
-
# your results will become cluttered with duplicates.
|
83
|
-
if r[1] == "MX" then
|
84
|
-
# MX lines look like "5 mx.domain.tld", so split on the space and assign r[2] (:answer) to the latter part.
|
85
|
-
#s = r[2].split(/\w/).map{|x| x}[1,1000]
|
86
|
-
# r[2] = s[1]
|
87
|
-
r[2] =~ /[0-9]+?\s(.+)/
|
88
|
-
s=$1
|
89
|
-
#puts "DEBUG: == BFK: MX Parsing Strip: Answer: " + r[2] + " : mod: " + s if @debug
|
90
|
-
r[2] = s
|
91
|
-
|
92
|
-
######### FIX BLANKS FOR MX
|
93
|
-
|
94
|
-
end
|
95
|
-
query = r[0]
|
96
|
-
answer = r[2]
|
97
|
-
rrtype = r[1]
|
98
|
-
res << PDNSResult.new(self.class.name,response_time,query,answer,rrtype,'white')
|
99
|
-
end
|
100
|
-
end
|
101
|
-
res
|
102
|
-
rescue Exception => e
|
103
|
-
$stderr.puts "#{self.class.name} Exception: #{e}"
|
104
|
-
raise e
|
105
|
-
end
|
106
|
-
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
@@ -1,122 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
require 'net/https'
|
3
|
-
require 'openssl'
|
4
|
-
require 'json'
|
5
|
-
require 'digest/md5'
|
6
|
-
require 'pp'
|
7
|
-
|
8
|
-
module PassiveDNS #:nodoc: don't document this
|
9
|
-
# The Provider module contains all the Passive DNS provider client code
|
10
|
-
module Provider
|
11
|
-
# Queries 360.cn's passive DNS database
|
12
|
-
class CN360 < PassiveDB
|
13
|
-
# Sets the modules self-reported name to "360.cn"
|
14
|
-
def self.name
|
15
|
-
"360.cn"
|
16
|
-
end
|
17
|
-
# Sets the configuration section name to "cn360"
|
18
|
-
def self.config_section_name
|
19
|
-
"cn360"
|
20
|
-
end
|
21
|
-
# Sets the command line database argument to "3"
|
22
|
-
def self.option_letter
|
23
|
-
"3"
|
24
|
-
end
|
25
|
-
|
26
|
-
# :debug enables verbose logging to standard output
|
27
|
-
attr_accessor :debug
|
28
|
-
# === Options
|
29
|
-
# * :debug Sets the debug flag for the module
|
30
|
-
# * "API" REQUIRED: http://some.web.address.for.their.api
|
31
|
-
# * "API_ID" REQUIRED: a username that is given when you register
|
32
|
-
# * "API_KEY" REQUIRED: a long and random password of sorts that is used along with the page request to generate a per page API key
|
33
|
-
#
|
34
|
-
# === Example Instantiation
|
35
|
-
#
|
36
|
-
# options = {
|
37
|
-
# :debug => true,
|
38
|
-
# "API" => "http://some.web.address.for.their.api",
|
39
|
-
# "API_ID" => "360user",
|
40
|
-
# "API_KEY" => "360apikey"
|
41
|
-
# }
|
42
|
-
#
|
43
|
-
# PassiveDNS::Provider::CN360.new(options)
|
44
|
-
#
|
45
|
-
def initialize(options={})
|
46
|
-
@debug = options[:debug] || false
|
47
|
-
@timeout = options[:timeout] || 20
|
48
|
-
["API", "API_ID", "API_KEY"].each do |opt|
|
49
|
-
if not options[opt]
|
50
|
-
raise "Field #{opt} is required. See README.md"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
@cp = options
|
54
|
-
end
|
55
|
-
|
56
|
-
# Takes a label (either a domain or an IP address) and returns
|
57
|
-
# an array of PassiveDNS::PDNSResult instances with the answers to the query
|
58
|
-
def lookup(label, limit=10000)
|
59
|
-
table = "rrset"
|
60
|
-
if label =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ or label =~ /^[0-9a-fA-F]+:[0-9a-fA-F:]+[0-9a-fA-F]$/
|
61
|
-
table = "rdata"
|
62
|
-
end
|
63
|
-
limit ||= 10000
|
64
|
-
path = "/api/#{table}/keyword/#{label}/count/#{limit}/"
|
65
|
-
Timeout::timeout(@timeout) {
|
66
|
-
url = @cp["API"]+path
|
67
|
-
url = URI.parse url
|
68
|
-
http = Net::HTTP.new(url.host, url.port)
|
69
|
-
http.use_ssl = (url.scheme == 'https')
|
70
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # I hate doing this
|
71
|
-
http.verify_depth = 5
|
72
|
-
request = Net::HTTP::Get.new(url.path)
|
73
|
-
request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
|
74
|
-
request.add_field('Accept', 'application/json')
|
75
|
-
request.add_field("X-BashTokid", @cp["API_ID"])
|
76
|
-
token = Digest::MD5.hexdigest(path+@cp["API_KEY"])
|
77
|
-
$stderr.puts "DEBUG: cn360 url = #{url} token = #{token}" if @debug
|
78
|
-
request.add_field("X-BashToken", token)
|
79
|
-
t1 = Time.now
|
80
|
-
response = http.request(request)
|
81
|
-
t2 = Time.now
|
82
|
-
recs = parse_json(response.body, label, t2-t1)
|
83
|
-
if limit
|
84
|
-
recs[0,limit]
|
85
|
-
else
|
86
|
-
recs
|
87
|
-
end
|
88
|
-
}
|
89
|
-
rescue Timeout::Error
|
90
|
-
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
91
|
-
recs
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
# parses the response of 360.cn's JSON reply to generate an array of PDNSResult
|
97
|
-
def parse_json(page,query,response_time=0)
|
98
|
-
res = []
|
99
|
-
data = JSON.parse(page)
|
100
|
-
if data.class == Hash and data['err']
|
101
|
-
raise "#{self.class.name} Error: #{data['err']}"
|
102
|
-
end
|
103
|
-
data.each do |row|
|
104
|
-
time_first = (row["time_first"]) ? Time.at(row["time_first"]) : nil
|
105
|
-
time_last = (row["time_last"]) ? Time.at(row["time_last"]) : nil
|
106
|
-
count = row["count"] || 0
|
107
|
-
query = row["rrname"]
|
108
|
-
answers = row["rdata"].gsub(/;$/,'').split(/;/)
|
109
|
-
rrtype = row["rrtype"]
|
110
|
-
answers.each do |answer|
|
111
|
-
res << PDNSResult.new(self.class.name, response_time, query, answer, rrtype, nil, time_first, time_last, count, TLPSecurityControl.new('yellow'))
|
112
|
-
end
|
113
|
-
end
|
114
|
-
res
|
115
|
-
rescue Exception => e
|
116
|
-
$stderr.puts "#{self.class.name} Exception: #{e}"
|
117
|
-
puts e.backtrace
|
118
|
-
raise e
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
@@ -1,112 +0,0 @@
|
|
1
|
-
# DESCRIPTION: Module to query Mnemonic's passive DNS repository
|
2
|
-
# CONTRIBUTOR: Drew Hunt (pinowudi@yahoo.com)
|
3
|
-
require 'net/http'
|
4
|
-
require 'net/https'
|
5
|
-
require 'openssl'
|
6
|
-
|
7
|
-
module PassiveDNS #:nodoc: don't document this
|
8
|
-
# The Provider module contains all the Passive DNS provider client code
|
9
|
-
module Provider
|
10
|
-
# Queries Mnemonic's passive DNS database
|
11
|
-
class Mnemonic < PassiveDB
|
12
|
-
# Sets the modules self-reported name to "Mnemonic"
|
13
|
-
def self.name
|
14
|
-
"Mnemonic"
|
15
|
-
end
|
16
|
-
# Sets the configuration section name to "mnemonic"
|
17
|
-
def self.config_section_name
|
18
|
-
"mnemonic"
|
19
|
-
end
|
20
|
-
# Sets the command line database argument to "m"
|
21
|
-
def self.option_letter
|
22
|
-
"m"
|
23
|
-
end
|
24
|
-
|
25
|
-
# :debug enables verbose logging to standard output
|
26
|
-
attr_accessor :debug
|
27
|
-
# === Options
|
28
|
-
# * :debug Sets the debug flag for the module
|
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
|
-
#
|
32
|
-
# === Example Instantiation
|
33
|
-
#
|
34
|
-
# options = {
|
35
|
-
# :debug => true,
|
36
|
-
# "APIKEY" => "01234567890abcdef01234567890abcdef012345",
|
37
|
-
# "URL" => "https://api.mnemonic.no/pdns/v3/"
|
38
|
-
# }
|
39
|
-
#
|
40
|
-
# PassiveDNS::Provider::Mnemonic.new(options)
|
41
|
-
#
|
42
|
-
def initialize(options={})
|
43
|
-
@debug = options[:debug] || false
|
44
|
-
@timeout = options[:timeout] || 20
|
45
|
-
@apikey = options["APIKEY"]
|
46
|
-
@url = options["URL"] || "https://api.mnemonic.no/pdns/v3/"
|
47
|
-
if @url == "https://passivedns.mnemonic.no/api1/?apikey="
|
48
|
-
@url = "https://api.mnemonic.no/pdns/v3/"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# Takes a label (either a domain or an IP address) and returns
|
53
|
-
# an array of PassiveDNS::PDNSResult instances with the answers to the query
|
54
|
-
def lookup(label, limit=nil)
|
55
|
-
$stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
|
56
|
-
Timeout::timeout(@timeout) {
|
57
|
-
url = "#{@url}#{label}"
|
58
|
-
$stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
|
59
|
-
url = URI.parse url
|
60
|
-
http = Net::HTTP.new(url.host, url.port)
|
61
|
-
http.use_ssl = (url.scheme == 'https')
|
62
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
63
|
-
http.verify_depth = 5
|
64
|
-
request = Net::HTTP::Get.new(url.path)
|
65
|
-
request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
|
66
|
-
if @apikey
|
67
|
-
request.add_field("Argus-API-Key", @apikey)
|
68
|
-
end
|
69
|
-
t1 = Time.now
|
70
|
-
response = http.request(request)
|
71
|
-
t2 = Time.now
|
72
|
-
recs = parse_json(response.body, label, t2-t1)
|
73
|
-
if limit
|
74
|
-
recs[0,limit]
|
75
|
-
else
|
76
|
-
recs
|
77
|
-
end
|
78
|
-
}
|
79
|
-
rescue Timeout::Error
|
80
|
-
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
81
|
-
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
# parses the response of mnemonic's JSON reply to generate an array of PDNSResult
|
86
|
-
def parse_json(page,query,response_time=0)
|
87
|
-
res = []
|
88
|
-
data = JSON.parse(page)
|
89
|
-
if data['data']
|
90
|
-
data['data'].each do |row|
|
91
|
-
if row['query']
|
92
|
-
query = row['query']
|
93
|
-
answer = row['answer']
|
94
|
-
rrtype = row['rrtype'].upcase
|
95
|
-
ttl = row['maxTtl'].to_i
|
96
|
-
firstseen = Time.at(row['firstSeenTimestamp'].to_i / 1000)
|
97
|
-
lastseen = Time.at(row['lastSeenTimestamp'].to_i / 1000)
|
98
|
-
tlp = row['tlp']
|
99
|
-
r = PDNSResult.new(self.class.name,response_time, query, answer, rrtype, ttl, firstseen, lastseen, tlp)
|
100
|
-
res << r
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
res
|
105
|
-
rescue Exception => e
|
106
|
-
$stderr.puts "#{self.class.name} Exception: #{e}"
|
107
|
-
raise e
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
@@ -1,129 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
require 'net/https'
|
3
|
-
require 'openssl'
|
4
|
-
require 'json'
|
5
|
-
|
6
|
-
# Please read http://www.tcpiputils.com/terms-of-service under automated requests
|
7
|
-
|
8
|
-
module PassiveDNS #:nodoc: don't document this
|
9
|
-
# The Provider module contains all the Passive DNS provider client code
|
10
|
-
module Provider
|
11
|
-
# Queries TCPIPUtils's passive DNS database
|
12
|
-
class TCPIPUtils < PassiveDB
|
13
|
-
# Sets the modules self-reported name to "TCPIPUtils"
|
14
|
-
def self.name
|
15
|
-
"TCPIPUtils"
|
16
|
-
end
|
17
|
-
# Sets the configuration section name to "tcpiputils"
|
18
|
-
def self.config_section_name
|
19
|
-
"tcpiputils"
|
20
|
-
end
|
21
|
-
# Sets the command line database argument to "t"
|
22
|
-
def self.option_letter
|
23
|
-
"t"
|
24
|
-
end
|
25
|
-
|
26
|
-
# :debug enables verbose logging to standard output
|
27
|
-
attr_accessor :debug
|
28
|
-
# === Options
|
29
|
-
# * :debug Sets the debug flag for the module
|
30
|
-
# * "APIKEY" REQUIRED: The API key associated with TCPIPUtils
|
31
|
-
# * "URL" Alternate url for testing. Defaults to "https://www.utlsapi.com/api.php?version=1.0&apikey="
|
32
|
-
#
|
33
|
-
# === Example Instantiation
|
34
|
-
#
|
35
|
-
# options = {
|
36
|
-
# :debug => true,
|
37
|
-
# "APIKEY" => "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
38
|
-
# "URL" => "https://www.utlsapi.com/api.php?version=1.0&apikey="
|
39
|
-
# }
|
40
|
-
#
|
41
|
-
# PassiveDNS::Provider::TCPIPUtils.new(options)
|
42
|
-
#
|
43
|
-
def initialize(options={})
|
44
|
-
@debug = options[:debug] || false
|
45
|
-
@timeout = options[:timeout] || 20
|
46
|
-
@apikey = options["APIKEY"] || raise("#{self.class.name} requires an APIKEY. See README.md")
|
47
|
-
@url = options["URL"] || "https://www.utlsapi.com/api.php?version=1.0&apikey="
|
48
|
-
end
|
49
|
-
|
50
|
-
# Takes a label (either a domain or an IP address) and returns
|
51
|
-
# an array of PassiveDNS::PDNSResult instances with the answers to the query
|
52
|
-
def lookup(label, limit=nil)
|
53
|
-
$stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
|
54
|
-
type = (label.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)) ? "domainneighbors" : "domainipdnshistory"
|
55
|
-
url = "#{@url}#{@apikey}&type=#{type}&q=#{label}"
|
56
|
-
recs = []
|
57
|
-
Timeout::timeout(@timeout) {
|
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+"?"+url.query)
|
64
|
-
request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
|
65
|
-
t1 = Time.now
|
66
|
-
response = http.request(request)
|
67
|
-
delta = (Time.now - t1).to_f
|
68
|
-
reply = JSON.parse(response.body)
|
69
|
-
if reply["status"] and reply["status"] == "succeed"
|
70
|
-
question = reply["data"]["question"]
|
71
|
-
recs = format_recs(reply["data"], question, delta)
|
72
|
-
elsif reply["status"] and reply["status"] == "error"
|
73
|
-
raise "#{self.class.name}: error from web API: #{reply["data"]}"
|
74
|
-
end
|
75
|
-
if limit
|
76
|
-
recs[0,limit]
|
77
|
-
else
|
78
|
-
recs
|
79
|
-
end
|
80
|
-
}
|
81
|
-
rescue Timeout::Error
|
82
|
-
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
|
87
|
-
# translates the data structure derived from of tcpiputils's JSON reply
|
88
|
-
def format_recs(reply_data, question, delta)
|
89
|
-
recs = []
|
90
|
-
fieldname = nil
|
91
|
-
rrtype = nil
|
92
|
-
add_records = false
|
93
|
-
reply_data.each do |key, data|
|
94
|
-
case key
|
95
|
-
when "ipv4"
|
96
|
-
fieldname = "ip"
|
97
|
-
rrtype = "A"
|
98
|
-
add_records = true
|
99
|
-
when "ipv6"
|
100
|
-
fieldname = "ip"
|
101
|
-
rrtype = "AAAA"
|
102
|
-
add_records = true
|
103
|
-
when "dns"
|
104
|
-
fieldname = "dns"
|
105
|
-
rrtype = "NS"
|
106
|
-
add_records = true
|
107
|
-
when "mx"
|
108
|
-
fieldname = "dns"
|
109
|
-
rrtype = "MX"
|
110
|
-
add_records = true
|
111
|
-
when "domains"
|
112
|
-
data.each do |rec|
|
113
|
-
lastseen = (rec["updatedate"]) ? Date.parse(rec["updatedate"]) : nil
|
114
|
-
recs << PDNSResult.new(self.class.name, delta, rec, question, "A", nil, nil, lastseen, nil, 'yellow')
|
115
|
-
end
|
116
|
-
end
|
117
|
-
if add_records
|
118
|
-
data.each do |rec|
|
119
|
-
lastseen = (rec["updatedate"]) ? Date.parse(rec["updatedate"]) : nil
|
120
|
-
recs << PDNSResult.new(self.class.name, delta, question, rec[fieldname], rrtype, nil, nil, lastseen, nil, 'yellow')
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
recs
|
125
|
-
end
|
126
|
-
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|