brimdata / brimcap

Convert pcap files into richly-typed ZNG summary logs (Zeek, Suricata, and more)
BSD 3-Clause "New" or "Revised" License
78 stars 8 forks source link

Apply a packet filter upstream of log generation #266

Open philrz opened 3 years ago

philrz commented 3 years ago

A community user inquired:

How do I use bpf filter for a lot of ips in the brim? I have a whitelist ip and want to filter those all ip logs The feature can reduce the sum of logs of big pcap files.

Indeed, as the user says, a bpf filter is one common way to do this kind of filtering in other tools. In Wireshark for instance, there's an optional bpf "capture filter" that specifies traffic to be included/excluded when capturing traffic off a live interface.

philrz commented 3 years ago

In looking at what's possible today, the approach described in the Zeek Customization article seems to be technically capable of achieving this. Since the Zeek & Suricata "runner" scripts take packet data off stdin and feed it through Zeek or Suricata, respectively, an approach like the one described here can be used to apply the bpf filter with tcpdump. Next I'll walk through a quick example of me doing this on my Mac.

Step 1

First, I copied the "stock" runner scripts from their original locations to an outside location so they won't be disturbed during app upgrades. Normally something in a home directory might be appropriate, but since this is just a quick test I'll use /tmp here.

$ cp /Applications/Brim.app/Contents/Resources/app/zdeps/zeek/ /tmp
$ cp /Applications/Brim.app/Contents/Resources/app/zdeps/zeek/zeekrunner /tmp

Step 2

Next I make two changes to each of the scripts:

  1. Point the dir variable at the base path for the Zeek/Suricata binaries. As described in the Zeek Customization article, this could be a wholly separate install that has other customizations, but since my only interest here is in adding the upstream tcpdump, I'm just pointing dir at the location of the binaries that came packaged with Brim.

  2. Rather than having the runner script exec the zeek or suricata binaries, respectively, I instead exec the application of the bpf filter via tcpdump. Since I'm working on the Mac in this case, I hit the issue described here and hence had to add the cat line shown below, but it's implied that should not be necessary on other platforms and hence one could start off with the exec tcpdump ...

Here's the modified version of each:

zeekrunnner

#!/usr/bin/env bash

dir="/Applications/Brim.app/Contents/Resources/app/zdeps/zeek"

export ZEEKPATH=$dir/share/zeek:$dir/share/zeek/policy:$dir/share/zeek/site
export ZEEK_PLUGIN_PATH=$dir/lib/zeek/plugins

# The packet filter and loaded scripts are disabled because they emit either
# timeless logs or logs with timestamp set to execution time rather than time
# of capture.
exec cat <(printf "\0\0\0\0") - | \
  tcpdump -r - -w - ip host 134.71.3.16 | \
  "$dir/bin/zeek" \
  -C -r - \
  --exec "event zeek_init() { Log::disable_stream(PacketFilter::LOG); Log::disable_stream(LoadedScripts::LOG); }" \
  local

suricatarunner

#!/usr/bin/env bash

dir="/Applications/Brim.app/Contents/Resources/app/zdeps/suricata"

if [ -z "$BRIM_SURICATA_USER_DIR" ]; then
    userdir="$dir"
    ruledir="$dir/var/lib/suricata/rules"
else
    userdir="$BRIM_SURICATA_USER_DIR"
    ruledir="$userdir/rules"
    if [ ! -d "$ruledir" ]; then
        mkdir -p "$ruledir"
    fi
    if [ ! -f "$ruledir/suricata.rules" ]; then
        cp "$dir/var/lib/suricata/rules/suricata.rules" "$ruledir"
    fi
fi

cp "$dir/brim-conf.yaml" "$userdir/brim-conf-run.yaml"

echo "
rule-files:
  - $ruledir/suricata.rules
" >> "$userdir/brim-conf-run.yaml"

exec cat <(printf "\0\0\0\0") - | \
  tcpdump -r - -w - ip host 134.71.3.16 | \
  exec "$dir/bin/suricata" -c "$userdir/brim-conf-run.yaml" --set classification-file="$dir/etc/suricata/classification.config" --set reference-config-file="$dir/etc/suricata/reference.config" --set threshold-file="$dir/etc/suricata/threshold.config" --set magic-file="$dir/share/file/magic.mgc" -r -

Step 3

Then in the Brim Preferences menu, I point the Suricata Runner and Zeek Runner settings at the paths for each modified script, then restart Brim as prompted.

image

Step 4

In the restarted Brim app, importing a pcap that contains this IP such as https://archive.wrccdc.org/pcaps/2018/wrccdc.2018-03-23.010014000000000.pcap.gz (uncompressed), we see the desired effect of only logs that were made based on packets that successfully passed through the bpf filter.

Zeek logs:

image

Suricata logs:

image


All that said, I respect this is not the easiest way to go about this. Challenges I see:

  1. It's a fairly advanced move to modify these Runner scripts. For instance, due to limitations on Windows, we use compiled Go code for these, so that's even more burden on the user.

  2. Modifying the bpf filter in two places is tedious and error prone.

I could definitely envision a smoother approach similar to what we see with Wireshark such that there'd be a single option among the Preferences in the app to specify the filter and have this automatically applied upstream of the log generation similar to what we've done here. I'll hold this issue open to track interest in that approach.

In a 1-on-1 chat with @mccanne, he confirmed my hunch that we could probably do this pretty easily with our pcap tool. Its code is embedded as part of zqd and we also ship it as a standalone binary with Brim. It can create packet indexes and extract flows, and could likely be extended to do this pipelined filtering as well, effectively taking the place of tcpdump in the examples shown above, with the currently-active bpf filter from the app passed down somehow.

philrz commented 2 years ago

In the time since this issue was first opened, Brim's pcap processing is now handled by a separate tool Brimcap that's bundled with the app. The same recipe above that describes modifying the runner scripts to handle the filtering should still be possible with Brimcap. The Custom Brimcap Config article provides some additional detail that might be useful for anyone wanting to attempt this. It's also still true that Brimcap itself could potentially still handle the packet filtering during the brimcap analyze phase, so I'll hold this issue open in the event we want to address that one day.