Skip to content
/ NRelay Public

W.I.P Ngrok Alternative: Self-hosted and open-source OOB reverse tunnel (TCP/UDP/SNI/HTTP/MC)

Notifications You must be signed in to change notification settings

sammwyy/NRelay

Repository files navigation

NRelay

Rust License: MIT Version Build Status

A super fast reverse tunnel system written in Rust that allows you to expose local services to the internet through secure tunnels. Similar to ngrok or Cloudflare Tunnel, but self-hosted.

What is NRelay?

Do you want to show your local web server to a friend? Or open up a local Minecraft server to play with others? Maybe test webhooks without deploying?

NRelay is a reverse proxy tunneling solution that consists of a relay server (running on a public server) and clients (running locally). It allows you to expose local development servers, APIs, or any network service to the internet without port forwarding or firewall configuration.

Key Features

  • Multiple Protocol Support: HTTP, HTTPS (TLS/SNI), TCP, UDP, Minecraft, and SSH - all in one tool
  • Flexible Routing: Hostname-based routing for HTTP/HTTPS, port-based for TCP/UDP
  • Self-Hosted: Run it on your own infrastructure with complete control
  • High Performance: Built with Rust and Tokio for blazing fast async I/O
  • Token-Based Security: Each tunnel gets its own unique authentication token
  • Origin Management: Easily organize and manage multiple relay server configurations
  • Admin API: RESTful API for programmatic tunnel management
  • Protocol Sniffing: Automatically routes traffic based on intelligent protocol detection

Supported Tunnel Types

Protocol Exposure Mode Default Port Routing Method
HTTP Hostname 80 Host header
HTTPS/TLS Hostname 443 SNI (Server Name Indication)
TCP Raw Port 20000-30000 Direct port mapping
UDP Raw Port 30000-40000 Direct port mapping
Minecraft Port 25565 Handshake parsing
SSH Port 20000-30000 Direct port mapping

Requirements

Server Requirements

  • Rust: 1.70 or higher
  • Operating System: Linux, macOS, or Windows
  • Public IP Address: Required for the relay server
  • Open Ports:
    • Control port (default: 7000)
    • Admin API port (default: 7001)
    • Protocol-specific ports (80 for HTTP, 443 for HTTPS, etc.)

Client Requirements

  • Rust: 1.70 or higher
  • Network Access: Ability to connect to the relay server's control port

Installation

Prerequisites

Make sure you have Rust installed. If not, install it from rustup.rs:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Building from Source

Clone the repository and build all components:

git clone https://github.com/sammwyy/NRelay.git
cd NRelay

# Build all workspace members
cargo build --release

# Binaries will be available in target/release/
# - nrelay (CLI tool)
# - nrelay_server (Relay server)
# - nrelay_client (Tunnel client)

Installing Binaries

# Install all binaries to ~/.cargo/bin/
cargo install --path nrelay
cargo install --path nrelay_server
cargo install --path nrelay_client

πŸ’‘ Pro Tip: Make sure ~/.cargo/bin is in your PATH to run the binaries from anywhere!

Usage

1. Running the Relay Server

On your public server, start the relay server:

# Set admin API token
export ADMIN_TOKEN="your-secret-admin-token"

# Run the server
nrelay_server \
  --control-port 7000 \
  --admin-port 7001 \
  --domain yourdomain.com

Server Options:

  • --control-port: Port for client control connections (default: 7000)
  • --admin-port: Port for admin API (default: 7001)
  • --admin-iface: Interface to bind admin API (default: 0.0.0.0)
  • --domain: Base domain for hostname-based tunnels
  • --admin-token: Bearer token for admin API authentication (can use env var)

2. Configuring an Origin (Client)

Add your relay server as an "origin":

nrelay origin add myserver \
  --server relay.yourdomain.com:7000 \
  --admin-url http://relay.yourdomain.com:7001 \
  --token your-secret-admin-token \
  --kind server

Origin Modes:

  • --kind server (self-hosted): CLI acts as ADMIN, directly connects to relay server. Use this for personal/self-hosted deployments.
  • --kind service (SaaS mode, default): CLI acts as USER, requests permissions from a backend service. Used for team/business deployments with dashboard authentication. (Note: SaaS backend not yet implemented)

πŸ’‘ Pro Tip: For self-hosted deployments, always use --kind server to avoid permission errors!

List configured origins:

nrelay origin list

Set default origin:

nrelay origin set-default myserver

πŸ’‘ Pro Tip: Once you set a default origin, you won't need to specify --origin in your tunnel commands!

3. Creating Tunnels

HTTP Tunnel

Expose a local HTTP server:

# Expose localhost:8080 via HTTP
nrelay http localhost:8080

# Output: Your tunnel is available at http://{tunnel-id}.yourdomain.com

HTTPS Tunnel

Expose a local HTTPS server:

nrelay https localhost:8443

TCP Tunnel

Expose a local TCP service:

# Expose local SSH server
nrelay tcp localhost:22

# Output: Your tunnel is available at relay.yourdomain.com:25432

Minecraft Server

Expose a Minecraft server:

nrelay minecraft localhost:25565

πŸ’‘ Pro Tip: The Minecraft tunnel runs on port 25565 by default, so your friends can connect directly without specifying a port!

Custom Options

# Specify origin
nrelay http localhost:3000 --origin myserver

# With custom configuration
nrelay tcp localhost:5432 --origin production-relay

4. Managing Origins

# List all origins
nrelay origin list

# Remove an origin
nrelay origin remove myserver

# Show origin details
nrelay origin show myserver

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Public Internet Traffic             β”‚
β”‚  (HTTP/HTTPS/TCP/UDP/Minecraft/SSH)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         NRelay Server (Public)         β”‚
β”‚                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Protocol Listeners             β”‚   β”‚
β”‚  β”‚  - HTTP:80                      β”‚   β”‚
β”‚  β”‚  - HTTPS:443                    β”‚   β”‚
β”‚  β”‚  - TCP: 20000-30000             β”‚   β”‚
β”‚  β”‚  - UDP: 30000-40000             β”‚   β”‚
β”‚  β”‚  - Minecraft: 25565             β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Tunnel Registry                β”‚   β”‚
β”‚  β”‚  (In-memory state)              β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Admin API (:7001)              β”‚   β”‚
β”‚  β”‚  - POST /tunnels                β”‚   β”‚
β”‚  β”‚  - Bearer token auth            β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Control Port (:7000)           β”‚   β”‚
β”‚  β”‚  - Client connections           β”‚   β”‚
β”‚  β”‚  - Protobuf protocol            β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚ Control Protocol
                  β”‚ (Protobuf over TCP)
                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      NRelay Client (Local)             β”‚
β”‚                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Control Connection             β”‚   β”‚
β”‚  β”‚  - Receives tunnel requests     β”‚   β”‚
β”‚  β”‚  - Spawns tunnel handlers       β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Tunnel Handlers                β”‚   β”‚
β”‚  β”‚  - Bidirectional proxy          β”‚   β”‚
β”‚  β”‚  - Per-connection spawning      β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       Local Service                     β”‚
β”‚   (localhost:8080, :3000, etc.)         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

How It Works

  1. Tunnel Creation: Client calls admin API to create tunnel, receives unique token
  2. Control Connection: Client establishes persistent connection to relay server
  3. Incoming Traffic: External request arrives at relay server
  4. Protocol Sniffing: Server extracts routing info (Host header, SNI, etc.)
  5. Tunnel Matching: Server identifies which tunnel should handle the request
  6. Connection Request: Server sends OpenTunnelRequest to client via control connection
  7. Tunnel Connection: Client spawns handler, connects back to server with tunnel token
  8. Bidirectional Proxy: Data flows: External ↔ Server ↔ Client ↔ Local Service

Project Structure

NRelay/
β”œβ”€β”€ nrelay/              # CLI tool for tunnel management
β”œβ”€β”€ nrelay_server/       # Relay server (gateway)
β”œβ”€β”€ nrelay_client/       # Tunnel client
β”œβ”€β”€ nrelay_core/         # Shared types and protocol definitions
β”œβ”€β”€ nrelay_proto_http/   # HTTP protocol sniffer
β”œβ”€β”€ nrelay_proto_sni/    # TLS/SNI sniffer
β”œβ”€β”€ nrelay_proto_tcp/    # TCP proxy handler
β”œβ”€β”€ nrelay_proto_udp/    # UDP proxy handler
└── nrelay_proto_mc/     # Minecraft protocol handler

Configuration

Origin Configuration

Origins are stored in ~/.nrelay/origins.toml:

[[origins]]
name = "myserver"
server = "relay.example.com:7000"
admin_url = "http://relay.example.com:7001"
admin_token = "your-admin-token"
kind = "server"  # "server" for self-hosted, "service" for SaaS (not yet implemented)
default = true

Environment Variables

Server:

  • ADMIN_TOKEN: Admin API bearer token

Client:

  • RUST_LOG: Logging level (e.g., info, debug, trace)

Security

  • Admin API: Protected by bearer token authentication
  • Tunnel Access: Each tunnel has a unique access token
  • Dual Auth Modes: Separate authentication for control and data connections
  • Message Size Limits: 64KB maximum for control messages to prevent DoS

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Sammwy

Acknowledgments

Built with:


(qβ™₯β€Ώβ™₯q) Happy Relaying πŸ’–

About

W.I.P Ngrok Alternative: Self-hosted and open-source OOB reverse tunnel (TCP/UDP/SNI/HTTP/MC)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published