Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ src/version.rs
db_v2.sqlite3
test.*
.idea
.codeartsdoer/
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ machine-uid = "0.2"
mac_address = "1.1.5"
whoami = "1.2"
base64 = "0.13"
axum = { version = "0.5", features = ["headers"] }
axum = { version = "0.5", features = ["headers", "ws"] }
sqlx = { version = "0.6", features = [ "runtime-tokio-rustls", "sqlite", "macros", "chrono", "json" ] }
deadpool = "0.8"
async-trait = "0.1"
Expand All @@ -40,6 +40,7 @@ chrono = "0.4"
jsonwebtoken = "8"
headers = "0.3"
once_cell = "1.8"
tokio-stream = "0.1"
sodiumoxide = "0.2"
tokio-tungstenite = "0.17"
tungstenite = "0.17"
Expand Down
10 changes: 7 additions & 3 deletions docs/management.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
# Console management integration

The opt-in `/v1` HTTP API is independent of RustDesk's client protocol ports. Set `RD_MANAGEMENT_BIND` to a private socket address, `RD_MANAGEMENT_TOKEN` to an independent random Bearer credential of at least 32 characters, and `RD_MANAGEMENT_DIR` to a persistent directory shared with the node agent. Do not publish this listener to the client-facing network.
The opt-in `/v1` HTTP API is independent of RustDesk's client protocol ports. Set `RD_MANAGEMENT_BIND` to a private socket address, `RD_MANAGEMENT_TOKEN` to an independent random Bearer credential of at least 32 characters, and `RD_MANAGEMENT_DIR` to a persistent directory for management state. Do not publish this listener to the client-facing network.

hbbs exposes `GET /v1/status`, `GET /v1/config`, `PUT /v1/config`, `GET /v1/logs`, `GET /v1/peers` and `GET/PUT /v1/bans`. hbbr additionally exposes `GET /v1/sessions` and `DELETE /v1/sessions/:uuid`; it has no peers endpoint. All endpoints require authorization. API version is 1. Session closure is asynchronous (`202`, `state: closing`). IP bans check both relay endpoints. Reported target IDs are not authenticated source identities.
hbbs exposes `GET /v1/status`, `GET /v1/config`, `PUT /v1/config`, `GET /v1/logs`, `GET /v1/peers`, `GET/PUT /v1/bans`, `POST /v1/restart`, `GET /v1/events` (SSE), `GET /v1/relays`, `GET /v1/relays/:id/sessions`, `DELETE /v1/relays/:id/sessions/:uuid`, `GET/PUT /v1/relays/:id/config`, `GET /v1/relays/:id/logs`, `POST /v1/relays/:id/restart` and `GET /v1/control` (WebSocket upgrade). hbbr additionally exposes `GET /v1/sessions`, `DELETE /v1/sessions/:uuid` and `POST /v1/restart`; it has no peers endpoint. All endpoints require authorization. API version is 1. Session closure is asynchronous (`202`, `state: closing`). IP bans check both relay endpoints. Reported target IDs are not authenticated source identities.

Relay aggregation: when `RD_HBBS_API_URL` is set on hbbr, it opens an outbound WebSocket to the hbbs management API (`/v1/control`), registers with its relay identity and reports heartbeats, session lifecycle events and session snapshots. hbbs fans the active ban policy out to every registered relay (on update and on registration), aggregates relay sessions behind `GET /v1/relays/:id/sessions`, forwards disconnect requests through `DELETE /v1/relays/:id/sessions/:uuid`, proxies relay-scoped management requests (`GET/PUT /v1/relays/:id/config`, `GET /v1/relays/:id/logs`, `POST /v1/relays/:id/restart`) over the control channel using request ids and HTTP-equivalent responses (a relay that stays silent fails the proxy request after 10 seconds), and folds each relay address reported at registration into the live relay server list (static `relay-servers` plus registered relays; dynamic `relay-servers` updates replace the static baseline and keep the registered addresses). hbbr identity comes from `RD_RELAY_ID` (or `HOSTNAME`); `RD_RELAY_ADDRESS` optionally advertises the address clients use to reach the relay and is folded into the live relay server list only when set — the relay id (often a container hostname) is never broadcast as an address. A re-registering relay replaces its previous connection, and registrations silent for 45 seconds are dropped. `GET /v1/events` streams aggregated events (`peer_online`, `peer_offline`, `session_opened`, `session_closed`, `relay_registered`, `relay_disconnected`, `bans_replaced`) as server-sent events with a 15 second keep-alive.

Files are service-specific: `hbbs-config.json`, `hbbr-config.json`, `hbbs-bans.json`, and `hbbr-bans.json`. Configurations use `{ "values": { "port": "21116" } }`, and policies use `{ "device_ids": [], "ips": [] }`. Saved bans are validated and restored before protocol startup even when `RD_MANAGEMENT_BIND` is empty. Disabling the HTTP listener does not clear admission policy; explicitly replace the bans with empty lists before disabling management if clearing is intended. Ban replacements serialize persistence outside the protocol admission lock and activate only after the write succeeds. Config updates follow the same contract: the merged desired configuration is persisted atomically first, and running state changes only after the write succeeds.

`PUT /v1/config` accepts a partial `{"values": {...}}` merge against the current desired configuration. Schema entries marked `"dynamic": true` take effect immediately without a restart: hbbr applies `downgrade-threshold`, `downgrade-start-check`, `limit-speed`, `total-bandwidth` and `single-bandwidth` live, and hbbs applies `always-use-relay` and `relay-servers` live. The response reports `applied` entries and `pending_restart` entries (with `current` and `pending` values); pending entries take effect on the next restart, when the saved file is loaded before the protocol starts. `GET /v1/config` returns the live effective values, the schema and the current `pending_restart` diff. Secret entries are stored in the clear in the shared directory but are always reported as `__REDACTED__`; submitting the placeholder keeps the stored value unchanged. A missing dynamic handler falls the entry back to restart-required handling.

`GET /v1/logs?tail=N` returns up to 2000 recent in-memory log lines (default 200) captured from the standard log format; it requires no container log access.
`GET /v1/logs?tail=N` returns up to 2000 recent in-memory log lines (default 200) captured from the standard log format; it requires no container log access. `GET /v1/relays/:id/logs` proxies the same read for a registered relay.

`POST /v1/restart` (directly on each service and proxied per relay) asks the supervisor to bring the service back: the process exits shortly after the response is flushed (`202`, `state: restarting`), and the persisted configuration including pending-restart entries is applied on the next startup. Relay restarts are fire-and-forget: the relay acknowledges, exits and drops off the control channel, and registers again once it is back.

Managed settings override startup inputs. Schema and validation are provided by `management-schema.json`. The API returns key placeholders, never the private key. It exposes only `id_ed25519.pub` as the public key.

Expand Down
1 change: 1 addition & 0 deletions src/hbbr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use clap::App;
mod common;
mod management;
mod relay_control;
mod relay_server;
use flexi_logger::*;
use hbb_common::{config::RELAY_PORT, ResultType};
Expand Down
Loading
Loading