Your first filtering chain

This tutorial will block ping requests sent to the local host: we will create a chain, check that it did its job, then remove it. Everything happens on the loopback interface, so you don’t need a remote server.

From here on, we assume bpfilter is installed on your system, and that you can use sudo. If you built it locally, you will need to substitute the bfcli command with $BUILD_DIRECTORY/output/sbin/bfcli.

We will create a chain named tutorial_ping, attached to Netfilter with the priorities 101-102. If you already use bpfilter on this machine, run sudo bfcli ruleset get first to check that this name and those priorities are not used by another chain.

Can we ping now?

Let’s check if we can ping the local host before we do anything:

$ ping -n -c 3 -W 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.017 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.021 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.018 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2049ms
rtt min/avg/max/mdev = 0.017/0.018/0.021/0.001 ms

Create a filtering rule

Use bfcli to create a filtering chain. A chain is a set of rules to filter packets on. Write the following in tutorial_ping.bf:

chain tutorial_ping BF_HOOK_NF_LOCAL_OUT{priorities=101-102} ACCEPT
    rule
        ip4.daddr eq 127.0.0.1
        ip4.proto eq icmp
        icmp.type eq echo-request
        counter
        DROP

We choose to attach our chain to BF_HOOK_NF_LOCAL_OUT, which sees the packets sent by the local 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 the ping requests sent to 127.0.0.1. Packets matching this rule will be counted, then dropped.

Before we apply it, let’s ask bfcli to validate our chain:

$ bfcli chain set --from-file tutorial_ping.bf --dry-run
info   : --dry-run used, chain not set

No error? Then we can apply it for real:

$ sudo bfcli chain set --from-file tutorial_ping.bf

The options between braces tell bpfilter where to attach the chain: without them, the chain would be loaded, but it wouldn’t filter anything. chain set only replaces the chain with the same name, so your other chains (if any) are left untouched.

Can we still ping?

Now that our filtering rule is in place, pings to the local host should be blocked. Let’s check this out:

$ ping -n -c 3 -W 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2030ms

100% packet loss? That’s great news! Depending on your version of ping, you might also see an error for each request it failed to send. Let’s see if this is bpfilter’s doing:

$ sudo bfcli chain get --name tutorial_ping
chain tutorial_ping BF_HOOK_NF_LOCAL_OUT{priorities=101-102} ACCEPT
    counters policy 1 packets 90 bytes; error 0 packets 0 bytes
    rule
        ip4.daddr eq 127.0.0.1
        ip4.proto eq icmp
        icmp.type eq echo-request
        counters 3 packets 294 bytes
        DROP

Our rule matched 3 packets: the 3 requests we just sent. The policy counters will be different on your machine, as they count every other packet sent by the host.

Clean up

We don’t want to block pings forever, so let’s remove our chain and check that ping works again:

$ sudo bfcli chain flush --name tutorial_ping
$ ping -n -c 3 -W 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.026 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.031 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.037 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2055ms
rtt min/avg/max/mdev = 0.026/0.031/0.037/0.004 ms

The replies are back! You can now delete tutorial_ping.bf.

If you are eager to learn more ways to filter traffic using bfcli, check how to block traffic from selected addresses, or read about rule evaluation to understand how matchers, verdicts, and policies work together.