-
Notifications
You must be signed in to change notification settings - Fork 471
CONNECT tunnel with access: full + tls: skip still causes 405 from upstream (WhatsApp/Baileys) #760
Copy link
Copy link
Open
Description
Summary
WebSocket connections through the sandbox proxy fail with HTTP 405 from WhatsApp's Noise protocol handshake, even with access: full and tls: skip configured. The same connection succeeds when made directly from the VPS host (outside the sandbox).
Environment
- Gateway:
ghcr.io/nvidia/openshell/gateway:0.0.21 - Sandbox binary: built Apr 2, 2026 (post WS-relay fix c6f3087)
- VPS: Hetzner CPX32, Ubuntu 24.04, x86_64
- Client: Baileys 7.0.0-rc.9 (WhatsApp Web client library)
- Runtime: Node.js 22 inside sandbox, also tested with Bun
Policy (relevant section)
whatsapp:
name: whatsapp
endpoints:
- host: "*.whatsapp.net"
port: 443
access: full
tls: skip
- host: "*.whatsapp.com"
port: 443
access: full
tls: skip
binaries:
- path: /usr/local/bin/bun
- path: /usr/local/bin/nodeWhat works
| Test | Location | Result |
|---|---|---|
fetch('https://web.whatsapp.com/') via bun |
Inside sandbox | 200 OK |
Raw CONNECT to web.whatsapp.com:443 |
Inside sandbox | 200 Connection Established |
| TLS cert check after CONNECT | Inside sandbox | Real DigiCert cert (not MITM'd) |
| Baileys full connection (QR generated) | VPS host directly | Works |
| WebSocket open via ws library | Inside sandbox | Opens successfully |
What fails
| Test | Location | Result |
|---|---|---|
| Baileys connection via proxy | Inside sandbox (Node) | WS opens → Noise handshake → 405 |
| Baileys connection via proxy | Inside sandbox (Bun) | WS opens → Noise handshake → 405 |
Detailed failure sequence
[WhatsApp] connection.update connection=connecting
[WhatsApp] WS open # <-- WebSocket establishes
{"msg":"connected to WA"} # <-- Noise hello sent
{"msg":"not logged in, attempting registration..."}
# Then noise-handler.js:141 throws:
Connection Failure, data: { reason: "405", location: "atn" }
Analysis
- The CONNECT tunnel returns 200 and the TLS certificate is WhatsApp's real DigiCert cert (not the proxy's), so TLS termination appears to be correctly skipped.
- The WebSocket opens successfully through the tunnel.
- The failure happens at the application protocol level (WhatsApp's Noise protocol handshake), after the WebSocket is established.
- The exact same Baileys version, Node version, and WhatsApp account work when connecting directly from the VPS host without the proxy.
- This suggests the proxy is modifying something subtle about the TCP stream or WebSocket frames that WhatsApp's server-side validation detects and rejects.
Reproduction
- Create a sandbox with the policy above
- Inside the sandbox, install baileys and attempt a connection through the proxy agent
- Observe that the WebSocket opens but the Noise handshake fails with 405
- Run the same code on the host directly — it succeeds and generates a QR code
Expected behavior
With access: full + tls: skip, the proxy should act as a raw TCP relay after CONNECT, passing bytes unmodified between the client and upstream. The Baileys Noise handshake should succeed identically to a direct connection.
Workaround needed
Is there a policy configuration that produces a completely transparent TCP tunnel with zero modification of the byte stream? Or is there a known interaction between the proxy's frame handling and binary WebSocket protocols?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels