|
4 weeks ago | |
---|---|---|
docs | 2 years ago | |
src | 2 years ago | |
Cargo.toml | 3 years ago | |
LICENSE | 3 years ago | |
README.md | 4 weeks ago | |
kracauer-config.toml | 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.