zeek/policy/dns-ext.bro
2010-10-26 17:03:19 -04:00

213 lines
5.7 KiB
Text

@load global-ext
@load dns
type dns_ext_session_info: record {
id: conn_id;
ts: time;
trans_id: count;
query: string;
qtype: count;
qclass: count;
total_answers: count &default=0;
rcode: count &default = 65536;
QR: bool &default=F;
Z: bool &default=F;
AA: bool &default=F;
RD: bool &default=F;
RA: bool &default=F;
TC: bool &default=F;
TTL: interval &default=0secs;
replies: set[string];
};
# Define the generic dns-ext event that can be handled from other scripts
global dns_ext: event(id: conn_id, di: dns_ext_session_info);
module DNS;
export {
# Follow this example to define domains that you would consider "local".
# This is primarily useful if you are monitoring authoritative nameservers,
# but also useful for any zones that *should* be pointing at your
# network.
# e.g.
#const local_domains = /(^|\.)(osu|ohio-state)\.edu$/ |
# /(^|\.)akamai(tech)?\.net$/ &redef;
const local_domains = /(^|\.)akamai(tech)?\.net$/ &redef;
redef enum Notice += {
# Raised when a non-local name is found to be pointing at a local host.
# This only works appropriately when all of your authoritative DNS
# servers are located in your "local_nets".
DNSExternalName,
};
}
global dns_sessions_ext: table[addr, addr, count] of dns_ext_session_info;
# This doesn't work with live traffic yet.
# It's waiting for support to dynamically construct pattern variables at init time.
#global dns_suffix_regex = build_regex(local_domains, "(^|\.)~~$");
#event bro_init()
# {
# local i: count = 0;
# local tmp_pattern: pattern;
# for ( d in local_domains )
# {
# tmp_pattern = string_to_pattern( fmt("=%s@", d), T );
#
# if ( i == 0 )
# pat = tmp_pattern;
# else
# pat = merge_pattern(tmp_pattern, pat);
# ++i;
# }
# }
event expire_DNS_session_ext(orig: addr, resp: addr, trans_id: count)
{
if ( [orig, resp, trans_id] in dns_sessions_ext )
{
local session = dns_sessions[orig, resp, trans_id];
local session_ext = dns_sessions_ext[orig, resp, trans_id];
event dns_ext(session_ext$id, session_ext);
}
}
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 session_ext: dns_ext_session_info;
if ( [orig, resp, msg$id] !in dns_sessions_ext )
{
session_ext$id = c$id;
session_ext$trans_id = msg$id;
session_ext$ts = network_time();
session_ext$RD = msg$RD;
session_ext$TC = msg$TC;
session_ext$qtype = qtype;
session_ext$qclass = qclass;
session_ext$query = query;
local strings: set[string] = set();
session_ext$replies = strings;
dns_sessions_ext[orig, resp, msg$id] = session_ext;
# This needs to expire before the original dns.bro script expires the
# the data from the dns_session variable.
schedule 14secs { expire_DNS_session_ext(orig, resp, msg$id) };
}
}
event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr)
{
local id = c$id;
local orig = id$orig_h;
local resp = id$resp_h;
local session = lookup_DNS_session(c, msg$id);
local session_ext: dns_ext_session_info;
if ( [orig, resp, msg$id] in dns_sessions_ext )
{
session_ext = dns_sessions_ext[orig, resp, msg$id];
add session_ext$replies[fmt("%s",a)];
session_ext$RA = msg$RA;
session_ext$TTL = ans$TTL;
session_ext$rcode = msg$rcode;
}
# Check for out of place domain names
if ( is_local_addr(a) && # referring to a local host
!is_local_addr(c$id$resp_h) && # response from a remote host
local_domains !in ans$query ) # drop known names
{
NOTICE([$note=DNSExternalName,
$msg=fmt("%s is pointing to a local host - %s.", ans$query, a),
$conn=c]);
}
}
event dns_TXT_reply(c: connection, msg: dns_msg, ans: dns_answer, str: string)
{
local id = c$id;
local orig = id$orig_h;
local resp = id$resp_h;
local session = lookup_DNS_session(c, msg$id);
local session_ext: dns_ext_session_info;
if ( [orig, resp, msg$id] in dns_sessions_ext )
{
session_ext = dns_sessions_ext[orig, resp, msg$id];
session_ext$rcode = msg$rcode;
add session_ext$replies[str];
}
}
event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr,
astr: string)
{
local id = c$id;
local orig = id$orig_h;
local resp = id$resp_h;
local session = lookup_DNS_session(c, msg$id);
local session_ext: dns_ext_session_info;
if ( [orig, resp, msg$id] in dns_sessions_ext )
{
session_ext = dns_sessions_ext[orig, resp, msg$id];
session_ext$rcode = msg$rcode;
add session_ext$replies[fmt("%s", a)];
}
}
event dns_MX_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string,
preference: count)
{
local id=c$id;
local session = lookup_DNS_session(c, msg$id);
local session_ext: dns_ext_session_info;
if ( [id$orig_h, id$resp_h, msg$id] in dns_sessions_ext )
{
session_ext = dns_sessions_ext[id$orig_h, id$resp_h, msg$id];
session_ext$rcode = msg$rcode;
add session_ext$replies[name];
}
}
event dns_PTR_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string)
{
local id = c$id;
local orig = id$orig_h;
local resp = id$resp_h;
local session = lookup_DNS_session(c, msg$id);
local session_ext: dns_ext_session_info;
if ( [orig, resp, msg$id] in dns_sessions_ext )
{
session_ext = dns_sessions_ext[orig, resp, msg$id];
session_ext$rcode = msg$rcode;
add session_ext$replies[name];
}
}
event dns_end(c: connection, msg: dns_msg)
{
local id = c$id;
local orig = id$orig_h;
local resp = id$resp_h;
local session = lookup_DNS_session(c, msg$id);
local session_ext: dns_ext_session_info;
if ( [orig, resp, msg$id] in dns_sessions_ext )
{
session_ext = dns_sessions_ext[orig, resp, msg$id];
session_ext$rcode = msg$rcode;
}
}