dns.log

The Domain Name System (DNS) log, or dns.log, is one of the most important data sources generated by Zeek. Although recent developments in domain name resolution have challenged traditional methods for collecting DNS data, dns.log remains a powerful tool for security and network administrators.

Those interested in getting details on every element of the dns.log should refer to DNS::Info.

Throughout the sections that follow, we will inspect Zeek logs in JSON format.

Inspecting the dns.log

To inspect the dns.log, we will use the same techniques we learned earlier in the manual. First, we have a JSON-formatted log file, either collected by Zeek watching a live interface, or by Zeek processing stored traffic. We use the jq utility to review the contents.

zeek@zeek:~/zeek-test/json$ jq . -c dns.log
{"ts":1591367999.306059,"uid":"CMdzit1AMNsmfAIiQc","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":8555,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":28,"qtype_name":"AAAA","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":false,"Z":0,"rejected":false}

{"ts":1591367999.305988,"uid":"CMdzit1AMNsmfAIiQc","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":19671,"rtt":0.06685185432434082,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":1,"qtype_name":"A","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":true,"Z":0,"answers":["31.3.245.133"],"TTLs":[3600],"rejected":false}

As before, we could see each field printed on its own line:

zeek@zeek:~/zeek-test/json$ jq . dns.log
{
  "ts": 1591367999.306059,
  "uid": "CMdzit1AMNsmfAIiQc",
  "id.orig_h": "192.168.4.76",
  "id.orig_p": 36844,
  "id.resp_h": "192.168.4.1",
  "id.resp_p": 53,
  "proto": "udp",
  "trans_id": 8555,
  "query": "testmyids.com",
  "qclass": 1,
  "qclass_name": "C_INTERNET",
  "qtype": 28,
  "qtype_name": "AAAA",
  "rcode": 0,
  "rcode_name": "NOERROR",
  "AA": false,
  "TC": false,
  "RD": true,
  "RA": false,
  "Z": 0,
  "rejected": false
}
{
  "ts": 1591367999.305988,
  "uid": "CMdzit1AMNsmfAIiQc",
  "id.orig_h": "192.168.4.76",
  "id.orig_p": 36844,
  "id.resp_h": "192.168.4.1",
  "id.resp_p": 53,
  "proto": "udp",
  "trans_id": 19671,
  "rtt": 0.06685185432434082,
  "query": "testmyids.com",
  "qclass": 1,
  "qclass_name": "C_INTERNET",
  "qtype": 1,
  "qtype_name": "A",
  "rcode": 0,
  "rcode_name": "NOERROR",
  "AA": false,
  "TC": false,
  "RD": true,
  "RA": true,
  "Z": 0,
  "answers": [
    "31.3.245.133"
  ],
  "TTLs": [
    3600
  ],
  "rejected": false
}

As emphasized in the conn.log material, what an analyst derives from any log is a function of the questions that he or she is trying to ask of it. The dns.log captures application-level name resolution activity, assuming that traffic is not encrypted, as is the case with DNS over HTTPS (DoH) or DNS over TLS (DoT). Applications mainly use DNS to resolve names to IP addresses, IP addresses to names, and certain other functions. Intruders use DNS for the same purposes, but may also subvert the protocol to carry command-and-control traffic, obfuscated or encrypted payload data, or other unwanted functions. DNS is a suitable protocol for these nefarious activities because administrators tend to allow it throughout their purview, as it is necessary for normal network operation.

In brief, when looking at the dns.log, analysts will primarily want to know who is asking a question, what is the nature of the question, who answered the question, and how was the question answered.

Understanding the Second dns.log Entry

Let’s use this framework to parse the two log entries. We will start with the second entry. For reference, that entry is the following:

{
  "ts": 1591367999.305988,
  "uid": "CMdzit1AMNsmfAIiQc",
  "id.orig_h": "192.168.4.76",
  "id.orig_p": 36844,
  "id.resp_h": "192.168.4.1",
  "id.resp_p": 53,
  "proto": "udp",
  "trans_id": 19671,
  "rtt": 0.06685185432434082,
  "query": "testmyids.com",
  "qclass": 1,
  "qclass_name": "C_INTERNET",
  "qtype": 1,
  "qtype_name": "A",
  "rcode": 0,
  "rcode_name": "NOERROR",
  "AA": false,
  "TC": false,
  "RD": true,
  "RA": true,
  "Z": 0,
  "answers": [
    "31.3.245.133"
  ],
  "TTLs": [
    3600
  ],
  "rejected": false
}

According to this log entry, 192.168.4.76 asked 192.168.4.1 for the A record of the host testmyids.com, and received the answer 31.3.245.133. There are more details in the log, but those are the key elements an analyst should be able to extract.

Understanding the First dns.log Entry

Let’s take a look at the first dns.log entry. For reference, that entry is the following:

{
  "ts": 1591367999.306059,
  "uid": "CMdzit1AMNsmfAIiQc",
  "id.orig_h": "192.168.4.76",
  "id.orig_p": 36844,
  "id.resp_h": "192.168.4.1",
  "id.resp_p": 53,
  "proto": "udp",
  "trans_id": 8555,
  "query": "testmyids.com",
  "qclass": 1,
  "qclass_name": "C_INTERNET",
  "qtype": 28,
  "qtype_name": "AAAA",
  "rcode": 0,
  "rcode_name": "NOERROR",
  "AA": false,
  "TC": false,
  "RD": true,
  "RA": false,
  "Z": 0,
  "rejected": false
}

According to this log entry, 192.168.4.76 asked 192.168.4.1 for the AAAA record of the host testmyids.com, and did not receive an answer.

This is technically true, but it is not the whole story. If we augment stock Zeek with an additional script available from the project, we get a bit more information.

Specifically, we can enable a new script, policy/protocols/dns/auth-addl.zeek.

We can invoke the script using this syntax:

zeek@zeek:~/zeek-test/json2$ zeek -C LogAscii::use_json=T protocols/dns/auth-addl.zeek -r ../tm1t.pcap

The end result shows more information for the first dns.log entry:

zeek@zeek:~/zeek-test/json2$ cat dns.log | head -1
{"ts":1591367999.306059,"uid":"CQsafSKqmlOyqrgC6","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":8555,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":28,"qtype_name":"AAAA","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":false,"Z":0,"rejected":false,"auth":["ns59.1and1.co.uk"]}

The bolded auth item in the log entry shows that ns59.1and1.co.uk is the authoritative name server that is designated to answer questions about the AAAA record for testmyids.com.

There are more details in the log, but those are the key elements an analyst should be able to extract.

The uid and Other Fields

Note the uid field in both log entries is CMdzit1AMNsmfAIiQc. This is the same UID value that appeared in the conn.log entry for a DNS record. That means the DNS activity in the conn.log and the DNS activity in this dns.log entry are the same.

You could have used the UID in the conn.log to search for the corresponding records in the dns.log using this UID. For example:

zeek@zeek:~/zeek-test/json$ grep CMdzit1AMNsmfAIiQc dns.log
{"ts":1591367999.306059,"uid":"CMdzit1AMNsmfAIiQc","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":8555,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":28,"qtype_name":"AAAA","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":false,"Z":0,"rejected":false}

{"ts":1591367999.305988,"uid":"CMdzit1AMNsmfAIiQc","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":19671,"rtt":0.06685185432434082,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":1,"qtype_name":"A","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":true,"Z":0,"answers":["31.3.245.133"],"TTLs":[3600.0],"rejected":false}

Note the matching uid fields in the dns.log entries. In this simple example, these are the only two entries in the dns.log. Extrapolate this technique to logs with billions of records and you will appreciate the value!

Remember that a single conn.log entry summarized all of the DNS traffic associate with the “connection” bearing UID CMdzit1AMNsmfAIiQc. Zeek treated the 4 packets associated with this conversation as a connection because they shared the same source and destination IP addresses and ports, and occurred over the UDP protocol. The single conn.log entry had the timestamp 1591367999.305988, which is also the timestamp of the first dns.log entry.

Zeek’s DNS protocol analyzer created two log entries because it recognized two different DNS exchanges. The first involved a query and response for IPv6-related information, i.e., a AAAA record for testmyids.com. The second involved a query and response for IPv4-related information, i.e., an A record for testmyids.com. It is interesting to note that the DNS resolver on the 192.168.4.76 system requested IPv6 information first, and then IPv4.

Conclusion

Zeek’s dns.log is a critical log that offers a great deal of information on how systems are interacting with the Internet and each other. In the next section we will look at other core Internet protocols.