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 declares two redefinable tables in pcap.bro that have special interpretations with regard to filtering:

         global capture_filters: table[string] of string &redef;
         global restrict_filters: table[string] of string &redef;

The key strings serve as a user-definable identifier for the filter strings they are associated with. The entries of the capture_filters table define what traffic Bro should capture, while restrict_filters' entries limit what traffic Bro captures. Bro builds the following tcpdump filter from both tables:

(OR of capture_filters' entries) and (AND of restrict_filters' entries)

Thus, repeated Refinements of capture_filters using the += initializer are combined using logical “OR”s, whereas for restrict_filters “AND”s are used. This follows from the tables' respective purposes—capture_filters permits any of its components, while restrict_filters rejects everything that does not comply with all of its components.

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

Here is an example. If you specify:

         redef capture_filters = { ["HTTP"] = "port http" };
         redef restrict_filter = { ["mynet"] = "net 128.3" };

then the corresponding tcpdump filter will be:

         (port http) and (net 128.3)

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

         redef capture_filters += { ["DNS"] = "udp port 53" };
         redef capture_filters += { ["FTP"] = "port ftp" };
     
         redef restrict_filters += { ["foonet"] = "net 128.3" };
         redef restrict_filters += { ["noflood"] = "not host syn-flood.magnet.com" };

yields this tcpdump filter:

         ((udp port 53) or (port ftp)) and ((net 128.3) and (not host syn-flood.magnet.com))

As you add analyzers, the final tcpdump filter can become quite complicated. You can load the predefined print-filter script to print out the resulting filter. This script handles the bro_init event and exits Bro 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.

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.