# NaiveProxy: A Secure Alternative to VLESS Based on Chromium
Amid aggressive blocking efforts, the NaiveProxy protocol offers a unique traffic camouflage approach—leveraging Chromium's original networking stack. We'll walk through setting up the client and server using sing-box and Caddy, dodging common pitfalls.
Traffic Camouflage Basics: Why NaiveProxy Beats uTLS?
Standard proxy protocols disguise themselves as HTTPS traffic, but the initial ClientHello packet stays vulnerable. It sends the TLS version, cipher list, and domain in plaintext. Go-based implementations (including Xray and sing-box) feature a telltale ClientHello fingerprint unique to the language, making them identifiable even with uTLS. The uTLS library only mimics browser behavior in that first packet, failing to replicate network stack subtleties like data transmission rhythm, frame lengths, and HTTP/2 quirks. NaiveProxy tackles this head-on by embedding a Chromium fragment that delivers pixel-perfect browser traffic emulation.
NaiveProxy Architecture: From Chromium to Proxy
The protocol's creator, klzgrad, stripped Chromium's source code down to just 0.3% of its functionality, keeping only what's needed for networking. Key features:
- Uses Chromium's native HTTP/2 stack for multiplexing
- Perfect match for ClientHello and subsequent packets to real browser traffic
- Ditches custom ciphers for standard TLS mechanisms
Important: It's fully compatible with standard HTTP/2 proxies in both directions. Naive clients work with any HTTP/2 proxy, and Naive servers accept connections from standard clients. But true camouflage only happens with Chromium's network stack—like in sing-box. Other clients (e.g., Go-based ones) may connect to a Naive server but won't provide full anonymity.
Padding: Three Layers of Protection Against Traffic Analysis
The protocol employs multi-level padding to thwart packet length analysis:
- DATA frames: The first 8 frames of each stream add a header (2 bytes for data length + 1 byte for padding length), followed by original data and padding bytes.
- CONNECT requests: Random-length headers bulk up frame sizes arbitrarily.
- END_STREAM: Extra frames before each RST_STREAM.
Testing revealed a critical flaw in sing-box: Instead of zeroing the buffer when adding padding, it sent leftover data from prior requests. This leaked sensitive info (like domain names and headers). Fixed in versions 1.13.1+ after merging two PRs that force buffer zeroing.
Client Setup: sing-box Outbound
Requires sing-box 1.13+. Client config:
{
"type": "naive",
"tag": "Proxy1",
"server": "1.2.3.4",
"server_port": 443,
"username": "username",
"password": "password",
"insecure_concurrency": 1,
"udp_over_tcp": {
"enabled": true
},
"quic": false,
"tls": {
"enabled": true,
"server_name": "s1.example.com"
}
}
Key parameters:
insecure_concurrency: Stick to 1. Higher values make traffic easier to analyze.udp_over_tcp: Enable for UDP support.server_name: Domain set up in Caddy. Must match the TLS section's server_name.
Caddy as TLS Terminator: Config and Fallback
Caddy handles TLS connections and routes traffic to the proxy or a decoy. Config (/etc/caddy/Caddyfile):
{
email [email protected]
auto_https disable_redirects
}
:443, https://s1.example.com {
tls {
issuer acme {
disable_http_challenge
}
}
route {
@naive {
method CONNECT
header Proxy-Authorization "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
}
handle @naive {
reverse_proxy h2c://127.0.0.1:1080 {
header_up Proxy-Authorization {header.Proxy-Authorization}
}
}
handle {
root * /srv/naive-fallback
file_server
}
}
}
Key points:
Proxy-Authorizationheader holds base64-encodedusername:password(generate withecho -n "username:password" | base64)./srv/naive-fallbackdirectory serves a static decoy site to fend off scans.auto_https disable_redirectsskips HTTP→HTTPS redirects since port 443 is HTTPS-only.
Server Side: sing-box Inbound and Caddy Integration
Server sing-box config (/etc/sing-box/config.json):
{
"log": {
"level": "warn",
"output": "/var/log/sing-box/sing-box.log"
},
"inbounds": [
{
"type": "naive",
"tag": "naive-in",
"network": "tcp",
"listen": "127.0.0.1",
"listen_port": 1080,
"users": [
{
"username": "username",
"password": "password"
}
]
}
],
"outbounds": [
{
"type": "direct"
}
]
}
Important:
- Server listens only on localhost:1080, as Caddy handles external connections.
warnlog level minimizes disk I/O.- Passwords must exactly match client and Caddy settings.
Key Takeaways
- Full camouflage needs Chromium stack: Only implementations using the original network code (like sing-box) match browser traffic perfectly.
- Concurrency = risk:
insecure_concurrencyover 1 heightens vulnerability to packet length analysis. - Keep components updated: Use sing-box 1.13.1+ to fix padding data leaks.
- Decoy site is essential: Static site in Caddy hides the proxy from scans.
- Reality isn't foolproof: As Reality's history shows, even clever solutions can get blocked by new fingerprints (e.g., connection counts).
— Editorial Team
No comments yet.