Usage¶
bpfilter
is composed of two main parts that work together: the clients are used by the users to define the filtering rules and send them to the daemon that performs the heavy lifting of generating the BPF bytecode.
Before anything, you will have to run the daemon on your system, see The daemon for more details.
Once the daemon is running, you need to choose which front-end’s CLI to use:
bfcli:
bpfilter
-specific CLI, developed as part of the project.bfcli
supports newbpfilter
features before other CLIs as it’s used for development. It allows for a more flexible rule definition: you can use a combination of filters and hooks that might not be possible with other CLIs. However, it doesn’t supportnftables
oriptables
rules format.nftables: requires a custom version of the
nft
binary withbpfilter
support (see below), and support for newbpfilter
features is usually a bit delayed.iptables: similar to
nftables
, howeveriptables
has been deprecated globally in favor ofnftables
.
Install¶
bpfilter is packaged for Fedora 40+, EPEL 9+ and supports Fedora 40+, CentOS Stream 9+, and Ubuntu 24.04+.
> sudo dnf install -y bpfilter
If you use a different distribution, you can still build and use bpfilter if you satisfy the requirements, see the developer documentation.
Example usage¶
From here on, we assume bpfilter has been installed on your system. If you build it locally, you will need to substitute the bpfilter
command with $BUILD_DIR/output/sbin/bpfilter
, same for bfcli
. The example below is meant to familiarize you with bpfilter, more in-depth information can be found throughout the documentation.
This example will block ping
requests sent going out of the local host to a remote server.
Can we ping now?
Let’s check if we can ping facebook.com
before we do anything:
$ ping -n -c 4 facebook.com
PING facebook.com (157.240.253.35) 56(84) bytes of data.
64 bytes from 157.240.253.35: icmp_seq=1 ttl=128 time=24.9 ms
64 bytes from 157.240.253.35: icmp_seq=2 ttl=128 time=23.6 ms
64 bytes from 157.240.253.35: icmp_seq=3 ttl=128 time=28.6 ms
64 bytes from 157.240.253.35: icmp_seq=4 ttl=128 time=24.8 ms
--- facebook.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 23.596/25.493/28.622/1.880 ms
Start the daemon
The daemon is responsible for receiving the user-defined filtering rules, and translating them into BPF programs. We will start it in --transient
mode, so all the filtering programs defined will be discarded when we stop it, preventing any mistake on our side!
$ sudo bpfilter --transient
info : waiting for requests...
Create a new filtering rule
Now that the daemon is up and running, we will use bfcli
to send a filtering chain. A chain is a set of rules to filter packets on:
$ sudo bfcli ruleset set --str "
chain BF_HOOK_NF_LOCAL_OUT policy ACCEPT
rule
ip4.proto icmp
DROP
"
We split the chain over multiple lines, to it’s easier to read. Alternatively, you can write the chain in a file and call bfcli ruleset set --file $MYFILE
. We choose to create a chain attached to BF_HOOK_NF_LOCAL_OUT
which is called for every packet leaving this host with ACCEPT
as the default policy: if a packet doesn’t match any of the rules defined, it will be accepted by default.
Our chain contains a single rule matching against the IPv4’s protocol
field. Packets matching this rule will be DROP
ed.
Can we still ping?
Now that our filtering rule is in place, pings to facebook.com
should be blocked, let’s check this out:
$ ping -n -c 4 facebook.com
PING facebook.com (157.240.253.35) 56(84) bytes of data.
--- facebook.com ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3010ms
100% packet loss? That’s great news! If you are eager to learn more ways to filter traffic using bfcli, check its documentation.