NaïveProxy is built on a core insight: rather than designing a new protocol that attempts to look like browser traffic, it is browser traffic — generated by the same Chromium network stack that ships inside Chrome. This page explains how each layer of the design contributes to censorship resistance, and where the boundaries of that protection lie.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/klzgrad/naiveproxy/llms.txt
Use this file to discover all available pages before exploring further.
Architecture
NaïveProxy is a two-component system designed to place an undetectable proxy inside ordinary HTTPS communication.- Serve real web content to any visitor that does not present valid credentials, making the server look like an ordinary website to censors and active probers.
- Route authenticated requests to the Naïve server backend, which operates as a forward proxy and applies the padding protocol to tunneled streams.
TLS Fingerprinting Defense
One of the most reliable ways to identify proxy software is by profiling the TLSClientHello message — the opening handshake that every TLS client sends before any encrypted data is exchanged. Each TLS library has a distinctive fingerprint: a specific ordering of cipher suites, a characteristic set of extensions, particular elliptic curve preferences.
NaïveProxy defeats this entirely by reusing Chrome’s BoringSSL. The client binary is a stripped-down Chromium build. Its TLS ClientHello is generated by the same code path, with the same parameters, compiled from the same source as the Chrome release it tracks. There is no synthetic fingerprint — a censor observing the handshake sees a genuine Chrome client.
This defense is only as strong as the currency of the binary. Always use the latest NaïveProxy release so your TLS fingerprint matches the Chrome version currently in widespread use. See Introduction for download links.
Traffic Classification Defense
Even without inspecting the TLS handshake, deep packet inspection systems can classify traffic by its statistical properties: the timing, direction, and size distribution of packets within a session. Proxy protocols often produce distinctive patterns — a single long-lived stream, unusual request sizes, or a burst of small packets at session start. NaïveProxy mitigates this through HTTP/2 multiplexing, which is Chrome’s native connection model. Multiple logical streams share a single TCP connection, producing the same interleaved packet patterns as a browser with multiple tabs open. The initial preamble — the sequence of SETTINGS, WINDOW_UPDATE, and HEADERS frames at connection start — matches Chrome’s exact behavior. The padding protocol (described below) further flattens the distinctive length spikes produced by the initial proxy handshakes, blending them into the background of normal browser traffic.Active Probing Defense
A sophisticated censor does not rely only on passive observation. It may send its own probe requests to a suspected proxy server to confirm its function — a technique called active probing. A server that responds to unauthenticated requests with proxy behavior, or with an unusual error, reveals itself. NaïveProxy defeats active probing through application fronting: the frontend server is a real web server that responds to normal HTTP(S) requests with real web content. Only requests that include a valid HTTPAuthorization header are routed to the Naïve proxy backend. Everything else receives an ordinary web response.
The probe_resistance directive in Caddy’s forward_proxy block enables this behavior. A censor sending probe requests without credentials sees a legitimate website — there is no detectable proxy surface.
Length-Based Traffic Analysis Defense
Even with multiplexing and fingerprint matching, the initial frames of a new CONNECT tunnel have a predictable structure: the TLS handshake, the HTTP/2 SETTINGS exchange, and the CONNECT request itself produce characteristic length spikes that can distinguish proxy sessions from normal browsing. NaïveProxy addresses this with a padding protocol applied to the first 8 reads and writes of each CONNECT tunnel. See the full padding protocol specification for the complete struct layout and design rationale. The three padding mechanisms are:Proxy Payload Padding
The first8 reads and writes of every bidirectional CONNECT stream are padded. Each padded write carries the original data length (2 bytes), a random padding size byte, the original data, and zero-fill padding:
H2 HEADERS Frame Padding
The CONNECT request and response HEADERS frames are short by normal browser standards and would stand out by length alone. Apadding header is added to each — filled with pseudo-random symbols that resist Huffman compression and HPACK indexing. The padding length is randomly distributed in [16, 32] bytes for requests and [30, 62] bytes for responses, bringing frame sizes into a range typical of real browser requests.
H2 RST_STREAM Frame Padding
NaïveProxy tends to generate more RST_STREAM frames per session than a typical browser, which is an unusual behavioral signal. To mask this, an END_STREAM DATA frame with total length uniformly distributed in [48, 72] bytes is prepended to each RST_STREAM frame, making the combined frame appear to be a HEADERS frame to passive observers.Opt-In Padding Protocol
The padding protocol is negotiated via the presence of apadding header in the CONNECT request and response. This design preserves interoperability in both directions:
- A NaïveProxy client connecting to a standard HTTP/2 proxy (one that does not understand the padding protocol) simply receives no
paddingheader in the response and falls back to unpadded operation. - A NaïveProxy server receiving a CONNECT from a standard HTTP/2 client (for example, a regular Chrome browser) sees no
paddingheader in the request and serves it without padding.
Fast Open limitation: The first CONNECT request to a server cannot use Fast Open (sending payload before the server response). At that point, the client does not yet know whether the server supports the padding protocol — it learns this from the first response. Sending unpadded payload speculatively could reveal the session’s true nature if the server does not support padding, so Fast Open is deferred until the server’s capability is confirmed.
Post-Quantum Key Agreement
NaïveProxy enables X25519Kyber768 post-quantum key agreement by default, matching Chrome’s current behavior. This protects against future “harvest now, decrypt later” attacks where an adversary records encrypted traffic today intending to decrypt it once quantum computers become available. If you need to disable post-quantum key exchange — for example, because it causes compatibility issues with certain network middleboxes — you can pass the--no-post-quantum flag to the naive binary.