Skip to content

How it works

Traffic enters the proxy listener (plain or TLS). The first matching route wins. IP filtering and rate limiting run before forwarding. Fingerprints are derived from the client→proxy side of the connection; the proxy then injects trusted headers so backends do not rely on spoofable client fields.

You can run only the proxy or the proxy plus the eBPF agent — they are different operational setups (Compose files and images are not interchangeable). Details: Containers.

  • Proxy alone (typical “plain” image / single service): TLS and HTTP/2 are terminated in-process; JA4 and HTTP/2 (Akamai) headers are produced here when enabled. There is no TCP SYN capture — no x-tcp-p0f from the kernel path.
  • Proxy + agent: a sidecar loads XDP, pins maps, and records SYNs; the proxy reads those maps and adds x-tcp-p0f. Needs Linux (e.g. kernel ≥ 5.11), bpffs, and the extra privileges described in eBPF TCP setup.

JA4 and Akamai always come from the proxy process; only the SYN fingerprint depends on the agent.

  • TLS (JA4): Computed from the ClientHello; in typical use, once per TLS session and reused for requests on that session.
  • TLS (JA4-S v1): Same ClientHello source, but ephemeral extensions (e.g. session_ticket, padding) are stripped before hashing, producing a stable fingerprint that does not change across reconnects caused by those extensions. Emitted as x-tls-ja4-sv1 and x-tls-ja4-sv1r.
  • HTTP/2 (Akamai): From HTTP/2 SETTINGS / control frames on that connection.
  • TCP SYN: From the initial SYN when eBPF is enabled; applies to the TCP connection, not each HTTP request on keep-alive.

The proxy overrides client-supplied X-Forwarded-* values. Treat x-tls-*, x-http2-*, and x-tcp-* headers as produced by the proxy, not the client.