🚨 Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis →
Socket
Book a DemoInstallSign in
Socket

github.com/n0madic/go-wstunnel

Package Overview
Dependencies
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

github.com/n0madic/go-wstunnel

Source
Go
Version
v0.0.0-20250611175127-2d0efd62fd16
Version published
Created
Source

wstunnel

A high-performance WebSocket tunnel library for Go that implements the net.Conn interface over WebSocket connections. Enables TCP and UDP traffic tunneling through WebSocket connections with TLS support, optional end-to-end encryption and browser fingerprinting.

Features

  • net.Conn Interface: Seamless integration with existing Go network code
  • TCP & UDP Support: Tunnel both TCP and UDP traffic through WebSocket
  • TLS Encryption: Built-in TLS support for secure connections
  • End-to-End Encryption: Optional ChaCha20-Poly1305 encryption with steganographic key exchange
  • Browser Fingerprinting: Mimic real browser traffic using uTLS (Chrome, Firefox, Safari, Edge)
  • Custom Headers: Support for custom HTTP headers in WebSocket handshake
  • High Performance: Optimized for throughput with zero-copy optimizations
  • Middleware Support: HTTP middleware for authentication, logging, etc.
  • Zero-value Configs: Idiomatic Go API with sensible defaults

Installation

go get -u github.com/n0madic/go-wstunnel

Quick Start

Client Example

package main

import (
    "fmt"
    "io"
    "time"

    "github.com/n0madic/go-wstunnel"
)

func main() {
    // Create client with Chrome browser fingerprint
    client := wstunnel.NewClient(wstunnel.ClientConfig{
        BrowserFingerprint: wstunnel.BrowserChrome,
        Timeout:            30 * time.Second,
        InsecureSkipVerify: true, // Only for testing
    })

    // Connect to WebSocket tunnel server
    conn, err := client.Connect("example.com:8443")
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    // Use like any net.Conn
    conn.Write([]byte("Hello, tunnel!"))

    buf := make([]byte, 1024)
    n, err := conn.Read(buf)
    if err != nil {
        panic(err)
    }

    fmt.Printf("Received: %s\n", buf[:n])
}

Server Example

package main

import (
    "crypto/tls"
    "io"
    "net"

    "github.com/n0madic/go-wstunnel"
)

func main() {
    // Load TLS certificate
    cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
    if err != nil {
        panic(err)
    }

    // Create server with handler
    server := wstunnel.NewServer(wstunnel.ServerConfig{
        Handler: handleConnection,
        TLSConfig: &tls.Config{
            Certificates: []tls.Certificate{cert},
        },
    })

    // Start server
    panic(server.ListenAndServe(":8443"))
}

func handleConnection(tunnelConn *wstunnel.Conn) {
    // Example: Echo server
    io.Copy(tunnelConn, tunnelConn)
}

End-to-End Encryption

Encrypted Client Example

// Client with mandatory encryption
client := wstunnel.NewClient(wstunnel.ClientConfig{
    Encrypted:          true,                    // Enable end-to-end encryption
    BrowserFingerprint: wstunnel.BrowserChrome,  // Optional browser mimicking
    InsecureSkipVerify: true,                    // Only for testing
})

conn, err := client.Connect("server.example.com:8443")
if err != nil {
    panic(err)
}
defer conn.Close()

// All data is automatically encrypted
conn.Write([]byte("Secret message"))

Server with Auto-Detection

// Server automatically detects encrypted clients
server := wstunnel.NewServer(wstunnel.ServerConfig{
    Handler: func(conn *wstunnel.Conn) {
        // No configuration needed - server auto-detects encryption
        // conn.Encrypted() can be used to check if connection is encrypted

        // Handle both encrypted and unencrypted clients
        io.Copy(conn, conn) // Echo server
    },
    Encrypted: false, // Optional encryption (auto-detect) - default behavior
    TLSConfig: &tls.Config{
        Certificates: []tls.Certificate{cert},
    },
})

Server with Mandatory Encryption

// Server requires encryption from all clients
server := wstunnel.NewServer(wstunnel.ServerConfig{
    Handler: func(conn *wstunnel.Conn) {
        // All connections are guaranteed to be encrypted
        // Unencrypted clients are rejected with 403 Forbidden

        io.Copy(conn, conn) // Echo server
    },
    Encrypted: true, // Mandatory encryption - reject unencrypted clients
    TLSConfig: &tls.Config{
        Certificates: []tls.Certificate{cert},
    },
})

Security Features

  • ChaCha20-Poly1305 AEAD: Authenticated encryption with 256-bit keys
  • X25519 Key Exchange: Elliptic curve Diffie-Hellman with perfect forward secrecy
  • Steganographic Headers: Key exchange hidden in innocent HTTP cookies
  • Automatic Nonce Management: No nonce reuse with deterministic overflow protection
  • Zero Configuration: Server automatically detects encrypted clients
  • Mandatory Encryption Modes: Both client and server can enforce encryption
  • Perfect Forward Secrecy: Each connection uses unique ephemeral keys

Advanced Usage

Custom Headers

headers := make(http.Header)
headers.Set("Authorization", "Bearer token123")
headers.Set("X-Custom-Header", "value")

client := wstunnel.NewClient(wstunnel.ClientConfig{
    Headers: headers,
})

Server with Custom Routes and WebSocket Path

server := wstunnel.NewServer(wstunnel.ServerConfig{
    WSPath: "/tunnel", // Custom WebSocket path (default: "/ws")
    Handler: myHandler,
    Routes: map[string]http.HandlerFunc{
        "/healthz": func(w http.ResponseWriter, r *http.Request) {
            w.Write([]byte("OK"))
        },
        "/api/status": func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set("Content-Type", "application/json")
            w.Write([]byte(`{"status":"running"}`))
        },
    },
})

// Add authentication middleware
server.Use(func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
    token := r.Header.Get("Authorization")
    if !isValidToken(token) {
        http.Error(w, "Unauthorized", 401)
        return
    }
    next(w, r)
})

// Add routes dynamically
server.AddRoute("/metrics", metricsHandler)

Client with Custom WebSocket Path

client := wstunnel.NewClient(wstunnel.ClientConfig{
    WSPath: "/tunnel", // Match server's custom path
    BrowserFingerprint: wstunnel.BrowserChrome,
})

Port Forwarding Server

func forwardToTarget(tunnelConn *wstunnel.Conn) {
    // Read target address from client
    buf := make([]byte, 256)
    n, err := tunnelConn.Read(buf)
    if err != nil {
        return
    }

    target := string(buf[:n]) // e.g., "tcp:example.com:80"
    parts := strings.SplitN(target, ":", 3)
    if len(parts) != 3 {
        return
    }

    // Connect to target
    targetConn, err := net.Dial(parts[0], parts[1]+":"+parts[2])
    if err != nil {
        return
    }
    defer targetConn.Close()

    // Send acknowledgment
    tunnelConn.Write([]byte("OK"))

    // Bidirectional copy
    go io.Copy(targetConn, tunnelConn)
    io.Copy(tunnelConn, targetConn)
}

Configuration

ClientConfig

type ClientConfig struct {
    // Connection settings
    Timeout            time.Duration  // Default: 30s
    InsecureSkipVerify bool           // Default: false
    TLSConfig          *tls.Config    // Default: nil

    // Encryption settings
    Encrypted          bool           // Default: false (enable end-to-end encryption)

    // Browser fingerprinting
    BrowserFingerprint BrowserType    // Default: none

    // HTTP settings
    UserAgent string                  // Default: "TunnelClient/1.0"
    Headers   http.Header             // Default: empty

    // WebSocket settings
    WSPath            string          // Default: "/ws"
    ReadBufferSize    int             // Default: 32KB
    WriteBufferSize   int             // Default: 32KB
    EnableCompression bool            // Default: false
}

ServerConfig

type ServerConfig struct {
    // TLS settings
    TLSConfig *tls.Config

    // HTTP server settings
    ReadHeaderTimeout time.Duration  // Default: 30s
    ReadTimeout       time.Duration  // Default: 60s
    WriteTimeout      time.Duration  // Default: 60s
    IdleTimeout       time.Duration  // Default: 90s
    MaxHeaderBytes    int            // Default: 1MB

    // WebSocket settings
    WSPath            string                    // Default: "/ws"
    CheckOrigin       func(*http.Request) bool  // Default: allow all
    Subprotocols      []string                  // Default: ["tunnel"]
    ReadBufferSize    int                       // Default: 32KB
    WriteBufferSize   int                       // Default: 32KB
    EnableCompression bool                      // Default: false

    // Encryption settings
    Encrypted         bool                      // Default: false (require encryption from all clients)

    // Connection handler and routes
    Handler ConnectionHandler
    Routes  map[string]http.HandlerFunc       // Additional HTTP routes
}

Browser Types

const (
    BrowserChrome  BrowserType = "chrome"
    BrowserFirefox BrowserType = "firefox"
    BrowserSafari  BrowserType = "safari"
    BrowserEdge    BrowserType = "edge"
    BrowserRandom  BrowserType = "random"
)

Performance

The library is optimized for high throughput with realistic end-to-end benchmarks that include all WebSocket + TLS + framing overhead:

Benchmark Results

Tested on Apple M4 Max (14 cores) - Average of 3 runs

BenchmarkData SizeDurationThroughputPacketsNotes
TCP Echo (Round-trip)
Quick Test10 MB0.14s147.1 MB/s2,560Fast validation (unencrypted)
Quick Test Encrypted10 MB0.15s134.1 MB/s2,560Fast validation (encrypted)
1KB Blocks100 MB3.70s54.1 MB/s102,400Small packet efficiency
64KB Blocks200 MB0.52s770.3 MB/s3,200Large packet optimization
TCP One-way (Maximum Speed)
32KB Blocks500 MB0.50s1009.0 MB/s16,000Unidirectional peak performance
UDP Echo (Round-trip)
1KB Blocks50 MB2.02s49.5 MB/s51,200UDP with round-trip latency
Concurrent Connections
4 Parallel200 MB total0.19s1031.2 MB/s12,800Multiple connections

Performance Characteristics

  • Round-trip (Echo): Lower throughput due to network latency and echo server processing
  • One-way: Maximum throughput when data flows in single direction
  • Large Blocks: Better efficiency with 64KB+ packet sizes
  • Concurrent: Best performance with multiple parallel connections
  • UDP: Consistent performance around 50 MB/s for small packets
  • Encryption Overhead: ~9% performance impact with ChaCha20-Poly1305 end-to-end encryption

All benchmarks include the complete tunnel chain: Client → WebSocket → TLS → Tunnel Server → Target Server → back, providing realistic real-world performance expectations.

Testing

# Run all tests
go test

# Run with verbose output
go test -v

# Run benchmarks
go test -bench=.

# Run specific benchmark
go test -bench=BenchmarkTCP_Echo_Quick -v

Dependencies

  • github.com/gorilla/websocket - WebSocket implementation
  • github.com/refraction-networking/utls - Browser fingerprinting
  • golang.org/x/crypto/chacha20poly1305 - ChaCha20-Poly1305 AEAD encryption
  • golang.org/x/crypto/curve25519 - X25519 elliptic curve key exchange
  • golang.org/x/crypto/hkdf - HMAC-based Key Derivation Function

License

MIT

FAQs

Package last updated on 11 Jun 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts