HTTP Proxying and Routing
Crate: kinetic-daemon Stage: 9 Reading time: 60 minutes Depends on: kinetic-types (Stage 1), kinetic-core (Stage 7), kinetic-network (Stage 8)
What Is This?
This file (http.rs) serves as the central traffic director and HTTP proxy interceptor for the Kinetic daemon. It acts as the critical bridge between traditional Web2 browsers (like Chrome, Firefox, or Safari) and the decentralized, P2P architecture of the Kinetic network.
When a user configures their operating system or web browser to use the Kinetic proxy (often facilitated via a PAC file), every single web request they make is routed through this daemon. The logic in this file determines exactly what to do with those HTTP and HTTPS requests.
This is not a general-purpose VPN or a generic web proxy designed to hide your IP address. It is a specialized, domain-aware routing engine that isolates traffic. Its singular purpose is to identify traffic destined for the .kin Top Level Domain (TLD), intercept it, resolve the decentralized routing paths via the Kinetic DHT (Distributed Hash Table), and forward the packets to the correct decentralized or web-bridged backend.
If a browser asks for google.com, this file will refuse to handle it, returning standard proxy error codes or simply dropping the traffic depending on the context. If a browser asks for saif.kin, this file takes complete ownership of the request lifecycle, ensuring that the traffic is routed over the Kinetic network.
This file is the literal entry point for all user-facing web traffic entering the Kinetic ecosystem.
Why Kinetic Needs This
Kinetic fundamentally changes how domains are registered, resolved, and hosted. Traditional DNS relies on ICANN, root servers, and centralized UDP-based queries. Kinetic relies on cryptographic keypairs, peer-to-peer hash tables, and decentralized storage.
However, web browsers are ignorant of Kinetic’s architecture. They speak HTTP, they expect standard DNS resolution via UDP port 53 to their ISP, and they definitely do not know what a libp2p PeerId is. We cannot ask users to write command-line scripts to download decentralized websites, nor can we realistically force the entire world to use a custom, bespoke “Kinetic Browser.” Widespread adoption requires friction-less integration with existing tools that users already have installed.
This file solves the integration problem. By running a local HTTP proxy on the user’s machine (for example, bound to 127.0.0.1:8080), Kinetic inserts itself into the browser’s standard execution flow. The browser asks the proxy to fetch a webpage, and the proxy (this file) translates that standard HTTP request into a series of decentralized operations.
Without this file, the entire system falls apart from a usability perspective:
- Browsers would try to ask OS-level DNS for
.kinrecords. - Because
.kinis not an ICANN-recognized TLD, the ISP’s DNS servers would immediately returnNXDOMAIN(domain does not exist). - Even if we somehow hijacked the OS DNS to return a decentralized identifier, standard browsers have no idea how to open a TCP connection to a libp2p
PeerIdor how to fetch data from an IPFS CID natively. - Users would not be able to load decentralized IPFS content directly from a
.kindomain without manually typing out long, ugly IPFS gateway URLs.
Furthermore, because this proxy runs locally and has access to the user’s internal network, it introduces massive security risks if not handled perfectly. A malicious actor could register a .kin domain and point its DNS record to the user’s local router IP (192.168.1.1). If the user visited that domain, the proxy would obediently fetch the router’s admin page, potentially exposing the local network.
Therefore, this file is not just a router; it is Kinetic’s primary application- layer firewall. It implements strict Server-Side Request Forgery (SSRF) protections, aggressive header sanitization, and infinite proxy loop prevention. It protects the user’s local machine from the decentralized web, and it protects the decentralized web from leaking the user’s local secrets.
How It Works
The architecture of this file is divided into two distinct halves: a front-end receiver that handles the incoming browser protocol, and a backend router that performs the actual DHT resolution and forwarding.
Phase 1: Request Interception and Protocol Handling
The entry point for all proxy logic in this file is the handle_proxy_request asynchronous function.
-> See: crates/kinetic-daemon/src/proxy/http.rs — Lines 6 to 106
1. Loop Prevention via Custom Headers
Before doing any protocol analysis, the proxy inspects the incoming HTTP request headers for a custom Kinetic-specific header: x-kinetic-loop-protect. If this header is present, it checks if the value exactly matches the daemon’s own local libp2p PeerId. If it matches, the request is immediately aborted, returning an HTTP 508 Loop Detected status code to the client.
Why is this necessary? In a decentralized network where nodes can proxy traffic to other nodes, routing loops are a threat. Imagine this scenario:
- Node A has a
.kindomain that resolves to Node B’s IP address. - Node B’s DNS configuration for that same domain accidentally resolves back to Node A.
- A user on Node A requests the domain. Node A forwards the request to Node B.
- Node B receives the request, resolves the domain, and forwards it back to Node A.
Without loop protection, this request would bounce back and forth infinitely, consuming 100% of the network bandwidth and CPU on both daemons until they crash. By injecting the x-kinetic-loop-protect header on all outbound proxy requests, Kinetic ensures that a request can never bounce back to the node that originally sent it.
2. Handling HTTPS (The CONNECT Method)
When a browser wants to visit a secure HTTPS website, it does not send the actual HTTP GET request to the proxy. If it did, the proxy would be able to see the plaintext traffic, defeating the purpose of TLS encryption. Instead, the browser uses the HTTP CONNECT method. This is the browser asking the proxy to act as a blind TCP tunnel. The proxy just forwards encrypted bytes back and forth without looking at them.
-> See: crates/kinetic-daemon/src/proxy/http.rs — Lines 22 to 66
- The proxy extracts the target hostname from the
CONNECTURI. - It immediately performs TLD validation. It normalizes the host and checks if it ends with the configured
TLD_SUFFIX(which is.kin). If it does not, the proxy returns an HTTP 403Forbidden. This enforces that the Kinetic daemon is only used to access the Kinetic network, preventing it from being abused as an open relay for the standard web. - If the domain is a valid
.kindomain, the proxy acknowledges the connection by returning an HTTP 200OK. - Simultaneously, it uses
tokio::spawnto spin up an asynchronous background task. - Inside this task, it calls
hyper::upgrade::on(req). This is a crucial Rust networking concept. It takes the standard HTTP request-response cycle and “upgrades” the underlying socket into a raw, bidirectional byte stream. - This upgraded raw stream is then passed to the
handle_connectfunction (which handles the actual TLS bridging and SNI routing, and is documented in its own topic file).
3. Handling Plain HTTP Fallback
If the request method is not CONNECT, it is a standard HTTP request (like a GET or POST over port 80).
-> See: crates/kinetic-daemon/src/proxy/http.rs — Lines 68 to 106
- Because standard proxy requests include the full URL in the request line, the proxy manually extracts the
HOSTheader and the URL path. - It performs the exact same TLD validation as the
CONNECTblock, returning an HTTP 502Bad Gatewayif the domain is not a.kindomain. - If valid, it passes the original request, the extracted hostname, the network client, and the daemon’s configuration into the massive
forward_to_backend_directfunction.
Phase 2: Domain Resolution and Routing
Once the proxy knows it needs to fetch a plain HTTP payload for a specific .kin domain, it enters the core routing logic inside forward_to_backend_direct.
-> See: crates/kinetic-daemon/src/proxy/http.rs — Lines 109 to 222
The Resolution Loop
Because DNS domains can use CNAME records to alias to other domains, the resolution process must happen in a loop. Kinetic enforces a strict maximum of 10 recursion steps. If a domain CNAMEs to another domain more than 10 times, the proxy aborts the request. This prevents malicious infinite CNAME chains designed to exhaust the daemon’s CPU.
Step-by-Step Resolution:
- Apex Extraction: The router takes the target domain (for example,
api.saif.kin) and extracts the apex domain (saif.kin). This is vital because all DNS records in the Kinetic network are stored and signed at the apex level to ensure cryptographic integrity of the entire zone. - DHT Lookup: The router calls
network_client.resolve_redundant_payload(&apex_domain). Instead of asking a centralized DNS server over UDP, this asks the libp2p Kademlia DHT for the bytes associated with the apex domain.- CROSS-CRATE: The
resolve_redundant_payloadfunction and the DHT mechanics are explained deeply in thekinetic-network(Stage 8) documentation.
- CROSS-CRATE: The
- JSON Deserialization Quirk: The bytes returned by the DHT are not raw DNS records. They are a JSON-serialized
NameRecord. This record contains cryptographic signatures, timestamps, and an inner payload.- The code uses
serde_json::from_sliceto parse theNameRecord. - It then extracts the inner
payload()field. This payload is the actual zone file data, which it passes toDnsZone::parse_payloadto reconstruct the full zone structure in memory. - CROSS-CRATE: The
NameRecordstruct andDnsZoneparsing logic are documented inkinetic-core(Stage 7).
- The code uses
- Subdomain Matching: The router must now find the specific record the user asked for. It calculates the requested subdomain. If the target was
saif.kin, the subdomain is@(the standard DNS symbol for the apex). If the target wasapi.saif.kin, it trims the apex and determines the subdomain isapi. - Record Selection & Precedence: It looks up the records for the calculated subdomain inside the parsed
DnsZone. A single subdomain can have multiple records defined by the owner. The router iterates through them, attempting to find a routable target based on a specific match statement:- IP Addresses (
A/AAAA): If found, the target is treated as a Web2 bridge. The loop breaks immediately. - P2P Identifiers (
PeerId): If found, the target is treated as a native decentralized route. The loop breaks immediately. - Decentralized Storage (
IPFS): If found, the target is formatted as anipfs://string and treated as a static content route. The loop breaks immediately. - Aliases (
CNAME): If found, the loop updates the target domain and restarts the entire resolution process from Step 1 (up to the 10-hop limit). Crucially, the code checks if the CNAME target ends in.kin. External CNAMEs (e.g., pointing a.kindomain toaws.com) are rejected and fail the resolution. - Text (
TXT):TXTrecords are skipped in this loop via acontinuestatement, as they contain verification data, not routing data.
- IP Addresses (
Phase 3: The Three Routing Strategies
Once the resolution loop terminates with a concrete target string, the router branches into one of three distinct execution paths based on the format of the target.
Strategy 1: IPFS Gateway Proxying
-> See: crates/kinetic-daemon/src/proxy/http.rs — Lines 225 to 269
If the target string begins with the ipfs:// protocol prefix, the domain is hosting a static website on the InterPlanetary File System.
Since standard web browsers cannot natively speak the IPFS swarm protocol, the proxy must bridge the request through an HTTP IPFS Gateway (which can be a public gateway like ipfs.io, or a local IPFS node running on the user’s machine).
- URL Construction: The proxy extracts the CID (Content Identifier) from the target string. It constructs a brand new URL by combining the configured
ipfs_gatewaysetting from the daemon’s config, the CID, and the user’s originally requested HTTP path. - Example: A request for
http://blog.kin/style.csspointing toipfs://QmABCbecomes a request tohttp://127.0.0.1:8080/ipfs/QmABC/style.css. - Request Forwarding: It uses the asynchronous
reqwestHTTP client to forward the request to the gateway. - Header Stripping (Request): The proxy strips the original
HOSTheader from the request before sending it to the gateway. If it left theHOST: blog.kinheader intact, the IPFS gateway would try to serve content forblog.kininstead of parsing the URL path for the CID, and the request would fail with a 404. - Header Stripping (Response): When the IPFS gateway responds with the content, the proxy iterates through the response headers and strips out the
Strict-Transport-Security(HSTS) header before passing the response back to the browser. - Why? Because if the browser caches an HSTS policy for a
.kindomain, it will stubbornly refuse to load that domain over plain HTTP in the future. Because IPFS gateways often enforce HSTS by default, we must strip it to prevent breaking the local proxy experience for the user.
Strategy 2: IP Routing and SSRF Protection (Web2 Bridging)
-> See: crates/kinetic-daemon/src/proxy/http.rs — Lines 271 to 379
If the target string parses successfully as a standard IPv4 or IPv6 address, the .kin domain is bridging out to a traditional web server. Because this instructs the local daemon to make arbitrary TCP connections based on untrusted DNS data, this is the most dangerous path in the entire codebase.
- The SSRF Threat: Server-Side Request Forgery (SSRF) occurs when an attacker tricks a server into making unauthorized internal network requests. If an attacker registered
evil.kinand pointed its DNSArecord to127.0.0.1:8080, and the user visited that domain, the attacker could theoretically interact with local services running on the user’s machine, bypassing the user’s local firewall. - Port Protection (Case 199): To combat this, the proxy deeply inspects the requested port. If the domain points to a loopback address (
127.0.0.1) OR an unspecified address (0.0.0.0), AND it attempts to hit one of the Kinetic Daemon’s own internal listening ports, the request is hard-blocked and rejected with a Proxy Error. - The blocked ports include:
proxy_port,api_port,dns_port,backend_port, the networkdaemon_port, and thepac_port. - This prevents infinite proxy loops and protects the daemon’s internal, unauthenticated API from being accessed via a malicious domain. This check occurs even in Dev Mode. It cannot be bypassed.
- Network Isolation: Next, it uses a helper function (
is_ssrf_risk) to check if the IP resides in a private network block (e.g.,192.168.x.x,10.x.x.x). Unless the user has enabledis_dev_modein their configuration, the proxy blocks all requests to private networks entirely. - Dev Mode Bypass: Developers often need to point a
.kindomain to a local development server running on their laptop (e.g.,192.168.1.5:3000). Enabling Dev Mode bypasses the private network block, allowing these requests through, though it still logs a stark warning. - HTTPS Auto-Upgrade: If the IP is a public, safe, routable IP, Kinetic assumes the target server is a modern Web2 server. To enforce security by default, it automatically upgrades the outbound connection scheme to
HTTPSand defaults the port to443(unless a specific port was requested by the user). - Certificate Forgiveness: Because the target IP is hosting a
.kindomain, it is unlikely to have a publicly trusted TLS certificate for that domain (since Certificate Authorities don’t recognize.kin). Therefore, the proxy configures the internalreqwestclient withdanger_accept_invalid_certs(true), allowing self-signed or invalid certificates for Web2 bridges. - Header Injection: It injects the
x-kinetic-loop-protectheader containing its own Peer ID before forwarding the request to the backend. - Just like the IPFS strategy, it sanitizes the response, stripping HSTS headers to prevent browser lock-out.
Strategy 3: Native P2P Routing
-> See: crates/kinetic-daemon/src/proxy/http.rs — Lines 380 to 468
If the target string parses successfully as a libp2p PeerId, the domain is hosted natively on another Kinetic node. The HTTP request must be serialized, wrapped, and sent over the decentralized swarm via libp2p.
- Dynamic Resolution (
HostRoutingRecord): Before routing, the proxy checks if the requested Peer ID is actually a staticHostRoutingRecord. In the Kinetic ecosystem, users with dynamic IPs can register a static, permanent Host ID. They then dynamically update the DHT to point that Host ID to their current, ephemeral Peer ID whenever their IP changes. - The proxy transparently resolves this by asking the
NetworkClientfor the current ephemeral Peer ID associated with the static Host ID. - Aggressive Privacy Sanitization: This is a critical security and privacy feature. When routing standard HTTP traffic over a public P2P network, we cannot trust the intermediary nodes or the destination node. The proxy strips sensitive headers from the incoming browser request before serializing it:
authorization: Removes API tokens and Basic Auth credentials.cookie: Removes session cookies. This prevents session hijacking. If a user had a cookie for a Web2 site, and accidentally visited a.kinsite with the same path structure, their browser might send the cookie. The proxy stops this dead.x-api-key: Removes custom authentication tokens.proxy-authorization: Removes local proxy credentials.
- Body Buffering and Memory Protection: Because P2P messages are handled as distinct byte packets in the libp2p request-response protocol, the proxy cannot easily stream infinite HTTP bodies as it could with a raw TCP socket. Instead, it uses
http_body_util::BodyExtand the.frame().awaitmethod to incrementally read the incoming HTTP request body into memory. - The 5MB Limit: As it buffers the body, it constantly checks the size. It enforces a strict
LIMITS_PROXY_MAX_BODY_BYTESlimit (currently 5 Megabytes). If a user tries to POST a file larger than 5MB to a P2P node, the proxy immediately aborts the connection. This prevents a malicious user from executing a memory exhaustion (OOM) attack on the local daemon by uploading a 10GB file. - P2P Transport: The sanitized headers, the URL path, the HTTP method, and the buffered body bytes are packaged into a custom
kinetic_network::ProxyRequeststruct. - The proxy calls
network_client.send_proxy_request. This function serializes the struct and transmits it over a dedicated libp2p request-response protocol to the target peer.- CROSS-CRATE:
send_proxy_requestand the underlying libp2p protocol are documented inkinetic-network(Stage 8).
- CROSS-CRATE:
- When the remote peer processes the request and replies, the proxy reconstructs a standard HTTP response. It strips HSTS and
public-key-pinsheaders, and streams the body back to the user’s local browser.
Key Pieces
handle_proxy_request
- Location:
http.rs:L6-L106 - What it does: The primary entry point for all incoming HTTP traffic originating from the local web browser or OS.
- Why it matters: It acts as the gatekeeper. It separates raw TCP
CONNECTtunnels (used for secure HTTPS) from standard HTTP plaintext fallback requests. Crucially, it enforces the.kinTLD restriction, ensuring the daemon is not abused as an open relay proxy for the clearnet.
forward_to_backend_direct
- Location:
http.rs:L109-L475 - What it does: The massive, monolithic routing engine that resolves a
.kindomain to a physical target and executes the correct forwarding strategy. - Why it matters: This function contains the core logic for decentralized DNS resolution, CNAME handling, and SSRF security. It is the absolute heart of the Kinetic proxy feature.
SSRF Port Protection Block (Case 199)
- Location:
http.rs:L298-L312 - What it does: Hard-blocks proxy requests that resolve to local IP addresses and attempt to hit the daemon’s own internal listening ports.
- Why it matters: Prevents a malicious
.kindomain from creating an infinite proxy loop or accessing the daemon’s private, unauthenticated management API. This protection cannot be bypassed, even when running in Dev Mode.
Header Sanitization Logic
- Location:
http.rs:L404-L419 - What it does: Iterates through all HTTP headers and strips sensitive authentication and cookie headers from requests destined for P2P targets.
- Why it matters: Ensures that a user’s local web browser does not accidentally leak sensitive Web2 session data over the public decentralized network to an untrusted peer.
How This Connects to the Rest of Kinetic
This file operates as a high-level orchestrator. It does not implement low-level networking protocols directly; instead, it glues together the local browser environment with the complex Kinetic core libraries.
- Inputs from the User: It receives standard HTTP traffic directly from a web browser (e.g., Chrome, Safari) or from operating system utilities using PAC (Proxy Auto-Configuration) files.
- Dependencies on
kinetic-core: It relies onkinetic_core::types::DnsZoneandkinetic_core::types::NameRecordto parse and understand the routing data retrieved from the network.- CROSS-CRATE:
DnsZoneandNameRecordconcepts are explained thoroughly in Stage 7 (kinetic-core).
- CROSS-CRATE:
- Dependencies on
kinetic-network: It uses theNetworkClientto query the Distributed Hash Table viaresolve_redundant_payloadand to transmit HTTP requests to other peers viasend_proxy_request.- CROSS-CRATE: DHT operations and the P2P proxy protocol are explained in
Stage 8 (
kinetic-network).
- CROSS-CRATE: DHT operations and the P2P proxy protocol are explained in
Stage 8 (
- Outputs to Backends: It generates outbound HTTP traffic to IPFS gateways and traditional Web2 servers using the
reqwestHTTP client, and outbound P2P traffic via the libp2p swarm.
Quick Reference
- Supported Target TLD:
.kinonly. Requests for other TLDs are rejected. - Maximum CNAME Recursion: 10 hops before aborting with a
NameNotFounderror. - Loop Protection Header:
x-kinetic-loop-protectprevents infinite A -> B -> A proxy loops. - Blocked Internal Ports (SSRF): Proxy Port, API Port, DNS Port, Backend Port, Daemon Port, PAC Port.
- Stripped P2P Request Headers:
authorization,cookie,x-api-key,proxy-authorization. - Stripped Response Headers:
strict-transport-security(HSTS),public-key-pins. - Max P2P Body Size: 5MB. Requests larger than this are dropped to prevent memory exhaustion.
- Dev Mode Impact: Allows routing to private IP addresses (e.g.,
192.168.x.x), but still blocks access to internal daemon ports.
Open Questions / Things to Revisit
-
P2P Body Streaming Inefficiency: Currently, the entire HTTP request body is buffered into memory (up to the 5MB limit) before being packaged into a
ProxyRequestand sent over the P2P network. While this effectively prevents memory exhaustion attacks, it makes uploading large files over the native P2P network practically impossible. We need to investigate if libp2p streams can be utilized to stream the HTTP body incrementally to the target peer, bypassing the need for a memory buffer entirely. -
HSTS Stripping Policy: The proxy indiscriminately strips
strict-transport-securityfrom all backend responses. This is a pragmatic choice to prevent browsers from locking themselves into HTTPS for domains that might later change to plain HTTP or P2P hosts. However, for node operators that intentionally want to enforce strict HTTPS for their.kinbridges, this forcefully downgrades their security. A future enhancement could allow nodes to opt-in to HSTS via a specific DNS TXT record flag. -
Hardcoded Connection Timeouts: The timeout for fetching data from an IPFS gateway is hardcoded to 30 seconds, and the timeout for Web2 IP bridges is 15 seconds. These values might be too aggressive for users on slow decentralized connections, leading to false failures. These values should eventually be extracted into the
KineticConfigso they can be tuned by the node operator. -
CONNECT Payload Inspection Blindspot: The
handle_proxy_requestfunction successfully intercepts theCONNECTmethod and spawns a tunnel, but this file does not inspect the contents of that tunnel whatsoever. If an attacker uses the proxy to tunnel non-TLS traffic (e.g., SSH or raw TCP attacks) to a.kindomain, the proxy will happily pass it through blindly. This is generally acceptable for a local proxy meant for web browsers, but we must ensure the downstreamhandle_connectlogic provides sufficient safeguards against protocol abuse.
Deep Dive: The SSRF Threat Model
To truly understand why the forward_to_backend_direct function is so complex, we must deeply analyze the threat model it is defending against. A Server-Side Request Forgery (SSRF) attack on a local proxy is uniquely devastating because the proxy runs on the user’s trusted local network.
Consider three distinct attack vectors that this file actively mitigates:
Vector 1: The Localhost Admin Panel
Many developers run local services on 127.0.0.1 (localhost), such as database admin panels (phpMyAdmin), local development servers, or even system management APIs. These services often lack authentication because they assume any traffic originating from 127.0.0.1 is the authorized local user. If an attacker registers evil.kin and points its DNS A record to 127.0.0.1:5432 (PostgreSQL), and tricks a Kinetic user into visiting http://evil.kin, the user’s browser sends the request to the Kinetic proxy. Without SSRF protection, the proxy would obediently connect to 127.0.0.1:5432 and forward the attacker’s HTTP payload into the local database, potentially executing arbitrary SQL commands. The is_ssrf_risk function in this file identifies 127.0.0.1 (loopback) and 0.0.0.0 (unspecified) as high-risk IPs and drops the connection.
Vector 2: The Home Router Attack
Most consumer home networks use a private IP space, typically 192.168.1.0/24 or 10.0.0.0/8. The home router usually resides at 192.168.1.1 and often has an administrative web interface that is vulnerable to Cross-Site Request Forgery (CSRF) or uses default credentials. An attacker can point router.evil.kin to 192.168.1.1. When the user visits this domain, the proxy, acting on behalf of the user, connects to the router. Because the proxy is on the same local network as the router, the connection succeeds. The attacker can then use the proxy to reconfigure the user’s router, perhaps changing its DNS settings to a malicious server. This is why Kinetic blocks all private IPv4 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and private IPv6 (Unique Local Addresses) by default.
Vector 3: The Internal Daemon Loop (Case 199)
This is the most subtle vector. The Kinetic daemon itself listens on several local ports (e.g., 127.0.0.1:8080 for the proxy, 127.0.0.1:3000 for the management API). What happens if an attacker points a domain back at the proxy port itself? The request hits the proxy. The proxy resolves the domain. The domain points back to the proxy. The proxy opens a new connection to itself and forwards the request. This creates an infinite loop of recursive proxy connections, rapidly exhausting all available file descriptors and memory on the host system, resulting in a severe Denial of Service (DoS). Furthermore, if the domain pointed to the daemon’s internal management API (which requires no authentication because it assumes local trust), the attacker could instruct the daemon to delete files or broadcast malicious P2P messages. This is mitigated by the explicit port-checking block (Lines 298-312), which is enforced unconditionally, even if the user has enabled Dev Mode.
Deep Dive: Rust Asynchronous Networking
This file makes heavy use of advanced Rust networking concepts. Let’s break down the mechanics of the CONNECT tunnel establishment.
When the handle_proxy_request function encounters a CONNECT method, it executes the following critical block:
- The function
hyper::upgrade::on(req)takes ownership of the incoming HTTP request. In the HTTP/1.1 protocol, a client can send anUpgradeheader (or in the case ofCONNECT, it is implied) to signal that it wants to stop speaking HTTP and start speaking a custom protocol over the established TCP socket. - The
hyperlibrary handles the complex state machine required to flush the HTTP response headers and hand over the raw, underlyingTcpStream(or TLS stream) back to the application. - Because waiting for the upgrade to complete and then pumping bytes back and forth is a long-running, blocking operation, Kinetic cannot perform it on the main proxy routing thread.
- It uses
tokio::spawn(async move { ... })to detach this workload into a lightweight asynchronous Green Thread. Theasync moveclosure captures the necessary variables (like theroot_caandleaf_cache) and moves them into the background task. - The main thread immediately returns an HTTP 200 OK response to the browser, telling it “The tunnel is ready, start sending your encrypted bytes.”
- In the background, the spawned task waits for
hyper::upgrade::onto return theUpgradedobject, which implementsAsyncReadandAsyncWrite. This object is then passed to the specializedhandle_connectTLS bridging logic.
Detailed Execution Walkthrough: P2P Routing
Let’s trace the exact lifecycle of a request destined for a decentralized peer.
- The Request Arrives: The user types
http://decentralized.kin/app.jsinto Chrome. Chrome sends an HTTP GET request to the local Kinetic proxy. - Entrypoint:
handle_proxy_requestreceives aRequest<Incoming>object from thehyperserver. - Loop Check: It extracts the
x-kinetic-loop-protectheader. It is absent (since Chrome didn’t send it). The check passes. - Method Check: The method is
GET, notCONNECT. It falls through to the plaintext handler. - Host Extraction: It parses the
Host: decentralized.kinheader. It verifies the.kinsuffix. - Delegation: It calls
forward_to_backend_direct, passing the request. - DHT Resolution: The routing loop asks the P2P
NetworkClientto resolvedecentralized.kin. - Payload Parsing: The DHT returns a JSON
NameRecord. The code deserializes it, extracts the payload, and parses it into aDnsZone. - Record Matching: It looks for the
@(apex) record in the zone. It iterates through the records and finds aDnsRecord::PeerId("12D3KooW..."). - Target Acquisition: The loop breaks. The target is a
PeerId. - Strategy Selection: The execution jumps to the P2P routing block (Strategy 3).
- Header Sanitization Loop: The code creates a new, empty
Vecfor headers. It iterates through the original request headers. If a header is namedcookie, it is dropped. If it is namedauthorization, it is dropped. TheHostheader is overridden to ensure it exactly matches the resolved domain. - Body Extraction: The code extracts the asynchronous body stream using
.into_body(). It enters awhile let Some(chunk)loop, polling the stream for data frames. - Buffer Limit Enforcement: As each frame arrives, its bytes are appended
to a
Vec<u8>. If the vector’s length exceedsLIMITS_PROXY_MAX_BODY_BYTES(5MB), the loop aborts and returns an error. - Serialization: The sanitized headers, the HTTP method string, the URL
path, and the fully buffered body bytes are assembled into a
ProxyRequeststruct. - Network Transmission:
network_client.send_proxy_requestis called. This uses libp2p’s request-response protocol to find the target peer in the swarm, open a substream, serialize theProxyRequestvia MessagePack or JSON, and transmit it. - Response Handling: The target peer processes the request and sends back
a
ProxyResponse. - Response Reconstruction: The proxy takes the
ProxyResponse, usesaxum::body::Body::fromto convert the returned byte array back into an asynchronous body stream, applies the returned headers (while skippingstrict-transport-security), and returns the finalResponseobject to thehyperserver. - Delivery: The
hyperserver writes the HTTP response back down the TCP socket to Chrome. The user seesapp.jsload successfully.
Error Handling and Protocol Signalling
When a proxy fails to route a request, it is critical that it communicates the failure correctly to the upstream web browser. Browsers have specific hardcoded behaviors for different HTTP error codes when they are communicating with a proxy server. This file maps Kinetic’s internal routing failures to standard HTTP status codes.
- HTTP 508 Loop Detected: If the
x-kinetic-loop-protectheader matches the daemon’s own Peer ID, the proxy returns a 508. This is a relatively obscure HTTP status code introduced by WebDAV, but it is semantically perfect here. It immediately tells the client (or the upstream proxy in a chain) that the network topology is broken. - HTTP 403 Forbidden: If a browser tries to establish a
CONNECTtunnel to a non-.kindomain (likegoogle.com:443), the proxy returns a 403. This is the standard proxy signal for “I understand your request, but I am administratively configured to refuse it.” This prevents the Kinetic daemon from being used as a generalized open relay, which would consume bandwidth and potentially expose the user’s IP address. - HTTP 502 Bad Gateway: If the proxy receives a plain HTTP request for a non-
.kindomain, or if theforward_to_backend_directfunction fails to resolve the domain in the DHT, it returns a 502. This tells the browser that the proxy itself is functioning correctly, but the upstream server (in this case, the decentralized network) failed to provide a valid response.
The overarching philosophy of error handling in this file is fail-closed. If a domain cannot be resolved, if an IP address is suspicious, or if a payload is too large, the proxy immediately aborts the connection rather than attempting a risky fallback.
Forward References: The CONNECT Tunnel and Certificates
While this file handles the interception of the CONNECT method, it does not actually perform the TLS man-in-the-middle attack necessary to bridge HTTPS traffic.
When hyper::upgrade::on yields the raw byte stream, it passes that stream, along with the root_ca and a leaf_cache, into the handle_connect function.
- The
root_cais the Kinetic daemon’s dynamically generated local Certificate Authority. - The
leaf_cacheis a memory-safe, thread-safe hash map (Arc<Mutex<LeafCertCache>>) that stores temporarily generated certificates for specific.kindomains.
Because generating RSA or ECDSA keypairs for every single HTTPS request is computationally expensive, the leaf_cache is passed from the main proxy state down into the connection handler. This allows the connection handler to reuse the fake certificate for saif.kin across multiple concurrent HTTP requests, dramatically improving proxy latency. FORWARD DEPENDENCY: The exact mechanics of TLS certificate generation, SNI parsing, and stream bridging are documented in the subsequent topic file covering https.rs. For now, understand that http.rs sets up the tunnel, and https.rs executes the cryptography within it.
Architectural Analogy
Think of this file as the strict border control checkpoint of a sovereign nation (the Kinetic Network).
- The browser is a foreigner arriving at the border. It speaks a different language (HTTP) and expects different infrastructure (ICANN DNS).
- The
handle_proxy_requestfunction is the initial passport check. It ensures the traveler is actually trying to enter the correct country (the.kinTLD) and isn’t a known threat (loop protection). - The
forward_to_backend_directfunction is the immigration routing system. It looks up the traveler’s destination in the national database (the DHT), ensures they aren’t trying to access restricted military bases (SSRF private network protection), and assigns them an escort to safely reach their final destination (the P2P proxying or IPFS bridging).