1
0

security: bind TURN grants to screen sessions

This commit is contained in:
2026-08-11 21:48:11 -07:00
parent 5ca214e4bb
commit 19f022f71a
16 changed files with 530 additions and 93 deletions
+33 -5
View File
@@ -118,14 +118,39 @@ then rate-limit issuance by both subject and trusted client IP. The presenter or
viewer must join signaling before requesting ICE configuration. GET/query-string
credentials remain forbidden.
Coturn removes the expiry prefix from a REST username before applying
`user-quota`. The suffix therefore must be a stable, opaque, session-participant
accounting key across repeat ICE issuance for that participant. Do not use the
authentication subject, email, profile id or another identity in this suffix,
and do not generate a fresh random suffix for every request: the former leaks
identity into TURN state/logs, while the latter gives every issuance a fresh
`user-quota`. A keyed digest of the opaque signaling session and participant ids
is an appropriate suffix. Application-side subject/IP issuance and concurrent
session limits remain mandatory; coturn cannot infer a Lumbridge member.
The template's `max-bps` and `bps-capacity` units are **bytes per second**, with
input and output accounted separately. In particular, `bps-capacity=500000000`
is a 500 MB/s (roughly 4 Gbit/s) ceiling, not a recommended launch budget.
Before public enablement, the operator must lower `total-quota` and
`bps-capacity` to the measured instance/network ceiling and an explicitly
accepted relay-egress budget. Start below that budget and raise only from
observed concurrent screen bitrate and allocation data. The 1,024-port relay
range is a hard capacity boundary, not evidence that 900 simultaneous relays are
operationally or financially safe.
An accepted response uses:
- username: `<expiry-unix-seconds>:<random-opaque-nonce>`
- username: `<expiry-unix-seconds>:<stable-opaque-participant-accounting-key>`
- credential: Base64 HMAC-SHA1 of that username using `TERA_TURN_SHARED_SECRET`
- response: `Cache-Control: private, no-store`
The shared secret never leaves the server. Expiry prevents new allocations and
refreshes; it cannot instantly terminate an allocation that already exists.
The shared secret never leaves the server. Expiry prevents a credential from
starting a newly authenticated TURN session. It does not terminate an allocation
that already exists, and coturn may continue accepting authenticated refreshes
within that established session. `stale-nonce` rotates coturn's protocol nonce
(the browser handles the 438 challenge); it is not credential revocation. Stop
and revoke must still close browser peer connections, while coturn's total
allocation and bandwidth limits bound residual abuse.
Install `tera-coturn-preflight` as `/usr/local/libexec/tera-coturn-preflight`
mode `0755`, and install the reviewed systemd drop-in only after confirming the
@@ -205,10 +230,13 @@ Verify through `getStats()` or browser WebRTC diagnostics that:
- the relay address is the current public IP, never the private VNIC address;
- two peers on different networks can exchange a screen track;
- blocking UDP forces TURN/TCP 3478, then TURN/TLS 5349;
- expired TURN credentials cannot create or refresh allocations;
- expired TURN credentials cannot start a new authenticated allocation;
- repeated ICE issuance for one signaling participant retains one opaque TURN
accounting suffix and the fifth concurrent allocation is refused by
`user-quota=4`, while a different participant remains independent;
- signaling revocation closes the application's peer connections, but an already-issued
stateless TURN credential remains usable until its short expiry (and an existing
allocation until coturn's configured allocation lifetime);
authenticated allocation may remain refreshable until the client disconnects);
- presenter stop and viewer leave close their browser peer connections;
- no CSP or Permissions Policy violation appears on either Tera entry host.
+6 -2
View File
@@ -28,10 +28,14 @@ pkey=/etc/coturn/certs/turn.privkey.pem
min-port=52000
max-port=53023
# One credential may briefly own several allocations during ICE restart. The
# total stays below the 1,024-port relay range; tune only from observed usage.
# Coturn keys user-quota by the REST username suffix after the expiry separator.
# The Tera issuer must reuse one opaque participant-scoped accounting suffix
# across that participant's credential renewals; a fresh suffix per request would
# evade this limit. The total stays below the 1,024-port relay range.
user-quota=4
total-quota=900
# Bytes per second, not bits. 500,000,000 B/s is about 4 Gbit/s; lower both
# global limits to an operator-approved NIC and egress-cost budget before launch.
max-bps=2000000
bps-capacity=500000000