Internet access is a right, not a privilege. https://openrung.org
  • Go 77.3%
  • TypeScript 9.3%
  • Shell 7.8%
  • JavaScript 1.7%
  • CSS 1.6%
  • Other 2.2%
Find a file
openrung-admin ce86883171
Merge pull request #100 from openrung/codex/brokerapi-module
Extract shared brokerapi client module
2026-07-25 00:01:41 +08:00
.claude Complete relay artifact rename 2026-07-14 14:09:26 +08:00
.github/workflows Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
brokerapi Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
cmd Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
deploy Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
desktop Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
desktop-volunteer Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
docs Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
internal Keep empty relay lists as JSON arrays 2026-07-24 23:50:25 +08:00
punchcore refactor: use relay as the generic runtime term 2026-07-14 09:41:37 +08:00
wsscore feat(wsscore): support SNI-less CloudFront connections 2026-07-22 15:43:06 +08:00
.dockerignore Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
.env.example refactor: use relay as the generic runtime term 2026-07-14 09:41:37 +08:00
.gitignore Add per-relay WSS fleet rollout tooling 2026-07-22 23:04:52 +08:00
CONTRIBUTING.md Remove native Android and iOS apps in favor of the React Native app 2026-07-04 18:06:18 +08:00
go.mod Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
go.sum refactor: extract reusable WSS core module 2026-07-22 12:34:05 +08:00
LICENSE Initial commit 2026-07-04 08:11:58 +08:00
Makefile Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
README.md Extract shared brokerapi client module 2026-07-24 17:32:53 +08:00
THIRD_PARTY_NOTICES.md feat: add per-relay WSS CDN fallback 2026-07-22 07:20:31 +08:00

OpenRung logo

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 License: GPL-3.0-or-later Go Platforms PRs welcome

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-host if needed) to use a DNS name, an IPv4 address, or a specific IPv6 address, or -listen-host dual to 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=false to let Xray bind the public port directly.
  • The broker currently advertises one public_host per 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 punchcore module, 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.