Skip to content

Repository files navigation

RatholeEngine

RatholeEngine

Multi-location reverse-tunnel system on rathole + Nginx

One port · one domain · one certificate · many foreign nodes routed by URL path. Built for censorship-resistant tunneling into Iran.

CI Release License Stars
shell python tunnel

English · فارسی · Full Wiki · Quick start · Documentation · Telegram

The CLI tools live under rathole-manager/. For the full Persian reference see docs/README.fa.md; a Persian summary is at the bottom of this page.


Contents

What is this

A single Iran server — behind one domain, one Let's Encrypt cert, one public port 443 — fronts many foreign nodes that connect back over a reverse tunnel. User traffic is routed to a node by URL path (map $uri $backend_port in nginx). Nothing but :443 is exposed on the Iran server; the foreign nodes have no public port.

Architecture

Three roles

Role Program Responsibility
Iran panel rathole-manager/ratholectl (bash) rathole server + nginx. Owns node inventory. Generates server.toml + rathole.conf.
Foreign node rathole-manager/ratholenode (bash) rathole client. Generates client.toml.
Hub rathole-manager/ratholehub/hub.py (Python, stdlib only) Central web panel driving many servers over SSH.

The core design principle everywhere: change state → regenerate config → validate → hot-reload. Configs are never hand-edited; they are rewritten in place (inode preserved) so rathole hot-reloads without dropping active tunnels, with automatic rollback if nginx -t fails.

Transport modes

The same tunnel can be carried five ways (plus a game/SNI L4 mode) — switching never changes user services, tokens, or paths, only the carrier. Each node's carrier is exclusive: the hub exposes it as a single select (ws/kcp/plain/noise/backhaul) that coordinates both sides.

Transport modes

  • websocket + TLS (default) — wss://domain:443, TLS terminated by nginx.
  • kcp — parallel UDP+FEC path for lossy links (looks like QUIC on UDP/443).
  • plain — no-TLS websocket to a separate HTTP listener (lighter, unencrypted).
  • noise — encrypted transport (Noise/X25519) on a second rathole instance, no TLS/cert.
  • backhaul (v1.6) — a separate Go core (Musixal/Backhaul) beside rathole that multiplexes many user connections onto one stream via SMUX; nginx proxies the hardcoded /channel + /tunnel paths to it on the same 443, so single-port/single-domain holds.
  • game / SNI — L4 passthrough on 443; TLS terminates on the node (VLESS+TLS+Vision).
  • adaptive failover (v1.5.0) — timer-driven probes classify each carrier (healthy / tls_failed / tcp_timeout / …) and auto-switch between ws and kcp with hysteresis + cooldown; plain requires explicit ALLOW_INSECURE=1.
  • secret control path (v1.5.0) — WebSocket control upgraded from / to /_rh/<32 hex>; nginx routes only that exact path to rathole; all other paths retain fake-site behaviour.

Details: docs/transport-modes.md.

Quick start

One command from GitHub (downloads the latest release bundle, then runs the installer). Defaults to loopy-iri/RatholeEngine — override with RATHOLE_GH to use a fork:

# Fully interactive (asks panel/node + details)
curl -fsSL https://raw.githubusercontent.com/loopy-iri/RatholeEngine/main/install.sh | sudo bash

# Iran server (panel), non-interactive:
curl -fsSL https://raw.githubusercontent.com/loopy-iri/RatholeEngine/main/install.sh | sudo bash -s -- --panel \
  --domain panel.example.ir \
  --fullchain /root/cert/panel.example.ir/fullchain.pem \
  --key       /root/cert/panel.example.ir/privkey.pem

# Foreign node, non-interactive:
curl -fsSL https://raw.githubusercontent.com/loopy-iri/RatholeEngine/main/install.sh | sudo bash -s -- --node -- \
  --server panel.example.ir:443 --name trk01 --token <T> --inbound-port 2087

install.sh fetches rathole-manager.zip + bootstrap.sh from the latest GitHub Release (published by the release workflow), then hands off to bootstrap.sh. Override the source repo with RATHOLE_GH="you/repo" or pin a version with RATHOLE_RELEASE="v1.2.3".

Offline / local bundle (no download) still works via bootstrap.sh directly — see docs/README.fa.md.

Re-running the panel installer is safe: it detects a previous or partial install, prints a ✓/✗ status per component, and offers resume (complete missing pieces, keep state — --repair, the default) or fresh (back up + wipe config/state, reinstall — --fresh). Under curl … | bash (no TTY) it defaults to the safe resume path.

Then add nodes from the Iran panel:

ratholectl hub on <port>             # enable hub on port <port>
ratholectl add trk01 2087            # → path /trk01 routed to that node
ratholectl proxy add mysvc http://127.0.0.1:9000   # /mysvc/ → any upstream, no rathole involved
ratholectl ls                        # list nodes + user paths
ratholectl status                    # full dashboard: domain, ports, cert, services, nodes (--json for the hub)
ratholectl paths                     # every config/file path with a ✓/✗
ratholectl version                   # manager_version + rathole_version
ratholectl doctor                    # health check

ratholectl add also prints a ready-to-paste curl … | sudo bash -s -- --node -- … one-liner for the foreign node, with the token/inbound already filled in.

From the hub you can drive all of this without the CLI: Update all rolls the update across every server one-by-one (progress bar + per-server status, with a green/yellow version badge on each), add to node wires an Iran node (name/token/inbound) onto a foreign node or upstream, and set main tunnel links a node to its Iran server.

Update & rollback

Updates take a full snapshot (CLI + configs + systemd units) into /var/backups/rathole-manager/ before touching anything, run a per-role health check afterwards, and auto-roll-back to the snapshot if the service fails to come up or nginx -t breaks.

# Update in place (auto-detects panel/node/hub; snapshot + health-check + auto-rollback)
curl -fsSL https://raw.githubusercontent.com/loopy-iri/RatholeEngine/main/install.sh | sudo bash -s -- --update
#   or, from an installed tree:  sudo bash /opt/rathole-manager/update.sh

sudo bash update.sh --list-backups        # list snapshots
sudo bash update.sh --rollback            # revert to the latest snapshot
sudo bash update.sh --rollback 20260713-2210   # revert to a specific one
sudo bash update.sh --no-rollback         # update but never auto-revert (snapshot only)

Full CLI reference and install flows (Persian): docs/README.fa.md.

Uninstall

bootstrap.sh auto-detects which roles are installed (panel / node / hub) and runs the matching uninstaller for each:

sudo bash bootstrap.sh --uninstall        # remove installed roles (asks to confirm)
sudo bash bootstrap.sh --purge --yes      # + rathole binary and hub config, no prompt
#   or per-role directly:  sudo bash uninstall-panel.sh [--purge] [--yes]

TLS certs are never removed. The shared common.sh is removed only when no other role remains on the host. The same option is item 7 in the interactive bootstrap.sh menu.

Documentation

Doc Contents
GitHub Wiki Complete GitHub Wiki (Getting Started, CLI Reference, Adaptive Filtering, Hub, Troubleshooting).
docs/architecture.md Three roles, the state→regenerate→reload principle, the path==name==map==inbound invariant.
docs/transport-modes.md The four transport carriers + game/SNI, with diagram.
docs/traffic-flow.md Layer-by-layer packet path (Mermaid + SVG diagrams).
docs/hub.md Central web panel (hub.py + hubcmds.py + ui/): REST API, security model, allow-listed actions.
docs/performance.md Tuning beyond the tunnel (BBR, kcp profiles, non-tunnel bottlenecks).
docs/amneziawg-reverse.md A separate AmneziaWG reverse-tunnel design (not part of the rathole flow).
docs/README.fa.md Full Persian CLI reference + install/uninstall flows.
docs/install-manual.md Full manual install (English): Iran panel + Pasargad config + foreign nodes + hub, step by step.
docs/install-manual.fa.md Same manual install guide, Persian.
rathole-multilocation-pasargad.md Original detailed design & troubleshooting doc (Persian).

Repository layout

install.sh                one-command installer from GitHub (curl | sudo bash)
bootstrap.sh              env prep + unpack + hand-off to installer (local or --url)
package.sh                build the distributable rathole-manager.zip
.github/workflows/        release.yml (build+publish on tag v*) · ci.yml (lint)
rathole-manager/
  ratholectl              Iran panel CLI (rathole server + nginx)
  ratholenode             foreign node CLI (rathole client)
  common.sh               shared bash helpers
  ratholehub/hub.py       central web panel (stdlib Python) — router/state/SSH/parsers
  ratholehub/hubcmds.py   security-critical action→argv allow-list (RE_* regexes)
  ratholehub/ui/          web UI assets (index.html, app.css, app.js, i18n.js)
  install-*.sh            per-role installers (panel/node/hub)
  update.sh               safe update: snapshot + health-check + rollback
  uninstall-*.sh
docs/                     documentation + assets/ (SVG/PNG diagrams)

Donation

tether bep-20 0x2364898407e8A42DA554B909989cd9B28eE61314

ton ton UQCondoXRwQNt0fQvvmYGa_Fn39D9szjQH4eBqIcUd5r1yfH

tron trx TRhnkJFpj9uxA2aqUxapJAFhkzNPbfxKwp


خلاصه‌ی فارسی

RatholeEngine یک سیستم تونل معکوس چند-موقعیتی روی rathole + Nginx است: یک سرور ایران (پشت یک دامنه، یک گواهی، یک پورت ۴۴۳) جلوی چند نود خارجی قرار می‌گیرد که با تونل معکوس به آن وصل می‌شوند و ترافیک با path به هر نود مسیریابی می‌شود. فقط پورت ۴۴۳ روی سرور ایران عمومی است.

سه نقش: پنل ایران (ratholectl — rathole server + nginx)، نود خارج (ratholenode — rathole client)، و هاب مرکزی (hub.py — پنل وب مدیریت چند سرور از طریق SSH).

اصل مرکزی: تغییر state → بازتولید کانفیگ → nginx -t → hot-reload (با حفظ inode و بازگشت خودکار در صورت خطا).

دستورهای مفید CLI: ratholectl status (داشبورد کامل: دامنه، پورت‌ها، گواهی، سرویس‌ها، نودها — با --json برای هاب)، ratholectl paths (مسیر همه‌ی فایل‌ها با ✓/✗)، ratholectl version (نسخه‌ی مدیر + rathole). ratholectl add یک دستور آماده‌ی curl … | sudo bash -s -- --node -- … هم برای نصب نود چاپ می‌کند.

از هاب: دکمه‌ی «آپدیت همه» همه‌ی سرورها را یکی‌یکی آپدیت می‌کند (progress bar + وضعیت هر سرور + badge نسخه سبز/زرد)، «افزودن به نود» یک نود ایران را روی نود/آپ‌استریم خارج سیم‌کشی می‌کند، و «تنظیم تونل اصلی» نود را به سرور ایرانش وصل می‌کند.

شروع سریع و مرجع کامل CLI (فارسی): docs/README.fa.md

فهرست مستندات فارسی:

Releases

Packages

Contributors

Languages