TLS Server Name Indication aware multiplexer/reverse proxy that retains source address information through the use of IPv6 and TUN devices (Planning Stage)
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
eaon 7888e99cde
Move to natively supported Mermaid diagrams
4 weeks ago
docs Pre-emptive documentation for the problems re: packet sizes 2 years ago
src Change how ports are configured/handled 2 years ago
Cargo.toml Read config from toml 3 years ago
LICENSE Publishing this under AGPL 3 (or later) 3 years ago
README.md Move to natively supported Mermaid diagrams 4 weeks ago
kracauer-config.toml Change how ports are configured/handled 2 years ago

README.md

Kracauer

Kracauer TLS Server Name Indication aware multiplexer and "stateless translator" (in this case, similar to a reverse proxy) that preserves IPv4 source address information by using a TUN device embedding it in an IPv6 /96 subnet of your choosing.

What's the problem now?

Usually reverse proxies work like this:

sequenceDiagram
    participant Client as 107.174.70.178 (Client)
    participant HAProxy as 93.184.216.34:443 (HAProxy)
    participant Host as 10.0.0.2:80 (httpd)
    Client->>HAProxy: TLS Handshake / ClientHello
    HAProxy-->>HAProxy: Pick host based on 𝗦𝗲𝗿𝘃𝗲𝗿 𝗡𝗮𝗺𝗲 𝗜𝗻𝗱𝗶𝗰𝗮𝘁𝗶𝗼𝗻
    HAProxy->>Client: TLS Handshake Response
    Client->>HAProxy: HTTP Request inside TLS Session
    HAProxy-->>HAProxy: Inject 𝟭𝟬𝟳.𝟭𝟳𝟰.𝟳𝟬.𝟭𝟳𝟴 in HTTP headers
    HAProxy->>Host: HTTP Request (𝘯𝘰𝘵 𝘱𝘢𝘳𝘵 𝘰𝘧 𝘵𝘩𝘦 𝘛𝘓𝘚 𝘴𝘦𝘴𝘴𝘪𝘰𝘯 𝘸𝘪𝘵𝘩 𝘵𝘩𝘦 𝘊𝘭𝘪𝘦𝘯𝘵)

In this case, TLS termination is handled by the reverse proxy, while injecting X-Original-IP or similar headers to allow logging the IPv4 address that actually accessed the resource.

Doing TLS termination on the reverse proxy is reasonable for many use cases, but if you also use IPv6 and allow it to direct communication with the hosts, then you are forced into quite a bit of duplication. Logging, TLS key material and configuration would necessarily be in multiple places. And that makes some sysadmins sad.

nginx also supports forwarding the entire TLS connection (even based on the requested hostname) without terminating it like so:

sequenceDiagram
    participant Client as 107.174.70.178 (Client)
    participant nginx as 93.184.216.34:443 (nginx)
    participant Host as 10.0.0.2:443 (httpd)
    Client->>nginx: TLS Handshake / ClientHello
    nginx-->>nginx: Pick host based on 𝗦𝗲𝗿𝘃𝗲𝗿 𝗡𝗮𝗺𝗲 𝗜𝗻𝗱𝗶𝗰𝗮𝘁𝗶𝗼𝗻
    nginx->>Host: TLS Handshake / ClientHello
    Host->>nginx: TLS Handshake Response
    nginx->>Client: TLS Handshake Response

When using this setup however, the host has no idea what the source address of the request was because the reverse proxy cannot inject headers into a TLS connection it doesn't terminate.

And what does Kracauer do instead?

Luckily, IPv6 is very generous with its availability of addresses, allowing us to just map the originating IP address onto an subnet that we have control over. RFC7755 talks about Stateless IP/ICMP Translation for datacenters (SIIT-DC) - Kracauer isn't an implementation of this but utilises the same principle. Instead of using an Explicit Address Mapping (RFC7757) however, Kracauer's map is based on hostnames. It inspects the TLS ClientHello (or HTTP request) and forwards the TLS (or HTTP) packets transparently to the appropriate host.

This is possible because a virtual TUN interface allows us to read/write packets from/to arbitrary sources/destinations. By embedding the client's source address into our virtual IPv6 source address, the host still has an idea about the source address while the TLS session is between the host and the client.

sequenceDiagram
    participant Client as 107.174.70.178 (Client)
    participant Kracauer as 93.184.216.34:443 (Kracauer)
    participant Host as [2001:470:8b1c:5d::1337]:443 (httpd)
    Client->>Kracauer: TLS Handshake / ClientHello
    Kracauer-->>Kracauer: Pick host based on 𝗦𝗲𝗿𝘃𝗲𝗿 𝗡𝗮𝗺𝗲 𝗜𝗻𝗱𝗶𝗰𝗮𝘁𝗶𝗼𝗻
    Kracauer-->>Kracauer: translate to IPv6 packets with source address ::𝗳𝗳𝗳𝗳:𝟬:𝟭𝟬𝟳.𝟭𝟳𝟰.𝟳𝟬.𝟭𝟳𝟴
    Kracauer->>Host: TLS Handshake / ClientHello
    Host->>Kracauer: TLS Handshake Response
    Kracauer-->>Kracauer: translate to IPv4 packets
    Kracauer->>Client: TLS Handshake Response

Kracauer doesn't know anything about keys or even certificates.

But I can't use IPv6 😢

Then I'm afraid retaining source address information while terminating TLS at the host is not possible and nginx' prepread, slt, or similar solutions are your only options.

On the origin of the software's name

Kracauer is named after Siegfried Kracauer who was, among other things, an architect and theorist that wrote about alienation in architecture:

[…] The hotel lobby (Hotelhalle), [is] seen by Kracauer […] as epitomizing the conditions of modern life in their anonymity and fragmentation […].

[…] the modern urban dweller could rely only on spaces, like that of the hotel lobby, “that bear witness to his nonexistence.” Detached from everyday life, individual atoms with no connection save their absolute anonymity, the hotel guests were scattered like atoms in a void, confronted with “nothing” (vis-à-vis de rien); stranded in their armchairs, the guests could do little more than find a “disinterested pleasure in contemplating the world.” In this way, “the civilization that tends toward rationalization loses itself in the elegant club chair,” in the ultimate space of indifference.

— Anthony Vidler in Warped Space, chapter The Architecture of Estrangement: Simmel, Kracauer, Benjamin

Credits

Inspiration struck in a conversation with Guan. Guan is cool.