A lot of BIND specific checks

This commit is contained in:
Miek Gieben 2011-09-21 14:22:43 +02:00
parent a91881457e
commit da2e464de1
4 changed files with 138 additions and 52 deletions

View File

@ -6,6 +6,7 @@ import (
const (
QUERY_NOERROR string = "QUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,z,0,0,0,0,do,0"
QUERY_NOTIFY string = "NOTIFY,NOERROR,qr,AA,tc,RD,ra,ad,cd,Z,0,0,0,0,do,0"
QUERY_ALL string = "QUERY,NOERROR,QR,AA,TC,RD,RA,AD,CD,Z,0,0,0,0,DO,0"
)
@ -44,9 +45,23 @@ func dnsServer(l *lexer) stateFn {
case !f.Do && f.UDPSize == 0 && f.Rcode == dns.RcodeSuccess:
// PowerDNS(SEC) clears DO bit, resets UDPSize. NOERROR
l.emit(&item{itemVendor, POWER})
return dnsPowerDNSLike
return dnsPowerdnsLike
case !f.Do && f.UDPSize == 0 && f.Rcode == dns.RcodeServerFailure:
// Neustar
l.emit(&item{itemVendor, NEUSTAR})
return dnsNeustarLike
case !f.Do && f.UDPSize == 0 && f.Rcode == dns.RcodeNotImplemented:
// Altas?
l.emit(&item{itemVendor, VERISIGN})
return dnsAtlasLike
case !f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeServerFailure:
// BIND8
fallthrough
case f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeServerFailure:
// BIND9 OLD
fallthrough
case f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeRefused:
// BIND leaves DO bit, but sets UDPSize to 4096. REFUSED.
// BIND9 leaves DO bit, but sets UDPSize to 4096. REFUSED.
l.emit(&item{itemVendor, ISC})
return dnsBindLike
case f.Do && f.UDPSize == 4097 && f.Rcode == dns.RcodeFormatError:
@ -62,6 +77,9 @@ func dnsServer(l *lexer) stateFn {
func dnsNsdLike(l *lexer) stateFn {
l.verbose("NsdLike")
l.setString(QUERY_NOERROR)
l.setQuestion("authors.bind.", dns.TypeTXT, dns.ClassCHAOS)
l.probe()
return nil
}
@ -69,6 +87,57 @@ func dnsNsdLike(l *lexer) stateFn {
func dnsBindLike(l *lexer) stateFn {
l.verbose("BindLike")
l.emit(&item{itemSoftware, BIND})
// Repeat the query, as we get a lot of information from it
l.setString("QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,0,0,0,0,DO,4097")
l.setQuestion(".", dns.TypeTXT, dns.ClassCHAOS)
f := l.probe()
switch {
case !f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeServerFailure:
l.emit(&item{itemVersionMajor, "8"})
case f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeServerFailure:
l.emit(&item{itemVersionMajor, "9"})
l.emit(&item{itemVersionMajor, "3"})
case f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeRefused:
// BIND9 leaves DO bit, but sets UDPSize to 4096. REFUSED.
l.emit(&item{itemVersionMajor, "9"})
l.emit(&item{itemVersionMajor, "[7..]"})
}
// Try authors.bind
l.setString(QUERY_NOERROR)
l.setQuestion("authors.bind.", dns.TypeTXT, dns.ClassCHAOS)
f = l.probe()
switch f.Rcode {
case dns.RcodeServerFailure:
// No authors.bind < 9
l.emit(&item{itemVersionMajor, "8"})
case dns.RcodeSuccess, dns.RcodeRefused:
// BIND 9 or BIND 10
l.emit(&item{itemVersionMajor, "[9..10]"})
}
// The three BIND (8, 9 and 10) behave differently when
// receiving a notify query
l.setString(QUERY_NOTIFY)
l.setQuestion("bind.", dns.TypeSOA, dns.ClassNONE)
f = l.probe()
switch {
case f.Opcode == dns.OpcodeNotify:
if f.Rcode == dns.RcodeRefused {
l.emit(&item{itemVersionMajor, "9"})
}
if f.Rcode == dns.RcodeServerFailure {
l.emit(&item{itemVersionMajor, "8"})
}
case f.Opcode == dns.OpcodeQuery && f.Rcode == dns.RcodeSuccess:
l.emit(&item{itemVersionMajor, "10"})
if !f.Response {
// Cardinal sin
l.emit(&item{itemVersionMinor, "-devel"})
l.emit(&item{itemVersionPatch, "20110809"})
}
}
return nil
}
@ -84,8 +153,20 @@ func dnsMaraLike(l *lexer) stateFn {
return nil
}
func dnsPowerDNSLike(l *lexer) stateFn {
l.verbose("PowerDNSLike")
func dnsPowerdnsLike(l *lexer) stateFn {
l.verbose("PowerdnsLike")
return nil
}
func dnsNeustarLike(l *lexer) stateFn {
l.verbose("NeustarLike")
return nil
}
func dnsAtlasLike(l *lexer) stateFn {
l.verbose("AtlasLike")
return nil
}

View File

@ -16,13 +16,17 @@ const (
POWERDNS = "PowerDNS"
WINDOWSDNS = "Windows DNS"
MARADNS = "MaraDNS"
NEUSTARDNS = "Neustar DNS"
ATLAS = "Atlas"
// Vendors
ISC = "ISC"
MARA = "MaraDNS.org" // check
NLNETLABS = "NLnet Labs"
MICROSOFT = "Microsoft"
POWER = "PowerDNS"
POWER = "PowerDNS.com"
NEUSTAR = "Neustar"
VERISIGN = "Verisign"
)
func startParse(addr string) {

View File

@ -20,8 +20,9 @@ const (
itemError itemType = iota
itemSoftware // the name of the DNS server software
itemVendor // vendor of the DNS software
itemVersionMin // the minimum version of the software (empty if not determined)
itemVersionMax // the maximum version of the software (empty if not determined)
itemVersionMinor // the minor version of the software (empty if not determined)
itemVersionMajor // the major version of the software (empty if not determined)
itemVersionPatch // the patch level of the software (empty if not determined)
)
// stateFn represents the state of the scanner as a function that returns the next state.

View File

@ -142,8 +142,8 @@ func NewClient() *Client {
c.Attempts = 1
c.ReplyChan = DefaultReplyChan
c.QueryChan = DefaultQueryChan
c.ReadTimeout = 0.5 * 1e9
c.WriteTimeout = 0.5 * 1e9
c.ReadTimeout = 1 * 1e9
c.WriteTimeout = 1 * 1e9
return c
}