torana

mTLS, header rewriting & mirroring

Traffic control and identity verification, all restricted to requests that are safe to duplicate or replay.

mTLS

Setting tls_client_ca on an https listener makes client certificates mandatory: a connection presenting no certificate, or one not signed by that CA, is rejected during the TLS handshake, before any HTTP request is processed. On success, torana forwards a SHA-256 fingerprint of the verified certificate to the upstream as X-Client-Cert-Fingerprint. That header is always stripped from the client's original request first, so it can never be spoofed by a client connecting over plain HTTP or a non-mTLS listener.

require client certificates
[[listener]]
addr = "0.0.0.0:8443"
protocol = "https"
tls_cert = "./certs/server.crt"
tls_key = "./certs/server.key"
tls_client_ca = "./certs/ca.crt"

Forwarded headers & trust boundary

torana sets X-Forwarded-Proto to the protocol the client actually connected with, and appends the real observed client IP to X-Forwarded-For (creating it if absent). If the client's own request already carried an X-Forwarded-For value, that value is kept and torana's IP is appended after it, the same convention nginx and Caddy use. This means an internet-facing torana listener does not by itself stop a client from forging the leading entries in its own X-Forwarded-For: only the last-appended IP is one torana actually observed on the socket. If an upstream trusts X-Forwarded-For for access control, rate limiting, or geolocation, it must read the last hop, not the first, or sit behind something (a CDN, a load balancer with its own trusted-proxy list) that strips or validates the header before torana ever sees it.

Header rewriting

Request overrides apply before the proxy's own X-Forwarded-* headers, so they can never override those; response overrides apply after the upstream replies. An empty string value removes the header instead of setting it.

rewrite headers
[route.headers]
request = { "x-internal-token" = "shared-secret" }
response = { "server" = "" }   # "" removes it

Traffic mirroring

Sends a duplicate, fire-and-forget copy of eligible requests to mirror.addr: the mirror's response (or failure, or timeout) never affects the real one. rate is 0-100 (default 100) and uses a low-cost timestamp-based approximation, not a cryptographic RNG, fine for sampling traffic, not for anything security-sensitive. Only GET/HEAD/OPTIONS requests with no body are mirrored, for the same reason retries are restricted the same way: duplicating a request that might carry a side effect risks running it twice.

mirror 10% of eligible traffic
[route.mirror]
addr = "http://127.0.0.1:3999"
rate = 10

Next: sandboxed WASM plugins.