[Bro] Converting a Bro Script to A New Stream
Chris Crawford
christopher.p.crawford at gmail.com
Mon Aug 20 06:43:15 PDT 2012
I was able to make some progress. This script does what I want, but
there are still some problems.
module Foo;
export {
redef enum Log::ID += { LOG };
type Info: record {
ts: time &log;
uid: string &log;
orig_ip: addr &log;
query: string &log;
};
}
event bro_init() &priority=5
{
Log::create_stream(Foo::LOG, [$columns=Info]);
}
event DNS::log_dns(rec: DNS::Info)
{
if(rec$qtype_name == "A")
if( |rec$answers| > 0 )
for( i in rec$answers )
if( "1.2.3.4" in rec$answers[i] )
Log::write(Foo::LOG, [
$ts=rec$ts, $uid=rec$uid, $orig_ip=rec$id$orig_h, $query=rec$query]);
}
I get the log I want, with the data I expect.
The problem is, I get thousands of entries in reporter.log that say:
"Reporter::ERROR field value missing [Foo::rec$qtype_name]"
And I get hundreds of entries that say:
"Reporter::ERROR field value missing [Foo::rec$answers]"
I think I'm getting these error messages because log_dns fires, but
rec is empty or doesn't exist. How can I check my theory? If that is
truly the case, is there a better way to write the initial logic in
event DNS::log_dns(rec: DNS::Info) that would break out of that
function if rec does not exist? I thought that checking for DNS
answers and then checking to make sure that there is a positive number
of answers would help to eliminate the errors I see in reporter.log,
but it doesn't.
-Chris
On Thu, Aug 16, 2012 at 5:32 PM, Chris Crawford
<christopher.p.crawford at gmail.com> wrote:
> I have a short bro script that I wrote that hooks the DNS log
> (http://www.bro-ids.org/documentation/logging.html#hooking-into-the-logging).
> Each time a DNS::log_dns event fires, if a specific IP is in
> rec$answers, the script prints out rec$ts, rec$uid, rec$id$orig_h, and
> rec$query.
>
> I want the entries from the script to go to their own log, though. I
> am struggling to figure out how to make that work. Based on the
> documentation for logging, it looks like I'd need to define a new
> Stream to create a new log file.
> (http://www.bro-ids.org/documentation/logging.html#adding-streams)
>
> Here's my original script that hooks the DNS logs:
>
> event DNS::log_dns(rec: DNS::Info)
> {
> for( i in rec$answers )
> if( "1.2.3.4" in rec$answers[i] )
> print fmt("%s %s %s %s", rec$ts, rec$uid,
> rec$id$orig_h, rec$query);
> }
>
>
> To make this go to its own log, I tried this:
>
>
>
> module Foo;
>
> export {
> # Create an ID for the our new stream. By convention, this is
> # called "LOG".
> redef enum Log::ID += { LOG };
>
> # Define the fields. By convention, the type is called "Info".
> type Info: record {
> ts: time &log;
> uid: string &log;
> orig_ip: string &log;
> query: string &log;
> };
>
> # Define a hook event. By convention, this is called
> # "log_<stream>".
> global log_foo: event(rec: Info);
>
> }
>
> redef record rec += {
> foo: Info &optional;
> };
>
> # This event should be handled at a higher priority so that when
> # users modify your stream later and they do it at priority 0,
> # their code runs after this.
> event bro_init() &priority=5
> {
> # Create the stream. This also adds a default filter automatically.
> Log::create_stream(Foo::LOG, [$columns=Info]);
> }
>
> event DNS::log_dns(rec: DNS::Info)
> {
> for( i in rec$answers )
> if( "1.2.3.4" in rec$answers[i] )
> local rec: Foo::Info = [ $ts=rec$ts,
> $uid=rec$uid, $orig_h=rec$id$orig_h, $query=rec$query];
> rec$foo = rec;
> Log::write(Foo::LOG, rec);
> }
>
> I get the errors:
>
> error in ./test.bro, line 22: unknown identifier (Foo::rec)
> error in ./test.bro, line 35 and ./test.bro, line 39: already defined (Foo::rec)
>
>
> I am new to writing Bro scripts. Any pointers on what I'm doing wrong?
>
>
> -Chris
More information about the Bro
mailing list