#!/usr/bin/perl # # $Id: Fingerprint.pm,v 1.17 2005/09/05 13:33:36 jakob Exp $ # # Copyright (c) 2003,2004,2005 Roy Arends & Jakob Schlyter. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the authors may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 5.6.0; package Net::DNS::Fingerprint; use strict; use warnings; use Net::DNS 0.42; our $VERSION = "0.9.3"; my %default = ( source => undef, timeout => 5, retry => 1, forcetcp => 0, debug => 0, qversion => 0, qchaos => 0, ); my $versionlength = 40; my @qy = ("0,IQUERY,0,0,1,0,0,0,NOERROR,0,0,0,0", "0,NS_NOTIFY_OP,0,0,0,0,0,0,NOERROR,0,0,0,0", "0,QUERY,0,0,0,0,0,0,NOERROR,0,0,0,0", "0,IQUERY,0,0,0,0,1,1,NOERROR,0,0,0,0", "0,QUERY,0,0,0,0,0,0,NOTIMP,0,0,0,0", "0,IQUERY,1,0,1,1,1,1,NOERROR,0,0,0,0", "0,UPDATE,0,0,0,1,0,0,NOERROR,0,0,0,0", "0,QUERY,1,1,1,1,1,1,NOERROR,0,0,0,0", "0,QUERY,0,0,0,0,0,1,NOERROR,0,0,0,0", ); my %initrule = (header => $qy[0], query => ". IN A", ); my @iq = ("1,IQUERY,0,0,1,0,0,0,FORMERR,0,0,0,0", # iq0 "1,IQUERY,0,0,1,0,0,0,FORMERR,1,0,0,0", # iq1 "1,IQUERY,0,0,1,0,0,0,NOTIMP,0,0,0,0", # iq2 "1,IQUERY,0,0,1,0,0,0,NOTIMP,1,0,0,0", # iq3 "1,IQUERY,0,0,1,1,0,0,FORMERR,0,0,0,0", # iq4 "1,IQUERY,0,0,1,1,0,0,NOTIMP,0,0,0,0", # iq5 "1,IQUERY,0,0,1,1,0,0,NOTIMP,1,0,0,0", # iq6 "1,IQUERY,1,0,1,0,0,0,NOTIMP,1,0,0,0", # iq7 "1,QUERY,1,0,1,0,0,0,NOTIMP,1,0,0,0", "1,QUERY,0,0,0,0,0,0,NOTIMP,0,0,0,0", "1,IQUERY,0,0,1,1,0,0,FORMERR,1,0,0,0", # iq10 "1,NS_NOTIFY_OP,0,0,0,0,0,0,FORMERR,1,0,0,0", "1,NS_NOTIFY_OP,0,0,0,0,0,0,NOTIMP,0,0,0,0", "1,NS_NOTIFY_OP,0,0,0,0,0,0,NOTIMP,1,0,0,0", "1,NS_NOTIFY_OP,0,0,0,0,0,0,NXDOMAIN,1,0,0,0", "1,NS_NOTIFY_OP,0,0,0,0,0,0,REFUSED,1,0,0,0", "1,NS_NOTIFY_OP,0,0,0,0,0,0,SERVFAIL,1,0,0,0", "1,NS_NOTIFY_OP,0,0,0,1,0,0,FORMERR,1,0,0,0", "1,NS_NOTIFY_OP,0,0,0,1,0,0,NOTIMP,0,0,0,0", "1,NS_NOTIFY_OP,0,0,0,1,0,0,NOTIMP,1,0,0,0", "1,NS_NOTIFY_OP,0,0,0,1,0,0,REFUSED,1,0,0,0", # iq20 "1,NS_NOTIFY_OP,0,0,0,1,0,0,SERVFAIL,1,0,0,0", "1,NS_NOTIFY_OP,1,0,0,0,0,0,NOTIMP,1,0,0,0", "1,QUERY,1,0,0,0,0,0,NOTIMP,1,0,0,0", "1,NS_NOTIFY_OP,1,0,0,0,0,0,SERVFAIL,1,0,0,0", "1,IQUERY,0,0,0,0,1,1,NOTIMP,0,0,0,0", "1,IQUERY,0,0,0,0,0,0,NOTIMP,0,0,0,0", "1,IQUERY,0,0,1,1,1,1,FORMERR,0,0,0,0", "1,IQUERY,1,0,1,1,1,1,FORMERR,0,0,0,0", "1,QUERY,.,0,1,.,.,.,NOTIMP,.+,.+,.+,.+", "1,QUERY,.,0,1,.,.,.,.+,.+,.+,.+,.+", #iq30 "1,QUERY,0,0,.,.,0,0,NXDOMAIN,1,0,0,0", "1,QUERY,0,0,.,.,0,0,FORMERR,1,0,0,0", "1,UPDATE,0,0,0,0,0,0,NOTIMP,0,0,0,0", "1,UPDATE,0,0,0,1,0,0,NOTIMP,0,0,0,0", "1,QUERY,0,0,1,0,0,0,NOERROR,1,0,0,0", "1,QUERY,1,1,1,1,1,1,NOTIMP,1,0,0,0", "1,QUERY,0,0,0,0,0,0,NOERROR,1,0,.+,0", "1,QUERY,0,0,1,0,0,0,FORMERR,1,0,0,0", "1,IQUERY,0,0,1,0,1,1,NOTIMP,1,0,0,0", "1,IQUERY,0,0,0,1,1,1,REFUSED,1,0,0,0", #iq40 "1,UPDATE,0,0,0,1,0,0,REFUSED,1,0,0,0", "1,IQUERY,0,0,0,1,1,1,FORMERR,0,0,0,0", "1,IQUERY,0,0,0,1,0,0,NOTIMP,0,0,0,0", "1,QUERY,1,0,1,0,0,0,FORMERR,1,0,0,0", "1,UPDATE,0,0,0,0,0,0,FORMERR,1,0,0,0", "1,UPDATE,0,0,0,0,0,0,FORMERR,0,0,0,0", "1,QUERY,0,0,1,0,0,0,FORMERR,0,0,0,0", "1,QUERY,0,0,1,0,0,0,SERVFAIL,1,0,0,0", #iq48 "1,QUERY,1,0,1,0,0,0,NXDOMAIN,1,0,1,0", "1,QUERY,0,0,1,0,0,0,REFUSED,1,0,0,0", #iq50 "1,QUERY,0,0,1,0,0,0,NOERROR,1,1,0,0", "1,IQUERY,0,0,1,0,0,0,REFUSED,0,0,0,0", "1,QUERY,0,0,0,0,0,0,FORMERR,0,0,0,0", "1,QUERY,0,0,1,1,1,0,NOERROR,1,0,1,0", "1,QUERY,0,0,1,1,0,0,NOERROR,1,0,1,0", "1,QUERY,0,0,1,0,1,0,NOERROR,.+,.+,.+,.+", "1,QUERY,0,0,1,0,0,0,.+,.+,.+,.+,.+", "1,QUERY,1,0,1,0,0,0,NOERROR,1,1,0,0", "1,QUERY,0,0,1,1,0,0,SERVFAIL,1,0,0,0", "1,QUERY,1,0,1,1,0,0,NOERROR,1,1,0,0", #iq60 "1,QUERY,0,0,1,1,0,0,REFUSED,1,0,0,0", "1,QUERY,0,0,0,0,0,0,NOTIMP,1,0,0,0", "1,QUERY,1,0,1,1,0,0,NOERROR,1,0,1,0", "1,IQUERY,0,0,1,1,1,1,NOTIMP,0,0,0,0", "1,UPDATE,0,0,0,0,0,0,REFUSED,0,0,0,0", "1,IQUERY,0,0,0,1,1,1,NOTIMP,1,0,0,0", "1,IQUERY,0,0,0,1,0,0,NOTIMP,1,0,0,0", "1,QUERY,0,1,1,1,1,1,NOERROR,1,0,.,0", "1,QUERY,0,1,1,1,0,1,NOERROR,1,0,.,0", "1,IQUERY,0,0,1,0,0,0,REFUSED,1,0,0,0", #iq70 "1,IQUERY,1,0,1,1,1,1,NOTIMP,1,0,0,0", "1,IQUERY,0,0,1,0,0,0,NOERROR,1,0,0,0", "1,QUERY,1,0,1,1,0,0,NOERROR,1,0,0,0", "1,IQUERY,1,0,1,1,0,0,NXDOMAIN,1,0,0,0", "1,UPDATE,0,0,0,1,0,0,FORMERR,0,0,0,0", "1,IQUERY,1,0,1,0,0,0,NXDOMAIN,1,0,0,0", "1,QUERY,0,0,1,1,0,0,FORMERR,1,0,0,0", "1,QUERY,0,0,0,1,0,0,SERVFAIL,1,0,0,0", "1,QUERY,0,0,1,1,0,0,NOERROR,1,1,0,0", "1,IQUERY,1,0,1,0,0,0,NOERROR,1,0,0,0", #iq80 "1,IQUERY,1,0,1,1,0,0,NOTIMP,1,0,0,0", "1,QUERY,0,0,1,1,0,0,NOERROR,1,0,0,0", "1,QUERY,1,0,1,1,0,0,NOERROR,1,1,1,.+", "1,QUERY,0,0,1,1,0,0,REFUSED,0,0,0,0", "1,UPDATE,0,0,0,1,0,0,NOTIMP,1,0,0,0", "1,QUERY,1,0,0,1,0,0,NXDOMAIN,1,0,0,0", "1,QUERY,0,0,0,1,0,0,NOTIMP,0,0,0,0", "1,QUERY,0,0,0,0,0,0,REFUSED,1,0,0,0", "1,QUERY,1,0,1,1,0,0,NXDOMAIN,1,0,0,0", "1,QUERY,1,0,0,0,0,0,NOERROR,1,1,0,0", #iq90 "1,IQUERY,1,0,1,1,0,1,NOTIMP,1,0,0,0", "1,QUERY,0,0,0,1,0,0,NOTIMP,1,0,0,0", "1,QUERY,0,0,1,0,0,1,SERVFAIL,1,0,0,0", ); my @ruleset = ( { fingerprint => "query timed out" , header => $qy[0], query => "com. IN A", ruleset => [ { fingerprint => "query timed out", header => $qy[7], query => ". CH A", ruleset => [ { fingerprint => "query timed out", header => $qy[6], query => ". IN A", ruleset => [ { fingerprint => $iq[38], result => { vendor => "Digital Lumber", product => "Oak DNS", version =>"" }, qv => "version.oak",}, { fingerprint => "query timed out", result => "TIMEOUT",}, { fingerprint => ".+", state => "q0tq0tq7tq6r?", }, ] }, { fingerprint => $iq[35], result => { vendor => "XBILL", product => "jnamed (dnsjava)", version => "" }, }, { fingerprint => $iq[36], result => { vendor => "menandmice", product => "QuickDNS", version => ""}, }, { fingerprint => $iq[37], result => { vendor => "unknown", product => "NonSequitur DNS", version => ""}, }, { fingerprint => ".+", state => "q0tq0tq7r?", }, ] }, { fingerprint => $iq[35], result => { vendor => "eNom", product => "eNom DNS", version =>""}, }, { fingerprint => ".+", state => "q0tq0r?", },] }, { fingerprint => $iq[0], header => $qy[1], query=> "jjjjjjjjjjjj IN A", ruleset => [ { fingerprint => $iq[12], result => { vendor => "ISC", product => "BIND", version => "8.4.1-p1" }, qv => "version.bind",}, { fingerprint => $iq[13], result => { vendor => "ISC", product => "BIND", version => "8 plus root server modifications"}, qv => "version.bind",}, { fingerprint => $iq[15], result => { vendor => "Cisco", product => "CNR", version => ""}, }, { fingerprint => $iq[16], header => $qy[2], query => "hostname.bind CH TXT", ruleset => [ { fingerprint => $iq[58], result => { vendor => "ISC", product => "BIND", version => "8.3.0-RC1 -- 8.4.4"}, qv => "version.bind",}, { fingerprint => $iq[50], result => { vendor => "ISC", product => "BIND", version => "8.3.0-RC1 -- 8.4.4"}, qv => "version.bind",}, { fingerprint => $iq[48], result => { vendor => "ISC", product => "BIND", version => "8.2.2-P3 -- 8.3.0-T2A"}, qv => "version.bind",}, { fingerprint => ".+", state => "q0r0q1r16q2r?", },] }, { fingerprint => ".+", state => "q0r0q1r?", },] }, { fingerprint => $iq[1], header => $qy[2], query => ". IN IXFR", ruleset => [ { fingerprint => $iq[31], result => { vendor => "Microsoft", product => "Windows DNS", version => "2000" }, }, { fingerprint => $iq[32], result => { vendor => "Microsoft", product => "Windows DNS", version => "NT4" }, }, { fingerprint => $iq[50], result => { vendor => "Microsoft", product => "Windows DNS", version => "2003"}, }, { fingerprint => ".+", state => "q0r1q2r?", }, ] }, { fingerprint => $iq[2], header => $qy[1], ruleset => [ { fingerprint => $iq[11], result => { vendor => "ISC", product => "BIND", version => "9.2.3rc1 -- 9.4.0a0" }, qv => "version.bind",}, { fingerprint => $iq[12], header => $qy[3], ruleset => [ { fingerprint => $iq[25], header => $qy[6], ruleset => [ { fingerprint => $iq[33], result => { vendor => "bboy", product => "MyDNS", version => "" },}, { fingerprint => $iq[34], header => $qy[2], query => "012345678901234567890123456789012345678901234567890123456789012.012345678901234567890123456789012345678901234567890123456789012.012345678901234567890123456789012345678901234567890123456789012.0123456789012345678901234567890123456789012345678901234567890. IN A", ruleset => [ { fingerprint => $iq[47], result => { vendor => "NLnetLabs", product => "NSD", version => "1.0.3 -- 1.2.1"}, qv => "version.server", }, { fingerprint => $iq[48], header => $qy[2], query => "hostname.bind CH TXT", ruleset => [ { fingerprint => $iq[50], result => { vendor => "NLnetLabs", product => "NSD", version => "1.2.2" }, qv => "version.server", }, { fingerprint => $iq[51], header => $qy[8], query => ". IN A", ruleset => [ { fingerprint => $iq[93], result => { vendor => "NLnetLabs", product => "NSD", version => "1.2.3 -- 2.1.2" } , qv => "version.server", }, { fingerprint => $iq[48], result => { vendor => "NLnetLabs", product => "NSD", version => "2.1.3" }, qv => "version.server", }, { fingerprint => ".+", state => "q0r2q1r12q3r25q6r34q2r48q2r51q8r?", }, ] }, { fingerprint => ".+", state => "q0r2q1r12q3r25q6r34q2r48q2r?", }, ] }, { fingerprint => $iq[49], header => $qy[2], query => "hostname.bind CH TXT", ruleset => [ { fingerprint => $iq[50], result => { vendor => "NLnetLabs", product => "NSD", version => "1.2.2 [root]"} , qv => "version.server", }, { fingerprint => $iq[51], result => { vendor => "NLnetLabs", product => "NSD", version => "1.2.3 [root]"}, qv => "version.server", }, { fingerprint => ".+", state => "q0r2q1r12q3r25q6r34q2r49q2r?", }, ] }, { fingerprint => $iq[53], result => { vendor => "NLnetLabs", product=>"NSD", version => "1.0.2"}, qv => "version.server", }, { fingerprint => ".+", state => "q0r2q1r12q3r25q6r34q2a?", },] }, { fingerprint => ".+", state => "q0r2q1r12q3r25q6r?", },] }, { fingerprint => $iq[26], result => { vendor => "VeriSign", product => "ATLAS", version => ""},}, { fingerprint => ".+", state => "q0r2q1r12q3r?", },] }, { fingerprint => $iq[15], header => $qy[6], ruleset => [ { fingerprint => $iq[45], result => { vendor => "Nominum", product =>"ANS", version =>""}, qv => "version.bind",}, { fingerprint => $iq[65], result => { vendor => "ISC", product => "BIND", version => "9.2.3rc1 -- 9.4.0a0" }, qv => "version.bind",}, { fingerprint => $iq[46], header => $qy[7], ruleset => [ { fingerprint => $iq[56], result => { vendor => "ISC", product => "BIND", version => "9.0.0b5 -- 9.0.1" }, qv => "version.bind",}, { fingerprint => $iq[57], result => { vendor => "ISC", product => "BIND", version => "9.1.0 -- 9.1.3" }, qv => "version.bind",}, { fingerprint => ".+", state => "q0r2q1r15q6r46q7r?", }, ] }, { fingerprint => ".+", state => "q0r2q1r15q6r?", },] }, { fingerprint => $iq[16], header => $qy[4], ruleset => [ { fingerprint => $iq[29], result => { vendor => "ISC", product => "BIND", version => "9.2.0a1 -- 9.2.0rc3"}, qv => "version.bind",}, { fingerprint => $iq[30], header => $qy[0], query => ". A CLASS0" , ruleset => [ { fingerprint => $iq[2], result => { vendor=>"ISC", product => "BIND", version =>"9.2.0rc7 -- 9.2.2-P3"}, qv => "version.bind", }, { fingerprint => $iq[0], result => { vendor=>"ISC", product => "BIND", version =>"9.2.0rc4 -- 9.2.0rc6"}, qv => "version.bind", }, { fingerprint => ".+", result => { vendor => "ISC", product => "BIND", version =>"9.2.0rc4 -- 9.2.2-P3"}, qv => "version.bind", }, ] }, { fingerprint => ".+", state => "q0r2q1r16q4r?", },] }, { fingerprint => ".+", state => "q0r2q1r?", }, ] }, { fingerprint => $iq[3], header => $qy[1], ruleset => [ { fingerprint => "query timed out", header => $qy[5], ruleset => [ { fingerprint => $iq[3], result => { vendor => "sourceforge", product =>"Dents", version =>""}, qv => "version.bind", }, { fingerprint => $iq[81], result => { vendor => "Microsoft", product => "Windows DNS", version => "2003" },}, { fingerprint => $iq[91], result => { vendor => "Microsoft", product => "Windows DNS", version => "2003" },}, { fingerprint => ".+", state => "q0r3q1tq5r?", }, ] }, { fingerprint => $iq[14], result => { vendor => "UltraDNS", product => "", version =>"v2.7.0.2 -- 2.7.3"}, qv => "version.bind", }, { fingerprint => $iq[13], header => $qy[5], ruleset => [ { fingerprint => $iq[39], result => { vendor => "pliant", product => "DNS Server", version =>""},}, { fingerprint => $iq[7], result => { vendor => "JHSOFT", product => "simple DNS plus", version =>""}, }, { fingerprint => $iq[71], header => $qy[6], ruleset => [ { fingerprint => $iq[41], result => { vendor =>"Netnumber", product =>"ENUM server", version =>""}, }, { fingerprint => $iq[85], result => { vendor =>"Raiden", product => "DNSD", version => ""}, }, ] }, { fingerprint => ".+", state => "q0r3q1r13q5r?", }, ] }, { fingerprint => ".+", state => "q0r3q1r?", }, ] }, { fingerprint => $iq[4], header => $qy[1], query=> "jjjjjjjjjjjj IN A", ruleset => [ { fingerprint => $iq[17], result => { vendor => "ISC", product => "BIND", version =>"9.0.0b5 -- 9.0.1 [rcursion enabled]"},qv => "version.bind", }, { fingerprint => $iq[18], header => $qy[5], query=> ". IN A" , ruleset => [ { fingerprint => $iq[27], result => { vendor => "ISC", product => "BIND", version => "4.9.3 -- 4.9.11"}, qv => "version.bind", }, { fingerprint => $iq[28], result => { vendor => "ISC", product => "BIND", version => "4.8 -- 4.8.3"}, }, { fingerprint => ".+", state => "q0r4q1r18q5r?", }, ] }, { fingerprint => $iq[19], result => {vendor => "ISC", product =>"BIND", version => "8.2.1 [recursion enabled]"}, qv => "version.bind", }, { fingerprint => $iq[20], header => $qy[3], query=> ". IN A", ruleset => [ { fingerprint => $iq[42], result => {vendor => "ISC", product =>"BIND", version =>"8.1-REL -- 8.2.1-T4B [recursion enabled]"}, qv => "version.bind", }, { fingerprint => ".+", state => "q0r4q1r20q3r?", },] }, { fingerprint => $iq[21], header => $qy[2], query => "hostname.bind CH TXT", ruleset => [ { fingerprint => $iq[60], result => {vendor =>"ISC", product => "BIND", version => "8.3.0-RC1 -- 8.4.4 [recursion enabled]"}, qv => "version.bind",}, { fingerprint => $iq[59], header => $qy[7], query=> ". IN A", ruleset => [ { fingerprint => $iq[68], result => {vendor =>"ISC", product => "BIND", version => "8.1-REL -- 8.2.1-T4B [recursion enabled]"}, qv => "version.bind", }, { fingerprint => $iq[69], result => {vendor =>"ISC", product => "BIND", version => "8.2.2-P3 -- 8.3.0-T2A [recursion enabled]"}, qv => "version.bind",}, { fingerprint => "connection failed", result => { vendor =>"Runtop", product => "dsl/cable", version =>""},}, { fingerprint => ".+", state => "q0r4q1r21q2r59q7r?", },] }, { fingerprint => $iq[58], result => {vendor => "ISC", product =>"BIND", version => "8.3.0-RC1 -- 8.4.4 [recursion local]"}, qv => "version.bind",}, { fingerprint => $iq[50], result => {vendor => "ISC", product =>"BIND", version => "8.3.0-RC1 -- 8.4.4 [recursion local]"}, qv => "version.bind",}, { fingerprint => $iq[61], result => {vendor => "ISC", product =>"BIND", version => "8.3.0-RC1 -- 8.4.4 [recursion local]"}, qv => "version.bind",}, { fingerprint => $iq[48], result => {vendor => "ISC", product =>"BIND", version => "8.2.2-P3 -- 8.3.0-T2A [recursion local]"}, qv => "version.bind",}, { fingerprint => ".+", state => "q0r4q1r21q2r?", },] }, { fingerprint => ".+", state => "q0r4q1r?", }, ] }, { fingerprint => $iq[5], header => $qy[1], ruleset => [ { fingerprint => $iq[11], result => { vendor => "ISC", product => "BIND", version => "9.2.3rc1 -- 9.4.0a0", option => "recursion enabled,split view" }, qv => "version.bind",}, { fingerprint => $iq[17], result => {vendor => "ISC", product =>"BIND", version => "9.2.3rc1 -- 9.4.0a0 [recursion enabled]"}, qv => "version.bind",}, { fingerprint => $iq[18], header => $qy[5], ruleset => [ { fingerprint => $iq[5], header => $qy[7], query => ". IN A", ruleset => [ { fingerprint => $iq[84], result => {vendor => "Nominum", product =>"CNS", version => ""}, qv => "version.bind",}, { fingerprint => $iq[59], result => {vendor => "Mikrotik", product =>"dsl/cable", version => ""}, }, { fingerprint => $iq[82], result => {vendor => "Mikrotik", product =>"dsl/cable", version => ""}, }, { fingerprint => ".+", state => "q0r5q1r18q5r5q7r?", }, ] }, { fingerprint => $iq[64], result => "unknown, smells like old BIND 4", }, { fingerprint => ".+", state => "q0r5q1r18q5r?", }, ] }, { fingerprint => $iq[20], header => $qy[7], ruleset => [ { fingerprint => $iq[54], result => {vendor => "ISC", product =>"BIND", version => "9.0.0b5 -- 9.0.1 [recursion enabled]"}, qv => "version.bind",}, { fingerprint => $iq[55], result => {vendor => "ISC", product =>"BIND", version => "9.1.0 -- 9.1.3 [recursion enabled]"}, qv => "version.bind",}, { fingerprint => $iq[63], result => {vendor => "ISC", product =>"BIND", version => "4.9.3 -- 4.9.11 [recursion enabled]"}, qv => "version.bind",}, { fingerprint => $iq[61], result => {vendor => "ISC", product =>"BIND", version => "9.0.0b5 -- 9.1.3 [recursion local]"}, qv => "version.bind",}, { fingerprint => ".+", state => "q0r5q1r20q7r?", }, ] }, { fingerprint => $iq[21], header => $qy[4], ruleset => [ { fingerprint => "query timed out", result => {vendor => "ISC", product =>"BIND", version => "9.2.0a1 -- 9.2.2-P3 [recursion enabled]"}, qv => "version.bind", }, { fingerprint => $iq[29], result => {vendor => "ISC", product =>"BIND", version => "9.2.0a1 -- 9.2.0rc3 [recursion enabled]"}, qv => "version.bind", }, { fingerprint => $iq[61], header => $qy[0], query => ". A CLASS0" , ruleset => [ { fingerprint => $iq[2], result => {vendor => "ISC", product =>"BIND", version => "9.2.0rc7 -- 9.2.2-P3 [recursion local]"}, qv => "version.bind", }, { fingerprint => $iq[0], result => {vendor => "ISC", product =>"BIND", version => "9.2.0a1 -- 9.2.0rc6 [recursion local]"}, qv => "version.bind", }, { fingerprint => ".+", result => {vendor => "ISC", product =>"BIND", version => "9.2.0a1 -- 9.2.2-P3 [recursion local]"}, qv => "version.bind", }, ] }, { fingerprint => $iq[30], header => $qy[0], query => ". A CLASS0" , ruleset => [ { fingerprint => $iq[2], result => {vendor => "ISC", product =>"BIND", version => "9.2.0rc7 -- 9.2.2-P3 [recursion enabled]"}, qv => "version.bind", }, { fingerprint => $iq[0], result => {vendor => "ISC", product =>"BIND", version => "9.2.0rc4 -- 9.2.0rc6 [recursion enabled]"}, qv => "version.bind", }, { fingerprint => ".+", result => {vendor => "ISC", product =>"BIND", version => "9.2.0rc4 -- 9.2.2-P3 [recursion enabled]"}, qv => "version.bind", }, ] }, { fingerprint => ".+", state => "q0r5q1r21q4r?", }, ] }, { fingerprint => ".+", state => "q0r5q1r?", }, ] }, { fingerprint => $iq[6], header => $qy[1], ruleset => [ { fingerprint => $iq[15], result => {vendor => "incognito", product =>"DNS commander", version => "v2.3.1.1 -- 4.0.5.1"}, qv => "version.bind", }, { fingerprint => $iq[19], header => $qy[3], ruleset => [ { fingerprint => $iq[66], result => {vendor => "vermicelli", product =>"totd", version => ""}, }, { fingerprint => $iq[67], result => {vendor => "JHSOFT", product =>"simple DNS plus", version => "[recursion enabled]"}, }, { fingerprint => ".+", state => "q0r6q1r19q3r?", }, ] }, { fingerprint => ".+", state => "q0r6q1r?", }, ] }, { fingerprint => $iq[7], header => $qy[1], ruleset => [ { fingerprint => $iq[22], result => {vendor => "PowerDNS", product =>"PowerDNS", version => "2.9.4 -- 2.9.11"}, qv => "version.bind", }, { fingerprint => $iq[24], result => {vendor => "PowerDNS", product =>"PowerDNS", version => "2.8 -- 2.9.3"}, qv => "version.bind", }, { fingerprint => ".+", state => "q0r7q1r?", }, ] }, { fingerprint => $iq[8], header => $qy[1], ruleset => [ { fingerprint => $iq[23], header => $qy[2] , query => ". CH A", ruleset => [ { fingerprint => "query timed out", result => { vendor => "DJ Bernstein", product => "TinyDNS", version => "1.04"} ,}, { fingerprint => $iq[32], result => {vendor => "DJ Bernstein", product => "TinyDNS", version => "1.05"} ,}, { fingerprint => ".+", state => "q0r8q1r23q2r?",},] }, { fingerprint => ".+", state => "q0r8q1r?", }, ] }, { fingerprint => $iq[9], header => $qy[1], ruleset => [ { fingerprint => $iq[9], result => { vendor => "Sam Trenholme", product =>"MaraDNS", version => ""}, qv => "erre-con-erre-cigarro.maradns.org"}, { fingerprint => ".+", state => "q0r9q1r?", }, ] }, { fingerprint => $iq[10], result => { vendor => "Microsoft", product =>"?", version => ""}, }, { fingerprint => $iq[26], result => { vendor => "Meilof Veeningen", product =>"Posadis", version =>""}, }, { fingerprint => $iq[43], header => $qy[6], ruleset => [ { fingerprint => $iq[34], result => { vendor => "Paul Rombouts", product =>"pdnsd", version =>""}, }, { fingerprint => $iq[75], result => { vendor => "antirez", product =>"Yaku-NS", version =>""}, }, { fingerprint => ".+", state => "q0r43q6r?", }, ] }, { fingerprint => $iq[44], result => { vendor =>"cpan", product=>"Net::DNS Nameserver", version =>""}, qv => "version.bind", }, { fingerprint => $iq[52], result => { vendor =>"NLnetLabs", product=>"NSD", version => "1.0 alpha"}, }, { fingerprint => $iq[55], result => { vendor =>"robtex", product=>"Viking DNS module", version=>""}, }, { fingerprint => $iq[59], result => { vendor =>"Max Feoktistov", product=>"small HTTP server [recursion enabled]", version =>""}, }, { fingerprint => $iq[60], result => { vendor =>"Axis", product=>"video server", version =>""}, }, { fingerprint => $iq[62], header => $qy[7], query => "1.0.0.127.in-addr.arpa. IN PTR", ruleset => [ { fingerprint => $iq[62], result => { vendor =>"Michael Tokarev", product=>"rbldnsd",version=>""}, qv => "version.bind", }, { fingerprint => $iq[79], result => { vendor =>"4D", product=>"WebSTAR", version=>""}, }, { fingerprint => $iq[83], result => { vendor =>"Netopia", product =>"dsl/cable", version => ""},}, { fingerprint => $iq[90], result => { vendor =>"TZO", product=>"Tzolkin DNS",version=>""}, }, { fingerprint => "query timed out", result => { vendor =>"Netopia", product =>"dsl/cable", version=>""},}, { fingerprint => ".+", state => "q0r62q7r?", }, ] }, { fingerprint => $iq[70], result => { vendor =>"Yutaka Sato", product=>"DeleGate DNS", version=>""},}, { fingerprint => $iq[72], result => { vendor =>"", product =>"sheerdns", version=>""}, }, { fingerprint => $iq[73], result => { vendor =>"Matthew Pratt", product=>"dproxy", version=>""}, }, { fingerprint => $iq[74], result => { vendor =>"Brad Garcia", product=>"dnrd",version=>""}, }, { fingerprint => $iq[76], result => { vendor =>"Sourceforge", product=>"JDNSS",version=>""}, }, { fingerprint => $iq[77], result => { vendor =>"Dan Kaminsky", product=>"nomde DNS tunnel",version=>""}, }, { fingerprint => $iq[78], result => { vendor =>"Max Feoktistov", product=>"small HTTP server", version =>""}, }, { fingerprint => $iq[79], result => { vendor =>"robtex", product=>"Viking DNS module", version=>""}, }, { fingerprint => $iq[80], result => { vendor =>"Fasthosts", product=>"Envisage DNS server", version=>""}, }, { fingerprint => $iq[81], result => { vendor =>"WinGate", product=>"Wingate DNS", version=>""},}, { fingerprint => $iq[82], result => { vendor =>"Ascenvision", product=>"SwiftDNS", version=>""},}, { fingerprint => $iq[86], result => { vendor =>"Nortel Networks", product=>"Instant Internet",version=>""}, }, { fingerprint => $iq[87], result => { vendor =>"ATOS", product=>"Stargate ADSL", version=>""},}, { fingerprint => $iq[88], result => { vendor =>"3Com", product=>"Office Connect Remote", version=>""},}, { fingerprint => $iq[89], result => { vendor =>"Alteon", product=>"ACEswitch", version=>""},}, { fingerprint => $iq[90], result => { vendor =>"javaprofessionals", product=>"javadns/jdns", version=>""},}, { fingerprint => $iq[92], result => { vendor =>"Beehive", product=>"CoDoNS",version=>""}, }, { fingerprint => ".+", state => "q0r?", }, ); ###################################################################### sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; my %config = @_; foreach my $k (keys %default) { if (defined $config{$k}) { $self->{$k} = $config{$k}; } else { $self->{$k} = $default{$k}; } } bless $self, $class; return $self; } sub hash { my $self = shift; my $addr = shift; my $port = shift; $port = 53 unless($port); return $self->init($addr, $port); } sub string { my $self = shift; my $addr = shift; my $port = shift; $port = 53 unless($port); my %r = $self->hash($addr, $port); my @s = (); if (defined $r{error}) { push @s, $r{error}; } elsif (defined $r{result}) { push @s, $r{result}; } else { push @s, $r{vendor} if(defined $r{vendor}); push @s, $r{product} if(defined $r{product}); push @s, $r{version} if(defined $r{version}); push @s, "[$r{option}]" if(defined $r{option}); } push @s, $r{vstring} if(defined $r{vstring}); push @s, "($r{state};$r{id})" if($self->{debug}); return join(" ", @s); } sub query_version { my $self = shift; my $qserver = shift; my $qport = shift; my $ident = shift; my $rrset = " id: "; my $resolver = Net::DNS::Resolver->new; $resolver->nameservers($qserver); $resolver->port($qport); $resolver->srcaddr($self->{source}); $resolver->retry($self->{retry}); $resolver->retrans($self->{timeout}); $resolver->usevc($self->{forcetcp}); my $query = $resolver->query($ident, 'TXT', 'CH'); if ($query && $query->header->ancount > 0) { foreach my $rr ($query->answer) { ($rrset = $rrset . "\"" . $rr->txtdata . "\" ") if ($rr->type eq "TXT"); } $rrset =~ s/\n/\" \"/g; if (length($rrset) > $versionlength) { $rrset = substr($rrset,0,$versionlength)."..." } return $rrset; } return " id unavailable (".$resolver->errorstring.")"; } sub init { my $self = shift; my $qserver = shift; my $qport = shift; return $self->process($qserver, $qport, $initrule{header}, $initrule{query}, \@ruleset); } sub process { my $self = shift; my $qserver = shift; my $qport = shift; my $qheader = shift; my $qstring = shift; my $ruleref = shift; my $ver; my $id; my %ret; if ($self->{debug}) { print STDERR "==> PROCESS $qserver:$qport $qheader $qstring\n"; print STDERR "\n"; } my ($answer, $ress) = $self->probe($qserver, $qport, $qheader, $qstring); if ($answer) { $id = header2fp($answer->header); } else { $id = $ress; } print STDERR "==> \"$id\"\n" if ($self->{debug}); for my $rule (@$ruleref) { $ver = " "; # we must have a fingerprint die "missing fingerprint" unless (defined $rule->{fingerprint}); # skip to next rule unless we have a matching fingerprint next unless ($id =~ /$rule->{fingerprint}/); # return if we have a result if (defined $rule->{result}) { if (defined $rule->{qv}) { $ver = $self->query_version($qserver, $qport, $rule->{qv}) if $self->{qversion}; } if ($self->{qchaos}) { $ver = $self->query_version($qserver, $qport, "version.bind"); } $ret{vstring} = $ver if($ver); if (ref($rule->{result})) { $ret{vendor} = $rule->{result}{vendor}; $ret{product} = $rule->{result}{product}; $ret{version} = $rule->{result}{version}; $ret{option} = $rule->{result}{option}; } else { $ret{result} = $rule->{result}; } return %ret; } # print state if no matches if (defined $rule->{state}) { $ver = $self->query_version($qserver, $qport, "hostname.bind") if $self->{qversion}; $ret{vstring} = $ver if($ver); $ret{error} = "No match found"; $ret{state} = $rule->{state}; $ret{id} = $id; return %ret; } # update query if defined if (defined $rule->{query}) { $qstring = $rule->{query}; } # recurse if we have a new header and a new ruleset if (defined $rule->{header} && defined $rule->{ruleset}) { return $self->process($qserver, $qport, $rule->{header}, $qstring, $rule->{ruleset}); } die "syntax error"; } return %ret; } sub header2fp { my $header = shift; my @list = ($header->qr, $header->opcode, $header->aa, $header->tc, $header->rd, $header->ra, $header->ad, $header->cd, $header->rcode, $header->qdcount, $header->ancount, $header->nscount, $header->arcount); return join(",", @list); } sub fp2header { my @list = split(/,/, shift); my $header = Net::DNS::Header->new; $header->qr(shift @list); $header->opcode(shift @list); $header->aa(shift @list); $header->tc(shift @list); $header->rd(shift @list); $header->ra(shift @list); $header->ad(shift @list); $header->cd(shift @list); $header->rcode(shift @list); $header->qdcount(shift @list); $header->ancount(shift @list); $header->nscount(shift @list); $header->arcount(shift @list); return $header; } sub probe { my $self = shift; my $qserver = shift; my $qport = shift; my $qheader = shift; my @qstring = split(/ /, shift); my $header = fp2header($qheader); my $packet = Net::DNS::Packet->new(\$header->data); $packet->push("question", Net::DNS::Question->new(@qstring)); if ($self->{debug}) { print STDERR "==> QUERY BEGIN\n"; print STDERR $packet->print, "\n"; print STDERR "==> QUERY END\n"; print STDERR "\n"; } my $resolver = Net::DNS::Resolver->new; $resolver->nameservers($qserver); $resolver->port($qport); $resolver->srcaddr($self->{source}); $resolver->retry($self->{retry}); $resolver->retrans($self->{timeout}); $resolver->usevc($self->{forcetcp}); my $answer = $resolver->send($packet); if ($answer && $self->{debug}) { print STDERR "==> ANSWER BEGIN\n"; print STDERR $answer->string, "\n"; print STDERR "==> ANSWER END\n"; print STDERR "\n"; } return ($answer, $resolver->errorstring); } sub version { return $VERSION; } 1;