Skip to content

pgigis/OpenPenny

Repository files navigation

OpenPenny

CI License Version

OpenPenny logo

OpenPenny tells you whether TCP traffic entering your network is genuinely non-spoofed. It implements the Penny test (SIGCOMM '24): drop a small number of packets in a redirected slice of traffic and watch which packets get retransmitted. Genuine TCP senders retransmit; spoofed sources do not.

Two modes:

  • Active. Drop a few packets in the slice; observe retransmissions.
  • Passive. Observe only — sequence coverage, gaps, duplicates, FIN/RST, idle expiry. No packets are dropped.

Capture is over AF_XDP (default), AF_PACKET (copy-mode tap), or DPDK. Optional forwarding to a TUN device or raw socket. Drive it from the CLI (openpenny_cli) or the gRPC daemon (pennyd + penny_worker).

Traffic slicing and analysis

Quick start

# Build the CLI (XDP-only).
cmake -S . -B build -DOPENPENNY_WITH_XDP=ON -DOPENPENNY_WITH_DPDK=OFF
cmake --build build

# Run an active test on TCP/5201 traffic.
sudo ./build/openpenny_cli \
  --config examples/configs/config_minimal_active.yaml \
  --iface <ifname> --tun xdp-tun

For passive observation, swap to config_minimal_passive.yaml and add --mode passive. The two minimal configs are single-file, no includes; production-shaped equivalents that split policy and platform live at examples/configs/config_default.yaml and config_passive.yaml.

Other entry points:

Requirements

Category Requirement
OS / privileges Linux with root or CAP_NET_ADMIN; kernel XDP for AF_XDP.
Toolchain CMake ≥ 3.16, C++17 compiler, pkg-config.
Libraries libbpf, libxdp, libelf, libpcap, openssl.
Optional (DPDK) libdpdk plus hugepages and driver binding.
Optional (gRPC) libgrpc++, grpc_cpp_plugin, Protobuf headers, protoc.

Build flavours

# CLI + gRPC daemon
cmake -S . -B build \
  -DOPENPENNY_WITH_XDP=ON \
  -DgRPC_DIR=/path/to/lib/cmake/gRPC \
  -DProtobuf_DIR=/path/to/lib/cmake/protobuf \
  -DGRPC_CPP_PLUGIN=/usr/bin/grpc_cpp_plugin

# DPDK
cmake -S . -B build -DOPENPENNY_WITH_DPDK=ON -DOPENPENNY_WITH_XDP=OFF

The eBPF program is built automatically; rebuild with cmake --build build --target xdp_bpf if you only need the BPF artifact.

Architecture (per queue)

                           NIC RX queue
                                │
                                │  (one of:)
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  kernel
        ┌───────────────────────┼───────────────────────┐
        ▼                       ▼                       ▼
   ┌─────────┐             ┌─────────┐             ┌─────────┐
   │ AF_XDP  │             │AF_PACKET│             │  DPDK   │
   │redirect │             │  copy   │             │   PMD   │
   └────┬────┘             └────┬────┘             └────┬────┘
─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─ ─  user
        └───────────────────────┼───────────────────────┘
                                ▼
    ┌───────────────────────────────────────────────────────┐
    │            PacketSource  →  PacketParser              │
    │           (one worker thread per RX queue)            │
    └──────────────────────────┬────────────────────────────┘
                               │
                   ┌───────────┴───────────┐
                   ▼                       ▼
            ┌────────────┐          ┌────────────┐
            │   Active   │          │  Passive   │
            │  pipeline  │          │  pipeline  │
            │ ────────── │          │ ────────── │
            │ drop a few │          │ observe    │
            │ packets;   │          │ gaps and   │
            │ watch for  │          │ coverage;  │
            │ retransmit │          │ no drops   │
            └──────┬─────┘          └─────┬──────┘
                   └───────────┬──────────┘
                               ▼
             ┌─────────────────────────────────────┐
             │   PacketSink  (egress.kind):        │
             │   none, tun, raw_socket, raw_nic    │
             └────────────────┬────────────────────┘
                              ▼
                  Summary  →  CLI / gRPC reply

One worker per RX queue. Each worker owns its packet source; egress is a single PacketSink shared across all workers.

Repository layout

Full map: docs/layout.md. High level:

  • src/, include/ — core library, pipelines, CLI, gRPC daemon and worker.
  • src/ingress/ — AF_XDP/eBPF, AF_PACKET mirror, DPDK backends.
  • ebpf/af_xdp/ — eBPF runtime program.
  • proto/ — gRPC service definition.
  • examples/ — configs and sample gRPC clients.
  • tools/traffic_generator/, tools/af_xdp/ — test traffic and AF_XDP diagnostics.
  • docs/ — start at docs/README.md.

References

Project

Primary author: Petros Gigis (pgigis). Contributors: https://github.com/pgigis/openpenny/graphs/contributors.

The Penny mechanism was developed by Petros Gigis, Mark Handley, and Stefano Vissicchio. This project was supported by the RIPE NCC Community Projects Fund 2024 (details).

Provided "as is" without warranty; the authors and funders are not liable for any damages arising from its use.