Installing the data plane
This page takes you from nothing to a data plane that is attached, evaluating traffic, and dropping nothing yet — which is exactly where you want to pause and watch before you enforce. Read the overview first if you have not; in particular, confirm Kapkan runs in the traffic path on this box, or there will be nothing for the program to drop.
1. Check the requirements
Four things, each with a one-line check you can run now:
| Requirement | Check | Notes |
|---|---|---|
| Linux 5.15 or newer | uname -r | The full test suite runs on 5.15, 6.1, 6.6 and 6.12 every change. Debian 12, Ubuntu 22.04/24.04, RHEL 9 and their rebuilds qualify. RHEL/Alma/Rocky 8 does not — it ships 4.18 and is supported into 2029, so check before assuming. |
| Kernel BTF | ls /sys/kernel/btf/vmlinux | Present on every distro kernel that meets the floor above. |
| A mounted bpffs | mount | grep ' /sys/fs/bpf ' | Kapkan pins its program and maps under pin_path, so policy survives a restart of the process. |
| A NIC driver with XDP support | ethtool -i eth0, then check the driver | Optional. Without it the kernel's generic path is used — correct, but lower capacity. See attach modes. |
The process also needs CAP_BPF and CAP_NET_ADMIN to load and attach the program, write access
to the bpffs mount, and the AF_NETLINK address family.
Nothing needs a compiler on the box. The BPF program is compiled when Kapkan is built and travels inside the binary.
2. Grant the capabilities (systemd)
Kapkan's packaged systemd unit is deliberately hardened, and as shipped it blocks an XDP
attach: no AmbientCapabilities, ProtectSystem=strict leaving /sys/fs/bpf read-only, and
RestrictAddressFamilies without AF_NETLINK. That is the right default — most Kapkan boxes never
run a data plane, and handing every one of them CAP_BPF to save the few that do is a bad trade.
The packages ship the override that opens exactly those holes, at
/usr/share/kapkan/kapkan-dataplane.conf. Install it deliberately, only on the boxes that run a
data plane:
sudo mkdir -p /etc/systemd/system/kapkan.service.d
sudo cp /usr/share/kapkan/kapkan-dataplane.conf /etc/systemd/system/kapkan.service.d/
sudo systemctl daemon-reload && sudo systemctl restart kapkan
iRunning Kapkan another way?
If you do not use the packaged unit, the requirement is the same: the process needs CAP_BPF and
CAP_NET_ADMIN, AF_NETLINK, and a writable /sys/fs/bpf. Grant those however your init or
container runtime does it.
3. Add the dataplane block
The dataplane block is optional. Absent, the feature does not exist and the binary behaves exactly
as it does without it. Here is a complete block with every key annotated; you need only interfaces
to start.
dataplane:
interfaces: [eth0] # NICs to attach to (at least one; restart to change)
xdp_mode: auto # auto | native | generic
pin_path: /sys/fs/bpf/kapkan # policy survives a restart of this process
on_exit: keep # keep the program attached on shutdown, or detach
drop_malformed: false # unparseable frames pass and are counted
allowlist: # SOURCE prefixes that always pass
- "198.51.100.7/32" # monitoring
- "192.0.2.0/24" # management network
ratelimit_profiles: # named ceilings, referenced by static rules
- { name: icmp_cap, mbps: 10 }
- { name: dns_reply, pps: 50000 }
static_rules: # always-on operator policy
- name: drop_chargen
match: { proto: udp, src_port: 19 }
action: drop
- name: cap_icmp
match: { proto: icmp }
action: ratelimit
profile: icmp_cap
limits:
max_dynamic_rules: 4096
max_static_rules: 256
max_ratelimit_sources: 1048576
allowlist, ratelimit_profiles, static_rules and limits are covered in
Tuning & reference. To bring the plane up you can leave them out entirely.
4. Tell a group to use it
Attaching the program does not drop anything on its own — a detection has to choose it as its method. Give a group a ladder rung that does:
hostgroups:
- name: game-servers
networks: ["203.0.113.32/27"]
escalation:
- { after_seconds: 0, action: dataplane } # drop locally first
- { after_seconds: 120, action: flowspec } # ask the router if that was not enough
- { after_seconds: 600, action: blackhole }
A ladder may only hold or strengthen (none < dataplane < flowspec < divert < blackhole), so a
dataplane rung may follow an alert-only rung but never flowspec, divert or blackhole.
For a single method with no ladder, set mitigation: dataplane on the group. Either way,
configuring a dataplane action without a dataplane block is rejected at startup rather than
silently doing nothing.
5. Start in dry-run and watch
Leave dry-run on for the first run — it is Kapkan's default, and it covers the data
plane exactly as it covers BGP. While dry_run: true, the program attaches and evaluates every
packet, but no rule is installed and nothing is dropped. The rules Kapkan would have installed
are logged and shown on the ban in /api/v1/bans, so you can review them against real attacks
before enforcing.
Confirm the attach succeeded:
kapkan dataplane status
You are looking for the program attached to your interface(s), the attach mode (native or
generic), and — because you are in dry-run — a clear note that drop verdicts are being rewritten
to passes. Reading that output in full, and what to watch once you flip to enforcing, is
Operating & monitoring.
When you are satisfied with what it would drop, turn dry-run off (globally, in the safety settings) to begin enforcing.