eBPF bypass with Suricata 7.0.2 in Debian 12 Bookworm

This does not work out-of-the-box currently. I saw a bug report that the currently shipped .bpf files are not working with current libbpf (version >1.0). However, here’s how you can compile them yourself.

I think the documentation might be a little bit unclear on this one. It’s not enough to set bypass in stream and e.g. bypass encrypted packets. It’s also not enough to set bypass yes in the af-packet section. You also need the bypass_filter.bpf (Or the XDP one, however I am having trouble with the XDP one right now). Without it you will see:

>>> ebpf-bypassed-stat
Success:
{
    "ens3": {
        "ipv4_fail": 0,
        "ipv4_maps_count": 0,
        "ipv4_success": 0,
        "ipv6_fail": 0,
        "ipv6_maps_count": 0,
        "ipv6_success": 0
    },
    "ens5": {
        "ipv4_fail": 0,
        "ipv4_maps_count": 0,
        "ipv4_success": 0,
        "ipv6_fail": 0,
        "ipv6_maps_count": 0,
        "ipv6_success": 0
    }
}

and:

>>> iface-bypassed-stat
Success:
{
    "ens3": {
        "ipv4_fail": 0,
        "ipv4_maps_count": 0,
        "ipv4_success": 0,
        "ipv6_fail": 0,
        "ipv6_maps_count": 0,
        "ipv6_success": 0
    },
    "ens5": {
        "ipv4_fail": 0,
        "ipv4_maps_count": 0,
        "ipv4_success": 0,
        "ipv6_fail": 0,
        "ipv6_maps_count": 0,
        "ipv6_success": 0
    }
}

or:

>>> iface-stat ens3
Success:
{
    "bypassed": 0,
    "drop": 0,
    "invalid-checksums": 11510,
    "pkts": 21704175
}

>>> iface-stat ens5
Success:
{
    "bypassed": 0,
    "drop": 0,
    "invalid-checksums": 0,
    "pkts": 21647543
}

You can see that bypassing does not happen, even though I configured it:

af-packet:
  - interface: ens3
    bypass: yes

  - interface: ens5
    bypass: yes

stream:
  bypass: true

app-layer:
  protocols:
    tls:
      encryption-handling: bypass

You also need to load the bypass_filter.bpf file:

ebpf-filter-file: /usr/lib/suricata/ebpf/bypass_filter.bpf

This is the one shipped with suricata. However. Trying to load this one results in:

 Error: ebpf: Unable to load eBPF objects in '/usr/lib/suricata/ebpf/bypass_filter.bpf': Operation not supported
 Error: ebpf: Unable to load eBPF objects in '/usr/lib/suricata/ebpf/bypass_filter.bpf': Operation not supported

Fixing this is relatively easy. The .bpf files provided in the Debian package are not up to date. So just grab suricata on git, configure it with –enable-ebpf-build and you should be able to run make within the ebpf folder. Then you can copy the .bpf files to /usr/lib/suricata/ebpf/. I would keep the source folder because maybe you want to edit the bpf files and compile them again. These steps are explained in the Installation documentation. Just don’t do make install – instead go to ebpf folder and type make. e.g.

# install dependencies as explained in above documentation
./scripts/bundle.sh
./autogen.sh
./configure --enable-ebpf-build
cd ebpf
make

Then something like cp *.bpf /usr/lib/suricata/ebpf/ will do the job. If it worked, you’ll see this:

 Info: ebpf: Successfully loaded eBPF file '/usr/lib/suricata/ebpf/bypass_filter.bpf' on 'ens3'
 Info: ebpf: Successfully loaded eBPF file '/usr/lib/suricata/ebpf/bypass_filter.bpf' on 'ens5'

Now suricatasc should return some values:

>>> ebpf-bypassed-stat
Success:
{
    "ens3": {
        "ipv4_fail": 0,
        "ipv4_maps_count": 32,
        "ipv4_success": 32292,
        "ipv6_fail": 0,
        "ipv6_maps_count": 0,
        "ipv6_success": 0
    },
    "ens5": {
        "ipv4_fail": 0,
        "ipv4_maps_count": 78,
        "ipv4_success": 32290,
        "ipv6_fail": 0,
        "ipv6_maps_count": 0,
        "ipv6_success": 0
    }
}

also with

>>> iface-bypassed-stat
Success:
{
    "ens3": {
        "ipv4_fail": 0,
        "ipv4_maps_count": 31,
        "ipv4_success": 32292,
        "ipv6_fail": 0,
        "ipv6_maps_count": 0,
        "ipv6_success": 0
    },
    "ens5": {
        "ipv4_fail": 0,
        "ipv4_maps_count": 78,
        "ipv4_success": 32290,
        "ipv6_fail": 0,
        "ipv6_maps_count": 0,
        "ipv6_success": 0
    }
}

or per-interface

>>> iface-stat ens3
Success:
{
    "bypassed": 35118,
    "drop": 0,
    "invalid-checksums": 159927,
    "pkts": 316078678
}
>>> iface-stat ens5
Success:
{
    "bypassed": 807883,
    "drop": 0,
    "invalid-checksums": 0,
    "pkts": 316991330
}

Yes, *cough* I should take a look at those invalid-checksums, maybe. But bypassing works! 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.