Skip to content
Guides 7 Connection Type: 2 views

Proxy for WebSocket Connections

A comprehensive guide to setting up and troubleshooting WebSocket proxy connections. Master GProxy for robust, real-time communication.

Proxying WebSocket connections involves configuring an intermediary server to correctly handle the HTTP Upgrade handshake and maintain the persistent, full-duplex TCP connection required for WebSocket communication. This setup allows for features like load balancing, SSL termination, caching, and access control for real-time applications.

Understanding WebSocket Proxying

WebSockets establish a persistent connection between a client and a server over a single TCP connection. This differs from traditional HTTP, which typically uses short-lived request/response cycles. The transition from HTTP to WebSocket is initiated via an "Upgrade" mechanism in the HTTP/1.1 protocol.

The client sends an initial HTTP GET request with specific headers:
* Upgrade: websocket
* Connection: Upgrade
* Sec-WebSocket-Key: [base64-encoded nonce]
* Sec-WebSocket-Version: 13

If the server supports WebSockets, it responds with an HTTP 101 Switching Protocols status, confirming the upgrade:
* HTTP/1.1 101 Switching Protocols
* Upgrade: websocket
* Connection: Upgrade
* Sec-WebSocket-Accept: [response key derived from client's key]

After this handshake, the connection is no longer HTTP but a raw TCP socket, over which WebSocket frames are exchanged. A proxy server must be configured to correctly forward these Upgrade and Connection headers and then maintain the long-lived TCP connection without buffering or closing it prematurely.

Setup for Common Proxy Servers

Nginx

Nginx can proxy WebSocket connections effectively by handling the HTTP Upgrade handshake. The key is to pass the Upgrade and Connection headers from the client to the backend server and ensure HTTP/1.1 is used.

http {
    upstream websocket_backend {
        server backend_server_1:8080;
        server backend_server_2:8080;
    }

    server {
        listen 80;
        server_name yourdomain.com;

        location /ws/ {
            proxy_pass http://websocket_backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host; # Important for backend if it relies on host header
            proxy_read_timeout 86400s; # Adjust as needed for long-lived connections
            proxy_send_timeout 86400s;
            proxy_buffering off; # Disable buffering for real-time data
        }

        # Other HTTP locations
        location / {
            proxy_pass http://other_http_backend;
            # ... other HTTP proxy settings
        }
    }
}
  • proxy_http_version 1.1;: Essential for the Upgrade header mechanism.
  • proxy_set_header Upgrade $http_upgrade;: Forwards the client's Upgrade header.
  • proxy_set_header Connection "upgrade";: Forwards the client's Connection header. Nginx automatically handles the transformation of Connection: upgrade to Connection: keep-alive for HTTP/1.1 connections if not explicitly set to "upgrade". Setting it explicitly ensures correct behavior for WebSockets.
  • proxy_read_timeout / proxy_send_timeout: Increase these from default values to prevent Nginx from closing long-lived WebSocket connections due to inactivity.
  • proxy_buffering off;: Prevents Nginx from buffering responses, which is critical for real-time WebSocket communication to ensure minimal latency.

Apache HTTP Server

Apache can proxy WebSocket connections using mod_proxy_wstunnel, which is part of mod_proxy. Ensure mod_proxy, mod_proxy_http, and mod_proxy_wstunnel are enabled.

<VirtualHost *:80>
    ServerName yourdomain.com

    # Enable proxy modules
    LoadModule proxy_module modules/mod_proxy.so
    LoadModule proxy_http_module modules/mod_proxy_http.so
    LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

    # Proxy WebSocket connections
    <Location /ws/>
        ProxyPass ws://backend_server:8080/ws/
        ProxyPassReverse ws://backend_server:8080/ws/
    </Location>

    # Proxy secure WebSocket connections (WSS)
    <Location /wss/>
        ProxyPass wss://backend_server:8443/wss/
        ProxyPassReverse wss://backend_server:8443/wss/
    </Location>

    # Other HTTP locations
    <Location />
        ProxyPass http://other_http_backend/
        ProxyPassReverse http://other_http_backend/
    </Location>
</VirtualHost>
  • ProxyPass ws://...: The ws:// schema tells mod_proxy_wstunnel to handle the WebSocket upgrade. For secure WebSockets, use wss://.
  • ProxyPassReverse: Ensures correct URL rewriting in response headers.
  • Apache's mod_proxy handles the Upgrade and Connection headers automatically when ws:// or wss:// is specified.

HAProxy

HAProxy supports WebSocket proxying since version 1.5. It can operate in http mode to inspect headers or tcp mode for raw forwarding. For WebSockets, it's common to use http mode with specific rules to detect the upgrade request.

global
    log /dev/log    local0 info
    maxconn 4000
    user haproxy
    group haproxy
    daemon

defaults
    mode http
    log global
    option httplog
    option dontlognull
    timeout connect 5000ms
    timeout client 50000ms # Increased for client-side WebSocket connections
    timeout server 50000ms # Increased for backend-side WebSocket connections

frontend http_frontend
    bind *:80
    acl is_websocket hdr(Upgrade) -i websocket
    use_backend ws_backend if is_websocket
    default_backend http_backend

backend ws_backend
    mode http
    # This option is crucial for WebSockets in HTTP mode; it tells HAProxy to
    # switch to TCP tunneling after the HTTP upgrade.
    option http-tunnel
    server backend_ws_1 backend_server_1:8080 check
    server backend_ws_2 backend_server_2:8080 check

backend http_backend
    mode http
    server backend_http_1 backend_server_3:80 check
  • acl is_websocket hdr(Upgrade) -i websocket: Defines an Access Control List (ACL) that matches requests containing an Upgrade: websocket header (case-insensitive).
  • use_backend ws_backend if is_websocket: Directs WebSocket upgrade requests to the ws_backend.
  • option http-tunnel: This is critical. When HAProxy detects an Upgrade header and this option is set, it switches from HTTP parsing mode to a raw TCP tunnel after the initial HTTP handshake. This allows the WebSocket protocol to operate unimpeded.
  • timeout client / timeout server: These timeouts should be increased significantly for WebSocket backends to prevent HAProxy from closing long-lived connections.

Troubleshooting Common Issues

Connection Dropping or Timeout

  • Proxy Timeouts: The most common cause. Ensure proxy_read_timeout, proxy_send_timeout (Nginx), timeout client, timeout server (HAProxy), or equivalent settings in other proxies are sufficiently high (e.g., 24 hours or more) for WebSocket connections.
  • Idle Connections: Some proxies or network devices might aggressively close idle TCP connections. If the WebSocket protocol has a keep-alive mechanism (e.g., ping/pong frames), ensure it's configured on both client and server to send periodic pings.
  • Load Balancer Inactivity: If a load balancer sits in front of the proxy, it might also have its own inactivity timeouts. Check these settings.

HTTP 400 Bad Request (Upgrade Header Missing or Incorrect)

  • Client Request: Verify the client is correctly sending Upgrade: websocket and Connection: Upgrade headers.
  • Proxy Configuration: Ensure the proxy is configured to forward these headers to the backend.
    • Nginx: Check proxy_set_header Upgrade $http_upgrade; and proxy_set_header Connection "upgrade";.
    • Apache: Ensure mod_proxy_wstunnel is enabled and ProxyPass uses ws:// or wss://.
    • HAProxy: Confirm the acl is_websocket correctly identifies the Upgrade header and use_backend directs it to a backend with option http-tunnel.

HTTP 502 Bad Gateway

  • Backend Server Issues: The proxy received an invalid response from the backend.
    • Is the backend WebSocket server running and listening on the expected port?
    • Is the backend correctly configured to handle WebSocket upgrades?
    • Check backend server logs for errors.
  • Network Connectivity: Verify the proxy can reach the backend server on the specified port.
  • Proxy Buffering: While proxy_buffering off is generally good for WebSockets, excessive data or misconfigurations can sometimes lead to 502s if the proxy struggles to handle the stream.

Security Considerations (SSL/TLS Termination)

  • WSS (Secure WebSockets): For secure WebSocket connections (wss://), the proxy must handle SSL/TLS termination.
    • The proxy will listen on port 443 (or another secure port), perform the TLS handshake, and then proxy the decrypted WebSocket traffic to the backend (often over plain ws:// or http:// internally).
    • Example Nginx for WSS:
      ```nginx
      server {
      listen 443 ssl;
      server_name yourdomain.com;
      ssl_certificate /etc/nginx/ssl/yourdomain.crt;
      ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
      location /ws/ {
          proxy_pass http://websocket_backend; # Backend might be plain HTTP
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_set_header Host $host;
          proxy_read_timeout 86400s;
          proxy_send_timeout 86400s;
          proxy_buffering off;
      }
      

      }
      `` * **Origin Headers:** WebSocket clients send anOrigin` header. Backend servers often validate this header for security reasons. Ensure your proxy is not stripping or altering this header if the backend relies on it.

Proxy Buffer Limits

  • Nginx: proxy_buffering off; is crucial. If not set, Nginx might buffer large WebSocket messages, introducing latency or causing timeouts.
  • HAProxy: option http-tunnel handles this by switching to raw TCP.

Comparison of Proxy Servers for WebSockets

Feature Nginx Apache HTTP Server (mod_proxy_wstunnel) HAProxy
Configuration Manual header forwarding Specific ws:// / wss:// directives ACLs and option http-tunnel
Complexity Moderate Moderate Moderate to High (for advanced features)
Performance High (Event-driven) Moderate (Process/Thread-based) High (Event-driven)
SSL/TLS Termination Excellent Good Excellent
Load Balancing Round-robin, IP hash, least_conn Round-robin Extensive (many algorithms, health checks)
Sticky Sessions IP hash (for basic), third-party modules Limited Cookie-based, source IP
Buffering Control proxy_buffering off Handled by mod_proxy_wstunnel option http-tunnel disables HTTP buffering

Key Considerations

  • Sticky Sessions: For some WebSocket applications, a client might need to remain connected to the same backend server throughout its session (e.g., if server-side state is maintained).
    • Nginx: Use ip_hash in the upstream block.
    • HAProxy: Use balance source or cookie directives.
    • Ensure your backend application is designed for horizontal scaling without requiring sticky sessions if possible, as it simplifies load balancing.
  • Health Checks: Configure robust health checks for your backend WebSocket servers within the proxy. This ensures that only healthy servers receive WebSocket upgrade requests.
  • Logging: Configure comprehensive logging on the proxy and backend. WebSocket connection issues can be transient, and detailed logs are essential for diagnosis.
  • HTTP/2 and WebSockets: While WebSockets typically use HTTP/1.1 for the upgrade handshake, they can coexist with HTTP/2. However, the WebSocket protocol itself does not run over HTTP/2 frames directly. Proxies handling HTTP/2 from clients will typically downgrade to HTTP/1.1 for the WebSocket upgrade to the backend.
Auto-update: 04.03.2026
All Categories

Advantages of our proxies

25,000+ proxies from 120+ countries