wstunnel

Tunnel anything through the one port firewalls leave open

scroll

Tunnel anything through the one port firewalls leave open.

wstunnel wraps TCP, UDP, SOCKS5 and more inside WebSocket, HTTP/2 or WebTransport, so your traffic walks through corporate proxies, captive networks and deep packet inspection looking like ordinary web traffic. One static Rust binary on each side, nothing else to install.

Linux, macOS, Windows, Android BSD-3-Clause Saturates a gigabit link on one connection
Without wstunnel, isometricAn application sends a packet straight at a firewall that only allows port 443. The packet is blocked at the wall and never reaches the service on the other side. application ssh, chrome, wireguard firewall only 443 gets through service sshd, dns, wireguard
Sent directly, the connection to port 22 stops at a firewall that only allows 443.

Up in two commands

One binary plays both roles. Start a server where you have unrestricted internet, then point a client at it from the constrained side.

1 On a host you control

my.server.com
# every interface, port 8080, TLS on
wstunnel server wss://[::]:8080

The server tells WebSocket from HTTP/2 on its own, so one listener serves both. Add --enable-webtransport to also serve QUIC on the same port. Pass your own certificate with --tls-certificate when you are ready.

2 On the constrained machine

laptop
# a SOCKS5 proxy on localhost:8888, exiting on the server
wstunnel client -L socks5://127.0.0.1:8888 \
  wss://my.server.com:8080

# socks5h resolves names on the far side
curl -x socks5h://127.0.0.1:8888 https://example.com

The syntax mirrors ssh -L and ssh -R: what to listen on, then where to forward. Every tunnel flag can be repeated.

What it carries, and how

wstunnel started as a way to get SSH out of a locked-down office. It now moves most kinds of traffic in either direction.

Forward tunnels

Listen locally and forward a fixed destination through the server, the way ssh -L does. Read from a Unix socket or from stdin when a program wants a pipe rather than a port.

  • tcp
  • udp
  • unix
  • stdio

Dynamic proxies

Decide the destination per connection instead of up front. Run a SOCKS5 or HTTP proxy for browsers and tools, or a transparent proxy on Linux to route any program without configuring it.

  • socks5
  • http
  • tproxy+tcp
  • tproxy+udp

Reverse tunnels

Have the server listen and forward back to your machine, so a service behind NAT or a strict firewall becomes reachable from the server's network. Same schemes, flipped with -R.

  • tcp
  • udp
  • socks5
  • http
  • unix

Transport

WebSocket by default, which performs best and survives most reverse proxies and CDNs. HTTP/2 is there for networks that block WebSocket upgrades. WebTransport runs the tunnel over HTTP/3 and QUIC for when TCP is throttled or lossy but UDP gets through. One server serves all three at once.

  • ws / wss
  • http / https
  • webtransport
  • IPv6
  • proxy protocol v2

Getting out

Reach the server through an HTTP proxy with credentials, override or hide the TLS SNI, use Encrypted Client Hello, and resolve names over DNS-over-HTTPS or DNS-over-TLS so the local resolver never sees them.

  • --http-proxy
  • --tls-sni-override
  • --tls-ech-enable
  • --dns-resolver

Locking the server down

Accept only clients that know a secret path prefix, restrict which destinations may be reached, or write YAML rules matching path, authorization header, protocol, port, host and CIDR. Certificates, keys, client CAs and rule files all reload on change.

  • --restrict-http-upgrade-path-prefix
  • --restrict-to
  • --restrict-config
  • mTLS

Common setups

The commands people actually run. Each one assumes a server started with wstunnel server wss://[::]:443 unless shown otherwise.

socks5
# keep 5 connections to the server warm so new tunnels open instantly
wstunnel client -L socks5://127.0.0.1:8888 --connection-min-idle 5 wss://my.server.com:443

curl -x socks5h://127.0.0.1:8888 https://example.com

In Firefox, set a SOCKS v5 proxy at 127.0.0.1:8888 and tick Proxy DNS when using SOCKS v5 so names resolve on the server rather than your machine. Add ?login=admin&password=admin to the socks5 URL to require credentials.

Get wstunnel

Static binaries mean no runtime, no package manager, no dependencies. Copy it where you want it and run it.

Static binary

Pick your platform on the releases page, unpack, and put the binary on your PATH.

tar -xzf wstunnel_*_linux_amd64.tar.gz
chmod +x wstunnel
./wstunnel --help

Docker

Images are published to GitHub's container registry for every release.

docker pull ghcr.io/erebe/wstunnel:latest

From source

Needs a Rust toolchain. Add --release for an optimized build.

cargo build --package wstunnel-cli
target/debug/wstunnel --help
wstunnel is not a privacy tool. The embedded certificate is self-signed and identical for every install, so use your own, and only tunnel traffic that is already encrypted end to end: SSH, HTTPS, WireGuard. The caveats page has the details.