etunnel

module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Nov 8, 2026 License: MIT

README

etunnel

npm crates.io PyPI NuGet Hex LuaRocks pub.dev Packagist Clojars JSR

A reverse-tunnel service like localhost.run / cloudflare tunnel, but zero registration and one line of code to use: an SDK client connects out to the server, gets a random subdomain with an automatically issued TLS certificate, and anything on the internet can then reach the developer's local service through https://<subdomain>.<domain>.

┌──────────┐  wss (multiplexed HTTP streams)   ┌─────────────┐  https
│ your app  │ ───────────────────────────────▶ │  etunneld   │ ◀──── internet
│ :3000     │ ◀─────────────────────────────── │ + auto-TLS  │       visitors
└──────────┘        one outbound WS            └─────────────┘   *.t.ggcode.uk

Live deployment: wss://t.ggcode.uk/tunnel — tunnels live at https://<name>.t.ggcode.uk.

Plans

Free (anonymous) Starter Pro
Registration none API key API key
Subdomain random word-word-42 1 custom 5 custom
Tunnel lifetime 4 hours 72 hours 30 days
Bandwidth 1 Mbps 10 Mbps 10 Mbps

Custom tiers: pass a JSON file to etunneld -tiers tiers.json mapping tier id → {name, ttlHours, customDomains, bandwidthMbps}.

Quick start

CLI
etunnel -server wss://t.ggcode.uk/tunnel 3000
#   https://cosmic-auroch-59.t.ggcode.uk -> 127.0.0.1:3000
#   plan: Free, expires in 4h
Go SDK — one call
import etunnel "etunnel/sdk"

t, err := etunnel.Connect(ctx, etunnel.Options{
    Server:    "wss://t.ggcode.uk/tunnel",
    LocalAddr: "127.0.0.1:3000",
})
fmt.Println(t.URL()) // https://cosmic-auroch-59.t.ggcode.uk
defer t.Close("done")
20 language SDKs

Single-file, dependency-light SDKs live in sdks/ (Go, Python, JS/Node, TypeScript, Deno, Java, Kotlin, C#, Rust, Swift, Dart, Ruby, PHP, Perl, Lua, Scala, Elixir, C++, C, Clojure). All honor the same ETUNNEL_SERVER / ETUNNEL_LOCAL / ETUNNEL_TOKEN / ETUNNEL_SUBDOMAIN environment variables and print TUNNEL_URL: ... when run standalone.

Paid plans (custom subdomains, longer TTL, 10 Mbps)
curl -X POST https://t.ggcode.uk/api/register \
     -d '{"email":"you@example.com","tier":"starter"}'
# {"apiKey":"et_...","tier":"starter", ...}

etunnel -server wss://t.ggcode.uk/tunnel -token et_... -subdomain mydev 3000

Server (etunneld)

Single static binary, three TLS modes:

# ACME on-demand per-hostname certificates (HTTP-01, needs :80 reachable)
etunneld -domain t.example.com -addr :443 -http-addr :80 \
         -tls-mode ondemand -acme-dir /var/lib/etunnel/acme -acme-email you@x.com

# Wildcard cert via DNS-01 (Cloudflare/AliDNS/DNSPod credentials via env)
etunneld -domain t.example.com -tls-mode dns -dns-provider cloudflare ...

# Your own cert (hot-reloaded) or plain HTTP behind an LB
etunneld -domain t.example.com -tls-mode static -tls-cert fullchain.pem -tls-key privkey.pem

Endpoints:

  • wss://<domain>/tunnel — SDK WebSocket endpoint (subprotocol etunnel-v1)
  • https://<domain>/api/register — POST {"email","tier"} → API key
  • https://<domain>/api/tiers — plan catalog
  • https://<base>/ — landing page; unknown subdomains get a branded 404
  • 127.0.0.1:9090/stats (admin) — live tunnels, uptime, byte counters
  • 127.0.0.1:9090/admin/accounts (admin, X-Admin-Token) — account management

Features

  • HTTP/1.1 reverse proxying by hostname with streaming bodies (Go SDK), X-Forwarded-For/X-Forwarded-Proto injection, chunked transfer, flushes
  • WebSocket / 101-upgrade pass-through (Go SDK): hijack + raw byte pipe, so wss://<sub>.t.ggcode.uk works for your local WS server
  • Plan-based limits: TTL expiry (server closes with ttl_expired), bandwidth rate limiting (token bucket, both directions), custom-domain quotas
  • Anonymous abuse guard: per-IP concurrent tunnel cap
  • Heartbeats (app-level ping/pong + liveness timeout), graceful bye, clean 502/504 when the local service is down or slow
  • Accounts persisted to JSON (atomic writes); tiers configurable via file
  • Protocol tolerant to client WS libraries that send binary frames with the text opcode (content-sniffed server side)

Layout

protocol/    wire protocol (frames + JSON control messages) shared by all
server/      etunneld: sessions, registry, proxy, tiers, TLS, admin API
sdk/         Go SDK (reference client, full streaming + WS passthrough)
cmd/etunneld server CLI          cmd/etunnel  client CLI
sdks/        20-language clients (see sdks/README.md)
examples/    basic usage example
integration_test.go  end-to-end tests (HTTP, WS, tiers, limits, TTL, -race)

Development

go build ./... && go test -race ./...   # full suite incl. integration tests
gofmt -w . && go vet ./...

Protocol details: PROTOCOL.md.

Directories

Path Synopsis
cmd
etunnel command
Command etunnel exposes a local port through an etunnel server.
Command etunnel exposes a local port through an etunnel server.
etunneld command
Command etunneld runs an etunnel tunnel server.
Command etunneld runs an etunnel tunnel server.
examples
basic command
Basic etunnel SDK example: expose a local HTTP service in one call.
Basic etunnel SDK example: expose a local HTTP service in one call.
Package protocol defines the etunnel wire protocol shared between the server and SDK clients.
Package protocol defines the etunnel wire protocol shared between the server and SDK clients.
Package etunnel is the Go SDK for etunnel tunnels: expose a local service on the public internet with one call.
Package etunnel is the Go SDK for etunnel tunnels: expose a local service on the public internet with one call.
Package server implements the etunnel tunnel server: WebSocket control sessions from SDK clients, HTTP(S) reverse proxying by hostname, plan-based limits (TTL / custom subdomains / bandwidth), accounts and TLS.
Package server implements the etunnel tunnel server: WebSocket control sessions from SDK clients, HTTP(S) reverse proxying by hostname, plan-based limits (TTL / custom subdomains / bandwidth), accounts and TLS.

Jump to

Keyboard shortcuts

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