Previous: Loading Analyzers, Up: Activating an Analyzer



7.1.2 Filtering

Most analyzers require Bro to capture a particular type of network traffic. These traffic flows can vary immensely in volume, so different analyzers can cost greatly differing amounts in terms of performance.

Bro predefines two redefinable string variables that have special interpretations with regard to filtering. (See Refinement for a discussion of redefinable variables.) capture_filter is a tcpdump filter that tells Bro what traffic it should capture. restrict_filter limits what traffic Bro captures. The tcpdump filter Bro uses is:

(capture_filter) and (restrict_filter)
So, for example, if you specify:
         redef capture_filter = "port http";
         redef restrict_filter = "net 128.3";

then the corresponding tcpdump filter will be:

         (port http) and (net 128.3)

which will capture all TCP port 80 traffic that has either a source or destination address belonging to the 128.3 network (i.e., 128.3/16).

If you do not define capture_filter, then its value is set to “tcp or udp”; if you do not define restrict_filter, then no restriction is in effect.

You may have noticed that other than their default values, the definitions of capture_filter and restrict_filter are symmetric. They differ only in the convention of how they are used. Usually, you either don't define a value for restrict_filter at all, or define it just once, using it to specify a restriction that holds across your environment. For example, either to confine packet capture to a subset of the traffic (like the "net 128.3" example above), or to exclude a particular traffic source ("not host syn-flood.magnet.com") or both of these ("net 128.3 and not host syn-flood.magnet.com").

For capture_filter, on the other hand, you usually don't define a single value, but instead refine it one or more times using the += initializer. (See Refinement for a discussion of refining a variable's initial value.) The way capture_filter's refinement is defined, it constructs a filter that is the “or” of each of its refinements. So, for example, if at one point in your script you have:

         redef capture_filter += "port ftp";

and at another:

         redef capture_filter += "udp port 53";

and at a third:

         redef capture_filter += "len >= 512 and len <= 1024";

then the resulting capture_filter will be:

         (port ftp) or (udp port 53) or (len >= 512 and len <= 1024)

(except there will be more parentheses, which don't actually affect the interpretation of the filter; see Refinement for the details of how the refinement is done, and why it leads to the extra parentheses).

restrict_filter has the same refinement mechanism, the “or”ing together of the different refinement additions, though, as mentioned above, it is not usually refined.

As you add analyzers, the final tcpdump filter can become quite complicated. You can use the predefined print-filter script shown below to print out the filter. This script handles the bro_init event and exits after printing the filter. Its intended use is that you can add it to the Bro command line (“bro my-own-script print-filter”) when you want to see what filter the script my-own-script winds up using.

     event bro_init()
         {
         if ( restrict_filter == "" && capture_filter == "" )
             print "tcp or not tcp";  # Capture everything.
     
         else if ( restrict_filter == "" )
             print capture_filter;
     
         else if ( capture_filter == "" )
             print restrict_filter;
     
         else
             print fmt("(%s) and (%s)", capture_filter, restrict_filter);
     
         exit();
         }

In the example above, print_filter prints out the tcpdump filter your Bro script would use and then exits.

There are two particular uses for print-filter. The first is to debug filtering problems. Unfortunately, Bro sometimes uses sufficiently complicated expressions that they tickle bugs in tcpdump's optimizer. You can take the filter printed out for your script and try running it through tcpdump by hand, and then also try using tcpdump's -O option to see if turning off the optimizer fixes the problem.

The second use is to provide a shadow backup to Bro: that is, a version of tcpdump running either on the same machine or a separate machine that uses the same network filter as Bro. While tcpdump can't perform any analysis of the traffic, the shadow guards against the possibility of Bro crashing, because if it does, you will still have a record of the subsequent network traffic which you can run through Bro for post-analysis.