WebSocket Upgrade and Bi-directional Proxy Guide
Overview
Toron supports full-duplex WebSocket protocol connections (RFC 6455) and HTTP/2 Extended CONNECT WebSockets (RFC 8441) for real-time web applications, chat services, and live telemetry streaming. The gateway detects HTTP/1.1 Upgrade: websocket headers, verifies 101 Switching Protocols handshakes, and provides transparent bi-directional stream tunneling between client sockets and backend microservice targets with built-in Slowloris defense and activity-refreshed idle deadline enforcement (SEC-27, CWE-400).
Configuration
WebSocket proxying works transparently over any standard upstream route in routes.yaml, governed by server-level idle timeout settings in config.yaml:
# config.yaml
server:
port: 8080
idle_timeout: "30s"
upgrade_idle_timeout: "60s" # Maximum inactivity deadline on WebSocket/upgraded streams (default: 60s)
# routes.yaml
routes:
# WebSocket Live Stream / Chat Upstream Target
- type: "upstream"
prefix: "/ws"
target: "http://localhost:9009"
How It Works
- HTTP/1.1 Handshake Verification (RFC 6455): When an incoming HTTP/1.1 request contains
Connection: UpgradeandUpgrade: websocket, Toron identifies the connection upgrade request and verifies the 101 status line. - HTTP/2 Extended CONNECT (RFC 8441): For HTTP/2 connections, clients send
:method = CONNECTand:protocol = websocket. Toron maps the extended CONNECT request, returns HTTP200 OKon the HTTP/2 stream, and bridges full-duplex stream data without dropping connection multiplexing. - Upstream Connection: Toron connects to the configured upstream target and forwards the original WebSocket handshake headers.
- Activity-Refreshed Bidirectional Stream Relay (
SEC-27):- Rather than permanently stripping socket deadlines, Toron arms both client and upstream sockets with
upgrade_idle_timeout(default60s). - Every chunk of data transferred in either direction refreshes read and write deadlines.
- If bidirectional silence exceeds
upgrade_idle_timeout, both sockets are deterministically severed viasync.Once, unblocking relay routines and reclaiming file descriptors. - Standard WebSocket Ping/Pong control frames (RFC 6455) and application keep-alives continuously refresh the deadline, keeping legitimate long-lived sessions active indefinitely.
- For HTTP/2 Extended CONNECT, a background watchdog monitors stream activity, tearing down the backend socket if inactivity occurs or if the client request context is cancelled (
r.Context().Done()/RST_STREAM).
- Rather than permanently stripping socket deadlines, Toron arms both client and upstream sockets with