# OpenRung: a broker that never carries traffic, and relays that do

> OpenRung splits censorship circumvention into three roles, a client, a relay and a control plane, and the split is strict: the broker matches and signs, the relay carries the bytes, and volunteer relays today sit in the exit position.

**openrung/openrung** — Internet access is a right, not a privilege.

- Repository: https://github.com/openrung/openrung
- Website: https://openrung.org
- Stars: 407 · Forks: 53
- Language: Go
- License: GPL-3.0
- Published: 2026-09-17 · Updated: 2026-09-17 · Language: en
- Canonical page: https://hysenlabs.com/projects/openrung-openrung

## Three roles, and only one of them touches traffic

Clients are mobile VPN apps, a desktop proxy app, and a terminal client with both proxy and full-device TUN modes. They find a relay and send user traffic to it. Relay operators, which means the OpenRung Foundation and community volunteers, run a small command-line app that passes that traffic out to the open internet. The broker sits between the two as a control plane only: it matches clients with healthy relays and never proxies user traffic. That division is drawn in the project's own diagram, where the client and the relay reach the broker with dotted lines for relay discovery and for register plus heartbeats, and the solid path runs client to relay to the open internet. A deployment where you run a broker can be read as a service that hands out addresses, nothing more.

## VLESS + REALITY + Vision, and the metrics that pick a relay

Relay transport is Xray-core's VLESS plus REALITY plus Vision, chosen because it is designed to be hard to distinguish from ordinary TLS traffic. Which relay a client gets is not random. The broker ranks candidates using recent shared metrics: connection success, active sessions, observed latency, and speed tests, so clients are steered toward relays that actually work. Two of those four inputs come from the relay side, since a relay registers and sends heartbeats to the broker, and the other two describe what a client observed. The directory requests, the raw-response signature verification, and the identity and cache-control headers all come from one place, the independently versioned brokerapi Go module, which is shared by every end-user client that talks to the broker.

## Direct first, WSS front only after a real network failure

The desktop app and both mobile clients attempt a direct Reality connection first, so the common case has no CDN in it. 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, and that sidecar carries opaque Reality bytes only to that relay's loopback Reality listener, which keeps the tunnel terminating where it started. The broker issues relay- and front-bound authorization tickets but stays outside the user data path even here, so a ticket says which relay and which front may be used without carrying what passes through them. Clients and the relay-local sidecar share the transport mechanics from the separately versioned wsscore module; ticket authority, origin authentication, deployment policy, telemetry orchestration and the user interfaces stay in the applications that own them.

## The Cloudflare front hides its name, the CloudFront front omits it

The two CDN fronts protect the server name in different ways, and the difference decides which one you can use where. For the Cloudflare front, the transport opportunistically uses a compiled-in ECH configuration, refreshes it from authenticated retry configurations, and retries quickly with ordinary TLS when ECH is blocked. It never bootstraps ECH through DNS. The CloudFront front never gets ECH applied at all, and omits the TLS server name instead, letting the encrypted HTTP Host header select the distribution while the same certificate verification runs against its exact hostname. On a direct connection the CloudFront front therefore never puts its hostname in a cleartext ClientHello, while the Cloudflare front conceals its own only as long as ECH survives, because the ordinary TLS fallback sends it. A configured proxy tunnels both fronts outside this transport and keeps sending the name.

## One installer line, and /etc/openrung/relay.env takes over

A volunteer relay starts with one command, and on Debian or Ubuntu the script installs Docker for you:

```sh
curl -fsSL https://raw.githubusercontent.com/openrung/openrung/main/deploy/relay/volunteer-up.sh | sudo sh
```

The script pulls the official relay image, runs it with the same hardened container setup the Foundation fleet uses, auto-detects your public IP, mints a stable relay identity and a public adjective-noun name, registers with the public broker, and confirms the relay is serving before it declares success. No account or token is needed. To pick the name yourself on the first run, with letters, digits, `.`, `_` and `-` and at most 63 characters:

```sh
curl -fsSL https://raw.githubusercontent.com/openrung/openrung/main/deploy/relay/volunteer-up.sh | sudo env OPENRUNG_LABEL=my-relay sh
```

Once /etc/openrung/relay.env exists it is authoritative, and editing it plus re-running the installer changes the name or any other setting. After that you need inbound TCP 443 open, `sudo ufw allow 443/tcp` if ufw fronts your firewall, then `docker logs -f openrung-relay` to watch and `docker rm -f openrung-relay` to stop. Re-running the same command updates the relay, keeps its identity, and rolls back automatically if the update fails.

## Volunteer relays are direct exits, not entry points

The page puts this in an IMPORTANT block before anything else, and it deserves the same weight. Relays currently act as direct exits, so the websites a user visits can see your server's IP address, much like a Tor exit node. That is the cost of volunteering: your address is the one that shows up in the logs of whatever the user opened. The mitigation is on the roadmap rather than in the code, since letting volunteers act as entry relays in front of dedicated exit servers would put a second, controlled machine between the volunteer and the destination. Until that lands, a volunteer is choosing to be the last hop. The same section points at docs/security-abuse.md for the security and abuse notes, and the following paragraph, which asks whether you would rather use a home computer than a VPS and starts describing a one-click desktop option, is cut off partway through on the published page.

## Broker state is memory until you point it at PostgreSQL

The broker's own configuration is two optional variables, and the shipped .env.example shows both shapes. OPENRUNG_VOLUNTEER_TOKEN is a shared token the broker requires for volunteer-class registration, with change-me as its placeholder value. OPENRUNG_RELAY_STORE defaults to memory, and the commented alternative is postgres with OPENRUNG_RELAY_DATABASE_URL set to a connection string; the file describes the PostgreSQL option as a shared relay-state backend for safer broker restarts and multiple brokers behind one load balancer, and tells local development to leave it at memory. The consequence is concrete: a broker on memory state restarts with no memory of which relays it knows, and two brokers behind one load balancer cannot see each other's relays. For a private deployment the Makefile also shows how a local broker is started, with OPENRUNG_ALLOW_ANONYMOUS_REGISTRATION=true and OPENRUNG_RELAY_SIGNING_KEY falling back to a fresh openssl rand -base64 32 value when the variable is unset.

## Four nested modules, one of them still at version zero

go.mod declares module openrung on go 1.25.5, and four submodules live beside it with replace directives pointing at local directories: brokerapi v0.7.0, wsscore v0.7.0, punchcore v0.1.0 and connectcore v0.0.0. That last version number is the one to notice. A zero version with a local replace means the module has no tagged release of its own, so anything importing connectcore resolves it from inside this repository rather than from a proxy. The external dependencies say what the pieces are built on: sagernet/sing-box v1.14.0-beta.17 and sagernet/sing v0.9.0-beta.2 are both prerelease, quic-go handles QUIC, hashicorp/yamux multiplexes streams, gorilla/websocket carries the WSS side, jackc/pgx/v5 reaches PostgreSQL, and charmbracelet bubbletea with lipgloss, bubbles and termenv are the terminal client's interface stack. The Makefile runs tests per module and passes two build tags, with_utls for the uTLS Reality client needed to dial relays and with_external_windivert to keep sing-box's embedded WinDivert64.sys driver out of the binary and the release archives.

## Conclusion

OpenRung fits a team that needs a fallback path out of a filtered network and can accept running the relay itself, since one command on a Linux VPS with a public IPv4 address is the whole setup. It does not fit a project that needs its relay to be an entry point rather than an exit, because volunteers acting as entry relays in front of dedicated exits is still on the roadmap. Before you volunteer, read docs/security-abuse.md and accept that the sites a user visits will see your server address. If you plan to build against the Go modules, check the versions first: brokerapi and wsscore are at v0.7.0 while connectcore is pinned at v0.0.0 and replaced by a local path.

## FAQ

### What is OpenRung and how is it different from running a VPN?

OpenRung is a relay network, described as similar in spirit to Tor's Snowflake. Clients in censored regions send traffic to volunteer or Foundation relays in unrestricted regions, while the broker only matches clients with healthy relays and never proxies user traffic.

### Can the OpenRung broker read my traffic?

No. The broker is a control plane that matches clients with healthy relays and never proxies user traffic, and it stays outside the user data path even when it issues relay- and front-bound authorization tickets for a WSS fallback.

### What does a volunteer OpenRung relay expose?

Relays currently act as direct exits, so the websites a user visits can see your server's IP address, much like a Tor exit node. Letting volunteers act as entry relays in front of dedicated exit servers is on the roadmap instead.

### How do I run an OpenRung relay on a Linux VPS?

Run `curl -fsSL https://raw.githubusercontent.com/openrung/openrung/main/deploy/relay/volunteer-up.sh | sudo sh`, which installs Docker on Debian or Ubuntu, registers the relay with the public broker, and needs no account or token. You then need inbound TCP 443 open and can watch the container with `docker logs -f openrung-relay`.

## Sources

- [License: GPL-3.0](https://github.com/openrung/openrung/blob/main/LICENSE)
- [openrung/openrung on GitHub](https://github.com/openrung/openrung)
- [Project website](https://openrung.org)
- [README](https://github.com/openrung/openrung/blob/main/README.md)
- [Releases](https://github.com/openrung/openrung/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/openrung-openrung
