bro

Bro Script to look up hostname from IP Address


I've wrote a bro script using the Input::add_table function to look up IPs and their corresponding hostnames and insert them into the conn_id record - so that I have id.source_name & id.destination_name in every log file. This works fine except when there are tunnel events and it crashes bro with a segmentation error. I suspect this is something to do with the encapsulation id but I don't really know. I know I could add the src & dest names to the Info record for each type but that would mean modifying every type. Is what I'm trying to do fundamentally incorrect or is there a bug in the tunnel code causing the crash ? Or is there a better way to do this

export {
global host_table: table[addr] of Val = table();
}

redef record conn_id += {
    src_name: string &optional &log;
    dest_name: string &optional &log;
};

const host_file = “hosts.txt”

event bro_init() &priority=20
{
    Input::add_table([$source=host_file, $name =“host_stream”, $idx=Idx, $val=Val, $destination=host_table]);
    Input::remove(“host_stream”);
}

event new_connection( c: connection ) {
    if( c$id$orig_h in host_table ) {
        c$id$src_name = host_table[c$id$orig_h]$host;
    }
    if( c$id$resp_h in host_table ) {
        c$id$dest_name = host_table[c$id$resp_h]$host;
    }
}

Solution

  • Unfortunately you don't want to extend the conn_id record. It is used internally in a number of ways which this change would impact. I would extend the Conn::Info record and add the data there.

    Your script was missing some pieces and I wanted to make the answer more usable for people in the future so I filled out the missing areas:

    @load base/protocols/conn
    
    module MyHostNames;
    
    export {
        ## File to load hostnames from.
        const host_file = "hosts.txt" &redef;
    }
    
    type Idx: record {
        host: addr;
    };
    
    type Val: record {
        hostname: string;
    };
    
    global host_table: table[addr] of Val = table();
    
    redef record Conn::Info += {
        orig_name: string &optional &log;
        resp_name: string &optional &log;
    };
    
    event bro_init() &priority=5
        {
        Input::add_table([$source=host_file,
                          $name="myhostnames_stream",
                          $idx=Idx,
                          $val=Val,
                          $destination=host_table]);
        Input::remove("myhostnames_stream");
        }
    
    event connection_state_remove(c: connection)
        {
        if ( c$id$orig_h in host_table )
            {
            c$conn$orig_name = host_table[c$id$orig_h]$hostname;
            }
    
        if ( c$id$resp_h in host_table )
            {
            c$conn$resp_name = host_table[c$id$resp_h]$hostname;
            }
        }
    

    I used an input file that looks like this (keep in mind some literal tabs in this data between columns!):

    #fields host    hostname
    #types  addr    string
    1.2.3.4 special-host