- Go 77.3%
- TypeScript 9.3%
- Shell 7.8%
- JavaScript 1.7%
- CSS 1.6%
- Other 2.2%
|
|
||
|---|---|---|
| .claude | ||
| .github/workflows | ||
| brokerapi | ||
| cmd | ||
| deploy | ||
| desktop | ||
| desktop-volunteer | ||
| docs | ||
| internal | ||
| punchcore | ||
| wsscore | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| CONTRIBUTING.md | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| THIRD_PARTY_NOTICES.md | ||
OpenRung
Reach the open internet.
OpenRung is a relay network that helps people living behind internet censorship reach blocked websites and apps through Foundation-operated and volunteer-run relays in unrestricted regions.
Website · Architecture · WSS fallback · Broker API · Report an issue
How it works
OpenRung connects censored users with relays in unrestricted regions, similar in spirit to Tor's Snowflake:
- Clients (mobile VPN apps, the desktop proxy app, and a desktop TUN CLI) route user traffic through a relay.
- Relay operators — the OpenRung Foundation and community volunteers — run a small command-line app that relays that traffic to the open internet.
- The broker is a control plane only: it matches clients with healthy relays and never proxies user traffic.
flowchart LR
client["📱 Client app<br/>(VPN mode)"]
relay["🔁 Relay"]
broker["🧭 Broker<br/>(control plane)"]
web["🌐 Open internet"]
client -. "relay discovery" .-> broker
relay -. "register + heartbeats" .-> broker
client == "VLESS + REALITY + Vision" ==> relay
relay ==> web
Relay transport uses Xray-core's VLESS + REALITY + Vision, designed to be hard to distinguish from ordinary TLS traffic. The broker ranks relay candidates using recent shared metrics — connection success, active sessions, observed latency, and speed tests — so clients are steered toward relays that actually work.
End-user broker-facing clients share the independently versioned
brokerapi Go module. It is the single source for relay
directory requests and raw-response signature verification, identity and
cache-control headers, telemetry and WSS-ticket requests, the loopback-only
cleartext exception, and the broker TLS transport. For the Cloudflare front
that transport opportunistically uses a compiled-in ECH configuration,
refreshes it from authenticated retry configurations, and quickly retries with
ordinary TLS when ECH is blocked. It never bootstraps ECH through DNS and never
applies ECH to the CloudFront front.
The desktop client still tries direct Reality first. When a genuine network
failure blocks a direct-mode Foundation relay, that relay may advertise its own
signed WSS fronts. Each CDN front terminates at the same relay's local sidecar,
which carries opaque Reality bytes only to that relay's loopback Reality
listener. The broker issues relay- and front-bound authorization tickets but
remains outside the user data path. The desktop client and relay-local sidecar
share the transport mechanics from the independently versioned
wsscore module; ticket authority, origin authentication,
deployment policy, telemetry orchestration, and user interfaces remain in
their owning applications.
Highlights
- 🙌 Simple volunteering — one CLI plus an Xray binary; IPv6-first with IPv4 and dual-stack options.
- 🕳️ Works behind CGNAT — volunteer-run relays with no inbound port can join through a reverse-tunnel relay hub.
- 📱 Full-device mobile client — the OpenRung app routes all device traffic in VPN mode (developed in a separate React Native repository).
- 🛡️ Direct-first censorship fallback — the desktop client can carry the existing end-to-end Reality connection through a relay-owned WSS/CDN front when the direct route is blocked.
- 🧭 Privacy-aware control plane — the broker matchmakes but never carries user traffic.
- 🗄️ Production-friendly broker — optional shared PostgreSQL state for safe restarts and load-balanced deployments.
- 📊 Operational visibility — colored per-connection logs for relay operators and an opt-in, token-protected telemetry dashboard.
Quick start
You need Go 1.25+, and relay operators also need an
Xray-core binary that supports
xray x25519 and xray run -config.
Start the broker
The broker fails closed: it refuses to start unless you either set a shared
registration token (OPENRUNG_VOLUNTEER_TOKEN, matched by hubs and
volunteer-run relays) or
explicitly opt into an open, unauthenticated broker. Running open lets anyone
register a relay into the directory, so only do it on a trusted/private network.
It also requires OPENRUNG_RELAY_SIGNING_KEY — standard base64 of the 32-byte
Ed25519 seed that signs every relay-list response (generate one with
openssl rand -base64 32):
OPENRUNG_ALLOW_ANONYMOUS_REGISTRATION=true \
OPENRUNG_RELAY_SIGNING_KEY="$(openssl rand -base64 32)" \
go run ./cmd/broker -addr :8080
For safer restarts or multiple brokers behind a load balancer, run the broker with shared PostgreSQL relay state (keep the token / anonymous flag):
OPENRUNG_ALLOW_ANONYMOUS_REGISTRATION=true \
OPENRUNG_RELAY_SIGNING_KEY="$(openssl rand -base64 32)" \
OPENRUNG_RELAY_STORE=postgres \
OPENRUNG_RELAY_DATABASE_URL='postgres://openrung:change-me@localhost:5432/openrung?sslmode=disable' \
go run ./cmd/broker -addr :8080
Relay ranking uses live metrics by default; pass -relay-ranking=legacy only
as a rollback path for the old IPv6-first ordering.
To enable the protected telemetry dashboard, set a separate administrator token
before starting the broker, then open /admin/telemetry:
OPENRUNG_ALLOW_ANONYMOUS_REGISTRATION=true \
OPENRUNG_RELAY_SIGNING_KEY="$(openssl rand -base64 32)" \
OPENRUNG_DASHBOARD_TOKEN='replace-with-a-long-random-token' \
go run ./cmd/broker -addr :8080
When the variable is unset, the dashboard and its data API return 404. In production, serve the broker over HTTPS so the administrator session cookie is protected in transit.
Run a relay
go run ./cmd/relay \
-broker http://localhost:8080 \
-public-port 443 \
-listen-port 443 \
-xray /path/to/xray
Useful to know:
- The relay listens on IPv6 (
::) by default and advertises the first global IPv6 address it finds. Pass-public-host(and-listen-hostif needed) to use a DNS name, an IPv4 address, or a specific IPv6 address, or-listen-host dualto listen on both stacks in one process. - A global IPv6 address still needs inbound firewall/router rules that allow clients to reach the relay port.
- Client connection events print in color by default — green on open, red on
close, with client IP, duration, and byte counts. Pass
-connection-log=falseto let Xray bind the public port directly. - The broker currently advertises one
public_hostper relay. For both IPv4 and IPv6 discovery, advertise a DNS name with A and AAAA records, or run separate registrations.
Important
Before you volunteer: relays currently act as direct exits, so the websites a user visits can see your IP address — much like a Tor exit node. Please read the security and abuse notes and make sure you are comfortable with that before relaying. Letting volunteers act as entry relays in front of dedicated exit servers is on the roadmap.
Volunteer-run relays behind CGNAT
Volunteer-run relays with no inbound port (carrier-grade NAT) can join through a relay hub. Run the hub on a publicly reachable host where bandwidth is cheap:
go run ./cmd/relayhub \
-broker http://localhost:8080 \
-public-host hub.example.com \
-port-range 20000-20100
Then run the relay in tunnel mode — it binds Xray to loopback and dials the hub
instead of exposing a port (no -public-host needed):
go run ./cmd/relay -tunnel -hub hub.example.com:9443 -xray /path/to/xray
All traffic for a CGNAT relay transits the hub, so keep the relay path opt-in
(public-IP relays should stay in direct mode) and run hubs off
metered cloud egress. See deploy/relayhub/README.md
for cost details and TLS setup.
Try a client
List relay candidates and run the desktop CLI relay check:
curl http://localhost:8080/api/v1/relays
go run ./cmd/client check -broker http://localhost:8080
For the zero-privilege desktop proxy app and macOS full-device CLI routing, see
docs/desktop-client.md.
The WSS fallback implemented here is desktop-only. Android and iOS are
developed in separate repositories and are not restored or updated by this
change; the original native clients have been retired from this repository.
Repository layout
cmd/broker/ Broker HTTP API (control plane).
cmd/relay/ Relay CLI for Xray-backed registration.
cmd/relayhub/ Relay hub for CGNAT volunteer-run relays
(reverse-tunnel data plane).
cmd/wsssidecar/ Relay-local WSS/CDN origin with a fixed loopback target.
cmd/client/ Desktop CLI client.
internal/broker/ Broker store and HTTP handlers.
internal/client/ Client engine, relay selection, and sing-box config.
internal/clienttelemetry/ Client metrics reporting to the broker.
internal/punch/ NAT hole-punch QUIC layer (session, transport, bridges) over punchcore.
internal/relay/ Shared relay descriptor models.
internal/relayhub/ Relay hub configuration.
internal/tunnel/ Reverse-tunnel transport (hub + relay client, yamux).
internal/relayruntime/ Relay runtime, Xray config, and broker client helpers.
internal/wssbridge/ Relay-side tickets, replay/origin authentication,
admission limits, and sidecar orchestration over wsscore.
brokerapi/ Shared broker control-plane Go client (nested module
github.com/openrung/openrung/brokerapi) for desktop and
separately released mobile bindings.
punchcore/ Shared NAT hole-punch protocol core (nested Go module
github.com/openrung/openrung/punchcore) consumed by the
servers, the desktop client, and the mobile app's binding.
wsscore/ Shared opaque Reality-over-WSS transport core (nested Go
module github.com/openrung/openrung/wsscore) consumed by
the desktop client and relay-local sidecar, and available
for separately released mobile clients to pin.
desktop/ Desktop GUI client (Wails v2 + React; own Go module).
desktop-volunteer/ One-click volunteer relay GUI (Wails v2 + React; own
Go module).
deploy/ Broker proxy, relay hub, and relay deployment assets.
docs/ Architecture, API, client, and operations docs.
Documentation
| Document | What it covers |
|---|---|
| Architecture | Goals, components, and trust boundaries |
| Broker API | HTTP API reference (/api/v1) |
| Component versioning | Independent release identities and compatibility contracts |
| Desktop clients | GUI proxy mode, Linux shell setup, and CLI TUN routing |
| WSS fallback | Per-relay protocol, trust boundaries, failure policy, and rollout |
| Per-relay CloudFront deployment | CloudFront and relay-local sidecar configuration |
| Security and abuse | Threat model, volunteer risk, and abuse handling |
| Relay hub deployment | Running a hub: TLS, ports, and cost |
Roadmap
- Dedicated exit servers — let volunteer operators choose to act as entry relays instead of direct exits.
- Abuse and rate controls — exit policies, rate limits, and abuse reporting ahead of a broad public rollout.
- NAT hole punching — direct client↔relay paths for volunteer-run relays
behind CGNAT, without a hub in the middle (core protocol in the
punchcoremodule,github.com/openrung/openrung/punchcore; shipped in the desktop and Android clients, iOS still planned). - Dual-stack relay discovery — multiple public endpoints per relay.
Have an opinion on what should come first? Open an issue — roadmap feedback is welcome.
Testing and feedback
OpenRung is under active development, and reports from real networks are the most valuable contribution:
- 🐛 Found a bug or a rough edge? Open an issue — relay IDs, connection logs, and network conditions help a lot.
- 💡 Feature ideas and questions are welcome as issues too.
- 🙋 Want to run a relay or help test the mobile app? Email admin@openrung.org.
Contributing
Contributions are accepted under GPL-3.0-or-later with a Developer Certificate
of Origin sign-off. See CONTRIBUTING.md for the details,
and thank you for helping people reach the open internet.
License
OpenRung is licensed under the GNU General Public License v3.0 or later
(GPL-3.0-or-later). See LICENSE.
The mobile app (maintained in its own repository) statically links sing-box (GPL-3.0-or-later), so the combined app — and the project as a whole — is GPL-3.0-or-later. The relay transport's VLESS + REALITY + Vision support comes from Xray-core (MPL-2.0), which the relay runs as a separate process.
Third-party components bundled or linked into distributed artifacts (Docker
images, server binaries), and the attribution and source-offer
obligations they carry, are documented in
THIRD_PARTY_NOTICES.md. Complete corresponding
source for any released binary is available from this repository.
Acknowledgements
OpenRung builds on excellent open source work:
- Xray-core — VLESS + REALITY + Vision relay transport
- sing-box — mobile tunnel engine
- MapLibre — maps in the mobile app
- Tor's Snowflake — inspiration for volunteer-powered circumvention
OpenRung is not affiliated with or endorsed by the sing-box, Xray, or MapLibre projects; their names are used descriptively.