High-performance TURN/STUN server written in Rust (RFC 5389, RFC 5766, RFC 8656).
Turna is the Turkish name of the crane — a migratory bird that relays itself across continents. This server does the same for your packets.
Production GA (0.3.0). The default Tokio datapath is the primary supported path:
STUN binding, the TURN allocation lifecycle, long-term-credential and JWT auth,
Prometheus/OpenTelemetry, config validation, durable runtime configuration,
per-subject limits, and graceful drain.
The new GA management changes are implemented in source but are not considered verified by this document until the exact release commit passes the workspace, Tarantool, frontend, container, Helm, migration, restart, and live relay gates in RELEASE.md.
The high-performance and alternative-transport backends are experimental,
gated behind Cargo features, and not yet runtime-verified for production: the
io-uring and af-xdp datapaths, and the dtls, quic, web-transport and
TLS-over-TCP (tls) transports. Treat them as preview until further validation
— see docs/PRODUCTION_READINESS.md.
update_config dynamically changes only max_allocations,
max_allocations_per_user, and max_bytes_per_sec_per_allocation (bytes/second). Changes are
published as one immutable versioned snapshot on the target node. set_user_limits
supports global, tenant, and realm/tenant/user overrides for allocation count,
bytes/second, and lifetime. Every field independently supports inherit, a finite
value, unlimited, or disabled where valid. Both RPCs require a target node,
expected version, and idempotency key; their responses come from the node's
durable terminal result rather than control-plane-local state.
- Memory-safe core in Rust with continuously fuzzed STUN/TURN parsers
(
fuzz/) and an auditedunsafeinventory confined to the transport/relay datapaths. - Batched UDP I/O —
SO_REUSEPORTrecv workers withrecvmmsg/sendmmsgand per-batch arena buffers; optionalio_uringandAF_XDPdatapaths behind features for kernel-bypass throughput. - Standalone-first management — node-targeted, idempotent runtime config and user-limit commands with desired/observed versions and Tarantool-backed restart restore.
- Experimental clustering — gossip discovery, a hash ring, TURN redirects, and allocation-state tooling. It does not guarantee transparent survival of active allocations, relay-socket rehydration, or zero-gap rolling upgrades.
- Operable — gRPC control plane +
turnactlCLI, Prometheus metrics and OpenTelemetry tracing, graceful drain and RFC 8016 session migration.
For a longer comparison and the design rationale, see docs/why-turna.md. Reproducible benchmarks against coturn live in bench/README.md.
| Guarantee | Status |
|---|---|
| Idempotent retry of management commands | Supported |
| Runtime config restore after restart | Supported (management-backend profile) |
| User-limits restore after restart | Supported |
| Existing allocation survives process crash | Not guaranteed |
| Existing media path migrates to another node | Not guaranteed |
| Drain waits indefinitely | No — bounded by drain_grace_secs |
| Multi-node ownership/state failover | Experimental / limited scope |
| Transparent active-session (media) failover | Out of GA scope |
"Supported" is a source-level statement pending the release verification gates in RELEASE.md; see docs/feature-support.md for the full matrix and docs/MANAGEMENT_API.md for the RPC contract.
- STUN binding and full TURN allocation lifecycle (Allocate / Refresh / CreatePermission / ChannelBind / Send & Data indications)
- UDP and TCP relay transports
- Long-term credential mechanism, JWT-based auth, rate limiting and credential rotation; multi-tenant realms with per-tenant relay port pools and limits
- Pluggable state backend (in-memory, Tarantool) for clustered deployments
- gRPC control plane + CLI (
turnactl) for live management - OpenTelemetry tracing and Prometheus metrics out of the box
- Graceful drain and RFC 8016 session migration on the default (tokio) datapath
- Continuously fuzzed STUN/TURN parsers (cargo-fuzz)
cargo build --release
./target/release/turna-node deploy/turn.tomldocker build -f deploy/Dockerfile -t turna:local .
docker run --rm \
-p 3478:3478/udp -p 3478:3478/tcp -p 9090:9090/tcp \
-v "$PWD/deploy/turn.toml:/etc/turna/turn.toml:ro" \
turna:localhelm install turna deploy/helm/turna \
--set turn.externalIP=203.0.113.10 \
--set turn.auth.sharedSecret="$(openssl rand -hex 32)"The chart keeps the TURN secret in a Kubernetes Secret, runs as a hardened non-root pod, and separates the public TURN service from an internal health/metrics service. See docs/DEPLOY.md.
Minimal turn.toml:
production = false
[turn]
listen = "0.0.0.0:3478"
external_ip = "203.0.113.10" # your real public IP
realm = "turna"
[turn.auth]
shared_secret = "use: openssl rand -hex 32"
[health]
listen = "0.0.0.0:9090"deploy/turn.toml is a complete annotated example; every option is documented
in docs/CONFIGURATION.md. With production = true,
config validation rejects placeholder secrets and a missing external_ip.
The workspace is split by domain so each concern is isolated:
- Protocol —
proto-stun,proto-turn,proto-rtp,packet - Datapath —
transport(tokio / io_uring / AF_XDP / DTLS / QUIC),relay,session,qos - Auth & crypto —
auth,crypto - State & cluster —
state-backend(in-memory / Tarantool),cluster,common - Control & ops —
control(gRPC),management,observability,health,rtp-analyzer - Binaries —
services/node(turna-node),services/control-plane(turna-control-plane) - Tools —
turnactl,benchmark,load-test,diff-test,garbage-gen
Design notes (AF_XDP datapath, DTLS, QUIC/WebTransport, RFC 6062 TCP allocations, allocation-store persistence) are under docs/design/; clustering is covered in docs/CLUSTER.md.
turna implements STUN (RFC 5389) and TURN (RFC 5766, RFC 8656). The table
below summarises standards and transport maturity. For the authoritative,
per-feature production maturity always check
docs/PRODUCTION_READINESS.md and
docs/feature-support.md.
| Standard / capability | RFC | Status |
|---|---|---|
| STUN Binding | RFC 5389 | Supported (default tokio datapath) |
Message integrity, SHA-256 (MESSAGE-INTEGRITY-SHA256) |
RFC 8489 | Supported |
| TURN allocation lifecycle, UDP relay | RFC 5766 / RFC 8656 | Supported (default tokio datapath) |
| TURN over TCP (TCP relay allocations) | RFC 6062 | Implemented, less exercised (preview) |
| Session migration | RFC 8016 | Supported (tokio datapath) |
TLS-over-TCP transport (tls) |
— | Experimental (preview) |
DTLS transport (dtls) |
— | Experimental (preview) |
QUIC transport (quic) |
— | Experimental (preview) |
WebTransport (web-transport) |
— | Experimental (preview) |
io_uring datapath |
— | Experimental (preview) |
AF_XDP datapath |
— | Experimental (preview) |
Status legend: Supported — exercised on the primary path and intended for production use; Preview — gated behind a Cargo feature and not yet runtime-verified for production.
turna-node exposes Prometheus metrics and a health endpoint, and emits
OpenTelemetry traces. Bind health/metrics to an internal interface only — see
docs/OBSERVABILITY.md. The management API and gRPC
control plane can be secured with mTLS (docs/MTLS.md).
Workspace crates can be consumed via a git dependency:
[dependencies]
turna-relay = { git = "https://github.com/kruatech/turna", tag = "v0.3.0" }cargo build --workspace --locked
cargo test --workspace --locked
cargo fmt --all --check
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo deny checkFuzz targets (nightly) live in fuzz/. See CONTRIBUTING.md
for the full workflow, including the unsafe audit process.
- CONTRIBUTING.md — how to build, test and submit changes
- CODE_OF_CONDUCT.md
- SUPPORT.md — where to get help
- ROADMAP.md
Parsers are fuzz-tested continuously; the threat model, production checklist and security invariants live in docs/SECURITY.md and docs/security/. To report a vulnerability privately, see SECURITY.md.
Licensed under the Apache License, Version 2.0. See NOTICE for attribution. The name "turna" and the logo are trademarks — see TRADEMARKS.md.