Skip to content
jprendesPublic

About

WebSocket proxy for TCP connections

Resources

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

wsproxy

A WebSocket proxy for TCP connections. Forward TCP traffic through WebSocket tunnels.

Architecture

TCP Client <---> ProxyClient <--WebSocket--> ProxyServer <---> TCP Server
  • ProxyServer: Listens for WebSocket connections and forwards data to TCP targets. Supports routing different URL paths to different backends.
  • ProxyClient: Listens for TCP connections and forwards data through WebSocket to the server.

Installation

cargo install --path .

Usage

Command Line

Server with a single default target:

wsproxy server --listen 0.0.0.0:8080 --default-target 127.0.0.1:22

Server with multiple routes:

wsproxy server --listen 0.0.0.0:8080 \
  --route /ssh=127.0.0.1:22 \
  --route /db=127.0.0.1:5432 \
  --route /redis=127.0.0.1:6379

Server with TLS (WSS):

wsproxy server --listen 0.0.0.0:8443 \
  --default-target 127.0.0.1:22 \
  --tls-cert cert.pem \
  --tls-key key.pem

Server with auto-generated self-signed certificate:

wsproxy server --listen 0.0.0.0:8443 \
  --default-target 127.0.0.1:22 \
  --tls-self-signed

Client:

wsproxy client --listen 127.0.0.1:2222 --server ws://proxy-server:8080/ssh

Client connecting to WSS server:

wsproxy client --listen 127.0.0.1:2222 --server wss://proxy-server:8443/ssh

Client with self-signed certificate (insecure mode):

wsproxy client --listen 127.0.0.1:2222 --server wss://proxy-server:8443/ssh --insecure

Client with custom CA certificate:

wsproxy client --listen 127.0.0.1:2222 --server wss://proxy-server:8443/ssh \
  --tls-ca-cert /path/to/ca.pem

SSH ProxyCommand (Tunnel Mode)

The tunnel command connects stdin/stdout directly to a WebSocket server, making it perfect for SSH's ProxyCommand option:

Direct tunnel:

wsproxy tunnel --server ws://proxy-server:8080/ssh

SSH config example:

Host myserver
    ProxyCommand wsproxy tunnel --server wss://proxy:8443/ssh
    User myuser

With self-signed certificate:

Host myserver
    ProxyCommand wsproxy tunnel --server wss://proxy:8443/ssh --insecure
    User myuser

Now ssh myserver will tunnel through the WebSocket proxy.

Docker

Run wsproxy in a container with automatic restart and startup on boot. See docs/docker.md.

Upstart

For systems using Upstart (Ubuntu 14.04 and earlier), see docs/upstart.md.

systemd

For systems using systemd (most modern Linux distributions), see docs/systemd.md.

Configuration File

Instead of command-line arguments, you can use a TOML configuration file with hot-reload support. When the config file changes, the server automatically picks up the new configuration without dropping active connections.

Start server with config file:

wsproxy server --config server.toml

Example configuration file (server.toml):

listen = "0.0.0.0:8080"
default_target = "localhost:22"

[routes]
"/ssh" = "ssh-server.internal:22"
"/db" = "db.example.com:5432"
"/redis" = "127.0.0.1:6379"

[tls]
cert = "cert.pem"
key = "key.pem"
# Or use: self_signed = true

Hostnames are resolved using DNS when each connection is established, allowing DNS changes to take effect without restarting the server.

Hot-reload behavior:

  • Routes and default_target changes: Applied instantly. Existing connections continue uninterrupted; new connections use the updated routing.
  • Listen address or TLS changes: Server automatically restarts. Existing connections continue until they complete naturally.
  • Invalid configuration: If the config file has syntax errors or invalid values, the error is logged and the server continues running with the previous valid configuration. Existing connections are not affected.

Note: The --config flag cannot be combined with other server options (--listen, --route, --default-target, --tls-*).

Library

use wsproxy::{ProxyServer, ProxyClient, TlsOptions};

#[tokio::main]
async fn main() -> wsproxy::Result<()> {
    // Server with multiple routes
    let server = ProxyServer::builder()
        .route("/ssh", "127.0.0.1:22")?
        .route("/db", "127.0.0.1:5432")?
        .bind("0.0.0.0:8080")?;

    // Server with TLS (WSS)
    let secure_server = ProxyServer::builder()
        .default_target("127.0.0.1:22")
        .tls("cert.pem", "key.pem")
        .bind("0.0.0.0:8443")?;

    // Server with auto-generated self-signed certificate
    let dev_server = ProxyServer::builder()
        .default_target("127.0.0.1:22")
        .tls_self_signed()
        .bind("0.0.0.0:8443")?;

    // Client (supports both ws:// and wss://)
    let client = ProxyClient::bind(
        "127.0.0.1:2222",
        "wss://proxy-server:8443/ssh",
        TlsOptions::default(),
    )?;

    // Client with custom CA certificate (for self-signed servers)
    let client_custom_ca = ProxyClient::bind(
        "127.0.0.1:2222",
        "wss://proxy-server:8443/ssh",
        TlsOptions {
            insecure: false,
            ca_cert_path: Some("/path/to/ca.pem".to_string()),
        },
    )?;

    // Run server with config file (supports hot-reload)
    // wsproxy::server::run_with_config("server.toml").await?;

    // Run (typically in separate processes)
    // server.run().await?;
    // client.run().await?;
    Ok(())
}

Example: Simple Chat with netcat

This example demonstrates a simple chat through the WebSocket proxy using nc (netcat).

Terminal 1 - Start a TCP listener (the "chat server"):

nc -l 9000

Terminal 2 - Start the proxy server:

wsproxy server --listen 127.0.0.1:8080 --default-target 127.0.0.1:9000

Terminal 3 - Start the proxy client:

wsproxy client --listen 127.0.0.1:2222 --server ws://127.0.0.1:8080

Terminal 4 - Connect to the proxy:

nc 127.0.0.1 2222

Now you can type messages in Terminal 4 and they will appear in Terminal 1 (and vice versa). The data flows:

Terminal 4 (nc) -> ProxyClient (:2222) -> WebSocket -> ProxyServer (:8080) -> Terminal 1 (nc :9000)

Press Ctrl+C in terminals 2 and 3 to stop the proxies (graceful shutdown).

License

MIT License - see LICENSE for details.

About

WebSocket proxy for TCP connections

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages