Hi,
Jakob and I spent the past few weeks hacking up a DNS implementation
fingerprint tool (where implementation == anything responding to a query).
This mail introduces the methodology of fingerprinting DNS
implementations.
A nameserver basically responds to a query. Inter-operability is an
obvious requirement here, the standard protocol behaviour of different DNS
implementations is expected to be the same.
Protocol behaviour of a DNS implementation is widely documented in the
case of a 'common' query. The DNS protocol is over 20 years old and since
its inception, there have been over 40 independant DNS implementations,
while some implementations have over 20 versions.
The methodology used to identify individual nameserver implementations is
based on "borderline" protocol behaviour. The DNS protocol offers a
multitude of message bits, response types, opcodes, classes, query types
and label types in a fashion that makes some mutually exclusive while some
are not used in a query messages at all. Not every implementation offers
the full set of features the DNS protocol set currently has. Some
implementations offer features outside the protocol set, and there are
implementations that do not comform to standards.
Also, new features added to - or bugs removed allow for differentiations
between versions of an implementation.
Methodology
We use a serie of "borderline" query-response messages to identify
implementations. A serie of query-response messages form a sequence.
We call the interpretation of these series to form a conclusion "DNS
sequencing".
As mentioned, responses to a "borderline" query is used in this method.
To be somewhat efficient, a tree can be constructed which consists of
queries (nodes) and responses (branches), where the leave nodes identify
the implementation.
Every path, from the root node (initial query) to a leave node (final
query) is essentially a "strain". The strains are used to distinguish
between, and as said, ultimatly identify implementations.
Parallel to this technique it is possible to identify some brands and
their versions by doing a specific query asking for the servers' version.
This technique does not satisfy our requirement since this has not been
implemented in all brands of nameservers (it is not part of any standard),
operators may have obscured the information and there are implementations
that try to resolve the query, essentially asking root-servers from a
different class for their version.
Implementation.
Our current software is written as a proof-of-concept. In field tests,
false positives were encountered when trying to identify a set of servers
residing behind a load-balancing apparatus where the servers itself are of
different implementations, or when a specific implementation behaves like
a forwarder.
We are actively looking for implementations not yet identified by this
tool to complement the set of strains.
The current set of strains identify the following implementations
and their versions:
ATLAS
BIND 4
BIND 4.8 -- 4.8.3
BIND 4.9.3 -- 4.9.11
BIND 8
BIND 8.1 -- 8.2.1T4B
BIND 8.2.1
BIND 8.2.2P3 -- 8.4.1
BIND 8.4.1P1
BIND 9
BIND 9.0.0b5 -- 9.0.1
BIND 9.1.0 -- 9.1.3
BIND 9.2.0a1 -- 9.2.0rc3
BIND 9.2.0rc4 -- 9.2.2P3
BIND 9.2.3rc1 -- 9.4.0a0
eNom DNS
Incognito DNS Commander
MARADNS
Microsoft Windows
Server 2003
Server 2000
Server NT4
MyDNS
Nominum ANS
Nominum CNS
NonSequitur DNS
NSD
Oak DNS
Pliant DNS Server
Posadis
PowerDNS
2.8 -- 2.9.3
2.9.4 -- 2.9.11
QuickDNS
Simple DNS plus
TinyDNS
UltraDNS
We are actively looking for volunteers who allow us to identify their
running code in some form or configuration of some version of:
chives
custom-dns
dents
dnrd
dnsmasq
gnudip-www
ibmdns
jeeves
lbdns
lbnamed
ldapdns
MacDNS
Microsoft Windows Server NT3.51
pdnsd
Stanford::DNSserver
yaku-ns
and/or
All other unidentified, unmentioned original code.
Thanks,
Roy Arends
Jakob Schlyter