The user-space program ...
- Loads the BPF program into the kernel
- Reads TCP and UDP conntrack entries (incl. NAT information) via
libnetfilter_conntrack
and offloads them to the BPF program via the BPF mapconn_map
- Attaches the BPF program to all specified interfaces
- Polls
conn_map
and checks if ...- The BPF program has received a package for a new (not yet offloaded) connection. If yes, lookup the connection (incl. NAT information) via
libnetfilter_conntrack
, and if it is found, offload it to the BPF program - The BPF program has received a new package for an already offloaded connection. If yes, it updates the conntrack entry timeout via
libnetfilter_conntrack
- An already existing connection has either finished (TCP FIN, RST) or a timeout has occurred. If yes, delete that connection from the BPF map
conn_map
so that the network stack can take over again
- The BPF program has received a package for a new (not yet offloaded) connection. If yes, lookup the connection (incl. NAT information) via
- If a SIGINT or SIGTERM occurs, it detaches and unloads the BPF program afterward
The kernel/BPF program ...
- Parses the
Ethernet
,VLAN
,IPv4
,TCP
andUDP
header - Checks if a connection entry inside the BPF map
conntrack
exists- If not, it creates a new entry to signal the user-space program and passes the package to the network stack (for now)
- If yes ...
- If the connection isn't marked as offloaded yet, it passes the package to the network stack
- If the connection is marked as offloaded, it determines via
bpf_fib_loopkup
if the package is to be redirected and where to. Depending on the result, it then applies NAT and routes the package to the next hop, passes the package to the network stack, or drops it. The next hop is cached as long as the connection is alive, ignoring possible routing table changes for now. - If the TCP FIN or RST is set, it marks the connection as finished and passes the package again to the network stack
- Prints debug messages to
/sys/kernel/debug/tracing/trace_pipe
Compile the XDP/TC BPF program. This creates four BPF objects (for the XDP and TC hook and little and big-endian machines) which will be located under kernel/obj/
.
cd kernel make
Compile the user-space program. It will be located at user/bin/bpfw
.
The libbpf
and libnetfilter_conntrack
libraries are needed for the compilation.
cd user make
Cross-compile the user-space program for OpenWrt. The paths (gcc, toolchain, ...) may need to be adjusted inside user/OpenWrt.mk
.
cd user make OPENWRT_DIR=<Path to the OpenWrt root directory> TARGET=<OpenWrt Target> # For example make OPENWRT_DIR=~/openwrt TARGET=x86_64 make OPENWRT_DIR=~/openwrt TARGET=aarch64
Execute the program. <hook>
can be either xdp
or tc
.
./bpfw <hook> <Path to the XDP/TC program> <Network Interfaces> # For example ./bpfw xdp xdp_le_bpfw.o lan1 lan2 ./bpfw tc tc_be_bpfw.o lan1 lan2
The following symbols should be set inside OpenWrt's make menuconfig
:
# For bpf_printk (debugging) support CONFIG_KERNEL_KPROBES=y # For TC support CONFIG_PACKAGE_kmod-sched-bpf=y CONFIG_PACKAGE_kmod-sched-core=y # Needed libraries for the user-space program CONFIG_PACKAGE_libbpf=y CONFIG_PACKAGE_libnetfilter-conntrack=y