Skip to content

How it works

Traffic enters on listen.port (plaintext) and/or listen.port_tls (TLS). When https_redirection is effective, a matched plaintext request returns 301 and is not forwarded. Otherwise 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 an eBPF capture program (XDP or TC), 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 / JA4_s1): From the ClientHello; in typical use, once per TLS session and reused for requests on that session. Header names and the stable variant: Fingerprinting.
  • 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.