Class EbpfOriginalDestinationResolver

java.lang.Object
org.mockserver.netty.proxy.EbpfOriginalDestinationResolver
All Implemented Interfaces:
TransparentProxyHandler.OriginalDestinationResolver

public class EbpfOriginalDestinationResolver extends Object implements TransparentProxyHandler.OriginalDestinationResolver
Resolves the original destination of a transparently intercepted TCP connection by reading a pinned BPF hash map populated by an external eBPF program.

Architecture: an external BPF program (typically attached to a cgroup via cgroup/connect4 or cgroup/sock_ops) records the original destination address in a BPF hash map keyed by socket cookie. This resolver reads that map entry for the accepted socket, extracts the original destination, and optionally deletes the entry to prevent stale data.

How it works:

  1. Open the pinned BPF map via bpf(BPF_OBJ_GET, path) to get a map fd
  2. Get the socket cookie via getsockopt(fd, SOL_SOCKET, SO_COOKIE)
  3. Lookup the original destination: bpf(BPF_MAP_LOOKUP_ELEM, map_fd, &cookie)
  4. Delete the consumed entry: bpf(BPF_MAP_DELETE_ELEM, map_fd, &cookie)
  5. Decode the 6-byte value (4-byte IPv4 + 2-byte port, network byte order)

BPF map format:

  • Map type: BPF_MAP_TYPE_HASH
  • Key: u64 socket cookie (8 bytes, native byte order)
  • Value: 6 bytes — 4-byte IPv4 address + 2-byte port (both network byte order)
  • Pinned at: configured path (default /sys/fs/bpf/mockserver_orig_dst)

Requirements:

  • Linux with BPF support (CONFIG_BPF_SYSCALL=y)
  • Netty epoll transport (EpollSocketChannel) for fd access
  • JNA native library for syscall() and getsockopt()
  • CAP_BPF capability (or root) for BPF map operations
  • An external BPF program populating the pinned map
  • Configuration: mockserver.transparentProxyEbpf=true

Chain position: in the CompositeOriginalDestinationResolver default chain, eBPF is placed after TPROXY and before SO_ORIGINAL_DST. Like SO_ORIGINAL_DST, the eBPF map lookup is O(1). It is tried before SO_ORIGINAL_DST because when an eBPF program is deployed, its data is more authoritative than the Netfilter conntrack state (the BPF program captures the destination before any NAT rewrites). When eBPF is not enabled or the map is unavailable, this resolver returns null and the chain falls through to SO_ORIGINAL_DST.

No new dependencies: this resolver uses JNA (already a MockServer dependency for SoOriginalDstResolver) and the Linux bpf() / getsockopt() syscalls. No BPF loader library is needed — the BPF program is loaded externally.

See Also:
  • Constructor Details

    • EbpfOriginalDestinationResolver

      public EbpfOriginalDestinationResolver(Configuration configuration)
  • Method Details

    • isPlatformSupported

      public boolean isPlatformSupported()
      Returns true if the platform supports eBPF map operations: Linux OS, Netty epoll transport, and JNA.
    • resolve

      public InetSocketAddress resolve(io.netty.channel.Channel channel)
      Specified by:
      resolve in interface TransparentProxyHandler.OriginalDestinationResolver
      Parameters:
      channel - the accepted Netty channel
      Returns:
      the original destination, or null if unavailable