
At Farsight, we work with a large amount of Passive DNS data, and we’re alwayslooking formore.While this data powers our flagship DNSDB, we alsobroadcast the raw Passive DNS data on theSecurity Information Exchange(SIE) (as channel 202) for those interested in an unfiltered real-time view ofworldwide DNS activity.
In this article, we present a simple example program showing how to filtersome potentially interesting information from our raw Passive DNS feed, usingthe Farsight Security-maintained open source C APIs
nmsg
and
wdns
. If youhaven’t already familiarized yourself with the NMSG C API, please readthis articlefor an introduction to the basics.
The DNSSEC suite of standards allows domain owners to sign their DNSinformation, authoritative DNS servers to serve up this signature information,and DNS clients to verify the signatures to prevent DNS forgery. Thesestandards require DNSSEC transactions to use a standardized DNS extensionmechanism (
). Because Farsight’sraw passive DNS information includes complete queries and responses, we candirectly observe
EDNS0
use.
We can also directly observe
EDNS0
non-compliance, and thus find some nameservers which are not yet ready for DNSSEC, and the hostnames for which theyare authoritative. We present an example program to extract this information:
The full code for the program, dnsqr_filter, can be found onFarsight Security’s blog-code GitHub page.
is a basic skeleton for filtering the raw passive DNS NMSG payloadsavailable on SIE. It provides a command-line interface to a basic
nmsg
I/O loop supporting a subset of the
nmsg
sources and destinations supportedby nmsgtool, and evaluates
nmsg
payloads with a filter function
dnsqr_filter()
to select which packets arewritten to the output file.
The filter for this sample program resides in
.It looks for Passive DNS messages containing non-
EDNS0
responses to
ENDS0
queries, and tells the main loop to output these messages.
The filter code starts by declaring variables to hold return codes, parsed DNSmessages, pointers to
nmsg
data, and the result of our filtering.
int
dnsqr_filter(nmsg_message_t msg) {
nmsg_res nres;
wdns_res wres;
wdns_message_t response = {0}, query = {0};
uint8_t *data;
size_t len;
int result = 0;
It then fetches the DNS response from the
base
:
dnsqr
encoded NMSG,returning if no response is present.
nres = nmsg_message_get_field(msg, "response", 0, (void **)&data, &len);
if (nres != nmsg_res_success) return result;
Next, we parse the DNS response using the low-level C library
:
wres = wdns_parse_message(&response, data, len);
if (wres != wdns_res_success) return result;
If the response did not use
EDNS0
,
response.edns.present
will be false. Ifthis is the case, we check if the request used
EDNS0
, and tell the main loopto save this message if it did:
if (!dns.edns.present) {
nres = nmsg_message_get_field(msg, "query", 0,
(void **)&data, &len);
if (nres == nmsg_res_success) {
wres = wdns_parse_message(&query, data, len);
if (wres == wdns_res_success)
result = query.edns.present;
}
}
Finally, we clean up our parsed
wdns
messages and return our result.
wdns_clear_message(&query);
wdns_clear_message(&response);
return result;
}
Once you’ve downloaded the code, and made sure you’ve installed the
nmsg
and
wdns
libraries, building and running should be as simple as:
$ make
cc -c main.c
cc -c edns_filter.c
cc -o dnsqr_edns_filter main.o edns_filter.o -lnmsg -lwdns
$ dnsqr_edns_filter -C ch202 -w edns_failures.nmsg
... wait a few seconds ...
^C
And you should have a file full of non-
EDNS0
DNS activity, which you caninspect withnmsgtool,manipulate using
python
scripts and the python NMSG API, or crunch with more elaborate C programs if you’re so inclined.
If you are not on SIE, you can run this code on your own recursive DNS serversby using
nmsgtool
to gather passive DNS information. You first need totell
nmsgtool
the query source IP addresses or subnets your recursive DNSserver will be using:
$ export DNSQR_RES_ADDRS="192.168.0.1, 172.16.1.0/27"
Then run
dnsqr_edns_filter
listening on a socket, andfeed it with
nmsgtool
:
$ dnsqr_edns_filter -l 127.0.0.1/5353 -w edns_failures.nmsg &
$ nmsgtool -i (interface) -V base -T dnsqr -s 127.0.0.1/5353
or you can use
nmsgtool
to save a batch of
base
:
dnsqr
messages for later filtering:
$ nmsgtool -i (interface) -V base -T dnsqr -c (count) -w (file)
$ dnsqr_edns_filter -r (file) -w (somewhat-more-interesting-file)
Of course, if you have this sort of interesting data to work with,you should consider e-mailing [email protected] to get your data in front of even more security-mindedpeople!
Chris Mikkelson is a Senior Distributed Systems Engineer for Farsight Security, Inc.