Nested modules in /opt/app/bro/share/bro/site/ not working?

Folks,

This may well be an RTFM - I just don't know which section would cover this.

I have two modules created in /opt/app/bro/share/bro/site/ , with the intention of having one @load the other - but I cannot seem to get the combination to work, and I'm unsure even where the failure is.

The @load'ed module, "CU_net_defs", is intended as a shim to some .csv files, periodically updated from the central DB which tracks internal subnet allocations, which is supposed to instantiate two global sets of CIDR's, one for top-level allocations (e.g. 128.253.0.0), and the other for internally-allocated subnets (e.g. 128.253.101.0/25).

The @load'ing module, "bro-wsSMTP", is intended to detect user workstations et.al. that have been compromised and are acting as spambots, by the following methodology.

   - understand the top-level allocations by @load'ing CU_net_defs;
   - understand an internal set of our e-mail infrastructure hosts and networks; and
   - generate logfiles, "ws-smtp.{}.log", containing entries where
        -- id$orig_h is part of a campus allocation;
        -- id$orig_h is *not* part of our e-mail infrastructure; and
        -- id$resp_h is *not* part of a campus allocation.

The final goal is to have the resulting "ws-smtp.{}.log" files fed into Splunk for detection/correlation.

The thing is, once I create an expression intended to isolate by way of the criteria above, I get no results whatever - even though the data is clearly in the normal smtp.log file.

Slightly abridged instances of the module files are appended below. Can anyone shed any light on this?

Thanks for any info,

Folks,

This may well be an RTFM - I just don't know which section would cover
this.

I have two modules created in /opt/app/bro/share/bro/site/ , with the
intention of having one @load the other - but I cannot seem to get the
combination to work, and I'm unsure even where the failure is.

Looks like you've done almost everything correctly! I think you just have some input files issues.

...

===== CU_net_defs/CU_net_defs.bro =====
module CU_net_defs;

export
{
    type IDX: record { cidr: subnet; };

    global CU_subnets: set[subnet];
    global CU_allocations: set[subnet];
}

event bro_init()
{
    Input::add_table([$source="/users/bro/devel/DNSDBnc/CU_subnets.txt", $name="CU_subnets",
                      $idx = IDX, $destination=CU_subnets]);
    Input::remove("CU_subnets");

Input::add_table([$source="/users/bro/devel/DNSDBnc/CU_allocations.txt", $name="CU_allocations",
                      $idx = IDX, $destination=CU_allocations]);
    Input::remove("CU_allocations");
}

I would remove the two Input::remove lines and add $mode=Input::REREAD to the two add_table calls.

I'm not sure if the immediate remove would prevent it from working at all, but you don't want to do that anyway. You want the input files to stay active and also update the sets when the files are updated.

Once you do that, check the reporter.log a few seconds after starting bro to see if it is complaining about accessing/parsing those 2 text files.

Most likely the root cause of your problem is that something is preventing them from being parsed properly which is making your two sets empty which makes your smtp filter match nothing.

If I had to guess, you are missing the required '#fields\tcidr' header.

===== bro-wsSMTP/ws-SMTP-outbound.bro =====
@load base/protocols/smtp
@load CU_net_defs

module ws_SMTP_outbound;

export
{
    global local_mail_infra: set[subnet] =
    {
        128.253.150.128/25,
        [stuff redacted...]
         132.236.101.7/32
    };
}

event bro_init()
{
    Log::add_filter(SMTP::LOG, [$name = "ws-smtp-outbound",
                               $path = "ws-smtp",
                               $pred(rec: SMTP::Info) =
                                {
                                    return rec$id?$orig_h
                                           && rec$id$orig_h in CU_net_defs::CU_allocations
                                           && !(rec$id$orig_h in local_mail_infra)
                                           && rec$id?$resp_h
                                           && !(rec$id$resp_h in CU_net_defs::CU_allocations)
                                           ;
                                }
                              ]
                   );
}

unrelated to problems, but

    !(rec$id$orig_h in local_mail_infra)

can be written as

    rec$id$orig_h !in local_mail_infra