dnstraverse 0.0.1

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.
Files changed (144) hide show
  1. data/LICENSE +674 -0
  2. data/README +4 -0
  3. data/Rakefile +19 -0
  4. data/a +44 -0
  5. data/bin/dnstraverse +300 -0
  6. data/doc.tar +0 -0
  7. data/doc/classes/DNSTraverse.html +198 -0
  8. data/doc/classes/DNSTraverse/CachingResolver.html +172 -0
  9. data/doc/classes/DNSTraverse/CachingResolver.src/M000055.html +21 -0
  10. data/doc/classes/DNSTraverse/CachingResolver.src/M000056.html +42 -0
  11. data/doc/classes/DNSTraverse/DecodedQuery.html +475 -0
  12. data/doc/classes/DNSTraverse/DecodedQuery.src/M000020.html +34 -0
  13. data/doc/classes/DNSTraverse/DecodedQuery.src/M000021.html +23 -0
  14. data/doc/classes/DNSTraverse/DecodedQuery.src/M000022.html +19 -0
  15. data/doc/classes/DNSTraverse/DecodedQuery.src/M000023.html +33 -0
  16. data/doc/classes/DNSTraverse/DecodedQuery.src/M000024.html +26 -0
  17. data/doc/classes/DNSTraverse/DecodedQuery.src/M000025.html +24 -0
  18. data/doc/classes/DNSTraverse/DecodedQuery.src/M000026.html +29 -0
  19. data/doc/classes/DNSTraverse/DecodedQuery.src/M000027.html +19 -0
  20. data/doc/classes/DNSTraverse/DecodedQuery.src/M000028.html +18 -0
  21. data/doc/classes/DNSTraverse/DecodedQuery.src/M000029.html +32 -0
  22. data/doc/classes/DNSTraverse/DecodedQuery.src/M000030.html +19 -0
  23. data/doc/classes/DNSTraverse/DecodedQuery.src/M000031.html +19 -0
  24. data/doc/classes/DNSTraverse/DecodedQuery.src/M000032.html +20 -0
  25. data/doc/classes/DNSTraverse/DecodedQuery.src/M000033.html +31 -0
  26. data/doc/classes/DNSTraverse/DecodedQueryCache.html +182 -0
  27. data/doc/classes/DNSTraverse/DecodedQueryCache.src/M000063.html +21 -0
  28. data/doc/classes/DNSTraverse/DecodedQueryCache.src/M000064.html +33 -0
  29. data/doc/classes/DNSTraverse/Fingerprint.html +277 -0
  30. data/doc/classes/DNSTraverse/Fingerprint.src/M000047.html +29 -0
  31. data/doc/classes/DNSTraverse/Fingerprint.src/M000048.html +18 -0
  32. data/doc/classes/DNSTraverse/Fingerprint.src/M000049.html +57 -0
  33. data/doc/classes/DNSTraverse/Fingerprint.src/M000050.html +28 -0
  34. data/doc/classes/DNSTraverse/Fingerprint.src/M000051.html +27 -0
  35. data/doc/classes/DNSTraverse/Fingerprint.src/M000052.html +35 -0
  36. data/doc/classes/DNSTraverse/Fingerprint.src/M000053.html +24 -0
  37. data/doc/classes/DNSTraverse/Fingerprint.src/M000054.html +29 -0
  38. data/doc/classes/DNSTraverse/InfoCache.html +235 -0
  39. data/doc/classes/DNSTraverse/InfoCache.src/M000034.html +20 -0
  40. data/doc/classes/DNSTraverse/InfoCache.src/M000035.html +23 -0
  41. data/doc/classes/DNSTraverse/InfoCache.src/M000036.html +28 -0
  42. data/doc/classes/DNSTraverse/InfoCache.src/M000037.html +25 -0
  43. data/doc/classes/DNSTraverse/InfoCache.src/M000038.html +27 -0
  44. data/doc/classes/DNSTraverse/InfoCache.src/M000039.html +33 -0
  45. data/doc/classes/DNSTraverse/MessageUtility.html +275 -0
  46. data/doc/classes/DNSTraverse/MessageUtility.src/M000011.html +35 -0
  47. data/doc/classes/DNSTraverse/MessageUtility.src/M000012.html +37 -0
  48. data/doc/classes/DNSTraverse/MessageUtility.src/M000013.html +28 -0
  49. data/doc/classes/DNSTraverse/MessageUtility.src/M000014.html +27 -0
  50. data/doc/classes/DNSTraverse/MessageUtility.src/M000015.html +30 -0
  51. data/doc/classes/DNSTraverse/MessageUtility.src/M000016.html +32 -0
  52. data/doc/classes/DNSTraverse/MessageUtility.src/M000017.html +34 -0
  53. data/doc/classes/DNSTraverse/MessageUtility.src/M000018.html +23 -0
  54. data/doc/classes/DNSTraverse/MessageUtility.src/M000019.html +36 -0
  55. data/doc/classes/DNSTraverse/Referral.html +641 -0
  56. data/doc/classes/DNSTraverse/Referral.src/M000065.html +22 -0
  57. data/doc/classes/DNSTraverse/Referral.src/M000066.html +21 -0
  58. data/doc/classes/DNSTraverse/Referral.src/M000067.html +23 -0
  59. data/doc/classes/DNSTraverse/Referral.src/M000068.html +19 -0
  60. data/doc/classes/DNSTraverse/Referral.src/M000069.html +18 -0
  61. data/doc/classes/DNSTraverse/Referral.src/M000070.html +54 -0
  62. data/doc/classes/DNSTraverse/Referral.src/M000071.html +25 -0
  63. data/doc/classes/DNSTraverse/Referral.src/M000072.html +27 -0
  64. data/doc/classes/DNSTraverse/Referral.src/M000073.html +23 -0
  65. data/doc/classes/DNSTraverse/Referral.src/M000074.html +20 -0
  66. data/doc/classes/DNSTraverse/Referral.src/M000075.html +40 -0
  67. data/doc/classes/DNSTraverse/Referral.src/M000076.html +52 -0
  68. data/doc/classes/DNSTraverse/Referral.src/M000077.html +29 -0
  69. data/doc/classes/DNSTraverse/Referral.src/M000078.html +54 -0
  70. data/doc/classes/DNSTraverse/Referral.src/M000079.html +18 -0
  71. data/doc/classes/DNSTraverse/Referral.src/M000080.html +22 -0
  72. data/doc/classes/DNSTraverse/Referral.src/M000081.html +20 -0
  73. data/doc/classes/DNSTraverse/Referral.src/M000082.html +29 -0
  74. data/doc/classes/DNSTraverse/Referral.src/M000083.html +28 -0
  75. data/doc/classes/DNSTraverse/Referral.src/M000084.html +29 -0
  76. data/doc/classes/DNSTraverse/Referral.src/M000085.html +55 -0
  77. data/doc/classes/DNSTraverse/Referral.src/M000086.html +30 -0
  78. data/doc/classes/DNSTraverse/Referral.src/M000087.html +24 -0
  79. data/doc/classes/DNSTraverse/Referral.src/M000088.html +20 -0
  80. data/doc/classes/DNSTraverse/Referral.src/M000089.html +58 -0
  81. data/doc/classes/DNSTraverse/ResolveError.html +111 -0
  82. data/doc/classes/DNSTraverse/Response.html +271 -0
  83. data/doc/classes/DNSTraverse/Response.src/M000057.html +27 -0
  84. data/doc/classes/DNSTraverse/Response.src/M000058.html +21 -0
  85. data/doc/classes/DNSTraverse/Response.src/M000059.html +19 -0
  86. data/doc/classes/DNSTraverse/Response.src/M000060.html +21 -0
  87. data/doc/classes/DNSTraverse/Response.src/M000061.html +31 -0
  88. data/doc/classes/DNSTraverse/Response.src/M000062.html +23 -0
  89. data/doc/classes/DNSTraverse/Response/NoGlue.html +222 -0
  90. data/doc/classes/DNSTraverse/Response/NoGlue.src/M000007.html +32 -0
  91. data/doc/classes/DNSTraverse/Response/NoGlue.src/M000008.html +18 -0
  92. data/doc/classes/DNSTraverse/Response/NoGlue.src/M000009.html +18 -0
  93. data/doc/classes/DNSTraverse/Response/NoGlue.src/M000010.html +18 -0
  94. data/doc/classes/DNSTraverse/Traverser.html +247 -0
  95. data/doc/classes/DNSTraverse/Traverser.src/M000040.html +17 -0
  96. data/doc/classes/DNSTraverse/Traverser.src/M000041.html +52 -0
  97. data/doc/classes/DNSTraverse/Traverser.src/M000042.html +61 -0
  98. data/doc/classes/DNSTraverse/Traverser.src/M000043.html +110 -0
  99. data/doc/classes/DNSTraverse/Traverser.src/M000044.html +63 -0
  100. data/doc/classes/DNSTraverse/Traverser.src/M000045.html +28 -0
  101. data/doc/classes/DNSTraverse/Traverser.src/M000046.html +18 -0
  102. data/doc/classes/FingerprintRules.html +175 -0
  103. data/doc/classes/Log.html +174 -0
  104. data/doc/classes/Log.src/M000002.html +18 -0
  105. data/doc/classes/Log.src/M000003.html +18 -0
  106. data/doc/classes/Log.src/M000004.html +18 -0
  107. data/doc/classes/Log/Formatter.html +165 -0
  108. data/doc/classes/Log/Formatter.src/M000005.html +22 -0
  109. data/doc/classes/Log/Formatter.src/M000006.html +24 -0
  110. data/doc/classes/TestFingerprint.html +137 -0
  111. data/doc/classes/TestFingerprint.src/M000001.html +22 -0
  112. data/doc/created.rid +1 -0
  113. data/doc/files/lib/dnstraverse/caching_resolver_rb.html +132 -0
  114. data/doc/files/lib/dnstraverse/decoded_query_cache_rb.html +132 -0
  115. data/doc/files/lib/dnstraverse/decoded_query_rb.html +132 -0
  116. data/doc/files/lib/dnstraverse/fingerprint_rb.html +134 -0
  117. data/doc/files/lib/dnstraverse/fingerprint_rules_rb.html +143 -0
  118. data/doc/files/lib/dnstraverse/info_cache_rb.html +131 -0
  119. data/doc/files/lib/dnstraverse/log_rb.html +131 -0
  120. data/doc/files/lib/dnstraverse/message_utility_rb.html +124 -0
  121. data/doc/files/lib/dnstraverse/referral_rb.html +134 -0
  122. data/doc/files/lib/dnstraverse/response_noglue_rb.html +124 -0
  123. data/doc/files/lib/dnstraverse/response_rb.html +132 -0
  124. data/doc/files/lib/dnstraverse/traverser_rb.html +137 -0
  125. data/doc/files/test/test_fingerprint_rb.html +133 -0
  126. data/doc/fr_class_index.html +43 -0
  127. data/doc/fr_file_index.html +39 -0
  128. data/doc/fr_method_index.html +115 -0
  129. data/doc/index.html +24 -0
  130. data/doc/rdoc-style.css +208 -0
  131. data/lib/dnstraverse/caching_resolver.rb +63 -0
  132. data/lib/dnstraverse/decoded_query.rb +199 -0
  133. data/lib/dnstraverse/decoded_query_cache.rb +53 -0
  134. data/lib/dnstraverse/fingerprint.rb +166 -0
  135. data/lib/dnstraverse/fingerprint_rules.rb +389 -0
  136. data/lib/dnstraverse/info_cache.rb +108 -0
  137. data/lib/dnstraverse/log.rb +55 -0
  138. data/lib/dnstraverse/message_utility.rb +199 -0
  139. data/lib/dnstraverse/referral.rb +463 -0
  140. data/lib/dnstraverse/response.rb +92 -0
  141. data/lib/dnstraverse/response_noglue.rb +54 -0
  142. data/lib/dnstraverse/traverser.rb +291 -0
  143. data/test/test_fingerprint.rb +29 -0
  144. metadata +231 -0
@@ -0,0 +1,199 @@
1
+ # DNSTraverse traverses the DNS to show statistics and information
2
+ # Copyright (C) 2008 James Ponder
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3 of the License.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'dnstraverse/info_cache'
17
+ require 'dnstraverse/log'
18
+
19
+ module DNSTraverse
20
+
21
+ class DecodedQuery
22
+
23
+ include MessageUtility
24
+
25
+ attr_reader :message, :bailiwick, :infocache
26
+ attr_reader :qname, :qclass, :qtype, :ip
27
+ attr_reader :endname
28
+ attr_reader :status
29
+ attr_reader :cacheable_good, :cacheable_bad
30
+ attr_reader :auth_ns, :auth_soa, :auth_other # authority info
31
+ attr_reader :exception_message, :error_message # :exception/:error only
32
+ attr_reader :answers # :answered only
33
+ attr_reader :authoritynames # auth_ns converted to array of strings
34
+ # attr_reader :stats_key
35
+
36
+ def initialize(args)
37
+ @message = args[:message] || nil # skip query - use this message/exception
38
+ @qname = args[:qname] # the query name
39
+ @qclass = args[:qclass] # the query class
40
+ @qtype = args[:qtype] # the query type
41
+ @ip = args[:ip] # the nameserver to query (was queried if :message passed)
42
+ @resolver = args[:resolver] # Dnsruby::Resolver / CachingResolver object
43
+ @bailiwick = args[:bailiwick] # the bailiwick in force
44
+ @cacheable_good = Hash.new # in-bailiwick records
45
+ @cacheable_bad = Hash.new # out-of-bailiwick records
46
+ @auth_ns = nil # NS RR records in authority section
47
+ @auth_soa = nil # SOA RR records in authority section
48
+ @auth_other = nil # Other RR records in authority section
49
+ @answers = nil # Answers, if :answered
50
+ @warnings = nil # Warnings if there are any (array)
51
+ query unless @message
52
+ process
53
+ return self
54
+ end
55
+
56
+ def warnings_add(warning)
57
+ @warnings = [] unless @warnings
58
+ if warning.is_a? Array then
59
+ @warnings.concat warning
60
+ else
61
+ @warnings.push warning
62
+ end
63
+ end
64
+
65
+ def makequery_with_udpsize(udpsize)
66
+ @resolver.udp_size = udpsize
67
+ return @resolver.query(@qname, @qtype)
68
+ end
69
+
70
+ # make a query
71
+ # start with whatever UDP size is configured in resolver
72
+ # fall-back to UDP size 512 if appropriate
73
+ def makequery_message
74
+ my_udp_size = @resolver.udp_size
75
+ message = makequery_with_udpsize(my_udp_size)
76
+ return message if message.is_a? Exception
77
+ return message if my_udp_size == 512
78
+ return message if (message.rcode != Dnsruby::RCode.FORMERR and
79
+ message.rcode != Dnsruby::RCode.NOTIMP and
80
+ message.rcode != Dnsruby::RCode.SERVFAIL)
81
+ Log.debug { "Possible failure by nameserver to understand EDNS0 - retry" }
82
+ message_retry = makequery_with_udpsize(512)
83
+ @resolver.udp_size = my_udp_size
84
+ return message if message_retry.is_a? Exception
85
+ return message if (message_retry.rcode == Dnsruby::RCode.FORMERR or
86
+ message_retry.rcode == Dnsruby::RCode.NOTIMP or
87
+ message_retry.rcode == Dnsruby::RCode.SERVFAIL)
88
+ warnings_add "#{message.answerfrom} doesn't seem to support EDNS0"
89
+ return message_retry
90
+ end
91
+
92
+ def query
93
+ Log.debug { "Querying #{@ip} for #{@qname}/#{@qclass}/#{@qtype}" }
94
+ @resolver.nameserver = ip
95
+ @message = makequery_message
96
+ unless @message.is_a? Exception then
97
+ msg_validate(message, :qname => @qname, :qclass => @qclass,
98
+ :qtype => @qtype)
99
+ warnings_add msg_comment(message, :want_recursion => false)
100
+ end
101
+ return @message
102
+ end
103
+
104
+ # # clean up the workings
105
+ # def cleanup
106
+ # @cacheable_good = @cacheable_bad = nil
107
+ # @starters = @starters_bailiwick = nil
108
+ # @auth_ns = @auth_soa = @auth_other = nil
109
+ # end
110
+
111
+ def inside_bailiwick?(name)
112
+ return true if @bailiwick.nil?
113
+ bwend = ".#{@bailiwick}"
114
+ namestr = name.to_s
115
+ return true if namestr.casecmp(@bailiwick) == 0
116
+ return true if namestr =~ /#{bwend}$/i
117
+ Log.debug { "#{namestr} is not inside bailiwick #{@bailiwick}" }
118
+ return false
119
+ end
120
+
121
+ NOERROR = Dnsruby::RCode.NOERROR
122
+ NXDOMAIN = Dnsruby::RCode.NXDOMAIN
123
+
124
+ def process
125
+ return process_exception if @message.is_a? Exception
126
+ @auth_ns, @auth_soa, @auth_other = msg_authority(@message)
127
+ @cacheable_good, @cacheable_bad = msg_cacheable(@message, @bailiwick)
128
+ @endname = msg_follow_cnames(@message, :qname => @qname, :qtype => @qtype,
129
+ :bailiwick => @bailiwick)
130
+ return process_restart unless inside_bailiwick?(@endname)
131
+ return process_error if @message.rcode != NOERROR
132
+ @answers = msg_answers?(@message, :qname => @endname, :qtype => qtype)
133
+ return process_answered if @answers
134
+ return process_nodata if @auth_soa.size > 0 or @auth_ns.size == 0
135
+ return process_referral unless @auth_ns.empty?
136
+ return process_restart
137
+ end
138
+
139
+ def process_exception
140
+ @status = :exception
141
+ @exception_message = @message.to_s
142
+ end
143
+
144
+ def process_restart
145
+ @status = :restart
146
+ end
147
+
148
+ def process_error
149
+ @status = :error
150
+ case @message.rcode
151
+ when Dnsruby::RCode::FORMERR
152
+ @error_message = "Formate error (FORMERR)"
153
+ when Dnsruby::RCode::SERVFAIL
154
+ @error_message = "Server failure (SERVFAIL)"
155
+ when Dnsruby::RCode::NXDOMAIN
156
+ @error_message = "No such domain (NXDOMAIN)"
157
+ when NOTIMP
158
+ @error_message = "Not implemented (NOTIMP)"
159
+ when REFUSED
160
+ @error_message = "Refused"
161
+ else
162
+ @error_message = @message.rcode.to_s
163
+ end
164
+ end
165
+
166
+ def process_answered
167
+ @status = :answered
168
+ return self
169
+ end
170
+
171
+ def process_nodata
172
+ @status = :nodata
173
+ return self
174
+ end
175
+
176
+ def process_referral
177
+ @status = :referral
178
+ @authoritynames = @auth_ns.map { |rr| rr.domainname.to_s.downcase }
179
+ return self
180
+ end
181
+
182
+ def to_s
183
+ case @status
184
+ when :error
185
+ return "Error: #{@error_message}"
186
+ when :exception
187
+ return "Exception: #{@exception_message}"
188
+ when :nodata
189
+ return "No data"
190
+ when :answered
191
+ return "Answered (#{@answers.size} entries)"
192
+ when :referral
193
+ return "Referral to #{@authoritynames.join(',')}"
194
+ when :restart
195
+ return "Query re-start with #{@endname}"
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,53 @@
1
+ # DNSTraverse traverses the DNS to show statistics and information
2
+ # Copyright (C) 2008 James Ponder
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3 of the License.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'dnstraverse/log'
17
+ require 'dnstraverse/decoded_query'
18
+
19
+ module DNSTraverse
20
+
21
+ class DecodedQueryCache
22
+
23
+ attr_reader :requests, :cache_hits, :resolver, :cache
24
+
25
+ def initialize(args)
26
+ @resolver = args[:resolver] || raise("Must pass resolver")
27
+ @cache = Hash.new
28
+ @requests = 0
29
+ @cache_hits = 0
30
+ end
31
+
32
+ def query(args)
33
+ qname = args[:qname] || raise("Must pass qname")
34
+ qclass = args[:qclass] || raise("Must pass qclass")
35
+ qtype = args[:qtype] || raise("Must pass qtype")
36
+ ip = args[:ip] || raise("Must pass ip")
37
+ bailiwick = args[:bailiwick] # could be nil
38
+ key = "key:dqc:#{ip}:#{qname}:#{qclass}:#{qtype}:#{bailiwick}"
39
+ Log.debug { "Decoded Query Cache query #{key}" }
40
+ if @cache.has_key?(key) then
41
+ Log.debug { "Decoded Query Cache hit: #{key}" }
42
+ @cache_hits+= 1
43
+ return @cache[key]
44
+ end
45
+ newargs = args.merge( { :resolver => @resolver } )
46
+ @cache[key] = DNSTraverse::DecodedQuery.new(newargs)
47
+ Log.debug { "Decoded Query Cache store: #{key}" }
48
+ return @cache[key]
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,166 @@
1
+ # DNSTraverse traverses the DNS to show statistics and information
2
+ # Copyright (C) 2008 James Ponder
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, version 3 of the License.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'dnstraverse/log'
17
+ require 'dnstraverse/fingerprint_rules'
18
+ require 'dnsruby'
19
+ require 'pp'
20
+
21
+ module DNSTraverse
22
+ class Fingerprint
23
+ include FingerprintRules
24
+
25
+ FINGERPRINT_TIMEOUT = 'query timed out'.freeze
26
+
27
+ attr_accessor :version_style # :none, :override, :append
28
+
29
+ def initialize(args = {})
30
+ @version_style = args[:version_style] || :append
31
+ cfg = Dnsruby::Config.new
32
+ rescfg = { :nameserver => cfg.nameserver, :ndots => cfg.ndots,
33
+ :apply_domain => false, :apply_search_list => false}
34
+ resargs = { :config_info => rescfg, :use_tcp => false, :recurse => false,
35
+ :packet_timeout => 2, :retry_times => 1, :retry_delay => 1,
36
+ :dnssec => false, :ignore_truncation => true, :src_address => '0.0.0.0',
37
+ :udp_size => 512 }
38
+ @resolver = Dnsruby::Resolver.new(resargs)
39
+ @resolver.udp_size = 512
40
+ #Dnsruby.log.level = Logger::DEBUG
41
+ #Log.level = Logger::DEBUG
42
+ end
43
+
44
+ def fingerprint(ip)
45
+ return process(ip, INITRULE[:header], INITRULE[:query], RULESET)
46
+ end
47
+
48
+ def process(ip, header, query, ruleset)
49
+ ret = Hash.new
50
+ answer, errstr = probe(ip, header, query)
51
+ id = answer ? header2fp(answer.header) : errstr
52
+ Log.debug { "query = #{query}, id = #{id}" }
53
+ for rule in ruleset do
54
+ raise "Missing fingerprint" unless rule.has_key?(:fingerprint)
55
+ next unless id =~ /#{rule[:fingerprint]}/
56
+ if rule.has_key?(:result) then
57
+ result = rule[:result]
58
+ for k in [:vendor, :product, :option] do
59
+ ret[k] = result[k] if result.has_key?(k) and result[k].length > 0
60
+ end
61
+ case @version_style
62
+ when :none
63
+ ret[:version] = result[:version]
64
+ when :append
65
+ ver = query_version(ip, result[:qv])
66
+ ver = query_version(ip, "version.bind") unless ver
67
+ ret[:version] = result[:version]
68
+ ret[:version]+= " (#{ver})" if ver
69
+ when :override
70
+ ver = query_version(ip, result[:qv])
71
+ ver = query_version(ip, "version.bind") unless ver
72
+ ret[:version] = ver ? ver : result[:version]
73
+ end
74
+ return ret
75
+ end
76
+ if rule.has_key?(:state) then
77
+ ret[:state] = rule[:state]
78
+ ret[:error] = "No match found"
79
+ ret[:id] = id
80
+ return ret
81
+ end
82
+ query = rule[:query] if rule.has_key?(:query)
83
+ if rule.has_key?(:header) and rule.has_key?(:ruleset) then
84
+ return process(ip, rule[:header], query, rule[:ruleset])
85
+ end
86
+ raise "Invalid ruleset -- no next step"
87
+ end
88
+ raise "Invalid ruleset -- fell off end"
89
+ end
90
+
91
+ def query_version(ip, name)
92
+ @resolver.nameserver = ip
93
+ @resolver.dnssec = false
94
+ begin
95
+ msg = @resolver.query(name, 'TXT', 'CH')
96
+ if msg.answer.size > 0 then
97
+ ver = msg.answer[0].data.sub(/[^0-9a-zA-Z. :!?-]/, '')
98
+ return ver.length > 0 ? ver : nil
99
+ end
100
+ rescue Exception
101
+ return nil
102
+ end
103
+ end
104
+
105
+ def header2fp(header)
106
+ list = [ header.qr, header.opcode, header.aa, header.tc, header.rd,
107
+ header.ra, header.ad, header.cd, header.get_header_rcode, header.qdcount,
108
+ header.ancount, header.nscount, header.arcount ]
109
+ list.map! do | item |
110
+ next '0' if item.instance_of? FalseClass
111
+ next '1' if item.instance_of? TrueClass
112
+ next "NS_NOTIFY_OP" if item == "Notify"
113
+ item
114
+ end
115
+ return list.join(',').upcase
116
+ end
117
+
118
+ def fp2header(headerstr)
119
+ list = headerstr.split(/,/)
120
+ h = Dnsruby::Header.new
121
+ h.qr = list.shift == '1' ? true : false
122
+ opcode = list.shift
123
+ opcode = "Notify" if opcode == "NS_NOTIFY_OP"
124
+ h.opcode = opcode
125
+ h.aa = list.shift == '1' ? true : false
126
+ h.tc = list.shift == '1' ? true : false
127
+ h.rd = list.shift == '1' ? true : false
128
+ h.ra = list.shift == '1' ? true : false
129
+ h.ad = list.shift == '1' ? true : false
130
+ h.cd = list.shift == '1' ? true : false
131
+ h.rcode = list.shift
132
+ h.qdcount = list.shift.to_i
133
+ h.ancount = list.shift.to_i
134
+ h.nscount = list.shift.to_i
135
+ h.arcount = list.shift.to_i
136
+ return h
137
+ end
138
+
139
+ def decode_query(querystr)
140
+ qname, qclass, qtype = querystr.split(/\s+/)
141
+ if qtype == "CLASS0" then # crappy data
142
+ qtype = qclass
143
+ qclass = "CLASS0"
144
+ end
145
+ q = Dnsruby::Question.new(qname, qtype, qclass)
146
+ return q
147
+ end
148
+
149
+ def probe(ip, headerstr, query)
150
+ @resolver.nameserver = ip
151
+ @resolver.dnssec = false
152
+ msg = Dnsruby::Message.new
153
+ msg.header = fp2header(headerstr)
154
+ msg.add_question(decode_query(query))
155
+ q = Queue.new
156
+ @resolver.send_async(msg, q)
157
+ id, result, error = q.pop
158
+ ans = result || error
159
+ return nil, FINGERPRINT_TIMEOUT if ans.is_a? Dnsruby::ResolvTimeout
160
+ return nil, ans.to_s if ans.is_a? Exception
161
+ return ans, nil
162
+ end
163
+
164
+ end
165
+
166
+ end
@@ -0,0 +1,389 @@
1
+ # $Id: Fingerprint.pm,v 1.17 2005/09/05 13:33:36 jakob Exp $
2
+ #
3
+ # Copyright (c) 2003,2004,2005 Roy Arends & Jakob Schlyter.
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions
8
+ # are met:
9
+ #
10
+ # 1. Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ # 3. The name of the authors may not be used to endorse or promote products
16
+ # derived from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
+ # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
+ # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
+ # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ module FingerprintRules
30
+
31
+ QY = [ "0,IQUERY,0,0,1,0,0,0,NOERROR,0,0,0,0",
32
+ "0,NS_NOTIFY_OP,0,0,0,0,0,0,NOERROR,0,0,0,0",
33
+ "0,QUERY,0,0,0,0,0,0,NOERROR,0,0,0,0",
34
+ "0,IQUERY,0,0,0,0,1,1,NOERROR,0,0,0,0",
35
+ "0,QUERY,0,0,0,0,0,0,NOTIMP,0,0,0,0",
36
+ "0,IQUERY,1,0,1,1,1,1,NOERROR,0,0,0,0",
37
+ "0,UPDATE,0,0,0,1,0,0,NOERROR,0,0,0,0",
38
+ "0,QUERY,1,1,1,1,1,1,NOERROR,0,0,0,0",
39
+ "0,QUERY,0,0,0,0,0,1,NOERROR,0,0,0,0",
40
+ ].freeze
41
+
42
+ INITRULE = { :header => QY[0], :query => ". IN A" }.freeze
43
+
44
+ IQ = [ "1,IQUERY,0,0,1,0,0,0,FORMERR,0,0,0,0", # iq0
45
+ "1,IQUERY,0,0,1,0,0,0,FORMERR,1,0,0,0", # iq1
46
+ "1,IQUERY,0,0,1,0,0,0,NOTIMP,0,0,0,0", # iq2
47
+ "1,IQUERY,0,0,1,0,0,0,NOTIMP,1,0,0,0", # iq3
48
+ "1,IQUERY,0,0,1,1,0,0,FORMERR,0,0,0,0", # iq4
49
+ "1,IQUERY,0,0,1,1,0,0,NOTIMP,0,0,0,0", # iq5
50
+ "1,IQUERY,0,0,1,1,0,0,NOTIMP,1,0,0,0", # iq6
51
+ "1,IQUERY,1,0,1,0,0,0,NOTIMP,1,0,0,0", # iq7
52
+ "1,QUERY,1,0,1,0,0,0,NOTIMP,1,0,0,0",
53
+ "1,QUERY,0,0,0,0,0,0,NOTIMP,0,0,0,0",
54
+ "1,IQUERY,0,0,1,1,0,0,FORMERR,1,0,0,0", # iq10
55
+ "1,NS_NOTIFY_OP,0,0,0,0,0,0,FORMERR,1,0,0,0",
56
+ "1,NS_NOTIFY_OP,0,0,0,0,0,0,NOTIMP,0,0,0,0",
57
+ "1,NS_NOTIFY_OP,0,0,0,0,0,0,NOTIMP,1,0,0,0",
58
+ "1,NS_NOTIFY_OP,0,0,0,0,0,0,NXDOMAIN,1,0,0,0",
59
+ "1,NS_NOTIFY_OP,0,0,0,0,0,0,REFUSED,1,0,0,0",
60
+ "1,NS_NOTIFY_OP,0,0,0,0,0,0,SERVFAIL,1,0,0,0",
61
+ "1,NS_NOTIFY_OP,0,0,0,1,0,0,FORMERR,1,0,0,0",
62
+ "1,NS_NOTIFY_OP,0,0,0,1,0,0,NOTIMP,0,0,0,0",
63
+ "1,NS_NOTIFY_OP,0,0,0,1,0,0,NOTIMP,1,0,0,0",
64
+ "1,NS_NOTIFY_OP,0,0,0,1,0,0,REFUSED,1,0,0,0", # iq20
65
+ "1,NS_NOTIFY_OP,0,0,0,1,0,0,SERVFAIL,1,0,0,0",
66
+ "1,NS_NOTIFY_OP,1,0,0,0,0,0,NOTIMP,1,0,0,0",
67
+ "1,QUERY,1,0,0,0,0,0,NOTIMP,1,0,0,0",
68
+ "1,NS_NOTIFY_OP,1,0,0,0,0,0,SERVFAIL,1,0,0,0",
69
+ "1,IQUERY,0,0,0,0,1,1,NOTIMP,0,0,0,0",
70
+ "1,IQUERY,0,0,0,0,0,0,NOTIMP,0,0,0,0",
71
+ "1,IQUERY,0,0,1,1,1,1,FORMERR,0,0,0,0",
72
+ "1,IQUERY,1,0,1,1,1,1,FORMERR,0,0,0,0",
73
+ "1,QUERY,.,0,1,.,.,.,NOTIMP,.+,.+,.+,.+",
74
+ "1,QUERY,.,0,1,.,.,.,.+,.+,.+,.+,.+", #iq30
75
+ "1,QUERY,0,0,.,.,0,0,NXDOMAIN,1,0,0,0",
76
+ "1,QUERY,0,0,.,.,0,0,FORMERR,1,0,0,0",
77
+ "1,UPDATE,0,0,0,0,0,0,NOTIMP,0,0,0,0",
78
+ "1,UPDATE,0,0,0,1,0,0,NOTIMP,0,0,0,0",
79
+ "1,QUERY,0,0,1,0,0,0,NOERROR,1,0,0,0",
80
+ "1,QUERY,1,1,1,1,1,1,NOTIMP,1,0,0,0",
81
+ "1,QUERY,0,0,0,0,0,0,NOERROR,1,0,.+,0",
82
+ "1,QUERY,0,0,1,0,0,0,FORMERR,1,0,0,0",
83
+ "1,IQUERY,0,0,1,0,1,1,NOTIMP,1,0,0,0",
84
+ "1,IQUERY,0,0,0,1,1,1,REFUSED,1,0,0,0", #iq40
85
+ "1,UPDATE,0,0,0,1,0,0,REFUSED,1,0,0,0",
86
+ "1,IQUERY,0,0,0,1,1,1,FORMERR,0,0,0,0",
87
+ "1,IQUERY,0,0,0,1,0,0,NOTIMP,0,0,0,0",
88
+ "1,QUERY,1,0,1,0,0,0,FORMERR,1,0,0,0",
89
+ "1,UPDATE,0,0,0,0,0,0,FORMERR,1,0,0,0",
90
+ "1,UPDATE,0,0,0,0,0,0,FORMERR,0,0,0,0",
91
+ "1,QUERY,0,0,1,0,0,0,FORMERR,0,0,0,0",
92
+ "1,QUERY,0,0,1,0,0,0,SERVFAIL,1,0,0,0", #iq48
93
+ "1,QUERY,1,0,1,0,0,0,NXDOMAIN,1,0,1,0",
94
+ "1,QUERY,0,0,1,0,0,0,REFUSED,1,0,0,0", #iq50
95
+ "1,QUERY,0,0,1,0,0,0,NOERROR,1,1,0,0",
96
+ "1,IQUERY,0,0,1,0,0,0,REFUSED,0,0,0,0",
97
+ "1,QUERY,0,0,0,0,0,0,FORMERR,0,0,0,0",
98
+ "1,QUERY,0,0,1,1,1,0,NOERROR,1,0,1,0",
99
+ "1,QUERY,0,0,1,1,0,0,NOERROR,1,0,1,0",
100
+ "1,QUERY,0,0,1,0,1,0,NOERROR,.+,.+,.+,.+",
101
+ "1,QUERY,0,0,1,0,0,0,.+,.+,.+,.+,.+",
102
+ "1,QUERY,1,0,1,0,0,0,NOERROR,1,1,0,0",
103
+ "1,QUERY,0,0,1,1,0,0,SERVFAIL,1,0,0,0",
104
+ "1,QUERY,1,0,1,1,0,0,NOERROR,1,1,0,0", #iq60
105
+ "1,QUERY,0,0,1,1,0,0,REFUSED,1,0,0,0",
106
+ "1,QUERY,0,0,0,0,0,0,NOTIMP,1,0,0,0",
107
+ "1,QUERY,1,0,1,1,0,0,NOERROR,1,0,1,0",
108
+ "1,IQUERY,0,0,1,1,1,1,NOTIMP,0,0,0,0",
109
+ "1,UPDATE,0,0,0,0,0,0,REFUSED,0,0,0,0",
110
+ "1,IQUERY,0,0,0,1,1,1,NOTIMP,1,0,0,0",
111
+ "1,IQUERY,0,0,0,1,0,0,NOTIMP,1,0,0,0",
112
+ "1,QUERY,0,1,1,1,1,1,NOERROR,1,0,.,0",
113
+ "1,QUERY,0,1,1,1,0,1,NOERROR,1,0,.,0",
114
+ "1,IQUERY,0,0,1,0,0,0,REFUSED,1,0,0,0", #iq70
115
+ "1,IQUERY,1,0,1,1,1,1,NOTIMP,1,0,0,0",
116
+ "1,IQUERY,0,0,1,0,0,0,NOERROR,1,0,0,0",
117
+ "1,QUERY,1,0,1,1,0,0,NOERROR,1,0,0,0",
118
+ "1,IQUERY,1,0,1,1,0,0,NXDOMAIN,1,0,0,0",
119
+ "1,UPDATE,0,0,0,1,0,0,FORMERR,0,0,0,0",
120
+ "1,IQUERY,1,0,1,0,0,0,NXDOMAIN,1,0,0,0",
121
+ "1,QUERY,0,0,1,1,0,0,FORMERR,1,0,0,0",
122
+ "1,QUERY,0,0,0,1,0,0,SERVFAIL,1,0,0,0",
123
+ "1,QUERY,0,0,1,1,0,0,NOERROR,1,1,0,0",
124
+ "1,IQUERY,1,0,1,0,0,0,NOERROR,1,0,0,0", #iq80
125
+ "1,IQUERY,1,0,1,1,0,0,NOTIMP,1,0,0,0",
126
+ "1,QUERY,0,0,1,1,0,0,NOERROR,1,0,0,0",
127
+ "1,QUERY,1,0,1,1,0,0,NOERROR,1,1,1,.+",
128
+ "1,QUERY,0,0,1,1,0,0,REFUSED,0,0,0,0",
129
+ "1,UPDATE,0,0,0,1,0,0,NOTIMP,1,0,0,0",
130
+ "1,QUERY,1,0,0,1,0,0,NXDOMAIN,1,0,0,0",
131
+ "1,QUERY,0,0,0,1,0,0,NOTIMP,0,0,0,0",
132
+ "1,QUERY,0,0,0,0,0,0,REFUSED,1,0,0,0",
133
+ "1,QUERY,1,0,1,1,0,0,NXDOMAIN,1,0,0,0",
134
+ "1,QUERY,1,0,0,0,0,0,NOERROR,1,1,0,0", #iq90
135
+ "1,IQUERY,1,0,1,1,0,1,NOTIMP,1,0,0,0",
136
+ "1,QUERY,0,0,0,1,0,0,NOTIMP,1,0,0,0",
137
+ "1,QUERY,0,0,1,0,0,1,SERVFAIL,1,0,0,0",
138
+ ].freeze
139
+
140
+ RULESET = [
141
+ { :fingerprint => "query timed out" , :header => QY[0], :query => "com. IN A", :ruleset => [
142
+ { :fingerprint => "query timed out", :header => QY[7], :query => ". CH A", :ruleset => [
143
+ { :fingerprint => "query timed out", :header => QY[6], :query => ". IN A", :ruleset => [
144
+ { :fingerprint => IQ[38], :result => { :vendor => "Digital Lumber", :product => "Oak DNS", :version =>"" }, :qv => ":version.oak",},
145
+ ## { :fingerprint => "query timed out", :result => "TIMEOUT",},
146
+ { :fingerprint => ".+", :state => "q0tq0tq7tq6r?", }, ]
147
+ },
148
+ { :fingerprint => IQ[35], :result => { :vendor => "XBILL", :product => "jnamed (dnsjava)", :version => "" }, },
149
+ { :fingerprint => IQ[36], :result => { :vendor => "menandmice", :product => "QuickDNS", :version => ""}, },
150
+ { :fingerprint => IQ[37], :result => { :vendor => "unknown", :product => "NonSequitur DNS", :version => ""}, },
151
+ { :fingerprint => ".+", :state => "q0tq0tq7r?", }, ]
152
+ },
153
+ { :fingerprint => IQ[35], :result => { :vendor => "eNom", :product => "eNom DNS", :version =>""}, },
154
+ { :fingerprint => ".+", :state => "q0tq0r?", },]
155
+ },
156
+
157
+ { :fingerprint => IQ[0], :header => QY[1], :query=> "jjjjjjjjjjjj IN A", :ruleset => [
158
+ { :fingerprint => IQ[12], :result => { :vendor => "ISC", :product => "BIND", :version => "8.4.1-p1" }, :qv => ":version.bind",},
159
+ { :fingerprint => IQ[13], :result => { :vendor => "ISC", :product => "BIND", :version => "8 plus root server modifications"}, :qv => ":version.bind",},
160
+ { :fingerprint => IQ[15], :result => { :vendor => "Cisco", :product => "CNR", :version => ""}, },
161
+ { :fingerprint => IQ[16], :header => QY[2], :query => "hostname.bind CH TXT", :ruleset => [
162
+ { :fingerprint => IQ[58], :result => { :vendor => "ISC", :product => "BIND", :version => "8.3.0-RC1 -- 8.4.4"}, :qv => ":version.bind",},
163
+ { :fingerprint => IQ[50], :result => { :vendor => "ISC", :product => "BIND", :version => "8.3.0-RC1 -- 8.4.4"}, :qv => ":version.bind",},
164
+ { :fingerprint => IQ[48], :result => { :vendor => "ISC", :product => "BIND", :version => "8.2.2-P3 -- 8.3.0-T2A"}, :qv => ":version.bind",},
165
+ { :fingerprint => ".+", :state => "q0r0q1r16q2r?", },]
166
+ },
167
+ { :fingerprint => ".+", :state => "q0r0q1r?", },]
168
+ },
169
+
170
+ { :fingerprint => IQ[1], :header => QY[2], :query => ". IN IXFR", :ruleset => [
171
+ { :fingerprint => IQ[31], :result => { :vendor => "Microsoft", :product => "Windows DNS", :version => "2000" }, },
172
+ { :fingerprint => IQ[32], :result => { :vendor => "Microsoft", :product => "Windows DNS", :version => "NT4" }, },
173
+ { :fingerprint => IQ[50], :result => { :vendor => "Microsoft", :product => "Windows DNS", :version => "2003"}, },
174
+ { :fingerprint => ".+", :state => "q0r1q2r?", }, ]
175
+ },
176
+
177
+ { :fingerprint => IQ[2], :header => QY[1], :ruleset => [
178
+ { :fingerprint => IQ[11], :result => { :vendor => "ISC", :product => "BIND", :version => "9.2.3rc1 -- 9.4.0a0" }, :qv => ":version.bind",},
179
+ { :fingerprint => IQ[12], :header => QY[3], :ruleset => [
180
+ { :fingerprint => IQ[25], :header => QY[6], :ruleset => [
181
+ { :fingerprint => IQ[33], :result => { :vendor => "bboy", :product => "MyDNS", :version => "" },},
182
+ { :fingerprint => IQ[34], :header => QY[2], :query => "012345678901234567890123456789012345678901234567890123456789012.012345678901234567890123456789012345678901234567890123456789012.012345678901234567890123456789012345678901234567890123456789012.0123456789012345678901234567890123456789012345678901234567890. IN A", :ruleset => [
183
+ { :fingerprint => IQ[47], :result => { :vendor => "NLnetLabs", :product => "NSD", :version => "1.0.3 -- 1.2.1"}, :qv => ":version.server", },
184
+ { :fingerprint => IQ[48], :header => QY[2], :query => "hostname.bind CH TXT", :ruleset => [
185
+ { :fingerprint => IQ[50], :result => { :vendor => "NLnetLabs", :product => "NSD", :version => "1.2.2" }, :qv => ":version.server", },
186
+ { :fingerprint => IQ[51], :header => QY[8], :query => ". IN A", :ruleset => [
187
+ { :fingerprint => IQ[93], :result => { :vendor => "NLnetLabs", :product => "NSD", :version => "1.2.3 -- 2.1.2" } , :qv => ":version.server", },
188
+ { :fingerprint => IQ[48], :result => { :vendor => "NLnetLabs", :product => "NSD", :version => "2.1.3" }, :qv => ":version.server", },
189
+ { :fingerprint => ".+", :state => "q0r2q1r12q3r25q6r34q2r48q2r51q8r?", }, ]
190
+ },
191
+ { :fingerprint => ".+", :state => "q0r2q1r12q3r25q6r34q2r48q2r?", }, ]
192
+ },
193
+ { :fingerprint => IQ[49], :header => QY[2], :query => "hostname.bind CH TXT", :ruleset => [
194
+ { :fingerprint => IQ[50], :result => { :vendor => "NLnetLabs", :product => "NSD", :version => "1.2.2 [root]"} , :qv => ":version.server", },
195
+ { :fingerprint => IQ[51], :result => { :vendor => "NLnetLabs", :product => "NSD", :version => "1.2.3 [root]"}, :qv => ":version.server", },
196
+ { :fingerprint => ".+", :state => "q0r2q1r12q3r25q6r34q2r49q2r?", }, ]
197
+ },
198
+ { :fingerprint => IQ[53], :result => { :vendor => "NLnetLabs", :product=>"NSD", :version => "1.0.2"}, :qv => ":version.server", },
199
+ { :fingerprint => ".+", :state => "q0r2q1r12q3r25q6r34q2a?", },]
200
+ },
201
+ { :fingerprint => ".+", :state => "q0r2q1r12q3r25q6r?", },]
202
+ },
203
+ { :fingerprint => IQ[26], :result => { :vendor => "VeriSign", :product => "ATLAS", :version => ""},},
204
+ { :fingerprint => ".+", :state => "q0r2q1r12q3r?", },]
205
+ },
206
+ { :fingerprint => IQ[15], :header => QY[6], :ruleset => [
207
+ { :fingerprint => IQ[45], :result => { :vendor => "Nominum", :product =>"ANS", :version =>""}, :qv => ":version.bind",},
208
+ { :fingerprint => IQ[65], :result => { :vendor => "ISC", :product => "BIND", :version => "9.2.3rc1 -- 9.4.0a0" }, :qv => ":version.bind",},
209
+ { :fingerprint => IQ[46], :header => QY[7], :ruleset => [
210
+ { :fingerprint => IQ[56], :result => { :vendor => "ISC", :product => "BIND", :version => "9.0.0b5 -- 9.0.1" }, :qv => ":version.bind",},
211
+ { :fingerprint => IQ[57], :result => { :vendor => "ISC", :product => "BIND", :version => "9.1.0 -- 9.1.3" }, :qv => ":version.bind",},
212
+ { :fingerprint => ".+", :state => "q0r2q1r15q6r46q7r?", }, ]
213
+ },
214
+ { :fingerprint => ".+", :state => "q0r2q1r15q6r?", },]
215
+ },
216
+ { :fingerprint => IQ[16], :header => QY[4], :ruleset => [
217
+ { :fingerprint => IQ[29], :result => { :vendor => "ISC", :product => "BIND", :version => "9.2.0a1 -- 9.2.0rc3"}, :qv => ":version.bind",},
218
+ { :fingerprint => IQ[30], :header => QY[0], :query => ". A CLASS0" , :ruleset => [
219
+ { :fingerprint => IQ[2], :result => { :vendor=>"ISC", :product => "BIND", :version =>"9.2.0rc7 -- 9.2.2-P3"}, :qv => ":version.bind", },
220
+ { :fingerprint => IQ[0], :result => { :vendor=>"ISC", :product => "BIND", :version =>"9.2.0rc4 -- 9.2.0rc6"}, :qv => ":version.bind", },
221
+ { :fingerprint => ".+", :result => { :vendor => "ISC", :product => "BIND", :version =>"9.2.0rc4 -- 9.2.2-P3"}, :qv => ":version.bind", }, ]
222
+ },
223
+ { :fingerprint => ".+", :state => "q0r2q1r16q4r?", },]
224
+ },
225
+ { :fingerprint => ".+", :state => "q0r2q1r?", }, ]
226
+ },
227
+
228
+ { :fingerprint => IQ[3], :header => QY[1], :ruleset => [
229
+ { :fingerprint => "query timed out", :header => QY[5], :ruleset => [
230
+ { :fingerprint => IQ[3], :result => { :vendor => "sourceforge", :product =>"Dents", :version =>""}, :qv => ":version.bind", },
231
+ { :fingerprint => IQ[81], :result => { :vendor => "Microsoft", :product => "Windows DNS", :version => "2003" },},
232
+ { :fingerprint => IQ[91], :result => { :vendor => "Microsoft", :product => "Windows DNS", :version => "2003" },},
233
+ { :fingerprint => ".+", :state => "q0r3q1tq5r?", }, ]
234
+
235
+ },
236
+ { :fingerprint => IQ[14], :result => { :vendor => "UltraDNS", :product => "", :version =>"v2.7.0.2 -- 2.7.3"}, :qv => ":version.bind", },
237
+ { :fingerprint => IQ[13], :header => QY[5], :ruleset => [
238
+ { :fingerprint => IQ[39], :result => { :vendor => "pliant", :product => "DNS Server", :version =>""},},
239
+ { :fingerprint => IQ[7], :result => { :vendor => "JHSOFT", :product => "simple DNS plus", :version =>""}, },
240
+ { :fingerprint => IQ[71], :header => QY[6], :ruleset => [
241
+ { :fingerprint => IQ[41], :result => { :vendor =>"Netnumber", :product =>"ENUM server", :version =>""}, },
242
+ { :fingerprint => IQ[85], :result => { :vendor =>"Raiden", :product => "DNSD", :version => ""}, }, ]
243
+ },
244
+ { :fingerprint => ".+", :state => "q0r3q1r13q5r?", }, ]
245
+ },
246
+ { :fingerprint => ".+", :state => "q0r3q1r?", }, ]
247
+ },
248
+
249
+ { :fingerprint => IQ[4], :header => QY[1], :query=> "jjjjjjjjjjjj IN A", :ruleset => [
250
+ { :fingerprint => IQ[17], :result => { :vendor => "ISC", :product => "BIND", :version =>"9.0.0b5 -- 9.0.1 [rcursion enabled]"}, :qv => ":version.bind", },
251
+ { :fingerprint => IQ[18], :header => QY[5], :query=> ". IN A" , :ruleset => [
252
+ { :fingerprint => IQ[27], :result => { :vendor => "ISC", :product => "BIND", :version => "4.9.3 -- 4.9.11"}, :qv => ":version.bind", },
253
+ { :fingerprint => IQ[28], :result => { :vendor => "ISC", :product => "BIND", :version => "4.8 -- 4.8.3"}, },
254
+ { :fingerprint => ".+", :state => "q0r4q1r18q5r?", }, ]
255
+ },
256
+ { :fingerprint => IQ[19], :result => {:vendor => "ISC", :product =>"BIND", :version => "8.2.1 [recursion enabled]"}, :qv => ":version.bind", },
257
+ { :fingerprint => IQ[20], :header => QY[3], :query=> ". IN A", :ruleset => [
258
+ { :fingerprint => IQ[42], :result => {:vendor => "ISC", :product =>"BIND", :version =>"8.1-REL -- 8.2.1-T4B [recursion enabled]"}, :qv => ":version.bind", },
259
+ { :fingerprint => ".+", :state => "q0r4q1r20q3r?", },]
260
+ },
261
+ { :fingerprint => IQ[21], :header => QY[2], :query => "hostname.bind CH TXT", :ruleset => [
262
+ { :fingerprint => IQ[60], :result => {:vendor =>"ISC", :product => "BIND", :version => "8.3.0-RC1 -- 8.4.4 [recursion enabled]"}, :qv => ":version.bind",},
263
+ { :fingerprint => IQ[59], :header => QY[7], :query=> ". IN A", :ruleset => [
264
+ { :fingerprint => IQ[68], :result => {:vendor =>"ISC", :product => "BIND", :version => "8.1-REL -- 8.2.1-T4B [recursion enabled]"}, :qv => ":version.bind", },
265
+ { :fingerprint => IQ[69], :result => {:vendor =>"ISC", :product => "BIND", :version => "8.2.2-P3 -- 8.3.0-T2A [recursion enabled]"}, :qv => ":version.bind",},
266
+ { :fingerprint => "connection failed", :result => { :vendor =>"Runtop", :product => "dsl/cable", :version =>""},},
267
+ { :fingerprint => ".+", :state => "q0r4q1r21q2r59q7r?", },]
268
+ },
269
+
270
+ { :fingerprint => IQ[58], :result => {:vendor => "ISC", :product =>"BIND", :version => "8.3.0-RC1 -- 8.4.4 [recursion local]"}, :qv => ":version.bind",},
271
+ { :fingerprint => IQ[50], :result => {:vendor => "ISC", :product =>"BIND", :version => "8.3.0-RC1 -- 8.4.4 [recursion local]"}, :qv => ":version.bind",},
272
+ { :fingerprint => IQ[61], :result => {:vendor => "ISC", :product =>"BIND", :version => "8.3.0-RC1 -- 8.4.4 [recursion local]"}, :qv => ":version.bind",},
273
+ { :fingerprint => IQ[48], :result => {:vendor => "ISC", :product =>"BIND", :version => "8.2.2-P3 -- 8.3.0-T2A [recursion local]"}, :qv => ":version.bind",},
274
+ { :fingerprint => ".+", :state => "q0r4q1r21q2r?", },]
275
+ },
276
+ { :fingerprint => ".+", :state => "q0r4q1r?", }, ]
277
+ },
278
+
279
+ { :fingerprint => IQ[5], :header => QY[1], :ruleset => [
280
+ { :fingerprint => IQ[11], :result => { :vendor => "ISC", :product => "BIND", :version => "9.2.3rc1 -- 9.4.0a0", :option => "recursion enabled,split view" }, :qv => ":version.bind",},
281
+ { :fingerprint => IQ[17], :result => {:vendor => "ISC", :product =>"BIND", :version => "9.2.3rc1 -- 9.4.0a0 [recursion enabled]"}, :qv => ":version.bind",},
282
+ { :fingerprint => IQ[18], :header => QY[5], :ruleset => [
283
+ { :fingerprint => IQ[5], :header => QY[7], :query => ". IN A", :ruleset => [
284
+ { :fingerprint => IQ[84], :result => {:vendor => "Nominum", :product =>"CNS", :version => ""}, :qv => ":version.bind",},
285
+ { :fingerprint => IQ[59], :result => {:vendor => "Mikrotik", :product =>"dsl/cable", :version => ""}, },
286
+ { :fingerprint => IQ[82], :result => {:vendor => "Mikrotik", :product =>"dsl/cable", :version => ""}, },
287
+ { :fingerprint => ".+", :state => "q0r5q1r18q5r5q7r?", }, ]
288
+ },
289
+ ## { :fingerprint => IQ[64], :result => "unknown, smells like old BIND 4", },
290
+ { :fingerprint => ".+", :state => "q0r5q1r18q5r?", }, ]
291
+ },
292
+ { :fingerprint => IQ[20], :header => QY[7], :ruleset => [
293
+ { :fingerprint => IQ[54], :result => {:vendor => "ISC", :product =>"BIND", :version => "9.0.0b5 -- 9.0.1 [recursion enabled]"}, :qv => ":version.bind",},
294
+ { :fingerprint => IQ[55], :result => {:vendor => "ISC", :product =>"BIND", :version => "9.1.0 -- 9.1.3 [recursion enabled]"}, :qv => ":version.bind",},
295
+ { :fingerprint => IQ[63], :result => {:vendor => "ISC", :product =>"BIND", :version => "4.9.3 -- 4.9.11 [recursion enabled]"}, :qv => ":version.bind",},
296
+ { :fingerprint => IQ[61], :result => {:vendor => "ISC", :product =>"BIND", :version => "9.0.0b5 -- 9.1.3 [recursion local]"}, :qv => ":version.bind",},
297
+ { :fingerprint => ".+", :state => "q0r5q1r20q7r?", }, ]
298
+ },
299
+ { :fingerprint => IQ[21], :header => QY[4], :ruleset => [
300
+ { :fingerprint => "query timed out", :result => {:vendor => "ISC", :product =>"BIND", :version => "9.2.0a1 -- 9.2.2-P3 [recursion enabled]"}, :qv => ":version.bind", },
301
+ { :fingerprint => IQ[29], :result => {:vendor => "ISC", :product =>"BIND", :version => "9.2.0a1 -- 9.2.0rc3 [recursion enabled]"}, :qv => ":version.bind", },
302
+ { :fingerprint => IQ[61], :header => QY[0], :query => ". A CLASS0" , :ruleset => [
303
+ { :fingerprint => IQ[2], :result => {:vendor => "ISC", :product =>"BIND", :version => "9.2.0rc7 -- 9.2.2-P3 [recursion local]"}, :qv => ":version.bind", },
304
+ { :fingerprint => IQ[0], :result => {:vendor => "ISC", :product =>"BIND", :version => "9.2.0a1 -- 9.2.0rc6 [recursion local]"}, :qv => ":version.bind", },
305
+ { :fingerprint => ".+", :result => {:vendor => "ISC", :product =>"BIND", :version => "9.2.0a1 -- 9.2.2-P3 [recursion local]"}, :qv => ":version.bind", }, ]
306
+ },
307
+ { :fingerprint => IQ[30], :header => QY[0], :query => ". A CLASS0" , :ruleset => [
308
+ { :fingerprint => IQ[2], :result => {:vendor => "ISC", :product =>"BIND", :version => "9.2.0rc7 -- 9.2.2-P3 [recursion enabled]"}, :qv => ":version.bind", },
309
+ { :fingerprint => IQ[0], :result => {:vendor => "ISC", :product =>"BIND", :version => "9.2.0rc4 -- 9.2.0rc6 [recursion enabled]"}, :qv => ":version.bind", },
310
+ { :fingerprint => ".+", :result => {:vendor => "ISC", :product =>"BIND", :version => "9.2.0rc4 -- 9.2.2-P3 [recursion enabled]"}, :qv => ":version.bind", }, ]
311
+ },
312
+ { :fingerprint => ".+", :state => "q0r5q1r21q4r?", }, ]
313
+ },
314
+ { :fingerprint => ".+", :state => "q0r5q1r?", }, ]
315
+ },
316
+
317
+ { :fingerprint => IQ[6], :header => QY[1], :ruleset => [
318
+ { :fingerprint => IQ[15], :result => {:vendor => "incognito", :product =>"DNS commander", :version => "v2.3.1.1 -- 4.0.5.1"}, :qv => ":version.bind", },
319
+ { :fingerprint => IQ[19], :header => QY[3], :ruleset => [
320
+ { :fingerprint => IQ[66], :result => {:vendor => "vermicelli", :product =>"totd", :version => ""}, },
321
+ { :fingerprint => IQ[67], :result => {:vendor => "JHSOFT", :product =>"simple DNS plus", :version => "[recursion enabled]"}, },
322
+ { :fingerprint => ".+", :state => "q0r6q1r19q3r?", }, ]
323
+ },
324
+ { :fingerprint => ".+", :state => "q0r6q1r?", }, ]
325
+ },
326
+
327
+ { :fingerprint => IQ[7], :header => QY[1], :ruleset => [
328
+ { :fingerprint => IQ[22], :result => {:vendor => "PowerDNS", :product =>"PowerDNS", :version => "2.9.4 -- 2.9.11"}, :qv => ":version.bind", },
329
+ { :fingerprint => IQ[24], :result => {:vendor => "PowerDNS", :product =>"PowerDNS", :version => "2.8 -- 2.9.3"}, :qv => ":version.bind", },
330
+ { :fingerprint => ".+", :state => "q0r7q1r?", }, ]
331
+ },
332
+
333
+ { :fingerprint => IQ[8], :header => QY[1], :ruleset => [
334
+ { :fingerprint => IQ[23], :header => QY[2] , :query => ". CH A", :ruleset => [
335
+ { :fingerprint => "query timed out", :result => { :vendor => "DJ Bernstein", :product => "TinyDNS", :version => "1.04"} ,},
336
+ { :fingerprint => IQ[32], :result => {:vendor => "DJ Bernstein", :product => "TinyDNS", :version => "1.05"} ,},
337
+ { :fingerprint => ".+", :state => "q0r8q1r23q2r?",},]
338
+ },
339
+ { :fingerprint => ".+", :state => "q0r8q1r?", }, ]
340
+ },
341
+
342
+ { :fingerprint => IQ[9], :header => QY[1], :ruleset => [
343
+ { :fingerprint => IQ[9], :result => { :vendor => "Sam Trenholme", :product =>"MaraDNS", :version => ""}, :qv => "erre-con-erre-cigarro.maradns.org"},
344
+ { :fingerprint => ".+", :state => "q0r9q1r?", }, ]
345
+ },
346
+
347
+ { :fingerprint => IQ[10], :result => { :vendor => "Microsoft", :product =>"?", :version => ""}, },
348
+ { :fingerprint => IQ[26], :result => { :vendor => "Meilof Veeningen", :product =>"Posadis", :version =>""}, },
349
+ { :fingerprint => IQ[43], :header => QY[6], :ruleset => [
350
+ { :fingerprint => IQ[34], :result => { :vendor => "Paul Rombouts", :product =>"pdnsd", :version =>""}, },
351
+ { :fingerprint => IQ[75], :result => { :vendor => "antirez", :product =>"Yaku-NS", :version =>""}, },
352
+ { :fingerprint => ".+", :state => "q0r43q6r?", }, ]
353
+ },
354
+
355
+ { :fingerprint => IQ[44], :result => { :vendor =>"cpan", :product=>"Net::DNS Nameserver", :version =>""}, :qv => ":version.bind", },
356
+ { :fingerprint => IQ[52], :result => { :vendor =>"NLnetLabs", :product=>"NSD", :version => "1.0 alpha"}, },
357
+ { :fingerprint => IQ[55], :result => { :vendor =>"robtex", :product=>"Viking DNS module", :version=>""}, },
358
+ { :fingerprint => IQ[59], :result => { :vendor =>"Max Feoktistov", :product=>"small HTTP server [recursion enabled]", :version =>""}, },
359
+ { :fingerprint => IQ[60], :result => { :vendor =>"Axis", :product=>"video server", :version =>""}, },
360
+ { :fingerprint => IQ[62], :header => QY[7], :query => "1.0.0.127.in-addr.arpa. IN PTR", :ruleset => [
361
+ { :fingerprint => IQ[62], :result => { :vendor =>"Michael Tokarev", :product=>"rbldnsd",:version=>""}, :qv => ":version.bind", },
362
+ { :fingerprint => IQ[79], :result => { :vendor =>"4D", :product=>"WebSTAR", :version=>""}, },
363
+ { :fingerprint => IQ[83], :result => { :vendor =>"Netopia", :product =>"dsl/cable", :version => ""},},
364
+ { :fingerprint => IQ[90], :result => { :vendor =>"TZO", :product=>"Tzolkin DNS",:version=>""}, },
365
+ { :fingerprint => "query timed out", :result => { :vendor =>"Netopia", :product =>"dsl/cable", :version=>""},},
366
+ { :fingerprint => ".+", :state => "q0r62q7r?", }, ]
367
+ },
368
+ { :fingerprint => IQ[70], :result => { :vendor =>"Yutaka Sato", :product=>"DeleGate DNS", :version=>""},},
369
+ { :fingerprint => IQ[72], :result => { :vendor =>"", :product =>"sheerdns", :version=>""}, },
370
+ { :fingerprint => IQ[73], :result => { :vendor =>"Matthew Pratt", :product=>"dproxy", :version=>""}, },
371
+ { :fingerprint => IQ[74], :result => { :vendor =>"Brad Garcia", :product=>"dnrd",:version=>""}, },
372
+ { :fingerprint => IQ[76], :result => { :vendor =>"Sourceforge", :product=>"JDNSS",:version=>""}, },
373
+ { :fingerprint => IQ[77], :result => { :vendor =>"Dan Kaminsky", :product=>"nomde DNS tunnel",:version=>""}, },
374
+ { :fingerprint => IQ[78], :result => { :vendor =>"Max Feoktistov", :product=>"small HTTP server", :version =>""}, },
375
+ { :fingerprint => IQ[79], :result => { :vendor =>"robtex", :product=>"Viking DNS module", :version=>""}, },
376
+ { :fingerprint => IQ[80], :result => { :vendor =>"Fasthosts", :product=>"Envisage DNS server", :version=>""}, },
377
+ { :fingerprint => IQ[81], :result => { :vendor =>"WinGate", :product=>"Wingate DNS", :version=>""},},
378
+ { :fingerprint => IQ[82], :result => { :vendor =>"Ascenvision", :product=>"SwiftDNS", :version=>""},},
379
+ { :fingerprint => IQ[86], :result => { :vendor =>"Nortel Networks", :product=>"Instant Internet",:version=>""}, },
380
+ { :fingerprint => IQ[87], :result => { :vendor =>"ATOS", :product=>"Stargate ADSL", :version=>""},},
381
+ { :fingerprint => IQ[88], :result => { :vendor =>"3Com", :product=>"Office Connect Remote", :version=>""},},
382
+ { :fingerprint => IQ[89], :result => { :vendor =>"Alteon", :product=>"ACEswitch", :version=>""},},
383
+ { :fingerprint => IQ[90], :result => { :vendor =>"javaprofessionals", :product=>"javadns/jdns", :version=>""},},
384
+
385
+ { :fingerprint => IQ[92], :result => { :vendor =>"Beehive", :product=>"CoDoNS",:version=>""}, },
386
+ { :fingerprint => ".+", :state => "q0r?", },
387
+
388
+ ].freeze
389
+ end