Incorporating dns_reponse in dns_request

Hello All,

Below is my event for dns_request in my site specific dns.bro policy.
It currently creates a notice.log entry (and eventually an email alert)
when any internal host does a look up for a domain in our
hostile_domain_list.

Example:
‘172.x.x.x queried ‘very.bad.org’ @ 2011-03-16-12:41:13.560817003 (EST)’

The only thing missing from this is the returned IP address, if one was
returned.

Current Function (with zone transfer logic removed for brevity):
event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count)
{
local id = c$id;
local orig = id$orig_h;
local resp = id$resp_h;
local session = lookup_DNS_session(c, msg$id);
local anno = DNS_query_annotation(c, msg, query, qtype, F);
local report = fmt("%.06f #%d %s", network_time(), session$id, c$id$orig_h);
local q: string;

if ( orig in okay_to_lookup_sensitive_hosts )
return;

if ( logging )
print dns_log, fmt("%s", report);

Check to see if this is a host or MX lookup for a designated hostile domain.

local subq = second_level_domain(query);
if ( check_domain_list && (query_types[qtype] == “A” || query_types[qtype] == “MX”) && subq in hostile_domain_list )
{
if( subq in hostile_domain_list[subq] || third_level_domain(query) in hostile_domain_list[subq] )
NOTICE([$note=SensitiveDNS_Lookup, $conn=c, $msg=fmt("%s queried ‘%s’ @ %T (EST)", id$orig_h, query, network_time())]);
}
session$pending_queries[msg$id] = anno;
session$last_active = network_time();
}

I have tried to incorporate code from some of the other functions like creating a local drr variable and passing that to the function, but haven’t had any luck.

Something like this:
function insert_name(c: connection, msg: dns_msg, ans: dns_answer, a: addr)
{
local drr: dns_response_record;

So, I guess my question is, is there a way to evaluate a DNS query along with its corresponding response and return an IP address in this same event?

I assume this may be a ‘no’ if each is handled completely independent.

Thanks for listening…err…reading!

Will

You're right, each is handled independently. If you check my github repository, there is a dns-ext.bro script[1], but it has memory trouble on live traffic. If you still want to test it though, it does what you want by tying the request and response(s) together.

You could write code like this if you load the dns-ext script:

event dns_ext(id: conn_id, di: dns_ext_session_info)
  {
  local subq = second_level_domain(di$query);
  if ( check_domain_list && (query_types[qtype] == "A" || query_types[qtype] == "MX") && subq in hostile_domain_list )
  {
  if( subq in hostile_domain_list[subq] || third_level_domain(di$query) in hostile_domain_list[subq] )
    NOTICE([$note=SensitiveDNS_Lookup, $conn=c, $msg=fmt("%s queried '%s' @ %T (EST) and the responses were: %s", id$orig_h, query, network_time(), di$replies)]);
               }
  }

This is very similar to one of the techniques we'll likely have in the next release for extension of shipped scripts, but that code above should do everything you were looking to do in the script you emailed.

Have fun!
  .Seth

1. https://github.com/sethhall/bro_scripts/blob/master/testing/dns-ext.bro

Oops, almost complete. The above should be...

  if ( check_domain_list && (query_types[di$qtype] == "A" || query_types[di$qtype] == "MX") && subq in hostile_domain_list )

  .Seth

Thanks Seth.

I will let you know how it works for us. I can understand how it could strain system resources attempting to correlate the events in real time. It will also be interesting to see how it will react on a domain that is sinkhole’d. Our spam appliance, for example, will retry the query 8-10 times until it gives up on domains we have sunk.

Will

The memory problem is a programming error on my part. It's been on my list to fix for a really long time. :slight_smile:

  .Seth