GitHub

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:

RequirementCheckNotes
Linux 5.15 or neweruname -rThe 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 BTFls /sys/kernel/btf/vmlinuxPresent on every distro kernel that meets the floor above.
A mounted bpffsmount | 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 supportethtool -i eth0, then check the driverOptional. 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.