# DNS Fingerprinting


# Announcing FP

*The* tool for DNS fingerprinting is [fpdns](https://github.com/kirei/fpdns), which is Perl based.
In recent times development seems to have picked up, but a little competition never hurt
anyone, so I wrote `fp` in Go. Fp is also a fingerprint program for DNS servers. Its aim is to
be more readable then `fpdns` is (was?). And make it more easy to add new server types.

 Help needed!

Do you have some old(er) nameserver laying around that can be queried? Does your (sick) mind
know of a few extra evil queries that can be sent to nameservers? If so, please contact
me: `query@evilquery.nl`. I want to get to a point where `fp` sends about 10 queries that
can be used to identify a server. 

 Fingerprint

A fingerprint in `fp` looks like this:

    .,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,4097,NSID

It has 20 fields, which are:

1. Domain name, `.` in this example;
2. Class, `CH` here;
3. Type, `TXT` here;
4. Opcode, `QUERY`;
5. Rcode, `NOERROR`;
6. Query response, `qr`, lowercase means false (not set), uppercase means true;
7. Authoritative, `aa`, lowercase. Thus not set here;
8. Truncated, `tc`, not set;
9. Recursion Desired, `RD`, uppercase, thus set;
9. Recursion Available, `ra`;
9. Authenticated Data, `ad`;
9. Checking Disabled, `cd`;
9. Zero, `z`;
9. Question section length, 1 here;
9. Answer section length, 0;
9. Authoritative section length, 0;
9. Additional section length, 0;
9. DNSSEC OK, `DO` (uppercase, thus set);
9. UDP bufsize, set to 4097;
9. NSID, uppercase: request NSID (or NSID was set).

These fingerprints are also used in *creating* the DNS queries that are send to nameserver(s)
being tested.

A full nameserver fingerprint consists out of multiple of these fingerprints. Right now
`fp` fires off 3 queries to test a server, so each nameserver fingerprint *must* also
consist out of 3 fingerprints. The nameserver [fingerprint of BIND9](https://github.com/miekg/godns/tree/master/examples/fp/data/Bind9)
looks like:

    # BIND9 fingerprints
    .,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID
    auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid
    bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid

When `fp` is extended with an extra fingerprint, this BIND9 fingerprint also
needs to get an extra fingerprint.

 Trying it yourself

As said, Currently `fp` only uses three queries, but this is expected to be increased in the
near future. In the [data directory](https://github.com/miekg/godns/tree/master/examples/fp/data), 
the file `q` holds the fingerprints of the queries to ask. Currently
[it](https://github.com/miekg/godns/tree/master/examples/fp/data/q) looks like this:

    # These are the queries that we ask the nameserver being identified
    #
    # The order is important, as the data files of the known nameservers are compared
    # in this order.
    .,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,4097,NSID
    auThoRs.bInD.,CH,TXT,QUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,z,1,0,0,0,do,0,nsid
    bind.,NONE,SOA,NOTIFY,NOERROR,qr,AA,tc,RD,ra,ad,cd,Z,1,0,0,0,do,0,nsid

A local run looks like this (this is abbreviated):

    % ./fp @localhost
    Server type     Diffs       Fingerprint         Recevied
    Bind9   0 .,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID .,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID
    Bind9   0 auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid
    Bind9   0 bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
            =
    Differences:    0

    Nsd3    2 .,CH,TXT,QUERY,NOERROR,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,nsid .,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID
    Nsd3    3 auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,aa,tc,rd,ra,ad,cd,z,1,0,0,0,do,0,nsid auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid
    Nsd3    6 .,CLASS0,TYPE0,NOTIFY,NXDOMAIN,QR,AA,tc,RD,ra,ad,cd,z,0,0,0,0,do,0,nsid bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
                =
    Differences:    11

What do you see here? On the left the nameserver type we're testing, then a number. This number represent the number of *differences* with the
stored fingerprint for this server. When this number is zero, it means the reply from the unknown server is an *exact* match with
one of the stored fingerprints. In general, the lower the number, the more exact the hit was.
For `bind9` in the example above, the accumulated number of differences is zero. This indicates the server is probably a BIND9 server.

For `nsd3` the story is completely different. The accumulated number of differences is 11, so this server probably isn't a NSD3 server.

# Report

With, `-report` fp will just show the fingerprint of a nameserver. If the server is positively identified, the finger
print can be added to `fp`:

    % ./fp -report @localhost
    # Fingerprint of <Nameserver> <version>
    # Supplied by <Name> on <Date>
    #
    .,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID
    auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid
    bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid


