A self-hosted tunneling server that exposes local servers to the public internet, similar to ngrok.
TunneLab is a self-hosted tunneling server that exposes local servers to the public internet, similar to ngrok. It provides the infrastructure for creating secure tunnels from your local development environment to the public internet.
-
TunneLab (this repository): Server-side infrastructure
- Control server for tunnel management
- HTTP/HTTPS reverse proxy with automatic TLS
- Authentication and authorization
- Tunnel registry with SQLite persistence
- WebSocket-based control connections
-
Client: Any client implementing the TunneLab protocol
- Test client included in
cmd/test-client/ - Protocol package available in
pkg/protocol/ - WebSocket control connection and yamux multiplexing
- Test client included in
- ✅ HTTP/HTTPS Tunneling - Expose local web servers with custom subdomains
- ✅ Automatic HTTPS - Let's Encrypt certificate generation and renewal
- ✅ TCP Tunneling - Expose any TCP service via assigned public ports
- ⚙️ gRPC over TCP - Run gRPC services through raw TCP tunnels (client handles TLS)
- ✅ WebSocket Support - Full WebSocket upgrade support
- ✅ TLS Termination - Automatic HTTPS with Let's Encrypt or manual certificates
- ✅ Multi-client Support - Handle multiple clients and tunnels simultaneously
- ✅ Authentication - Token-based authentication
- ✅ Monitoring - Health checks and request logging
- ✅ Auto-reconnection - Clients automatically reconnect on connection loss
System Requirements:
- Go 1.21 or higher
- Linux/macOS/Windows (tested on Linux)
- Public server with domain and static IP
- SQLite3 client tools (for database management)
Install Dependencies:
# Ubuntu/Debian
sudo apt update
sudo apt install golang sqlite3
# CentOS/RHEL/Fedora
sudo yum install golang sqlite
# OR for newer versions
sudo dnf install golang sqlite
# macOS (using Homebrew)
brew install go sqlite
# Windows (using Chocolatey)
choco install golang sqlitePort Requirements:
- Port 80 - HTTP traffic
- Port 443 - HTTPS traffic
- Port 4443 - Control server (WebSocket)
Network Requirements:
- Public IP address
- Domain name with DNS control
- Firewall rules allowing the above ports
# Clone the repository
git clone https://github.com/essajiwa/tunnelab.git
cd tunnelab
# Build the server
go build -o tunnelab-server ./cmd/server
# Create configuration
cp configs/server.example.yaml configs/server.yaml
# Edit configs/server.yaml with your settings
# Run the server (database is automatically created on first start)
./tunnelab-server -config configs/server.yaml# Check Go version
go version
# Check SQLite3
sqlite3 --version
# Verify build
ls -la tunnelab-server
# Test database
sqlite3 tunnelab.db ".tables"Configure your DNS with the following records:
yourdomain.com A YOUR_PUBLIC_IP
control.yourdomain.com A YOUR_PUBLIC_IP
*.yourdomain.com A YOUR_PUBLIC_IP
./scripts/generate-token.shSave this token for use with the test client or any client that leverages TunneLab.
Example server configuration:
server:
domain: "yourdomain.com"
control_port: 4443
http_port: 80
https_port: 443
tls:
mode: "auto" # Let's Encrypt automatic HTTPS
email: "[email protected]"
cache_dir: "./certs"
staging: false # Use production (true for testing)
database:
type: "sqlite"
path: "/var/lib/tunnelab/tunnelab.db"
auth:
required: true
logging:
level: "info"
format: "json"See docs/USAGE.md for full configuration options.
Use the included test client to create tunnels:
# Build test client
go build -o test-client ./cmd/test-client
# Start a tunnel
./test-client -server ws://localhost:4443 -token YOUR_TOKEN -subdomain myapp -port 3000
# Output:
# Tunnel started: https://myapp.yourdomain.com
# Forwarding to: localhost:3000┌─────────────┐ HTTPS ┌─────────────────┐ WebSocket ┌─────────────┐
│ Public │ ──────────→ │ TunneLab │ ─────────────→ │ Client │
│ Client │ │ Server │ │ │
│ Browser │ │ │ │ │
└─────────────┘ └─────────────────┘ └─────────────┘
│ │ │
│ myapp.yourdomain.com │ Control: :4443 │
│ │ Proxy: :80/:443 │
│ │ │ Local HTTP
│ │ Yamux Stream (TCP) ─────────────→│ Server
│ │ │ :3000
│ │ │
│←───────────────────────── Response ──────────────────────────│
TunneLab uses a WebSocket-based control channel and multiplexed data streams:
- Control Channel: WebSocket connection for tunnel management
- Data Channel: Multiplexed TCP streams (using yamux) for actual traffic
- Message Format: JSON-encoded control messages
See docs/API_DOCUMENTATION.md for the full protocol specification.
tunnelab/
├── cmd/
│ ├── server/ # Server entry point
│ └── test-client/ # Test client implementation
├── internal/
│ ├── database/ # Database models and operations
│ └── server/ # Server implementation
│ ├── auth/ # Authentication service
│ ├── config/ # Configuration management
│ ├── control/ # WebSocket control handler
│ ├── proxy/ # HTTP reverse proxy
│ ├── registry/ # Tunnel registry
│ └── tls/ # TLS certificate management
├── pkg/
│ └── protocol/ # Public protocol package (for clients)
├── configs/ # Configuration files
│ └── server.example.yaml
├── scripts/ # Utility scripts
│ ├── setup.sh
│ ├── generate-token.sh
│ └── test-tunnel.sh
├── docs/ # Documentation
│ ├── API_DOCUMENTATION.md
│ ├── LETSENCRYPT.md
│ ├── QUICKSTART.md
│ └── TESTING.md
├── Makefile # Build automation
├── go.mod # Go module definition
└── README.md # This file
# Build using Makefile (recommended)
make build
# Build manually
go build -o tunnelab-server ./cmd/server
# Build for Linux
GOOS=linux GOARCH=amd64 go build -o tunnelab-server-linux ./cmd/server
# Build with version info
go build -ldflags "-X main.version=1.0.0" -o tunnelab-server ./cmd/serverThe server is configured via YAML file. See configs/server.example.yaml for a complete example:
# Copy example configuration
cp configs/server.example.yaml configs/server.yaml
# Edit configuration
nano configs/server.yaml# Basic health check
curl http://localhost/health- Authentication: Token-based authentication required
- TLS: Automatic HTTPS with Let's Encrypt or manual certificates
- Database: SQLite for tunnel persistence and client management
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
MIT License - see LICENSE file for details.
- Technical Design - Complete system design
- Let's Encrypt Setup - HTTPS with automatic certificates
- Quick Start - Get started in 5 minutes
- Usage Guide - Detailed usage instructions
- API Documentation - Protocol and API reference
- Implementation Status - Current implementation status
Contributions are welcome! Please fork the repository and submit a pull request.
- Core HTTP tunneling
- WebSocket support
- Let's Encrypt integration (automatic HTTPS)
- Manual certificate support
- TCP tunneling
- Enhanced gRPC controls (service allowlists, TLS enforcement)
- UDP tunneling
- Web dashboard
- Custom domain support (BYOD)
- Load balancing
- Geographic routing
- Plugin system
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: [email protected]
- Inspired by frp and ngrok
- Uses yamux for stream multiplexing
- Uses gorilla/websocket for WebSocket support
Made with ❤️ for developers who need to expose their local servers