umbra

package module
v1.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 13, 2026 License: MIT Imports: 31 Imported by: 0

README

Umbra - Secure Communication Library with DPI Bypass

Go Version License

A secure network communication library for Go that provides end-to-end encrypted communication using Elliptic Curve Cryptography (ECC) with advanced traffic obfuscation capabilities designed to bypass Deep Packet Inspection (DPI).

Features

  • 🔒 End-to-End Encryption: ECDH key exchange with ChaCha20-Poly1305 encryption
  • 🎭 DPI-Resistant Obfuscation: TLS + WebSocket encapsulation to bypass traffic analysis
  • 📦 Multi-Algorithm Compression: Gzip, LZ4, Zstd, Snappy with configurable levels
  • 🚀 High Performance: Modern cryptographic algorithms with low latency
  • 🔑 Flexible Key Management: Support for both static and ephemeral keys (forward secrecy)
  • 📜 Standards Compliant: PEM format for key storage, RFC 6455 WebSocket frames
  • 🛡️ Security Hardened: Replay protection, integrity verification, TLS 1.3 support
  • 🔧 Easy to Use: net-like API design for easy integration

Installation

go get github.com/hivecassiny/umbra

Quick Start

Basic Example (No Obfuscation)
package main

import (
    "fmt"
    "github.com/hivecassiny/umbra"
    "log"
)

func main() {
    // Server
    go func() {
        listener, _ := umbra.Listen("tcp", ":8080", nil)
        defer listener.Close()
        
        conn, _ := listener.Accept()
        defer conn.Close()
        
        buf := make([]byte, 1024)
        n, _ := conn.Read(buf)
        fmt.Println("Received:", string(buf[:n]))
    }()

    // Client
    conn, _ := umbra.Dial("tcp", "localhost:8080", nil)
    defer conn.Close()
    
    conn.Write([]byte("Hello, secure world!"))
}

Data Compression

Enable compression to reduce bandwidth usage by up to 70%. Supports multiple algorithms with configurable compression levels.

Compression Algorithms
Algorithm Compression Speed Best For
CompressionZstd ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ Best overall (recommended)
CompressionGzip ⭐⭐⭐⭐ ⭐⭐⭐ Compatibility
CompressionLZ4 ⭐⭐⭐ ⭐⭐⭐⭐⭐ Real-time, low CPU
CompressionSnappy ⭐⭐⭐ ⭐⭐⭐⭐⭐ Simple, fast
Benchmark (1KB JSON Data)
Algorithm Compressed Size Ratio Compress Speed Decompress Speed
Original 1000 B - - -
Gzip-1 ~350 B 65% 200 MB/s 400 MB/s
Gzip-6 ~300 B 70% 80 MB/s 400 MB/s
LZ4 ~420 B 58% 800 MB/s 4000 MB/s
Zstd-1 ~320 B 68% 500 MB/s 1500 MB/s
Zstd-3 ~280 B 72% 300 MB/s 1500 MB/s
Snappy ~450 B 55% 600 MB/s 2000 MB/s
Usage Example
// Server with compression
serverConfig := &umbra.Config{
    Compression: &umbra.CompressionConfig{
        Enabled: true,
        Type:    umbra.CompressionZstd,
        Level:   3, // 1=fastest, higher=better compression
    },
}
listener, _ := umbra.Listen("tcp", ":8080", serverConfig)

// Client with matching compression
clientConfig := &umbra.Config{
    Compression: &umbra.CompressionConfig{
        Enabled: true,
        Type:    umbra.CompressionZstd,
        Level:   3,
    },
}
conn, _ := umbra.Dial("tcp", "localhost:8080", clientConfig)
Compression Levels
Algorithm Level Range Default Notes
Gzip 1-9 6 1=BestSpeed, 9=BestCompression
LZ4 0-9 0 (fast) Higher levels trade speed for ratio
Zstd 1-22 3 1=fastest, 19+=best compression
Snappy N/A N/A Fixed algorithm, no levels

Note: Both client and server must use the same compression settings.

Advanced: DPI-Resistant Obfuscation

For environments with Deep Packet Inspection (such as ISPs in China), use advanced obfuscation mode. This makes your traffic appear as legitimate HTTPS WebSocket communication.

Obfuscation Levels
Level Description Requirements
ObfuscationLevelBasic Padding and header obfuscation None
ObfuscationLevelAdvanced TLS + WebSocket encapsulation Domain + TLS cert
Obfuscation Modes
Mode Description
ObfuscationNone No obfuscation
ObfuscationHTTP HTTP traffic obfuscation
ObfuscationRandom Random padding
ObfuscationWebSocket WebSocket frames (recommended for DPI bypass)
Example: Advanced Mode (DPI Bypass)
package main

import (
    "crypto/elliptic"
    "fmt"
    "github.com/hivecassiny/umbra"
    "log"
    "time"
)

func main() {
    // Generate self-signed certificate for your domain
    certPEM, keyPEM, err := umbra.GenerateSelfSignedCert([]string{"pool.yoursite.com"})
    if err != nil {
        log.Fatal(err)
    }

    // Server configuration
    serverConfig := &umbra.Config{
        Curve: elliptic.P256(),
        TLS: &umbra.TLSConfig{
            CertPEM: certPEM,
            KeyPEM:  keyPEM,
        },
        Obfuscation: &umbra.ObfuscationConfig{
            Enabled:   true,
            Level:     umbra.ObfuscationLevelAdvanced,
            Mode:      umbra.ObfuscationWebSocket,
            Domain:    "pool.yoursite.com",  // Your domain
            CoverPath: "/ws",                 // WebSocket endpoint
        },
    }

    // Client configuration
    clientConfig := &umbra.Config{
        Curve: elliptic.P256(),
        TLS: &umbra.TLSConfig{
            ServerName: "pool.yoursite.com",
            SkipVerify: true,  // For self-signed certs
        },
        Obfuscation: &umbra.ObfuscationConfig{
            Enabled:   true,
            Level:     umbra.ObfuscationLevelAdvanced,
            Mode:      umbra.ObfuscationWebSocket,
            Domain:    "pool.yoursite.com",
        },
    }

    // Start server
    go func() {
        listener, err := umbra.Listen("tcp", ":443", serverConfig)
        if err != nil {
            log.Fatal(err)
        }
        defer listener.Close()
        
        fmt.Println("DPI-resistant server listening on :443")
        
        for {
            conn, err := listener.Accept()
            if err != nil {
                continue
            }
            go handleConnection(conn)
        }
    }()

    time.Sleep(time.Second)

    // Connect with client
    conn, err := umbra.Dial("tcp", "localhost:443", clientConfig)
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
    
    fmt.Println("Connected with DPI-resistant obfuscation")
}

Configuration Validation

The library validates your configuration and provides helpful error messages:

// Validate config before use
if err := umbra.ValidateConfig(config, isServer); err != nil {
    log.Fatal(err)
}

// Or with verbose output
umbra.ValidateAndExplain(config, isServer, true)

Important Security Notes

⚠️ Domain Requirements

When using ObfuscationLevelAdvanced:

  1. Use a domain you control (e.g., pool.yoursite.com)
  2. Do NOT use google.com, cloudflare.com, or similar major domains
  3. DPI systems perform active probing - they will verify if your server is the real domain
  4. Domain must resolve to your server IP via DNS A record
🔐 TLS Certificate Configuration

You have two options for certificates. Let's Encrypt is strongly recommended.

Advantage Description
Trusted CA Browser and DPI systems recognize it as legitimate
Free No cost, auto-renews every 90 days
No SkipVerify Client doesn't need to skip verification
Best Stealth Indistinguishable from normal HTTPS
# Install certbot
sudo apt install certbot  # Ubuntu/Debian
sudo yum install certbot  # CentOS/RHEL

# Get certificate (domain must resolve to this server)
sudo certbot certonly --standalone -d pool.yoursite.com

# Certificate files location:
# /etc/letsencrypt/live/pool.yoursite.com/fullchain.pem  (certificate)
# /etc/letsencrypt/live/pool.yoursite.com/privkey.pem   (private key)
// Server: Load Let's Encrypt certificate
certPEM, _ := os.ReadFile("/etc/letsencrypt/live/pool.yoursite.com/fullchain.pem")
keyPEM, _ := os.ReadFile("/etc/letsencrypt/live/pool.yoursite.com/privkey.pem")

serverConfig := &umbra.Config{
    TLS: &umbra.TLSConfig{
        CertPEM: string(certPEM),
        KeyPEM:  string(keyPEM),
    },
    Obfuscation: &umbra.ObfuscationConfig{
        Enabled: true,
        Level:   umbra.ObfuscationLevelAdvanced,
        Mode:    umbra.ObfuscationWebSocket,
        Domain:  "pool.yoursite.com",
    },
}

// Client: No need to skip verification!
clientConfig := &umbra.Config{
    TLS: &umbra.TLSConfig{
        ServerName: "pool.yoursite.com",
        SkipVerify: false,  // Real cert, no need to skip
    },
    // ...
}
Option 2: Self-Signed Certificate
Consideration Description
Quick Setup No domain verification needed
Requires SkipVerify Client must set SkipVerify: true
Less Stealthy DPI may flag non-CA certificates
// Generate self-signed certificate
certPEM, keyPEM, err := umbra.GenerateSelfSignedCert([]string{"pool.yoursite.com"})

// Client MUST skip verification
clientConfig.TLS.SkipVerify = true
📋 Complete Setup Checklist
  1. ✅ Buy a domain (~$5-10/year from Namecheap, Cloudflare, etc.)
  2. ✅ Add DNS A record: pool.yoursite.comyour.server.ip
  3. ✅ Get Let's Encrypt certificate with certbot
  4. ✅ Configure Nginx as reverse proxy (optional but recommended)
  5. ✅ Set up a cover website at / for active probing defense
🛡️ Nginx Reverse Proxy (Optional)

For best stealth, put a normal website in front:

server {
    listen 443 ssl http2;
    server_name pool.yoursite.com;
    
    ssl_certificate /etc/letsencrypt/live/pool.yoursite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pool.yoursite.com/privkey.pem;
    
    # Normal website (for cover - defeats active probing)
    location / {
        root /var/www/html;
        index index.html;
    }
    
    # WebSocket endpoint (your actual service)
    location /ws {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

API Reference

Key Management
// Generate key pair
privKey, err := umbra.GenerateKey(elliptic.P256())

// Encode/decode keys
privPEM, _ := umbra.EncodePrivateKey(privKey)
pubPEM, _ := umbra.EncodePublicKey(&privKey.PublicKey)

privKey, _ := umbra.DecodePrivateKey(privPEM)
pubKey, _ := umbra.DecodePublicKey(pubPEM)
Connection Management
// Client connection
conn, err := umbra.Dial("tcp", "host:port", config)
conn, err := umbra.DialTimeout(5*time.Second, "tcp", "host:port", config)

// Server listener
listener, err := umbra.Listen("tcp", ":port", config)
conn, err := listener.Accept()
TLS Certificate Generation
// RSA certificate
certPEM, keyPEM, err := umbra.GenerateSelfSignedCert([]string{"domain.com", "192.168.1.1"})

// ECDSA certificate (better performance)
certPEM, keyPEM, err := umbra.GenerateSelfSignedCertECDSA([]string{"domain.com"})

Performance

Metric Value
Encryption throughput ~800 Mbps
Handshake time ~2.5 ms
Memory per connection ~4 KB
Obfuscation overhead 5-15%

Protocol Details

Encryption Stack
  1. Key Exchange: ECDH (P-256/P-384/P-521)
  2. Symmetric Encryption: ChaCha20-Poly1305
  3. Key Derivation: HKDF-SHA256
  4. TLS Layer: TLS 1.2/1.3 (advanced mode)
Message Format
+------+-----------+----------------+
| Type | Length    | Encrypted Data |
+------+-----------+----------------+
| 1B   | 4B        | Variable       |
+------+-----------+----------------+

Future Roadmap

v2.0 - HTTP/3 (QUIC) Support

When current TLS + WebSocket obfuscation is no longer sufficient, upgrade to HTTP/3:

Feature Description Priority
QUIC Protocol UDP-based transport, better for high-latency networks High
HTTP/3 Disguise Traffic appears as standard HTTP/3 High
0-RTT Connection Faster connection establishment Medium
Brutal Congestion Control Better performance on lossy networks Medium

Implementation Notes:

  • Requires quic-go library (~50MB dependency)
  • Need to handle UDP blocking in some networks
  • Consider Hysteria2 protocol as reference

When to Upgrade:

  • If current WebSocket mode gets blocked
  • If users report UDP works better in their network
  • If 0-RTT fast reconnection is needed

  • obfs4 - Pluggable transport for Tor
  • V2Ray - Platform for building proxies
  • WireGuard - Modern VPN protocol
  • Hysteria2 - QUIC-based proxy protocol (reference for HTTP/3)

License

MIT License - see LICENSE

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Commit your changes
  4. Push to the branch
  5. Create a Pull Request

Documentation

Overview

Package umbra provides encrypted TCP connections using Elliptic Curve Cryptography for key exchange and ChaCha20-Poly1305 for authenticated encryption.

The package enables secure communication over TCP with forward secrecy support through ephemeral key exchange. It includes advanced traffic obfuscation capabilities designed to bypass Deep Packet Inspection (DPI) systems.

Features

  • End-to-end encryption using ECDH key exchange and ChaCha20-Poly1305
  • Forward secrecy with ephemeral keys
  • Traffic obfuscation to evade DPI detection
  • Real TLS wrapper for advanced stealth
  • WebSocket frame encapsulation
  • Self-signed certificate generation

Basic Usage

// Server side
listener, _ := umbra.Listen("tcp", ":8080", nil)
conn, _ := listener.Accept()

// Client side
conn, _ := umbra.Dial("tcp", "localhost:8080", nil)

Advanced Usage with DPI Bypass

For environments with Deep Packet Inspection (such as some ISPs in China), use the advanced obfuscation mode:

// Generate self-signed certificate
certPEM, keyPEM, _ := umbra.GenerateSelfSignedCert([]string{"pool.yoursite.com"})

// Server config
serverConfig := &umbra.Config{
    TLS: &umbra.TLSConfig{
        CertPEM: certPEM,
        KeyPEM:  keyPEM,
    },
    Obfuscation: &umbra.ObfuscationConfig{
        Enabled:   true,
        Level:     umbra.ObfuscationLevelAdvanced,
        Mode:      umbra.ObfuscationWebSocket,
        Domain:    "pool.yoursite.com",
        CoverPath: "/ws",
    },
}

// Client config
clientConfig := &umbra.Config{
    TLS: &umbra.TLSConfig{
        ServerName: "pool.yoursite.com",
        SkipVerify: true,
    },
    Obfuscation: &umbra.ObfuscationConfig{
        Enabled:   true,
        Level:     umbra.ObfuscationLevelAdvanced,
        Mode:      umbra.ObfuscationWebSocket,
        Domain:    "pool.yoursite.com",
    },
}

Obfuscation Levels

  • ObfuscationLevelBasic: Padding and header obfuscation (no extra config needed)
  • ObfuscationLevelAdvanced: TLS + WebSocket encapsulation (requires Domain and TLS cert)

Obfuscation Modes

  • ObfuscationNone: No obfuscation
  • ObfuscationHTTP: HTTP traffic obfuscation
  • ObfuscationRandom: Random padding obfuscation
  • ObfuscationWebSocket: WebSocket frame encapsulation (recommended for DPI bypass)

Security Considerations

  • Uses P256 curve by default (configurable to P384, P521)
  • Implements HKDF for key derivation
  • Includes replay protection through monotonic counters
  • TLS 1.2/1.3 for advanced obfuscation mode
  • Do NOT use google.com or similar domains for SNI spoofing (will be detected)

Important Notes for Advanced Mode

When using ObfuscationLevelAdvanced, you MUST:

  1. Use a domain you control (e.g., "pool.yoursite.com")
  2. Configure TLS certificates (self-signed or Let's Encrypt)
  3. Optionally set up Nginx as reverse proxy for cover website

Using domains like google.com or cloudflare.com will be detected by active probing and may result in IP blocking.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateCoverResponse

func CreateCoverResponse(statusCode int) []byte

CreateCoverResponse generates a realistic HTTP response for cover website This is used when non-WebSocket requests hit the server (e.g., DPI active probing)

func DecodePrivateKey

func DecodePrivateKey(pemData string) (*ecdsa.PrivateKey, error)

DecodePrivateKey decodes a private key from PEM format.

func DecodePublicKey

func DecodePublicKey(pemData string) (*ecdsa.PublicKey, error)

DecodePublicKey decodes a public key from PEM format.

func EncodePrivateKey

func EncodePrivateKey(key *ecdsa.PrivateKey) (string, error)

EncodePrivateKey encodes a private key to PEM format.

func EncodePublicKey

func EncodePublicKey(key *ecdsa.PublicKey) (string, error)

EncodePublicKey encodes a public key to PEM format.

func GenerateKey

func GenerateKey(curve elliptic.Curve) (*ecdsa.PrivateKey, error)

GenerateKey creates a new ECDSA key pair using the specified curve. If curve is nil, P256 will be used by default.

Example

ExampleGenerateKey demonstrates ECC key generation and PEM encoding.

package main

import (
	"fmt"
	"log"

	"github.com/hivecassiny/umbra"
)

func main() {
	privKey, err := umbra.GenerateKey(nil)
	if err != nil {
		log.Fatal(err)
	}

	privPEM, err := umbra.EncodePrivateKey(privKey)
	if err != nil {
		log.Fatal(err)
	}

	pubPEM, err := umbra.EncodePublicKey(&privKey.PublicKey)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Private key PEM length: %d\n", len(privPEM))
	fmt.Printf("Public key PEM length: %d\n", len(pubPEM))

	// Verify round-trip
	decoded, err := umbra.DecodePrivateKey(privPEM)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Keys match: %v\n", decoded.D.Cmp(privKey.D) == 0)
}
Output:

Private key PEM length: 227
Public key PEM length: 178
Keys match: true

func GenerateSelfSignedCert

func GenerateSelfSignedCert(hosts []string) (certPEM, keyPEM string, err error)

GenerateSelfSignedCert generates a self-signed TLS certificate. The certificate is valid for the specified hosts (domains or IPs). Returns PEM-encoded certificate and private key.

Example:

certPEM, keyPEM, err := umbra.GenerateSelfSignedCert([]string{"pool.example.com", "192.168.1.100"})

func GenerateSelfSignedCertECDSA

func GenerateSelfSignedCertECDSA(hosts []string) (certPEM, keyPEM string, err error)

GenerateSelfSignedCertECDSA generates a self-signed TLS certificate using ECDSA. Uses P-256 curve for better performance than RSA.

func ValidateAndExplain

func ValidateAndExplain(config *Config, isServer bool, verbose bool) error

ValidateAndExplain validates config and prints explanations if verbose is true. Useful for debugging configuration issues.

func ValidateConfig

func ValidateConfig(config *Config, isServer bool) error

ValidateConfig validates the configuration and returns user-friendly errors. Call this before creating connections to catch configuration errors early.

func WrapWithTLS

func WrapWithTLS(conn net.Conn, config *TLSConfig, isClient bool) (net.Conn, error)

WrapWithTLS wraps a connection with TLS encryption. For clients, this performs a TLS handshake as a client. For servers, this performs a TLS handshake as a server.

Types

type CompressionConfig added in v1.0.9

type CompressionConfig struct {
	Enabled bool
	Type    CompressionType
	Level   int // Compression level (algorithm specific, 0 = default)
}

CompressionConfig holds configuration for data compression.

type CompressionType added in v1.0.9

type CompressionType uint8

CompressionType defines the compression algorithm to use.

const (
	CompressionNone   CompressionType = iota // No compression
	CompressionGzip                          // Gzip - good compression ratio, moderate speed
	CompressionLZ4                           // LZ4 - fastest, good for real-time
	CompressionZstd                          // Zstd - best compression ratio, fast
	CompressionSnappy                        // Snappy - fast, simple
)

func (CompressionType) String added in v1.0.9

func (c CompressionType) String() string

String returns the name of the compression type.

type Config

type Config struct {
	Curve           elliptic.Curve
	PrivateKey      *ecdsa.PrivateKey
	PublicKey       *ecdsa.PublicKey
	UseEphemeralKey bool
	Obfuscation     *ObfuscationConfig // Obfuscation configuration
	Compression     *CompressionConfig // Compression configuration
	TLS             *TLSConfig         // TLS configuration for advanced obfuscation
}

Config holds configuration parameters for ECC encryption.

type ECCConn

type ECCConn struct {
	// contains filtered or unexported fields
}

ECCConn represents an encrypted connection using ECC for key exchange and symmetric encryption for data transfer.

func Dial

func Dial(network, address string, config *Config) (*ECCConn, error)

Dial establishes an encrypted connection to the specified network address. It performs a handshake to exchange public keys and derive symmetric encryption keys.

Example

ExampleDial demonstrates basic ECC encrypted communication.

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/hivecassiny/umbra"
)

func main() {
	// Start server
	listener, err := umbra.Listen("tcp", "127.0.0.1:0", nil)
	if err != nil {
		log.Fatal(err)
	}
	defer listener.Close()

	addr := listener.Addr().String()

	// Server goroutine: echo back received data
	go func() {
		conn, err := listener.Accept()
		if err != nil {
			return
		}
		defer conn.Close()

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

	time.Sleep(50 * time.Millisecond)

	// Client: connect and send a message
	conn, err := umbra.Dial("tcp", addr, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	conn.Write([]byte("Hello, Umbra!"))

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

	fmt.Println(string(buf[:n]))
}
Output:

Hello, Umbra!
Example (WithCompression)

ExampleDial_withCompression demonstrates connection with data compression.

package main

import (
	"fmt"
	"log"
	"net"
	"time"

	"github.com/hivecassiny/umbra"
)

func main() {
	config := &umbra.Config{
		Compression: &umbra.CompressionConfig{
			Enabled: true,
			Type:    umbra.CompressionSnappy,
		},
	}

	listener, err := umbra.Listen("tcp", "127.0.0.1:0", config)
	if err != nil {
		log.Fatal(err)
	}
	defer listener.Close()

	go func() {
		conn, err := listener.Accept()
		if err != nil {
			return
		}
		defer conn.Close()
		buf := make([]byte, 1024)
		n, _ := conn.Read(buf)
		conn.Write(buf[:n])
	}()

	time.Sleep(50 * time.Millisecond)

	conn, err := umbra.Dial("tcp", listener.Addr().String(), config)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// net.Conn interface is used transparently
	var c net.Conn = conn
	c.Write([]byte("compressed data"))
	buf := make([]byte, 1024)
	n, _ := c.Read(buf)
	fmt.Println(string(buf[:n]))
}
Output:

compressed data
Example (WithObfuscation)

ExampleDial_withObfuscation demonstrates connection with traffic obfuscation.

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/hivecassiny/umbra"
)

func main() {
	serverConfig := &umbra.Config{
		Obfuscation: &umbra.ObfuscationConfig{
			Enabled: true,
			Level:   umbra.ObfuscationLevelBasic,
			Mode:    umbra.ObfuscationRandom,
		},
	}

	listener, err := umbra.Listen("tcp", "127.0.0.1:0", serverConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer listener.Close()

	go func() {
		conn, err := listener.Accept()
		if err != nil {
			return
		}
		defer conn.Close()
		buf := make([]byte, 1024)
		n, _ := conn.Read(buf)
		conn.Write(buf[:n])
	}()

	time.Sleep(50 * time.Millisecond)

	clientConfig := &umbra.Config{
		Obfuscation: &umbra.ObfuscationConfig{
			Enabled: true,
			Level:   umbra.ObfuscationLevelBasic,
			Mode:    umbra.ObfuscationRandom,
		},
	}

	conn, err := umbra.Dial("tcp", listener.Addr().String(), clientConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	conn.Write([]byte("obfuscated message"))
	buf := make([]byte, 1024)
	n, _ := conn.Read(buf)
	fmt.Println(string(buf[:n]))
}
Output:

obfuscated message

func DialTimeout

func DialTimeout(timeout time.Duration, network, address string, config *Config) (*ECCConn, error)

DialTimeout establishes an encrypted connection to the specified network address with timeout.

func NewConn

func NewConn(conn net.Conn, config *Config, isClient bool) (*ECCConn, error)

NewConn creates a new ECCConn from an existing network connection. It handles the key exchange handshake and sets up the symmetric encryption. isClient indicates whether this connection is acting as a client (true) or server (false).

func (*ECCConn) Close

func (ec *ECCConn) Close() error

Close closes the underlying network connection.

func (*ECCConn) GetPublicKey

func (ec *ECCConn) GetPublicKey() *ecdsa.PublicKey

GetPublicKey returns the public key of the local endpoint.

func (*ECCConn) LocalAddr

func (ec *ECCConn) LocalAddr() net.Addr

LocalAddr returns the local network address.

func (*ECCConn) Read

func (ec *ECCConn) Read(b []byte) (int, error)

Read reads encrypted data from the connection, decrypts it, and returns the plaintext. It handles the message framing and decryption using the receiving AEAD cipher. The nonce is updated for each message to ensure uniqueness. Supports partial reads by buffering unread data.

func (*ECCConn) RemoteAddr

func (ec *ECCConn) RemoteAddr() net.Addr

RemoteAddr returns the remote network address.

func (*ECCConn) SetDeadline

func (ec *ECCConn) SetDeadline(t time.Time) error

SetDeadline sets the read and write deadlines associated with the connection.

func (*ECCConn) SetReadDeadline

func (ec *ECCConn) SetReadDeadline(t time.Time) error

SetReadDeadline sets the deadline for future Read calls.

func (*ECCConn) SetWriteDeadline

func (ec *ECCConn) SetWriteDeadline(t time.Time) error

SetWriteDeadline sets the deadline for future Write calls.

func (*ECCConn) Write

func (ec *ECCConn) Write(b []byte) (int, error)

Write encrypts the plaintext data and writes it to the connection. It handles message framing and encryption using the sending AEAD cipher. The nonce is updated for each message to ensure uniqueness.

type ECCListener

type ECCListener struct {
	// contains filtered or unexported fields
}

ECCListener represents a listener that accepts ECC-encrypted connections.

func Listen

func Listen(network, address string, config *Config) (*ECCListener, error)

Listen creates a listener for encrypted connections on the specified network address.

Example

ExampleListen demonstrates creating an ECC encrypted server.

package main

import (
	"fmt"
	"io"
	"log"

	"github.com/hivecassiny/umbra"
)

func main() {
	listener, err := umbra.Listen("tcp", "127.0.0.1:0", nil)
	if err != nil {
		log.Fatal(err)
	}
	defer listener.Close()

	go func() {
		conn, err := listener.Accept()
		if err != nil {
			return
		}
		defer conn.Close()

		// Echo server
		buf := make([]byte, 1024)
		for {
			n, err := conn.Read(buf)
			if err != nil {
				if err != io.EOF {
					log.Println("Read error:", err)
				}
				return
			}
			conn.Write(buf[:n])
		}
	}()

	// Client connects
	conn, err := umbra.Dial("tcp", listener.Addr().String(), nil)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	conn.Write([]byte("ping"))
	buf := make([]byte, 1024)
	n, _ := conn.Read(buf)
	fmt.Println(string(buf[:n]))
}
Output:

ping

func (*ECCListener) Accept

func (el *ECCListener) Accept() (net.Conn, error)

Accept waits for and returns the next encrypted connection to the listener.

func (*ECCListener) Addr

func (el *ECCListener) Addr() net.Addr

Addr returns the listener's network address.

func (*ECCListener) Close

func (el *ECCListener) Close() error

Close closes the listener.

type HTTPObfuscator

type HTTPObfuscator struct {
	// contains filtered or unexported fields
}

HTTPObfuscator implements HTTP traffic obfuscation

type ObfuscationConfig

type ObfuscationConfig struct {
	Enabled bool             // Whether obfuscation is enabled
	Level   ObfuscationLevel // Obfuscation level (Basic or Advanced)
	Mode    ObfuscationMode  // Obfuscation mode to use

	// ===== Basic Mode Parameters =====
	MinPacketSize int // Minimum packet size for padding
	MaxPacketSize int // Maximum packet size for padding
	MinDelayMs    int // Minimum delay in milliseconds
	MaxDelayMs    int // Maximum delay in milliseconds

	// Domain is the domain you control.
	// IMPORTANT: DPI systems inspect SNI. This domain appears in TLS handshake.
	// Example: "pool.yoursite.com"
	// WARNING: Do NOT use google.com or similar - active probing will detect this.
	Domain string

	// CoverPath is the WebSocket endpoint path.
	// Example: "/ws"
	// Your server should serve a normal website on / and forward /ws to your pool.
	// This helps defeat active probing by GFW.
	CoverPath string
}

ObfuscationConfig holds configuration for traffic obfuscation

type ObfuscationLevel

type ObfuscationLevel int

ObfuscationLevel defines the strength of traffic obfuscation

const (
	// ObfuscationLevelBasic provides padding and basic header obfuscation.
	// No special configuration required. Suitable for basic privacy needs.
	ObfuscationLevelBasic ObfuscationLevel = iota

	// ObfuscationLevelAdvanced provides TLS + WebSocket encapsulation.
	// REQUIRES: Domain and TLS configuration.
	// This mode makes traffic appear as legitimate HTTPS WebSocket communication.
	// Use this mode to bypass DPI (Deep Packet Inspection) systems.
	//
	// Required configuration:
	//   - ObfuscationConfig.Domain: A domain you control (e.g., "pool.yoursite.com")
	//   - Config.TLS: TLS certificate configuration
	//
	// IMPORTANT: Do NOT use domains like google.com or cloudflare.com.
	// DPI systems perform active probing - they will connect to verify
	// if your server is actually the claimed domain. If not, your IP may be blocked.
	ObfuscationLevelAdvanced
)

type ObfuscationMode

type ObfuscationMode int

ObfuscationMode defines the type of traffic obfuscation to use

const (
	ObfuscationNone      ObfuscationMode = iota // No obfuscation
	ObfuscationHTTP                             // HTTP traffic obfuscation
	ObfuscationHTTPS                            // HTTPS traffic obfuscation (legacy, same as HTTP)
	ObfuscationRandom                           // Random padding obfuscation
	ObfuscationWebSocket                        // WebSocket frame encapsulation (recommended for DPI bypass)
)

type RandomObfuscator

type RandomObfuscator struct {
	// contains filtered or unexported fields
}

RandomObfuscator implements random padding obfuscation

type TLSConfig

type TLSConfig struct {

	// CertPEM is the PEM-encoded certificate for TLS.
	// Required for server-side advanced obfuscation (manual mode).
	// You can generate a self-signed cert using GenerateSelfSignedCert().
	CertPEM string

	// KeyPEM is the PEM-encoded private key for TLS.
	// Required for server-side advanced obfuscation (manual mode).
	KeyPEM string

	// CustomTLSConfig allows providing a pre-built *tls.Config (e.g., from CertMagic).
	// When set, CertPEM/KeyPEM are ignored for the server side and this config is used instead.
	// This enables dynamic certificate management (auto-renewal).
	CustomTLSConfig *tls.Config

	// ServerName is the SNI (Server Name Indication) to send during TLS handshake.
	// This MUST match the domain in your certificate.
	// IMPORTANT: DPI systems inspect SNI to identify destination.
	// Use your own domain, NOT google.com or cloudflare.com.
	// Those will be detected by active probing.
	ServerName string

	// SkipVerify skips certificate verification.
	// Use this with self-signed certificates.
	// WARNING: Only enable this if you trust the server.
	SkipVerify bool

	// CACertPEM is an optional custom CA certificate for verification.
	// If provided, this CA will be used instead of system roots.
	CACertPEM string

	// ALPN protocols to advertise. Defaults to ["h2", "http/1.1"].
	// Setting this to match real browsers improves stealth.
	ALPNProtos []string
}

TLSConfig holds TLS-specific configuration for advanced obfuscation. For advanced obfuscation mode (ObfuscationAdvanced), TLS is REQUIRED.

type WebSocketObfuscator

type WebSocketObfuscator struct {
	// contains filtered or unexported fields
}

WebSocketObfuscator encapsulates data in WebSocket frames. This makes traffic appear as legitimate WebSocket communication.

func (*WebSocketObfuscator) GenerateHandshakeRequest

func (w *WebSocketObfuscator) GenerateHandshakeRequest() ([]byte, string)

GenerateHandshakeRequest creates a WebSocket upgrade request

func (*WebSocketObfuscator) GenerateHandshakeResponse

func (w *WebSocketObfuscator) GenerateHandshakeResponse(clientKey string) []byte

GenerateHandshakeResponse creates a WebSocket upgrade response

func (*WebSocketObfuscator) ParseHandshakeRequest

func (w *WebSocketObfuscator) ParseHandshakeRequest(request []byte) (string, error)

ParseHandshakeRequest parses a WebSocket upgrade request and extracts the key

func (*WebSocketObfuscator) ValidateHandshakeResponse

func (w *WebSocketObfuscator) ValidateHandshakeResponse(response []byte, originalKey string) error

ValidateHandshakeResponse validates the server's WebSocket response

Directories

Path Synopsis
examples
basic command
Basic example demonstrates simple ECC encrypted communication.
Basic example demonstrates simple ECC encrypted communication.
compression command
Compression example demonstrates data compression with different algorithms.
Compression example demonstrates data compression with different algorithms.
custom_tls command
Custom TLS example demonstrates using CustomTLSConfig for dynamic certificate management.
Custom TLS example demonstrates using CustomTLSConfig for dynamic certificate management.
obfuscation command
Obfuscation example demonstrates traffic obfuscation with different modes.
Obfuscation example demonstrates traffic obfuscation with different modes.
tls command
TLS example demonstrates advanced obfuscation with TLS encryption.
TLS example demonstrates advanced obfuscation with TLS encryption.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL