Watch
1
0
Fork
You've already forked zoraxy-tunnel
0
mirror of https://github.com/sniffingsugar/zoraxy-tunnel.git synced 2026-08-23 19:38:56 +02:00
Selfhosted alternative Tunnel Service with zoraxy like Cloudflare Tunnels
  • Go 66.1%
  • HTML 33.2%
  • Dockerfile 0.7%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-01 19:04:14 +02:00
.github/workflows Added project 2026-07-31 19:26:44 +02:00
client Added project 2026-07-31 19:26:44 +02:00
web Offer to issue an SSL cert when installing a route 2026-08-01 16:12:28 +02:00
wire Added project 2026-07-31 19:26:44 +02:00
zoraxy_plugin Added project 2026-07-31 19:26:44 +02:00
.gitignore Added project 2026-07-31 19:26:44 +02:00
.introspect Fixed docker / Added introspec / Prepared for Release v1.1.1 2026-08-01 19:04:14 +02:00
.releaseurl Added project 2026-07-31 19:26:44 +02:00
cert.go Added project 2026-07-31 19:26:44 +02:00
CHANGELOG.md Fixed docker / Added introspec / Prepared for Release v1.1.1 2026-08-01 19:04:14 +02:00
config.go Added project 2026-07-31 19:26:44 +02:00
control.go Added project 2026-07-31 19:26:44 +02:00
go.mod Added project 2026-07-31 19:26:44 +02:00
go.sum Added project 2026-07-31 19:26:44 +02:00
handler.go Offer to issue an SSL cert when installing a route 2026-08-01 16:12:28 +02:00
icon.png Added project 2026-07-31 19:26:44 +02:00
ingress.go Added project 2026-07-31 19:26:44 +02:00
main.go Fixed docker / Added introspec / Prepared for Release v1.1.1 2026-08-01 19:04:14 +02:00
README.md Added project 2026-07-31 19:26:44 +02:00
tunnel.go Added project 2026-07-31 19:26:44 +02:00
zoraxy_api.go Offer to issue an SSL cert when installing a route 2026-08-01 16:12:28 +02:00

zoraxy-tunnel

A self-hosted, Cloudflare-Tunnel-style reverse tunnel for Zoraxy. Run the plugin on your Zoraxy box, expose one TLS port, and reach services behind NAT/firewalls from anywhere — without an external account.

Browser ──▶ Zoraxy (TLS) ──▶ plugin ingress :9080
                                   │  (yamux stream over TLS)
                                   ▼
                            tunnel-client ──▶ http://127.0.0.1:3000 (your service)

How it works

The plugin runs three listeners:

Port Kind Purpose
dynamic HTTP Dashboard UI (/ui) + JSON API (/ui/api/*), proxied by Zoraxy
9080 (static) HTTP Ingress — public traffic Zoraxy routes here, dispatched by Host
9443 (static) TLS Control plane — tunnel clients dial this

On first start the plugin mints a self-signed cert valid 99 years and shows its SHA256 fingerprint in the dashboard. Clients pin that fingerprint during the TLS handshake — if the cert doesn't match, the connection is killed before any data is exchanged. Authorization is a per-tunnel token (stored only as a hash).

Trust model

  1. Plugin generates cert → fingerprint shown in UI.
  2. Client connects to :9443, computes SHA256 of the presented cert, compares to --fingerprint. Mismatch → connection dropped.
  3. Client authenticates with --token; plugin maps it to a tunnel by hash.
  4. One live client per tunnel (a reconnecting client replaces the previous one).

Setup

1. Build

git clone https://github.com/sniffingsugar/zoraxy-tunnel
cd zoraxy-tunnel
go build -o zoraxy-tunnel .          # the plugin
go build -o tunnel-client ./client   # the client

Pre-built binaries for both are published under releases.

2. Install the plugin

Drop the binary into Zoraxy's plugin folder (folder name must equal binary name):

plugins/zoraxy-tunnel/zoraxy-tunnel

Restart Zoraxy. Open the plugin UI.

3. Configure the node

In the dashboard:

  1. Set Server address to where clients reach your control port, e.g. tunnel.example.com:9443 (port-forward/expose 9443 to the internet).
  2. Note the fingerprint.

4. Create a tunnel + connect a client

Click Create tunnel, name it, and copy the command the modal shows. There are three ready-to-paste variants:

CLI

tunnel-client \
  --server tunnel.example.com:9443 \
  --token zt_… \
  --fingerprint "AB:CD:EF:…"

Docker

docker run -d --name tunnel-client --restart unless-stopped \
  --network host \
  ghcr.io/sniffingsugar/tunnel-client:latest \
  --server tunnel.example.com:9443 \
  --token zt_… \
  --fingerprint "AB:CD:EF:…"

docker-compose.yml

services:
  tunnel-client:
    image: ghcr.io/sniffingsugar/tunnel-client:latest
    container_name: tunnel-client
    restart: unless-stopped
    network_mode: host          # Linux: 127.0.0.1 targets work as-is
    command:
      - --server=tunnel.example.com:9443
      - --token=zt_…
      - --fingerprint=AB:CD:EF:…

The token is shown once. Only a hash is stored afterwards — regenerate it from the tunnel's menu if you lose it.

With Docker, the client reaches services on the host. On Linux network_mode: host makes 127.0.0.1:3000 work directly. On macOS/Windows Docker Desktop, drop network_mode: host and target host.docker.internal instead in each service's target.

5. Register a service + install the route

Inside a tunnel, Register service:

  • Public host — e.g. app.example.com (the domain the world visits)
  • Path prefix — optional, e.g. /api
  • Local target — what the client dials, e.g. http://127.0.0.1:3000

Then click Install route. The plugin creates a Zoraxy proxy rule app.example.com → 127.0.0.1:9080 for you. Deleting the service or the tunnel removes that route automatically.

Public HTTP(S) and WebSockets are both supported and streamed.

Requirements

  • Zoraxy 3.2.0+ (plugin system)
  • One publicly reachable TCP port for :9443 (port-forward / expose)
  • Go 1.23+ to build from source

License

MIT